|
|
1.1 root 1: # include <errno.h>
2: # include "sendmail.h"
3:
4: #ifndef DAEMON
5: SCCSID(@(#)4.1a_daemon.c 3.35+ 12/5/82 (w/o daemon mode));
6: #else
7:
8: # include <sys/socket.h>
9: # include <net/in.h>
10: # include <wait.h>
11:
12: SCCSID(@(#)4.1a_daemon.c 3.35+ 12/5/82 (with daemon mode));
13:
14: /*
15: ** DAEMON.C -- routines to use when running as a daemon.
16: **
17: ** 4.1a BSD version -- this version is not well supported.
18: **
19: ** This entire file is highly dependent on the 4.1a BSD
20: ** interprocess communication primitives. No attempt has
21: ** been made to make this file portable to Version 7,
22: ** Version 6, MPX files, etc. If you should try such a
23: ** thing yourself, I recommend chucking the entire file
24: ** and starting from scratch. Basic semantics are:
25: **
26: ** getrequests()
27: ** Opens a port and initiates a connection.
28: ** Returns in a child. Must set InChannel and
29: ** OutChannel appropriately.
30: ** makeconnection(host, port, outfile, infile)
31: ** Make a connection to the named host on the given
32: ** port. Set *outfile and *infile to the files
33: ** appropriate for communication. Returns zero on
34: ** success, else an exit status describing the
35: ** error.
36: **
37: ** The semantics of both of these should be clean.
38: */
39: /*
40: ** GETREQUESTS -- open mail IPC port and get requests.
41: **
42: ** Parameters:
43: ** none.
44: **
45: ** Returns:
46: ** none.
47: **
48: ** Side Effects:
49: ** Waits until some interesting activity occurs. When
50: ** it does, a child is created to process it, and the
51: ** parent waits for completion. Return from this
52: ** routine is always in the child.
53: */
54:
55: getrequests()
56: {
57: union wait status;
58:
59: for (;;)
60: {
61: register int pid;
62: register int port;
63:
64: /*
65: ** Wait for a connection.
66: */
67:
68: while ((port = getconnection()) < 0)
69: {
70: # ifdef LOG
71: if (LogLevel > 0)
72: syslog(LOG_SALERT, "cannot get connection");
73: # endif LOG
74: finis();
75: }
76:
77: /*
78: ** Create a subprocess to process the mail.
79: */
80:
81: # ifdef DEBUG
82: if (tTd(15, 2))
83: printf("getrequests: forking (port = %d)\n", port);
84: # endif DEBUG
85:
86: pid = fork();
87: if (pid < 0)
88: {
89: syserr("daemon: cannot fork");
90: sleep(10);
91: (void) close(port);
92: continue;
93: }
94:
95: if (pid == 0)
96: {
97: /*
98: ** CHILD -- return to caller.
99: ** Verify calling user id if possible here.
100: */
101:
102: InChannel = fdopen(port, "r");
103: OutChannel = fdopen(port, "w");
104: # ifdef DEBUG
105: if (tTd(15, 2))
106: printf("getreq: returning\n");
107: # endif DEBUG
108: # ifdef LOG
109: if (LogLevel > 11)
110: syslog(LOG_DEBUG, "connected, pid=%d", getpid());
111: # endif LOG
112: return;
113: }
114:
115: /*
116: ** PARENT -- wait for child to terminate.
117: ** Perhaps we should allow concurrent processing?
118: */
119:
120: # ifdef DEBUG
121: if (tTd(15, 2))
122: {
123: sleep(2);
124: printf("getreq: parent waiting\n");
125: }
126: # endif DEBUG
127:
128: /* close the port so that others will hang (for a while) */
129: (void) close(port);
130:
131: /* pick up old zombies; implement load limiting */
132: while (wait3(&status, WNOHANG, 0) > 0)
133: continue;
134: }
135: }
136: /*
137: ** GETCONNECTION -- make a connection with the outside world
138: **
139: ** This routine is horribly contorted to try to get around a bunch
140: ** of 4.1a IPC bugs. There appears to be nothing we can do to make
141: ** it "right" -- the code to interrupt accepts just doesn't work
142: ** right. However, this is an attempt to minimize the probablity
143: ** of problems.
144: **
145: ** Parameters:
146: ** none.
147: **
148: ** Returns:
149: ** The port for mail traffic.
150: **
151: ** Side Effects:
152: ** Waits for a connection.
153: */
154:
155: #define IPPORT_PLAYPORT 3055 /* random number */
156:
157: struct sockaddr_in SendmailAddress = { AF_INET, IPPORT_SMTP };
158:
159: getconnection()
160: {
161: int s;
162: #ifdef NVMUNIX
163: int t;
164: #endif NVMUNIX
165: struct sockaddr otherend;
166:
167: /*
168: ** Set up the address for the mailer.
169: */
170:
171: SendmailAddress.sin_addr.s_addr = 0;
172: SendmailAddress.sin_port = IPPORT_SMTP;
173: # ifdef DEBUG
174: if (tTd(15, 15))
175: SendmailAddress.sin_port = IPPORT_PLAYPORT;
176: # endif DEBUG
177: SendmailAddress.sin_port = htons(SendmailAddress.sin_port);
178:
179: /*
180: ** Try to actually open the connection.
181: */
182:
183: # ifdef DEBUG
184: if (tTd(15, 1))
185: printf("getconnection\n");
186: # endif DEBUG
187:
188: for (;; sleep(15))
189: {
190: int i;
191:
192: /* get a socket for the SMTP connection */
193: #ifdef NVMUNIX
194: s = socket(AF_INET, SOCK_STREAM, 0, 0);
195: bind(s, &SendmailAddress, sizeof SendmailAddress, 0);
196: listen(s, 10);
197: #else NVMUNIX
198: /* do loop is to avoid 4.1b kernel bug (?) */
199: i = 60;
200: do
201: {
202: s = socket(SOCK_STREAM, 0, &SendmailAddress, SO_ACCEPTCONN);
203: if (s < 0)
204: sleep(10);
205: } while (--i > 0 && s < 0);
206: #endif NVMUNIX
207: if (s < 0)
208: {
209: /* probably another daemon already */
210: syserr("getconnection: can't create socket");
211: return (-1);
212: }
213:
214: # ifdef DEBUG
215: if (tTd(15, 1))
216: printf("getconnection: %d\n", s);
217: # endif DEBUG
218:
219: /* wait for a connection */
220: do
221: {
222: errno = 0;
223: #ifdef NVMUNIX
224: lotherend = sizeof otherend;
225: t = accept(s, &otherend, &lotherend, 0);
226: if (t >= 0)
227: return (t);
228: #else NVMUNIX
229: if (accept(s, &otherend) >= 0)
230: return (s);
231: #endif NVMUNIX
232: } while (errno == EINTR);
233: syserr("getconnection: accept");
234: sleep(5);
235: (void) close(s);
236: }
237: }
238: /*
239: ** CLRDAEMON -- reset the daemon connection
240: **
241: ** Parameters:
242: ** none.
243: **
244: ** Returns:
245: ** none.
246: **
247: ** Side Effects:
248: ** releases any resources used by the passive daemon.
249: */
250:
251: clrdaemon()
252: {
253: }
254: /*
255: ** MAKECONNECTION -- make a connection to an SMTP socket on another machine.
256: **
257: ** Parameters:
258: ** host -- the name of the host.
259: ** port -- the port number to connect to.
260: ** outfile -- a pointer to a place to put the outfile
261: ** descriptor.
262: ** infile -- ditto for infile.
263: **
264: ** Returns:
265: ** An exit code telling whether the connection could be
266: ** made and if not why not.
267: **
268: ** Side Effects:
269: ** none.
270: */
271:
272: makeconnection(host, port, outfile, infile)
273: char *host;
274: u_short port;
275: FILE **outfile;
276: FILE **infile;
277: {
278: register int s;
279:
280: /*
281: ** Set up the address for the mailer.
282: ** Accept "[a.b.c.d]" syntax for host name.
283: */
284:
285: if (host[0] == '[')
286: {
287: long hid = 0;
288: int i, j;
289: register char *p = host;
290:
291: for (i = 3; i >= 0 && *p != ']' && *p != '\0'; i--)
292: {
293: j = 0;
294: while (isdigit(*++p))
295: j = j * 10 + (*p - '0');
296: if (*p != (i == 0 ? ']' : '.') || j > 255 || j < 0)
297: break;
298: hid |= j << ((3 - i) * 8);
299: }
300: if (i >= 0 || *p != ']' || *++p != '\0')
301: {
302: usrerr("Invalid numeric domain spec \"%s\"", host);
303: return (EX_NOHOST);
304: }
305: SendmailAddress.sin_addr.s_addr = hid;
306: }
307: else if ((SendmailAddress.sin_addr.s_addr = rhost(&host)) == -1)
308: return (EX_NOHOST);
309: if (port == 0)
310: port = IPPORT_SMTP;
311: SendmailAddress.sin_port = htons(port);
312:
313: /*
314: ** Try to actually open the connection.
315: */
316:
317: # ifdef DEBUG
318: if (tTd(16, 1))
319: printf("makeconnection (%s)\n", host);
320: # endif DEBUG
321:
322: #ifdef NVMUNIX
323: s = socket(AF_INET, SOCK_STREAM, 0, 0);
324: #else NVMUNIX
325: s = socket(SOCK_STREAM, 0, (struct sockaddr_in *) 0, 0);
326: #endif NVMUNIX
327: if (s < 0)
328: {
329: syserr("makeconnection: no socket");
330: goto failure;
331: }
332:
333: # ifdef DEBUG
334: if (tTd(16, 1))
335: printf("makeconnection: %d\n", s);
336: # endif DEBUG
337: (void) fflush(CurEnv->e_xfp); /* for debugging */
338: #ifdef NVMUNIX
339: bind(s, &SendmailAddress, sizeof SendmailAddress, 0);
340: if (connect(s, &SendmailAddress, sizeof SendmailAddress, 0) < 0)
341: #else NVMUNIX
342: if (connect(s, &SendmailAddress) < 0)
343: #endif NVMUNIX
344: {
345: /* failure, decide if temporary or not */
346: failure:
347: switch (errno)
348: {
349: case EISCONN:
350: case ETIMEDOUT:
351: case EINPROGRESS:
352: case EALREADY:
353: case EADDRINUSE:
354: case ENETDOWN:
355: case ENETRESET:
356: case ENOBUFS:
357: case ECONNREFUSED:
358: /* there are others, I'm sure..... */
359: return (EX_TEMPFAIL);
360:
361: default:
362: return (EX_UNAVAILABLE);
363: }
364: }
365:
366: /* connection ok, put it into canonical form */
367: *outfile = fdopen(s, "w");
368: *infile = fdopen(s, "r");
369:
370: return (0);
371: }
372:
373: /*
374: ** MYHOSTNAME -- return the name of this host.
375: **
376: ** Parameters:
377: ** hostbuf -- a place to return the name of this host.
378: ** size -- the size of hostbuf.
379: **
380: ** Returns:
381: ** A list of aliases for this host.
382: ** NULL if it can't find an alias list.
383: **
384: ** Side Effects:
385: ** none.
386: */
387:
388: char **
389: myhostname(hostbuf, size)
390: char hostbuf[];
391: int size;
392: {
393: register char *p;
394:
395: gethostname(hostbuf, size);
396: for (p = hostbuf; *p != '\0'; p++)
397: if (islower(*p))
398: *p -= 'a' - 'A';
399:
400: /* now where would we find an alias list? */
401: return (NULL);
402: }
403:
404: # else DAEMON
405:
406: /*
407: ** MYHOSTNAME -- stub version for case of no daemon code.
408: **
409: ** Can't convert to upper case here because might be a UUCP name.
410: */
411:
412: char **
413: myhostname(hostbuf, size)
414: char hostbuf[];
415: int size;
416: {
417: register FILE *f;
418:
419: hostbuf[0] = '\0';
420: f = fopen("/usr/include/whoami", "r");
421: if (f != NULL)
422: {
423: (void) fgets(hostbuf, size, f);
424: fixcrlf(hostbuf, TRUE);
425: (void) fclose(f);
426: }
427: return (NULL);
428: }
429:
430: #endif DAEMON
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.