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

1.1     ! root        1: /*
        !             2: **  Sendmail
        !             3: **  Copyright (c) 1983  Eric P. Allman
        !             4: **  Berkeley, California
        !             5: **
        !             6: **  Copyright (c) 1983 Regents of the University of California.
        !             7: **  All rights reserved.  The Berkeley software License Agreement
        !             8: **  specifies the terms and conditions for redistribution.
        !             9: */
        !            10: 
        !            11: 
        !            12: # include <errno.h>
        !            13: # include "sendmail.h"
        !            14: 
        !            15: # ifndef DAEMON
        !            16: # ifndef lint
        !            17: static char    SccsId[] = "@(#)daemon.c        5.19 (Berkeley) 5/6/86  (w/o daemon mode)";
        !            18: # endif not lint
        !            19: # else
        !            20: 
        !            21: # include <netdb.h>
        !            22: # include <sys/signal.h>
        !            23: # include <sys/wait.h>
        !            24: # include <sys/time.h>
        !            25: # include <sys/resource.h>
        !            26: 
        !            27: # ifndef lint
        !            28: static char    SccsId[] = "@(#)daemon.c        5.19 (Berkeley) 5/6/86 (with daemon mode)";
        !            29: # endif not lint
        !            30: 
        !            31: /*
        !            32: **  DAEMON.C -- routines to use when running as a daemon.
        !            33: **
        !            34: **     This entire file is highly dependent on the 4.2 BSD
        !            35: **     interprocess communication primitives.  No attempt has
        !            36: **     been made to make this file portable to Version 7,
        !            37: **     Version 6, MPX files, etc.  If you should try such a
        !            38: **     thing yourself, I recommend chucking the entire file
        !            39: **     and starting from scratch.  Basic semantics are:
        !            40: **
        !            41: **     getrequests()
        !            42: **             Opens a port and initiates a connection.
        !            43: **             Returns in a child.  Must set InChannel and
        !            44: **             OutChannel appropriately.
        !            45: **     clrdaemon()
        !            46: **             Close any open files associated with getting
        !            47: **             the connection; this is used when running the queue,
        !            48: **             etc., to avoid having extra file descriptors during
        !            49: **             the queue run and to avoid confusing the network
        !            50: **             code (if it cares).
        !            51: **     makeconnection(host, port, outfile, infile)
        !            52: **             Make a connection to the named host on the given
        !            53: **             port.  Set *outfile and *infile to the files
        !            54: **             appropriate for communication.  Returns zero on
        !            55: **             success, else an exit status describing the
        !            56: **             error.
        !            57: **     maphostname(hbuf, hbufsize)
        !            58: **             Convert the entry in hbuf into a canonical form.  It
        !            59: **             may not be larger than hbufsize.
        !            60: */
        !            61: /*
        !            62: **  GETREQUESTS -- open mail IPC port and get requests.
        !            63: **
        !            64: **     Parameters:
        !            65: **             none.
        !            66: **
        !            67: **     Returns:
        !            68: **             none.
        !            69: **
        !            70: **     Side Effects:
        !            71: **             Waits until some interesting activity occurs.  When
        !            72: **             it does, a child is created to process it, and the
        !            73: **             parent waits for completion.  Return from this
        !            74: **             routine is always in the child.  The file pointers
        !            75: **             "InChannel" and "OutChannel" should be set to point
        !            76: **             to the communication channel.
        !            77: */
        !            78: 
        !            79: struct sockaddr_in     SendmailAddress;/* internet address of sendmail */
        !            80: 
        !            81: int    DaemonSocket    = -1;           /* fd describing socket */
        !            82: char   *NetName;                       /* name of home (local?) network */
        !            83: 
        !            84: getrequests()
        !            85: {
        !            86:        int t;
        !            87:        register struct servent *sp;
        !            88:        int on = 1;
        !            89:        extern reapchild();
        !            90: 
        !            91:        /*
        !            92:        **  Set up the address for the mailer.
        !            93:        */
        !            94: 
        !            95:        sp = getservbyname("smtp", "tcp");
        !            96:        if (sp == NULL)
        !            97:        {
        !            98:                syserr("server \"smtp\" unknown");
        !            99:                goto severe;
        !           100:        }
        !           101:        SendmailAddress.sin_family = AF_INET;
        !           102:        SendmailAddress.sin_addr.s_addr = INADDR_ANY;
        !           103:        SendmailAddress.sin_port = sp->s_port;
        !           104: 
        !           105:        /*
        !           106:        **  Try to actually open the connection.
        !           107:        */
        !           108: 
        !           109: # ifdef DEBUG
        !           110:        if (tTd(15, 1))
        !           111:                printf("getrequests: port 0x%x\n", SendmailAddress.sin_port);
        !           112: # endif DEBUG
        !           113: 
        !           114:        /* get a socket for the SMTP connection */
        !           115:        DaemonSocket = socket(AF_INET, SOCK_STREAM, 0);
        !           116:        if (DaemonSocket < 0)
        !           117:        {
        !           118:                /* probably another daemon already */
        !           119:                syserr("getrequests: can't create socket");
        !           120:          severe:
        !           121: # ifdef LOG
        !           122:                if (LogLevel > 0)
        !           123:                        syslog(LOG_ALERT, "cannot get connection");
        !           124: # endif LOG
        !           125:                finis();
        !           126:        }
        !           127: 
        !           128: #ifdef DEBUG
        !           129:        /* turn on network debugging? */
        !           130:        if (tTd(15, 15))
        !           131:                (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on);
        !           132: #endif DEBUG
        !           133: 
        !           134:        (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof on);
        !           135:        (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof on);
        !           136: 
        !           137:        if (bind(DaemonSocket, &SendmailAddress, sizeof SendmailAddress) < 0)
        !           138:        {
        !           139:                syserr("getrequests: cannot bind");
        !           140:                (void) close(DaemonSocket);
        !           141:                goto severe;
        !           142:        }
        !           143:        if (listen(DaemonSocket, 10) < 0)
        !           144:        {
        !           145:                syserr("getrequests: cannot listen");
        !           146:                (void) close(DaemonSocket);
        !           147:                goto severe;
        !           148:        }
        !           149: 
        !           150:        (void) signal(SIGCHLD, reapchild);
        !           151: 
        !           152: # ifdef DEBUG
        !           153:        if (tTd(15, 1))
        !           154:                printf("getrequests: %d\n", DaemonSocket);
        !           155: # endif DEBUG
        !           156: 
        !           157:        for (;;)
        !           158:        {
        !           159:                register int pid;
        !           160:                auto int lotherend;
        !           161:                struct sockaddr_in otherend;
        !           162:                extern int RefuseLA;
        !           163: 
        !           164:                /* see if we are rejecting connections */
        !           165:                while (getla() > RefuseLA)
        !           166:                        sleep(5);
        !           167: 
        !           168:                /* wait for a connection */
        !           169:                do
        !           170:                {
        !           171:                        errno = 0;
        !           172:                        lotherend = sizeof otherend;
        !           173:                        t = accept(DaemonSocket, &otherend, &lotherend);
        !           174:                } while (t < 0 && errno == EINTR);
        !           175:                if (t < 0)
        !           176:                {
        !           177:                        syserr("getrequests: accept");
        !           178:                        sleep(5);
        !           179:                        continue;
        !           180:                }
        !           181: 
        !           182:                /*
        !           183:                **  Create a subprocess to process the mail.
        !           184:                */
        !           185: 
        !           186: # ifdef DEBUG
        !           187:                if (tTd(15, 2))
        !           188:                        printf("getrequests: forking (fd = %d)\n", t);
        !           189: # endif DEBUG
        !           190: 
        !           191:                pid = fork();
        !           192:                if (pid < 0)
        !           193:                {
        !           194:                        syserr("daemon: cannot fork");
        !           195:                        sleep(10);
        !           196:                        (void) close(t);
        !           197:                        continue;
        !           198:                }
        !           199: 
        !           200:                if (pid == 0)
        !           201:                {
        !           202:                        extern struct hostent *gethostbyaddr();
        !           203:                        register struct hostent *hp;
        !           204:                        char buf[MAXNAME];
        !           205: 
        !           206:                        /*
        !           207:                        **  CHILD -- return to caller.
        !           208:                        **      Collect verified idea of sending host.
        !           209:                        **      Verify calling user id if possible here.
        !           210:                        */
        !           211: 
        !           212:                        (void) signal(SIGCHLD, SIG_DFL);
        !           213: 
        !           214:                        /* determine host name */
        !           215:                        hp = gethostbyaddr((char *) &otherend.sin_addr, sizeof otherend.sin_addr, AF_INET);
        !           216:                        if (hp != NULL)
        !           217:                        {
        !           218:                                (void) strcpy(buf, hp->h_name);
        !           219:                                if (NetName != NULL && NetName[0] != '\0' &&
        !           220:                                    index(hp->h_name, '.') == NULL)
        !           221:                                {
        !           222:                                        (void) strcat(buf, ".");
        !           223:                                        (void) strcat(buf, NetName);
        !           224:                                }
        !           225:                        }
        !           226:                        else
        !           227:                        {
        !           228:                                extern char *inet_ntoa();
        !           229: 
        !           230:                                /* produce a dotted quad */
        !           231:                                (void) sprintf(buf, "[%s]",
        !           232:                                        inet_ntoa(otherend.sin_addr));
        !           233:                        }
        !           234: 
        !           235:                        /* should we check for illegal connection here? XXX */
        !           236: 
        !           237:                        RealHostName = newstr(buf);
        !           238: 
        !           239:                        (void) close(DaemonSocket);
        !           240:                        InChannel = fdopen(t, "r");
        !           241:                        OutChannel = fdopen(dup(t), "w");
        !           242: # ifdef DEBUG
        !           243:                        if (tTd(15, 2))
        !           244:                                printf("getreq: returning\n");
        !           245: # endif DEBUG
        !           246: # ifdef LOG
        !           247:                        if (LogLevel > 11)
        !           248:                                syslog(LOG_DEBUG, "connected, pid=%d", getpid());
        !           249: # endif LOG
        !           250:                        return;
        !           251:                }
        !           252: 
        !           253:                /* close the port so that others will hang (for a while) */
        !           254:                (void) close(t);
        !           255:        }
        !           256:        /*NOTREACHED*/
        !           257: }
        !           258: /*
        !           259: **  CLRDAEMON -- reset the daemon connection
        !           260: **
        !           261: **     Parameters:
        !           262: **             none.
        !           263: **
        !           264: **     Returns:
        !           265: **             none.
        !           266: **
        !           267: **     Side Effects:
        !           268: **             releases any resources used by the passive daemon.
        !           269: */
        !           270: 
        !           271: clrdaemon()
        !           272: {
        !           273:        if (DaemonSocket >= 0)
        !           274:                (void) close(DaemonSocket);
        !           275:        DaemonSocket = -1;
        !           276: }
        !           277: /*
        !           278: **  MAKECONNECTION -- make a connection to an SMTP socket on another machine.
        !           279: **
        !           280: **     Parameters:
        !           281: **             host -- the name of the host.
        !           282: **             port -- the port number to connect to.
        !           283: **             outfile -- a pointer to a place to put the outfile
        !           284: **                     descriptor.
        !           285: **             infile -- ditto for infile.
        !           286: **
        !           287: **     Returns:
        !           288: **             An exit code telling whether the connection could be
        !           289: **                     made and if not why not.
        !           290: **
        !           291: **     Side Effects:
        !           292: **             none.
        !           293: */
        !           294: 
        !           295: int    h_errno;        /*this will go away when code implemented*/
        !           296: 
        !           297: makeconnection(host, port, outfile, infile)
        !           298:        char *host;
        !           299:        u_short port;
        !           300:        FILE **outfile;
        !           301:        FILE **infile;
        !           302: {
        !           303:        register int s;
        !           304:        int sav_errno;
        !           305: 
        !           306:        /*
        !           307:        **  Set up the address for the mailer.
        !           308:        **      Accept "[a.b.c.d]" syntax for host name.
        !           309:        */
        !           310: 
        !           311:        h_errno = 0;
        !           312:        errno = 0;
        !           313: 
        !           314:        if (host[0] == '[')
        !           315:        {
        !           316:                long hid;
        !           317:                register char *p = index(host, ']');
        !           318: 
        !           319:                if (p != NULL)
        !           320:                {
        !           321:                        *p = '\0';
        !           322:                        hid = inet_addr(&host[1]);
        !           323:                        *p = ']';
        !           324:                }
        !           325:                if (p == NULL || hid == -1)
        !           326:                {
        !           327:                        usrerr("Invalid numeric domain spec \"%s\"", host);
        !           328:                        return (EX_NOHOST);
        !           329:                }
        !           330:                SendmailAddress.sin_addr.s_addr = hid;
        !           331:        }
        !           332:        else
        !           333:        {
        !           334:                register struct hostent *hp = gethostbyname(host);
        !           335: 
        !           336:                if (hp == NULL)
        !           337:                {
        !           338:                        if (errno == ETIMEDOUT || h_errno == TRY_AGAIN)
        !           339:                                return (EX_TEMPFAIL);
        !           340: 
        !           341:                        /*
        !           342:                        **  XXX Should look for mail forwarder record here
        !           343:                        **  XXX if (h_errno == NO_ADDRESS).
        !           344:                        */
        !           345: 
        !           346:                        return (EX_NOHOST);
        !           347:                }
        !           348:                bcopy(hp->h_addr, (char *) &SendmailAddress.sin_addr, hp->h_length);
        !           349:        }
        !           350: 
        !           351:        /*
        !           352:        **  Determine the port number.
        !           353:        */
        !           354: 
        !           355:        if (port != 0)
        !           356:                SendmailAddress.sin_port = htons(port);
        !           357:        else
        !           358:        {
        !           359:                register struct servent *sp = getservbyname("smtp", "tcp");
        !           360: 
        !           361:                if (sp == NULL)
        !           362:                {
        !           363:                        syserr("makeconnection: server \"smtp\" unknown");
        !           364:                        return (EX_OSFILE);
        !           365:                }
        !           366:                SendmailAddress.sin_port = sp->s_port;
        !           367:        }
        !           368: 
        !           369:        /*
        !           370:        **  Try to actually open the connection.
        !           371:        */
        !           372: 
        !           373: # ifdef DEBUG
        !           374:        if (tTd(16, 1))
        !           375:                printf("makeconnection (%s)\n", host);
        !           376: # endif DEBUG
        !           377: 
        !           378:        s = socket(AF_INET, SOCK_STREAM, 0);
        !           379:        if (s < 0)
        !           380:        {
        !           381:                syserr("makeconnection: no socket");
        !           382:                sav_errno = errno;
        !           383:                goto failure;
        !           384:        }
        !           385: 
        !           386: # ifdef DEBUG
        !           387:        if (tTd(16, 1))
        !           388:                printf("makeconnection: %d\n", s);
        !           389: 
        !           390:        /* turn on network debugging? */
        !           391:        if (tTd(16, 14))
        !           392:        {
        !           393:                int on = 1;
        !           394:                (void) setsockopt(DaemonSocket, SOL_SOCKET, SO_DEBUG, (char *)&on, sizeof on);
        !           395:        }
        !           396: # endif DEBUG
        !           397:        (void) fflush(CurEnv->e_xfp);                   /* for debugging */
        !           398:        errno = 0;                                      /* for debugging */
        !           399:        SendmailAddress.sin_family = AF_INET;
        !           400:        if (connect(s, &SendmailAddress, sizeof SendmailAddress) < 0)
        !           401:        {
        !           402:                sav_errno = errno;
        !           403:                (void) close(s);
        !           404:                /* failure, decide if temporary or not */
        !           405:        failure:
        !           406:                switch (sav_errno)
        !           407:                {
        !           408:                  case EISCONN:
        !           409:                  case ETIMEDOUT:
        !           410:                  case EINPROGRESS:
        !           411:                  case EALREADY:
        !           412:                  case EADDRINUSE:
        !           413:                  case EHOSTDOWN:
        !           414:                  case ENETDOWN:
        !           415:                  case ENETRESET:
        !           416:                  case ENOBUFS:
        !           417:                  case ECONNREFUSED:
        !           418:                  case ECONNRESET:
        !           419:                  case EHOSTUNREACH:
        !           420:                  case ENETUNREACH:
        !           421:                        /* there are others, I'm sure..... */
        !           422:                        return (EX_TEMPFAIL);
        !           423: 
        !           424:                  case EPERM:
        !           425:                        /* why is this happening? */
        !           426:                        syserr("makeconnection: funny failure, addr=%lx, port=%x",
        !           427:                                SendmailAddress.sin_addr.s_addr, SendmailAddress.sin_port);
        !           428:                        return (EX_TEMPFAIL);
        !           429: 
        !           430:                  default:
        !           431:                        return (EX_UNAVAILABLE);
        !           432:                }
        !           433:        }
        !           434: 
        !           435:        /* connection ok, put it into canonical form */
        !           436:        *outfile = fdopen(s, "w");
        !           437:        *infile = fdopen(s, "r");
        !           438: 
        !           439:        return (EX_OK);
        !           440: }
        !           441: /*
        !           442: **  MYHOSTNAME -- return the name of this host.
        !           443: **
        !           444: **     Parameters:
        !           445: **             hostbuf -- a place to return the name of this host.
        !           446: **             size -- the size of hostbuf.
        !           447: **
        !           448: **     Returns:
        !           449: **             A list of aliases for this host.
        !           450: **
        !           451: **     Side Effects:
        !           452: **             none.
        !           453: */
        !           454: 
        !           455: char **
        !           456: myhostname(hostbuf, size)
        !           457:        char hostbuf[];
        !           458:        int size;
        !           459: {
        !           460:        extern struct hostent *gethostbyname();
        !           461:        struct hostent *hp;
        !           462: 
        !           463:        if (gethostname(hostbuf, size) < 0)
        !           464:        {
        !           465:                (void) strcpy(hostbuf, "localhost");
        !           466:        }
        !           467:        hp = gethostbyname(hostbuf);
        !           468:        if (hp != NULL)
        !           469:        {
        !           470:                (void) strcpy(hostbuf, hp->h_name);
        !           471:                return (hp->h_aliases);
        !           472:        }
        !           473:        else
        !           474:                return (NULL);
        !           475: }
        !           476: /*
        !           477: **  MAPHOSTNAME -- turn a hostname into canonical form
        !           478: **
        !           479: **     Parameters:
        !           480: **             hbuf -- a buffer containing a hostname.
        !           481: **             hbsize -- the size of hbuf.
        !           482: **
        !           483: **     Returns:
        !           484: **             none.
        !           485: **
        !           486: **     Side Effects:
        !           487: **             Looks up the host specified in hbuf.  If it is not
        !           488: **             the canonical name for that host, replace it with
        !           489: **             the canonical name.  If the name is unknown, or it
        !           490: **             is already the canonical name, leave it unchanged.
        !           491: */
        !           492: 
        !           493: maphostname(hbuf, hbsize)
        !           494:        char *hbuf;
        !           495:        int hbsize;
        !           496: {
        !           497:        register struct hostent *hp;
        !           498:        extern struct hostent *gethostbyname();
        !           499: 
        !           500:        /*
        !           501:        **  If first character is a bracket, then it is an address
        !           502:        **  lookup.  Address is copied into a temporary buffer to
        !           503:        **  strip the brackets and to preserve hbuf if address is
        !           504:        **  unknown.
        !           505:        */
        !           506: 
        !           507:        if (*hbuf == '[')
        !           508:        {
        !           509:                extern struct hostent *gethostbyaddr();
        !           510:                u_long in_addr;
        !           511:                char ptr[256];
        !           512:                char *bptr;
        !           513: 
        !           514:                (void) strcpy(ptr, hbuf);
        !           515:                bptr = index(ptr,']');
        !           516:                *bptr = '\0';
        !           517:                in_addr = inet_addr(&ptr[1]);
        !           518:                hp = gethostbyaddr((char *) &in_addr, sizeof(struct in_addr), AF_INET);
        !           519:                if (hp == NULL)
        !           520:                        return;
        !           521:        }
        !           522:        else
        !           523:        {
        !           524:                makelower(hbuf);
        !           525:                hp = gethostbyname(hbuf);
        !           526:        }
        !           527:        if (hp != NULL)
        !           528:        {
        !           529:                int i = strlen(hp->h_name);
        !           530: 
        !           531:                if (i >= hbsize)
        !           532:                        hp->h_name[--i] = '\0';
        !           533:                (void) strcpy(hbuf, hp->h_name);
        !           534:        }
        !           535: }
        !           536: 
        !           537: # else DAEMON
        !           538: /* code for systems without sophisticated networking */
        !           539: 
        !           540: /*
        !           541: **  MYHOSTNAME -- stub version for case of no daemon code.
        !           542: **
        !           543: **     Can't convert to upper case here because might be a UUCP name.
        !           544: **
        !           545: **     Mark, you can change this to be anything you want......
        !           546: */
        !           547: 
        !           548: char **
        !           549: myhostname(hostbuf, size)
        !           550:        char hostbuf[];
        !           551:        int size;
        !           552: {
        !           553:        register FILE *f;
        !           554: 
        !           555:        hostbuf[0] = '\0';
        !           556:        f = fopen("/usr/include/whoami", "r");
        !           557:        if (f != NULL)
        !           558:        {
        !           559:                (void) fgets(hostbuf, size, f);
        !           560:                fixcrlf(hostbuf, TRUE);
        !           561:                (void) fclose(f);
        !           562:        }
        !           563:        return (NULL);
        !           564: }
        !           565: /*
        !           566: **  MAPHOSTNAME -- turn a hostname into canonical form
        !           567: **
        !           568: **     Parameters:
        !           569: **             hbuf -- a buffer containing a hostname.
        !           570: **             hbsize -- the size of hbuf.
        !           571: **
        !           572: **     Returns:
        !           573: **             none.
        !           574: **
        !           575: **     Side Effects:
        !           576: **             Looks up the host specified in hbuf.  If it is not
        !           577: **             the canonical name for that host, replace it with
        !           578: **             the canonical name.  If the name is unknown, or it
        !           579: **             is already the canonical name, leave it unchanged.
        !           580: */
        !           581: 
        !           582: /*ARGSUSED*/
        !           583: maphostname(hbuf, hbsize)
        !           584:        char *hbuf;
        !           585:        int hbsize;
        !           586: {
        !           587:        return;
        !           588: }
        !           589: 
        !           590: #endif DAEMON

unix.superglobalmegacorp.com

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