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