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: **  MAKECONNECTION -- make a connection to an SMTP socket on another machine.
 240: **
 241: **	Parameters:
 242: **		host -- the name of the host.
 243: **		port -- the port number to connect to.
 244: **		outfile -- a pointer to a place to put the outfile
 245: **			descriptor.
 246: **		infile -- ditto for infile.
 247: **
 248: **	Returns:
 249: **		An exit code telling whether the connection could be
 250: **			made and if not why not.
 251: **
 252: **	Side Effects:
 253: **		none.
 254: */
 255: 
 256: makeconnection(host, port, outfile, infile)
 257:     char *host;
 258:     u_short port;
 259:     FILE **outfile;
 260:     FILE **infile;
 261: {
 262:     register int s;
 263: 
 264:     /*
 265: 	**  Set up the address for the mailer.
 266: 	**	Accept "[a.b.c.d]" syntax for host name.
 267: 	*/
 268: 
 269:     if (host[0] == '[')
 270:     {
 271:         long hid = 0;
 272:         int i, j;
 273:         register char *p = host;
 274: 
 275:         for (i = 3; i >= 0 && *p != ']' && *p != '\0'; i--)
 276:         {
 277:             j = 0;
 278:             while (isdigit(*++p))
 279:                 j = j * 10 + (*p - '0');
 280:             if (*p != (i == 0 ? ']' : '.') || j > 255 || j < 0)
 281:                 break;
 282:             hid |= j << ((3 - i) * 8);
 283:         }
 284:         if (i >= 0 || *p != ']' || *++p != '\0')
 285:         {
 286:             usrerr("Invalid numeric domain spec \"%s\"", host);
 287:             return (EX_NOHOST);
 288:         }
 289:         SendmailAddress.sin_addr.s_addr = hid;
 290:     }
 291:     else if ((SendmailAddress.sin_addr.s_addr = rhost(&host)) == -1)
 292:         return (EX_NOHOST);
 293:     if (port == 0)
 294:         port = IPPORT_SMTP;
 295:     SendmailAddress.sin_port = htons(port);
 296: 
 297:     /*
 298: 	**  Try to actually open the connection.
 299: 	*/
 300: 
 301: # ifdef DEBUG
 302:     if (tTd(16, 1))
 303:         printf("makeconnection (%s)\n", host);
 304: # endif DEBUG
 305: 
 306: #ifdef NVMUNIX
 307:     s = socket(AF_INET, SOCK_STREAM, 0, 0);
 308: #else NVMUNIX
 309:     s = socket(SOCK_STREAM, 0, (struct sockaddr_in *) 0, 0);
 310: #endif NVMUNIX
 311:     if (s < 0)
 312:     {
 313:         syserr("makeconnection: no socket");
 314:         goto failure;
 315:     }
 316: 
 317: # ifdef DEBUG
 318:     if (tTd(16, 1))
 319:         printf("makeconnection: %d\n", s);
 320: # endif DEBUG
 321:     (void) fflush(CurEnv->e_xfp);           /* for debugging */
 322: #ifdef NVMUNIX
 323:     bind(s, &SendmailAddress, sizeof SendmailAddress, 0);
 324:     if (connect(s, &SendmailAddress, sizeof SendmailAddress, 0) < 0)
 325: #else NVMUNIX
 326:     if (connect(s, &SendmailAddress) < 0)
 327: #endif NVMUNIX
 328:     {
 329:         /* failure, decide if temporary or not */
 330:     failure:
 331:         switch (errno)
 332:         {
 333:           case EISCONN:
 334:           case ETIMEDOUT:
 335:           case EINPROGRESS:
 336:           case EALREADY:
 337:           case EADDRINUSE:
 338:           case ENETDOWN:
 339:           case ENETRESET:
 340:           case ENOBUFS:
 341:           case ECONNREFUSED:
 342:             /* there are others, I'm sure..... */
 343:             return (EX_TEMPFAIL);
 344: 
 345:           default:
 346:             return (EX_UNAVAILABLE);
 347:         }
 348:     }
 349: 
 350:     /* connection ok, put it into canonical form */
 351:     *outfile = fdopen(s, "w");
 352:     *infile = fdopen(s, "r");
 353: 
 354:     return (0);
 355: }
 356: 
 357: /*
 358: **  MYHOSTNAME -- return the name of this host.
 359: **
 360: **	Parameters:
 361: **		hostbuf -- a place to return the name of this host.
 362: **		size -- the size of hostbuf.
 363: **
 364: **	Returns:
 365: **		A list of aliases for this host.
 366: **		NULL if it can't find an alias list.
 367: **
 368: **	Side Effects:
 369: **		none.
 370: */
 371: 
 372: char **
 373: myhostname(hostbuf, size)
 374:     char hostbuf[];
 375:     int size;
 376: {
 377:     register char *p;
 378: 
 379:     gethostname(hostbuf, size);
 380:     for (p = hostbuf; *p != '\0'; p++)
 381:         if (islower(*p))
 382:             *p -= 'a' - 'A';
 383: 
 384:     /* now where would we find an alias list? */
 385:     return (NULL);
 386: }
 387: 
 388: # else DAEMON
 389: 
 390: /*
 391: **  MYHOSTNAME -- stub version for case of no daemon code.
 392: **
 393: **	Can't convert to upper case here because might be a UUCP name.
 394: */
 395: 
 396: char **
 397: myhostname(hostbuf, size)
 398:     char hostbuf[];
 399:     int size;
 400: {
 401:     register FILE *f;
 402: 
 403:     hostbuf[0] = '\0';
 404:     f = fopen("/usr/include/whoami", "r");
 405:     if (f != NULL)
 406:     {
 407:         (void) fgets(hostbuf, size, f);
 408:         fixcrlf(hostbuf, TRUE);
 409:         (void) fclose(f);
 410:     }
 411:     return (NULL);
 412: }
 413: 
 414: #endif DAEMON

Defined functions

getconnection defined in line 159; used 1 times
  • in line 68
getrequests defined in line 55; never used
makeconnection defined in line 256; never used
myhostname defined in line 396; never used

Defined variables

SendmailAddress defined in line 157; used 16 times

Defined macros

IPPORT_PLAYPORT defined in line 155; used 1 times
Last modified: 1983-12-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1104
Valid CSS Valid XHTML 1.0 Strict