Annotation of 43BSD/usr.lib/sendmail/src/deliver.c, revision 1.1.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: #ifndef lint
                     12: static char    SccsId[] = "@(#)deliver.c       5.10 (Berkeley) 3/2/86";
                     13: #endif not lint
                     14: 
                     15: # include <signal.h>
                     16: # include <errno.h>
                     17: # include "sendmail.h"
                     18: # include <sys/stat.h>
                     19: # include <netdb.h>
                     20: 
                     21: /*
                     22: **  DELIVER -- Deliver a message to a list of addresses.
                     23: **
                     24: **     This routine delivers to everyone on the same host as the
                     25: **     user on the head of the list.  It is clever about mailers
                     26: **     that don't handle multiple users.  It is NOT guaranteed
                     27: **     that it will deliver to all these addresses however -- so
                     28: **     deliver should be called once for each address on the
                     29: **     list.
                     30: **
                     31: **     Parameters:
                     32: **             e -- the envelope to deliver.
                     33: **             firstto -- head of the address list to deliver to.
                     34: **
                     35: **     Returns:
                     36: **             zero -- successfully delivered.
                     37: **             else -- some failure, see ExitStat for more info.
                     38: **
                     39: **     Side Effects:
                     40: **             The standard input is passed off to someone.
                     41: */
                     42: 
                     43: deliver(e, firstto)
                     44:        register ENVELOPE *e;
                     45:        ADDRESS *firstto;
                     46: {
                     47:        char *host;                     /* host being sent to */
                     48:        char *user;                     /* user being sent to */
                     49:        char **pvp;
                     50:        register char **mvp;
                     51:        register char *p;
                     52:        register MAILER *m;             /* mailer for this recipient */
                     53:        ADDRESS *ctladdr;
                     54:        register ADDRESS *to = firstto;
                     55:        bool clever = FALSE;            /* running user smtp to this mailer */
                     56:        ADDRESS *tochain = NULL;        /* chain of users in this mailer call */
                     57:        register int rcode;             /* response code */
                     58:        char *pv[MAXPV+1];
                     59:        char tobuf[MAXLINE-50];         /* text line of to people */
                     60:        char buf[MAXNAME];
                     61:        char tfrombuf[MAXNAME];         /* translated from person */
                     62:        extern bool checkcompat();
                     63:        extern ADDRESS *getctladdr();
                     64:        extern char *remotename();
                     65: 
                     66:        errno = 0;
                     67:        if (bitset(QDONTSEND, to->q_flags))
                     68:                return (0);
                     69: 
                     70:        m = to->q_mailer;
                     71:        host = to->q_host;
                     72: 
                     73: # ifdef DEBUG
                     74:        if (tTd(10, 1))
                     75:                printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n",
                     76:                        m->m_mno, host, to->q_user);
                     77: # endif DEBUG
                     78: 
                     79:        /*
                     80:        **  If this mailer is expensive, and if we don't want to make
                     81:        **  connections now, just mark these addresses and return.
                     82:        **      This is useful if we want to batch connections to
                     83:        **      reduce load.  This will cause the messages to be
                     84:        **      queued up, and a daemon will come along to send the
                     85:        **      messages later.
                     86:        **              This should be on a per-mailer basis.
                     87:        */
                     88: 
                     89:        if (NoConnect && !QueueRun && bitnset(M_EXPENSIVE, m->m_flags) &&
                     90:            !Verbose)
                     91:        {
                     92:                for (; to != NULL; to = to->q_next)
                     93:                {
                     94:                        if (bitset(QDONTSEND, to->q_flags) || to->q_mailer != m)
                     95:                                continue;
                     96:                        to->q_flags |= QQUEUEUP|QDONTSEND;
                     97:                        e->e_to = to->q_paddr;
                     98:                        message(Arpa_Info, "queued");
                     99:                        if (LogLevel > 4)
                    100:                                logdelivery("queued");
                    101:                }
                    102:                e->e_to = NULL;
                    103:                return (0);
                    104:        }
                    105: 
                    106:        /*
                    107:        **  Do initial argv setup.
                    108:        **      Insert the mailer name.  Notice that $x expansion is
                    109:        **      NOT done on the mailer name.  Then, if the mailer has
                    110:        **      a picky -f flag, we insert it as appropriate.  This
                    111:        **      code does not check for 'pv' overflow; this places a
                    112:        **      manifest lower limit of 4 for MAXPV.
                    113:        **              The from address rewrite is expected to make
                    114:        **              the address relative to the other end.
                    115:        */
                    116: 
                    117:        /* rewrite from address, using rewriting rules */
                    118:        expand("\001f", buf, &buf[sizeof buf - 1], e);
                    119:        (void) strcpy(tfrombuf, remotename(buf, m, TRUE, TRUE));
                    120: 
                    121:        define('g', tfrombuf, e);               /* translated sender address */
                    122:        define('h', host, e);                   /* to host */
                    123:        Errors = 0;
                    124:        pvp = pv;
                    125:        *pvp++ = m->m_argv[0];
                    126: 
                    127:        /* insert -f or -r flag as appropriate */
                    128:        if (FromFlag && (bitnset(M_FOPT, m->m_flags) || bitnset(M_ROPT, m->m_flags)))
                    129:        {
                    130:                if (bitnset(M_FOPT, m->m_flags))
                    131:                        *pvp++ = "-f";
                    132:                else
                    133:                        *pvp++ = "-r";
                    134:                expand("\001g", buf, &buf[sizeof buf - 1], e);
                    135:                *pvp++ = newstr(buf);
                    136:        }
                    137: 
                    138:        /*
                    139:        **  Append the other fixed parts of the argv.  These run
                    140:        **  up to the first entry containing "$u".  There can only
                    141:        **  be one of these, and there are only a few more slots
                    142:        **  in the pv after it.
                    143:        */
                    144: 
                    145:        for (mvp = m->m_argv; (p = *++mvp) != NULL; )
                    146:        {
                    147:                while ((p = index(p, '\001')) != NULL)
                    148:                        if (*++p == 'u')
                    149:                                break;
                    150:                if (p != NULL)
                    151:                        break;
                    152: 
                    153:                /* this entry is safe -- go ahead and process it */
                    154:                expand(*mvp, buf, &buf[sizeof buf - 1], e);
                    155:                *pvp++ = newstr(buf);
                    156:                if (pvp >= &pv[MAXPV - 3])
                    157:                {
                    158:                        syserr("Too many parameters to %s before $u", pv[0]);
                    159:                        return (-1);
                    160:                }
                    161:        }
                    162: 
                    163:        /*
                    164:        **  If we have no substitution for the user name in the argument
                    165:        **  list, we know that we must supply the names otherwise -- and
                    166:        **  SMTP is the answer!!
                    167:        */
                    168: 
                    169:        if (*mvp == NULL)
                    170:        {
                    171:                /* running SMTP */
                    172: # ifdef SMTP
                    173:                clever = TRUE;
                    174:                *pvp = NULL;
                    175: # else SMTP
                    176:                /* oops!  we don't implement SMTP */
                    177:                syserr("SMTP style mailer");
                    178:                return (EX_SOFTWARE);
                    179: # endif SMTP
                    180:        }
                    181: 
                    182:        /*
                    183:        **  At this point *mvp points to the argument with $u.  We
                    184:        **  run through our address list and append all the addresses
                    185:        **  we can.  If we run out of space, do not fret!  We can
                    186:        **  always send another copy later.
                    187:        */
                    188: 
                    189:        tobuf[0] = '\0';
                    190:        e->e_to = tobuf;
                    191:        ctladdr = NULL;
                    192:        for (; to != NULL; to = to->q_next)
                    193:        {
                    194:                /* avoid sending multiple recipients to dumb mailers */
                    195:                if (tobuf[0] != '\0' && !bitnset(M_MUSER, m->m_flags))
                    196:                        break;
                    197: 
                    198:                /* if already sent or not for this host, don't send */
                    199:                if (bitset(QDONTSEND, to->q_flags) ||
                    200:                    strcmp(to->q_host, host) != 0 ||
                    201:                    to->q_mailer != firstto->q_mailer)
                    202:                        continue;
                    203: 
                    204:                /* avoid overflowing tobuf */
                    205:                if (sizeof tobuf - (strlen(to->q_paddr) + strlen(tobuf) + 2) < 0)
                    206:                        break;
                    207: 
                    208: # ifdef DEBUG
                    209:                if (tTd(10, 1))
                    210:                {
                    211:                        printf("\nsend to ");
                    212:                        printaddr(to, FALSE);
                    213:                }
                    214: # endif DEBUG
                    215: 
                    216:                /* compute effective uid/gid when sending */
                    217:                if (to->q_mailer == ProgMailer)
                    218:                        ctladdr = getctladdr(to);
                    219: 
                    220:                user = to->q_user;
                    221:                e->e_to = to->q_paddr;
                    222:                to->q_flags |= QDONTSEND;
                    223: 
                    224:                /*
                    225:                **  Check to see that these people are allowed to
                    226:                **  talk to each other.
                    227:                */
                    228: 
                    229:                if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize)
                    230:                {
                    231:                        usrerr("Message is too large; %ld bytes max", m->m_maxsize);
                    232:                        NoReturn = TRUE;
                    233:                        giveresponse(EX_UNAVAILABLE, m, e);
                    234:                        continue;
                    235:                }
                    236:                if (!checkcompat(to))
                    237:                {
                    238:                        giveresponse(EX_UNAVAILABLE, m, e);
                    239:                        continue;
                    240:                }
                    241: 
                    242:                /*
                    243:                **  Strip quote bits from names if the mailer is dumb
                    244:                **      about them.
                    245:                */
                    246: 
                    247:                if (bitnset(M_STRIPQ, m->m_flags))
                    248:                {
                    249:                        stripquotes(user, TRUE);
                    250:                        stripquotes(host, TRUE);
                    251:                }
                    252:                else
                    253:                {
                    254:                        stripquotes(user, FALSE);
                    255:                        stripquotes(host, FALSE);
                    256:                }
                    257: 
                    258:                /* hack attack -- delivermail compatibility */
                    259:                if (m == ProgMailer && *user == '|')
                    260:                        user++;
                    261: 
                    262:                /*
                    263:                **  If an error message has already been given, don't
                    264:                **      bother to send to this address.
                    265:                **
                    266:                **      >>>>>>>>>> This clause assumes that the local mailer
                    267:                **      >> NOTE >> cannot do any further aliasing; that
                    268:                **      >>>>>>>>>> function is subsumed by sendmail.
                    269:                */
                    270: 
                    271:                if (bitset(QBADADDR|QQUEUEUP, to->q_flags))
                    272:                        continue;
                    273: 
                    274:                /* save statistics.... */
                    275:                markstats(e, to);
                    276: 
                    277:                /*
                    278:                **  See if this user name is "special".
                    279:                **      If the user name has a slash in it, assume that this
                    280:                **      is a file -- send it off without further ado.  Note
                    281:                **      that this type of addresses is not processed along
                    282:                **      with the others, so we fudge on the To person.
                    283:                */
                    284: 
                    285:                if (m == LocalMailer)
                    286:                {
                    287:                        if (user[0] == '/')
                    288:                        {
                    289:                                rcode = mailfile(user, getctladdr(to));
                    290:                                giveresponse(rcode, m, e);
                    291:                                continue;
                    292:                        }
                    293:                }
                    294: 
                    295:                /*
                    296:                **  Address is verified -- add this user to mailer
                    297:                **  argv, and add it to the print list of recipients.
                    298:                */
                    299: 
                    300:                /* link together the chain of recipients */
                    301:                to->q_tchain = tochain;
                    302:                tochain = to;
                    303: 
                    304:                /* create list of users for error messages */
                    305:                (void) strcat(tobuf, ",");
                    306:                (void) strcat(tobuf, to->q_paddr);
                    307:                define('u', user, e);           /* to user */
                    308:                define('z', to->q_home, e);     /* user's home */
                    309: 
                    310:                /*
                    311:                **  Expand out this user into argument list.
                    312:                */
                    313: 
                    314:                if (!clever)
                    315:                {
                    316:                        expand(*mvp, buf, &buf[sizeof buf - 1], e);
                    317:                        *pvp++ = newstr(buf);
                    318:                        if (pvp >= &pv[MAXPV - 2])
                    319:                        {
                    320:                                /* allow some space for trailing parms */
                    321:                                break;
                    322:                        }
                    323:                }
                    324:        }
                    325: 
                    326:        /* see if any addresses still exist */
                    327:        if (tobuf[0] == '\0')
                    328:        {
                    329:                define('g', (char *) NULL, e);
                    330:                return (0);
                    331:        }
                    332: 
                    333:        /* print out messages as full list */
                    334:        e->e_to = tobuf + 1;
                    335: 
                    336:        /*
                    337:        **  Fill out any parameters after the $u parameter.
                    338:        */
                    339: 
                    340:        while (!clever && *++mvp != NULL)
                    341:        {
                    342:                expand(*mvp, buf, &buf[sizeof buf - 1], e);
                    343:                *pvp++ = newstr(buf);
                    344:                if (pvp >= &pv[MAXPV])
                    345:                        syserr("deliver: pv overflow after $u for %s", pv[0]);
                    346:        }
                    347:        *pvp++ = NULL;
                    348: 
                    349:        /*
                    350:        **  Call the mailer.
                    351:        **      The argument vector gets built, pipes
                    352:        **      are created as necessary, and we fork & exec as
                    353:        **      appropriate.
                    354:        **      If we are running SMTP, we just need to clean up.
                    355:        */
                    356: 
                    357:        message(Arpa_Info, "Connecting to %s.%s...", host, m->m_name);
                    358: 
                    359:        if (ctladdr == NULL)
                    360:                ctladdr = &e->e_from;
                    361: # ifdef SMTP
                    362:        if (clever)
                    363:        {
                    364:                /* send the initial SMTP protocol */
                    365:                rcode = smtpinit(m, pv);
                    366: 
                    367:                if (rcode == EX_OK)
                    368:                {
                    369:                        /* send the recipient list */
                    370:                        tobuf[0] = '\0';
                    371:                        for (to = tochain; to != NULL; to = to->q_tchain)
                    372:                        {
                    373:                                int i;
                    374: 
                    375:                                e->e_to = to->q_paddr;
                    376:                                i = smtprcpt(to, m);
                    377:                                if (i != EX_OK)
                    378:                                {
                    379:                                        markfailure(e, to, i);
                    380:                                        giveresponse(i, m, e);
                    381:                                }
                    382:                                else
                    383:                                {
                    384:                                        (void) strcat(tobuf, ",");
                    385:                                        (void) strcat(tobuf, to->q_paddr);
                    386:                                }
                    387:                        }
                    388: 
                    389:                        /* now send the data */
                    390:                        if (tobuf[0] == '\0')
                    391:                                e->e_to = NULL;
                    392:                        else
                    393:                        {
                    394:                                e->e_to = tobuf + 1;
                    395:                                rcode = smtpdata(m, e);
                    396:                        }
                    397: 
                    398:                        /* now close the connection */
                    399:                        smtpquit(m);
                    400:                }
                    401:        }
                    402:        else
                    403: # endif SMTP
                    404:                rcode = sendoff(e, m, pv, ctladdr);
                    405: 
                    406:        /*
                    407:        **  Do final status disposal.
                    408:        **      We check for something in tobuf for the SMTP case.
                    409:        **      If we got a temporary failure, arrange to queue the
                    410:        **              addressees.
                    411:        */
                    412: 
                    413:        if (tobuf[0] != '\0')
                    414:                giveresponse(rcode, m, e);
                    415:        if (rcode != EX_OK)
                    416:        {
                    417:                for (to = tochain; to != NULL; to = to->q_tchain)
                    418:                        markfailure(e, to, rcode);
                    419:        }
                    420: 
                    421:        errno = 0;
                    422:        define('g', (char *) NULL, e);
                    423:        return (rcode);
                    424: }
                    425: /*
                    426: **  MARKFAILURE -- mark a failure on a specific address.
                    427: **
                    428: **     Parameters:
                    429: **             e -- the envelope we are sending.
                    430: **             q -- the address to mark.
                    431: **             rcode -- the code signifying the particular failure.
                    432: **
                    433: **     Returns:
                    434: **             none.
                    435: **
                    436: **     Side Effects:
                    437: **             marks the address (and possibly the envelope) with the
                    438: **                     failure so that an error will be returned or
                    439: **                     the message will be queued, as appropriate.
                    440: */
                    441: 
                    442: markfailure(e, q, rcode)
                    443:        register ENVELOPE *e;
                    444:        register ADDRESS *q;
                    445:        int rcode;
                    446: {
                    447:        if (rcode == EX_OK)
                    448:                return;
                    449:        else if (rcode != EX_TEMPFAIL)
                    450:                q->q_flags |= QBADADDR;
                    451:        else if (curtime() > e->e_ctime + TimeOut)
                    452:        {
                    453:                extern char *pintvl();
                    454:                char buf[MAXLINE];
                    455: 
                    456:                if (!bitset(EF_TIMEOUT, e->e_flags))
                    457:                {
                    458:                        (void) sprintf(buf, "Cannot send message for %s",
                    459:                                pintvl(TimeOut, FALSE));
                    460:                        if (e->e_message != NULL)
                    461:                                free(e->e_message);
                    462:                        e->e_message = newstr(buf);
                    463:                        message(Arpa_Info, buf);
                    464:                }
                    465:                q->q_flags |= QBADADDR;
                    466:                e->e_flags |= EF_TIMEOUT;
                    467:        }
                    468:        else
                    469:                q->q_flags |= QQUEUEUP;
                    470: }
                    471: /*
                    472: **  DOFORK -- do a fork, retrying a couple of times on failure.
                    473: **
                    474: **     This MUST be a macro, since after a vfork we are running
                    475: **     two processes on the same stack!!!
                    476: **
                    477: **     Parameters:
                    478: **             none.
                    479: **
                    480: **     Returns:
                    481: **             From a macro???  You've got to be kidding!
                    482: **
                    483: **     Side Effects:
                    484: **             Modifies the ==> LOCAL <== variable 'pid', leaving:
                    485: **                     pid of child in parent, zero in child.
                    486: **                     -1 on unrecoverable error.
                    487: **
                    488: **     Notes:
                    489: **             I'm awfully sorry this looks so awful.  That's
                    490: **             vfork for you.....
                    491: */
                    492: 
                    493: # define NFORKTRIES    5
                    494: # ifdef VMUNIX
                    495: # define XFORK vfork
                    496: # else VMUNIX
                    497: # define XFORK fork
                    498: # endif VMUNIX
                    499: 
                    500: # define DOFORK(fORKfN) \
                    501: {\
                    502:        register int i;\
                    503: \
                    504:        for (i = NFORKTRIES; --i >= 0; )\
                    505:        {\
                    506:                pid = fORKfN();\
                    507:                if (pid >= 0)\
                    508:                        break;\
                    509:                if (i > 0)\
                    510:                        sleep((unsigned) NFORKTRIES - i);\
                    511:        }\
                    512: }
                    513: /*
                    514: **  DOFORK -- simple fork interface to DOFORK.
                    515: **
                    516: **     Parameters:
                    517: **             none.
                    518: **
                    519: **     Returns:
                    520: **             pid of child in parent.
                    521: **             zero in child.
                    522: **             -1 on error.
                    523: **
                    524: **     Side Effects:
                    525: **             returns twice, once in parent and once in child.
                    526: */
                    527: 
                    528: dofork()
                    529: {
                    530:        register int pid;
                    531: 
                    532:        DOFORK(fork);
                    533:        return (pid);
                    534: }
                    535: /*
                    536: **  SENDOFF -- send off call to mailer & collect response.
                    537: **
                    538: **     Parameters:
                    539: **             e -- the envelope to mail.
                    540: **             m -- mailer descriptor.
                    541: **             pvp -- parameter vector to send to it.
                    542: **             ctladdr -- an address pointer controlling the
                    543: **                     user/groupid etc. of the mailer.
                    544: **
                    545: **     Returns:
                    546: **             exit status of mailer.
                    547: **
                    548: **     Side Effects:
                    549: **             none.
                    550: */
                    551: 
                    552: sendoff(e, m, pvp, ctladdr)
                    553:        register ENVELOPE *e;
                    554:        MAILER *m;
                    555:        char **pvp;
                    556:        ADDRESS *ctladdr;
                    557: {
                    558:        auto FILE *mfile;
                    559:        auto FILE *rfile;
                    560:        register int i;
                    561:        int pid;
                    562: 
                    563:        /*
                    564:        **  Create connection to mailer.
                    565:        */
                    566: 
                    567:        pid = openmailer(m, pvp, ctladdr, FALSE, &mfile, &rfile);
                    568:        if (pid < 0)
                    569:                return (-1);
                    570: 
                    571:        /*
                    572:        **  Format and send message.
                    573:        */
                    574: 
                    575:        putfromline(mfile, m);
                    576:        (*e->e_puthdr)(mfile, m, e);
                    577:        putline("\n", mfile, m);
                    578:        (*e->e_putbody)(mfile, m, e);
                    579:        (void) fclose(mfile);
                    580: 
                    581:        i = endmailer(pid, pvp[0]);
                    582: 
                    583:        /* arrange a return receipt if requested */
                    584:        if (e->e_receiptto != NULL && bitnset(M_LOCAL, m->m_flags))
                    585:        {
                    586:                e->e_flags |= EF_SENDRECEIPT;
                    587:                /* do we want to send back more info? */
                    588:        }
                    589: 
                    590:        return (i);
                    591: }
                    592: /*
                    593: **  ENDMAILER -- Wait for mailer to terminate.
                    594: **
                    595: **     We should never get fatal errors (e.g., segmentation
                    596: **     violation), so we report those specially.  For other
                    597: **     errors, we choose a status message (into statmsg),
                    598: **     and if it represents an error, we print it.
                    599: **
                    600: **     Parameters:
                    601: **             pid -- pid of mailer.
                    602: **             name -- name of mailer (for error messages).
                    603: **
                    604: **     Returns:
                    605: **             exit code of mailer.
                    606: **
                    607: **     Side Effects:
                    608: **             none.
                    609: */
                    610: 
                    611: endmailer(pid, name)
                    612:        int pid;
                    613:        char *name;
                    614: {
                    615:        int st;
                    616: 
                    617:        /* in the IPC case there is nothing to wait for */
                    618:        if (pid == 0)
                    619:                return (EX_OK);
                    620: 
                    621:        /* wait for the mailer process to die and collect status */
                    622:        st = waitfor(pid);
                    623:        if (st == -1)
                    624:        {
                    625:                syserr("endmailer %s: wait", name);
                    626:                return (EX_SOFTWARE);
                    627:        }
                    628: 
                    629:        /* see if it died a horrid death */
                    630:        if ((st & 0377) != 0)
                    631:        {
                    632:                syserr("mailer %s died with signal %o", name, st);
                    633:                ExitStat = EX_TEMPFAIL;
                    634:                return (EX_TEMPFAIL);
                    635:        }
                    636: 
                    637:        /* normal death -- return status */
                    638:        st = (st >> 8) & 0377;
                    639:        return (st);
                    640: }
                    641: /*
                    642: **  OPENMAILER -- open connection to mailer.
                    643: **
                    644: **     Parameters:
                    645: **             m -- mailer descriptor.
                    646: **             pvp -- parameter vector to pass to mailer.
                    647: **             ctladdr -- controlling address for user.
                    648: **             clever -- create a full duplex connection.
                    649: **             pmfile -- pointer to mfile (to mailer) connection.
                    650: **             prfile -- pointer to rfile (from mailer) connection.
                    651: **
                    652: **     Returns:
                    653: **             pid of mailer ( > 0 ).
                    654: **             -1 on error.
                    655: **             zero on an IPC connection.
                    656: **
                    657: **     Side Effects:
                    658: **             creates a mailer in a subprocess.
                    659: */
                    660: 
                    661: openmailer(m, pvp, ctladdr, clever, pmfile, prfile)
                    662:        MAILER *m;
                    663:        char **pvp;
                    664:        ADDRESS *ctladdr;
                    665:        bool clever;
                    666:        FILE **pmfile;
                    667:        FILE **prfile;
                    668: {
                    669:        int pid;
                    670:        int mpvect[2];
                    671:        int rpvect[2];
                    672:        FILE *mfile;
                    673:        FILE *rfile;
                    674:        extern FILE *fdopen();
                    675: 
                    676: # ifdef DEBUG
                    677:        if (tTd(11, 1))
                    678:        {
                    679:                printf("openmailer:");
                    680:                printav(pvp);
                    681:        }
                    682: # endif DEBUG
                    683:        errno = 0;
                    684: 
                    685:        CurHostName = m->m_mailer;
                    686: 
                    687:        /*
                    688:        **  Deal with the special case of mail handled through an IPC
                    689:        **  connection.
                    690:        **      In this case we don't actually fork.  We must be
                    691:        **      running SMTP for this to work.  We will return a
                    692:        **      zero pid to indicate that we are running IPC.
                    693:        **  We also handle a debug version that just talks to stdin/out.
                    694:        */
                    695: 
                    696: #ifdef DEBUG
                    697:        /* check for Local Person Communication -- not for mortals!!! */
                    698:        if (strcmp(m->m_mailer, "[LPC]") == 0)
                    699:        {
                    700:                *pmfile = stdout;
                    701:                *prfile = stdin;
                    702:                return (0);
                    703:        }
                    704: #endif DEBUG
                    705: 
                    706:        if (strcmp(m->m_mailer, "[IPC]") == 0)
                    707:        {
                    708: #ifdef HOSTINFO
                    709:                register STAB *st;
                    710:                extern STAB *stab();
                    711: #endif HOSTINFO
                    712: #ifdef DAEMON
                    713:                register int i;
                    714:                register u_short port;
                    715: 
                    716:                CurHostName = pvp[1];
                    717:                if (!clever)
                    718:                        syserr("non-clever IPC");
                    719:                if (pvp[2] != NULL)
                    720:                        port = atoi(pvp[2]);
                    721:                else
                    722:                        port = 0;
                    723: #ifdef HOSTINFO
                    724:                /* see if we have already determined that this host is fried */
                    725:                st = stab(pvp[1], ST_HOST, ST_FIND);
                    726:                if (st == NULL || st->s_host.ho_exitstat == EX_OK)
                    727:                        i = makeconnection(pvp[1], port, pmfile, prfile);
                    728:                else
                    729:                {
                    730:                        i = st->s_host.ho_exitstat;
                    731:                        errno = st->s_host.ho_errno;
                    732:                }
                    733: #else HOSTINFO
                    734:                i = makeconnection(pvp[1], port, pmfile, prfile);
                    735: #endif HOSTINFO
                    736:                if (i != EX_OK)
                    737:                {
                    738: #ifdef HOSTINFO
                    739:                        /* enter status of this host */
                    740:                        if (st == NULL)
                    741:                                st = stab(pvp[1], ST_HOST, ST_ENTER);
                    742:                        st->s_host.ho_exitstat = i;
                    743:                        st->s_host.ho_errno = errno;
                    744: #endif HOSTINFO
                    745:                        ExitStat = i;
                    746:                        return (-1);
                    747:                }
                    748:                else
                    749:                        return (0);
                    750: #else DAEMON
                    751:                syserr("openmailer: no IPC");
                    752:                return (-1);
                    753: #endif DAEMON
                    754:        }
                    755: 
                    756:        /* create a pipe to shove the mail through */
                    757:        if (pipe(mpvect) < 0)
                    758:        {
                    759:                syserr("openmailer: pipe (to mailer)");
                    760:                return (-1);
                    761:        }
                    762: 
                    763: #ifdef SMTP
                    764:        /* if this mailer speaks smtp, create a return pipe */
                    765:        if (clever && pipe(rpvect) < 0)
                    766:        {
                    767:                syserr("openmailer: pipe (from mailer)");
                    768:                (void) close(mpvect[0]);
                    769:                (void) close(mpvect[1]);
                    770:                return (-1);
                    771:        }
                    772: #endif SMTP
                    773: 
                    774:        /*
                    775:        **  Actually fork the mailer process.
                    776:        **      DOFORK is clever about retrying.
                    777:        **
                    778:        **      Dispose of SIGCHLD signal catchers that may be laying
                    779:        **      around so that endmail will get it.
                    780:        */
                    781: 
                    782:        if (CurEnv->e_xfp != NULL)
                    783:                (void) fflush(CurEnv->e_xfp);           /* for debugging */
                    784:        (void) fflush(stdout);
                    785: # ifdef SIGCHLD
                    786:        (void) signal(SIGCHLD, SIG_DFL);
                    787: # endif SIGCHLD
                    788:        DOFORK(XFORK);
                    789:        /* pid is set by DOFORK */
                    790:        if (pid < 0)
                    791:        {
                    792:                /* failure */
                    793:                syserr("openmailer: cannot fork");
                    794:                (void) close(mpvect[0]);
                    795:                (void) close(mpvect[1]);
                    796: #ifdef SMTP
                    797:                if (clever)
                    798:                {
                    799:                        (void) close(rpvect[0]);
                    800:                        (void) close(rpvect[1]);
                    801:                }
                    802: #endif SMTP
                    803:                return (-1);
                    804:        }
                    805:        else if (pid == 0)
                    806:        {
                    807:                int i;
                    808:                extern int DtableSize;
                    809: 
                    810:                /* child -- set up input & exec mailer */
                    811:                /* make diagnostic output be standard output */
                    812:                (void) signal(SIGINT, SIG_IGN);
                    813:                (void) signal(SIGHUP, SIG_IGN);
                    814:                (void) signal(SIGTERM, SIG_DFL);
                    815: 
                    816:                /* arrange to filter standard & diag output of command */
                    817:                if (clever)
                    818:                {
                    819:                        (void) close(rpvect[0]);
                    820:                        (void) close(1);
                    821:                        (void) dup(rpvect[1]);
                    822:                        (void) close(rpvect[1]);
                    823:                }
                    824:                else if (OpMode == MD_SMTP || HoldErrs)
                    825:                {
                    826:                        /* put mailer output in transcript */
                    827:                        (void) close(1);
                    828:                        (void) dup(fileno(CurEnv->e_xfp));
                    829:                }
                    830:                (void) close(2);
                    831:                (void) dup(1);
                    832: 
                    833:                /* arrange to get standard input */
                    834:                (void) close(mpvect[1]);
                    835:                (void) close(0);
                    836:                if (dup(mpvect[0]) < 0)
                    837:                {
                    838:                        syserr("Cannot dup to zero!");
                    839:                        _exit(EX_OSERR);
                    840:                }
                    841:                (void) close(mpvect[0]);
                    842:                if (!bitnset(M_RESTR, m->m_flags))
                    843:                {
                    844:                        if (ctladdr == NULL || ctladdr->q_uid == 0)
                    845:                        {
                    846:                                (void) setgid(DefGid);
                    847:                                (void) setuid(DefUid);
                    848:                        }
                    849:                        else
                    850:                        {
                    851:                                (void) setgid(ctladdr->q_gid);
                    852:                                (void) setuid(ctladdr->q_uid);
                    853:                        }
                    854:                }
                    855: 
                    856:                /* arrange for all the files to be closed */
                    857:                for (i = 3; i < DtableSize; i++)
                    858: #ifdef FIOCLEX
                    859:                        (void) ioctl(i, FIOCLEX, 0);
                    860: #else FIOCLEX
                    861:                        (void) close(i);
                    862: #endif FIOCLEX
                    863: 
                    864:                /* try to execute the mailer */
                    865:                execve(m->m_mailer, pvp, UserEnviron);
                    866: 
                    867: #ifdef FIOCLEX
                    868:                syserr("Cannot exec %s", m->m_mailer);
                    869: #else FIOCLEX
                    870:                printf("Cannot exec '%s' errno=%d\n", m->m_mailer, errno);
                    871:                (void) fflush(stdout);
                    872: #endif FIOCLEX
                    873:                if (m == LocalMailer || errno == EIO || errno == EAGAIN ||
                    874:                    errno == ENOMEM || errno == EPROCLIM)
                    875:                        _exit(EX_TEMPFAIL);
                    876:                else
                    877:                        _exit(EX_UNAVAILABLE);
                    878:        }
                    879: 
                    880:        /*
                    881:        **  Set up return value.
                    882:        */
                    883: 
                    884:        (void) close(mpvect[0]);
                    885:        mfile = fdopen(mpvect[1], "w");
                    886:        if (clever)
                    887:        {
                    888:                (void) close(rpvect[1]);
                    889:                rfile = fdopen(rpvect[0], "r");
                    890:        }
                    891: 
                    892:        *pmfile = mfile;
                    893:        *prfile = rfile;
                    894: 
                    895:        return (pid);
                    896: }
                    897: /*
                    898: **  GIVERESPONSE -- Interpret an error response from a mailer
                    899: **
                    900: **     Parameters:
                    901: **             stat -- the status code from the mailer (high byte
                    902: **                     only; core dumps must have been taken care of
                    903: **                     already).
                    904: **             m -- the mailer descriptor for this mailer.
                    905: **
                    906: **     Returns:
                    907: **             none.
                    908: **
                    909: **     Side Effects:
                    910: **             Errors may be incremented.
                    911: **             ExitStat may be set.
                    912: */
                    913: 
                    914: giveresponse(stat, m, e)
                    915:        int stat;
                    916:        register MAILER *m;
                    917:        ENVELOPE *e;
                    918: {
                    919:        register char *statmsg;
                    920:        extern char *SysExMsg[];
                    921:        register int i;
                    922:        extern int N_SysEx;
                    923:        char buf[MAXLINE];
                    924: 
                    925: #ifdef lint
                    926:        if (m == NULL)
                    927:                return;
                    928: #endif lint
                    929: 
                    930:        /*
                    931:        **  Compute status message from code.
                    932:        */
                    933: 
                    934:        i = stat - EX__BASE;
                    935:        if (stat == 0)
                    936:                statmsg = "250 Sent";
                    937:        else if (i < 0 || i > N_SysEx)
                    938:        {
                    939:                (void) sprintf(buf, "554 unknown mailer error %d", stat);
                    940:                stat = EX_UNAVAILABLE;
                    941:                statmsg = buf;
                    942:        }
                    943:        else if (stat == EX_TEMPFAIL)
                    944:        {
                    945:                (void) strcpy(buf, SysExMsg[i]);
                    946:                if (h_errno == TRY_AGAIN)
                    947:                {
                    948:                        extern char *errstring();
                    949: 
                    950:                        statmsg = errstring(h_errno+MAX_ERRNO);
                    951:                }
                    952:                else
                    953:                {
                    954:                        if (errno != 0)
                    955:                        {
                    956:                                extern char *errstring();
                    957: 
                    958:                                statmsg = errstring(errno);
                    959:                        }
                    960:                        else
                    961:                        {
                    962: #ifdef SMTP
                    963:                                extern char SmtpError[];
                    964: 
                    965:                                statmsg = SmtpError;
                    966: #else SMTP
                    967:                                statmsg = NULL;
                    968: #endif SMTP
                    969:                        }
                    970:                }
                    971:                if (statmsg != NULL && statmsg[0] != '\0')
                    972:                {
                    973:                        (void) strcat(buf, ": ");
                    974:                        (void) strcat(buf, statmsg);
                    975:                }
                    976:                statmsg = buf;
                    977:        }
                    978:        else
                    979:        {
                    980:                statmsg = SysExMsg[i];
                    981:        }
                    982: 
                    983:        /*
                    984:        **  Print the message as appropriate
                    985:        */
                    986: 
                    987:        if (stat == EX_OK || stat == EX_TEMPFAIL)
                    988:                message(Arpa_Info, &statmsg[4]);
                    989:        else
                    990:        {
                    991:                Errors++;
                    992:                usrerr(statmsg);
                    993:        }
                    994: 
                    995:        /*
                    996:        **  Final cleanup.
                    997:        **      Log a record of the transaction.  Compute the new
                    998:        **      ExitStat -- if we already had an error, stick with
                    999:        **      that.
                   1000:        */
                   1001: 
                   1002:        if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2))
                   1003:                logdelivery(&statmsg[4]);
                   1004: 
                   1005:        if (stat != EX_TEMPFAIL)
                   1006:                setstat(stat);
                   1007:        if (stat != EX_OK)
                   1008:        {
                   1009:                if (e->e_message != NULL)
                   1010:                        free(e->e_message);
                   1011:                e->e_message = newstr(&statmsg[4]);
                   1012:        }
                   1013:        errno = 0;
                   1014:        h_errno = 0;
                   1015: }
                   1016: /*
                   1017: **  LOGDELIVERY -- log the delivery in the system log
                   1018: **
                   1019: **     Parameters:
                   1020: **             stat -- the message to print for the status
                   1021: **
                   1022: **     Returns:
                   1023: **             none
                   1024: **
                   1025: **     Side Effects:
                   1026: **             none
                   1027: */
                   1028: 
                   1029: logdelivery(stat)
                   1030:        char *stat;
                   1031: {
                   1032:        extern char *pintvl();
                   1033: 
                   1034: # ifdef LOG
                   1035:        syslog(LOG_INFO, "%s: to=%s, delay=%s, stat=%s", CurEnv->e_id,
                   1036:               CurEnv->e_to, pintvl(curtime() - CurEnv->e_ctime, TRUE), stat);
                   1037: # endif LOG
                   1038: }
                   1039: /*
                   1040: **  PUTFROMLINE -- output a UNIX-style from line (or whatever)
                   1041: **
                   1042: **     This can be made an arbitrary message separator by changing $l
                   1043: **
                   1044: **     One of the ugliest hacks seen by human eyes is contained herein:
                   1045: **     UUCP wants those stupid "remote from <host>" lines.  Why oh why
                   1046: **     does a well-meaning programmer such as myself have to deal with
                   1047: **     this kind of antique garbage????
                   1048: **
                   1049: **     Parameters:
                   1050: **             fp -- the file to output to.
                   1051: **             m -- the mailer describing this entry.
                   1052: **
                   1053: **     Returns:
                   1054: **             none
                   1055: **
                   1056: **     Side Effects:
                   1057: **             outputs some text to fp.
                   1058: */
                   1059: 
                   1060: putfromline(fp, m)
                   1061:        register FILE *fp;
                   1062:        register MAILER *m;
                   1063: {
                   1064:        char *template = "\001l\n";
                   1065:        char buf[MAXLINE];
                   1066: 
                   1067:        if (bitnset(M_NHDR, m->m_flags))
                   1068:                return;
                   1069: 
                   1070: # ifdef UGLYUUCP
                   1071:        if (bitnset(M_UGLYUUCP, m->m_flags))
                   1072:        {
                   1073:                char *bang;
                   1074:                char xbuf[MAXLINE];
                   1075: 
                   1076:                expand("\001g", buf, &buf[sizeof buf - 1], CurEnv);
                   1077:                bang = index(buf, '!');
                   1078:                if (bang == NULL)
                   1079:                        syserr("No ! in UUCP! (%s)", buf);
                   1080:                else
                   1081:                {
                   1082:                        *bang++ = '\0';
                   1083:                        (void) sprintf(xbuf, "From %s  \001d remote from %s\n", bang, buf);
                   1084:                        template = xbuf;
                   1085:                }
                   1086:        }
                   1087: # endif UGLYUUCP
                   1088:        expand(template, buf, &buf[sizeof buf - 1], CurEnv);
                   1089:        putline(buf, fp, m);
                   1090: }
                   1091: /*
                   1092: **  PUTBODY -- put the body of a message.
                   1093: **
                   1094: **     Parameters:
                   1095: **             fp -- file to output onto.
                   1096: **             m -- a mailer descriptor to control output format.
                   1097: **             e -- the envelope to put out.
                   1098: **
                   1099: **     Returns:
                   1100: **             none.
                   1101: **
                   1102: **     Side Effects:
                   1103: **             The message is written onto fp.
                   1104: */
                   1105: 
                   1106: putbody(fp, m, e)
                   1107:        FILE *fp;
                   1108:        MAILER *m;
                   1109:        register ENVELOPE *e;
                   1110: {
                   1111:        char buf[MAXLINE];
                   1112: 
                   1113:        /*
                   1114:        **  Output the body of the message
                   1115:        */
                   1116: 
                   1117:        if (e->e_dfp == NULL)
                   1118:        {
                   1119:                if (e->e_df != NULL)
                   1120:                {
                   1121:                        e->e_dfp = fopen(e->e_df, "r");
                   1122:                        if (e->e_dfp == NULL)
                   1123:                                syserr("Cannot open %s", e->e_df);
                   1124:                }
                   1125:                else
                   1126:                        putline("<<< No Message Collected >>>", fp, m);
                   1127:        }
                   1128:        if (e->e_dfp != NULL)
                   1129:        {
                   1130:                rewind(e->e_dfp);
                   1131:                while (!ferror(fp) && fgets(buf, sizeof buf, e->e_dfp) != NULL)
                   1132:                {
                   1133:                        if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) &&
                   1134:                            strncmp(buf, "From", 4) == 0)
                   1135:                                (void) putc('>', fp);
                   1136:                        putline(buf, fp, m);
                   1137:                }
                   1138: 
                   1139:                if (ferror(e->e_dfp))
                   1140:                {
                   1141:                        syserr("putbody: read error");
                   1142:                        ExitStat = EX_IOERR;
                   1143:                }
                   1144:        }
                   1145: 
                   1146:        (void) fflush(fp);
                   1147:        if (ferror(fp) && errno != EPIPE)
                   1148:        {
                   1149:                syserr("putbody: write error");
                   1150:                ExitStat = EX_IOERR;
                   1151:        }
                   1152:        errno = 0;
                   1153: }
                   1154: /*
                   1155: **  MAILFILE -- Send a message to a file.
                   1156: **
                   1157: **     If the file has the setuid/setgid bits set, but NO execute
                   1158: **     bits, sendmail will try to become the owner of that file
                   1159: **     rather than the real user.  Obviously, this only works if
                   1160: **     sendmail runs as root.
                   1161: **
                   1162: **     This could be done as a subordinate mailer, except that it
                   1163: **     is used implicitly to save messages in ~/dead.letter.  We
                   1164: **     view this as being sufficiently important as to include it
                   1165: **     here.  For example, if the system is dying, we shouldn't have
                   1166: **     to create another process plus some pipes to save the message.
                   1167: **
                   1168: **     Parameters:
                   1169: **             filename -- the name of the file to send to.
                   1170: **             ctladdr -- the controlling address header -- includes
                   1171: **                     the userid/groupid to be when sending.
                   1172: **
                   1173: **     Returns:
                   1174: **             The exit code associated with the operation.
                   1175: **
                   1176: **     Side Effects:
                   1177: **             none.
                   1178: */
                   1179: 
                   1180: mailfile(filename, ctladdr)
                   1181:        char *filename;
                   1182:        ADDRESS *ctladdr;
                   1183: {
                   1184:        register FILE *f;
                   1185:        register int pid;
                   1186: 
                   1187:        /*
                   1188:        **  Fork so we can change permissions here.
                   1189:        **      Note that we MUST use fork, not vfork, because of
                   1190:        **      the complications of calling subroutines, etc.
                   1191:        */
                   1192: 
                   1193:        DOFORK(fork);
                   1194: 
                   1195:        if (pid < 0)
                   1196:                return (EX_OSERR);
                   1197:        else if (pid == 0)
                   1198:        {
                   1199:                /* child -- actually write to file */
                   1200:                struct stat stb;
                   1201: 
                   1202:                (void) signal(SIGINT, SIG_DFL);
                   1203:                (void) signal(SIGHUP, SIG_DFL);
                   1204:                (void) signal(SIGTERM, SIG_DFL);
                   1205:                (void) umask(OldUmask);
                   1206:                if (stat(filename, &stb) < 0)
                   1207:                {
                   1208:                        errno = 0;
                   1209:                        stb.st_mode = 0666;
                   1210:                }
                   1211:                if (bitset(0111, stb.st_mode))
                   1212:                        exit(EX_CANTCREAT);
                   1213:                if (ctladdr == NULL)
                   1214:                        ctladdr = &CurEnv->e_from;
                   1215:                if (!bitset(S_ISGID, stb.st_mode) || setgid(stb.st_gid) < 0)
                   1216:                {
                   1217:                        if (ctladdr->q_uid == 0)
                   1218:                                (void) setgid(DefGid);
                   1219:                        else
                   1220:                                (void) setgid(ctladdr->q_gid);
                   1221:                }
                   1222:                if (!bitset(S_ISUID, stb.st_mode) || setuid(stb.st_uid) < 0)
                   1223:                {
                   1224:                        if (ctladdr->q_uid == 0)
                   1225:                                (void) setuid(DefUid);
                   1226:                        else
                   1227:                                (void) setuid(ctladdr->q_uid);
                   1228:                }
                   1229:                f = dfopen(filename, "a");
                   1230:                if (f == NULL)
                   1231:                        exit(EX_CANTCREAT);
                   1232: 
                   1233:                putfromline(f, ProgMailer);
                   1234:                (*CurEnv->e_puthdr)(f, ProgMailer, CurEnv);
                   1235:                putline("\n", f, ProgMailer);
                   1236:                (*CurEnv->e_putbody)(f, ProgMailer, CurEnv);
                   1237:                putline("\n", f, ProgMailer);
                   1238:                (void) fclose(f);
                   1239:                (void) fflush(stdout);
                   1240: 
                   1241:                /* reset ISUID & ISGID bits for paranoid systems */
                   1242:                (void) chmod(filename, (int) stb.st_mode);
                   1243:                exit(EX_OK);
                   1244:                /*NOTREACHED*/
                   1245:        }
                   1246:        else
                   1247:        {
                   1248:                /* parent -- wait for exit status */
                   1249:                int st;
                   1250: 
                   1251:                st = waitfor(pid);
                   1252:                if ((st & 0377) != 0)
                   1253:                        return (EX_UNAVAILABLE);
                   1254:                else
                   1255:                        return ((st >> 8) & 0377);
                   1256:        }
                   1257: }
                   1258: /*
                   1259: **  SENDALL -- actually send all the messages.
                   1260: **
                   1261: **     Parameters:
                   1262: **             e -- the envelope to send.
                   1263: **             mode -- the delivery mode to use.  If SM_DEFAULT, use
                   1264: **                     the current SendMode.
                   1265: **
                   1266: **     Returns:
                   1267: **             none.
                   1268: **
                   1269: **     Side Effects:
                   1270: **             Scans the send lists and sends everything it finds.
                   1271: **             Delivers any appropriate error messages.
                   1272: **             If we are running in a non-interactive mode, takes the
                   1273: **                     appropriate action.
                   1274: */
                   1275: 
                   1276: sendall(e, mode)
                   1277:        ENVELOPE *e;
                   1278:        char mode;
                   1279: {
                   1280:        register ADDRESS *q;
                   1281:        bool oldverbose;
                   1282:        int pid;
                   1283: 
                   1284:        /* determine actual delivery mode */
                   1285:        if (mode == SM_DEFAULT)
                   1286:        {
                   1287:                extern bool shouldqueue();
                   1288: 
                   1289:                if (shouldqueue(e->e_msgpriority))
                   1290:                        mode = SM_QUEUE;
                   1291:                else
                   1292:                        mode = SendMode;
                   1293:        }
                   1294: 
                   1295: #ifdef DEBUG
                   1296:        if (tTd(13, 1))
                   1297:        {
                   1298:                printf("\nSENDALL: mode %c, sendqueue:\n", mode);
                   1299:                printaddr(e->e_sendqueue, TRUE);
                   1300:        }
                   1301: #endif DEBUG
                   1302: 
                   1303:        /*
                   1304:        **  Do any preprocessing necessary for the mode we are running.
                   1305:        **      Check to make sure the hop count is reasonable.
                   1306:        **      Delete sends to the sender in mailing lists.
                   1307:        */
                   1308: 
                   1309:        CurEnv = e;
                   1310: 
                   1311:        if (e->e_hopcount > MAXHOP)
                   1312:        {
                   1313:                syserr("sendall: too many hops (%d max)", MAXHOP);
                   1314:                return;
                   1315:        }
                   1316: 
                   1317:        if (!MeToo)
                   1318:        {
                   1319:                extern ADDRESS *recipient();
                   1320: 
                   1321:                e->e_from.q_flags |= QDONTSEND;
                   1322:                (void) recipient(&e->e_from, &e->e_sendqueue);
                   1323:        }
                   1324: 
                   1325: # ifdef QUEUE
                   1326:        if ((mode == SM_QUEUE || mode == SM_FORK ||
                   1327:             (mode != SM_VERIFY && SuperSafe)) &&
                   1328:            !bitset(EF_INQUEUE, e->e_flags))
                   1329:                queueup(e, TRUE, mode == SM_QUEUE);
                   1330: #endif QUEUE
                   1331: 
                   1332:        oldverbose = Verbose;
                   1333:        switch (mode)
                   1334:        {
                   1335:          case SM_VERIFY:
                   1336:                Verbose = TRUE;
                   1337:                break;
                   1338: 
                   1339:          case SM_QUEUE:
                   1340:                e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE;
                   1341:                return;
                   1342: 
                   1343:          case SM_FORK:
                   1344:                if (e->e_xfp != NULL)
                   1345:                        (void) fflush(e->e_xfp);
                   1346:                pid = fork();
                   1347:                if (pid < 0)
                   1348:                {
                   1349:                        mode = SM_DELIVER;
                   1350:                        break;
                   1351:                }
                   1352:                else if (pid > 0)
                   1353:                {
                   1354:                        /* be sure we leave the temp files to our child */
                   1355:                        e->e_id = e->e_df = NULL;
                   1356:                        return;
                   1357:                }
                   1358: 
                   1359:                /* double fork to avoid zombies */
                   1360:                if (fork() > 0)
                   1361:                        exit(EX_OK);
                   1362: 
                   1363:                /* be sure we are immune from the terminal */
                   1364:                disconnect(FALSE);
                   1365: 
                   1366:                break;
                   1367:        }
                   1368: 
                   1369:        /*
                   1370:        **  Run through the list and send everything.
                   1371:        */
                   1372: 
                   1373:        for (q = e->e_sendqueue; q != NULL; q = q->q_next)
                   1374:        {
                   1375:                if (mode == SM_VERIFY)
                   1376:                {
                   1377:                        e->e_to = q->q_paddr;
                   1378:                        if (!bitset(QDONTSEND|QBADADDR, q->q_flags))
                   1379:                                message(Arpa_Info, "deliverable");
                   1380:                }
                   1381:                else
                   1382:                        (void) deliver(e, q);
                   1383:        }
                   1384:        Verbose = oldverbose;
                   1385: 
                   1386:        /*
                   1387:        **  Now run through and check for errors.
                   1388:        */
                   1389: 
                   1390:        if (mode == SM_VERIFY)
                   1391:                return;
                   1392: 
                   1393:        for (q = e->e_sendqueue; q != NULL; q = q->q_next)
                   1394:        {
                   1395:                register ADDRESS *qq;
                   1396: 
                   1397: # ifdef DEBUG
                   1398:                if (tTd(13, 3))
                   1399:                {
                   1400:                        printf("Checking ");
                   1401:                        printaddr(q, FALSE);
                   1402:                }
                   1403: # endif DEBUG
                   1404: 
                   1405:                /* only send errors if the message failed */
                   1406:                if (!bitset(QBADADDR, q->q_flags))
                   1407:                        continue;
                   1408: 
                   1409:                /* we have an address that failed -- find the parent */
                   1410:                for (qq = q; qq != NULL; qq = qq->q_alias)
                   1411:                {
                   1412:                        char obuf[MAXNAME + 6];
                   1413:                        extern char *aliaslookup();
                   1414: 
                   1415:                        /* we can only have owners for local addresses */
                   1416:                        if (!bitnset(M_LOCAL, qq->q_mailer->m_flags))
                   1417:                                continue;
                   1418: 
                   1419:                        /* see if the owner list exists */
                   1420:                        (void) strcpy(obuf, "owner-");
                   1421:                        if (strncmp(qq->q_user, "owner-", 6) == 0)
                   1422:                                (void) strcat(obuf, "owner");
                   1423:                        else
                   1424:                                (void) strcat(obuf, qq->q_user);
                   1425:                        if (aliaslookup(obuf) == NULL)
                   1426:                                continue;
                   1427: 
                   1428: # ifdef DEBUG
                   1429:                        if (tTd(13, 4))
                   1430:                                printf("Errors to %s\n", obuf);
                   1431: # endif DEBUG
                   1432: 
                   1433:                        /* owner list exists -- add it to the error queue */
                   1434:                        sendtolist(obuf, (ADDRESS *) NULL, &e->e_errorqueue);
                   1435:                        ErrorMode = EM_MAIL;
                   1436:                        break;
                   1437:                }
                   1438: 
                   1439:                /* if we did not find an owner, send to the sender */
                   1440:                if (qq == NULL && bitset(QBADADDR, q->q_flags))
                   1441:                        sendtolist(e->e_from.q_paddr, qq, &e->e_errorqueue);
                   1442:        }
                   1443: 
                   1444:        if (mode == SM_FORK)
                   1445:                finis();
                   1446: }

unix.superglobalmegacorp.com

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