Actual source code: mpiuopen.c
petsc-3.10.5 2019-03-28
Report Typos and Errors

      1: #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for popen() */
      2: /*
      3:       Some PETSc utilites routines to add simple parallel IO capability
      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 on MPI_Comm

     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:     Concepts: opening ASCII file
     32:     Concepts: files^opening ASCII

     34: .seealso: PetscFClose(), PetscSynchronizedFGets(), PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
     35:           PetscFPrintf()
     36: @*/
     37: PetscErrorCode  PetscFOpen(MPI_Comm comm,const char name[],const char mode[],FILE **fp)
     38: {
     40:   PetscMPIInt    rank;
     41:   FILE           *fd;
     42:   char           fname[PETSC_MAX_PATH_LEN],tname[PETSC_MAX_PATH_LEN];

     45:   MPI_Comm_rank(comm,&rank);
     46:   if (!rank) {
     47:     PetscBool isstdout,isstderr;
     48:     PetscStrcmp(name,"stdout",&isstdout);
     49:     PetscStrcmp(name,"stderr",&isstderr);
     50:     if (isstdout || !name) fd = PETSC_STDOUT;
     51:     else if (isstderr) fd = PETSC_STDERR;
     52:     else {
     53:       PetscBool devnull;
     54:       PetscStrreplace(PETSC_COMM_SELF,name,tname,PETSC_MAX_PATH_LEN);
     55:       PetscFixFilename(tname,fname);
     56:       PetscStrbeginswith(fname,"/dev/null",&devnull);
     57:       if (devnull) {
     58:         PetscStrcpy(fname,"/dev/null");
     59:       }
     60:       PetscInfo1(0,"Opening file %s\n",fname);
     61:       fd   = fopen(fname,mode);
     62:       if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file %s\n",fname);
     63:     }
     64:   } else fd = 0;
     65:   *fp = fd;
     66:   return(0);
     67: }

     69: /*@C
     70:     PetscFClose - Has the first processor in the communicator close a
     71:     file; all others do nothing.

     73:     Logically Collective on MPI_Comm

     75:     Input Parameters:
     76: +   comm - the communicator
     77: -   fd - the file, opened with PetscFOpen()

     79:    Level: developer

     81:     Fortran Note:
     82:     This routine is not supported in Fortran.

     84:     Concepts: files^closing ASCII
     85:     Concepts: closing file

     87: .seealso: PetscFOpen()
     88: @*/
     89: PetscErrorCode  PetscFClose(MPI_Comm comm,FILE *fd)
     90: {
     92:   PetscMPIInt    rank;
     93:   int            err;

     96:   MPI_Comm_rank(comm,&rank);
     97:   if (!rank && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
     98:     err = fclose(fd);
     99:     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
    100:   }
    101:   return(0);
    102: }

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

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

    110:      Collective on MPI_Comm, but only process 0 runs the command

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

    116:    Level: intermediate

    118:    Notes:
    119:        Does not work under Windows

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

    123: @*/
    124: PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd)
    125: {
    127:   PetscMPIInt    rank;

    130:   MPI_Comm_rank(comm,&rank);
    131:   if (!rank) {
    132:     char buf[1024];
    133:     while (fgets(buf,1024,fd)) ; /* wait till it prints everything */
    134:     (void) pclose(fd);
    135:   }
    136:   return(0);
    137: }

    140: /*@C
    141:       PetscPOpen - Runs a program on processor zero and sends either its input or output to
    142:           a file.

    144:      Logically Collective on MPI_Comm, but only process 0 runs the command

    146:    Input Parameters:
    147: +   comm - MPI communicator, only processor zero runs the program
    148: .   machine - machine to run command on or NULL, or string with 0 in first location
    149: .   program - name of program to run
    150: -   mode - either r or w

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

    155:    Level: intermediate

    157:    Notes:
    158:        Use PetscPClose() to close the file pointer when you are finished with it
    159:        Does not work under Windows

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

    164:        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
    165:     will be replaced with relevent values.

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

    169: @*/
    170: PetscErrorCode  PetscPOpen(MPI_Comm comm,const char machine[],const char program[],const char mode[],FILE **fp)
    171: {
    173:   PetscMPIInt    rank;
    174:   size_t         i,len,cnt;
    175:   char           commandt[PETSC_MAX_PATH_LEN],command[PETSC_MAX_PATH_LEN];
    176:   FILE           *fd;

    179:   /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
    180:   if (PetscPOpenMachine[0] || (machine && machine[0])) {
    181:     PetscStrcpy(command,"ssh ");
    182:     if (PetscPOpenMachine[0]) {
    183:       PetscStrcat(command,PetscPOpenMachine);
    184:     } else {
    185:       PetscStrcat(command,machine);
    186:     }
    187:     PetscStrcat(command," \" export DISPLAY=${DISPLAY}; ");
    188:     /*
    189:         Copy program into command but protect the " with a \ in front of it
    190:     */
    191:     PetscStrlen(command,&cnt);
    192:     PetscStrlen(program,&len);
    193:     for (i=0; i<len; i++) {
    194:       if (program[i] == '\"') command[cnt++] = '\\';
    195:       command[cnt++] = program[i];
    196:     }
    197:     command[cnt] = 0;

    199:     PetscStrcat(command,"\"");
    200:   } else {
    201:     PetscStrcpy(command,program);
    202:   }

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

    206:   MPI_Comm_rank(comm,&rank);
    207:   if (!rank) {
    208:     PetscInfo1(0,"Running command :%s\n",commandt);
    209:     if (!(fd = popen(commandt,mode))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot run command %s",commandt);
    210:     if (fp) *fp = fd;
    211:   }
    212:   return(0);
    213: }

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

    218:      Logically Collective on MPI_Comm, but only process 0 runs the command

    220:    Input Parameter:
    221: .   machine - machine to run command on or NULL to remove previous entry

    223:    Options Database:
    224: .   -popen_machine <machine>

    226:    Level: intermediate

    228: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpen()

    230: @*/
    231: PetscErrorCode  PetscPOpenSetMachine(const char machine[])
    232: {

    236:   if (machine) {
    237:     PetscStrcpy(PetscPOpenMachine,machine);
    238:   } else {
    239:     PetscPOpenMachine[0] = 0;
    240:   }
    241:   return(0);
    242: }

    244: #endif