Actual source code: mpiuopen.c
petsc-3.12.5 2020-03-29
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>
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: Notes:
26: NULL (0), "stderr" or "stdout" may be passed in as the filename
28: Fortran Note:
29: This routine is not supported in Fortran.
32: .seealso: PetscFClose(), PetscSynchronizedFGets(), PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
33: PetscFPrintf()
34: @*/
35: PetscErrorCode PetscFOpen(MPI_Comm comm,const char name[],const char mode[],FILE **fp)
36: {
38: PetscMPIInt rank;
39: FILE *fd;
40: char fname[PETSC_MAX_PATH_LEN],tname[PETSC_MAX_PATH_LEN];
43: MPI_Comm_rank(comm,&rank);
44: if (!rank) {
45: PetscBool isstdout,isstderr;
46: PetscStrcmp(name,"stdout",&isstdout);
47: PetscStrcmp(name,"stderr",&isstderr);
48: if (isstdout || !name) fd = PETSC_STDOUT;
49: else if (isstderr) fd = PETSC_STDERR;
50: else {
51: PetscBool devnull;
52: PetscStrreplace(PETSC_COMM_SELF,name,tname,PETSC_MAX_PATH_LEN);
53: PetscFixFilename(tname,fname);
54: PetscStrbeginswith(fname,"/dev/null",&devnull);
55: if (devnull) {
56: PetscStrcpy(fname,"/dev/null");
57: }
58: PetscInfo1(0,"Opening file %s\n",fname);
59: fd = fopen(fname,mode);
60: if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file %s\n",fname);
61: }
62: } else fd = 0;
63: *fp = fd;
64: return(0);
65: }
67: /*@C
68: PetscFClose - Has the first processor in the communicator close a
69: file; all others do nothing.
71: Logically Collective
73: Input Parameters:
74: + comm - the communicator
75: - fd - the file, opened with PetscFOpen()
77: Level: developer
79: Fortran Note:
80: This routine is not supported in Fortran.
83: .seealso: PetscFOpen()
84: @*/
85: PetscErrorCode PetscFClose(MPI_Comm comm,FILE *fd)
86: {
88: PetscMPIInt rank;
89: int err;
92: MPI_Comm_rank(comm,&rank);
93: if (!rank && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
94: err = fclose(fd);
95: if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
96: }
97: return(0);
98: }
100: #if defined(PETSC_HAVE_POPEN)
101: static char PetscPOpenMachine[128] = "";
103: /*@C
104: PetscPClose - Closes (ends) a program on processor zero run with PetscPOpen()
106: Collective, but only process 0 runs the command
108: Input Parameters:
109: + comm - MPI communicator, only processor zero runs the program
110: - fp - the file pointer where program input or output may be read or NULL if don't care
112: Level: intermediate
114: Notes:
115: Does not work under Windows
117: .seealso: PetscFOpen(), PetscFClose(), PetscPOpen()
119: @*/
120: PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd)
121: {
123: PetscMPIInt rank;
126: MPI_Comm_rank(comm,&rank);
127: if (!rank) {
128: char buf[1024];
129: while (fgets(buf,1024,fd)) ; /* wait till it prints everything */
130: (void) pclose(fd);
131: }
132: return(0);
133: }
136: /*@C
137: PetscPOpen - Runs a program on processor zero and sends either its input or output to
138: a file.
140: Logically Collective, but only process 0 runs the command
142: Input Parameters:
143: + comm - MPI communicator, only processor zero runs the program
144: . machine - machine to run command on or NULL, or string with 0 in first location
145: . program - name of program to run
146: - mode - either r or w
148: Output Parameter:
149: . fp - the file pointer where program input or output may be read or NULL if don't care
151: Level: intermediate
153: Notes:
154: Use PetscPClose() to close the file pointer when you are finished with it
155: Does not work under Windows
157: If machine is not provided will use the value set with PetsPOpenSetMachine() if that was provided, otherwise
158: will use the machine running node zero of the communicator
160: The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
161: will be replaced with relevent values.
163: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpenSetMachine()
165: @*/
166: PetscErrorCode PetscPOpen(MPI_Comm comm,const char machine[],const char program[],const char mode[],FILE **fp)
167: {
169: PetscMPIInt rank;
170: size_t i,len,cnt;
171: char commandt[PETSC_MAX_PATH_LEN],command[PETSC_MAX_PATH_LEN];
172: FILE *fd;
175: /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
176: if (PetscPOpenMachine[0] || (machine && machine[0])) {
177: PetscStrcpy(command,"ssh ");
178: if (PetscPOpenMachine[0]) {
179: PetscStrcat(command,PetscPOpenMachine);
180: } else {
181: PetscStrcat(command,machine);
182: }
183: PetscStrcat(command," \" export DISPLAY=${DISPLAY}; ");
184: /*
185: Copy program into command but protect the " with a \ in front of it
186: */
187: PetscStrlen(command,&cnt);
188: PetscStrlen(program,&len);
189: for (i=0; i<len; i++) {
190: if (program[i] == '\"') command[cnt++] = '\\';
191: command[cnt++] = program[i];
192: }
193: command[cnt] = 0;
195: PetscStrcat(command,"\"");
196: } else {
197: PetscStrcpy(command,program);
198: }
200: PetscStrreplace(comm,command,commandt,1024);
202: MPI_Comm_rank(comm,&rank);
203: if (!rank) {
204: PetscInfo1(0,"Running command :%s\n",commandt);
205: if (!(fd = popen(commandt,mode))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot run command %s",commandt);
206: if (fp) *fp = fd;
207: }
208: return(0);
209: }
211: /*@C
212: PetscPOpenSetMachine - Sets the name of the default machine to run PetscPOpen() calls on
214: Logically Collective, but only process 0 runs the command
216: Input Parameter:
217: . machine - machine to run command on or NULL to remove previous entry
219: Options Database:
220: . -popen_machine <machine>
222: Level: intermediate
224: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpen()
226: @*/
227: PetscErrorCode PetscPOpenSetMachine(const char machine[])
228: {
232: if (machine) {
233: PetscStrcpy(PetscPOpenMachine,machine);
234: } else {
235: PetscPOpenMachine[0] = 0;
236: }
237: return(0);
238: }
240: #endif