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