Annotation of 43BSDTahoe/new/nntp/server/spawn.c, revision 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.