Actual source code: mpiuopen.c

petsc-3.14.6 2021-03-30
Report Typos and Errors
  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:     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 = NULL;
 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(NULL,"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