xref: /petsc/src/sys/fileio/mpiuopen.c (revision 4c500f23f41a3f3a0e9b2cac83fcce6b0e919e07)
10039db0dSBarry Smith #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for popen() */
2e5c89e4eSSatish Balay /*
3*4c500f23SPierre Jolivet       Some PETSc utility routines to add simple parallel IO capabilities
4e5c89e4eSSatish Balay */
5c6db04a5SJed Brown #include <petscsys.h>
6e5c89e4eSSatish Balay 
7d0286d30SJed Brown #include <errno.h>
8d0286d30SJed Brown 
9e5c89e4eSSatish Balay /*@C
10e5c89e4eSSatish Balay     PetscFOpen - Has the first process in the communicator open a file;
11e5c89e4eSSatish Balay     all others do nothing.
12e5c89e4eSSatish Balay 
13d083f849SBarry Smith     Logically Collective
14e5c89e4eSSatish Balay 
15e5c89e4eSSatish Balay     Input Parameters:
16e5c89e4eSSatish Balay +   comm - the communicator
17e5c89e4eSSatish Balay .   name - the filename
18e5c89e4eSSatish Balay -   mode - the mode for fopen(), usually "w"
19e5c89e4eSSatish Balay 
20e5c89e4eSSatish Balay     Output Parameter:
21e5c89e4eSSatish Balay .   fp - the file pointer
22e5c89e4eSSatish Balay 
23e5c89e4eSSatish Balay     Level: developer
24e5c89e4eSSatish Balay 
25e5c89e4eSSatish Balay     Notes:
260298fd71SBarry Smith        NULL (0), "stderr" or "stdout" may be passed in as the filename
27e5c89e4eSSatish Balay 
28e5c89e4eSSatish Balay     Fortran Note:
29e5c89e4eSSatish Balay     This routine is not supported in Fortran.
30e5c89e4eSSatish Balay 
31e5c89e4eSSatish Balay 
32d75a2efbSBarry Smith .seealso: PetscFClose(), PetscSynchronizedFGets(), PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
33d75a2efbSBarry Smith           PetscFPrintf()
34e5c89e4eSSatish Balay @*/
357087cfbeSBarry Smith PetscErrorCode  PetscFOpen(MPI_Comm comm,const char name[],const char mode[],FILE **fp)
36e5c89e4eSSatish Balay {
37e5c89e4eSSatish Balay   PetscErrorCode ierr;
38e5c89e4eSSatish Balay   PetscMPIInt    rank;
39e5c89e4eSSatish Balay   FILE           *fd;
40e5c89e4eSSatish Balay   char           fname[PETSC_MAX_PATH_LEN],tname[PETSC_MAX_PATH_LEN];
41e5c89e4eSSatish Balay 
42e5c89e4eSSatish Balay   PetscFunctionBegin;
43e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
44e5c89e4eSSatish Balay   if (!rank) {
45ace3abfcSBarry Smith     PetscBool isstdout,isstderr;
46e5c89e4eSSatish Balay     ierr = PetscStrcmp(name,"stdout",&isstdout);CHKERRQ(ierr);
47e5c89e4eSSatish Balay     ierr = PetscStrcmp(name,"stderr",&isstderr);CHKERRQ(ierr);
48a297a907SKarl Rupp     if (isstdout || !name) fd = PETSC_STDOUT;
49a297a907SKarl Rupp     else if (isstderr) fd = PETSC_STDERR;
50a297a907SKarl Rupp     else {
51b3f259d6SBarry Smith       PetscBool devnull;
52e5c89e4eSSatish Balay       ierr = PetscStrreplace(PETSC_COMM_SELF,name,tname,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
53e5c89e4eSSatish Balay       ierr = PetscFixFilename(tname,fname);CHKERRQ(ierr);
54b3f259d6SBarry Smith       ierr = PetscStrbeginswith(fname,"/dev/null",&devnull);CHKERRQ(ierr);
55b3f259d6SBarry Smith       if (devnull) {
56b3f259d6SBarry Smith         ierr = PetscStrcpy(fname,"/dev/null");CHKERRQ(ierr);
57b3f259d6SBarry Smith       }
58ae15b995SBarry Smith       ierr = PetscInfo1(0,"Opening file %s\n",fname);CHKERRQ(ierr);
59e5c89e4eSSatish Balay       fd   = fopen(fname,mode);
60e32f2f54SBarry Smith       if (!fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file %s\n",fname);
61e5c89e4eSSatish Balay     }
62e5c89e4eSSatish Balay   } else fd = 0;
63e5c89e4eSSatish Balay   *fp = fd;
64e5c89e4eSSatish Balay   PetscFunctionReturn(0);
65e5c89e4eSSatish Balay }
66e5c89e4eSSatish Balay 
67e8976759SBarry Smith /*@C
68e5c89e4eSSatish Balay     PetscFClose - Has the first processor in the communicator close a
69e5c89e4eSSatish Balay     file; all others do nothing.
70e5c89e4eSSatish Balay 
71d083f849SBarry Smith     Logically Collective
72e5c89e4eSSatish Balay 
73e5c89e4eSSatish Balay     Input Parameters:
74e5c89e4eSSatish Balay +   comm - the communicator
75e5c89e4eSSatish Balay -   fd - the file, opened with PetscFOpen()
76e5c89e4eSSatish Balay 
77e5c89e4eSSatish Balay    Level: developer
78e5c89e4eSSatish Balay 
79e5c89e4eSSatish Balay     Fortran Note:
80e5c89e4eSSatish Balay     This routine is not supported in Fortran.
81e5c89e4eSSatish Balay 
82e5c89e4eSSatish Balay 
83e5c89e4eSSatish Balay .seealso: PetscFOpen()
84e5c89e4eSSatish Balay @*/
857087cfbeSBarry Smith PetscErrorCode  PetscFClose(MPI_Comm comm,FILE *fd)
86e5c89e4eSSatish Balay {
87e5c89e4eSSatish Balay   PetscErrorCode ierr;
88e5c89e4eSSatish Balay   PetscMPIInt    rank;
89ed9cf6e9SBarry Smith   int            err;
90e5c89e4eSSatish Balay 
91e5c89e4eSSatish Balay   PetscFunctionBegin;
92e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
93ed9cf6e9SBarry Smith   if (!rank && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
94ed9cf6e9SBarry Smith     err = fclose(fd);
95e32f2f54SBarry Smith     if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
96ed9cf6e9SBarry Smith   }
97e5c89e4eSSatish Balay   PetscFunctionReturn(0);
98e5c89e4eSSatish Balay }
99e5c89e4eSSatish Balay 
100e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN)
10174ba8654SBarry Smith static char PetscPOpenMachine[128] = "";
102e5c89e4eSSatish Balay 
103e5c89e4eSSatish Balay /*@C
104e5c89e4eSSatish Balay       PetscPClose - Closes (ends) a program on processor zero run with PetscPOpen()
105e5c89e4eSSatish Balay 
106d083f849SBarry Smith      Collective, but only process 0 runs the command
107e5c89e4eSSatish Balay 
108e5c89e4eSSatish Balay    Input Parameters:
109e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
1100298fd71SBarry Smith -   fp - the file pointer where program input or output may be read or NULL if don't care
111e5c89e4eSSatish Balay 
112e5c89e4eSSatish Balay    Level: intermediate
113e5c89e4eSSatish Balay 
114e5c89e4eSSatish Balay    Notes:
115e5c89e4eSSatish Balay        Does not work under Windows
116e5c89e4eSSatish Balay 
117e5c89e4eSSatish Balay .seealso: PetscFOpen(), PetscFClose(), PetscPOpen()
118e5c89e4eSSatish Balay 
119e5c89e4eSSatish Balay @*/
120016831caSBarry Smith PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd)
121e5c89e4eSSatish Balay {
122e5c89e4eSSatish Balay   PetscErrorCode ierr;
123e5c89e4eSSatish Balay   PetscMPIInt    rank;
124e5c89e4eSSatish Balay 
125e5c89e4eSSatish Balay   PetscFunctionBegin;
126e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
127e5c89e4eSSatish Balay   if (!rank) {
128e5c89e4eSSatish Balay     char buf[1024];
129a297a907SKarl Rupp     while (fgets(buf,1024,fd)) ; /* wait till it prints everything */
130016831caSBarry Smith     (void) pclose(fd);
131e5c89e4eSSatish Balay   }
132e5c89e4eSSatish Balay   PetscFunctionReturn(0);
133e5c89e4eSSatish Balay }
134e5c89e4eSSatish Balay 
135e5c89e4eSSatish Balay 
136e5c89e4eSSatish Balay /*@C
137e5c89e4eSSatish Balay       PetscPOpen - Runs a program on processor zero and sends either its input or output to
138e5c89e4eSSatish Balay           a file.
139e5c89e4eSSatish Balay 
140d083f849SBarry Smith      Logically Collective, but only process 0 runs the command
141e5c89e4eSSatish Balay 
142e5c89e4eSSatish Balay    Input Parameters:
143e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
1440298fd71SBarry Smith .   machine - machine to run command on or NULL, or string with 0 in first location
145e5c89e4eSSatish Balay .   program - name of program to run
146e5c89e4eSSatish Balay -   mode - either r or w
147e5c89e4eSSatish Balay 
148e5c89e4eSSatish Balay    Output Parameter:
1490298fd71SBarry Smith .   fp - the file pointer where program input or output may be read or NULL if don't care
150e5c89e4eSSatish Balay 
151e5c89e4eSSatish Balay    Level: intermediate
152e5c89e4eSSatish Balay 
153e5c89e4eSSatish Balay    Notes:
154e5c89e4eSSatish Balay        Use PetscPClose() to close the file pointer when you are finished with it
155e5c89e4eSSatish Balay        Does not work under Windows
156e5c89e4eSSatish Balay 
15774ba8654SBarry Smith        If machine is not provided will use the value set with PetsPOpenSetMachine() if that was provided, otherwise
15874ba8654SBarry Smith        will use the machine running node zero of the communicator
15974ba8654SBarry Smith 
160e5c89e4eSSatish Balay        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
161e5c89e4eSSatish Balay     will be replaced with relevent values.
162e5c89e4eSSatish Balay 
16374ba8654SBarry Smith .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpenSetMachine()
164e5c89e4eSSatish Balay 
165e5c89e4eSSatish Balay @*/
1667087cfbeSBarry Smith PetscErrorCode  PetscPOpen(MPI_Comm comm,const char machine[],const char program[],const char mode[],FILE **fp)
167e5c89e4eSSatish Balay {
168e5c89e4eSSatish Balay   PetscErrorCode ierr;
169e5c89e4eSSatish Balay   PetscMPIInt    rank;
170e5c89e4eSSatish Balay   size_t         i,len,cnt;
171e5c89e4eSSatish Balay   char           commandt[PETSC_MAX_PATH_LEN],command[PETSC_MAX_PATH_LEN];
172e5c89e4eSSatish Balay   FILE           *fd;
173e5c89e4eSSatish Balay 
174e5c89e4eSSatish Balay   PetscFunctionBegin;
175e5c89e4eSSatish Balay   /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
17674ba8654SBarry Smith   if (PetscPOpenMachine[0] || (machine && machine[0])) {
177e5c89e4eSSatish Balay     ierr = PetscStrcpy(command,"ssh ");CHKERRQ(ierr);
17874ba8654SBarry Smith     if (PetscPOpenMachine[0]) {
17974ba8654SBarry Smith       ierr = PetscStrcat(command,PetscPOpenMachine);CHKERRQ(ierr);
18074ba8654SBarry Smith     } else {
181e5c89e4eSSatish Balay       ierr = PetscStrcat(command,machine);CHKERRQ(ierr);
18274ba8654SBarry Smith     }
183d5649816SBarry Smith     ierr = PetscStrcat(command," \" export DISPLAY=${DISPLAY}; ");CHKERRQ(ierr);
184e5c89e4eSSatish Balay     /*
185e5c89e4eSSatish Balay         Copy program into command but protect the " with a \ in front of it
186e5c89e4eSSatish Balay     */
187e5c89e4eSSatish Balay     ierr = PetscStrlen(command,&cnt);CHKERRQ(ierr);
188e5c89e4eSSatish Balay     ierr = PetscStrlen(program,&len);CHKERRQ(ierr);
189e5c89e4eSSatish Balay     for (i=0; i<len; i++) {
190a297a907SKarl Rupp       if (program[i] == '\"') command[cnt++] = '\\';
191e5c89e4eSSatish Balay       command[cnt++] = program[i];
192e5c89e4eSSatish Balay     }
193e5c89e4eSSatish Balay     command[cnt] = 0;
194a297a907SKarl Rupp 
195e5c89e4eSSatish Balay     ierr = PetscStrcat(command,"\"");CHKERRQ(ierr);
196e5c89e4eSSatish Balay   } else {
197e5c89e4eSSatish Balay     ierr = PetscStrcpy(command,program);CHKERRQ(ierr);
198e5c89e4eSSatish Balay   }
199e5c89e4eSSatish Balay 
200e5c89e4eSSatish Balay   ierr = PetscStrreplace(comm,command,commandt,1024);CHKERRQ(ierr);
201e5c89e4eSSatish Balay 
202e5c89e4eSSatish Balay   ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
203e5c89e4eSSatish Balay   if (!rank) {
204ae15b995SBarry Smith     ierr = PetscInfo1(0,"Running command :%s\n",commandt);CHKERRQ(ierr);
205f23aa3ddSBarry Smith     if (!(fd = popen(commandt,mode))) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot run command %s",commandt);
206e5c89e4eSSatish Balay     if (fp) *fp = fd;
207e5c89e4eSSatish Balay   }
208e5c89e4eSSatish Balay   PetscFunctionReturn(0);
209e5c89e4eSSatish Balay }
210e5c89e4eSSatish Balay 
21174ba8654SBarry Smith /*@C
21274ba8654SBarry Smith       PetscPOpenSetMachine - Sets the name of the default machine to run PetscPOpen() calls on
21374ba8654SBarry Smith 
214d083f849SBarry Smith      Logically Collective, but only process 0 runs the command
21574ba8654SBarry Smith 
21674ba8654SBarry Smith    Input Parameter:
21774ba8654SBarry Smith .   machine - machine to run command on or NULL to remove previous entry
21874ba8654SBarry Smith 
21974ba8654SBarry Smith    Options Database:
22074ba8654SBarry Smith .   -popen_machine <machine>
22174ba8654SBarry Smith 
22274ba8654SBarry Smith    Level: intermediate
22374ba8654SBarry Smith 
22474ba8654SBarry Smith .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpen()
22574ba8654SBarry Smith 
22674ba8654SBarry Smith @*/
22774ba8654SBarry Smith PetscErrorCode  PetscPOpenSetMachine(const char machine[])
22874ba8654SBarry Smith {
22974ba8654SBarry Smith   PetscErrorCode ierr;
23074ba8654SBarry Smith 
23174ba8654SBarry Smith   PetscFunctionBegin;
23274ba8654SBarry Smith   if (machine) {
23374ba8654SBarry Smith     ierr = PetscStrcpy(PetscPOpenMachine,machine);CHKERRQ(ierr);
23474ba8654SBarry Smith   } else {
23574ba8654SBarry Smith     PetscPOpenMachine[0] = 0;
23674ba8654SBarry Smith   }
23774ba8654SBarry Smith   PetscFunctionReturn(0);
23874ba8654SBarry Smith }
23974ba8654SBarry Smith 
240e5c89e4eSSatish Balay #endif
241