|
|
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: register char *ap;
200: struct hostent *hp;
201:
202: if (myname = rindex (*vec, '/'))
203: myname++;
204: if (myname == NULL || *myname == NULL)
205: myname = *vec;
206:
207: (void) gethostname (myhost, sizeof myhost);
208: if (hp = gethostbyname (myhost))
209: (void) strcpy (myhost, hp -> h_name);
210: nbits = getdtablesize ();
211:
212: for (vec++; ap = *vec; vec++) {
213: if (*ap == '-')
214: switch (*++ap) {
215: case 'd':
216: options |= SO_DEBUG;
217: continue;
218:
219: case 'p':
220: if ((ap = *++vec) == NULL
221: || *ap == '-'
222: || (isock -> sin_port = atoi (ap)) <= 0)
223: padios (NULLCP, "usage: %s -p portno", myname);
224: isock -> sin_port = htons (isock -> sin_port);
225: continue;
226:
227: default:
228: padios (NULLCP, "-%s: unknown switch", ap);
229: }
230:
231: padios (NULLCP, "usage: %s [switches]", myname);
232: }
233: }
234:
235: /* */
236:
237: static envinit () {
238: int i,
239: sd;
240:
241: if (!(debug = isatty (2))) {
242: for (i = 0; i < 5; i++) {
243: switch (fork ()) {
244: case NOTOK:
245: sleep (5);
246: continue;
247:
248: case OK:
249: break;
250:
251: default:
252: _exit (0);
253: }
254: break;
255: }
256:
257: (void) chdir ("/");
258:
259: if ((sd = open ("/dev/null", O_RDWR)) == NOTOK)
260: padios ("/dev/null", "unable to read");
261: if (sd != 0)
262: (void) dup2 (sd, 0), (void) close (sd);
263: (void) dup2 (0, 1);
264: (void) dup2 (0, 2);
265:
266: if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) {
267: (void) ioctl (sd, TIOCNOTTY, NULLCP);
268: (void) close (sd);
269: }
270: }
271:
272: for (sd = 3; sd < nbits; sd++)
273: (void) close (sd);
274:
275: (void) signal (SIGPIPE, SIG_IGN);
276:
277: openlog (myname, LOG_PID);
278: padvise (NULLCP, LOG_INFO, "starting");
279: if (debug)
280: padvise (NULLCP, LOG_DEBUG, "options=0x%x port=%d",
281: options, ntohs (isock -> sin_port));
282: }
283:
284: /* */
285:
286: /* ARGSUSED */
287:
288: static int chldser (sig, code, sc)
289: int sig;
290: long code;
291: struct sigcontext *sc;
292: {
293: union wait status;
294:
295: while (wait3 (&status, WNOHANG, NULLRP) > 0)
296: continue;
297: }
298:
299: /* */
300:
301: /* VARARGS2 */
302:
303: void padios (what, fmt, a, b, c, d, e, f, g, h, i, j)
304: char *what,
305: *fmt,
306: *a,
307: *b,
308: *c,
309: *d,
310: *e,
311: *f,
312: *g,
313: *h,
314: *i,
315: *j;
316: {
317: padvise (what, LOG_SALERT, fmt, a, b, c, d, e, f, g, h, i, j);
318: _exit (1);
319: }
320:
321: /* */
322:
323: /* VARARGS3 */
324:
325: void padvise (what, code, fmt, a, b, c, d, e, f, g, h, i, j)
326: char *what,
327: *fmt,
328: *a,
329: *b,
330: *c,
331: *d,
332: *e,
333: *f,
334: *g,
335: *h,
336: *i,
337: *j;
338: int code;
339: {
340: int eindex = errno;
341: char buffer[BUFSIZ];
342:
343: (void) sprintf (buffer, fmt, a, b, c, d, e, f, g, h, i, j);
344: if (what)
345: if (eindex > 0 && eindex < sys_nerr)
346: syslog (code, "%s %s: %s", buffer, what, sys_errlist[eindex]);
347: else
348: syslog (code, "%s %s: Error %d", buffer, what, eindex);
349: else
350: syslog (code, "%s", buffer);
351:
352: if (debug) {
353: fprintf (stderr, "[%d] %s", code, buffer);
354: if (what)
355: (void) fputc (' ', stderr), perror (what);
356: else
357: (void) fputc ('\n', stderr);
358: (void) fflush (stderr);
359: }
360:
361: errno = eindex;
362: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.