Annotation of 42BSD/usr.lib/sendmail/aux/4.1a_daemon.c, revision 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.