1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.
   4:  *
   5:  * Redistribution and use in source and binary forms, with or without
   6:  * modification, are permitted provided that the following conditions
   7:  * are met:
   8:  * 1. Redistributions of source code must retain the above copyright
   9:  *    notice, this list of conditions and the following disclaimer.
  10:  * 2. Redistributions in binary form must reproduce the above copyright
  11:  *    notice, this list of conditions and the following disclaimer in the
  12:  *    documentation and/or other materials provided with the distribution.
  13:  * 3. All advertising materials mentioning features or use of this software
  14:  *    must display the following acknowledgement:
  15:  *	This product includes software developed by the University of
  16:  *	California, Berkeley and its contributors.
  17:  * 4. Neither the name of the University nor the names of its contributors
  18:  *    may be used to endorse or promote products derived from this software
  19:  *    without specific prior written permission.
  20:  *
  21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31:  * SUCH DAMAGE.
  32:  */
  33: 
  34: #if !defined(lint) && defined(DOSCCS)
  35: static char sccsid[] = "@(#)popen.c	5.16 (Berkeley) 4/1/91";
  36: #endif
  37: 
  38: #include "rcv.h"
  39: #include <sys/signal.h>
  40: #include <sys/wait.h>
  41: 
  42: #define READ 0
  43: #define WRITE 1
  44: static int *pid;
  45: 
  46: struct fp {
  47:     FILE *fp;
  48:     int pipe;
  49:     struct fp *link;
  50: };
  51: static struct fp *fp_head;
  52: 
  53: FILE *
  54: Fopen(file, mode)
  55:     char *file, *mode;
  56: {
  57:     FILE *fp;
  58: 
  59:     if ((fp = fopen(file, mode)) != NULL)
  60:         register_file(fp, 0);
  61:     return fp;
  62: }
  63: 
  64: FILE *
  65: Fdopen(fd, mode)
  66:     char *mode;
  67: {
  68:     FILE *fp;
  69: 
  70:     if ((fp = fdopen(fd, mode)) != NULL)
  71:         register_file(fp, 0);
  72:     return fp;
  73: }
  74: 
  75: Fclose(fp)
  76:     FILE *fp;
  77: {
  78:     unregister_file(fp);
  79:     return fclose(fp);
  80: }
  81: 
  82: FILE *
  83: Popen(cmd, mode)
  84:     char *cmd;
  85:     char *mode;
  86: {
  87:     int p[2];
  88:     int myside, hisside, fd0, fd1;
  89:     FILE *fp;
  90: 
  91:     if (pid == 0)
  92:         pid = (int *) malloc((unsigned) sizeof (int) * getdtablesize());
  93:     if (pipe(p) < 0)
  94:         return NULL;
  95:     if (*mode == 'r') {
  96:         myside = p[READ];
  97:         fd0 = -1;
  98:         hisside = fd1 = p[WRITE];
  99:     } else {
 100:         myside = p[WRITE];
 101:         hisside = fd0 = p[READ];
 102:         fd1 = -1;
 103:     }
 104:     if ((pid[myside] = start_command(cmd, 0L, fd0, fd1, NOSTR)) < 0) {
 105:         close(p[READ]);
 106:         close(p[WRITE]);
 107:         return NULL;
 108:     }
 109:     (void) close(hisside);
 110:     if ((fp = fdopen(myside, mode)) != NULL)
 111:         register_file(fp, 1);
 112:     return fp;
 113: }
 114: 
 115: Pclose(ptr)
 116:     FILE *ptr;
 117: {
 118:     int i;
 119:     long omask;
 120: 
 121:     i = fileno(ptr);
 122:     unregister_file(ptr);
 123:     (void) fclose(ptr);
 124:     omask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP));
 125:     i = wait_child(pid[i]);
 126:     sigsetmask(omask);
 127:     return i;
 128: }
 129: 
 130: close_all_files()
 131: {
 132: 
 133:     while (fp_head)
 134:         if (fp_head->pipe)
 135:             (void) Pclose(fp_head->fp);
 136:         else
 137:             (void) Fclose(fp_head->fp);
 138: }
 139: 
 140: register_file(fp, pipe)
 141:     FILE *fp;
 142: {
 143:     struct fp *fpp;
 144: 
 145:     if ((fpp = (struct fp *) malloc(sizeof *fpp)) == NULL)
 146:         panic("Out of memory");
 147:     fpp->fp = fp;
 148:     fpp->pipe = pipe;
 149:     fpp->link = fp_head;
 150:     fp_head = fpp;
 151: }
 152: 
 153: unregister_file(fp)
 154:     FILE *fp;
 155: {
 156:     struct fp **pp, *p;
 157: 
 158:     for (pp = &fp_head; p = *pp; pp = &p->link)
 159:         if (p->fp == fp) {
 160:             *pp = p->link;
 161:             free((char *) p);
 162:             return;
 163:         }
 164:     /* XXX
 165: 	 * Ignore this for now; there may still be uncaught
 166: 	 * duplicate closes.
 167: 	panic("Invalid file pointer");
 168: 	*/
 169: }
 170: 
 171: /*
 172:  * Run a command without a shell, with optional arguments and splicing
 173:  * of stdin and stdout.  The command name can be a sequence of words.
 174:  * Signals must be handled by the caller.
 175:  * "Mask" contains the signals to ignore in the new process.
 176:  * SIGINT is enabled unless it's in the mask.
 177:  */
 178: /*VARARGS4*/
 179: run_command(cmd, mask, infd, outfd, a0, a1, a2)
 180:     char *cmd;
 181:     long mask;
 182:     int infd, outfd;
 183:     char *a0, *a1, *a2;
 184: {
 185:     int pid;
 186: 
 187:     if ((pid = start_command(cmd, mask, infd, outfd, a0, a1, a2)) < 0)
 188:         return -1;
 189:     return wait_command(pid);
 190: }
 191: 
 192: /*VARARGS4*/
 193: start_command(cmd, mask, infd, outfd, a0, a1, a2)
 194:     char *cmd;
 195:     long mask;
 196:     int  infd, outfd;
 197:     char *a0, *a1, *a2;
 198: {
 199:     int pid;
 200: 
 201:     if ((pid = vfork()) < 0) {
 202:         perror("fork");
 203:         return -1;
 204:     }
 205:     if (pid == 0) {
 206:         char *argv[100];
 207:         int i = getrawlist(cmd, argv, sizeof argv / sizeof *argv);
 208: 
 209:         if ((argv[i++] = a0) != NOSTR &&
 210:             (argv[i++] = a1) != NOSTR &&
 211:             (argv[i++] = a2) != NOSTR)
 212:             argv[i] = NOSTR;
 213:         prepare_child(mask, infd, outfd);
 214:         execvp(argv[0], argv);
 215:         perror(argv[0]);
 216:         _exit(1);
 217:     }
 218:     return pid;
 219: }
 220: 
 221: prepare_child(mask, infd, outfd)
 222:     long mask;
 223:     int  infd, outfd;
 224: {
 225:     int i;
 226: 
 227:     if (infd >= 0)
 228:         dup2(infd, 0);
 229:     if (outfd >= 0)
 230:         dup2(outfd, 1);
 231:     for (i = getdtablesize(); --i > 2;)
 232:         close(i);
 233:     for (i = 1; i <= NSIG; i++)
 234:         if (mask & sigmask(i))
 235:             (void) signal(i, SIG_IGN);
 236:     if ((mask & sigmask(SIGINT)) == 0)
 237:         (void) signal(SIGINT, SIG_DFL);
 238:     (void) sigsetmask(0L);
 239: }
 240: 
 241: wait_command(pid)
 242:     int pid;
 243: {
 244: 
 245:     if (wait_child(pid) < 0) {
 246:         printf("Fatal error in process.\n");
 247:         return -1;
 248:     }
 249:     return 0;
 250: }
 251: 
 252: struct child {
 253:     int pid;
 254:     char done;
 255:     char free;
 256:     union wait status;
 257:     struct child *link;
 258: };
 259: static struct child *child;
 260: 
 261: struct child *
 262: findchild(pid)
 263:     int pid;
 264: {
 265:     register struct child **cpp;
 266: 
 267:     for (cpp = &child; *cpp != NULL && (*cpp)->pid != pid;
 268:          cpp = &(*cpp)->link)
 269:             ;
 270:     if (*cpp == NULL) {
 271:         *cpp = (struct child *) malloc(sizeof (struct child));
 272:         (*cpp)->pid = pid;
 273:         (*cpp)->done = (*cpp)->free = 0;
 274:         (*cpp)->link = NULL;
 275:     }
 276:     return *cpp;
 277: }
 278: 
 279: delchild(cp)
 280:     register struct child *cp;
 281: {
 282:     register struct child **cpp;
 283: 
 284:     for (cpp = &child; *cpp != cp; cpp = &(*cpp)->link)
 285:         ;
 286:     *cpp = cp->link;
 287:     free((char *) cp);
 288: }
 289: 
 290: void
 291: sigchild()
 292: {
 293:     int pid;
 294:     union wait status;
 295:     register struct child *cp;
 296: 
 297:     while ((pid =
 298:         wait3((int *)&status, WNOHANG, (struct rusage *)0)) > 0) {
 299:         cp = findchild(pid);
 300:         if (cp->free)
 301:             delchild(cp);
 302:         else {
 303:             cp->done = 1;
 304:             cp->status = status;
 305:         }
 306:     }
 307: }
 308: 
 309: union wait wait_status;
 310: 
 311: /*
 312:  * Wait for a specific child to die.
 313:  */
 314: wait_child(pid)
 315:     int pid;
 316: {
 317:     long mask = sigblock(sigmask(SIGCHLD));
 318:     register struct child *cp = findchild(pid);
 319: 
 320:     while (!cp->done)
 321:         sigpause(mask);
 322:     wait_status = cp->status;
 323:     delchild(cp);
 324:     sigsetmask(mask);
 325:     return wait_status.w_status ? -1 : 0;
 326: }
 327: 
 328: /*
 329:  * Mark a child as don't care.
 330:  */
 331: free_child(pid)
 332:     int pid;
 333: {
 334:     long mask = sigblock(sigmask(SIGCHLD));
 335:     register struct child *cp = findchild(pid);
 336: 
 337:     if (cp->done)
 338:         delchild(cp);
 339:     else
 340:         cp->free = 1;
 341:     sigsetmask(mask);
 342: }

Defined functions

Pclose defined in line 115; used 2 times
Popen defined in line 82; used 2 times
close_all_files defined in line 130; used 1 times
delchild defined in line 279; used 3 times
findchild defined in line 261; used 3 times
free_child defined in line 331; used 2 times
prepare_child defined in line 221; used 2 times
register_file defined in line 140; used 3 times
sigchild defined in line 290; used 2 times
start_command defined in line 193; used 4 times
unregister_file defined in line 153; used 2 times
wait_child defined in line 314; used 5 times
wait_command defined in line 241; used 1 times

Defined variables

child defined in line 259; used 2 times
fp_head defined in line 51; used 7 times
pid defined in line 44; used 30 times
sccsid defined in line 35; never used
wait_status defined in line 309; used 2 times

Defined struct's

child defined in line 252; used 22 times
fp defined in line 46; used 10 times

Defined macros

READ defined in line 42; used 3 times
WRITE defined in line 43; used 3 times
Last modified: 1993-02-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3410
Valid CSS Valid XHTML 1.0 Strict