|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.