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