1: /* popd.c - the POP server */ 2: 3: /* Author: Marshall T. Rose <MRose@UDel> (MTR) 4: Department of Computer Science and Information Sciences 5: University of Delaware 6: Newark, DE 19716 7: 302/451-1951 8: 9: Date: Sun Oct 28 16:23:26 1984 10: */ 11: 12: #include <errno.h> 13: #include <signal.h> 14: #include <stdio.h> 15: #include <strings.h> 16: #include <syslog.h> 17: #include <sys/types.h> 18: #include <sys/file.h> 19: #include <sys/ioctl.h> 20: #include <sys/socket.h> 21: #include <sys/time.h> 22: #include <sys/resource.h> 23: #include <sys/wait.h> 24: #include <netinet/in.h> 25: #include <netdb.h> 26: #include <arpa/inet.h> 27: 28: 29: #define NOTOK (-1) 30: #define OK 0 31: 32: #define NULLCP ((char *) 0) 33: #define NULLRP ((struct rusage *) 0) 34: 35: #define FAST /* fast start-up of BBoards */ 36: 37: /* */ 38: 39: extern int errno; 40: extern int sys_nerr; 41: extern char *sys_errlist[]; 42: extern char *sys_siglist[]; 43: 44: 45: int debug = 0; 46: static int nbits = ((sizeof (int)) * 8); 47: static int options = 0; 48: 49: 50: char *myname = "popd"; 51: char myhost[BUFSIZ]; 52: static char *myprotocol = "tcp"; 53: static char *myservice = "pop"; 54: 55: static struct sockaddr_in in_socket; 56: static struct sockaddr_in *isock = &in_socket; 57: 58: 59: int chldser (); 60: void padios (), padvise (); 61: 62: /* */ 63: 64: /* ARGSUSED */ 65: 66: main (argc, argv, envp) 67: int argc; 68: char **argv, 69: **envp; 70: { 71: int fd, 72: sd; 73: struct servent *sp; 74: struct sockaddr_in out_socket, 75: *osock = &out_socket; 76: 77: if ((sp = getservbyname (myservice, myprotocol)) == NULL) 78: padios (NULLCP, "%s/%s: unknown service", myprotocol, myservice); 79: isock -> sin_family = AF_INET; 80: isock -> sin_port = sp -> s_port; 81: isock -> sin_addr.s_addr = INADDR_ANY; 82: arginit (argv); 83: envinit (); 84: 85: #ifdef RESTART 86: for (;;) { 87: char reason[BUFSIZ]; 88: union wait status; 89: 90: switch (fork ()) { 91: case NOTOK: 92: sleep (5); 93: continue; 94: 95: case OK: 96: break; 97: 98: default: 99: sleep (60); 100: (void) wait3 (&status, 0, NULLRP); 101: if (WIFEXITED (status)) 102: (void) sprintf (reason, "exit=0%o", status.w_retcode); 103: else 104: if (WIFSIGNALED (status)) 105: (void) sprintf (reason, "signal=%s%s", 106: status.w_termsig < NSIG 107: ? sys_siglist[status.w_termsig] : "unknown", 108: status.w_coredump ? " (core dumped)" : NULL); 109: else 110: (void) strcpy (reason, "stopped(!!)"); 111: padvise (NULLCP, LOG_WARNING, "%s/%s server has terminated -- %s", 112: sp -> s_proto, sp -> s_name, reason); 113: continue; 114: } 115: break; 116: } 117: 118: closelog (); 119: openlog (myname, LOG_PID); 120: padvise (NULLCP, LOG_INFO, "restart"); 121: #endif RESTART 122: 123: /* */ 124: 125: if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK) 126: padios ("socket", "unable to create"); 127: if (options & SO_DEBUG) 128: if (setsockopt (sd, SOL_SOCKET, SO_DEBUG, NULL, 0) == NOTOK) 129: padvise ("SO_DEBUG", LOG_WARNING, "unable to set socket option"); 130: if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, NULL, 0) == NOTOK) 131: padvise ("SO_KEEPALIVE", LOG_WARNING, "unable to set socket option"); 132: if (bind (sd, (struct sockaddr *) isock, sizeof *isock) == NOTOK) 133: padios ("socket", "unable to bind"); 134: 135: (void) signal (SIGCHLD, chldser); 136: (void) listen (sd, SOMAXCONN); 137: #ifdef FAST 138: popinit (); 139: #endif FAST 140: for (;;) { 141: int i = sizeof *osock; 142: 143: if ((fd = accept (sd, (struct sockaddr *) osock, &i)) == NOTOK) { 144: if (errno != EINTR) 145: padvise ("socket", LOG_WARNING, 146: "unable to accept connection on"); 147: continue; 148: } 149: #ifdef FAST 150: popassert (); 151: #endif FAST 152: switch (fork ()) { 153: case OK: 154: (void) close (sd); 155: (void) signal (SIGCHLD, SIG_DFL); 156: server (fd, osock); 157: _exit (0); 158: 159: case NOTOK: 160: padvise ("socket", LOG_WARNING, 161: "no forks, so rejecting connection on"); 162: default: 163: (void) close (fd); 164: } 165: } 166: } 167: 168: /* */ 169: 170: static server (fd, sin) 171: int fd; 172: struct sockaddr_in *sin; 173: { 174: u_short port; 175: struct hostent *hp; 176: struct in_addr *addr; 177: 178: closelog (); 179: openlog (myname, LOG_PID); 180: port = ntohs (sin -> sin_port); 181: addr = &sin -> sin_addr; 182: hp = gethostbyaddr (addr, sizeof *addr, sin -> sin_family); 183: padvise (NULLCP, LOG_INFO, "servicing %s/%d", 184: hp ? hp -> h_name : inet_ntoa (*addr), port); 185: 186: (void) dup2 (fd, 0); 187: (void) close (fd); 188: (void) dup2 (0, 1); 189: 190: pop (0, 1, sin -> sin_family == AF_INET && port < IPPORT_RESERVED && hp, 191: hp ? hp -> h_name : NULLCP); 192: } 193: 194: /* */ 195: 196: static arginit (vec) 197: char **vec; 198: { 199: register char *ap; 200: struct hostent *hp; 201: 202: if (myname = rindex (*vec, '/')) 203: myname++; 204: if (myname == NULL || *myname == NULL) 205: myname = *vec; 206: 207: (void) gethostname (myhost, sizeof myhost); 208: if (hp = gethostbyname (myhost)) 209: (void) strcpy (myhost, hp -> h_name); 210: nbits = getdtablesize (); 211: 212: for (vec++; ap = *vec; vec++) { 213: if (*ap == '-') 214: switch (*++ap) { 215: case 'd': 216: options |= SO_DEBUG; 217: continue; 218: 219: case 'p': 220: if ((ap = *++vec) == NULL 221: || *ap == '-' 222: || (isock -> sin_port = atoi (ap)) <= 0) 223: padios (NULLCP, "usage: %s -p portno", myname); 224: isock -> sin_port = htons (isock -> sin_port); 225: continue; 226: 227: default: 228: padios (NULLCP, "-%s: unknown switch", ap); 229: } 230: 231: padios (NULLCP, "usage: %s [switches]", myname); 232: } 233: } 234: 235: /* */ 236: 237: static envinit () { 238: int i, 239: sd; 240: 241: if (!(debug = isatty (2))) { 242: for (i = 0; i < 5; i++) { 243: switch (fork ()) { 244: case NOTOK: 245: sleep (5); 246: continue; 247: 248: case OK: 249: break; 250: 251: default: 252: _exit (0); 253: } 254: break; 255: } 256: 257: (void) chdir ("/"); 258: 259: if ((sd = open ("/dev/null", O_RDWR)) == NOTOK) 260: padios ("/dev/null", "unable to read"); 261: if (sd != 0) 262: (void) dup2 (sd, 0), (void) close (sd); 263: (void) dup2 (0, 1); 264: (void) dup2 (0, 2); 265: 266: if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) { 267: (void) ioctl (sd, TIOCNOTTY, NULLCP); 268: (void) close (sd); 269: } 270: } 271: 272: for (sd = 3; sd < nbits; sd++) 273: (void) close (sd); 274: 275: (void) signal (SIGPIPE, SIG_IGN); 276: 277: openlog (myname, LOG_PID); 278: padvise (NULLCP, LOG_INFO, "starting"); 279: if (debug) 280: padvise (NULLCP, LOG_DEBUG, "options=0x%x port=%d", 281: options, ntohs (isock -> sin_port)); 282: } 283: 284: /* */ 285: 286: /* ARGSUSED */ 287: 288: static int chldser (sig, code, sc) 289: int sig; 290: long code; 291: struct sigcontext *sc; 292: { 293: union wait status; 294: 295: while (wait3 (&status, WNOHANG, NULLRP) > 0) 296: continue; 297: } 298: 299: /* */ 300: 301: /* VARARGS2 */ 302: 303: void padios (what, fmt, a, b, c, d, e, f, g, h, i, j) 304: char *what, 305: *fmt, 306: *a, 307: *b, 308: *c, 309: *d, 310: *e, 311: *f, 312: *g, 313: *h, 314: *i, 315: *j; 316: { 317: padvise (what, LOG_SALERT, fmt, a, b, c, d, e, f, g, h, i, j); 318: _exit (1); 319: } 320: 321: /* */ 322: 323: /* VARARGS3 */ 324: 325: void padvise (what, code, fmt, a, b, c, d, e, f, g, h, i, j) 326: char *what, 327: *fmt, 328: *a, 329: *b, 330: *c, 331: *d, 332: *e, 333: *f, 334: *g, 335: *h, 336: *i, 337: *j; 338: int code; 339: { 340: int eindex = errno; 341: char buffer[BUFSIZ]; 342: 343: (void) sprintf (buffer, fmt, a, b, c, d, e, f, g, h, i, j); 344: if (what) 345: if (eindex > 0 && eindex < sys_nerr) 346: syslog (code, "%s %s: %s", buffer, what, sys_errlist[eindex]); 347: else 348: syslog (code, "%s %s: Error %d", buffer, what, eindex); 349: else 350: syslog (code, "%s", buffer); 351: 352: if (debug) { 353: fprintf (stderr, "[%d] %s", code, buffer); 354: if (what) 355: (void) fputc (' ', stderr), perror (what); 356: else 357: (void) fputc ('\n', stderr); 358: (void) fflush (stderr); 359: } 360: 361: errno = eindex; 362: }