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