xref: /petsc/src/sys/fileio/mpiuopen.c (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
10039db0dSBarry Smith #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for popen() */
2e5c89e4eSSatish Balay /*
34c500f23SPierre Jolivet       Some PETSc utility routines to add simple parallel IO capabilities
4e5c89e4eSSatish Balay */
5c6db04a5SJed Brown #include <petscsys.h>
6e94e781bSJacob Faibussowitsch #include <petsc/private/logimpl.h>
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 
31d75a2efbSBarry Smith .seealso: PetscFClose(), PetscSynchronizedFGets(), PetscSynchronizedPrintf(), PetscSynchronizedFlush(),
32d75a2efbSBarry Smith           PetscFPrintf()
33e5c89e4eSSatish Balay @*/
347087cfbeSBarry Smith PetscErrorCode  PetscFOpen(MPI_Comm comm,const char name[],const char mode[],FILE **fp)
35e5c89e4eSSatish Balay {
36e5c89e4eSSatish Balay   PetscErrorCode ierr;
37e5c89e4eSSatish Balay   PetscMPIInt    rank;
38e5c89e4eSSatish Balay   FILE           *fd;
39e5c89e4eSSatish Balay   char           fname[PETSC_MAX_PATH_LEN],tname[PETSC_MAX_PATH_LEN];
40e5c89e4eSSatish Balay 
41e5c89e4eSSatish Balay   PetscFunctionBegin;
42ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
43dd400576SPatrick Sanan   if (rank == 0) {
44ace3abfcSBarry Smith     PetscBool isstdout,isstderr;
45e5c89e4eSSatish Balay     ierr = PetscStrcmp(name,"stdout",&isstdout);CHKERRQ(ierr);
46e5c89e4eSSatish Balay     ierr = PetscStrcmp(name,"stderr",&isstderr);CHKERRQ(ierr);
47a297a907SKarl Rupp     if (isstdout || !name) fd = PETSC_STDOUT;
48a297a907SKarl Rupp     else if (isstderr) fd = PETSC_STDERR;
49a297a907SKarl Rupp     else {
50b3f259d6SBarry Smith       PetscBool devnull;
51e5c89e4eSSatish Balay       ierr = PetscStrreplace(PETSC_COMM_SELF,name,tname,PETSC_MAX_PATH_LEN);CHKERRQ(ierr);
52e5c89e4eSSatish Balay       ierr = PetscFixFilename(tname,fname);CHKERRQ(ierr);
53b3f259d6SBarry Smith       ierr = PetscStrbeginswith(fname,"/dev/null",&devnull);CHKERRQ(ierr);
54b3f259d6SBarry Smith       if (devnull) {
55b3f259d6SBarry Smith         ierr = PetscStrcpy(fname,"/dev/null");CHKERRQ(ierr);
56b3f259d6SBarry Smith       }
577d3de750SJacob Faibussowitsch       ierr = PetscInfo(0,"Opening file %s\n",fname);CHKERRQ(ierr);
58e5c89e4eSSatish Balay       fd   = fopen(fname,mode);
59*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!fd,PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN,"Unable to open file %s",fname);
60e5c89e4eSSatish Balay     }
6102c9f0b5SLisandro Dalcin   } else fd = NULL;
62e5c89e4eSSatish Balay   *fp = fd;
63e5c89e4eSSatish Balay   PetscFunctionReturn(0);
64e5c89e4eSSatish Balay }
65e5c89e4eSSatish Balay 
66e8976759SBarry Smith /*@C
67e5c89e4eSSatish Balay     PetscFClose - Has the first processor in the communicator close a
68e5c89e4eSSatish Balay     file; all others do nothing.
69e5c89e4eSSatish Balay 
70d083f849SBarry Smith     Logically Collective
71e5c89e4eSSatish Balay 
72e5c89e4eSSatish Balay     Input Parameters:
73e5c89e4eSSatish Balay +   comm - the communicator
74e5c89e4eSSatish Balay -   fd - the file, opened with PetscFOpen()
75e5c89e4eSSatish Balay 
76e5c89e4eSSatish Balay    Level: developer
77e5c89e4eSSatish Balay 
78e5c89e4eSSatish Balay     Fortran Note:
79e5c89e4eSSatish Balay     This routine is not supported in Fortran.
80e5c89e4eSSatish Balay 
81e5c89e4eSSatish Balay .seealso: PetscFOpen()
82e5c89e4eSSatish Balay @*/
837087cfbeSBarry Smith PetscErrorCode  PetscFClose(MPI_Comm comm,FILE *fd)
84e5c89e4eSSatish Balay {
85e5c89e4eSSatish Balay   PetscErrorCode ierr;
86e5c89e4eSSatish Balay   PetscMPIInt    rank;
87ed9cf6e9SBarry Smith   int            err;
88e5c89e4eSSatish Balay 
89e5c89e4eSSatish Balay   PetscFunctionBegin;
90ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
91dd400576SPatrick Sanan   if (rank == 0 && fd != PETSC_STDOUT && fd != PETSC_STDERR) {
92ed9cf6e9SBarry Smith     err = fclose(fd);
93*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on file");
94ed9cf6e9SBarry Smith   }
95e5c89e4eSSatish Balay   PetscFunctionReturn(0);
96e5c89e4eSSatish Balay }
97e5c89e4eSSatish Balay 
98e5c89e4eSSatish Balay #if defined(PETSC_HAVE_POPEN)
9974ba8654SBarry Smith static char PetscPOpenMachine[128] = "";
100e5c89e4eSSatish Balay 
101e5c89e4eSSatish Balay /*@C
102e5c89e4eSSatish Balay       PetscPClose - Closes (ends) a program on processor zero run with PetscPOpen()
103e5c89e4eSSatish Balay 
104d083f849SBarry Smith      Collective, but only process 0 runs the command
105e5c89e4eSSatish Balay 
106e5c89e4eSSatish Balay    Input Parameters:
107e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
1080298fd71SBarry Smith -   fp - the file pointer where program input or output may be read or NULL if don't care
109e5c89e4eSSatish Balay 
110e5c89e4eSSatish Balay    Level: intermediate
111e5c89e4eSSatish Balay 
112e5c89e4eSSatish Balay    Notes:
113e5c89e4eSSatish Balay        Does not work under Windows
114e5c89e4eSSatish Balay 
115e5c89e4eSSatish Balay .seealso: PetscFOpen(), PetscFClose(), PetscPOpen()
116e5c89e4eSSatish Balay 
117e5c89e4eSSatish Balay @*/
118016831caSBarry Smith PetscErrorCode PetscPClose(MPI_Comm comm,FILE *fd)
119e5c89e4eSSatish Balay {
120e5c89e4eSSatish Balay   PetscErrorCode ierr;
121e5c89e4eSSatish Balay   PetscMPIInt    rank;
122e5c89e4eSSatish Balay 
123e5c89e4eSSatish Balay   PetscFunctionBegin;
124ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
125dd400576SPatrick Sanan   if (rank == 0) {
126e5c89e4eSSatish Balay     char buf[1024];
127a297a907SKarl Rupp     while (fgets(buf,1024,fd)) ; /* wait till it prints everything */
128016831caSBarry Smith     (void) pclose(fd);
129e5c89e4eSSatish Balay   }
130e5c89e4eSSatish Balay   PetscFunctionReturn(0);
131e5c89e4eSSatish Balay }
132e5c89e4eSSatish Balay 
133e5c89e4eSSatish Balay /*@C
134e5c89e4eSSatish Balay       PetscPOpen - Runs a program on processor zero and sends either its input or output to
135e5c89e4eSSatish Balay           a file.
136e5c89e4eSSatish Balay 
137d083f849SBarry Smith      Logically Collective, but only process 0 runs the command
138e5c89e4eSSatish Balay 
139e5c89e4eSSatish Balay    Input Parameters:
140e5c89e4eSSatish Balay +   comm - MPI communicator, only processor zero runs the program
1410298fd71SBarry Smith .   machine - machine to run command on or NULL, or string with 0 in first location
142e5c89e4eSSatish Balay .   program - name of program to run
143e5c89e4eSSatish Balay -   mode - either r or w
144e5c89e4eSSatish Balay 
145e5c89e4eSSatish Balay    Output Parameter:
1460298fd71SBarry Smith .   fp - the file pointer where program input or output may be read or NULL if don't care
147e5c89e4eSSatish Balay 
148e5c89e4eSSatish Balay    Level: intermediate
149e5c89e4eSSatish Balay 
150e5c89e4eSSatish Balay    Notes:
151e5c89e4eSSatish Balay        Use PetscPClose() to close the file pointer when you are finished with it
152e5c89e4eSSatish Balay        Does not work under Windows
153e5c89e4eSSatish Balay 
15474ba8654SBarry Smith        If machine is not provided will use the value set with PetsPOpenSetMachine() if that was provided, otherwise
15574ba8654SBarry Smith        will use the machine running node zero of the communicator
15674ba8654SBarry Smith 
157e5c89e4eSSatish Balay        The program string may contain ${DISPLAY}, ${HOMEDIRECTORY} or ${WORKINGDIRECTORY}; these
158a5b23f4aSJose E. Roman     will be replaced with relevant values.
159e5c89e4eSSatish Balay 
16074ba8654SBarry Smith .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpenSetMachine()
161e5c89e4eSSatish Balay 
162e5c89e4eSSatish Balay @*/
1637087cfbeSBarry Smith PetscErrorCode  PetscPOpen(MPI_Comm comm,const char machine[],const char program[],const char mode[],FILE **fp)
164e5c89e4eSSatish Balay {
165e5c89e4eSSatish Balay   PetscErrorCode ierr;
166e5c89e4eSSatish Balay   PetscMPIInt    rank;
167e5c89e4eSSatish Balay   size_t         i,len,cnt;
168e5c89e4eSSatish Balay   char           commandt[PETSC_MAX_PATH_LEN],command[PETSC_MAX_PATH_LEN];
169e5c89e4eSSatish Balay   FILE           *fd;
170e5c89e4eSSatish Balay 
171e5c89e4eSSatish Balay   PetscFunctionBegin;
172e5c89e4eSSatish Balay   /* all processors have to do the string manipulation because PetscStrreplace() is a collective operation */
17374ba8654SBarry Smith   if (PetscPOpenMachine[0] || (machine && machine[0])) {
174e5c89e4eSSatish Balay     ierr = PetscStrcpy(command,"ssh ");CHKERRQ(ierr);
17574ba8654SBarry Smith     if (PetscPOpenMachine[0]) {
17674ba8654SBarry Smith       ierr = PetscStrcat(command,PetscPOpenMachine);CHKERRQ(ierr);
17774ba8654SBarry Smith     } else {
178e5c89e4eSSatish Balay       ierr = PetscStrcat(command,machine);CHKERRQ(ierr);
17974ba8654SBarry Smith     }
180d5649816SBarry Smith     ierr = PetscStrcat(command," \" export DISPLAY=${DISPLAY}; ");CHKERRQ(ierr);
181e5c89e4eSSatish Balay     /*
182e5c89e4eSSatish Balay         Copy program into command but protect the " with a \ in front of it
183e5c89e4eSSatish Balay     */
184e5c89e4eSSatish Balay     ierr = PetscStrlen(command,&cnt);CHKERRQ(ierr);
185e5c89e4eSSatish Balay     ierr = PetscStrlen(program,&len);CHKERRQ(ierr);
186e5c89e4eSSatish Balay     for (i=0; i<len; i++) {
187a297a907SKarl Rupp       if (program[i] == '\"') command[cnt++] = '\\';
188e5c89e4eSSatish Balay       command[cnt++] = program[i];
189e5c89e4eSSatish Balay     }
190e5c89e4eSSatish Balay     command[cnt] = 0;
191a297a907SKarl Rupp 
192e5c89e4eSSatish Balay     ierr = PetscStrcat(command,"\"");CHKERRQ(ierr);
193e5c89e4eSSatish Balay   } else {
194e5c89e4eSSatish Balay     ierr = PetscStrcpy(command,program);CHKERRQ(ierr);
195e5c89e4eSSatish Balay   }
196e5c89e4eSSatish Balay 
197e5c89e4eSSatish Balay   ierr = PetscStrreplace(comm,command,commandt,1024);CHKERRQ(ierr);
198e5c89e4eSSatish Balay 
199ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
200dd400576SPatrick Sanan   if (rank == 0) {
2017d3de750SJacob Faibussowitsch     ierr = PetscInfo(NULL,"Running command :%s\n",commandt);CHKERRQ(ierr);
202*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!(fd = popen(commandt,mode)),PETSC_COMM_SELF,PETSC_ERR_LIB,"Cannot run command %s",commandt);
203e5c89e4eSSatish Balay     if (fp) *fp = fd;
204e5c89e4eSSatish Balay   }
205e5c89e4eSSatish Balay   PetscFunctionReturn(0);
206e5c89e4eSSatish Balay }
207e5c89e4eSSatish Balay 
20874ba8654SBarry Smith /*@C
20974ba8654SBarry Smith       PetscPOpenSetMachine - Sets the name of the default machine to run PetscPOpen() calls on
21074ba8654SBarry Smith 
211d083f849SBarry Smith      Logically Collective, but only process 0 runs the command
21274ba8654SBarry Smith 
21374ba8654SBarry Smith    Input Parameter:
21410699b91SBarry Smith .   machine - machine to run command on or NULL for the current machine
21574ba8654SBarry Smith 
21674ba8654SBarry Smith    Options Database:
21710699b91SBarry Smith .   -popen_machine <machine> - run the process on this machine
21874ba8654SBarry Smith 
21974ba8654SBarry Smith    Level: intermediate
22074ba8654SBarry Smith 
22174ba8654SBarry Smith .seealso: PetscFOpen(), PetscFClose(), PetscPClose(), PetscPOpen()
22274ba8654SBarry Smith @*/
22374ba8654SBarry Smith PetscErrorCode  PetscPOpenSetMachine(const char machine[])
22474ba8654SBarry Smith {
22574ba8654SBarry Smith   PetscErrorCode ierr;
22674ba8654SBarry Smith 
22774ba8654SBarry Smith   PetscFunctionBegin;
22874ba8654SBarry Smith   if (machine) {
22974ba8654SBarry Smith     ierr = PetscStrcpy(PetscPOpenMachine,machine);CHKERRQ(ierr);
23074ba8654SBarry Smith   } else {
23174ba8654SBarry Smith     PetscPOpenMachine[0] = 0;
23274ba8654SBarry Smith   }
23374ba8654SBarry Smith   PetscFunctionReturn(0);
23474ba8654SBarry Smith }
23574ba8654SBarry Smith 
236e5c89e4eSSatish Balay #endif
237