# 2.11BSD#431 - /usr/src/usr.sbin/sendmail/aux/4.1a_daemon.c

##### Functions

    clrdaemon         X
    getconnection     X
    getrequests       X
    makeconnection    X
    myhostname        X

##### Variables

    SendmailAddress   X

##### Macros

    IPPORT_PLAYPORT   X

       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

- in line 171-177(5), 195(2), 202, 305-311(3), 339-342(5)

#### Defined macros

IPPORT_PLAYPORT defined in line 155; used 1 times

- in line 175

Last modified: 1987-02-18 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1226 |