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

Defined functions

clrdaemon defined in line 251; never used
getconnection defined in line 159; used 1 times
  • in line 68
getrequests defined in line 55; never used
makeconnection defined in line 272; never used
myhostname defined in line 412; 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: 1987-02-18
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3251
Valid CSS Valid XHTML 1.0 Strict