xref: /petsc/src/sys/fileio/mpiuopen.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
10039db0dSBarry Smith #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for popen() */
2e5c89e4eSSatish Balay /*
34c500f23SPierre Jolivet       Some PETSc utility routines to add simple parallel IO capabilities
4e5c89e4eSSatish Balay */
5c6db04a5SJed Brown #include <petscsys.h>
6e94e781bSJacob Faibussowitsch #include <petsc/private/logimpl.h>
7d0286d30SJed Brown #include <errno.h>
8d0286d30SJed Brown 
9e5c89e4eSSatish Balay /*@C
10e5c89e4eSSatish Balay     PetscFOpen - Has the first process in the communicator open a file;
11e5c89e4eSSatish Balay     all others do nothing.
12e5c89e4eSSatish Balay 
13d083f849SBarry Smith     Logically Collective
14e5c89e4eSSatish Balay 
15e5c89e4eSSatish Balay     Input Parameters:
16e5c89e4eSSatish Balay +   comm - the communicator
17e5c89e4eSSatish Balay .   name - the filename
18e5c89e4eSSatish Balay -   mode - the mode for fopen(), usually "w"
19e5c89e4eSSatish Balay 
20e5c89e4eSSatish Balay     Output Parameter:
21e5c89e4eSSatish Balay .   fp - the file pointer
22e5c89e4eSSatish Balay 
23e5c89e4eSSatish Balay     Level: developer
24e5c89e4eSSatish Balay 
25e5c89e4eSSatish Balay     Notes:
260298fd71SBarry Smith        NULL (0), "stderr" or "stdout" may be passed in as the filename
27e5c89e4eSSatish Balay 
28e5c89e4eSSatish Balay     Fortran Note:
29e5c89e4eSSatish Balay     This routine is not supported in Fortran.
30e5c89e4eSSatish Balay 
31db781477SPatrick Sanan .seealso: `PetscFClose()`, `PetscSynchronizedFGets()`, `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`,
32db781477SPatrick Sanan           `PetscFPrintf()`
33e5c89e4eSSatish Balay @*/
349371c9d4SSatish Balay PetscErrorCode PetscFOpen(MPI_Comm comm, const char name[], const char mode[], FILE **fp) {
35e5c89e4eSSatish Balay   PetscMPIInt rank;
36e5c89e4eSSatish Balay   FILE       *fd;
37e5c89e4eSSatish Balay   char        fname[PETSC_MAX_PATH_LEN], tname[PETSC_MAX_PATH_LEN];
38e5c89e4eSSatish Balay 
39e5c89e4eSSatish Balay   PetscFunctionBegin;
409566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
41dd400576SPatrick Sanan   if (rank == 0) {
42ace3abfcSBarry Smith     PetscBool isstdout, isstderr;
439566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stdout", &isstdout));
449566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stderr", &isstderr));
45a297a907SKarl Rupp     if (isstdout || !name) fd = PETSC_STDOUT;
46a297a907SKarl Rupp     else if (isstderr) fd = PETSC_STDERR;
47a297a907SKarl Rupp     else {
48b3f259d6SBarry Smith       PetscBool devnull;
499566063dSJacob Faibussowitsch       PetscCall(PetscStrreplace(PETSC_COMM_SELF, name, tname, PETSC_MAX_PATH_LEN));
509566063dSJacob Faibussowitsch       PetscCall(PetscFixFilename(tname, fname));
519566063dSJacob Faibussowitsch       PetscCall(PetscStrbeginswith(fname, "/dev/null", &devnull));
52*48a46eb9SPierre Jolivet       if (devnull) PetscCall(PetscStrcpy(fname, "/dev/null"));
539566063dSJacob Faibussowitsch       PetscCall(PetscInfo(0, "Opening file %s\n", fname));
54e5c89e4eSSatish Balay       fd = fopen(fname, mode);
5528b400f6SJacob Faibussowitsch       PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open file %s", fname);
56e5c89e4eSSatish Balay     }
5702c9f0b5SLisandro Dalcin   } else fd = NULL;
58e5c89e4eSSatish Balay   *fp = fd;
59e5c89e4eSSatish Balay   PetscFunctionReturn(0);
60e5c89e4eSSatish Balay }
61e5c89e4eSSatish Balay 
62e8976759SBarry Smith /*@C
63e5c89e4eSSatish Balay     PetscFClose - Has the first processor in the communicator close a
64e5c89e4eSSatish Balay     file; all others do nothing.
65e5c89e4eSSatish Balay 
66d083f849SBarry Smith     Logically Collective
67e5c89e4eSSatish Balay 
68e5c89e4eSSatish Balay     Input Parameters:
69e5c89e4eSSatish Balay +   comm - the communicator
70e5c89e4eSSatish Balay -   fd - the file, opened with PetscFOpen()
71e5c89e4eSSatish Balay 
72e5c89e4eSSatish Balay    Level: developer
73e5c89e4eSSatish Balay 
74e5c89e4eSSatish Balay     Fortran Note:
75e5c89e4eSSatish Balay     This routine is not supported in Fortran.
76e5c89e4eSSatish Balay 
77db781477SPatrick Sanan .seealso: `PetscFOpen()`
78e5c89e4eSSatish Balay @*/
799371c9d4SSatish Balay PetscErrorCode PetscFClose(MPI_Comm comm, FILE *fd) {
80e5c89e4eSSatish Balay   PetscMPIInt rank;
81ed9cf6e9SBarry Smith   int         err;
82e5c89e4eSSatish Balay 
83e5c89e4eSSatish Balay   PetscFunctionBegin;
849566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
85dd400576SPatrick Sanan   if (rank == 0 && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
86ed9cf6e9SBarry Smith     err = fclose(fd);
8728b400f6SJacob Faibussowitsch     PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
88ed9cf6e9SBarry Smith   }
89e5c89e4eSSatish Balay   PetscFunctionReturn(0);
90e5c89e4eSSatish Balay }
91e5c89e4eSSatish Balay 
92e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN)
9374ba8654SBarry Smith static char PetscPOpenMachine[128] = "";
94e5c89e4eSSatish Balay 
95e5c89e4eSSatish Balay /*@C
96e5c89e4eSSatish Balay       PetscPClose - Closes (ends) a program on processor zero run with PetscPOpen()
97e5c89e4eSSatish Balay 
98d083f849SBarry Smith      Collective, but only process 0 runs the command
99e5c89e4eSSatish Balay 
100e5c89e4eSSatish Balay    Input Parameters:
101e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
1020298fd71SBarry Smith -   fp - the file pointer where program input or output may be read or NULL if don't care
103e5c89e4eSSatish Balay 
104e5c89e4eSSatish Balay    Level: intermediate
105e5c89e4eSSatish Balay 
106e5c89e4eSSatish Balay    Notes:
107e5c89e4eSSatish Balay        Does not work under Windows
108e5c89e4eSSatish Balay 
109db781477SPatrick Sanan .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPOpen()`
110e5c89e4eSSatish Balay 
111e5c89e4eSSatish Balay @*/
1129371c9d4SSatish Balay PetscErrorCode PetscPClose(MPI_Comm comm, FILE *fd) {
113e5c89e4eSSatish Balay   PetscMPIInt rank;
114e5c89e4eSSatish Balay 
115e5c89e4eSSatish Balay   PetscFunctionBegin;
1169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
117dd400576SPatrick Sanan   if (rank == 0) {
118e5c89e4eSSatish Balay     char buf[1024];
1199371c9d4SSatish Balay     while (fgets(buf, 1024, fd))
1209371c9d4SSatish Balay       ; /* wait till it prints everything */
121016831caSBarry Smith     (void)pclose(fd);
122e5c89e4eSSatish Balay   }
123e5c89e4eSSatish Balay   PetscFunctionReturn(0);
124e5c89e4eSSatish Balay }
125e5c89e4eSSatish Balay 
126e5c89e4eSSatish Balay /*@C
127e5c89e4eSSatish Balay       PetscPOpen - Runs a program on processor zero and sends either its input or output to
128e5c89e4eSSatish Balay           a file.
129e5c89e4eSSatish Balay 
130d083f849SBarry Smith      Logically Collective, but only process 0 runs the command
131e5c89e4eSSatish Balay 
132e5c89e4eSSatish Balay    Input Parameters:
133e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
1340298fd71SBarry Smith .   machine - machine to run command on or NULL, or string with 0 in first location
135e5c89e4eSSatish Balay .   program - name of program to run
136e5c89e4eSSatish Balay -   mode - either r or w
137e5c89e4eSSatish Balay 
138e5c89e4eSSatish Balay    Output Parameter:
1390298fd71SBarry Smith .   fp - the file pointer where program input or output may be read or NULL if don't care
140e5c89e4eSSatish Balay 
141e5c89e4eSSatish Balay    Level: intermediate
142e5c89e4eSSatish Balay 
143e5c89e4eSSatish Balay    Notes:
144e5c89e4eSSatish Balay        Use PetscPClose() to close the file pointer when you are finished with it
145e5c89e4eSSatish Balay        Does not work under Windows
146e5c89e4eSSatish Balay 
14774ba8654SBarry Smith        If machine is not provided will use the value set with PetsPOpenSetMachine() if that was provided, otherwise
14874ba8654SBarry Smith        will use the machine running node zero of the communicator
14974ba8654SBarry Smith 
150e5c89e4eSSatish Balay        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
151a5b23f4aSJose E. Roman     will be replaced with relevant values.
152e5c89e4eSSatish Balay 
153db781477SPatrick Sanan .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPClose()`, `PetscPOpenSetMachine()`
154e5c89e4eSSatish Balay 
155e5c89e4eSSatish Balay @*/
1569371c9d4SSatish Balay PetscErrorCode PetscPOpen(MPI_Comm comm, const char machine[], const char program[], const char mode[], FILE **fp) {
157e5c89e4eSSatish Balay   PetscMPIInt rank;
158e5c89e4eSSatish Balay   size_t      i, len, cnt;
159e5c89e4eSSatish Balay   char        commandt[PETSC_MAX_PATH_LEN], command[PETSC_MAX_PATH_LEN];
160e5c89e4eSSatish Balay   FILE       *fd;
161e5c89e4eSSatish Balay 
162e5c89e4eSSatish Balay   PetscFunctionBegin;
163e5c89e4eSSatish Balay   /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
16474ba8654SBarry Smith   if (PetscPOpenMachine[0] || (machine && machine[0])) {
1659566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(command, "ssh "));
16674ba8654SBarry Smith     if (PetscPOpenMachine[0]) {
1679566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(command, PetscPOpenMachine));
16874ba8654SBarry Smith     } else {
1699566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(command, machine));
17074ba8654SBarry Smith     }
1719566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(command, " \" export DISPLAY=${DISPLAY}; "));
172e5c89e4eSSatish Balay     /*
173e5c89e4eSSatish Balay         Copy program into command but protect the " with a \ in front of it
174e5c89e4eSSatish Balay     */
1759566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(command, &cnt));
1769566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(program, &len));
177e5c89e4eSSatish Balay     for (i = 0; i < len; i++) {
178a297a907SKarl Rupp       if (program[i] == '\"') command[cnt++] = '\\';
179e5c89e4eSSatish Balay       command[cnt++] = program[i];
180e5c89e4eSSatish Balay     }
181e5c89e4eSSatish Balay     command[cnt] = 0;
182a297a907SKarl Rupp 
1839566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(command, "\""));
184e5c89e4eSSatish Balay   } else {
1859566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(command, program));
186e5c89e4eSSatish Balay   }
187e5c89e4eSSatish Balay 
1889566063dSJacob Faibussowitsch   PetscCall(PetscStrreplace(comm, command, commandt, 1024));
189e5c89e4eSSatish Balay 
1909566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
191dd400576SPatrick Sanan   if (rank == 0) {
1929566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Running command :%s\n", commandt));
193cc73adaaSBarry Smith     PetscCheck((fd = popen(commandt, mode)), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot run command %s", commandt);
194e5c89e4eSSatish Balay     if (fp) *fp = fd;
195e5c89e4eSSatish Balay   }
196e5c89e4eSSatish Balay   PetscFunctionReturn(0);
197e5c89e4eSSatish Balay }
198e5c89e4eSSatish Balay 
19974ba8654SBarry Smith /*@C
20074ba8654SBarry Smith       PetscPOpenSetMachine - Sets the name of the default machine to run PetscPOpen() calls on
20174ba8654SBarry Smith 
202d083f849SBarry Smith      Logically Collective, but only process 0 runs the command
20374ba8654SBarry Smith 
20474ba8654SBarry Smith    Input Parameter:
20510699b91SBarry Smith .   machine - machine to run command on or NULL for the current machine
20674ba8654SBarry Smith 
20774ba8654SBarry Smith    Options Database:
20810699b91SBarry Smith .   -popen_machine <machine> - run the process on this machine
20974ba8654SBarry Smith 
21074ba8654SBarry Smith    Level: intermediate
21174ba8654SBarry Smith 
212db781477SPatrick Sanan .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPClose()`, `PetscPOpen()`
21374ba8654SBarry Smith @*/
2149371c9d4SSatish Balay PetscErrorCode PetscPOpenSetMachine(const char machine[]) {
21574ba8654SBarry Smith   PetscFunctionBegin;
21674ba8654SBarry Smith   if (machine) {
2179566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(PetscPOpenMachine, machine));
21874ba8654SBarry Smith   } else {
21974ba8654SBarry Smith     PetscPOpenMachine[0] = 0;
22074ba8654SBarry Smith   }
22174ba8654SBarry Smith   PetscFunctionReturn(0);
22274ba8654SBarry Smith }
22374ba8654SBarry Smith 
224e5c89e4eSSatish Balay #endif
225