Annotation of 42BSD/usr.lib/sendmail/src/daemon.c, revision 1.1.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.