xref: /petsc/src/sys/fileio/mpiuopen.c (revision cf53795e253c8c9d9d0fbcef4cffd37d916c4e81)
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 
13*cf53795eSBarry Smith     Logically Collective; No Fortran Support
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 
25811af0c4SBarry Smith     Note:
260298fd71SBarry Smith        NULL (0), "stderr" or "stdout" may be passed in as the filename
27e5c89e4eSSatish Balay 
28db781477SPatrick Sanan .seealso: `PetscFClose()`, `PetscSynchronizedFGets()`, `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`,
29db781477SPatrick Sanan           `PetscFPrintf()`
30e5c89e4eSSatish Balay @*/
31d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFOpen(MPI_Comm comm, const char name[], const char mode[], FILE **fp)
32d71ae5a4SJacob Faibussowitsch {
33e5c89e4eSSatish Balay   PetscMPIInt rank;
34e5c89e4eSSatish Balay   FILE       *fd;
35e5c89e4eSSatish Balay   char        fname[PETSC_MAX_PATH_LEN], tname[PETSC_MAX_PATH_LEN];
36e5c89e4eSSatish Balay 
37e5c89e4eSSatish Balay   PetscFunctionBegin;
389566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
39dd400576SPatrick Sanan   if (rank == 0) {
40ace3abfcSBarry Smith     PetscBool isstdout, isstderr;
419566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stdout", &isstdout));
429566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stderr", &isstderr));
43a297a907SKarl Rupp     if (isstdout || !name) fd = PETSC_STDOUT;
44a297a907SKarl Rupp     else if (isstderr) fd = PETSC_STDERR;
45a297a907SKarl Rupp     else {
46b3f259d6SBarry Smith       PetscBool devnull;
479566063dSJacob Faibussowitsch       PetscCall(PetscStrreplace(PETSC_COMM_SELF, name, tname, PETSC_MAX_PATH_LEN));
489566063dSJacob Faibussowitsch       PetscCall(PetscFixFilename(tname, fname));
499566063dSJacob Faibussowitsch       PetscCall(PetscStrbeginswith(fname, "/dev/null", &devnull));
5048a46eb9SPierre Jolivet       if (devnull) PetscCall(PetscStrcpy(fname, "/dev/null"));
519566063dSJacob Faibussowitsch       PetscCall(PetscInfo(0, "Opening file %s\n", fname));
52e5c89e4eSSatish Balay       fd = fopen(fname, mode);
5328b400f6SJacob Faibussowitsch       PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open file %s", fname);
54e5c89e4eSSatish Balay     }
5502c9f0b5SLisandro Dalcin   } else fd = NULL;
56e5c89e4eSSatish Balay   *fp = fd;
57e5c89e4eSSatish Balay   PetscFunctionReturn(0);
58e5c89e4eSSatish Balay }
59e5c89e4eSSatish Balay 
60e8976759SBarry Smith /*@C
61e5c89e4eSSatish Balay     PetscFClose - Has the first processor in the communicator close a
62e5c89e4eSSatish Balay     file; all others do nothing.
63e5c89e4eSSatish Balay 
64*cf53795eSBarry Smith     Logically Collective; No Fortran Support
65e5c89e4eSSatish Balay 
66e5c89e4eSSatish Balay     Input Parameters:
67e5c89e4eSSatish Balay +   comm - the communicator
68e5c89e4eSSatish Balay -   fd - the file, opened with PetscFOpen()
69e5c89e4eSSatish Balay 
70e5c89e4eSSatish Balay    Level: developer
71e5c89e4eSSatish Balay 
72db781477SPatrick Sanan .seealso: `PetscFOpen()`
73e5c89e4eSSatish Balay @*/
74d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFClose(MPI_Comm comm, FILE *fd)
75d71ae5a4SJacob Faibussowitsch {
76e5c89e4eSSatish Balay   PetscMPIInt rank;
77ed9cf6e9SBarry Smith   int         err;
78e5c89e4eSSatish Balay 
79e5c89e4eSSatish Balay   PetscFunctionBegin;
809566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
81dd400576SPatrick Sanan   if (rank == 0 && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
82ed9cf6e9SBarry Smith     err = fclose(fd);
8328b400f6SJacob Faibussowitsch     PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
84ed9cf6e9SBarry Smith   }
85e5c89e4eSSatish Balay   PetscFunctionReturn(0);
86e5c89e4eSSatish Balay }
87e5c89e4eSSatish Balay 
88e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN)
8974ba8654SBarry Smith static char PetscPOpenMachine[128] = "";
90e5c89e4eSSatish Balay 
91e5c89e4eSSatish Balay /*@C
92811af0c4SBarry Smith       PetscPClose - Closes (ends) a program on processor zero run with `PetscPOpen()`
93e5c89e4eSSatish Balay 
94d083f849SBarry Smith      Collective, but only process 0 runs the command
95e5c89e4eSSatish Balay 
96e5c89e4eSSatish Balay    Input Parameters:
97e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
980298fd71SBarry Smith -   fp - the file pointer where program input or output may be read or NULL if don't care
99e5c89e4eSSatish Balay 
100e5c89e4eSSatish Balay    Level: intermediate
101e5c89e4eSSatish Balay 
102811af0c4SBarry Smith    Note:
103e5c89e4eSSatish Balay        Does not work under Windows
104e5c89e4eSSatish Balay 
105db781477SPatrick Sanan .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPOpen()`
106e5c89e4eSSatish Balay @*/
107d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPClose(MPI_Comm comm, FILE *fd)
108d71ae5a4SJacob Faibussowitsch {
109e5c89e4eSSatish Balay   PetscMPIInt rank;
110e5c89e4eSSatish Balay 
111e5c89e4eSSatish Balay   PetscFunctionBegin;
1129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
113dd400576SPatrick Sanan   if (rank == 0) {
114e5c89e4eSSatish Balay     char buf[1024];
1159371c9d4SSatish Balay     while (fgets(buf, 1024, fd))
1169371c9d4SSatish Balay       ; /* wait till it prints everything */
117016831caSBarry Smith     (void)pclose(fd);
118e5c89e4eSSatish Balay   }
119e5c89e4eSSatish Balay   PetscFunctionReturn(0);
120e5c89e4eSSatish Balay }
121e5c89e4eSSatish Balay 
122e5c89e4eSSatish Balay /*@C
123e5c89e4eSSatish Balay       PetscPOpen - Runs a program on processor zero and sends either its input or output to
124e5c89e4eSSatish Balay           a file.
125e5c89e4eSSatish Balay 
126d083f849SBarry Smith      Logically Collective, but only process 0 runs the command
127e5c89e4eSSatish Balay 
128e5c89e4eSSatish Balay    Input Parameters:
129e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
1300298fd71SBarry Smith .   machine - machine to run command on or NULL, or string with 0 in first location
131e5c89e4eSSatish Balay .   program - name of program to run
132e5c89e4eSSatish Balay -   mode - either r or w
133e5c89e4eSSatish Balay 
134e5c89e4eSSatish Balay    Output Parameter:
1350298fd71SBarry Smith .   fp - the file pointer where program input or output may be read or NULL if don't care
136e5c89e4eSSatish Balay 
137e5c89e4eSSatish Balay    Level: intermediate
138e5c89e4eSSatish Balay 
139e5c89e4eSSatish Balay    Notes:
140811af0c4SBarry Smith        Use `PetscPClose()` to close the file pointer when you are finished with it
141811af0c4SBarry Smith 
142e5c89e4eSSatish Balay        Does not work under Windows
143e5c89e4eSSatish Balay 
144811af0c4SBarry Smith        If machine is not provided will use the value set with `PetsPOpenSetMachine()` if that was provided, otherwise
14574ba8654SBarry Smith        will use the machine running node zero of the communicator
14674ba8654SBarry Smith 
147e5c89e4eSSatish Balay        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
148a5b23f4aSJose E. Roman     will be replaced with relevant values.
149e5c89e4eSSatish Balay 
150db781477SPatrick Sanan .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPClose()`, `PetscPOpenSetMachine()`
151e5c89e4eSSatish Balay @*/
152d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPOpen(MPI_Comm comm, const char machine[], const char program[], const char mode[], FILE **fp)
153d71ae5a4SJacob Faibussowitsch {
154e5c89e4eSSatish Balay   PetscMPIInt rank;
155e5c89e4eSSatish Balay   size_t      i, len, cnt;
156e5c89e4eSSatish Balay   char        commandt[PETSC_MAX_PATH_LEN], command[PETSC_MAX_PATH_LEN];
157e5c89e4eSSatish Balay   FILE       *fd;
158e5c89e4eSSatish Balay 
159e5c89e4eSSatish Balay   PetscFunctionBegin;
160e5c89e4eSSatish Balay   /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
16174ba8654SBarry Smith   if (PetscPOpenMachine[0] || (machine && machine[0])) {
1629566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(command, "ssh "));
16374ba8654SBarry Smith     if (PetscPOpenMachine[0]) {
1649566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(command, PetscPOpenMachine));
16574ba8654SBarry Smith     } else {
1669566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(command, machine));
16774ba8654SBarry Smith     }
1689566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(command, " \" export DISPLAY=${DISPLAY}; "));
169e5c89e4eSSatish Balay     /*
170e5c89e4eSSatish Balay         Copy program into command but protect the " with a \ in front of it
171e5c89e4eSSatish Balay     */
1729566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(command, &cnt));
1739566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(program, &len));
174e5c89e4eSSatish Balay     for (i = 0; i < len; i++) {
175a297a907SKarl Rupp       if (program[i] == '\"') command[cnt++] = '\\';
176e5c89e4eSSatish Balay       command[cnt++] = program[i];
177e5c89e4eSSatish Balay     }
178e5c89e4eSSatish Balay     command[cnt] = 0;
179a297a907SKarl Rupp 
1809566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(command, "\""));
181e5c89e4eSSatish Balay   } else {
1829566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(command, program));
183e5c89e4eSSatish Balay   }
184e5c89e4eSSatish Balay 
1859566063dSJacob Faibussowitsch   PetscCall(PetscStrreplace(comm, command, commandt, 1024));
186e5c89e4eSSatish Balay 
1879566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
188dd400576SPatrick Sanan   if (rank == 0) {
1899566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Running command :%s\n", commandt));
190cc73adaaSBarry Smith     PetscCheck((fd = popen(commandt, mode)), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot run command %s", commandt);
191e5c89e4eSSatish Balay     if (fp) *fp = fd;
192e5c89e4eSSatish Balay   }
193e5c89e4eSSatish Balay   PetscFunctionReturn(0);
194e5c89e4eSSatish Balay }
195e5c89e4eSSatish Balay 
19674ba8654SBarry Smith /*@C
197811af0c4SBarry Smith       PetscPOpenSetMachine - Sets the name of the default machine to run `PetscPOpen()` calls on
19874ba8654SBarry Smith 
199d083f849SBarry Smith      Logically Collective, but only process 0 runs the command
20074ba8654SBarry Smith 
20174ba8654SBarry Smith    Input Parameter:
20210699b91SBarry Smith .   machine - machine to run command on or NULL for the current machine
20374ba8654SBarry Smith 
204811af0c4SBarry Smith    Options Database Key:
20510699b91SBarry Smith .   -popen_machine <machine> - run the process on this machine
20674ba8654SBarry Smith 
20774ba8654SBarry Smith    Level: intermediate
20874ba8654SBarry Smith 
209db781477SPatrick Sanan .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPClose()`, `PetscPOpen()`
21074ba8654SBarry Smith @*/
211d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPOpenSetMachine(const char machine[])
212d71ae5a4SJacob Faibussowitsch {
21374ba8654SBarry Smith   PetscFunctionBegin;
21474ba8654SBarry Smith   if (machine) {
2159566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(PetscPOpenMachine, machine));
21674ba8654SBarry Smith   } else {
21774ba8654SBarry Smith     PetscPOpenMachine[0] = 0;
21874ba8654SBarry Smith   }
21974ba8654SBarry Smith   PetscFunctionReturn(0);
22074ba8654SBarry Smith }
22174ba8654SBarry Smith 
222e5c89e4eSSatish Balay #endif
223