|
|
1.1 root 1: /* popd.c - the POP server */
2:
3: /* Author: Marshall T. Rose <MRose@UDel> (MTR)
4: Department of Computer Science and Information Sciences
5: University of Delaware
6: Newark, DE 19716
7: 302/451-1951
8:
9: Date: Sun Oct 28 16:23:26 1984
10: */
11:
12: #include <errno.h>
13: #include <signal.h>
14: #include <stdio.h>
15: #include <strings.h>
16: #include <syslog.h>
17: #include <sys/types.h>
18: #include <sys/file.h>
19: #include <sys/ioctl.h>
20: #include <sys/socket.h>
21: #include <sys/time.h>
22: #include <sys/resource.h>
23: #include <sys/wait.h>
24: #include <netinet/in.h>
25: #include <netdb.h>
26: #include <arpa/inet.h>
27:
28:
29: #define NOTOK (-1)
30: #define OK 0
31:
32: #define NULLCP ((char *) 0)
33: #define NULLRP ((struct rusage *) 0)
34:
35: #define FAST /* fast start-up of BBoards */
36:
37: /* */
38:
39: extern int errno;
40: extern int sys_nerr;
41: extern char *sys_errlist[];
42: extern char *sys_siglist[];
43:
44:
45: int debug = 0;
46: static int nbits = ((sizeof (int)) * 8);
47: static int options = 0;
48:
49:
50: char *myname = "popd";
51: char myhost[BUFSIZ];
52: static char *myprotocol = "tcp";
53: static char *myservice = "pop";
54:
55: static struct sockaddr_in in_socket;
56: static struct sockaddr_in *isock = &in_socket;
57:
58:
59: int chldser ();
60: void padios (), padvise ();
61:
62: /* */
63:
64: /* ARGSUSED */
65:
66: main (argc, argv, envp)
67: int argc;
68: char **argv,
69: **envp;
70: {
71: int fd,
72: sd;
73: struct servent *sp;
74: struct sockaddr_in out_socket,
75: *osock = &out_socket;
76:
77: if ((sp = getservbyname (myservice, myprotocol)) == NULL)
78: padios (NULLCP, "%s/%s: unknown service", myprotocol, myservice);
79: isock -> sin_family = AF_INET;
80: isock -> sin_port = sp -> s_port;
81: isock -> sin_addr.s_addr = INADDR_ANY;
82: arginit (argv);
83: envinit ();
84:
85: #ifdef RESTART
86: for (;;) {
87: char reason[BUFSIZ];
88: union wait status;
89:
90: switch (fork ()) {
91: case NOTOK:
92: sleep (5);
93: continue;
94:
95: case OK:
96: break;
97:
98: default:
99: sleep (60);
100: (void) wait3 (&status, 0, NULLRP);
101: if (WIFEXITED (status))
102: (void) sprintf (reason, "exit=0%o", status.w_retcode);
103: else
104: if (WIFSIGNALED (status))
105: (void) sprintf (reason, "signal=%s%s",
106: status.w_termsig < NSIG
107: ? sys_siglist[status.w_termsig] : "unknown",
108: status.w_coredump ? " (core dumped)" : NULL);
109: else
110: (void) strcpy (reason, "stopped(!!)");
111: padvise (NULLCP, LOG_WARNING, "%s/%s server has terminated -- %s",
112: sp -> s_proto, sp -> s_name, reason);
113: continue;
114: }
115: break;
116: }
117:
118: closelog ();
119: openlog (myname, LOG_PID);
120: padvise (NULLCP, LOG_INFO, "restart");
121: #endif RESTART
122:
123: /* */
124:
125: if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == NOTOK)
126: padios ("socket", "unable to create");
127: if (options & SO_DEBUG)
128: if (setsockopt (sd, SOL_SOCKET, SO_DEBUG, NULL, 0) == NOTOK)
129: padvise ("SO_DEBUG", LOG_WARNING, "unable to set socket option");
130: if (setsockopt (sd, SOL_SOCKET, SO_KEEPALIVE, NULL, 0) == NOTOK)
131: padvise ("SO_KEEPALIVE", LOG_WARNING, "unable to set socket option");
132: if (bind (sd, (struct sockaddr *) isock, sizeof *isock) == NOTOK)
133: padios ("socket", "unable to bind");
134:
135: (void) signal (SIGCHLD, chldser);
136: (void) listen (sd, SOMAXCONN);
137: #ifdef FAST
138: popinit ();
139: #endif FAST
140: for (;;) {
141: int i = sizeof *osock;
142:
143: if ((fd = accept (sd, (struct sockaddr *) osock, &i)) == NOTOK) {
144: if (errno != EINTR)
145: padvise ("socket", LOG_WARNING,
146: "unable to accept connection on");
147: continue;
148: }
149: #ifdef FAST
150: popassert ();
151: #endif FAST
152: switch (fork ()) {
153: case OK:
154: (void) close (sd);
155: (void) signal (SIGCHLD, SIG_DFL);
156: server (fd, osock);
157: _exit (0);
158:
159: case NOTOK:
160: padvise ("socket", LOG_WARNING,
161: "no forks, so rejecting connection on");
162: default:
163: (void) close (fd);
164: }
165: }
166: }
167:
168: /* */
169:
170: static server (fd, sin)
171: int fd;
172: struct sockaddr_in *sin;
173: {
174: u_short port;
175: struct hostent *hp;
176: struct in_addr *addr;
177:
178: closelog ();
179: openlog (myname, LOG_PID);
180: port = ntohs (sin -> sin_port);
181: addr = &sin -> sin_addr;
182: hp = gethostbyaddr (addr, sizeof *addr, sin -> sin_family);
183: padvise (NULLCP, LOG_INFO, "servicing %s/%d",
184: hp ? hp -> h_name : inet_ntoa (*addr), port);
185:
186: (void) dup2 (fd, 0);
187: (void) close (fd);
188: (void) dup2 (0, 1);
189:
190: pop (0, 1, sin -> sin_family == AF_INET && port < IPPORT_RESERVED && hp,
191: hp ? hp -> h_name : NULLCP);
192: }
193:
194: /* */
195:
196: static arginit (vec)
197: char **vec;
198: {
199: int port;
200: register char *ap;
201: struct hostent *hp;
202:
203: if (myname = rindex (*vec, '/'))
204: myname++;
205: if (myname == NULL || *myname == NULL)
206: myname = *vec;
207:
208: (void) gethostname (myhost, sizeof myhost);
209: if (hp = gethostbyname (myhost))
210: (void) strcpy (myhost, hp -> h_name);
211: nbits = getdtablesize ();
212:
213: for (vec++; ap = *vec; vec++) {
214: if (*ap == '-')
215: switch (*++ap) {
216: case 'd':
217: options |= SO_DEBUG;
218: continue;
219:
220: case 'p':
221: if ((ap = *++vec) == NULL
222: || *ap == '-'
223: || (port = atoi (ap)) <= 0)
224: padios (NULLCP, "usage: %s -p portno", myname);
225: isock -> sin_port = htons ((u_short) port);
226: continue;
227:
228: default:
229: padios (NULLCP, "-%s: unknown switch", ap);
230: }
231:
232: padios (NULLCP, "usage: %s [switches]", myname);
233: }
234: }
235:
236: /* */
237:
238: static envinit () {
239: int i,
240: sd;
241:
242: if (!(debug = isatty (2))) {
243: for (i = 0; i < 5; i++) {
244: switch (fork ()) {
245: case NOTOK:
246: sleep (5);
247: continue;
248:
249: case OK:
250: break;
251:
252: default:
253: _exit (0);
254: }
255: break;
256: }
257:
258: (void) chdir ("/");
259:
260: if ((sd = open ("/dev/null", O_RDWR)) == NOTOK)
261: padios ("/dev/null", "unable to read");
262: if (sd != 0)
263: (void) dup2 (sd, 0), (void) close (sd);
264: (void) dup2 (0, 1);
265: (void) dup2 (0, 2);
266:
267: if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) {
268: (void) ioctl (sd, TIOCNOTTY, NULLCP);
269: (void) close (sd);
270: }
271: }
272:
273: for (sd = 3; sd < nbits; sd++)
274: (void) close (sd);
275:
276: (void) signal (SIGPIPE, SIG_IGN);
277:
278: openlog (myname, LOG_PID);
279: padvise (NULLCP, LOG_INFO, "starting");
280: if (debug)
281: padvise (NULLCP, LOG_DEBUG, "options=0x%x port=%d",
282: options, ntohs (isock -> sin_port));
283: }
284:
285: /* */
286:
287: /* ARGSUSED */
288:
289: static int chldser (sig, code, sc)
290: int sig;
291: long code;
292: struct sigcontext *sc;
293: {
294: union wait status;
295:
296: while (wait3 (&status, WNOHANG, NULLRP) > 0)
297: continue;
298: }
299:
300: /* */
301:
302: /* VARARGS2 */
303:
304: void padios (what, fmt, a, b, c, d, e, f, g, h, i, j)
305: char *what,
306: *fmt,
307: *a,
308: *b,
309: *c,
310: *d,
311: *e,
312: *f,
313: *g,
314: *h,
315: *i,
316: *j;
317: {
318: padvise (what, LOG_SALERT, fmt, a, b, c, d, e, f, g, h, i, j);
319: _exit (1);
320: }
321:
322: /* */
323:
324: /* VARARGS3 */
325:
326: void padvise (what, code, fmt, a, b, c, d, e, f, g, h, i, j)
327: char *what,
328: *fmt,
329: *a,
330: *b,
331: *c,
332: *d,
333: *e,
334: *f,
335: *g,
336: *h,
337: *i,
338: *j;
339: int code;
340: {
341: int eindex = errno;
342: char buffer[BUFSIZ];
343:
344: (void) sprintf (buffer, fmt, a, b, c, d, e, f, g, h, i, j);
345: if (what)
346: if (eindex > 0 && eindex < sys_nerr)
347: syslog (code, "%s %s: %s", buffer, what, sys_errlist[eindex]);
348: else
349: syslog (code, "%s %s: Error %d", buffer, what, eindex);
350: else
351: syslog (code, "%s", buffer);
352:
353: if (debug) {
354: fprintf (stderr, "[%d] %s", code, buffer);
355: if (what)
356: (void) fputc (' ', stderr), perror (what);
357: else
358: (void) fputc ('\n', stderr);
359: (void) fflush (stderr);
360: }
361:
362: errno = eindex;
363: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.