Actual source code: mpiuopen.c
1: #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for popen() */
2: /*
3: Some PETSc utility routines to add simple parallel IO capabilities
4: */
5: #include <petscsys.h>
6: #include <petsc/private/logimpl.h>
7: #include <errno.h>
9: /*@C
10: PetscFOpen - Has the first process in the communicator open a file;
11: all others do nothing.
13: Logically Collective
15: Input Parameters:
16: + comm - the communicator
17: . name - the filename
18: - mode - the mode for fopen(), usually "w"
20: Output Parameter:
21: . fp - the file pointer
23: Level: developer
25: Note:
26: NULL (0), "stderr" or "stdout" may be passed in as the filename
28: Fortran Note:
29: This routine is not supported in Fortran.
31: .seealso: `PetscFClose()`, `PetscSynchronizedFGets()`, `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`,
32: `PetscFPrintf()`
33: @*/
34: PetscErrorCode PetscFOpen(MPI_Comm comm, const char name[], const char mode[], FILE **fp)
35: {
36: PetscMPIInt rank;
37: FILE *fd;
38: char fname[PETSC_MAX_PATH_LEN], tname[PETSC_MAX_PATH_LEN];
40: MPI_Comm_rank(comm, &rank);
41: if (rank == 0) {
42: PetscBool isstdout, isstderr;
43: PetscStrcmp(name, "stdout", &isstdout);
44: PetscStrcmp(name, "stderr", &isstderr);
45: if (isstdout || !name) fd = PETSC_STDOUT;
46: else if (isstderr) fd = PETSC_STDERR;
47: else {
48: PetscBool devnull;
49: PetscStrreplace(PETSC_COMM_SELF, name, tname, PETSC_MAX_PATH_LEN);
50: PetscFixFilename(tname, fname);
51: PetscStrbeginswith(fname, "/dev/null", &devnull);
52: if (devnull) PetscStrcpy(fname, "/dev/null");
53: PetscInfo(0, "Opening file %s\n", fname);
54: fd = fopen(fname, mode);
56: }
57: } else fd = NULL;
58: *fp = fd;
59: return 0;
60: }
62: /*@C
63: PetscFClose - Has the first processor in the communicator close a
64: file; all others do nothing.
66: Logically Collective
68: Input Parameters:
69: + comm - the communicator
70: - fd - the file, opened with PetscFOpen()
72: Level: developer
74: Fortran Note:
75: This routine is not supported in Fortran.
77: .seealso: `PetscFOpen()`
78: @*/
79: PetscErrorCode PetscFClose(MPI_Comm comm, FILE *fd)
80: {
81: PetscMPIInt rank;
82: int err;
84: MPI_Comm_rank(comm, &rank);
85: if (rank == 0 && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
86: err = fclose(fd);
88: }
89: return 0;
90: }
92: #if defined(PETSC_HAVE_POPEN)
93: static char PetscPOpenMachine[128] = "";
95: /*@C
96: PetscPClose - Closes (ends) a program on processor zero run with `PetscPOpen()`
98: Collective, but only process 0 runs the command
100: Input Parameters:
101: + comm - MPI communicator, only processor zero runs the program
102: - fp - the file pointer where program input or output may be read or NULL if don't care
104: Level: intermediate
106: Note:
107: Does not work under Windows
109: .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPOpen()`
110: @*/
111: PetscErrorCode PetscPClose(MPI_Comm comm, FILE *fd)
112: {
113: PetscMPIInt rank;
115: MPI_Comm_rank(comm, &rank);
116: if (rank == 0) {
117: char buf[1024];
118: while (fgets(buf, 1024, fd))
119: ; /* wait till it prints everything */
120: (void)pclose(fd);
121: }
122: return 0;
123: }
125: /*@C
126: PetscPOpen - Runs a program on processor zero and sends either its input or output to
127: a file.
129: Logically Collective, but only process 0 runs the command
131: Input Parameters:
132: + comm - MPI communicator, only processor zero runs the program
133: . machine - machine to run command on or NULL, or string with 0 in first location
134: . program - name of program to run
135: - mode - either r or w
137: Output Parameter:
138: . fp - the file pointer where program input or output may be read or NULL if don't care
140: Level: intermediate
142: Notes:
143: Use `PetscPClose()` to close the file pointer when you are finished with it
145: Does not work under Windows
147: If machine is not provided will use the value set with `PetsPOpenSetMachine()` if that was provided, otherwise
148: will use the machine running node zero of the communicator
150: The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
151: will be replaced with relevant values.
153: .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPClose()`, `PetscPOpenSetMachine()`
154: @*/
155: PetscErrorCode PetscPOpen(MPI_Comm comm, const char machine[], const char program[], const char mode[], FILE **fp)
156: {
157: PetscMPIInt rank;
158: size_t i, len, cnt;
159: char commandt[PETSC_MAX_PATH_LEN], command[PETSC_MAX_PATH_LEN];
160: FILE *fd;
162: /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
163: if (PetscPOpenMachine[0] || (machine && machine[0])) {
164: PetscStrcpy(command, "ssh ");
165: if (PetscPOpenMachine[0]) {
166: PetscStrcat(command, PetscPOpenMachine);
167: } else {
168: PetscStrcat(command, machine);
169: }
170: PetscStrcat(command, " \" export DISPLAY=${DISPLAY}; ");
171: /*
172: Copy program into command but protect the " with a \ in front of it
173: */
174: PetscStrlen(command, &cnt);
175: PetscStrlen(program, &len);
176: for (i = 0; i < len; i++) {
177: if (program[i] == '\"') command[cnt++] = '\\';
178: command[cnt++] = program[i];
179: }
180: command[cnt] = 0;
182: PetscStrcat(command, "\"");
183: } else {
184: PetscStrcpy(command, program);
185: }
187: PetscStrreplace(comm, command, commandt, 1024);
189: MPI_Comm_rank(comm, &rank);
190: if (rank == 0) {
191: PetscInfo(NULL, "Running command :%s\n", commandt);
193: if (fp) *fp = fd;
194: }
195: return 0;
196: }
198: /*@C
199: PetscPOpenSetMachine - Sets the name of the default machine to run `PetscPOpen()` calls on
201: Logically Collective, but only process 0 runs the command
203: Input Parameter:
204: . machine - machine to run command on or NULL for the current machine
206: Options Database Key:
207: . -popen_machine <machine> - run the process on this machine
209: Level: intermediate
211: .seealso: `PetscFOpen()`, `PetscFClose()`, `PetscPClose()`, `PetscPOpen()`
212: @*/
213: PetscErrorCode PetscPOpenSetMachine(const char machine[])
214: {
215: if (machine) {
216: PetscStrcpy(PetscPOpenMachine, machine);
217: } else {
218: PetscPOpenMachine[0] = 0;
219: }
220: return 0;
221: }
223: #endif