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,&current_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