# 2.11BSD#431 - /usr/src/usr.sbin/sendmail/src/deliver.c

##### Functions

    deliver           X
    dofork            X
    endmailer         X
    giveresponse      X
    logdelivery       X
    mailfile          X
    markfailure       X
    openmailer        X
    putbody           X
    putfromline       X
    sendall           X
    sendoff           X

##### Macros

    DOFORK            X
    NFORKTRIES        X
    XFORK             X

       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: #if !defined(lint) && !defined(NOSCCS)
      12: static char SccsId[] = "@(#)deliver.c	5.10.1 (2.11BSD GTE) 3/6/95";
      13: #endif
      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 ((int)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, h_errno;
     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:         char    mbuf[8];
     992:
     993:         Errors++;
     994:         sprintf(mbuf, "%.3s %%s", statmsg);
     995:         usrerr(mbuf, &statmsg[4]);
     996:     }
     997:
     998:     /*
     999: 	**  Final cleanup.
    1000: 	**	Log a record of the transaction.  Compute the new
    1001: 	**	ExitStat -- if we already had an error, stick with
    1002: 	**	that.
    1003: 	*/
    1004:
    1005:     if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2))
    1006:         logdelivery(&statmsg[4]);
    1007:
    1008:     if (stat != EX_TEMPFAIL)
    1009:         setstat(stat);
    1010:     if (stat != EX_OK)
    1011:     {
    1012:         if (e->e_message != NULL)
    1013:             free(e->e_message);
    1014:         e->e_message = newstr(&statmsg[4]);
    1015:     }
    1016:     errno = 0;
    1017:     h_errno = 0;
    1018: }
    1019: /*
    1020: **  LOGDELIVERY -- log the delivery in the system log
    1021: **
    1022: **	Parameters:
    1023: **		stat -- the message to print for the status
    1024: **
    1025: **	Returns:
    1026: **		none
    1027: **
    1028: **	Side Effects:
    1029: **		none
    1030: */
    1031:
    1032: logdelivery(stat)
    1033:     char *stat;
    1034: {
    1035:     extern char *pintvl();
    1036:
    1037: # ifdef LOG
    1038:     syslog(LOG_INFO, "%s: to=%s, delay=%s, stat=%s", CurEnv->e_id,
    1039:            CurEnv->e_to, pintvl(curtime() - CurEnv->e_ctime, TRUE), stat);
    1040: # endif LOG
    1041: }
    1042: /*
    1043: **  PUTFROMLINE -- output a UNIX-style from line (or whatever)
    1044: **
    1045: **	This can be made an arbitrary message separator by changing $l
    1046: **
    1047: **	One of the ugliest hacks seen by human eyes is contained herein:
    1048: **	UUCP wants those stupid "remote from <host>" lines.  Why oh why
    1049: **	does a well-meaning programmer such as myself have to deal with
    1050: **	this kind of antique garbage????
    1051: **
    1052: **	Parameters:
    1053: **		fp -- the file to output to.
    1054: **		m -- the mailer describing this entry.
    1055: **
    1056: **	Returns:
    1057: **		none
    1058: **
    1059: **	Side Effects:
    1060: **		outputs some text to fp.
    1061: */
    1062:
    1063: putfromline(fp, m)
    1064:     register FILE *fp;
    1065:     register MAILER *m;
    1066: {
    1067:     char *template = "\001l\n";
    1068:     char buf[MAXLINE];
    1069:
    1070:     if (bitnset(M_NHDR, m->m_flags))
    1071:         return;
    1072:
    1073: # ifdef UGLYUUCP
    1074:     if (bitnset(M_UGLYUUCP, m->m_flags))
    1075:     {
    1076:         char *bang;
    1077:         char xbuf[MAXLINE];
    1078:
    1079:         expand("\001g", buf, &buf[sizeof buf - 1], CurEnv);
    1080:         bang = index(buf, '!');
    1081:         if (bang == NULL)
    1082:             syserr("No ! in UUCP! (%s)", buf);
    1083:         else
    1084:         {
    1085:             *bang++ = '\0';
    1086:             (void) sprintf(xbuf, "From %s  \001d remote from %s\n", bang, buf);
    1087:             template = xbuf;
    1088:         }
    1089:     }
    1090: # endif UGLYUUCP
    1091:     expand(template, buf, &buf[sizeof buf - 1], CurEnv);
    1092:     putline(buf, fp, m);
    1093: }
    1094: /*
    1095: **  PUTBODY -- put the body of a message.
    1096: **
    1097: **	Parameters:
    1098: **		fp -- file to output onto.
    1099: **		m -- a mailer descriptor to control output format.
    1100: **		e -- the envelope to put out.
    1101: **
    1102: **	Returns:
    1103: **		none.
    1104: **
    1105: **	Side Effects:
    1106: **		The message is written onto fp.
    1107: */
    1108:
    1109: putbody(fp, m, e)
    1110:     FILE *fp;
    1111:     MAILER *m;
    1112:     register ENVELOPE *e;
    1113: {
    1114:     char buf[MAXLINE];
    1115:
    1116:     /*
    1117: 	**  Output the body of the message
    1118: 	*/
    1119:
    1120:     if (e->e_dfp == NULL)
    1121:     {
    1122:         if (e->e_df != NULL)
    1123:         {
    1124:             e->e_dfp = fopen(e->e_df, "r");
    1125:             if (e->e_dfp == NULL)
    1126:                 syserr("Cannot open %s", e->e_df);
    1127:         }
    1128:         else
    1129:             putline("<<< No Message Collected >>>", fp, m);
    1130:     }
    1131:     if (e->e_dfp != NULL)
    1132:     {
    1133:         rewind(e->e_dfp);
    1134:         while (!ferror(fp) && fgets(buf, sizeof buf, e->e_dfp) != NULL)
    1135:         {
    1136:             if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) &&
    1137:                 strncmp(buf, "From", 4) == 0)
    1138:                 (void) putc('>', fp);
    1139:             putline(buf, fp, m);
    1140:         }
    1141:
    1142:         if (ferror(e->e_dfp))
    1143:         {
    1144:             syserr("putbody: read error");
    1145:             ExitStat = EX_IOERR;
    1146:         }
    1147:     }
    1148:
    1149:     (void) fflush(fp);
    1150:     if (ferror(fp) && errno != EPIPE)
    1151:     {
    1152:         syserr("putbody: write error");
    1153:         ExitStat = EX_IOERR;
    1154:     }
    1155:     errno = 0;
    1156: }
    1157: /*
    1158: **  MAILFILE -- Send a message to a file.
    1159: **
    1160: **	If the file has the setuid/setgid bits set, but NO execute
    1161: **	bits, sendmail will try to become the owner of that file
    1162: **	rather than the real user.  Obviously, this only works if
    1163: **	sendmail runs as root.
    1164: **
    1165: **	This could be done as a subordinate mailer, except that it
    1166: **	is used implicitly to save messages in ~/dead.letter.  We
    1167: **	view this as being sufficiently important as to include it
    1168: **	here.  For example, if the system is dying, we shouldn't have
    1169: **	to create another process plus some pipes to save the message.
    1170: **
    1171: **	Parameters:
    1172: **		filename -- the name of the file to send to.
    1173: **		ctladdr -- the controlling address header -- includes
    1174: **			the userid/groupid to be when sending.
    1175: **
    1176: **	Returns:
    1177: **		The exit code associated with the operation.
    1178: **
    1179: **	Side Effects:
    1180: **		none.
    1181: */
    1182:
    1183: mailfile(filename, ctladdr)
    1184:     char *filename;
    1185:     ADDRESS *ctladdr;
    1186: {
    1187:     register FILE *f;
    1188:     register int pid;
    1189:
    1190:     /*
    1191: 	**  Fork so we can change permissions here.
    1192: 	**	Note that we MUST use fork, not vfork, because of
    1193: 	**	the complications of calling subroutines, etc.
    1194: 	*/
    1195:
    1196:     DOFORK(fork);
    1197:
    1198:     if (pid < 0)
    1199:         return (EX_OSERR);
    1200:     else if (pid == 0)
    1201:     {
    1202:         /* child -- actually write to file */
    1203:         struct stat stb;
    1204:
    1205:         (void) signal(SIGINT, SIG_DFL);
    1206:         (void) signal(SIGHUP, SIG_DFL);
    1207:         (void) signal(SIGTERM, SIG_DFL);
    1208:         (void) umask(OldUmask);
    1209:         if (stat(filename, &stb) < 0)
    1210:         {
    1211:             errno = 0;
    1212:             stb.st_mode = 0666;
    1213:         }
    1214:         if (bitset(0111, stb.st_mode))
    1215:             exit(EX_CANTCREAT);
    1216:         if (ctladdr == NULL)
    1217:             ctladdr = &CurEnv->e_from;
    1218:         if (!bitset(S_ISGID, stb.st_mode) || setgid(stb.st_gid) < 0)
    1219:         {
    1220:             if (ctladdr->q_uid == 0)
    1221:                 (void) setgid(DefGid);
    1222:             else
    1223:                 (void) setgid(ctladdr->q_gid);
    1224:         }
    1225:         if (!bitset(S_ISUID, stb.st_mode) || setuid(stb.st_uid) < 0)
    1226:         {
    1227:             if (ctladdr->q_uid == 0)
    1228:                 (void) setuid(DefUid);
    1229:             else
    1230:                 (void) setuid(ctladdr->q_uid);
    1231:         }
    1232:         f = dfopen(filename, "a");
    1233:         if (f == NULL)
    1234:             exit(EX_CANTCREAT);
    1235:
    1236:         putfromline(f, ProgMailer);
    1237:         (*CurEnv->e_puthdr)(f, ProgMailer, CurEnv);
    1238:         putline("\n", f, ProgMailer);
    1239:         (*CurEnv->e_putbody)(f, ProgMailer, CurEnv);
    1240:         putline("\n", f, ProgMailer);
    1241:         (void) fclose(f);
    1242:         (void) fflush(stdout);
    1243:
    1244:         /* reset ISUID & ISGID bits for paranoid systems */
    1245:         (void) chmod(filename, (int) stb.st_mode);
    1246:         exit(EX_OK);
    1247:         /*NOTREACHED*/
    1248:     }
    1249:     else
    1250:     {
    1251:         /* parent -- wait for exit status */
    1252:         int st;
    1253:
    1254:         st = waitfor(pid);
    1255:         if ((st & 0377) != 0)
    1256:             return (EX_UNAVAILABLE);
    1257:         else
    1258:             return ((st >> 8) & 0377);
    1259:     }
    1260: }
    1261: /*
    1262: **  SENDALL -- actually send all the messages.
    1263: **
    1264: **	Parameters:
    1265: **		e -- the envelope to send.
    1266: **		mode -- the delivery mode to use.  If SM_DEFAULT, use
    1267: **			the current SendMode.
    1268: **
    1269: **	Returns:
    1270: **		none.
    1271: **
    1272: **	Side Effects:
    1273: **		Scans the send lists and sends everything it finds.
    1274: **		Delivers any appropriate error messages.
    1275: **		If we are running in a non-interactive mode, takes the
    1276: **			appropriate action.
    1277: */
    1278:
    1279: sendall(e, mode)
    1280:     ENVELOPE *e;
    1281:     char mode;
    1282: {
    1283:     register ADDRESS *q;
    1284:     bool oldverbose;
    1285:     int pid;
    1286:     bool announcequeueup;
    1287:
    1288:     /* determine actual delivery mode */
    1289:     if (mode == SM_DEFAULT)
    1290:     {
    1291:         if (shouldqueue(e->e_msgpriority))
    1292:             mode = SM_QUEUE;
    1293:         announcequeueup = mode == SendMode;
    1294:     }
    1295:     else
    1296:         announcequeueup = FALSE;
    1297:
    1298: #ifdef DEBUG
    1299:     if (tTd(13, 1))
    1300:     {
    1301:         printf("\nSENDALL: mode %c, sendqueue:\n", mode);
    1302:         printaddr(e->e_sendqueue, TRUE);
    1303:     }
    1304: #endif DEBUG
    1305:
    1306:     /*
    1307: 	**  Do any preprocessing necessary for the mode we are running.
    1308: 	**	Check to make sure the hop count is reasonable.
    1309: 	**	Delete sends to the sender in mailing lists.
    1310: 	*/
    1311:
    1312:     CurEnv = e;
    1313:
    1314:     if (e->e_hopcount > MAXHOP)
    1315:     {
    1316:         errno = 0;
    1317:         queueup(e, TRUE, announcequeueup);
    1318:         e->e_flags |= EF_FATALERRS|EF_CLRQUEUE;
    1319:         syserr("too many hops (%d max): from %s via %s, to %s",
    1320:             MAXHOP, e->e_from.q_paddr,
    1321:             RealHostName == NULL ? "localhost" : RealHostName,
    1322:             e->e_sendqueue->q_paddr);
    1323:         return;
    1324:     }
    1325:
    1326:     if (!MeToo)
    1327:     {
    1328:         extern ADDRESS *recipient();
    1329:
    1330:         e->e_from.q_flags |= QDONTSEND;
    1331:         (void) recipient(&e->e_from, &e->e_sendqueue);
    1332:     }
    1333:
    1334: # ifdef QUEUE
    1335:     if ((mode == SM_QUEUE || mode == SM_FORK ||
    1336:          (mode != SM_VERIFY && SuperSafe)) &&
    1337:         !bitset(EF_INQUEUE, e->e_flags))
    1338:         queueup(e, TRUE, announcequeueup);
    1339: #endif QUEUE
    1340:
    1341:     oldverbose = Verbose;
    1342:     switch (mode)
    1343:     {
    1344:       case SM_VERIFY:
    1345:         Verbose = TRUE;
    1346:         break;
    1347:
    1348:       case SM_QUEUE:
    1349:         e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE;
    1350:         return;
    1351:
    1352:       case SM_FORK:
    1353:         if (e->e_xfp != NULL)
    1354:             (void) fflush(e->e_xfp);
    1355:         pid = fork();
    1356:         if (pid < 0)
    1357:         {
    1358:             mode = SM_DELIVER;
    1359:             break;
    1360:         }
    1361:         else if (pid > 0)
    1362:         {
    1363:             /* be sure we leave the temp files to our child */
    1364:             e->e_id = e->e_df = NULL;
    1365:             return;
    1366:         }
    1367:
    1368:         /* double fork to avoid zombies */
    1369:         if (fork() > 0)
    1370:             exit(EX_OK);
    1371:
    1372:         /* be sure we are immune from the terminal */
    1373:         disconnect(FALSE);
    1374:
    1375:         break;
    1376:     }
    1377:
    1378:     /*
    1379: 	**  Run through the list and send everything.
    1380: 	*/
    1381:
    1382:     for (q = e->e_sendqueue; q != NULL; q = q->q_next)
    1383:     {
    1384:         if (mode == SM_VERIFY)
    1385:         {
    1386:             e->e_to = q->q_paddr;
    1387:             if (!bitset(QDONTSEND|QBADADDR, q->q_flags))
    1388:                 message(Arpa_Info, "deliverable");
    1389:         }
    1390:         else
    1391:             (void) deliver(e, q);
    1392:     }
    1393:     Verbose = oldverbose;
    1394:
    1395:     /*
    1396: 	**  Now run through and check for errors.
    1397: 	*/
    1398:
    1399:     if (mode == SM_VERIFY)
    1400:         return;
    1401:
    1402:     for (q = e->e_sendqueue; q != NULL; q = q->q_next)
    1403:     {
    1404:         register ADDRESS *qq;
    1405:
    1406: # ifdef DEBUG
    1407:         if (tTd(13, 3))
    1408:         {
    1409:             printf("Checking ");
    1410:             printaddr(q, FALSE);
    1411:         }
    1412: # endif DEBUG
    1413:
    1414:         /* only send errors if the message failed */
    1415:         if (!bitset(QBADADDR, q->q_flags))
    1416:             continue;
    1417:
    1418:         /* we have an address that failed -- find the parent */
    1419:         for (qq = q; qq != NULL; qq = qq->q_alias)
    1420:         {
    1421:             char obuf[MAXNAME + 6];
    1422:             extern char *aliaslookup();
    1423:
    1424:             /* we can only have owners for local addresses */
    1425:             if (!bitnset(M_LOCAL, qq->q_mailer->m_flags))
    1426:                 continue;
    1427:
    1428:             /* see if the owner list exists */
    1429:             (void) strcpy(obuf, "owner-");
    1430:             if (strncmp(qq->q_user, "owner-", 6) == 0)
    1431:                 (void) strcat(obuf, "owner");
    1432:             else
    1433:                 (void) strcat(obuf, qq->q_user);
    1434:             if (aliaslookup(obuf) == NULL)
    1435:                 continue;
    1436:
    1437: # ifdef DEBUG
    1438:             if (tTd(13, 4))
    1439:                 printf("Errors to %s\n", obuf);
    1440: # endif DEBUG
    1441:
    1442:             /* owner list exists -- add it to the error queue */
    1443:             sendtolist(obuf, (ADDRESS *) NULL, &e->e_errorqueue);
    1444:             ErrorMode = EM_MAIL;
    1445:             break;
    1446:         }
    1447:
    1448:         /* if we did not find an owner, send to the sender */
    1449:         if (qq == NULL && bitset(QBADADDR, q->q_flags))
    1450:             sendtolist(e->e_from.q_paddr, qq, &e->e_errorqueue);
    1451:     }
    1452:
    1453:     if (mode == SM_FORK)
    1454:         finis();
    1455: }

