Annotation of 43BSD/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: **  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

unix.superglobalmegacorp.com

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