Annotation of 43BSDTahoe/new/nntp/server/spawn.c, revision 1.1.1.1

1.1       root        1: #ifndef lint
                      2: static char    *sccsid = "@(#)spawn.c  1.1     (Berkeley) 10/15/87";
                      3: #endif
                      4: 
                      5: #include "../common/conf.h"
                      6: 
                      7: #include "common.h"
                      8: 
                      9: #include <signal.h>
                     10: 
                     11: #ifdef XFER_TIMEOUT
                     12: static int     xfer_lines;
                     13: static int     old_xfer_lines;
                     14: #endif
                     15: 
                     16: static char    tempfile[256];
                     17: 
                     18: /*
                     19:  * spawn -- create a child process with the input from the client
                     20:  * as stdin.
                     21:  *
                     22:  *     Parameters:     "path" is the path of the program to invoke.
                     23:  *                     "name" is the name to call the program.
                     24:  *                     "flag" is a single flag to be passed to the program.
                     25:  *                     "cont_code" is the response code to transmit
                     26:  *                     on successful startup.
                     27:  *                     "err_code" is the response code to transmit when
                     28:  *                     something goes wrong.
                     29:  *
                     30:  *     Returns:        -1 on non-zero return from child,
                     31:  *                     0 on error before fork/exec,
                     32:  *                     1 otherwise.
                     33:  *
                     34:  *     Side effects:   Creates and removes temporary file;
                     35:  *                     accepts input from client; forks and execs.
                     36:  *                     Can time out if XFER_TIMEOUT is defined.
                     37:  */
                     38: 
                     39: spawn(path, name, flag, cont_code, err_code, errbuf)
                     40:        char            *path;
                     41:        char            *name;
                     42:        char            *flag;
                     43:        int             cont_code;
                     44:        int             err_code;
                     45:        char            *errbuf;
                     46: {
                     47:        char            line[MAX_STRLEN];
                     48:        register char   *cp;
                     49:        int             i, fd;
                     50:        int             fds[2];
                     51:        int             pid, npid;
                     52:        int             exit_status;
                     53: #ifdef XFER_TIMEOUT
                     54:        int             xfer_timeout();
                     55:        int             (*otimeout)();
                     56: #endif
                     57:        union wait      status;
                     58:        register FILE   *fp;
                     59: 
                     60:        (void) strcpy(tempfile, "/tmp/rpostXXXXXX");
                     61:        (void) mktemp(tempfile);
                     62: 
                     63:        fp = fopen(tempfile, "w");
                     64:        if (fp == NULL) {
                     65:                printf("%d Cannot create temporary file.\r\n", err_code);
                     66:                (void) fflush(stdout);
                     67:                return (0);
                     68:        } else {
                     69:                printf("%d Enter news, period on a line by itself to end.\r\n",
                     70:                        cont_code);
                     71:                (void) fflush(stdout);
                     72:        }
                     73: 
                     74: #ifdef XFER_TIMEOUT
                     75:        xfer_lines = old_xfer_lines = 0;
                     76:        otimeout = signal(SIGALRM, xfer_timeout);
                     77:        (void) alarm(XFER_TIMEOUT);
                     78: #endif
                     79: 
                     80:        while (fgets(line, sizeof(line), stdin) != NULL) {
                     81: #ifdef XFER_TIMEOUT
                     82:                xfer_lines++;
                     83: #endif
                     84:                if ((cp = index(line, '\r')) != NULL)
                     85:                        *cp = '\0';
                     86:                else if ((cp = index(line, '\n')) != NULL)
                     87:                        *cp = '\0';
                     88: 
                     89:                if (line[0] == '.' && line[1] == '\0')
                     90:                        break;
                     91: 
                     92:                if (line[0] == '.')
                     93:                        fputs(line+1, fp);
                     94:                else
                     95:                        fputs(line, fp);
                     96:                putc('\n', fp);
                     97:        }
                     98:        (void) fclose(fp);
                     99: 
                    100: #ifdef XFER_TIMEOUT
                    101:        (void) alarm(0);
                    102:        (void) signal(SIGALRM, otimeout);
                    103: #endif
                    104: 
                    105:        /* See if the connection got closed somehow... */
                    106: 
                    107:        if (line[0] != '.' && line[1] != '\0') {
                    108:                (void) unlink(tempfile);
                    109: #ifdef SYSLOG
                    110: # ifdef LOG
                    111:                syslog(LOG_ERR, "%s spawn: EOF before period on line by itself",
                    112:                        hostname);
                    113: # else
                    114:                syslog(LOG_ERR, "spawn: EOF before period on line by itself");
                    115: # endif
                    116: #endif
                    117:                return (0);
                    118:        }
                    119:                
                    120: #ifdef POSTER
                    121:        (void) chown(tempfile, uid_poster, gid_poster);
                    122: #endif
                    123: 
                    124:        /* Set up a pipe so we can see errors from rnews */
                    125: 
                    126:        if (pipe(fds) < 0) {
                    127: #ifdef SYSLOG
                    128:                syslog(LOG_ERR, "spawn: pipe: %m");
                    129: #endif
                    130:                (void) unlink(tempfile);
                    131:                return (-1);
                    132:        }
                    133: 
                    134:        /*
                    135:         * Ok, now we have the article in "tempfile".  We
                    136:         * should be able to fork off, close fd's 0 to 31 (or
                    137:         * whatever), open "tempfile" for input, thus making
                    138:         * it stdin, and then execl the inews.  We think.
                    139:         */
                    140: 
                    141:        pid = vfork();
                    142:        if (pid == 0) {         /* We're in child */
                    143: #ifdef POSTER
                    144:                (void) setuid(uid_poster);
                    145:                (void) setgid(gid_poster);
                    146: #endif
                    147: 
                    148:                /* Set up stdout and stderr for child */
                    149: 
                    150:                if (fds[1] != 1) {
                    151:                        (void) dup2(fds[1], 1);
                    152:                        (void) close(fds[1]);
                    153:                }
                    154:                (void) dup2(1, 2);
                    155: 
                    156:                for (i = 3; i < 10; ++i) /* XXX but getdtablesize is too big */
                    157:                        (void) close(i);
                    158: 
                    159:                fd = open(tempfile, O_RDONLY);
                    160:                if (fd != 0) {
                    161:                        (void) dup2(fd, 0);
                    162:                        (void) close(fd);
                    163:                }
                    164: 
                    165:                execl(path, name, flag, (char *) NULL);
                    166:                fprintf(stderr, "spawn: execl ");
                    167:                perror(path);
                    168:                _exit(-1);      /* Error */
                    169:        } else {
                    170:                (void) close(fds[1]);
                    171:                fp = fdopen(fds[0], "r");
                    172:                if (fp == NULL) {
                    173:                        printf("%d Cannot fdopen %s pipe\r\n", err_code, path);
                    174:                        (void) fflush(stdout);
                    175: #ifdef SYSLOG
                    176:                        syslog(LOG_ERR, "spawn: pipe: %m");
                    177: #endif
                    178:                        (void) unlink(tempfile);
                    179:                        return (0);
                    180:                }
                    181: 
                    182:                if (errbuf)
                    183:                        *errbuf = '\0';
                    184: 
                    185:                while (fgets(line, sizeof (line), fp) != NULL) {
                    186:                        if (line[0] != '\n') {
                    187:                                if (errbuf) {
                    188:                                        if (cp = index(line, '\n'))
                    189:                                                *cp = '\0';
                    190:                                        (void) strcat(errbuf, line);
                    191:                                        (void) strcat(errbuf, "\\");
                    192:                                }
                    193: #ifdef SYSLOG
                    194:                                syslog(LOG_ERR, "%s: %s", path, line);
                    195: #endif
                    196:                        }
                    197:                }
                    198: 
                    199:                while ((npid = wait(&status)) > 0)
                    200:                        if (npid == pid) {
                    201:                                exit_status = status.w_T.w_Retcode;
                    202:                                break;
                    203:                        }
                    204: 
                    205:                (void) fclose(fp);
                    206:                (void) unlink(tempfile);
                    207:                (void) fflush(stdout);
                    208:                if (npid < 0) {
                    209: #ifdef SYSLOG
                    210:                        syslog(LOG_ERR, "spawn: wait pid %d: %m", pid);
                    211: #endif
                    212:                        return (-1);
                    213:                }
                    214: 
                    215: #ifdef SYSLOG
                    216:                if (exit_status != 0)
                    217:                        syslog(LOG_ERR, "spawn: %s exit status %d",
                    218:                                path, exit_status);
                    219: #endif
                    220:                        
                    221:                return (exit_status ? -1 : 1);
                    222:        }
                    223: }
                    224: 
                    225: #ifdef XFER_TIMEOUT
                    226: 
                    227: xfer_timeout()
                    228: {
                    229:        if (old_xfer_lines < xfer_lines) {
                    230:                old_xfer_lines = xfer_lines;
                    231:                (void) alarm(XFER_TIMEOUT);
                    232:                return;
                    233:        }
                    234: 
                    235:        /* Timed out. */
                    236: 
                    237:        printf("%d timeout after %d seconds, closing connection.\r\n",
                    238:                ERR_FAULT, XFER_TIMEOUT);
                    239:        fflush(stdout);
                    240: 
                    241: #ifdef LOG
                    242:        syslog(LOG_ERR, "%s transfer_timeout", hostname);
                    243: #endif LOG
                    244: 
                    245:        (void) unlink(tempfile);
                    246: 
                    247:        exit(1);
                    248: }
                    249: 
                    250: #endif XFER_TIMEOUT

unix.superglobalmegacorp.com

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