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> 8 9 /*@C 10 PetscFOpen - Has the first process in the communicator open a file; 11 all others do nothing. 12 13 Logically Collective 14 15 Input Parameters: 16 + comm - the communicator 17 . name - the filename 18 - mode - the mode for fopen(), usually "w" 19 20 Output Parameter: 21 . fp - the file pointer 22 23 Level: developer 24 25 Notes: 26 NULL (0), "stderr" or "stdout" may be passed in as the filename 27 28 Fortran Note: 29 This routine is not supported in Fortran. 30 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 PetscErrorCode ierr; 37 PetscMPIInt rank; 38 FILE *fd; 39 char fname[PETSC_MAX_PATH_LEN],tname[PETSC_MAX_PATH_LEN]; 40 41 PetscFunctionBegin; 42 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 43 if (!rank) { 44 PetscBool isstdout,isstderr; 45 ierr = PetscStrcmp(name,"stdout",&isstdout);CHKERRQ(ierr); 46 ierr = PetscStrcmp(name,"stderr",&isstderr);CHKERRQ(ierr); 47 if (isstdout || !name) fd = PETSC_STDOUT; 48 else if (isstderr) fd = PETSC_STDERR; 49 else { 50 PetscBool devnull; 51 ierr = PetscStrreplace(PETSC_COMM_SELF,name,tname,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 52 ierr = PetscFixFilename(tname,fname);CHKERRQ(ierr); 53 ierr = PetscStrbeginswith(fname,"/dev/null",&devnull);CHKERRQ(ierr); 54 if (devnull) { 55 ierr = PetscStrcpy(fname,"/dev/null");CHKERRQ(ierr); 56 } 57 ierr = PetscInfo1(0,"Opening file %s\n",fname);CHKERRQ(ierr); 58 fd = fopen(fname,mode); 59 if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file %s\n",fname); 60 } 61 } else fd = NULL; 62 *fp = fd; 63 PetscFunctionReturn(0); 64 } 65 66 /*@C 67 PetscFClose - Has the first processor in the communicator close a 68 file; all others do nothing. 69 70 Logically Collective 71 72 Input Parameters: 73 + comm - the communicator 74 - fd - the file, opened with PetscFOpen() 75 76 Level: developer 77 78 Fortran Note: 79 This routine is not supported in Fortran. 80 81 .seealso: PetscFOpen() 82 @*/ 83 PetscErrorCode PetscFClose(MPI_Comm comm,FILE *fd) 84 { 85 PetscErrorCode ierr; 86 PetscMPIInt rank; 87 int err; 88 89 PetscFunctionBegin; 90 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 91 if (!rank && fd != PETSC_STDOUT && fd != PETSC_STDERR) { 92 err = fclose(fd); 93 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file"); 94 } 95 PetscFunctionReturn(0); 96 } 97 98 #if defined(PETSC_HAVE_POPEN) 99 static char PetscPOpenMachine[128] = ""; 100 101 /*@C 102 PetscPClose - Closes (ends) a program on processor zero run with PetscPOpen() 103 104 Collective, but only process 0 runs the command 105 106 Input Parameters: 107 + comm - MPI communicator, only processor zero runs the program 108 - fp - the file pointer where program input or output may be read or NULL if don't care 109 110 Level: intermediate 111 112 Notes: 113 Does not work under Windows 114 115 .seealso: PetscFOpen(), PetscFClose(), PetscPOpen() 116 117 @*/ 118 PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd) 119 { 120 PetscErrorCode ierr; 121 PetscMPIInt rank; 122 123 PetscFunctionBegin; 124 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 125 if (!rank) { 126 char buf[1024]; 127 while (fgets(buf,1024,fd)) ; /* wait till it prints everything */ 128 (void) pclose(fd); 129 } 130 PetscFunctionReturn(0); 131 } 132 133 /*@C 134 PetscPOpen - Runs a program on processor zero and sends either its input or output to 135 a file. 136 137 Logically Collective, but only process 0 runs the command 138 139 Input Parameters: 140 + comm - MPI communicator, only processor zero runs the program 141 . machine - machine to run command on or NULL, or string with 0 in first location 142 . program - name of program to run 143 - mode - either r or w 144 145 Output Parameter: 146 . fp - the file pointer where program input or output may be read or NULL if don't care 147 148 Level: intermediate 149 150 Notes: 151 Use PetscPClose() to close the file pointer when you are finished with it 152 Does not work under Windows 153 154 If machine is not provided will use the value set with PetsPOpenSetMachine() if that was provided, otherwise 155 will use the machine running node zero of the communicator 156 157 The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these 158 will be replaced with relevent values. 159 160 .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpenSetMachine() 161 162 @*/ 163 PetscErrorCode PetscPOpen(MPI_Comm comm,const char machine[],const char program[],const char mode[],FILE **fp) 164 { 165 PetscErrorCode ierr; 166 PetscMPIInt rank; 167 size_t i,len,cnt; 168 char commandt[PETSC_MAX_PATH_LEN],command[PETSC_MAX_PATH_LEN]; 169 FILE *fd; 170 171 PetscFunctionBegin; 172 /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */ 173 if (PetscPOpenMachine[0] || (machine && machine[0])) { 174 ierr = PetscStrcpy(command,"ssh ");CHKERRQ(ierr); 175 if (PetscPOpenMachine[0]) { 176 ierr = PetscStrcat(command,PetscPOpenMachine);CHKERRQ(ierr); 177 } else { 178 ierr = PetscStrcat(command,machine);CHKERRQ(ierr); 179 } 180 ierr = PetscStrcat(command," \" export DISPLAY=${DISPLAY}; ");CHKERRQ(ierr); 181 /* 182 Copy program into command but protect the " with a \ in front of it 183 */ 184 ierr = PetscStrlen(command,&cnt);CHKERRQ(ierr); 185 ierr = PetscStrlen(program,&len);CHKERRQ(ierr); 186 for (i=0; i<len; i++) { 187 if (program[i] == '\"') command[cnt++] = '\\'; 188 command[cnt++] = program[i]; 189 } 190 command[cnt] = 0; 191 192 ierr = PetscStrcat(command,"\"");CHKERRQ(ierr); 193 } else { 194 ierr = PetscStrcpy(command,program);CHKERRQ(ierr); 195 } 196 197 ierr = PetscStrreplace(comm,command,commandt,1024);CHKERRQ(ierr); 198 199 ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr); 200 if (!rank) { 201 ierr = PetscInfo1(NULL,"Running command :%s\n",commandt);CHKERRQ(ierr); 202 if (!(fd = popen(commandt,mode))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot run command %s",commandt); 203 if (fp) *fp = fd; 204 } 205 PetscFunctionReturn(0); 206 } 207 208 /*@C 209 PetscPOpenSetMachine - Sets the name of the default machine to run PetscPOpen() calls on 210 211 Logically Collective, but only process 0 runs the command 212 213 Input Parameter: 214 . machine - machine to run command on or NULL for the current machine 215 216 Options Database: 217 . -popen_machine <machine> - run the process on this machine 218 219 Level: intermediate 220 221 .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpen() 222 @*/ 223 PetscErrorCode PetscPOpenSetMachine(const char machine[]) 224 { 225 PetscErrorCode ierr; 226 227 PetscFunctionBegin; 228 if (machine) { 229 ierr = PetscStrcpy(PetscPOpenMachine,machine);CHKERRQ(ierr); 230 } else { 231 PetscPOpenMachine[0] = 0; 232 } 233 PetscFunctionReturn(0); 234 } 235 236 #endif 237