# 2.11BSD#431 - /usr/src/ucb/Mail/popen.c

##### Functions

    Fclose            X
    Fdopen            X
    Fopen             X
    Pclose            X
    Popen             X
    close_all_files   X
    delchild          X
    findchild         X
    free_child        X
    prepare_child     X
    register_file     X
    run_command       X
    sigchild          X
    start_command     X
    unregister_file   X
    wait_child        X
    wait_command      X

##### Variables

    wait_status       X

##### Macros

    READ              X
    WRITE             X

##### struct's

    child             X
    fp                X

       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

Fclose defined in line 75; used 77 times

- in line 137
- in /usr/src/ucb/Mail/aux.c line 277, 302
- in /usr/src/ucb/Mail/cmd2.c line 193, 202
- in /usr/src/ucb/Mail/cmd3.c line 155
- in /usr/src/ucb/Mail/collect.c line 288-293(2), 332, 368, 422-426(2), 445, 474-479(2), 487, 619
- in /usr/src/ucb/Mail/edit.c line 125, 172, 178
- in /usr/src/ucb/Mail/fio.c line 216
- in /usr/src/ucb/Mail/lex.c line 80, 86, 95, 143, 649
- in /usr/src/ucb/Mail/names.c line 254, 266, 310, 319-320(2)
- in /usr/src/ucb/Mail/quit.c line 126, 174-178(2), 184, 202, 208-209(2), 216-230(7), 237, 246-248(3), 267, 273-277(3), 290, 306-314(4), 320, 351, 364-369(3), 413, 428, 436-437(2), 469, 477
- in /usr/src/ucb/Mail/send.c line 371, 390, 437, 455-461(4), 550

Fdopen defined in line 64; used 4 times

- in /usr/src/ucb/Mail/def.h line 275
- in /usr/src/ucb/Mail/edit.c line 155
- in /usr/src/ucb/Mail/fio.c line 68
- in /usr/src/ucb/Mail/names.c line 307

Fopen defined in line 53; used 35 times

- in /usr/src/ucb/Mail/aux.c line 271
- in /usr/src/ucb/Mail/cmd2.c line 184
- in /usr/src/ucb/Mail/cmd3.c line 149
- in /usr/src/ucb/Mail/collect.c line 105, 277, 326, 409, 464, 613
- in /usr/src/ucb/Mail/def.h line 274
- in /usr/src/ucb/Mail/edit.c line 210
- in /usr/src/ucb/Mail/lex.c line 71, 639
- in /usr/src/ucb/Mail/names.c line 244, 298
- in /usr/src/ucb/Mail/quit.c line 103, 110, 127, 156, 200-205(2), 213, 227, 235, 301, 337, 395, 421-426(2), 438, 448
- in /usr/src/ucb/Mail/send.c line 368, 431-435(2), 538

Pclose defined in line 115; used 2 times

- in line 135
- in /usr/src/ucb/Mail/cmd1.c line 330

Popen defined in line 82; used 2 times

- in /usr/src/ucb/Mail/cmd1.c line 308
- in /usr/src/ucb/Mail/def.h line 276

close_all_files defined in line 130; used 1 times

- in /usr/src/ucb/Mail/lex.c line 499

delchild defined in line 279; used 3 times

- in line 301, 323, 338

findchild defined in line 261; used 3 times

- in line 299, 318, 335

free_child defined in line 331; used 2 times

- in /usr/src/ucb/Mail/names.c line 295
- in /usr/src/ucb/Mail/send.c line 388

prepare_child defined in line 221; used 2 times

- in line 213
- in /usr/src/ucb/Mail/send.c line 374

register_file defined in line 140; used 3 times

- in line 60, 71, 111

run_command defined in line 179; used 5 times

- in /usr/src/ucb/Mail/cmd1.c line 438
- in /usr/src/ucb/Mail/cmd3.c line 62, 80
- in /usr/src/ucb/Mail/collect.c line 473
- in /usr/src/ucb/Mail/edit.c line 187

sigchild defined in line 290; used 2 times

- in /usr/src/ucb/Mail/main.c line 64, 71

start_command defined in line 193; used 4 times

- in line 104, 187
- in /usr/src/ucb/Mail/fio.c line 348
- in /usr/src/ucb/Mail/names.c line 288

unregister_file defined in line 153; used 2 times

- in line 78, 122

wait_child defined in line 314; used 5 times

- in line 125, 245
- in /usr/src/ucb/Mail/cmd2.c line 377
- in /usr/src/ucb/Mail/fio.c line 357
- in /usr/src/ucb/Mail/send.c line 386

wait_command defined in line 241; used 1 times

- in line 189

#### Defined variables

child defined in line 259; used 2 times

- in line 267, 284

fp_head defined in line 51; used 7 times

- in line 133-137(4), 149-150(2), 158

pid defined in line 44; used 30 times

- in line 91-92(2), 104, 125, 185-189(3), 199-205(3), 218, 241-245(3), 253, 262-272(6), 293-299(3), 314-318(3), 331-335(3)

sccsid defined in line 35; never used
wait_status defined in line 309; used 2 times

- in line 322-325(2)

#### Defined struct's

child defined in line 252; used 22 times

- in line 257-265(8), 271(4), 280-282(4), 295(2), 318(2), 335(2)

fp defined in line 46; used 10 times

- in line 49-51(4), 143-145(4), 156(2)

#### Defined macros

READ defined in line 42; used 3 times

- in line 96-105(3)

WRITE defined in line 43; used 3 times

- in line 98-100(2), 106

Last modified: 1993-02-14 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1283 |