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