Annotation of 42BSD/usr.lib/sendmail/aux/4.1a_daemon.c, revision 1.1.1.1

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: **  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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.