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:     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.

 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) {
 53:         PetscStrcpy(fname,"/dev/null");
 54:       }
 55:       PetscInfo(0,"Opening file %s\n",fname);
 56:       fd   = fopen(fname,mode);
 58:     }
 59:   } else fd = NULL;
 60:   *fp = fd;
 61:   return 0;
 62: }

 64: /*@C
 65:     PetscFClose - Has the first processor in the communicator close a
 66:     file; all others do nothing.

 68:     Logically Collective

 70:     Input Parameters:
 71: +   comm - the communicator
 72: -   fd - the file, opened with PetscFOpen()

 74:    Level: developer

 76:     Fortran Note:
 77:     This routine is not supported in Fortran.

 79: .seealso: PetscFOpen()
 80: @*/
 81: PetscErrorCode  PetscFClose(MPI_Comm comm,FILE *fd)
 82: {
 83:   PetscMPIInt    rank;
 84:   int            err;

 86:   MPI_Comm_rank(comm,&rank);
 87:   if (rank == 0 && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
 88:     err = fclose(fd);
 90:   }
 91:   return 0;
 92: }

 94: #if defined(PETSC_HAVE_POPEN)
 95: static char PetscPOpenMachine[128] = "";

 97: /*@C
 98:       PetscPClose - Closes (ends) a program on processor zero run with PetscPOpen()

100:      Collective, but only process 0 runs the command

102:    Input Parameters:
103: +   comm - MPI communicator, only processor zero runs the program
104: -   fp - the file pointer where program input or output may be read or NULL if don't care

106:    Level: intermediate

108:    Notes:
109:        Does not work under Windows

111: .seealso: PetscFOpen(), PetscFClose(), PetscPOpen()

113: @*/
114: PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd)
115: {
116:   PetscMPIInt    rank;

118:   MPI_Comm_rank(comm,&rank);
119:   if (rank == 0) {
120:     char buf[1024];
121:     while (fgets(buf,1024,fd)) ; /* wait till it prints everything */
122:     (void) pclose(fd);
123:   }
124:   return 0;
125: }

127: /*@C
128:       PetscPOpen - Runs a program on processor zero and sends either its input or output to
129:           a file.

131:      Logically Collective, but only process 0 runs the command

133:    Input Parameters:
134: +   comm - MPI communicator, only processor zero runs the program
135: .   machine - machine to run command on or NULL, or string with 0 in first location
136: .   program - name of program to run
137: -   mode - either r or w

139:    Output Parameter:
140: .   fp - the file pointer where program input or output may be read or NULL if don't care

142:    Level: intermediate

144:    Notes:
145:        Use PetscPClose() to close the file pointer when you are finished with it
146:        Does not work under Windows

148:        If machine is not provided will use the value set with PetsPOpenSetMachine() if that was provided, otherwise
149:        will use the machine running node zero of the communicator

151:        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
152:     will be replaced with relevant values.

154: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpenSetMachine()

156: @*/
157: PetscErrorCode  PetscPOpen(MPI_Comm comm,const char machine[],const char program[],const char mode[],FILE **fp)
158: {
159:   PetscMPIInt    rank;
160:   size_t         i,len,cnt;
161:   char           commandt[PETSC_MAX_PATH_LEN],command[PETSC_MAX_PATH_LEN];
162:   FILE           *fd;

164:   /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
165:   if (PetscPOpenMachine[0] || (machine && machine[0])) {
166:     PetscStrcpy(command,"ssh ");
167:     if (PetscPOpenMachine[0]) {
168:       PetscStrcat(command,PetscPOpenMachine);
169:     } else {
170:       PetscStrcat(command,machine);
171:     }
172:     PetscStrcat(command," \" export DISPLAY=${DISPLAY}; ");
173:     /*
174:         Copy program into command but protect the " with a \ in front of it
175:     */
176:     PetscStrlen(command,&cnt);
177:     PetscStrlen(program,&len);
178:     for (i=0; i<len; i++) {
179:       if (program[i] == '\"') command[cnt++] = '\\';
180:       command[cnt++] = program[i];
181:     }
182:     command[cnt] = 0;

184:     PetscStrcat(command,"\"");
185:   } else {
186:     PetscStrcpy(command,program);
187:   }

189:   PetscStrreplace(comm,command,commandt,1024);

191:   MPI_Comm_rank(comm,&rank);
192:   if (rank == 0) {
193:     PetscInfo(NULL,"Running command :%s\n",commandt);
195:     if (fp) *fp = fd;
196:   }
197:   return 0;
198: }

200: /*@C
201:       PetscPOpenSetMachine - Sets the name of the default machine to run PetscPOpen() calls on

203:      Logically Collective, but only process 0 runs the command

205:    Input Parameter:
206: .   machine - machine to run command on or NULL for the current machine

208:    Options Database:
209: .   -popen_machine <machine> - run the process on this machine

211:    Level: intermediate

213: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpen()
214: @*/
215: PetscErrorCode  PetscPOpenSetMachine(const char machine[])
216: {
217:   if (machine) {
218:     PetscStrcpy(PetscPOpenMachine,machine);
219:   } else {
220:     PetscPOpenMachine[0] = 0;
221:   }
222:   return 0;
223: }

225: #endif