Annotation of 42BSD/usr.lib/sendmail/src/daemon.c, revision 1.1

1.1     ! root        1: # include <errno.h>
        !             2: # include "sendmail.h"
        !             3: 
        !             4: #ifndef DAEMON
        !             5: SCCSID(@(#)daemon.c    4.4             8/28/83 (w/o daemon mode));
        !             6: #else
        !             7: 
        !             8: #include <sys/socket.h>
        !             9: #include <netinet/in.h>
        !            10: #include <netdb.h>
        !            11: #include <sys/wait.h>
        !            12: 
        !            13: SCCSID(@(#)daemon.c    4.4             8/28/83 (with daemon mode));
        !            14: 
        !            15: /*
        !            16: **  DAEMON.C -- routines to use when running as a daemon.
        !            17: **
        !            18: **     This entire file is highly dependent on the 4.2 BSD
        !            19: **     interprocess communication primitives.  No attempt has
        !            20: **     been made to make this file portable to Version 7,
        !            21: **     Version 6, MPX files, etc.  If you should try such a
        !            22: **     thing yourself, I recommend chucking the entire file
        !            23: **     and starting from scratch.  Basic semantics are:
        !            24: **
        !            25: **     getrequests()
        !            26: **             Opens a port and initiates a connection.
        !            27: **             Returns in a child.  Must set InChannel and
        !            28: **             OutChannel appropriately.
        !            29: **     clrdaemon()
        !            30: **             Close any open files associated with getting
        !            31: **             the connection; this is used when running the queue,
        !            32: **             etc., to avoid having extra file descriptors during
        !            33: **             the queue run and to avoid confusing the network
        !            34: **             code (if it cares).
        !            35: **     makeconnection(host, port, outfile, infile)
        !            36: **             Make a connection to the named host on the given
        !            37: **             port.  Set *outfile and *infile to the files
        !            38: **             appropriate for communication.  Returns zero on
        !            39: **             success, else an exit status describing the
        !            40: **             error.
        !            41: **
        !            42: **     The semantics of both of these should be clean.
        !            43: */
        !            44: /*
        !            45: **  GETREQUESTS -- open mail IPC port and get requests.
        !            46: **
        !            47: **     Parameters:
        !            48: **             none.
        !            49: **
        !            50: **     Returns:
        !            51: **             none.
        !            52: **
        !            53: **     Side Effects:
        !            54: **             Waits until some interesting activity occurs.  When
        !            55: **             it does, a child is created to process it, and the
        !            56: **             parent waits for completion.  Return from this
        !            57: **             routine is always in the child.  The file pointers
        !            58: **             "InChannel" and "OutChannel" should be set to point
        !            59: **             to the communication channel.
        !            60: */
        !            61: 
        !            62: struct sockaddr_in     SendmailAddress;/* internet address of sendmail */
        !            63: int    DaemonSocket = -1;              /* fd describing socket */
        !            64: 
        !            65: getrequests()
        !            66: {
        !            67:        int t;
        !            68:        union wait status;
        !            69:        register struct servent *sp;
        !            70: 
        !            71:        /*
        !            72:        **  Set up the address for the mailer.
        !            73:        */
        !            74: 
        !            75:        sp = getservbyname("smtp", "tcp");
        !            76:        if (sp == NULL)
        !            77:        {
        !            78:                syserr("server \"smtp\" unknown");
        !            79:                goto severe;
        !            80:        }
        !            81:        SendmailAddress.sin_family = AF_INET;
        !            82:        SendmailAddress.sin_addr.s_addr = INADDR_ANY;
        !            83:        SendmailAddress.sin_port = sp->s_port;
        !            84: 
        !            85:        /*
        !            86:        **  Try to actually open the connection.
        !            87:        */
        !            88: 
        !            89: # ifdef DEBUG
        !            90:        if (tTd(15, 1))
        !            91:                printf("getrequests: port 0x%x\n", SendmailAddress.sin_port);
        !            92: # endif DEBUG
        !            93: 
        !            94:        /* get a socket for the SMTP connection */
        !            95:        DaemonSocket = socket(AF_INET, SOCK_STREAM, 0, 0);
        !            96:        if (DaemonSocket < 0)
        !            97:        {
        !            98:                /* probably another daemon already */
        !            99:                syserr("getrequests: can't create socket");
        !           100:          severe:
        !           101: # ifdef LOG
        !           102:                if (LogLevel > 0)
        !           103:                        syslog(LOG_SALERT, "cannot get connection");
        !           104: # endif LOG
        !           105:                finis();
        !           106:        }
        !           107: 
        !           108: #ifdef DEBUG
        !           109:        /* turn on network debugging? */
        !           110:        if (tTd(15, 15))
        !           111:                (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, 0, 0);
        !           112: #endif DEBUG
        !           113: 
        !           114:        if (bind(DaemonSocket, &SendmailAddress, sizeof SendmailAddress, 0) < 0)
        !           115:        {
        !           116:                syserr("getrequests: cannot bind");
        !           117:                (void) close(DaemonSocket);
        !           118:                goto severe;
        !           119:        }
        !           120:        listen(DaemonSocket, 10);
        !           121: 
        !           122: # ifdef DEBUG
        !           123:        if (tTd(15, 1))
        !           124:                printf("getrequests: %d\n", DaemonSocket);
        !           125: # endif DEBUG
        !           126: 
        !           127:        for (;;)
        !           128:        {
        !           129:                register int pid;
        !           130:                auto int lotherend;
        !           131:                struct sockaddr_in otherend;
        !           132:                extern int RefuseLA;
        !           133: 
        !           134:                /* see if we are rejecting connections */
        !           135:                while (getla() > RefuseLA)
        !           136:                        sleep(5);
        !           137: 
        !           138:                /* wait for a connection */
        !           139:                do
        !           140:                {
        !           141:                        errno = 0;
        !           142:                        lotherend = sizeof otherend;
        !           143:                        t = accept(DaemonSocket, &otherend, &lotherend, 0);
        !           144:                } while (t < 0 && errno == EINTR);
        !           145:                if (t < 0)
        !           146:                {
        !           147:                        syserr("getrequests: accept");
        !           148:                        sleep(5);
        !           149:                        continue;
        !           150:                }
        !           151: 
        !           152:                /*
        !           153:                **  Create a subprocess to process the mail.
        !           154:                */
        !           155: 
        !           156: # ifdef DEBUG
        !           157:                if (tTd(15, 2))
        !           158:                        printf("getrequests: forking (fd = %d)\n", t);
        !           159: # endif DEBUG
        !           160: 
        !           161:                pid = fork();
        !           162:                if (pid < 0)
        !           163:                {
        !           164:                        syserr("daemon: cannot fork");
        !           165:                        sleep(10);
        !           166:                        (void) close(t);
        !           167:                        continue;
        !           168:                }
        !           169: 
        !           170:                if (pid == 0)
        !           171:                {
        !           172:                        extern struct hostent *gethostbyaddr();
        !           173:                        register struct hostent *hp;
        !           174:                        extern char *RealHostName;      /* srvrsmtp.c */
        !           175:                        char buf[MAXNAME];
        !           176: 
        !           177:                        /*
        !           178:                        **  CHILD -- return to caller.
        !           179:                        **      Collect verified idea of sending host.
        !           180:                        **      Verify calling user id if possible here.
        !           181:                        */
        !           182: 
        !           183:                        /* determine host name */
        !           184:                        hp = gethostbyaddr(&otherend.sin_addr, sizeof otherend.sin_addr, AF_INET);
        !           185:                        if (hp != NULL)
        !           186:                                (void) sprintf(buf, "%s.ARPA", hp->h_name);
        !           187:                        else
        !           188:                                /* this should produce a dotted quad */
        !           189:                                (void) sprintf(buf, "%lx", otherend.sin_addr.s_addr);
        !           190:                        RealHostName = newstr(buf);
        !           191: 
        !           192:                        (void) close(DaemonSocket);
        !           193:                        InChannel = fdopen(t, "r");
        !           194:                        OutChannel = fdopen(t, "w");
        !           195: # ifdef DEBUG
        !           196:                        if (tTd(15, 2))
        !           197:                                printf("getreq: returning\n");
        !           198: # endif DEBUG
        !           199: # ifdef LOG
        !           200:                        if (LogLevel > 11)
        !           201:                                syslog(LOG_DEBUG, "connected, pid=%d", getpid());
        !           202: # endif LOG
        !           203:                        return;
        !           204:                }
        !           205: 
        !           206:                /*
        !           207:                **  PARENT -- wait for child to terminate.
        !           208:                **      Perhaps we should allow concurrent processing?
        !           209:                */
        !           210: 
        !           211: # ifdef DEBUG
        !           212:                if (tTd(15, 2))
        !           213:                {
        !           214:                        sleep(2);
        !           215:                        printf("getreq: parent waiting\n");
        !           216:                }
        !           217: # endif DEBUG
        !           218: 
        !           219:                /* close the port so that others will hang (for a while) */
        !           220:                (void) close(t);
        !           221: 
        !           222:                /* pick up old zombies */
        !           223:                while (wait3(&status, WNOHANG, 0) > 0)
        !           224:                        continue;
        !           225:        }
        !           226:        /*NOTREACHED*/
        !           227: }
        !           228: /*
        !           229: **  CLRDAEMON -- reset the daemon connection
        !           230: **
        !           231: **     Parameters:
        !           232: **             none.
        !           233: **
        !           234: **     Returns:
        !           235: **             none.
        !           236: **
        !           237: **     Side Effects:
        !           238: **             releases any resources used by the passive daemon.
        !           239: */
        !           240: 
        !           241: clrdaemon()
        !           242: {
        !           243:        if (DaemonSocket >= 0)
        !           244:                (void) close(DaemonSocket);
        !           245:        DaemonSocket = -1;
        !           246: }
        !           247: /*
        !           248: **  MAKECONNECTION -- make a connection to an SMTP socket on another machine.
        !           249: **
        !           250: **     Parameters:
        !           251: **             host -- the name of the host.
        !           252: **             port -- the port number to connect to.
        !           253: **             outfile -- a pointer to a place to put the outfile
        !           254: **                     descriptor.
        !           255: **             infile -- ditto for infile.
        !           256: **
        !           257: **     Returns:
        !           258: **             An exit code telling whether the connection could be
        !           259: **                     made and if not why not.
        !           260: **
        !           261: **     Side Effects:
        !           262: **             none.
        !           263: */
        !           264: 
        !           265: makeconnection(host, port, outfile, infile)
        !           266:        char *host;
        !           267:        u_short port;
        !           268:        FILE **outfile;
        !           269:        FILE **infile;
        !           270: {
        !           271:        register int s;
        !           272: 
        !           273:        /*
        !           274:        **  Set up the address for the mailer.
        !           275:        **      Accept "[a.b.c.d]" syntax for host name.
        !           276:        */
        !           277: 
        !           278:        if (host[0] == '[')
        !           279:        {
        !           280:                long hid;
        !           281:                register char *p = index(host, ']');
        !           282: 
        !           283:                if (p != NULL)
        !           284:                {
        !           285:                        *p = '\0';
        !           286:                        hid = inet_addr(&host[1]);
        !           287:                        *p = ']';
        !           288:                }
        !           289:                if (p == NULL || hid == -1)
        !           290:                {
        !           291:                        usrerr("Invalid numeric domain spec \"%s\"", host);
        !           292:                        return (EX_NOHOST);
        !           293:                }
        !           294:                SendmailAddress.sin_addr.s_addr = hid;
        !           295:        }
        !           296:        else
        !           297:        {
        !           298:                register struct hostent *hp = gethostbyname(host);
        !           299: 
        !           300:                if (hp == NULL)
        !           301:                        return (EX_NOHOST);
        !           302:                bmove(hp->h_addr, (char *) &SendmailAddress.sin_addr, hp->h_length);
        !           303:        }
        !           304: 
        !           305:        /*
        !           306:        **  Determine the port number.
        !           307:        */
        !           308: 
        !           309:        if (port != 0)
        !           310:                SendmailAddress.sin_port = htons(port);
        !           311:        else
        !           312:        {
        !           313:                register struct servent *sp = getservbyname("smtp", "tcp");
        !           314: 
        !           315:                if (sp == NULL)
        !           316:                {
        !           317:                        syserr("makeconnection: server \"smtp\" unknown");
        !           318:                        return (EX_OSFILE);
        !           319:                }
        !           320:                SendmailAddress.sin_port = sp->s_port;
        !           321:        }
        !           322: 
        !           323:        /*
        !           324:        **  Try to actually open the connection.
        !           325:        */
        !           326: 
        !           327: # ifdef DEBUG
        !           328:        if (tTd(16, 1))
        !           329:                printf("makeconnection (%s)\n", host);
        !           330: # endif DEBUG
        !           331: 
        !           332:        s = socket(AF_INET, SOCK_STREAM, 0, 0);
        !           333:        if (s < 0)
        !           334:        {
        !           335:                syserr("makeconnection: no socket");
        !           336:                goto failure;
        !           337:        }
        !           338: 
        !           339: # ifdef DEBUG
        !           340:        if (tTd(16, 1))
        !           341:                printf("makeconnection: %d\n", s);
        !           342: 
        !           343:        /* turn on network debugging? */
        !           344:        if (tTd(16, 14))
        !           345:                (void) setsockopt(s, SOL_SOCKET, SO_DEBUG, 0, 0);
        !           346: # endif DEBUG
        !           347:        (void) fflush(CurEnv->e_xfp);                   /* for debugging */
        !           348:        errno = 0;                                      /* for debugging */
        !           349:        SendmailAddress.sin_family = AF_INET;
        !           350:        if (connect(s, &SendmailAddress, sizeof SendmailAddress, 0) < 0)
        !           351:        {
        !           352:                /* failure, decide if temporary or not */
        !           353:        failure:
        !           354:                switch (errno)
        !           355:                {
        !           356:                  case EISCONN:
        !           357:                  case ETIMEDOUT:
        !           358:                  case EINPROGRESS:
        !           359:                  case EALREADY:
        !           360:                  case EADDRINUSE:
        !           361:                  case EHOSTDOWN:
        !           362:                  case ENETDOWN:
        !           363:                  case ENETRESET:
        !           364:                  case ENOBUFS:
        !           365:                  case ECONNREFUSED:
        !           366:                  case ECONNRESET:
        !           367:                  case EHOSTUNREACH:
        !           368:                  case ENETUNREACH:
        !           369:                        /* there are others, I'm sure..... */
        !           370:                        return (EX_TEMPFAIL);
        !           371: 
        !           372:                  case EPERM:
        !           373:                        /* why is this happening? */
        !           374:                        syserr("makeconnection: funny failure, addr=%lx, port=%x",
        !           375:                                SendmailAddress.sin_addr.s_addr, SendmailAddress.sin_port);
        !           376:                        return (EX_TEMPFAIL);
        !           377: 
        !           378:                  default:
        !           379:                        return (EX_UNAVAILABLE);
        !           380:                }
        !           381:        }
        !           382: 
        !           383:        /* connection ok, put it into canonical form */
        !           384:        *outfile = fdopen(s, "w");
        !           385:        *infile = fdopen(s, "r");
        !           386: 
        !           387:        return (EX_OK);
        !           388: }
        !           389: /*
        !           390: **  MYHOSTNAME -- return the name of this host.
        !           391: **
        !           392: **     Parameters:
        !           393: **             hostbuf -- a place to return the name of this host.
        !           394: **             size -- the size of hostbuf.
        !           395: **
        !           396: **     Returns:
        !           397: **             A list of aliases for this host.
        !           398: **
        !           399: **     Side Effects:
        !           400: **             none.
        !           401: */
        !           402: 
        !           403: char **
        !           404: myhostname(hostbuf, size)
        !           405:        char hostbuf[];
        !           406:        int size;
        !           407: {
        !           408:        extern struct hostent *gethostbyname();
        !           409:        struct hostent *hp;
        !           410:        auto int i = size;
        !           411: 
        !           412:        gethostname(hostbuf, &i);
        !           413:        hp = gethostbyname(hostbuf);
        !           414:        if (hp != NULL)
        !           415:                return (hp->h_aliases);
        !           416:        else
        !           417:                return (NULL);
        !           418: }
        !           419: 
        !           420: # else DAEMON
        !           421: 
        !           422: /*
        !           423: **  MYHOSTNAME -- stub version for case of no daemon code.
        !           424: **
        !           425: **     Can't convert to upper case here because might be a UUCP name.
        !           426: **
        !           427: **     Mark, you can change this to be anything you want......
        !           428: */
        !           429: 
        !           430: char **
        !           431: myhostname(hostbuf, size)
        !           432:        char hostbuf[];
        !           433:        int size;
        !           434: {
        !           435:        register FILE *f;
        !           436: 
        !           437:        hostbuf[0] = '\0';
        !           438:        f = fopen("/usr/include/whoami", "r");
        !           439:        if (f != NULL)
        !           440:        {
        !           441:                (void) fgets(hostbuf, size, f);
        !           442:                fixcrlf(hostbuf, TRUE);
        !           443:                (void) fclose(f);
        !           444:        }
        !           445:        return (NULL);
        !           446: }
        !           447: 
        !           448: #endif DAEMON

unix.superglobalmegacorp.com

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