|
|
1.1 ! root 1: #ifndef lint ! 2: static char *sccsid = "@(#)serve.c 1.24 (Berkeley) 10/15/87"; ! 3: #endif ! 4: ! 5: /* ! 6: * Main server routine ! 7: */ ! 8: ! 9: #include "common.h" ! 10: #include <signal.h> ! 11: #include <sys/time.h> ! 12: ! 13: #ifdef LOG ! 14: #include <sys/resource.h> ! 15: #endif ! 16: ! 17: extern int ahbs(), group(), help(), ihave(); ! 18: extern int list(), newgroups(), newnews(), nextlast(), post(); ! 19: extern int slave(), stat(), xhdr(); ! 20: ! 21: static struct cmdent { ! 22: char *cmd_name; ! 23: int (*cmd_fctn)(); ! 24: } cmdtbl[] = { ! 25: "article", ahbs, ! 26: "body", ahbs, ! 27: "group", group, ! 28: "head", ahbs, ! 29: "help", help, ! 30: "ihave", ihave, ! 31: "last", nextlast, ! 32: "list", list, ! 33: "newgroups", newgroups, ! 34: "newnews", newnews, ! 35: "next", nextlast, ! 36: "post", post, ! 37: "slave", slave, ! 38: "stat", ahbs, ! 39: #ifdef XHDR ! 40: "xhdr", xhdr, ! 41: #endif XHDR ! 42: }; ! 43: #define NUMCMDS (sizeof(cmdtbl) / sizeof(struct cmdent)) ! 44: ! 45: ! 46: /* ! 47: * serve -- given a connection on stdin/stdout, serve ! 48: * a client, executing commands until the client ! 49: * says goodbye. ! 50: * ! 51: * Parameters: None. ! 52: * ! 53: * Returns: Exits. ! 54: * ! 55: * Side effects: Talks to client, does a lot of ! 56: * stuff. ! 57: */ ! 58: ! 59: serve() ! 60: { ! 61: char line[MAX_STRLEN]; ! 62: char host[MAX_STRLEN]; ! 63: char gdbuf[MAX_STRLEN]; ! 64: char **argp; ! 65: char *timeptr, *cp; ! 66: int argnum, i; ! 67: struct timeval clock, now; ! 68: extern char *ctime(); ! 69: #ifdef POSTER ! 70: struct passwd *pp; ! 71: #endif ! 72: #ifdef TIMEOUT ! 73: void timeout(); ! 74: #endif ! 75: #ifdef LOG ! 76: struct rusage me, children; ! 77: ! 78: grps_acsd = arts_acsd = 0; ! 79: #endif ! 80: ! 81: /* Not all systems pass fd's 1 and 2 from inetd ... */ ! 82: ! 83: (void) close(1); ! 84: (void) close(2); ! 85: (void) dup(0); ! 86: (void) dup(0); ! 87: ! 88: /* If we're ALONE, then we've already opened syslog */ ! 89: ! 90: #ifndef ALONE ! 91: # ifdef SYSLOG ! 92: # ifdef BSD_42 ! 93: openlog("nntpd", LOG_PID); ! 94: # else ! 95: openlog("nntpd", LOG_PID, SYSLOG); ! 96: # endif ! 97: # endif ! 98: #endif ! 99: ! 100: #ifdef ALONE ! 101: (void) signal(SIGCHLD, SIG_IGN); ! 102: #endif ! 103: ! 104: /* Ignore SIGPIPE, since we'll see closed connections with read */ ! 105: ! 106: (void) signal(SIGPIPE, SIG_IGN); ! 107: ! 108: /* Get permissions and see if we can talk to this client */ ! 109: ! 110: host_access(&canread, &canpost, &canxfer, gdbuf); ! 111: ! 112: if (gethostname(host, sizeof(host)) < 0) ! 113: (void) strcpy(host, "Amnesiac"); ! 114: ! 115: if (!canread && !canxfer) { ! 116: printf("%d %s NNTP server can't talk to you. Goodbye.\r\n", ! 117: ERR_ACCESS, host); ! 118: (void) fflush(stdout); ! 119: #ifdef LOG ! 120: syslog(LOG_INFO, "%s refused connection", hostname); ! 121: #endif ! 122: exit(1); ! 123: } ! 124: ! 125: /* If we can talk, proceed with initialization */ ! 126: ! 127: ngpermcount = get_nglist(&ngpermlist, gdbuf); ! 128: ! 129: #ifdef POSTER ! 130: pp = getpwnam(POSTER); ! 131: if (pp != NULL) { ! 132: uid_poster = pp->pw_uid; ! 133: gid_poster = pp->pw_gid; ! 134: } else ! 135: #endif ! 136: uid_poster = gid_poster = 0; ! 137: ! 138: #ifndef FASTFORK ! 139: num_groups = 0; ! 140: num_groups = read_groups(); /* Read in the active file */ ! 141: #else ! 142: signal(SIGALRM, SIG_IGN); /* Children don't deal with */ ! 143: /* these things */ ! 144: #endif ! 145: ! 146: art_fp = NULL; ! 147: argp = (char **) NULL; /* for first time */ ! 148: ! 149: (void) gettimeofday(&clock, (struct timezone *)NULL); ! 150: timeptr = ctime(&clock.tv_sec); ! 151: if ((cp = index(timeptr, '\n')) != NULL) ! 152: *cp = '\0'; ! 153: else ! 154: timeptr = "Unknown date"; ! 155: ! 156: printf("%d %s NNTP server version %s ready at %s (%s).\r\n", ! 157: canpost ? OK_CANPOST : OK_NOPOST, ! 158: host, nntp_version, ! 159: timeptr, ! 160: canpost ? "posting ok" : "no posting"); ! 161: (void) fflush(stdout); ! 162: ! 163: /* ! 164: * Now get commands one at a time and execute the ! 165: * appropriate routine to deal with them. ! 166: */ ! 167: ! 168: #ifdef TIMEOUT ! 169: (void) signal(SIGALRM, timeout); ! 170: (void) alarm(TIMEOUT); ! 171: #endif TIMEOUT ! 172: ! 173: while (fgets(line, sizeof(line), stdin) != NULL) { ! 174: #ifdef TIMEOUT ! 175: (void) alarm(0); ! 176: #endif TIMEOUT ! 177: ! 178: cp = index(line, '\r'); /* Zap CR-LF */ ! 179: if (cp != NULL) ! 180: *cp = '\0'; ! 181: else { ! 182: cp = index(line, '\n'); ! 183: if (cp != NULL) ! 184: *cp = '\0'; ! 185: } ! 186: ! 187: if ((argnum = parsit(line, &argp)) == 0) ! 188: continue; /* Null command */ ! 189: else { ! 190: for (i = 0; i < NUMCMDS; ++i) ! 191: if (streql(cmdtbl[i].cmd_name, argp[0])) ! 192: break; ! 193: if (i < NUMCMDS) ! 194: (*cmdtbl[i].cmd_fctn)(argnum, argp); ! 195: else { ! 196: if (streql(argp[0], "quit")) ! 197: break; ! 198: #ifdef LOG ! 199: syslog(LOG_INFO, "%s unrecognized %s", ! 200: hostname, ! 201: line); ! 202: #endif ! 203: printf("%d Command unrecognized.\r\n", ! 204: ERR_COMMAND); ! 205: (void) fflush(stdout); ! 206: } ! 207: } ! 208: #ifdef TIMEOUT ! 209: (void) alarm(TIMEOUT); ! 210: #endif TIMEOUT ! 211: } ! 212: ! 213: printf("%d %s closing connection. Goodbye.\r\n", OK_GOODBYE, host); ! 214: (void) fflush(stdout); ! 215: ! 216: ! 217: #ifdef LOG ! 218: if (ferror(stdout)) ! 219: syslog(LOG_ERR, "%s disconnect: %m", hostname); ! 220: ! 221: if (getrusage(RUSAGE_SELF, &me) < 0) { ! 222: syslog(LOG_ERR, "getrusage RUSAGE_SELF: %m"); ! 223: if (grps_acsd) ! 224: syslog(LOG_INFO, "%s exit %d articles %d groups", ! 225: hostname, arts_acsd, grps_acsd); ! 226: exit(1); ! 227: } ! 228: if (getrusage(RUSAGE_CHILDREN, &children) < 0) { ! 229: syslog(LOG_ERR, "getrusage RUSAGE_CHILDREN: %m"); ! 230: if (grps_acsd) ! 231: syslog(LOG_INFO, "%s exit %d articles %d groups", ! 232: hostname, arts_acsd, grps_acsd); ! 233: exit(1); ! 234: } ! 235: if (grps_acsd) ! 236: syslog(LOG_INFO, "%s exit %d articles %d groups", ! 237: hostname, arts_acsd, grps_acsd); ! 238: if (nn_told) ! 239: syslog(LOG_INFO, "%s newnews_stats told %d took %d", ! 240: hostname, nn_told, nn_took); ! 241: if (ih_accepted || ih_rejected || ih_failed) ! 242: syslog(LOG_INFO, ! 243: "%s ihave_stats accepted %d rejected %d failed %d", ! 244: hostname, ! 245: ih_accepted, ! 246: ih_rejected, ! 247: ih_failed); ! 248: (void) gettimeofday(&now, (struct timezone *)NULL); ! 249: (void) sprintf(line, "user %.1f system %.1f elapsed %.1f", ! 250: (float) me.ru_utime.tv_sec + ! 251: (float) me.ru_utime.tv_usec/1000000.0 + ! 252: (float) children.ru_utime.tv_sec + ! 253: (float) children.ru_utime.tv_usec/1000000.0, ! 254: (float) me.ru_stime.tv_sec + ! 255: (float) me.ru_stime.tv_usec/1000000.0 + ! 256: (float) children.ru_stime.tv_sec + ! 257: (float) children.ru_stime.tv_usec/1000000.0, ! 258: (float) (now.tv_sec - clock.tv_sec) + ! 259: (float) now.tv_usec/1000000.0 - ! 260: (float) clock.tv_usec/1000000.0); ! 261: ! 262: syslog(LOG_INFO, "%s times %s", hostname, line); ! 263: #endif ! 264: ! 265: #ifdef PROFILE ! 266: profile(); ! 267: #endif ! 268: ! 269: exit(0); ! 270: } ! 271: ! 272: ! 273: #ifdef TIMEOUT ! 274: /* ! 275: * No activity for TIMEOUT seconds, so print an error message ! 276: * and close the connection. ! 277: */ ! 278: ! 279: void ! 280: timeout() ! 281: { ! 282: printf("%d Timeout after %d seconds, closing connection.\r\n", ! 283: ERR_FAULT, TIMEOUT); ! 284: (void) fflush(stdout); ! 285: ! 286: #ifdef LOG ! 287: syslog(LOG_ERR, "%s timeout", hostname); ! 288: #endif LOG ! 289: ! 290: exit(1); ! 291: } ! 292: #endif TIMEOUT
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.