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