122701Sdist /* 222701Sdist ** Sendmail 322701Sdist ** Copyright (c) 1983 Eric P. Allman 422701Sdist ** Berkeley, California 522701Sdist ** 622701Sdist ** Copyright (c) 1983 Regents of the University of California. 722701Sdist ** All rights reserved. The Berkeley software License Agreement 822701Sdist ** specifies the terms and conditions for redistribution. 922701Sdist */ 1022701Sdist 1122701Sdist #ifndef lint 12*25026Seric static char SccsId[] = "@(#)deliver.c 5.6 (Berkeley) 09/24/85"; 1322701Sdist #endif not lint 1422701Sdist 15294Seric # include <signal.h> 164123Seric # include <errno.h> 174621Seric # include "sendmail.h" 184327Seric # include <sys/stat.h> 19294Seric 20294Seric /* 214315Seric ** DELIVER -- Deliver a message to a list of addresses. 22294Seric ** 234315Seric ** This routine delivers to everyone on the same host as the 244315Seric ** user on the head of the list. It is clever about mailers 254315Seric ** that don't handle multiple users. It is NOT guaranteed 264315Seric ** that it will deliver to all these addresses however -- so 274315Seric ** deliver should be called once for each address on the 284315Seric ** list. 294315Seric ** 30294Seric ** Parameters: 319370Seric ** e -- the envelope to deliver. 324621Seric ** firstto -- head of the address list to deliver to. 33294Seric ** 34294Seric ** Returns: 35294Seric ** zero -- successfully delivered. 36294Seric ** else -- some failure, see ExitStat for more info. 37294Seric ** 38294Seric ** Side Effects: 39294Seric ** The standard input is passed off to someone. 40294Seric */ 41294Seric 429370Seric deliver(e, firstto) 439370Seric register ENVELOPE *e; 444621Seric ADDRESS *firstto; 45294Seric { 464452Seric char *host; /* host being sent to */ 474452Seric char *user; /* user being sent to */ 48294Seric char **pvp; 493233Seric register char **mvp; 503233Seric register char *p; 5110306Seric register MAILER *m; /* mailer for this recipient */ 524397Seric ADDRESS *ctladdr; 534621Seric register ADDRESS *to = firstto; 544863Seric bool clever = FALSE; /* running user smtp to this mailer */ 555032Seric ADDRESS *tochain = NULL; /* chain of users in this mailer call */ 568003Seric register int rcode; /* response code */ 5710306Seric char *pv[MAXPV+1]; 5810306Seric char tobuf[MAXLINE-50]; /* text line of to people */ 5910306Seric char buf[MAXNAME]; 6010306Seric char tfrombuf[MAXNAME]; /* translated from person */ 6110306Seric extern bool checkcompat(); 6210306Seric extern ADDRESS *getctladdr(); 6310306Seric extern char *remotename(); 64294Seric 654488Seric errno = 0; 667052Seric if (bitset(QDONTSEND, to->q_flags)) 673233Seric return (0); 68294Seric 696974Seric m = to->q_mailer; 706974Seric host = to->q_host; 716974Seric 72294Seric # ifdef DEBUG 737672Seric if (tTd(10, 1)) 743233Seric printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n", 756974Seric m->m_mno, host, to->q_user); 76294Seric # endif DEBUG 77294Seric 78294Seric /* 795903Seric ** If this mailer is expensive, and if we don't want to make 805903Seric ** connections now, just mark these addresses and return. 815903Seric ** This is useful if we want to batch connections to 825903Seric ** reduce load. This will cause the messages to be 835903Seric ** queued up, and a daemon will come along to send the 845903Seric ** messages later. 855903Seric ** This should be on a per-mailer basis. 865903Seric */ 875903Seric 8810682Seric if (NoConnect && !QueueRun && bitnset(M_EXPENSIVE, m->m_flags) && 898428Seric !Verbose) 905903Seric { 915903Seric for (; to != NULL; to = to->q_next) 928431Seric { 938431Seric if (bitset(QDONTSEND, to->q_flags) || to->q_mailer != m) 948431Seric continue; 958431Seric to->q_flags |= QQUEUEUP|QDONTSEND; 969370Seric e->e_to = to->q_paddr; 978496Seric message(Arpa_Info, "queued"); 988496Seric if (LogLevel > 4) 998496Seric logdelivery("queued"); 1008431Seric } 1019370Seric e->e_to = NULL; 1025903Seric return (0); 1035903Seric } 1045903Seric 1055903Seric /* 1063233Seric ** Do initial argv setup. 1073233Seric ** Insert the mailer name. Notice that $x expansion is 1083233Seric ** NOT done on the mailer name. Then, if the mailer has 1093233Seric ** a picky -f flag, we insert it as appropriate. This 1103233Seric ** code does not check for 'pv' overflow; this places a 1113233Seric ** manifest lower limit of 4 for MAXPV. 1128062Seric ** The from address rewrite is expected to make 1138062Seric ** the address relative to the other end. 1142968Seric */ 1152968Seric 1164452Seric /* rewrite from address, using rewriting rules */ 11716150Seric expand("\001f", buf, &buf[sizeof buf - 1], e); 11810306Seric (void) strcpy(tfrombuf, remotename(buf, m, TRUE, TRUE)); 1194452Seric 1209370Seric define('g', tfrombuf, e); /* translated sender address */ 1219370Seric define('h', host, e); /* to host */ 1223233Seric Errors = 0; 1233233Seric pvp = pv; 1243233Seric *pvp++ = m->m_argv[0]; 1252968Seric 1263233Seric /* insert -f or -r flag as appropriate */ 12710682Seric if (FromFlag && (bitnset(M_FOPT, m->m_flags) || bitnset(M_ROPT, m->m_flags))) 1283233Seric { 12910682Seric if (bitnset(M_FOPT, m->m_flags)) 1303233Seric *pvp++ = "-f"; 1313233Seric else 1323233Seric *pvp++ = "-r"; 13316150Seric expand("\001g", buf, &buf[sizeof buf - 1], e); 1343233Seric *pvp++ = newstr(buf); 1353233Seric } 136294Seric 137294Seric /* 1383233Seric ** Append the other fixed parts of the argv. These run 1393233Seric ** up to the first entry containing "$u". There can only 1403233Seric ** be one of these, and there are only a few more slots 1413233Seric ** in the pv after it. 142294Seric */ 143294Seric 1443233Seric for (mvp = m->m_argv; (p = *++mvp) != NULL; ) 145294Seric { 14616150Seric while ((p = index(p, '\001')) != NULL) 1473233Seric if (*++p == 'u') 1483233Seric break; 1493233Seric if (p != NULL) 1503233Seric break; 1513233Seric 1523233Seric /* this entry is safe -- go ahead and process it */ 1539370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 1543233Seric *pvp++ = newstr(buf); 1553233Seric if (pvp >= &pv[MAXPV - 3]) 1563233Seric { 1573233Seric syserr("Too many parameters to %s before $u", pv[0]); 1583233Seric return (-1); 1593233Seric } 160294Seric } 1614863Seric 1626038Seric /* 1636038Seric ** If we have no substitution for the user name in the argument 1646038Seric ** list, we know that we must supply the names otherwise -- and 1656038Seric ** SMTP is the answer!! 1666038Seric */ 1676038Seric 1683233Seric if (*mvp == NULL) 1694863Seric { 1704863Seric /* running SMTP */ 1715179Seric # ifdef SMTP 1724863Seric clever = TRUE; 1734863Seric *pvp = NULL; 1745179Seric # else SMTP 1756038Seric /* oops! we don't implement SMTP */ 1765179Seric syserr("SMTP style mailer"); 1775179Seric return (EX_SOFTWARE); 1785179Seric # endif SMTP 1794863Seric } 180294Seric 181294Seric /* 1823233Seric ** At this point *mvp points to the argument with $u. We 1833233Seric ** run through our address list and append all the addresses 1843233Seric ** we can. If we run out of space, do not fret! We can 1853233Seric ** always send another copy later. 186294Seric */ 187294Seric 1883233Seric tobuf[0] = '\0'; 1899370Seric e->e_to = tobuf; 1904397Seric ctladdr = NULL; 1913233Seric for (; to != NULL; to = to->q_next) 192294Seric { 1933233Seric /* avoid sending multiple recipients to dumb mailers */ 19410682Seric if (tobuf[0] != '\0' && !bitnset(M_MUSER, m->m_flags)) 1953233Seric break; 1963233Seric 1973233Seric /* if already sent or not for this host, don't send */ 1987052Seric if (bitset(QDONTSEND, to->q_flags) || 1997052Seric strcmp(to->q_host, host) != 0 || 2007052Seric to->q_mailer != firstto->q_mailer) 2013233Seric continue; 2024397Seric 2038225Seric /* avoid overflowing tobuf */ 2049370Seric if (sizeof tobuf - (strlen(to->q_paddr) + strlen(tobuf) + 2) < 0) 2058225Seric break; 2068225Seric 2075032Seric # ifdef DEBUG 2087672Seric if (tTd(10, 1)) 2095032Seric { 2105032Seric printf("\nsend to "); 2115032Seric printaddr(to, FALSE); 2125032Seric } 2135032Seric # endif DEBUG 2145032Seric 2154397Seric /* compute effective uid/gid when sending */ 2164596Seric if (to->q_mailer == ProgMailer) 2174397Seric ctladdr = getctladdr(to); 2184397Seric 2193233Seric user = to->q_user; 2209370Seric e->e_to = to->q_paddr; 2213233Seric to->q_flags |= QDONTSEND; 2223233Seric 2233233Seric /* 2243233Seric ** Check to see that these people are allowed to 2253233Seric ** talk to each other. 2263233Seric */ 2273233Seric 22810699Seric if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize) 22910699Seric { 23010699Seric usrerr("Message is too large; %ld bytes max", m->m_maxsize); 23110699Seric NoReturn = TRUE; 23210699Seric giveresponse(EX_UNAVAILABLE, m, e); 23310699Seric continue; 23410699Seric } 2353233Seric if (!checkcompat(to)) 236294Seric { 23710105Seric giveresponse(EX_UNAVAILABLE, m, e); 2383233Seric continue; 239294Seric } 2403233Seric 2413233Seric /* 2424099Seric ** Strip quote bits from names if the mailer is dumb 2434099Seric ** about them. 2443233Seric */ 2453233Seric 24610682Seric if (bitnset(M_STRIPQ, m->m_flags)) 247294Seric { 2484099Seric stripquotes(user, TRUE); 2494099Seric stripquotes(host, TRUE); 2503233Seric } 2514099Seric else 2524099Seric { 2534099Seric stripquotes(user, FALSE); 2544099Seric stripquotes(host, FALSE); 2554099Seric } 2563233Seric 2579206Seric /* hack attack -- delivermail compatibility */ 2589206Seric if (m == ProgMailer && *user == '|') 2599206Seric user++; 2609206Seric 2613233Seric /* 2624161Seric ** If an error message has already been given, don't 2634161Seric ** bother to send to this address. 2644161Seric ** 2654161Seric ** >>>>>>>>>> This clause assumes that the local mailer 2664161Seric ** >> NOTE >> cannot do any further aliasing; that 2674161Seric ** >>>>>>>>>> function is subsumed by sendmail. 2684161Seric */ 2694161Seric 2707293Seric if (bitset(QBADADDR|QQUEUEUP, to->q_flags)) 2714161Seric continue; 2724161Seric 2734283Seric /* save statistics.... */ 2749370Seric markstats(e, to); 2754283Seric 2764161Seric /* 2773233Seric ** See if this user name is "special". 2783233Seric ** If the user name has a slash in it, assume that this 2796974Seric ** is a file -- send it off without further ado. Note 2806974Seric ** that this type of addresses is not processed along 2816974Seric ** with the others, so we fudge on the To person. 2823233Seric */ 2833233Seric 2844596Seric if (m == LocalMailer) 2853233Seric { 2865599Seric if (user[0] == '/') 287294Seric { 2888003Seric rcode = mailfile(user, getctladdr(to)); 28910105Seric giveresponse(rcode, m, e); 2903233Seric continue; 291294Seric } 292294Seric } 2933233Seric 2944315Seric /* 2954315Seric ** Address is verified -- add this user to mailer 2964315Seric ** argv, and add it to the print list of recipients. 2974315Seric */ 2984315Seric 2996059Seric /* link together the chain of recipients */ 3006272Seric to->q_tchain = tochain; 3016272Seric tochain = to; 3026059Seric 3033233Seric /* create list of users for error messages */ 3049388Seric (void) strcat(tobuf, ","); 3054082Seric (void) strcat(tobuf, to->q_paddr); 3069370Seric define('u', user, e); /* to user */ 3079370Seric define('z', to->q_home, e); /* user's home */ 3083233Seric 3094863Seric /* 3106059Seric ** Expand out this user into argument list. 3114863Seric */ 3124863Seric 3136059Seric if (!clever) 3143233Seric { 3159370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 3164863Seric *pvp++ = newstr(buf); 3174863Seric if (pvp >= &pv[MAXPV - 2]) 3184863Seric { 3194863Seric /* allow some space for trailing parms */ 3204863Seric break; 3214863Seric } 3224863Seric } 323294Seric } 324294Seric 3254067Seric /* see if any addresses still exist */ 3264067Seric if (tobuf[0] == '\0') 3274863Seric { 3289370Seric define('g', (char *) NULL, e); 3294067Seric return (0); 3304863Seric } 3314067Seric 3323233Seric /* print out messages as full list */ 3339388Seric e->e_to = tobuf + 1; 3343233Seric 335294Seric /* 3363233Seric ** Fill out any parameters after the $u parameter. 337294Seric */ 338294Seric 3394863Seric while (!clever && *++mvp != NULL) 340294Seric { 3419370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 3423233Seric *pvp++ = newstr(buf); 3433233Seric if (pvp >= &pv[MAXPV]) 3443233Seric syserr("deliver: pv overflow after $u for %s", pv[0]); 345294Seric } 3463233Seric *pvp++ = NULL; 347294Seric 348294Seric /* 349294Seric ** Call the mailer. 3502898Seric ** The argument vector gets built, pipes 351294Seric ** are created as necessary, and we fork & exec as 3522898Seric ** appropriate. 3534863Seric ** If we are running SMTP, we just need to clean up. 354294Seric */ 355294Seric 3569370Seric message(Arpa_Info, "Connecting to %s.%s...", host, m->m_name); 3579370Seric 3584397Seric if (ctladdr == NULL) 3599370Seric ctladdr = &e->e_from; 3605179Seric # ifdef SMTP 3614863Seric if (clever) 3624863Seric { 3639370Seric /* send the initial SMTP protocol */ 36410168Seric rcode = smtpinit(m, pv); 3659370Seric 3669388Seric if (rcode == EX_OK) 3679370Seric { 3689388Seric /* send the recipient list */ 3699388Seric tobuf[0] = '\0'; 3709388Seric for (to = tochain; to != NULL; to = to->q_tchain) 3719388Seric { 3729388Seric int i; 3739370Seric 3749388Seric e->e_to = to->q_paddr; 37510168Seric i = smtprcpt(to, m); 3769388Seric if (i != EX_OK) 3779388Seric { 37810092Seric markfailure(e, to, i); 37910105Seric giveresponse(i, m, e); 3809388Seric } 3819388Seric else 3829388Seric { 38323102Seric (void) strcat(tobuf, ","); 38423102Seric (void) strcat(tobuf, to->q_paddr); 3859388Seric } 3869388Seric } 3879388Seric 3889388Seric /* now send the data */ 3899388Seric if (tobuf[0] == '\0') 3909388Seric e->e_to = NULL; 3919370Seric else 3929370Seric { 3939388Seric e->e_to = tobuf + 1; 39410168Seric rcode = smtpdata(m, e); 3959370Seric } 3969388Seric 3979388Seric /* now close the connection */ 39815531Seric smtpquit(m); 3999370Seric } 4004863Seric } 4014863Seric else 4025179Seric # endif SMTP 40310168Seric rcode = sendoff(e, m, pv, ctladdr); 4043233Seric 4054621Seric /* 4069388Seric ** Do final status disposal. 4079388Seric ** We check for something in tobuf for the SMTP case. 4089388Seric ** If we got a temporary failure, arrange to queue the 4099388Seric ** addressees. 4104621Seric */ 4114621Seric 4129388Seric if (tobuf[0] != '\0') 41310105Seric giveresponse(rcode, m, e); 4149388Seric if (rcode != EX_OK) 4154621Seric { 4165032Seric for (to = tochain; to != NULL; to = to->q_tchain) 41710092Seric markfailure(e, to, rcode); 4184621Seric } 4194621Seric 4204488Seric errno = 0; 4219370Seric define('g', (char *) NULL, e); 4228003Seric return (rcode); 4233233Seric } 4243233Seric /* 42510092Seric ** MARKFAILURE -- mark a failure on a specific address. 42610092Seric ** 42710092Seric ** Parameters: 42810092Seric ** e -- the envelope we are sending. 42910092Seric ** q -- the address to mark. 43010092Seric ** rcode -- the code signifying the particular failure. 43110092Seric ** 43210092Seric ** Returns: 43310092Seric ** none. 43410092Seric ** 43510092Seric ** Side Effects: 43610092Seric ** marks the address (and possibly the envelope) with the 43710092Seric ** failure so that an error will be returned or 43810092Seric ** the message will be queued, as appropriate. 43910092Seric */ 44010092Seric 44110092Seric markfailure(e, q, rcode) 44210092Seric register ENVELOPE *e; 44310092Seric register ADDRESS *q; 44410092Seric int rcode; 44510092Seric { 44610092Seric if (rcode == EX_OK) 44710092Seric return; 44810092Seric else if (rcode != EX_TEMPFAIL) 44910092Seric q->q_flags |= QBADADDR; 45010092Seric else if (curtime() > e->e_ctime + TimeOut) 45110092Seric { 45210092Seric extern char *pintvl(); 45310105Seric char buf[MAXLINE]; 45410092Seric 45510092Seric if (!bitset(EF_TIMEOUT, e->e_flags)) 45610105Seric { 45710105Seric (void) sprintf(buf, "Cannot send message for %s", 45810092Seric pintvl(TimeOut, FALSE)); 45910105Seric if (e->e_message != NULL) 46010105Seric free(e->e_message); 46110105Seric e->e_message = newstr(buf); 46210105Seric message(Arpa_Info, buf); 46310105Seric } 46410092Seric q->q_flags |= QBADADDR; 46510092Seric e->e_flags |= EF_TIMEOUT; 46610092Seric } 46710092Seric else 46810092Seric q->q_flags |= QQUEUEUP; 46910092Seric } 47010092Seric /* 4714214Seric ** DOFORK -- do a fork, retrying a couple of times on failure. 4724214Seric ** 4734214Seric ** This MUST be a macro, since after a vfork we are running 4744214Seric ** two processes on the same stack!!! 4754214Seric ** 4764214Seric ** Parameters: 4774214Seric ** none. 4784214Seric ** 4794214Seric ** Returns: 4804214Seric ** From a macro??? You've got to be kidding! 4814214Seric ** 4824214Seric ** Side Effects: 4834214Seric ** Modifies the ==> LOCAL <== variable 'pid', leaving: 4844214Seric ** pid of child in parent, zero in child. 4854214Seric ** -1 on unrecoverable error. 4864214Seric ** 4874214Seric ** Notes: 4884214Seric ** I'm awfully sorry this looks so awful. That's 4894214Seric ** vfork for you..... 4904214Seric */ 4914214Seric 4924214Seric # define NFORKTRIES 5 4939148Seric # ifdef VMUNIX 4944214Seric # define XFORK vfork 4959148Seric # else VMUNIX 4964214Seric # define XFORK fork 4979148Seric # endif VMUNIX 4984214Seric 4994214Seric # define DOFORK(fORKfN) \ 5004214Seric {\ 5014214Seric register int i;\ 5024214Seric \ 50323504Seric for (i = NFORKTRIES; --i >= 0; )\ 5044214Seric {\ 5054214Seric pid = fORKfN();\ 5064214Seric if (pid >= 0)\ 5074214Seric break;\ 50823504Seric if (i > 0)\ 50923504Seric sleep(NFORKTRIES - i);\ 5104214Seric }\ 5114214Seric } 5124214Seric /* 5134637Seric ** DOFORK -- simple fork interface to DOFORK. 5144637Seric ** 5154637Seric ** Parameters: 5164637Seric ** none. 5174637Seric ** 5184637Seric ** Returns: 5194637Seric ** pid of child in parent. 5204637Seric ** zero in child. 5214637Seric ** -1 on error. 5224637Seric ** 5234637Seric ** Side Effects: 5244637Seric ** returns twice, once in parent and once in child. 5254637Seric */ 5264637Seric 5274637Seric dofork() 5284637Seric { 5294637Seric register int pid; 5304637Seric 5314637Seric DOFORK(fork); 5324637Seric return (pid); 5334637Seric } 5344637Seric /* 5353233Seric ** SENDOFF -- send off call to mailer & collect response. 5363233Seric ** 5373233Seric ** Parameters: 5389370Seric ** e -- the envelope to mail. 5393233Seric ** m -- mailer descriptor. 5403233Seric ** pvp -- parameter vector to send to it. 5414397Seric ** ctladdr -- an address pointer controlling the 5424397Seric ** user/groupid etc. of the mailer. 5433233Seric ** 5443233Seric ** Returns: 5453233Seric ** exit status of mailer. 5463233Seric ** 5473233Seric ** Side Effects: 5483233Seric ** none. 5493233Seric */ 5503233Seric 55110168Seric sendoff(e, m, pvp, ctladdr) 5529370Seric register ENVELOPE *e; 5539370Seric MAILER *m; 5543233Seric char **pvp; 5554397Seric ADDRESS *ctladdr; 5563233Seric { 5574863Seric auto FILE *mfile; 5584863Seric auto FILE *rfile; 5593233Seric register int i; 5603233Seric int pid; 5614863Seric 5624863Seric /* 5634863Seric ** Create connection to mailer. 5644863Seric */ 5654863Seric 5664863Seric pid = openmailer(m, pvp, ctladdr, FALSE, &mfile, &rfile); 5674863Seric if (pid < 0) 5684863Seric return (-1); 5694863Seric 5704863Seric /* 5714863Seric ** Format and send message. 5724863Seric */ 5734863Seric 57410168Seric putfromline(mfile, m); 57510168Seric (*e->e_puthdr)(mfile, m, e); 57610168Seric putline("\n", mfile, m); 57710168Seric (*e->e_putbody)(mfile, m, e); 5784863Seric (void) fclose(mfile); 5794863Seric 5804863Seric i = endmailer(pid, pvp[0]); 5815981Seric 5825981Seric /* arrange a return receipt if requested */ 58310682Seric if (e->e_receiptto != NULL && bitnset(M_LOCAL, m->m_flags)) 5845981Seric { 5859370Seric e->e_flags |= EF_SENDRECEIPT; 5865981Seric /* do we want to send back more info? */ 5875981Seric } 5885981Seric 5894863Seric return (i); 5904863Seric } 5914863Seric /* 5924863Seric ** ENDMAILER -- Wait for mailer to terminate. 5934863Seric ** 5944863Seric ** We should never get fatal errors (e.g., segmentation 5954863Seric ** violation), so we report those specially. For other 5964863Seric ** errors, we choose a status message (into statmsg), 5974863Seric ** and if it represents an error, we print it. 5984863Seric ** 5994863Seric ** Parameters: 6004863Seric ** pid -- pid of mailer. 6014863Seric ** name -- name of mailer (for error messages). 6024863Seric ** 6034863Seric ** Returns: 6044863Seric ** exit code of mailer. 6054863Seric ** 6064863Seric ** Side Effects: 6074863Seric ** none. 6084863Seric */ 6094863Seric 6104863Seric endmailer(pid, name) 6114863Seric int pid; 6124863Seric char *name; 6134863Seric { 6149370Seric int st; 6154863Seric 6166038Seric /* in the IPC case there is nothing to wait for */ 6176038Seric if (pid == 0) 6186038Seric return (EX_OK); 6196038Seric 6206038Seric /* wait for the mailer process to die and collect status */ 6219370Seric st = waitfor(pid); 6229370Seric if (st == -1) 6238127Seric { 6249370Seric syserr("endmailer %s: wait", name); 6259370Seric return (EX_SOFTWARE); 6264863Seric } 6276038Seric 6286038Seric /* see if it died a horrid death */ 6294863Seric if ((st & 0377) != 0) 6304863Seric { 63124941Seric syserr("mailer %s died with signal %o", name, st); 63224941Seric ExitStat = EX_TEMPFAIL; 63324941Seric return (EX_TEMPFAIL); 6344863Seric } 6356038Seric 6366038Seric /* normal death -- return status */ 6379370Seric st = (st >> 8) & 0377; 6389370Seric return (st); 6394863Seric } 6404863Seric /* 6414863Seric ** OPENMAILER -- open connection to mailer. 6424863Seric ** 6434863Seric ** Parameters: 6444863Seric ** m -- mailer descriptor. 6454863Seric ** pvp -- parameter vector to pass to mailer. 6464863Seric ** ctladdr -- controlling address for user. 6474863Seric ** clever -- create a full duplex connection. 6484863Seric ** pmfile -- pointer to mfile (to mailer) connection. 6494863Seric ** prfile -- pointer to rfile (from mailer) connection. 6504863Seric ** 6514863Seric ** Returns: 6526038Seric ** pid of mailer ( > 0 ). 6534863Seric ** -1 on error. 6546038Seric ** zero on an IPC connection. 6554863Seric ** 6564863Seric ** Side Effects: 6574863Seric ** creates a mailer in a subprocess. 6584863Seric */ 6594863Seric 6604863Seric openmailer(m, pvp, ctladdr, clever, pmfile, prfile) 6619370Seric MAILER *m; 6624863Seric char **pvp; 6634863Seric ADDRESS *ctladdr; 6644863Seric bool clever; 6654863Seric FILE **pmfile; 6664863Seric FILE **prfile; 6674863Seric { 6684863Seric int pid; 6694709Seric int mpvect[2]; 6704863Seric int rpvect[2]; 6713233Seric FILE *mfile; 6724863Seric FILE *rfile; 6733233Seric extern FILE *fdopen(); 6743233Seric 6753233Seric # ifdef DEBUG 6767672Seric if (tTd(11, 1)) 677294Seric { 6788178Seric printf("openmailer:"); 6793233Seric printav(pvp); 680294Seric } 6813233Seric # endif DEBUG 6824488Seric errno = 0; 6833233Seric 6846038Seric /* 6856038Seric ** Deal with the special case of mail handled through an IPC 6866038Seric ** connection. 6876038Seric ** In this case we don't actually fork. We must be 6886038Seric ** running SMTP for this to work. We will return a 6896038Seric ** zero pid to indicate that we are running IPC. 69011160Seric ** We also handle a debug version that just talks to stdin/out. 6916038Seric */ 6926038Seric 69311160Seric #ifdef DEBUG 69411160Seric /* check for Local Person Communication -- not for mortals!!! */ 69511160Seric if (strcmp(m->m_mailer, "[LPC]") == 0) 69611160Seric { 69711160Seric *pmfile = stdout; 69811160Seric *prfile = stdin; 69911160Seric return (0); 70011160Seric } 70111160Seric #endif DEBUG 70211160Seric 7036038Seric if (strcmp(m->m_mailer, "[IPC]") == 0) 7046038Seric { 70524941Seric #ifdef HOSTINFO 70624941Seric register STAB *st; 70724941Seric extern STAB *stab(); 70824941Seric #endif HOSTINFO 7099370Seric #ifdef DAEMON 7106038Seric register int i; 7117285Seric register u_short port; 7126038Seric 7136038Seric if (!clever) 7146038Seric syserr("non-clever IPC"); 7156632Seric if (pvp[2] != NULL) 7167285Seric port = atoi(pvp[2]); 7176632Seric else 7187285Seric port = 0; 71924941Seric #ifdef HOSTINFO 72024941Seric /* see if we have already determined that this host is fried */ 72124941Seric st = stab(pvp[1], ST_HOST, ST_FIND); 72224941Seric if (st == NULL || st->s_host.ho_exitstat == EX_OK) 72324941Seric i = makeconnection(pvp[1], port, pmfile, prfile); 72424941Seric else 72524941Seric i = st->s_host.ho_exitstat; 72624941Seric #else HOSTINFO 7277285Seric i = makeconnection(pvp[1], port, pmfile, prfile); 72824941Seric #endif HOSTINFO 7296038Seric if (i != EX_OK) 7306047Seric { 73124941Seric #ifdef HOSTINFO 73224941Seric /* enter status of this host */ 73324941Seric if (st == NULL) 73424941Seric st = stab(pvp[1], ST_HOST, ST_ENTER); 73524941Seric st->s_host.ho_exitstat = i; 73624941Seric st->s_host.ho_errno = errno; 73724941Seric #endif HOSTINFO 7386047Seric ExitStat = i; 7396038Seric return (-1); 7406047Seric } 7416038Seric else 7426038Seric return (0); 7439370Seric #else DAEMON 7449370Seric syserr("openmailer: no IPC"); 7459370Seric return (-1); 7469370Seric #endif DAEMON 7476038Seric } 7486038Seric 7492898Seric /* create a pipe to shove the mail through */ 7504709Seric if (pipe(mpvect) < 0) 751294Seric { 7529370Seric syserr("openmailer: pipe (to mailer)"); 753294Seric return (-1); 754294Seric } 7554863Seric 7569370Seric #ifdef SMTP 7574863Seric /* if this mailer speaks smtp, create a return pipe */ 7584863Seric if (clever && pipe(rpvect) < 0) 7594863Seric { 7609370Seric syserr("openmailer: pipe (from mailer)"); 7614863Seric (void) close(mpvect[0]); 7624863Seric (void) close(mpvect[1]); 7634863Seric return (-1); 7644863Seric } 7659370Seric #endif SMTP 7664863Seric 7676038Seric /* 7686038Seric ** Actually fork the mailer process. 7696038Seric ** DOFORK is clever about retrying. 7706038Seric */ 7716038Seric 7729538Seric if (CurEnv->e_xfp != NULL) 7739538Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 7749370Seric (void) fflush(stdout); 7754214Seric DOFORK(XFORK); 7764327Seric /* pid is set by DOFORK */ 777294Seric if (pid < 0) 778294Seric { 7796038Seric /* failure */ 7809370Seric syserr("openmailer: cannot fork"); 7814709Seric (void) close(mpvect[0]); 7824709Seric (void) close(mpvect[1]); 7839370Seric #ifdef SMTP 7844863Seric if (clever) 7854863Seric { 7864863Seric (void) close(rpvect[0]); 7874863Seric (void) close(rpvect[1]); 7884863Seric } 7899370Seric #endif SMTP 790294Seric return (-1); 791294Seric } 792294Seric else if (pid == 0) 793294Seric { 79415772Seric int i; 79524941Seric extern int DtableSize; 79615772Seric 797294Seric /* child -- set up input & exec mailer */ 7981621Seric /* make diagnostic output be standard output */ 7994477Seric (void) signal(SIGINT, SIG_IGN); 8004477Seric (void) signal(SIGHUP, SIG_IGN); 8014215Seric (void) signal(SIGTERM, SIG_DFL); 8024709Seric 8034709Seric /* arrange to filter standard & diag output of command */ 8044863Seric if (clever) 8054709Seric { 8064863Seric (void) close(rpvect[0]); 8074709Seric (void) close(1); 8084863Seric (void) dup(rpvect[1]); 8094863Seric (void) close(rpvect[1]); 8104863Seric } 8119275Seric else if (OpMode == MD_SMTP || HoldErrs) 8124863Seric { 8139370Seric /* put mailer output in transcript */ 8144863Seric (void) close(1); 8159538Seric (void) dup(fileno(CurEnv->e_xfp)); 8164709Seric } 8174082Seric (void) close(2); 8184082Seric (void) dup(1); 8194709Seric 8204709Seric /* arrange to get standard input */ 8214709Seric (void) close(mpvect[1]); 8224082Seric (void) close(0); 8234709Seric if (dup(mpvect[0]) < 0) 824294Seric { 8252898Seric syserr("Cannot dup to zero!"); 8262898Seric _exit(EX_OSERR); 827294Seric } 8284709Seric (void) close(mpvect[0]); 82910682Seric if (!bitnset(M_RESTR, m->m_flags)) 8304215Seric { 83116883Seric if (ctladdr == NULL || ctladdr->q_uid == 0) 8324417Seric { 8334417Seric (void) setgid(DefGid); 8344417Seric (void) setuid(DefUid); 8354417Seric } 8364417Seric else 8374415Seric { 8384417Seric (void) setgid(ctladdr->q_gid); 8394417Seric (void) setuid(ctladdr->q_uid); 8404415Seric } 8414215Seric } 8429370Seric 84315772Seric /* arrange for all the files to be closed */ 84424941Seric for (i = 3; i < DtableSize; i++) 84515772Seric #ifdef FIOCLEX 84615772Seric (void) ioctl(i, FIOCLEX, 0); 84715772Seric #else FIOCLEX 84815772Seric (void) close(i); 84915772Seric #endif FIOCLEX 8502774Seric 8516038Seric /* try to execute the mailer */ 852*25026Seric execve(m->m_mailer, pvp, UserEnviron); 8536038Seric 85415772Seric #ifdef FIOCLEX 85515772Seric syserr("Cannot exec %s", m->m_mailer); 85615772Seric #else FIOCLEX 8574214Seric printf("Cannot exec '%s' errno=%d\n", m->m_mailer, errno); 8584082Seric (void) fflush(stdout); 85915772Seric #endif FIOCLEX 86024941Seric if (m == LocalMailer || errno == EIO || errno == EAGAIN || 86124941Seric errno == ENOMEM || errno == EPROCLIM) 86216902Seric _exit(EX_TEMPFAIL); 86316902Seric else 86416902Seric _exit(EX_UNAVAILABLE); 865294Seric } 866294Seric 8674709Seric /* 8684863Seric ** Set up return value. 8694709Seric */ 8704709Seric 8714709Seric (void) close(mpvect[0]); 8724709Seric mfile = fdopen(mpvect[1], "w"); 8734863Seric if (clever) 8744863Seric { 8754863Seric (void) close(rpvect[1]); 8764863Seric rfile = fdopen(rpvect[0], "r"); 8774863Seric } 878294Seric 8794863Seric *pmfile = mfile; 8804863Seric *prfile = rfile; 881294Seric 8824863Seric return (pid); 883294Seric } 884294Seric /* 885294Seric ** GIVERESPONSE -- Interpret an error response from a mailer 886294Seric ** 887294Seric ** Parameters: 888294Seric ** stat -- the status code from the mailer (high byte 889294Seric ** only; core dumps must have been taken care of 890294Seric ** already). 891294Seric ** m -- the mailer descriptor for this mailer. 892294Seric ** 893294Seric ** Returns: 8944082Seric ** none. 895294Seric ** 896294Seric ** Side Effects: 8971518Seric ** Errors may be incremented. 898294Seric ** ExitStat may be set. 899294Seric */ 900294Seric 90110105Seric giveresponse(stat, m, e) 902294Seric int stat; 9039370Seric register MAILER *m; 90410105Seric ENVELOPE *e; 905294Seric { 906294Seric register char *statmsg; 907294Seric extern char *SysExMsg[]; 908294Seric register int i; 909294Seric extern int N_SysEx; 91010105Seric char buf[MAXLINE]; 911294Seric 91212135Seric #ifdef lint 91312135Seric if (m == NULL) 91412135Seric return; 91512135Seric #endif lint 91612135Seric 9174315Seric /* 9184315Seric ** Compute status message from code. 9194315Seric */ 9204315Seric 921294Seric i = stat - EX__BASE; 9229370Seric if (stat == 0) 9239370Seric statmsg = "250 Sent"; 9249370Seric else if (i < 0 || i > N_SysEx) 9259370Seric { 9269370Seric (void) sprintf(buf, "554 unknown mailer error %d", stat); 9279370Seric stat = EX_UNAVAILABLE; 9289370Seric statmsg = buf; 9299370Seric } 93010105Seric else if (stat == EX_TEMPFAIL) 93110105Seric { 93210124Seric (void) strcpy(buf, SysExMsg[i]); 93310124Seric if (errno != 0) 93410105Seric { 93515137Seric extern char *errstring(); 93615137Seric 93721061Seric statmsg = errstring(errno); 93821061Seric } 93921061Seric else 94021061Seric { 94121061Seric #ifdef SMTP 94221061Seric extern char SmtpError[]; 94321061Seric 94421061Seric statmsg = SmtpError; 94521061Seric #else SMTP 94621061Seric statmsg = NULL; 94721061Seric #endif SMTP 94821061Seric } 94921061Seric if (statmsg != NULL && statmsg[0] != '\0') 95021061Seric { 95110124Seric (void) strcat(buf, ": "); 95221061Seric (void) strcat(buf, statmsg); 95310105Seric } 95410105Seric statmsg = buf; 95510105Seric } 956294Seric else 95721061Seric { 958294Seric statmsg = SysExMsg[i]; 95921061Seric } 9609370Seric 9619370Seric /* 9629370Seric ** Print the message as appropriate 9639370Seric */ 9649370Seric 96510105Seric if (stat == EX_OK || stat == EX_TEMPFAIL) 9668003Seric message(Arpa_Info, &statmsg[4]); 967294Seric else 968294Seric { 9691518Seric Errors++; 9709370Seric usrerr(statmsg); 971294Seric } 972294Seric 973294Seric /* 974294Seric ** Final cleanup. 975294Seric ** Log a record of the transaction. Compute the new 976294Seric ** ExitStat -- if we already had an error, stick with 977294Seric ** that. 978294Seric */ 979294Seric 9807680Seric if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2)) 9818496Seric logdelivery(&statmsg[4]); 9827858Seric 9834621Seric if (stat != EX_TEMPFAIL) 9844621Seric setstat(stat); 98510105Seric if (stat != EX_OK) 98610105Seric { 98710105Seric if (e->e_message != NULL) 98810105Seric free(e->e_message); 98910105Seric e->e_message = newstr(&statmsg[4]); 99010105Seric } 99110124Seric errno = 0; 992294Seric } 993294Seric /* 9948496Seric ** LOGDELIVERY -- log the delivery in the system log 9958496Seric ** 9968496Seric ** Parameters: 9978496Seric ** stat -- the message to print for the status 9988496Seric ** 9998496Seric ** Returns: 10008496Seric ** none 10018496Seric ** 10028496Seric ** Side Effects: 10038496Seric ** none 10048496Seric */ 10058496Seric 10068496Seric logdelivery(stat) 10078496Seric char *stat; 10088496Seric { 10098496Seric extern char *pintvl(); 10108496Seric 10118496Seric # ifdef LOG 10128496Seric syslog(LOG_INFO, "%s: to=%s, delay=%s, stat=%s", CurEnv->e_id, 10138496Seric CurEnv->e_to, pintvl(curtime() - CurEnv->e_ctime, TRUE), stat); 10148496Seric # endif LOG 10158496Seric } 10168496Seric /* 10176974Seric ** PUTFROMLINE -- output a UNIX-style from line (or whatever) 1018294Seric ** 10196974Seric ** This can be made an arbitrary message separator by changing $l 1020294Seric ** 102116150Seric ** One of the ugliest hacks seen by human eyes is contained herein: 102216150Seric ** UUCP wants those stupid "remote from <host>" lines. Why oh why 102316150Seric ** does a well-meaning programmer such as myself have to deal with 102416150Seric ** this kind of antique garbage???? 10256974Seric ** 1026294Seric ** Parameters: 10276974Seric ** fp -- the file to output to. 10286974Seric ** m -- the mailer describing this entry. 1029294Seric ** 1030294Seric ** Returns: 10316974Seric ** none 1032294Seric ** 1033294Seric ** Side Effects: 10346974Seric ** outputs some text to fp. 1035294Seric */ 1036294Seric 103710168Seric putfromline(fp, m) 10386974Seric register FILE *fp; 10396974Seric register MAILER *m; 1040294Seric { 104116150Seric char *template = "\001l\n"; 10426974Seric char buf[MAXLINE]; 1043294Seric 104410682Seric if (bitnset(M_NHDR, m->m_flags)) 10456974Seric return; 10464315Seric 10476974Seric # ifdef UGLYUUCP 104810682Seric if (bitnset(M_UGLYUUCP, m->m_flags)) 10494205Seric { 105012223Seric char *bang; 105112223Seric char xbuf[MAXLINE]; 10526041Seric 105316150Seric expand("\001g", buf, &buf[sizeof buf - 1], CurEnv); 105412223Seric bang = index(buf, '!'); 10556974Seric if (bang == NULL) 105612223Seric syserr("No ! in UUCP! (%s)", buf); 10575099Seric else 10589370Seric { 105912223Seric *bang++ = '\0'; 106016150Seric (void) sprintf(xbuf, "From %s \001d remote from %s\n", bang, buf); 106112223Seric template = xbuf; 10629370Seric } 10636974Seric } 10645179Seric # endif UGLYUUCP 106512223Seric expand(template, buf, &buf[sizeof buf - 1], CurEnv); 106610168Seric putline(buf, fp, m); 10675981Seric } 10685981Seric /* 10696974Seric ** PUTBODY -- put the body of a message. 10706974Seric ** 10716974Seric ** Parameters: 10726974Seric ** fp -- file to output onto. 107310168Seric ** m -- a mailer descriptor to control output format. 10749538Seric ** e -- the envelope to put out. 10756974Seric ** 10766974Seric ** Returns: 10776974Seric ** none. 10786974Seric ** 10796974Seric ** Side Effects: 10806974Seric ** The message is written onto fp. 10816974Seric */ 10826974Seric 108310168Seric putbody(fp, m, e) 10846974Seric FILE *fp; 10859370Seric MAILER *m; 10869538Seric register ENVELOPE *e; 10876974Seric { 108810168Seric char buf[MAXLINE]; 10896974Seric 10906974Seric /* 10916974Seric ** Output the body of the message 10926974Seric */ 10936974Seric 10949538Seric if (e->e_dfp == NULL) 10956974Seric { 10969538Seric if (e->e_df != NULL) 10979538Seric { 10989538Seric e->e_dfp = fopen(e->e_df, "r"); 10999538Seric if (e->e_dfp == NULL) 11009538Seric syserr("Cannot open %s", e->e_df); 11019538Seric } 11029538Seric else 110310168Seric putline("<<< No Message Collected >>>", fp, m); 11049538Seric } 11059538Seric if (e->e_dfp != NULL) 11069538Seric { 11079538Seric rewind(e->e_dfp); 110810168Seric while (!ferror(fp) && fgets(buf, sizeof buf, e->e_dfp) != NULL) 110916875Seric { 111016875Seric if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) && 111116875Seric strncmp(buf, "From", 4) == 0) 111223102Seric (void) putc('>', fp); 111310168Seric putline(buf, fp, m); 111416875Seric } 11156974Seric 11169538Seric if (ferror(e->e_dfp)) 11176974Seric { 11186974Seric syserr("putbody: read error"); 11196974Seric ExitStat = EX_IOERR; 11206974Seric } 11216974Seric } 11226974Seric 11236974Seric (void) fflush(fp); 11246974Seric if (ferror(fp) && errno != EPIPE) 11256974Seric { 11266974Seric syserr("putbody: write error"); 11276974Seric ExitStat = EX_IOERR; 11286974Seric } 11296974Seric errno = 0; 11306974Seric } 11316974Seric /* 1132294Seric ** MAILFILE -- Send a message to a file. 1133294Seric ** 11344327Seric ** If the file has the setuid/setgid bits set, but NO execute 11354327Seric ** bits, sendmail will try to become the owner of that file 11364327Seric ** rather than the real user. Obviously, this only works if 11374327Seric ** sendmail runs as root. 11384327Seric ** 11399370Seric ** This could be done as a subordinate mailer, except that it 11409370Seric ** is used implicitly to save messages in ~/dead.letter. We 11419370Seric ** view this as being sufficiently important as to include it 11429370Seric ** here. For example, if the system is dying, we shouldn't have 11439370Seric ** to create another process plus some pipes to save the message. 11449370Seric ** 1145294Seric ** Parameters: 1146294Seric ** filename -- the name of the file to send to. 11474397Seric ** ctladdr -- the controlling address header -- includes 11484397Seric ** the userid/groupid to be when sending. 1149294Seric ** 1150294Seric ** Returns: 1151294Seric ** The exit code associated with the operation. 1152294Seric ** 1153294Seric ** Side Effects: 1154294Seric ** none. 1155294Seric */ 1156294Seric 11574397Seric mailfile(filename, ctladdr) 1158294Seric char *filename; 11594397Seric ADDRESS *ctladdr; 1160294Seric { 1161294Seric register FILE *f; 11624214Seric register int pid; 1163294Seric 11644214Seric /* 11654214Seric ** Fork so we can change permissions here. 11664214Seric ** Note that we MUST use fork, not vfork, because of 11674214Seric ** the complications of calling subroutines, etc. 11684214Seric */ 11694067Seric 11704214Seric DOFORK(fork); 11714214Seric 11724214Seric if (pid < 0) 11734214Seric return (EX_OSERR); 11744214Seric else if (pid == 0) 11754214Seric { 11764214Seric /* child -- actually write to file */ 11774327Seric struct stat stb; 11784327Seric 11794215Seric (void) signal(SIGINT, SIG_DFL); 11804215Seric (void) signal(SIGHUP, SIG_DFL); 11814215Seric (void) signal(SIGTERM, SIG_DFL); 118223102Seric (void) umask(OldUmask); 11834327Seric if (stat(filename, &stb) < 0) 118411935Seric { 118511935Seric errno = 0; 11864431Seric stb.st_mode = 0666; 118711935Seric } 11884327Seric if (bitset(0111, stb.st_mode)) 11894327Seric exit(EX_CANTCREAT); 11904401Seric if (ctladdr == NULL) 11916900Seric ctladdr = &CurEnv->e_from; 11924327Seric if (!bitset(S_ISGID, stb.st_mode) || setgid(stb.st_gid) < 0) 11934417Seric { 11944417Seric if (ctladdr->q_uid == 0) 11954417Seric (void) setgid(DefGid); 11964417Seric else 11974417Seric (void) setgid(ctladdr->q_gid); 11984417Seric } 11994327Seric if (!bitset(S_ISUID, stb.st_mode) || setuid(stb.st_uid) < 0) 12004417Seric { 12014417Seric if (ctladdr->q_uid == 0) 12024417Seric (void) setuid(DefUid); 12034417Seric else 12044417Seric (void) setuid(ctladdr->q_uid); 12054417Seric } 12066887Seric f = dfopen(filename, "a"); 12074214Seric if (f == NULL) 12084214Seric exit(EX_CANTCREAT); 12094214Seric 121010168Seric putfromline(f, ProgMailer); 121110168Seric (*CurEnv->e_puthdr)(f, ProgMailer, CurEnv); 121210168Seric putline("\n", f, ProgMailer); 121310168Seric (*CurEnv->e_putbody)(f, ProgMailer, CurEnv); 121410168Seric putline("\n", f, ProgMailer); 12154214Seric (void) fclose(f); 12164214Seric (void) fflush(stdout); 12174417Seric 12186887Seric /* reset ISUID & ISGID bits for paranoid systems */ 12194621Seric (void) chmod(filename, (int) stb.st_mode); 12204214Seric exit(EX_OK); 12214315Seric /*NOTREACHED*/ 12224214Seric } 12234214Seric else 12244214Seric { 12254214Seric /* parent -- wait for exit status */ 12269370Seric int st; 12274214Seric 12289370Seric st = waitfor(pid); 12299370Seric if ((st & 0377) != 0) 12309370Seric return (EX_UNAVAILABLE); 12319370Seric else 12329370Seric return ((st >> 8) & 0377); 12334214Seric } 1234294Seric } 12354550Seric /* 12364550Seric ** SENDALL -- actually send all the messages. 12374550Seric ** 12384550Seric ** Parameters: 12397043Seric ** e -- the envelope to send. 124014874Seric ** mode -- the delivery mode to use. If SM_DEFAULT, use 124114874Seric ** the current SendMode. 12424550Seric ** 12434550Seric ** Returns: 12444550Seric ** none. 12454550Seric ** 12464550Seric ** Side Effects: 12474550Seric ** Scans the send lists and sends everything it finds. 12487043Seric ** Delivers any appropriate error messages. 12499275Seric ** If we are running in a non-interactive mode, takes the 12509275Seric ** appropriate action. 12514550Seric */ 12524550Seric 12539275Seric sendall(e, mode) 12547043Seric ENVELOPE *e; 12559275Seric char mode; 12564550Seric { 12575008Seric register ADDRESS *q; 12587779Seric bool oldverbose; 12599275Seric int pid; 12604550Seric 126114874Seric /* determine actual delivery mode */ 126214874Seric if (mode == SM_DEFAULT) 126314874Seric { 126424941Seric extern bool shouldqueue(); 126514874Seric 126624941Seric if (shouldqueue(e->e_msgpriority)) 126714874Seric mode = SM_QUEUE; 126814874Seric else 126914874Seric mode = SendMode; 127014874Seric } 127114874Seric 12729370Seric #ifdef DEBUG 12738248Seric if (tTd(13, 1)) 12745032Seric { 12759275Seric printf("\nSENDALL: mode %c, sendqueue:\n", mode); 12767043Seric printaddr(e->e_sendqueue, TRUE); 12775032Seric } 12789370Seric #endif DEBUG 12795008Seric 12807043Seric /* 12819275Seric ** Do any preprocessing necessary for the mode we are running. 12829370Seric ** Check to make sure the hop count is reasonable. 12839370Seric ** Delete sends to the sender in mailing lists. 12847043Seric */ 12857043Seric 12869370Seric CurEnv = e; 12879370Seric 12889370Seric if (e->e_hopcount > MAXHOP) 12899275Seric { 12909370Seric syserr("sendall: too many hops (%d max)", MAXHOP); 12919370Seric return; 12929370Seric } 12939275Seric 12949370Seric if (!MeToo) 12959370Seric { 129612611Seric extern ADDRESS *recipient(); 129712611Seric 12989370Seric e->e_from.q_flags |= QDONTSEND; 129912611Seric (void) recipient(&e->e_from, &e->e_sendqueue); 13009275Seric } 13019370Seric 13029370Seric # ifdef QUEUE 13039335Seric if ((mode == SM_QUEUE || mode == SM_FORK || 13049335Seric (mode != SM_VERIFY && SuperSafe)) && 13059335Seric !bitset(EF_INQUEUE, e->e_flags)) 13069370Seric queueup(e, TRUE, mode == SM_QUEUE); 13079275Seric #endif QUEUE 13089275Seric 13097779Seric oldverbose = Verbose; 13109275Seric switch (mode) 13119275Seric { 13129275Seric case SM_VERIFY: 13137779Seric Verbose = TRUE; 13149275Seric break; 13159275Seric 13169275Seric case SM_QUEUE: 13179335Seric e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; 13189275Seric return; 13199275Seric 13209275Seric case SM_FORK: 13219538Seric if (e->e_xfp != NULL) 13229538Seric (void) fflush(e->e_xfp); 13239275Seric pid = fork(); 13249275Seric if (pid < 0) 13259275Seric { 13269275Seric mode = SM_DELIVER; 13279275Seric break; 13289275Seric } 13299275Seric else if (pid > 0) 13309293Seric { 13319293Seric /* be sure we leave the temp files to our child */ 13329335Seric e->e_id = e->e_df = NULL; 13339275Seric return; 13349293Seric } 13359275Seric 13369275Seric /* double fork to avoid zombies */ 13379275Seric if (fork() > 0) 13389275Seric exit(EX_OK); 13399275Seric 13409293Seric /* be sure we are immune from the terminal */ 134110133Seric disconnect(FALSE); 13429293Seric 13439275Seric break; 13449275Seric } 13459275Seric 13469275Seric /* 13479275Seric ** Run through the list and send everything. 13489275Seric */ 13499275Seric 13507043Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 13514550Seric { 13529275Seric if (mode == SM_VERIFY) 13534550Seric { 13549293Seric e->e_to = q->q_paddr; 13555008Seric if (!bitset(QDONTSEND|QBADADDR, q->q_flags)) 13567052Seric message(Arpa_Info, "deliverable"); 13574550Seric } 13585008Seric else 13599370Seric (void) deliver(e, q); 13604550Seric } 13617779Seric Verbose = oldverbose; 13627043Seric 13637043Seric /* 13647043Seric ** Now run through and check for errors. 13657043Seric */ 13667043Seric 13679275Seric if (mode == SM_VERIFY) 13687043Seric return; 13697043Seric 13707043Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 13717043Seric { 13727043Seric register ADDRESS *qq; 13737043Seric 13748248Seric # ifdef DEBUG 13758248Seric if (tTd(13, 3)) 13768248Seric { 13778248Seric printf("Checking "); 13788248Seric printaddr(q, FALSE); 13798248Seric } 13808248Seric # endif DEBUG 13818248Seric 13829335Seric /* only send errors if the message failed */ 13839335Seric if (!bitset(QBADADDR, q->q_flags)) 13849335Seric continue; 13857043Seric 13867043Seric /* we have an address that failed -- find the parent */ 13877043Seric for (qq = q; qq != NULL; qq = qq->q_alias) 13887043Seric { 13897043Seric char obuf[MAXNAME + 6]; 13907043Seric extern char *aliaslookup(); 13917043Seric 13927043Seric /* we can only have owners for local addresses */ 139310682Seric if (!bitnset(M_LOCAL, qq->q_mailer->m_flags)) 13947043Seric continue; 13957043Seric 13967043Seric /* see if the owner list exists */ 13977043Seric (void) strcpy(obuf, "owner-"); 13987047Seric if (strncmp(qq->q_user, "owner-", 6) == 0) 13997047Seric (void) strcat(obuf, "owner"); 14007047Seric else 14017047Seric (void) strcat(obuf, qq->q_user); 14027043Seric if (aliaslookup(obuf) == NULL) 14037043Seric continue; 14047043Seric 14058248Seric # ifdef DEBUG 14068248Seric if (tTd(13, 4)) 14078248Seric printf("Errors to %s\n", obuf); 14088248Seric # endif DEBUG 14098248Seric 14107043Seric /* owner list exists -- add it to the error queue */ 14119615Seric sendtolist(obuf, (ADDRESS *) NULL, &e->e_errorqueue); 141216883Seric ErrorMode = EM_MAIL; 14137043Seric break; 14147043Seric } 14157043Seric 14167043Seric /* if we did not find an owner, send to the sender */ 14178426Seric if (qq == NULL && bitset(QBADADDR, q->q_flags)) 14189615Seric sendtolist(e->e_from.q_paddr, qq, &e->e_errorqueue); 14197043Seric } 14209275Seric 14219275Seric if (mode == SM_FORK) 14229275Seric finis(); 14234550Seric } 1424