]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/support/pop/popd.c
aliasbr.c: Remove duplicate prototypes. Others in aliasbr.h.
[nmh] / docs / historical / mh-6.8.5 / support / pop / popd.c
1 /* popd.c - the POP server */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: popd.c,v 1.16 1993/08/25 17:23:05 jromine Exp $";
4 #endif /* lint */
5
6 /* Author: Marshall T. Rose <MRose@UDel> (MTR)
7 Department of Computer Science and Information Sciences
8 University of Delaware
9 Newark, DE 19716
10 302/451-1951
11
12 Date: Sun Oct 28 16:23:26 1984
13 */
14
15 #include <errno.h>
16 #include <signal.h>
17 #include <stdio.h>
18 #include "../h/strings.h"
19 #include "syslog.h"
20 #include <sys/types.h>
21 #include <sys/file.h>
22 #ifndef NOIOCTLH
23 #include <sys/ioctl.h>
24 #endif
25 #include <sys/socket.h>
26 #include <sys/time.h>
27 #ifdef SIGTSTP
28 #include <sys/resource.h>
29 #include <sys/wait.h>
30 #endif
31 #include <netinet/in.h>
32 #include <netdb.h>
33 #include <arpa/inet.h>
34 #ifdef KPOP
35 #include <krb.h>
36
37 static Key_schedule schedule;
38 static KTEXT_ST ticket;
39 static AUTH_DAT kdata;
40 #endif
41 #ifdef SYS5
42 #include <fcntl.h>
43 #endif
44
45
46 #ifdef SYS5
47 #define u_short ushort
48 #endif
49
50 #define NOTOK (-1)
51 #define OK 0
52
53 #define NULLCP ((char *) 0)
54 #define NULLRP ((struct rusage *) 0)
55
56 #define FAST /* fast start-up of BBoards */
57
58 /* \f */
59
60 extern int errno;
61 #ifndef BSD44
62 extern int sys_nerr;
63 extern char *sys_errlist[];
64 extern char *sys_siglist[];
65 #endif
66
67
68 int debug = 0;
69 static int nbits = ((sizeof (int)) * 8);
70 static int options = 0;
71
72 #ifndef POPSERVICE
73 #define POPSERVICE "pop"
74 #endif
75
76 char *myname = "popd";
77 char myhost[BUFSIZ];
78 static char *myprotocol = "tcp";
79 static char *myservice = POPSERVICE;
80
81 static struct sockaddr_in in_socket;
82 static struct sockaddr_in *isock = &in_socket;
83
84 #ifdef KPOP
85 static AUTH_DAT kdata;
86 #endif
87
88 static TYPESIG chldser ();
89 void padios (), padvise ();
90
91 static server(), arginit(), envinit();
92 /* \f */
93
94 /* ARGSUSED */
95
96 main (argc, argv, envp)
97 int argc;
98 char **argv,
99 **envp;
100 {
101 #ifdef KPOP
102 int i;
103 #else
104 int fd,
105 sd;
106 int on = 1;
107 struct servent *sp;
108 struct sockaddr_in out_socket,
109 *osock = &out_socket;
110 #endif
111
112 #ifdef KPOP
113 i = sizeof(in_socket);
114 if (getpeername(0, &in_socket, &i) < 0)
115 padios("getpeername", "bad status");
116 #else
117 if ((sp = getservbyname (myservice, myprotocol)) == NULL)
118 padios (NULLCP, "%s/%s: unknown service", myprotocol, myservice);
119 isock -> sin_family = AF_INET;
120 isock -> sin_port = sp -> s_port;
121 isock -> sin_addr.s_addr = INADDR_ANY;
122 #endif
123 arginit (argv);
124 envinit ();
125
126 #ifndef KPOP
127 #ifdef RESTART
128 for (;;) {
129 char reason[BUFSIZ];
130 #if defined(BSD42) && !defined(WAITINT)
131 union wait status;
132 #else
133 int status;
134 #endif
135
136 switch (fork ()) {
137 case NOTOK:
138 sleep (5);
139 continue;
140
141 case OK:
142 break;
143
144 default:
145 sleep (60);
146 (void) wait3 (&status, 0, NULLRP);
147 if (WIFEXITED (status))
148 (void) sprintf (reason, "exit=0%o", status.w_retcode);
149 else
150 if (WIFSIGNALED (status))
151 (void) sprintf (reason, "signal=%s%s",
152 status.w_termsig < NSIG
153 ? sys_siglist[status.w_termsig] : "unknown",
154 status.w_coredump ? " (core dumped)" : NULL);
155 else
156 (void) strcpy (reason, "stopped(!!)");
157 padvise (NULLCP, LOG_WARNING, "%s/%s server has terminated -- %s",
158 sp -> s_proto, sp -> s_name, reason);
159 continue;
160 }
161 break;
162 }
163
164 closelog ();
165 #ifndef BSD43
166 openlog (myname, LOG_PID);
167 #else /* BSD43 */
168 openlog (myname, LOG_PID, LOG_DAEMON);
169 #endif /* BSD43 */
170 padvise (NULLCP, LOG_INFO, "restart");
171 #endif /* RESTART */
172
173 /* \f */
174
175 if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK)
176 padios ("socket", "unable to create");
177 #ifndef BSD43
178 if (options & SO_DEBUG)
179 if (setsockopt (sd, SOL_SOCKET, SO_DEBUG, NULL, 0) == NOTOK)
180 padvise ("SO_DEBUG", LOG_WARNING, "unable to set socket option");
181 if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, NULL, 0) == NOTOK)
182 padvise ("SO_KEEPALIVE", LOG_WARNING, "unable to set socket option");
183 #else /* BSD43 */
184 if (options & SO_DEBUG)
185 if (setsockopt (sd, SOL_SOCKET, SO_DEBUG, &on, sizeof on) == NOTOK)
186 padvise ("SO_DEBUG", LOG_WARNING, "unable to set socket option");
187 if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof on) == NOTOK)
188 padvise ("SO_KEEPALIVE", LOG_WARNING, "unable to set socket option");
189 #endif /* BSD43 */
190 if (bind (sd, (struct sockaddr *) isock, sizeof *isock) == NOTOK)
191 padios ("socket", "unable to bind");
192
193 #ifdef SIGCHLD
194 (void) signal (SIGCHLD, chldser);
195 #endif /* SIGCHLD */
196 (void) listen (sd, SOMAXCONN);
197 #endif /* KPOP */
198 #ifdef FAST
199 popinit ();
200 #endif /* FAST */
201 #ifndef KPOP
202 for (;;) {
203 int i = sizeof *osock;
204
205 if ((fd = accept (sd, (struct sockaddr *) osock, &i)) == NOTOK) {
206 if (errno != EINTR)
207 padvise ("socket", LOG_WARNING,
208 "unable to accept connection on");
209 continue;
210 }
211 #endif
212 #ifdef FAST
213 popassert ();
214 #endif /* FAST */
215 #ifndef KPOP
216 switch (fork ()) {
217 case OK:
218 (void) close (sd);
219 #ifdef SIGCHLD
220 (void) signal (SIGCHLD, SIG_DFL);
221 #endif /* SIGCHLD */
222 server (fd, osock);
223 _exit (0);
224
225 case NOTOK:
226 padvise ("socket", LOG_WARNING,
227 "no forks, so rejecting connection on");
228 default:
229 (void) close (fd);
230 }
231 }
232 #else
233 server (0, isock);
234 #endif
235 }
236
237 /* \f */
238
239 static server (fd, sin)
240 int fd;
241 struct sockaddr_in *sin;
242 {
243 u_short port;
244 struct hostent *hp;
245 struct in_addr *addr;
246 #ifdef KPOP
247 int auth;
248 int sin_len;
249 struct sockaddr_in faddr;
250 char instance[INST_SZ];
251 char version[9];
252 char user[ANAME_SZ];
253 #endif
254
255 closelog ();
256 #ifndef BSD43
257 openlog (myname, LOG_PID);
258 #else /* BSD43 */
259 openlog (myname, LOG_PID, LOG_DAEMON);
260 #endif /* BSD43 */
261 port = ntohs (sin -> sin_port);
262 addr = &sin -> sin_addr;
263 hp = gethostbyaddr ((char *)addr, sizeof *addr, sin -> sin_family);
264 padvise (NULLCP, LOG_INFO, "servicing %s/%d",
265 hp ? hp -> h_name : inet_ntoa (*addr), port);
266 if (fd != 0)
267 {
268 (void) dup2 (fd, 0);
269 (void) close (fd);
270 }
271 (void) dup2 (0, 1);
272
273 #ifdef KPOP
274 sin_len = sizeof (struct sockaddr_in);
275 if (getpeername(0, &faddr, &sin_len) < 0) {
276 padvise("getpeername", LOG_INFO, "");
277 exit(1);
278 }
279 strcpy(instance, "*");
280 auth = krb_recvauth(0L, 0, &ticket, "pop", instance,
281 &faddr, (struct sockaddr_in *)NULL,
282 &kdata, "", schedule, version);
283 if (auth == KSUCCESS)
284 auth = krb_kntoln(&kdata, user);
285
286 if (auth != KSUCCESS) {
287 padvise(NULLCP, LOG_INFO, "bad kerberos data, not ok'ing");
288 kpop (0, 1, NULLCP, NULLCP, auth); /* respond(NOTOK, krb_err_txt[auth]); */
289 } else {
290 kpop (0, 1, user, (hp ? hp -> h_name : NULLCP), 0);
291 }
292 #else
293 pop (0, 1, sin -> sin_family == AF_INET && port < IPPORT_RESERVED && hp,
294 hp ? hp -> h_name : NULLCP);
295 #endif
296 }
297
298 /* \f */
299
300 static arginit (vec)
301 char **vec;
302 {
303 int port;
304 register char *ap;
305 struct hostent *hp;
306
307 if (myname = rindex (*vec, '/'))
308 myname++;
309 if (myname == NULL || *myname == 0)
310 myname = *vec;
311
312 (void) gethostname (myhost, sizeof myhost);
313 if (hp = gethostbyname (myhost))
314 (void) strcpy (myhost, hp -> h_name);
315 #ifndef BSD42
316 nbits = _NFILE;
317 #else /* BSD42 */
318 nbits = getdtablesize ();
319 #endif /* BSD42 */
320
321 for (vec++; ap = *vec; vec++) {
322 if (*ap == '-')
323 switch (*++ap) {
324 case 'd':
325 options |= SO_DEBUG;
326 continue;
327
328 case 'p':
329 if ((ap = *++vec) == NULL
330 || *ap == '-'
331 || (port = atoi (ap)) <= 0)
332 padios (NULLCP, "usage: %s -p portno", myname);
333 isock -> sin_port = htons ((u_short) port);
334 continue;
335
336 default:
337 padios (NULLCP, "-%s: unknown switch", ap);
338 }
339
340 padios (NULLCP, "usage: %s [switches]", myname);
341 }
342 }
343
344 /* \f */
345
346 static envinit () {
347 #ifndef KPOP
348 int i,
349 sd;
350
351 if (!(debug = isatty (2))) {
352 for (i = 0; i < 5; i++) {
353 switch (fork ()) {
354 case NOTOK:
355 sleep (5);
356 continue;
357
358 case OK:
359 break;
360
361 default:
362 _exit (0);
363 }
364 break;
365 }
366
367 (void) chdir ("/");
368
369 if ((sd = open ("/dev/null", O_RDWR)) == NOTOK)
370 padios ("/dev/null", "unable to read");
371 if (sd != 0)
372 (void) dup2 (sd, 0), (void) close (sd);
373 (void) dup2 (0, 1);
374 (void) dup2 (0, 2);
375
376 if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) {
377 #ifdef TIOCNOTTY
378 (void) ioctl (sd, TIOCNOTTY, NULLCP);
379 #endif /* TIOCNOTTY */
380 (void) close (sd);
381 }
382 }
383
384 for (sd = 3; sd < nbits; sd++)
385 (void) close (sd);
386 #endif /* KPOP */
387
388 (void) signal (SIGPIPE, SIG_IGN);
389
390 #ifndef BSD43
391 openlog (myname, LOG_PID);
392 #else /* BSD43 */
393 openlog (myname, LOG_PID, LOG_DAEMON);
394 #endif /* BSD43 */
395 padvise (NULLCP, LOG_INFO, "starting");
396 if (debug)
397 padvise (NULLCP, LOG_DEBUG, "options=0x%x port=%d",
398 options, ntohs (isock -> sin_port));
399 }
400
401 /* \f */
402
403 #ifndef KPOP
404
405 /* ARGSUSED */
406
407 #ifdef SIGCHLD
408
409 static TYPESIG chldser (sig, code, sc)
410 int sig;
411 long code;
412 struct sigcontext *sc;
413 {
414 #if defined(BSD42) && !defined(WAITINT)
415 union wait status;
416 #else
417 int status;
418 #endif
419
420 while (wait3 (&status, WNOHANG, NULLRP) > 0)
421 continue;
422 }
423
424 #endif /* SIGCHLD */
425 #endif /* KPOP */
426
427 /* \f */
428
429 /* VARARGS2 */
430
431 void padios (what, fmt, a, b, c, d, e, f, g, h, i, j)
432 char *what,
433 *fmt,
434 *a,
435 *b,
436 *c,
437 *d,
438 *e,
439 *f,
440 *g,
441 *h,
442 *i,
443 *j;
444 {
445 padvise (what, LOG_ERR, fmt, a, b, c, d, e, f, g, h, i, j);
446 _exit (1);
447 }
448
449 /* \f */
450
451 /* VARARGS3 */
452
453 void padvise (what, code, fmt, a, b, c, d, e, f, g, h, i, j)
454 char *what,
455 *fmt,
456 *a,
457 *b,
458 *c,
459 *d,
460 *e,
461 *f,
462 *g,
463 *h,
464 *i,
465 *j;
466 int code;
467 {
468 int eindex = errno;
469 char buffer[BUFSIZ];
470
471 (void) sprintf (buffer, fmt, a, b, c, d, e, f, g, h, i, j);
472 if (what)
473 if (eindex > 0 && eindex < sys_nerr)
474 syslog (code, "%s %s: %s", buffer, what, sys_errlist[eindex]);
475 else
476 syslog (code, "%s %s: Error %d", buffer, what, eindex);
477 else
478 syslog (code, "%s", buffer);
479
480 if (debug) {
481 fprintf (stderr, "[%d] %s", code, buffer);
482 if (what)
483 (void) fputc (' ', stderr), perror (what);
484 else
485 (void) fputc ('\n', stderr);
486 (void) fflush (stderr);
487 }
488
489 errno = eindex;
490 }