1 #ifndef lint
2 static char sccsid[] = "@(#)$Id: main.c,v 1.22 1994/11/17 16:40:42 sob Exp sob $";
3 #endif
4
5 /*
6 * Network News Transfer Protocol server
7 *
8 * Phil Lapsley
9 * University of California, Berkeley
10 * (Internet: phil@berkeley.edu; UUCP: ...!ucbvax!phil)
11 * Stan Barber
12 * Academ Consulting Services
13 * (Internet: sob@academ.com; UUCP: ...!academ!sob)
14 * Wayne Davison
15 * (Internet: davison@borland.com)
16 */
17
18 #include "common.h"
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #ifndef EXCELAN
22 #include <netdb.h>
23 #else
24 struct sockaddr_in current_peer = { AF_INET, IPPORT_NNTP };
25 #endif
26 #include <signal.h>
27 /* XXX Should be #ifdef VARARGS */
28 #ifndef USG
29 #ifdef sun
30 #include <varargs.h>
31 #endif
32 #endif
33 #ifdef hpux
34 #include <varargs.h>
35 #endif
36
37 #ifdef SETPROCTITLE
38 #ifndef HAVE_PROCTITLE
39 char **Argv = NULL; /* pointer to argument vector */
40 char *LastArgv = NULL; /* end of argv */
41 #endif
42 #endif /* SETPROCTITLE */
43
44 int
main(argc,argv,envp)45 main(argc,argv,envp)
46 int argc;
47 char **argv, **envp;
48 {
49
50 #ifdef ALONE /* If no inetd */
51
52 int sockt, client;
53 socklen_t length;
54 struct sockaddr from;
55 #ifdef LOAD
56 register int load;
57 #endif /* LOAD */
58
59 disassoc();
60
61 /* fd 0-2 should be open and point to / now. */
62
63 /* Let's close all the other FD's just to be sure */
64 for(sockt = 3; sockt < 40; sockt++)
65 (void) close(sockt);
66
67 #ifdef SYSLOG
68 #ifdef LOG_DAEMON
69 openlog("nntpd", LOG_PID, SYSLOG); /* fd 3 */
70 #else
71 openlog("nntpd", LOG_PID); /* fd 3 */
72 #endif
73 #endif /* SYSLOG */
74
75
76 #ifdef FASTFORK
77 num_groups = read_groups(); /* Read active file now (fd 4) */
78 /* and then do it every */
79 #if 0
80 set_timer(); /* so often later */
81 #endif
82 #endif /* FASTFORK */
83
84 #ifndef EXCELAN
85 sockt = get_socket(); /* should be fd 4 or 5 */
86 if ( getuid() == 0 ) { /* Running as root */
87
88 if (setgid((gid_t) NEWS_GID) == -1) {
89 #ifdef SYSLOG
90 syslog(LOG_ERR, "setgid: %m");
91 #endif
92 exit(1);
93 }
94
95 if (setuid((uid_t) NEWS_UID) == -1) {
96 #ifdef SYSLOG
97 syslog(LOG_ERR, "setuid: %m");
98 #endif
99 exit(1);
100 }
101 }
102 #ifdef USG
103 (void) signal(SIGCLD, SIG_IGN);
104 #else /* !USG */
105 (void) signal(SIGCHLD, reaper);
106 #endif /* USG */
107
108 #ifdef DEBUG
109 (void) signal(SIGUSR1, debugup);
110 (void) signal(SIGUSR2, debugdown);
111 #endif
112
113 if (listen(sockt, SOMAXCONN) < 0) {
114 #ifdef SYSLOG
115 syslog(LOG_ERR, "main: listen: %m");
116 #endif /* SYSLOG */
117 exit(1);
118 }
119 #endif /* EXCELAN */
120
121 #ifdef SETPROCTITLE
122 #ifndef HAVE_PROCTITLE
123 /*
124 * Save start and extent of argv for setproctitle.
125 */
126
127 Argv = argv;
128 #ifdef SDD
129 LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
130 #else /*SDD*/
131 while (*envp)
132 envp++;
133 LastArgv = envp[-1] + strlen(envp[-1]);
134 #endif /*SDD*/
135 #endif
136 #endif /* SETPROCTITLE */
137 #if defined(LOAD) && defined(SETPROCTITLE)
138 /* If LOAD and SETPROCTITLE, display load before first accept() */
139 load = getla();
140 setproctitle("%sing connections: loadav %d",
141 load > LOAD ? "reject" : "accept", load);
142 #endif /* LOAD && SETPROCTITLE */
143
144 for (;;) {
145 #ifdef LOAD
146 char oline[NNTP_STRLEN];
147 #endif /* LOAD */
148 #ifdef EXCELAN
149 int status;
150 sockt = 3;
151 sockt = get_socket();
152 if (sockt < 0)
153 continue;
154 #ifdef USG
155 (void) signal(SIGCLD, SIG_IGN);
156 #endif
157 bzero((char *)&from,sizeof(from));
158 client = accept(sockt, &from);
159 #else /* !EXCELAN */
160 length = sizeof (from);
161 client = accept(sockt, &from, &length);
162 #endif /* EXCELAN */
163 if (client < 0) {
164 #ifdef SYSLOG
165 #ifdef EXCELAN
166 if (errno != EINTR && errno != 60 )
167 #else /* !EXCELAN */
168 if (errno != EINTR)
169 #endif /* EXCELAN */
170 syslog(LOG_ERR, "accept: %m\n");
171 #endif /* SYSLOG */
172 #ifdef EXCELAN
173 close(sockt);
174 sleep(1);
175 #endif /* EXCELAN */
176 continue;
177 }
178
179 #ifdef LOAD
180 if (( load = getla()) > LOAD ) {
181 #ifdef SETPROCTITLE
182 setproctitle("rejecting connections: loadav %d", load);
183 #endif /* SETPROCTITLE */
184 sprintf( oline, "%d loadav at %d, try later\r\n",
185 ERR_GOODBYE, load );
186 write( client, oline, strlen( oline ));
187 #ifdef SYSLOG
188 syslog( LOG_INFO, "loadav at %d, sleeping", load );
189 #endif /* SYSLOG */
190 close( client );
191 sleep( 5 );
192 continue;
193 } else {
194 #ifdef SETPROCTITLE
195 setproctitle("accepting connections: loadav %d", load);
196 #endif /* SETPROCTITLE */
197 }
198 #endif /* LOAD */
199
200 switch (fork()) {
201 case -1:
202 #ifdef SYSLOG
203 syslog(LOG_ERR, "fork: %m\n");
204 #endif /* SYSLOG */
205 #ifdef EXCELAN
206 (void) close(sockt);
207 #endif /* EXCELAN */
208 (void) close(client);
209 break;
210
211 case 0:
212 #ifdef EXCELAN
213 if (fork())
214 exit(0);
215 bcopy(&from,¤t_peer,sizeof(from));
216 make_stdio(sockt);
217 #else /* !EXCELAN */
218 (void) close(sockt);
219 make_stdio(client);
220 #endif /* EXCELAN */
221 #ifdef USG
222 (void) signal(SIGCLD,SIG_DFL);
223 #endif /* USG */
224 serve();
225 break;
226
227 default:
228 #ifdef EXCELAN
229 (void) close(sockt);
230 #else /* !EXCELAN */
231 (void) close(client);
232 #endif /* EXCELAN */
233 break;
234 }
235 }
236
237 #else /* !ALONE */ /* We have inetd */
238
239 #ifdef LOAD
240 {
241 register int load;
242
243 #ifdef SYSLOG
244 #ifdef LOG_DAEMON
245 openlog("nntpd", LOG_PID, SYSLOG);
246 #else
247 openlog("nntpd", LOG_PID);
248 #endif
249 #endif /* SYSLOG */
250 if (( load = getla()) > LOAD ) {
251 printf("%d loadav at %d, try later\r\n",
252 ERR_GOODBYE, load );
253 (void) fflush(stdout);
254 #ifdef SYSLOG
255 syslog( LOG_INFO, "loadav at %d, exiting", load );
256 closelog();
257 #endif
258 exit(1);
259 }
260 #ifdef SYSLOG
261 closelog();
262 #endif
263 }
264 #endif /* LOAD */
265 #ifdef SETPROCTITLE
266 #ifndef HAVE_PROCTITLE
267 /*
268 * Save start and extent of argv for setproctitle.
269 */
270
271 Argv = argv;
272 #ifdef SDD
273 LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
274 #else /*SDD*/
275 while (*envp)
276 envp++;
277 LastArgv = envp[-1] + strlen(envp[-1]);
278 #endif /*SDD*/
279 #endif
280 #endif /* SETPROCTITLE */
281
282 #ifdef USG
283 (void) signal(SIGCLD,SIG_DFL);
284 #endif /* USG */
285
286 serve();
287
288 #endif /* ALONE */
289 }
290
291 /*
292 * clobber argv so ps will show what we're doing.
293 * stolen from sendmail
294 */
295 #ifdef SETPROCTITLE
296 #ifndef HAVE_PROCTITLE
297 #if defined(sun) || defined(hpux)
298 /*VARARGS*/
299 void
setproctitle(va_alist)300 setproctitle(va_alist)
301 va_dcl
302 {
303 register char *p, *fmt;
304 register int i;
305 char buf[BUFSIZ];
306 va_list ap;
307
308 va_start(ap);
309 fmt = va_arg(ap, char *);
310
311 (void) vsprintf(buf, fmt, ap);
312
313 /* make ps print "(nntpd)" */
314 p = Argv[0];
315 *p++ = '-';
316
317 i = strlen(buf);
318 if (i > LastArgv - p - 2) {
319 i = LastArgv - p - 2;
320 buf[i] = '\0';
321 }
322 strcpy(p, buf);
323 p += i;
324 while (p < LastArgv)
325 *p++ = ' ';
326
327 va_end(ap);
328 }
329 #else
330 /*VARARGS1*/
331 void
setproctitle(fmt,a,b,c)332 setproctitle(fmt, a, b, c)
333 char *fmt;
334 {
335 register char *p;
336 register int i;
337 char buf[BUFSIZ];
338
339 (void) sprintf(buf, fmt, a, b, c);
340
341 /* make ps print "(nntpd)" */
342 p = Argv[0];
343 *p++ = '-';
344
345 i = strlen(buf);
346 if (i > LastArgv - p - 2) {
347 i = LastArgv - p - 2;
348 buf[i] = '\0';
349 }
350 (void) strcpy(p, buf);
351 p += i;
352 while (p < LastArgv)
353 *p++ = ' ';
354 }
355 #endif /* hpux */
356 #endif
357 #endif /* SETPROCTITLE */
358