Annotation of 42BSD/usr.lib/sendmail/src/savemail.c, revision 1.1.1.1

1.1       root        1: # include <pwd.h>
                      2: # include "sendmail.h"
                      3: 
                      4: SCCSID(@(#)savemail.c  4.2             8/28/83);
                      5: 
                      6: /*
                      7: **  SAVEMAIL -- Save mail on error
                      8: **
                      9: **     If mailing back errors, mail it back to the originator
                     10: **     together with an error message; otherwise, just put it in
                     11: **     dead.letter in the user's home directory (if he exists on
                     12: **     this machine).
                     13: **
                     14: **     Parameters:
                     15: **             e -- the envelope containing the message in error.
                     16: **
                     17: **     Returns:
                     18: **             none
                     19: **
                     20: **     Side Effects:
                     21: **             Saves the letter, by writing or mailing it back to the
                     22: **             sender, or by putting it in dead.letter in her home
                     23: **             directory.
                     24: */
                     25: 
                     26: savemail(e)
                     27:        register ENVELOPE *e;
                     28: {
                     29:        register struct passwd *pw;
                     30:        register FILE *xfile;
                     31:        char buf[MAXLINE+1];
                     32:        extern struct passwd *getpwnam();
                     33:        register char *p;
                     34:        extern char *ttypath();
                     35:        typedef int (*fnptr)();
                     36: 
                     37: # ifdef DEBUG
                     38:        if (tTd(6, 1))
                     39:                printf("\nsavemail\n");
                     40: # endif DEBUG
                     41: 
                     42:        if (bitset(EF_RESPONSE, e->e_flags))
                     43:                return;
                     44:        if (e->e_class < 0)
                     45:        {
                     46:                message(Arpa_Info, "Dumping junk mail");
                     47:                return;
                     48:        }
                     49:        ForceMail = TRUE;
                     50:        e->e_flags &= ~EF_FATALERRS;
                     51: 
                     52:        /*
                     53:        **  In the unhappy event we don't know who to return the mail
                     54:        **  to, make someone up.
                     55:        */
                     56: 
                     57:        if (e->e_from.q_paddr == NULL)
                     58:        {
                     59:                if (parseaddr("root", &e->e_from, 0, '\0') == NULL)
                     60:                {
                     61:                        syserr("Cannot parse root!");
                     62:                        ExitStat = EX_SOFTWARE;
                     63:                        finis();
                     64:                }
                     65:        }
                     66:        e->e_to = NULL;
                     67: 
                     68:        /*
                     69:        **  If called from Eric Schmidt's network, do special mailback.
                     70:        **      Fundamentally, this is the mailback case except that
                     71:        **      it returns an OK exit status (assuming the return
                     72:        **      worked).
                     73:        **  Also, if the from address is not local, mail it back.
                     74:        */
                     75: 
                     76:        if (ErrorMode == EM_BERKNET)
                     77:        {
                     78:                ExitStat = EX_OK;
                     79:                ErrorMode = EM_MAIL;
                     80:        }
                     81:        if (!bitnset(M_LOCAL, e->e_from.q_mailer->m_flags))
                     82:                ErrorMode = EM_MAIL;
                     83: 
                     84:        /*
                     85:        **  If writing back, do it.
                     86:        **      If the user is still logged in on the same terminal,
                     87:        **      then write the error messages back to hir (sic).
                     88:        **      If not, mail back instead.
                     89:        */
                     90: 
                     91:        if (ErrorMode == EM_WRITE)
                     92:        {
                     93:                p = ttypath();
                     94:                if (p == NULL || freopen(p, "w", stdout) == NULL)
                     95:                {
                     96:                        ErrorMode = EM_MAIL;
                     97:                        errno = 0;
                     98:                }
                     99:                else
                    100:                {
                    101:                        expand("$n", buf, &buf[sizeof buf - 1], e);
                    102:                        printf("\r\nMessage from %s...\r\n", buf);
                    103:                        printf("Errors occurred while sending mail.\r\n");
                    104:                        if (e->e_xfp != NULL)
                    105:                        {
                    106:                                (void) fflush(e->e_xfp);
                    107:                                xfile = fopen(queuename(e, 'x'), "r");
                    108:                        }
                    109:                        else
                    110:                                xfile = NULL;
                    111:                        if (xfile == NULL)
                    112:                        {
                    113:                                syserr("Cannot open %s", queuename(e, 'x'));
                    114:                                printf("Transcript of session is unavailable.\r\n");
                    115:                        }
                    116:                        else
                    117:                        {
                    118:                                printf("Transcript follows:\r\n");
                    119:                                while (fgets(buf, sizeof buf, xfile) != NULL &&
                    120:                                       !ferror(stdout))
                    121:                                        fputs(buf, stdout);
                    122:                                (void) fclose(xfile);
                    123:                        }
                    124:                        if (ferror(stdout))
                    125:                                (void) syserr("savemail: stdout: write err");
                    126:                }
                    127:        }
                    128: 
                    129:        /*
                    130:        **  If mailing back, do it.
                    131:        **      Throw away all further output.  Don't do aliases, since
                    132:        **      this could cause loops, e.g., if joe mails to x:joe,
                    133:        **      and for some reason the network for x: is down, then
                    134:        **      the response gets sent to x:joe, which gives a
                    135:        **      response, etc.  Also force the mail to be delivered
                    136:        **      even if a version of it has already been sent to the
                    137:        **      sender.
                    138:        */
                    139: 
                    140:        if (ErrorMode == EM_MAIL)
                    141:        {
                    142:                if (e->e_errorqueue == NULL)
                    143:                        sendtolist(e->e_from.q_paddr, (ADDRESS *) NULL,
                    144:                               &e->e_errorqueue);
                    145:                if (returntosender(e->e_message != NULL ? e->e_message :
                    146:                                   "Unable to deliver mail",
                    147:                                   e->e_errorqueue, TRUE) == 0)
                    148:                        return;
                    149:        }
                    150: 
                    151:        /*
                    152:        **  Save the message in dead.letter.
                    153:        **      If we weren't mailing back, and the user is local, we
                    154:        **      should save the message in dead.letter so that the
                    155:        **      poor person doesn't have to type it over again --
                    156:        **      and we all know what poor typists programmers are.
                    157:        */
                    158: 
                    159:        p = NULL;
                    160:        if (e->e_from.q_mailer == LocalMailer)
                    161:        {
                    162:                if (e->e_from.q_home != NULL)
                    163:                        p = e->e_from.q_home;
                    164:                else if ((pw = getpwnam(e->e_from.q_user)) != NULL)
                    165:                        p = pw->pw_dir;
                    166:        }
                    167:        if (p == NULL)
                    168:        {
                    169:                syserr("Can't return mail to %s", e->e_from.q_paddr);
                    170: # ifdef DEBUG
                    171:                p = "/usr/tmp";
                    172: # endif
                    173:        }
                    174:        if (p != NULL && e->e_dfp != NULL)
                    175:        {
                    176:                auto ADDRESS *q;
                    177:                bool oldverb = Verbose;
                    178: 
                    179:                /* we have a home directory; open dead.letter */
                    180:                define('z', p, e);
                    181:                expand("$z/dead.letter", buf, &buf[sizeof buf - 1], e);
                    182:                Verbose = TRUE;
                    183:                message(Arpa_Info, "Saving message in %s", buf);
                    184:                Verbose = oldverb;
                    185:                e->e_to = buf;
                    186:                q = NULL;
                    187:                sendtolist(buf, (ADDRESS *) NULL, &q);
                    188:                (void) deliver(e, q);
                    189:        }
                    190: 
                    191:        /* add terminator to writeback message */
                    192:        if (ErrorMode == EM_WRITE)
                    193:                printf("-----\r\n");
                    194: }
                    195: /*
                    196: **  RETURNTOSENDER -- return a message to the sender with an error.
                    197: **
                    198: **     Parameters:
                    199: **             msg -- the explanatory message.
                    200: **             returnto -- the queue of people to send the message to.
                    201: **             sendbody -- if TRUE, also send back the body of the
                    202: **                     message; otherwise just send the header.
                    203: **
                    204: **     Returns:
                    205: **             zero -- if everything went ok.
                    206: **             else -- some error.
                    207: **
                    208: **     Side Effects:
                    209: **             Returns the current message to the sender via
                    210: **             mail.
                    211: */
                    212: 
                    213: static bool    SendBody;
                    214: 
                    215: #define MAXRETURNS     6       /* max depth of returning messages */
                    216: 
                    217: returntosender(msg, returnto, sendbody)
                    218:        char *msg;
                    219:        ADDRESS *returnto;
                    220:        bool sendbody;
                    221: {
                    222:        char buf[MAXNAME];
                    223:        extern putheader(), errbody();
                    224:        register ENVELOPE *ee;
                    225:        extern ENVELOPE *newenvelope();
                    226:        ENVELOPE errenvelope;
                    227:        static int returndepth;
                    228:        register ADDRESS *q;
                    229: 
                    230: # ifdef DEBUG
                    231:        if (tTd(6, 1))
                    232:        {
                    233:                printf("Return To Sender: msg=\"%s\", depth=%d, CurEnv=%x,\n",
                    234:                       msg, returndepth, CurEnv);
                    235:                printf("\treturnto=");
                    236:                printaddr(returnto, TRUE);
                    237:        }
                    238: # endif DEBUG
                    239: 
                    240:        if (++returndepth >= MAXRETURNS)
                    241:        {
                    242:                if (returndepth != MAXRETURNS)
                    243:                        syserr("returntosender: infinite recursion on %s", returnto->q_paddr);
                    244:                /* don't "unrecurse" and fake a clean exit */
                    245:                /* returndepth--; */
                    246:                return (0);
                    247:        }
                    248: 
                    249:        SendBody = sendbody;
                    250:        define('g', "$f", CurEnv);
                    251:        ee = newenvelope(&errenvelope);
                    252:        ee->e_puthdr = putheader;
                    253:        ee->e_putbody = errbody;
                    254:        ee->e_flags |= EF_RESPONSE;
                    255:        ee->e_sendqueue = returnto;
                    256:        openxscript(ee);
                    257:        for (q = returnto; q != NULL; q = q->q_next)
                    258:        {
                    259:                if (q->q_alias == NULL)
                    260:                        addheader("to", q->q_paddr, ee);
                    261:        }
                    262:        (void) sprintf(buf, "Returned mail: %s", msg);
                    263:        addheader("subject", buf, ee);
                    264: 
                    265:        /* fake up an address header for the from person */
                    266:        expand("$n", buf, &buf[sizeof buf - 1], CurEnv);
                    267:        if (parseaddr(buf, &ee->e_from, -1, '\0') == NULL)
                    268:        {
                    269:                syserr("Can't parse myself!");
                    270:                ExitStat = EX_SOFTWARE;
                    271:                returndepth--;
                    272:                return (-1);
                    273:        }
                    274: 
                    275:        /* push state into submessage */
                    276:        CurEnv = ee;
                    277:        define('f', "$n", ee);
                    278:        define('x', "Mail Delivery Subsystem", ee);
                    279:        eatheader(ee);
                    280: 
                    281:        /* actually deliver the error message */
                    282:        sendall(ee, SM_DEFAULT);
                    283: 
                    284:        /* restore state */
                    285:        dropenvelope(ee);
                    286:        CurEnv = CurEnv->e_parent;
                    287:        returndepth--;
                    288: 
                    289:        /* should check for delivery errors here */
                    290:        return (0);
                    291: }
                    292: /*
                    293: **  ERRBODY -- output the body of an error message.
                    294: **
                    295: **     Typically this is a copy of the transcript plus a copy of the
                    296: **     original offending message.
                    297: **
                    298: **     Parameters:
                    299: **             fp -- the output file.
                    300: **             m -- the mailer to output to.
                    301: **             e -- the envelope we are working in.
                    302: **
                    303: **     Returns:
                    304: **             none
                    305: **
                    306: **     Side Effects:
                    307: **             Outputs the body of an error message.
                    308: */
                    309: 
                    310: errbody(fp, m, e)
                    311:        register FILE *fp;
                    312:        register struct mailer *m;
                    313:        register ENVELOPE *e;
                    314: {
                    315:        register FILE *xfile;
                    316:        char buf[MAXLINE];
                    317:        char *p;
                    318: 
                    319:        /*
                    320:        **  Output transcript of errors
                    321:        */
                    322: 
                    323:        (void) fflush(stdout);
                    324:        p = queuename(e->e_parent, 'x');
                    325:        if ((xfile = fopen(p, "r")) == NULL)
                    326:        {
                    327:                syserr("Cannot open %s", p);
                    328:                fprintf(fp, "  ----- Transcript of session is unavailable -----\n");
                    329:        }
                    330:        else
                    331:        {
                    332:                fprintf(fp, "   ----- Transcript of session follows -----\n");
                    333:                if (e->e_xfp != NULL)
                    334:                        (void) fflush(e->e_xfp);
                    335:                while (fgets(buf, sizeof buf, xfile) != NULL)
                    336:                        putline(buf, fp, m);
                    337:                (void) fclose(xfile);
                    338:        }
                    339:        errno = 0;
                    340: 
                    341:        /*
                    342:        **  Output text of original message
                    343:        */
                    344: 
                    345:        if (NoReturn)
                    346:                fprintf(fp, "\n   ----- Return message suppressed -----\n\n");
                    347:        else if (e->e_parent->e_dfp != NULL)
                    348:        {
                    349:                if (SendBody)
                    350:                {
                    351:                        putline("\n", fp, m);
                    352:                        putline("   ----- Unsent message follows -----\n", fp, m);
                    353:                        (void) fflush(fp);
                    354:                        putheader(fp, m, e->e_parent);
                    355:                        putline("\n", fp, m);
                    356:                        putbody(fp, m, e->e_parent);
                    357:                }
                    358:                else
                    359:                {
                    360:                        putline("\n", fp, m);
                    361:                        putline("  ----- Message header follows -----\n", fp, m);
                    362:                        (void) fflush(fp);
                    363:                        putheader(fp, m, e->e_parent);
                    364:                }
                    365:        }
                    366:        else
                    367:        {
                    368:                putline("\n", fp, m);
                    369:                putline("  ----- No message was collected -----\n", fp, m);
                    370:                putline("\n", fp, m);
                    371:        }
                    372: 
                    373:        /*
                    374:        **  Cleanup and exit
                    375:        */
                    376: 
                    377:        if (errno != 0)
                    378:                syserr("errbody: I/O error");
                    379: }

unix.superglobalmegacorp.com

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