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