#### Defined functions

deliver defined in line 43; used 2 times

- in line 1391
- in /usr/src/usr.sbin/sendmail/src/savemail.c line 284

dofork defined in line 528; used 2 times

- in /usr/src/usr.sbin/sendmail/src/queue.c line 285
- in /usr/src/usr.sbin/sendmail/src/srvrsmtp.c line 645

endmailer defined in line 611; used 2 times

- in line 581
- in /usr/src/usr.sbin/sendmail/src/usersmtp.c line 354

giveresponse defined in line 914; used 7 times

- in line 233-238(2), 290, 380, 414
- in /usr/src/usr.sbin/sendmail/src/recipient.c line 303, 316

logdelivery defined in line 1032; used 3 times

- in line 100, 1006
- in /usr/src/usr.sbin/sendmail/src/queue.c line 142

mailfile defined in line 1183; used 1 times

- in line 289

markfailure defined in line 442; used 2 times

- in line 379, 418

openmailer defined in line 661; used 2 times

- in line 567
- in /usr/src/usr.sbin/sendmail/src/usersmtp.c line 93

putbody defined in line 1109; used 7 times

- in /usr/src/usr.sbin/sendmail/src/envelope.c line 40, 55
- in /usr/src/usr.sbin/sendmail/src/main.c line 112, 152
- in /usr/src/usr.sbin/sendmail/src/queue.c line 92, 105
- in /usr/src/usr.sbin/sendmail/src/savemail.c line 499

putfromline defined in line 1063; used 3 times

- in line 575, 1236
- in /usr/src/usr.sbin/sendmail/src/savemail.c line 308

sendall defined in line 1279; used 4 times

- in /usr/src/usr.sbin/sendmail/src/main.c line 716
- in /usr/src/usr.sbin/sendmail/src/queue.c line 633
- in /usr/src/usr.sbin/sendmail/src/savemail.c line 425
- in /usr/src/usr.sbin/sendmail/src/srvrsmtp.c line 338

sendoff defined in line 552; used 1 times

- in line 404

#### Defined variables

SccsId defined in line 12; never used

#### Defined macros

DOFORK defined in line 500; used 3 times

- in line 532, 788, 1196

NFORKTRIES defined in line 493; used 2 times

- in line 504, 510

XFORK defined in line 497; used 1 times

- in line 788

Last modified: 1995-03-07 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 4373 |