xref: /petsc/src/sys/fileio/mpiuopen.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
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 
25811af0c4SBarry Smith     Note:
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 @*/
34*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFOpen(MPI_Comm comm, const char name[], const char mode[], FILE **fp)
35*d71ae5a4SJacob Faibussowitsch {
36e5c89e4eSSatish Balay   PetscMPIInt rank;
37e5c89e4eSSatish Balay   FILE       *fd;
38e5c89e4eSSatish Balay   char        fname[PETSC_MAX_PATH_LEN], tname[PETSC_MAX_PATH_LEN];
39e5c89e4eSSatish Balay 
40e5c89e4eSSatish Balay   PetscFunctionBegin;
419566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
42dd400576SPatrick Sanan   if (rank == 0) {
43ace3abfcSBarry Smith     PetscBool isstdout, isstderr;
449566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stdout", &isstdout));
459566063dSJacob Faibussowitsch     PetscCall(PetscStrcmp(name, "stderr", &isstderr));
46a297a907SKarl Rupp     if (isstdout || !name) fd = PETSC_STDOUT;
47a297a907SKarl Rupp     else if (isstderr) fd = PETSC_STDERR;
48a297a907SKarl Rupp     else {
49b3f259d6SBarry Smith       PetscBool devnull;
509566063dSJacob Faibussowitsch       PetscCall(PetscStrreplace(PETSC_COMM_SELF, name, tname, PETSC_MAX_PATH_LEN));
519566063dSJacob Faibussowitsch       PetscCall(PetscFixFilename(tname, fname));
529566063dSJacob Faibussowitsch       PetscCall(PetscStrbeginswith(fname, "/dev/null", &devnull));
5348a46eb9SPierre Jolivet       if (devnull) PetscCall(PetscStrcpy(fname, "/dev/null"));
549566063dSJacob Faibussowitsch       PetscCall(PetscInfo(0, "Opening file %s\n", fname));
55e5c89e4eSSatish Balay       fd = fopen(fname, mode);
5628b400f6SJacob Faibussowitsch       PetscCheck(fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Unable to open file %s", fname);
57e5c89e4eSSatish Balay     }
5802c9f0b5SLisandro Dalcin   } else fd = NULL;
59e5c89e4eSSatish Balay   *fp = fd;
60e5c89e4eSSatish Balay   PetscFunctionReturn(0);
61e5c89e4eSSatish Balay }
62e5c89e4eSSatish Balay 
63e8976759SBarry Smith /*@C
64e5c89e4eSSatish Balay     PetscFClose - Has the first processor in the communicator close a
65e5c89e4eSSatish Balay     file; all others do nothing.
66e5c89e4eSSatish Balay 
67d083f849SBarry Smith     Logically Collective
68e5c89e4eSSatish Balay 
69e5c89e4eSSatish Balay     Input Parameters:
70e5c89e4eSSatish Balay +   comm - the communicator
71e5c89e4eSSatish Balay -   fd - the file, opened with PetscFOpen()
72e5c89e4eSSatish Balay 
73e5c89e4eSSatish Balay    Level: developer
74e5c89e4eSSatish Balay 
75e5c89e4eSSatish Balay     Fortran Note:
76e5c89e4eSSatish Balay     This routine is not supported in Fortran.
77e5c89e4eSSatish Balay 
78db781477SPatrick Sanan .seealso: `PetscFOpen()`
79e5c89e4eSSatish Balay @*/
80*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscFClose(MPI_Comm comm, FILE *fd)
81*d71ae5a4SJacob Faibussowitsch {
82e5c89e4eSSatish Balay   PetscMPIInt rank;
83ed9cf6e9SBarry Smith   int         err;
84e5c89e4eSSatish Balay 
85e5c89e4eSSatish Balay   PetscFunctionBegin;
869566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
87dd400576SPatrick Sanan   if (rank == 0 && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
88ed9cf6e9SBarry Smith     err = fclose(fd);
8928b400f6SJacob Faibussowitsch     PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
90ed9cf6e9SBarry Smith   }
91e5c89e4eSSatish Balay   PetscFunctionReturn(0);
92e5c89e4eSSatish Balay }
93e5c89e4eSSatish Balay 
94e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN)
9574ba8654SBarry Smith static char PetscPOpenMachine[128] = "";
96e5c89e4eSSatish Balay 
97e5c89e4eSSatish Balay /*@C
98811af0c4SBarry Smith       PetscPClose - Closes (ends) a program on processor zero run with `PetscPOpen()`
99e5c89e4eSSatish Balay 
100d083f849SBarry Smith      Collective, but only process 0 runs the command
101e5c89e4eSSatish Balay 
102e5c89e4eSSatish Balay    Input Parameters:
103e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
1040298fd71SBarry Smith -   fp - the file pointer where program input or output may be read or NULL if don't care
105e5c89e4eSSatish Balay 
106e5c89e4eSSatish Balay    Level: intermediate
107e5c89e4eSSatish Balay 
108811af0c4SBarry Smith    Note:
109e5c89e4eSSatish Balay        Does not work under Windows
110e5c89e4eSSatish Balay 
111db781477SPatrick Sanan .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPOpen()`
112e5c89e4eSSatish Balay @*/
113*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPClose(MPI_Comm comm, FILE *fd)
114*d71ae5a4SJacob Faibussowitsch {
115e5c89e4eSSatish Balay   PetscMPIInt rank;
116e5c89e4eSSatish Balay 
117e5c89e4eSSatish Balay   PetscFunctionBegin;
1189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
119dd400576SPatrick Sanan   if (rank == 0) {
120e5c89e4eSSatish Balay     char buf[1024];
1219371c9d4SSatish Balay     while (fgets(buf, 1024, fd))
1229371c9d4SSatish Balay       ; /* wait till it prints everything */
123016831caSBarry Smith     (void)pclose(fd);
124e5c89e4eSSatish Balay   }
125e5c89e4eSSatish Balay   PetscFunctionReturn(0);
126e5c89e4eSSatish Balay }
127e5c89e4eSSatish Balay 
128e5c89e4eSSatish Balay /*@C
129e5c89e4eSSatish Balay       PetscPOpen - Runs a program on processor zero and sends either its input or output to
130e5c89e4eSSatish Balay           a file.
131e5c89e4eSSatish Balay 
132d083f849SBarry Smith      Logically Collective, but only process 0 runs the command
133e5c89e4eSSatish Balay 
134e5c89e4eSSatish Balay    Input Parameters:
135e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
1360298fd71SBarry Smith .   machine - machine to run command on or NULL, or string with 0 in first location
137e5c89e4eSSatish Balay .   program - name of program to run
138e5c89e4eSSatish Balay -   mode - either r or w
139e5c89e4eSSatish Balay 
140e5c89e4eSSatish Balay    Output Parameter:
1410298fd71SBarry Smith .   fp - the file pointer where program input or output may be read or NULL if don't care
142e5c89e4eSSatish Balay 
143e5c89e4eSSatish Balay    Level: intermediate
144e5c89e4eSSatish Balay 
145e5c89e4eSSatish Balay    Notes:
146811af0c4SBarry Smith        Use `PetscPClose()` to close the file pointer when you are finished with it
147811af0c4SBarry Smith 
148e5c89e4eSSatish Balay        Does not work under Windows
149e5c89e4eSSatish Balay 
150811af0c4SBarry Smith        If machine is not provided will use the value set with `PetsPOpenSetMachine()` if that was provided, otherwise
15174ba8654SBarry Smith        will use the machine running node zero of the communicator
15274ba8654SBarry Smith 
153e5c89e4eSSatish Balay        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
154a5b23f4aSJose E. Roman     will be replaced with relevant values.
155e5c89e4eSSatish Balay 
156db781477SPatrick Sanan .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPClose()`, `PetscPOpenSetMachine()`
157e5c89e4eSSatish Balay @*/
158*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPOpen(MPI_Comm comm, const char machine[], const char program[], const char mode[], FILE **fp)
159*d71ae5a4SJacob Faibussowitsch {
160e5c89e4eSSatish Balay   PetscMPIInt rank;
161e5c89e4eSSatish Balay   size_t      i, len, cnt;
162e5c89e4eSSatish Balay   char        commandt[PETSC_MAX_PATH_LEN], command[PETSC_MAX_PATH_LEN];
163e5c89e4eSSatish Balay   FILE       *fd;
164e5c89e4eSSatish Balay 
165e5c89e4eSSatish Balay   PetscFunctionBegin;
166e5c89e4eSSatish Balay   /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
16774ba8654SBarry Smith   if (PetscPOpenMachine[0] || (machine && machine[0])) {
1689566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(command, "ssh "));
16974ba8654SBarry Smith     if (PetscPOpenMachine[0]) {
1709566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(command, PetscPOpenMachine));
17174ba8654SBarry Smith     } else {
1729566063dSJacob Faibussowitsch       PetscCall(PetscStrcat(command, machine));
17374ba8654SBarry Smith     }
1749566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(command, " \" export DISPLAY=${DISPLAY}; "));
175e5c89e4eSSatish Balay     /*
176e5c89e4eSSatish Balay         Copy program into command but protect the " with a \ in front of it
177e5c89e4eSSatish Balay     */
1789566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(command, &cnt));
1799566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(program, &len));
180e5c89e4eSSatish Balay     for (i = 0; i < len; i++) {
181a297a907SKarl Rupp       if (program[i] == '\"') command[cnt++] = '\\';
182e5c89e4eSSatish Balay       command[cnt++] = program[i];
183e5c89e4eSSatish Balay     }
184e5c89e4eSSatish Balay     command[cnt] = 0;
185a297a907SKarl Rupp 
1869566063dSJacob Faibussowitsch     PetscCall(PetscStrcat(command, "\""));
187e5c89e4eSSatish Balay   } else {
1889566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(command, program));
189e5c89e4eSSatish Balay   }
190e5c89e4eSSatish Balay 
1919566063dSJacob Faibussowitsch   PetscCall(PetscStrreplace(comm, command, commandt, 1024));
192e5c89e4eSSatish Balay 
1939566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
194dd400576SPatrick Sanan   if (rank == 0) {
1959566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Running command :%s\n", commandt));
196cc73adaaSBarry Smith     PetscCheck((fd = popen(commandt, mode)), PETSC_COMM_SELF, PETSC_ERR_LIB, "Cannot run command %s", commandt);
197e5c89e4eSSatish Balay     if (fp) *fp = fd;
198e5c89e4eSSatish Balay   }
199e5c89e4eSSatish Balay   PetscFunctionReturn(0);
200e5c89e4eSSatish Balay }
201e5c89e4eSSatish Balay 
20274ba8654SBarry Smith /*@C
203811af0c4SBarry Smith       PetscPOpenSetMachine - Sets the name of the default machine to run `PetscPOpen()` calls on
20474ba8654SBarry Smith 
205d083f849SBarry Smith      Logically Collective, but only process 0 runs the command
20674ba8654SBarry Smith 
20774ba8654SBarry Smith    Input Parameter:
20810699b91SBarry Smith .   machine - machine to run command on or NULL for the current machine
20974ba8654SBarry Smith 
210811af0c4SBarry Smith    Options Database Key:
21110699b91SBarry Smith .   -popen_machine <machine> - run the process on this machine
21274ba8654SBarry Smith 
21374ba8654SBarry Smith    Level: intermediate
21474ba8654SBarry Smith 
215db781477SPatrick Sanan .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPClose()`, `PetscPOpen()`
21674ba8654SBarry Smith @*/
217*d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPOpenSetMachine(const char machine[])
218*d71ae5a4SJacob Faibussowitsch {
21974ba8654SBarry Smith   PetscFunctionBegin;
22074ba8654SBarry Smith   if (machine) {
2219566063dSJacob Faibussowitsch     PetscCall(PetscStrcpy(PetscPOpenMachine, machine));
22274ba8654SBarry Smith   } else {
22374ba8654SBarry Smith     PetscPOpenMachine[0] = 0;
22474ba8654SBarry Smith   }
22574ba8654SBarry Smith   PetscFunctionReturn(0);
22674ba8654SBarry Smith }
22774ba8654SBarry Smith 
228e5c89e4eSSatish Balay #endif
229