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: {
37: PetscMPIInt rank;
38: FILE *fd;
39: char fname[PETSC_MAX_PATH_LEN],tname[PETSC_MAX_PATH_LEN];
42: MPI_Comm_rank(comm,&rank);
43: if (rank == 0) {
44: PetscBool isstdout,isstderr;
45: PetscStrcmp(name,"stdout",&isstdout);
46: PetscStrcmp(name,"stderr",&isstderr);
47: if (isstdout || !name) fd = PETSC_STDOUT;
48: else if (isstderr) fd = PETSC_STDERR;
49: else {
50: PetscBool devnull;
51: PetscStrreplace(PETSC_COMM_SELF,name,tname,PETSC_MAX_PATH_LEN);
52: PetscFixFilename(tname,fname);
53: PetscStrbeginswith(fname,"/dev/null",&devnull);
54: if (devnull) {
55: PetscStrcpy(fname,"/dev/null");
56: }
57: PetscInfo1(0,"Opening file %s\n",fname);
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: return(0);
64: }
66: /*@C
67: PetscFClose - Has the first processor in the communicator close a
68: file; all others do nothing.
70: Logically Collective
72: Input Parameters:
73: + comm - the communicator
74: - fd - the file, opened with PetscFOpen()
76: Level: developer
78: Fortran Note:
79: This routine is not supported in Fortran.
81: .seealso: PetscFOpen()
82: @*/
83: PetscErrorCode PetscFClose(MPI_Comm comm,FILE *fd)
84: {
86: PetscMPIInt rank;
87: int err;
90: MPI_Comm_rank(comm,&rank);
91: if (rank == 0 && 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: return(0);
96: }
98: #if defined(PETSC_HAVE_POPEN)
99: static char PetscPOpenMachine[128] = "";
101: /*@C
102: PetscPClose - Closes (ends) a program on processor zero run with PetscPOpen()
104: Collective, but only process 0 runs the command
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
110: Level: intermediate
112: Notes:
113: Does not work under Windows
115: .seealso: PetscFOpen(), PetscFClose(), PetscPOpen()
117: @*/
118: PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd)
119: {
121: PetscMPIInt rank;
124: MPI_Comm_rank(comm,&rank);
125: if (rank == 0) {
126: char buf[1024];
127: while (fgets(buf,1024,fd)) ; /* wait till it prints everything */
128: (void) pclose(fd);
129: }
130: return(0);
131: }
133: /*@C
134: PetscPOpen - Runs a program on processor zero and sends either its input or output to
135: a file.
137: Logically Collective, but only process 0 runs the command
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
145: Output Parameter:
146: . fp - the file pointer where program input or output may be read or NULL if don't care
148: Level: intermediate
150: Notes:
151: Use PetscPClose() to close the file pointer when you are finished with it
152: Does not work under Windows
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
157: The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
158: will be replaced with relevant values.
160: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpenSetMachine()
162: @*/
163: PetscErrorCode PetscPOpen(MPI_Comm comm,const char machine[],const char program[],const char mode[],FILE **fp)
164: {
166: PetscMPIInt rank;
167: size_t i,len,cnt;
168: char commandt[PETSC_MAX_PATH_LEN],command[PETSC_MAX_PATH_LEN];
169: FILE *fd;
172: /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
173: if (PetscPOpenMachine[0] || (machine && machine[0])) {
174: PetscStrcpy(command,"ssh ");
175: if (PetscPOpenMachine[0]) {
176: PetscStrcat(command,PetscPOpenMachine);
177: } else {
178: PetscStrcat(command,machine);
179: }
180: PetscStrcat(command," \" export DISPLAY=${DISPLAY}; ");
181: /*
182: Copy program into command but protect the " with a \ in front of it
183: */
184: PetscStrlen(command,&cnt);
185: PetscStrlen(program,&len);
186: for (i=0; i<len; i++) {
187: if (program[i] == '\"') command[cnt++] = '\\';
188: command[cnt++] = program[i];
189: }
190: command[cnt] = 0;
192: PetscStrcat(command,"\"");
193: } else {
194: PetscStrcpy(command,program);
195: }
197: PetscStrreplace(comm,command,commandt,1024);
199: MPI_Comm_rank(comm,&rank);
200: if (rank == 0) {
201: PetscInfo1(NULL,"Running command :%s\n",commandt);
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: return(0);
206: }
208: /*@C
209: PetscPOpenSetMachine - Sets the name of the default machine to run PetscPOpen() calls on
211: Logically Collective, but only process 0 runs the command
213: Input Parameter:
214: . machine - machine to run command on or NULL for the current machine
216: Options Database:
217: . -popen_machine <machine> - run the process on this machine
219: Level: intermediate
221: .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpen()
222: @*/
223: PetscErrorCode PetscPOpenSetMachine(const char machine[])
224: {
228: if (machine) {
229: PetscStrcpy(PetscPOpenMachine,machine);
230: } else {
231: PetscPOpenMachine[0] = 0;
232: }
233: return(0);
234: }
236: #endif