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: }

Defined functions

errbody defined in line 310; used 2 times
returntosender defined in line 217; never used
savemail defined in line 26; used 1 times

Defined macros

MAXRETURNS defined in line 215; used 2 times
Last modified: 1983-12-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1295
Valid CSS Valid XHTML 1.0 Strict