1: #ifndef lint
   2: static  char    *sccsid = "@(#)spawn.c	1.6	(Berkeley) 2/6/88";
   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[NNTP_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: #ifdef USG
  58:     int     status;
  59: #else not USG
  60:     union wait  status;
  61: #endif not USG
  62:     register FILE   *fp;
  63: 
  64:     (void) strcpy(tempfile, "/tmp/rpostXXXXXX");
  65:     (void) mktemp(tempfile);
  66: 
  67:     fp = fopen(tempfile, "w");
  68:     if (fp == NULL) {
  69:         printf("%d Cannot create temporary file.\r\n", err_code);
  70:         (void) fflush(stdout);
  71:         return (0);
  72:     } else {
  73:         printf("%d Ok\r\n", cont_code);
  74:         (void) fflush(stdout);
  75:     }
  76: 
  77: #ifdef XFER_TIMEOUT
  78:     xfer_lines = old_xfer_lines = 0;
  79:     otimeout = signal(SIGALRM, xfer_timeout);
  80:     (void) alarm(XFER_TIMEOUT);
  81: #endif
  82: 
  83:     while (fgets(line, sizeof(line), stdin) != NULL) {
  84: #ifdef XFER_TIMEOUT
  85:         xfer_lines++;
  86: #endif
  87:         if ((cp = index(line, '\r')) != NULL)
  88:             *cp = '\0';
  89:         else if ((cp = index(line, '\n')) != NULL)
  90:             *cp = '\0';
  91: 
  92:         if (line[0] == '.' && line[1] == '\0')
  93:             break;
  94: 
  95:         if (line[0] == '.')
  96:             fputs(line+1, fp);
  97:         else
  98:             fputs(line, fp);
  99:         putc('\n', fp);
 100:     }
 101:     (void) fclose(fp);
 102: 
 103: #ifdef XFER_TIMEOUT
 104:     (void) alarm(0);
 105:     (void) signal(SIGALRM, otimeout);
 106: #endif
 107: 
 108:     /* See if the connection got closed somehow... */
 109: 
 110:     if (line[0] != '.' && line[1] != '\0') {
 111:         (void) unlink(tempfile);
 112: #ifdef SYSLOG
 113: # ifdef LOG
 114:         syslog(LOG_ERR, "%s spawn: EOF before period on line by itself",
 115:             hostname);
 116: # else
 117:         syslog(LOG_ERR, "spawn: EOF before period on line by itself");
 118: # endif
 119: #endif
 120:         return (0);
 121:     }
 122: 
 123: #ifdef POSTER
 124:     (void) chown(tempfile, uid_poster, gid_poster);
 125: #endif
 126: 
 127:     /* Set up a pipe so we can see errors from rnews */
 128: 
 129:     if (pipe(fds) < 0) {
 130: #ifdef SYSLOG
 131:         syslog(LOG_ERR, "spawn: pipe: %m");
 132: #endif
 133:         (void) unlink(tempfile);
 134:         return (-1);
 135:     }
 136: 
 137:     /*
 138: 	 * Ok, now we have the article in "tempfile".  We
 139: 	 * should be able to fork off, close fd's 0 to 31 (or
 140: 	 * whatever), open "tempfile" for input, thus making
 141: 	 * it stdin, and then execl the inews.  We think.
 142: 	 */
 143: 
 144:     pid = vfork();
 145:     if (pid == 0) {     /* We're in child */
 146: #ifdef POSTER
 147:         (void) setuid(uid_poster);
 148:         (void) setgid(gid_poster);
 149: #endif
 150: 
 151:         /* Set up stdout and stderr for child */
 152: 
 153:         if (fds[1] != 1) {
 154:             (void) dup2(fds[1], 1);
 155:             (void) close(fds[1]);
 156:         }
 157:         (void) dup2(1, 2);
 158: 
 159:         for (i = 3; i < 10; ++i) /* XXX but getdtablesize is too big */
 160:             (void) close(i);
 161: 
 162:         fd = open(tempfile, O_RDONLY);
 163:         if (fd != 0) {
 164:             (void) dup2(fd, 0);
 165:             (void) close(fd);
 166:         }
 167: 
 168:         execl(path, name, flag, (char *) NULL);
 169:         fprintf(stderr, "spawn: execl ");
 170:         perror(path);
 171:         _exit(-1);  /* Error */
 172:     } else {
 173:         (void) close(fds[1]);
 174:         fp = fdopen(fds[0], "r");
 175:         if (fp == NULL) {
 176:             printf("%d Cannot fdopen %s pipe\r\n", err_code, path);
 177:             (void) fflush(stdout);
 178: #ifdef SYSLOG
 179:             syslog(LOG_ERR, "spawn: pipe: %m");
 180: #endif
 181:             (void) unlink(tempfile);
 182:             return (0);
 183:         }
 184: 
 185:         if (errbuf)
 186:             *errbuf = '\0';
 187: 
 188:         while (fgets(line, sizeof (line), fp) != NULL) {
 189:             if (line[0] != '\n') {
 190:                 if (errbuf) {
 191:                     if (cp = index(line, '\n'))
 192:                         *cp = '\0';
 193:                     (void) strcat(errbuf, line);
 194:                     (void) strcat(errbuf, "\\");
 195:                 }
 196: #ifdef SYSLOG
 197:                 syslog(LOG_ERR, "%s: %s", path, line);
 198: #endif
 199:             }
 200:         }
 201: 
 202:         while ((npid = wait(&status)) > 0)
 203:             if (npid == pid) {
 204: #ifdef USG
 205:                 exit_status = (status >> 8) & 0xff;
 206: #else not USG
 207:                 exit_status = status.w_T.w_Retcode;
 208: #endif not USG
 209:                 break;
 210:             }
 211: 
 212:         (void) fclose(fp);
 213:         (void) unlink(tempfile);
 214:         (void) fflush(stdout);
 215:         if (npid < 0) {
 216: #ifdef SYSLOG
 217:             syslog(LOG_ERR, "spawn: wait pid %d: %m", pid);
 218: #endif
 219:             return (-1);
 220:         }
 221: 
 222: #ifdef SYSLOG
 223:         if (exit_status != 0)
 224:             syslog(LOG_ERR, "spawn: %s exit status %d",
 225:                 path, exit_status);
 226: #endif
 227: 
 228:         return (exit_status ? -1 : 1);
 229:     }
 230: }
 231: 
 232: #ifdef XFER_TIMEOUT
 233: 
 234: xfer_timeout()
 235: {
 236:     if (old_xfer_lines < xfer_lines) {
 237:         old_xfer_lines = xfer_lines;
 238:         (void) alarm(XFER_TIMEOUT);
 239:         return;
 240:     }
 241: 
 242:     /* Timed out. */
 243: 
 244:     printf("%d timeout after %d seconds, closing connection.\r\n",
 245:         ERR_FAULT, XFER_TIMEOUT);
 246:     fflush(stdout);
 247: 
 248: #ifdef LOG
 249:     syslog(LOG_ERR, "%s transfer_timeout", hostname);
 250: #endif LOG
 251: 
 252:     (void) unlink(tempfile);
 253: 
 254:     exit(1);
 255: }
 256: 
 257: #endif XFER_TIMEOUT

Defined functions

spawn defined in line 39; used 2 times
xfer_timeout defined in line 234; used 2 times

Defined variables

old_xfer_lines defined in line 13; used 3 times
sccsid defined in line 2; never used
tempfile defined in line 16; used 10 times
xfer_lines defined in line 12; used 4 times
Last modified: 1988-02-07
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3852
Valid CSS Valid XHTML 1.0 Strict