|
|
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.