pfopen.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00029 #include "pfopen.h"
00030
00031 #include "dnxDebug.h"
00032
00033 #include <sys/types.h>
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <unistd.h>
00037 #include <string.h>
00038 #include <errno.h>
00039 #include <fcntl.h>
00040 #include <signal.h>
00041 #include <sys/wait.h>
00042 #include <assert.h>
00043
00044 #define elemcount(x) (sizeof(x)/sizeof(*(x)))
00045
00046
00047
00093 PFILE * pfopen(const char * cmdstring, const char * type)
00094 {
00095 PFILE * pfile;
00096 int pid, eno, i, pfd[6];
00097
00098
00099 assert((type[0] == 'r' || type[0] == 'w') && type[1] == 0);
00100
00101
00102 if ((pfile = (PFILE *)xcalloc(1, sizeof *pfile)) == 0)
00103 {
00104 errno = ENOMEM;
00105 return 0;
00106 }
00107
00108
00109 memset(pfd, -1, sizeof pfd);
00110 if (pipe(pfd) < 0 || pipe(pfd+2) < 0
00111 || (*type == 'w' && pipe(pfd+4) < 0))
00112 goto errout;
00113
00114
00115 if ((pfile->fp[0] = fdopen(pfd[0], "r")) == 0
00116 || (pfile->fp[1] = fdopen(pfd[2], "r")) == 0
00117 || (*type == 'w' && (pfile->fp[2] = fdopen(pfd[5], "w")) == 0))
00118 goto errout;
00119
00120
00121 if ((pid = fork()) < 0)
00122 goto errout;
00123
00124
00125 if (pid == 0)
00126 {
00127
00128 setpgid(0, 0);
00129
00130
00131 fclose(pfile->fp[0]);
00132 fclose(pfile->fp[1]);
00133 if (pfd[1] != STDOUT_FILENO)
00134 {
00135 dup2(pfd[1], STDOUT_FILENO);
00136 close(pfd[1]);
00137 }
00138 if (pfd[3] != STDERR_FILENO)
00139 {
00140 dup2(pfd[3], STDERR_FILENO);
00141 close(pfd[3]);
00142 }
00143
00144
00145 if (*type == 'w')
00146 {
00147
00148 fclose(pfile->fp[2]);
00149 if (pfd[4] != STDIN_FILENO)
00150 {
00151 dup2(pfd[4], STDIN_FILENO);
00152 close(pfd[4]);
00153 }
00154 }
00155
00156 execl("/bin/sh", "/bin/sh", "-c", cmdstring, (char *)0);
00157
00158 _exit(127);
00159 }
00160
00161
00162
00163
00164 close(pfd[1]);
00165 close(pfd[3]);
00166 if (*type == 'w')
00167 close(pfd[4]);
00168
00169
00170 pfile->pid = pid;
00171
00172 return pfile;
00173
00174 errout:
00175 eno = errno;
00176
00177
00178 if (pfile->fp[0] != 0)
00179 fclose(pfile->fp[0]), pfd[0] = -1;
00180 if (pfile->fp[1] != 0)
00181 fclose(pfile->fp[1]), pfd[2] = -1;
00182 if (pfile->fp[2] != 0)
00183 fclose(pfile->fp[2]), pfd[5] = -1;
00184
00185
00186 for (i = 0; i < elemcount(pfd); i++)
00187 if (pfd[i] >= 0)
00188 close(pfd[i]);
00189
00190 xfree(pfile);
00191 errno = eno;
00192 return 0;
00193 }
00194
00195
00196
00212 int pfclose(PFILE * pfile)
00213 {
00214 int stat;
00215
00216 if (pfile == 0)
00217 {
00218 errno = EINVAL;
00219 return -1;
00220 }
00221
00222 if (pfile->fp[0] != 0)
00223 fclose(pfile->fp[0]);
00224 if (pfile->fp[1] != 0)
00225 fclose(pfile->fp[1]);
00226 if (pfile->fp[2] != 0)
00227 fclose(pfile->fp[2]);
00228
00229 xfree(pfile);
00230
00231 while (waitpid(pfile->pid, &stat, 0) < 0)
00232 if (errno != EINTR)
00233 return -1;
00234
00235 return stat;
00236 }
00237
00238
00239
00247 int pfkill(PFILE * pfile, int sig)
00248 {
00249 assert(pfile);
00250
00251
00252 return kill(-(pfile->pid), sig);
00253 }
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 #ifdef PFOPEN_TEST
00271
00272 #include "utesthelp.h"
00273 #include "dnxError.h"
00274
00275
00276
00277
00278 char * program = "m4";
00279 char * text = "This is a test\n";
00280 char * errtext = "Terminated\n";
00281 int verbose;
00282
00283 int main(int argc, char ** argv)
00284 {
00285 PFILE * pf;
00286 FILE * fin, * fout, * ferr;
00287 char buf[128];
00288
00289 verbose = argc > 1 ? 1 : 0;
00290
00291 CHECK_NONZERO(pf = pfopen(program, "w"));
00292
00293 fin = PF_IN(pf);
00294 fout = PF_OUT(pf);
00295 ferr = PF_ERR(pf);
00296
00297 fprintf(fin, text);
00298 fflush(fin);
00299 close(fileno(fin));
00300
00301 fgets(buf, sizeof buf, fout);
00302
00303 CHECK_ZERO(strcmp(text, buf));
00304
00305 CHECK_ZERO(pfclose(pf));
00306
00307 #ifdef DEBUG_HEAP
00308 CHECK_ZERO(dnxCheckHeap());
00309 #endif
00310
00311 return 0;
00312 }
00313
00314 #endif
00315
00316
00317