Annotation of 43BSDReno/usr.bin/mail/popen.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.