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