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

Defined functions

clrdaemon defined in line 261; used 1 times
getconnection defined in line 168; used 1 times
  • in line 76
getrequests defined in line 63; used 1 times
makeconnection defined in line 285; used 1 times
myhostname defined in line 439; used 2 times

Defined variables

DaemonSocket defined in line 166; used 4 times
SendmailAddress defined in line 165; used 17 times

Defined macros

IPPORT_PLAYPORT defined in line 163; used 1 times
wait3 defined in line 7; used 1 times
Last modified: 1984-03-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1294
Valid CSS Valid XHTML 1.0 Strict