122701Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 333728Sbostic * Copyright (c) 1988 Regents of the University of California. 433728Sbostic * All rights reserved. 533728Sbostic * 642825Sbostic * %sccs.include.redist.c% 733728Sbostic */ 822701Sdist 922701Sdist #ifndef lint 10*57441Seric static char sccsid[] = "@(#)deliver.c 6.5 (Berkeley) 01/10/93"; 1133728Sbostic #endif /* not lint */ 1222701Sdist 1340961Sbostic #include "sendmail.h" 1433931Sbostic #include <sys/signal.h> 1533931Sbostic #include <sys/stat.h> 1633931Sbostic #include <netdb.h> 1736030Sbostic #include <fcntl.h> 1833931Sbostic #include <errno.h> 1935651Seric #ifdef NAMED_BIND 2034022Sbostic #include <arpa/nameser.h> 2134022Sbostic #include <resolv.h> 2235651Seric #endif 23294Seric 24294Seric /* 254315Seric ** DELIVER -- Deliver a message to a list of addresses. 26294Seric ** 274315Seric ** This routine delivers to everyone on the same host as the 284315Seric ** user on the head of the list. It is clever about mailers 294315Seric ** that don't handle multiple users. It is NOT guaranteed 304315Seric ** that it will deliver to all these addresses however -- so 314315Seric ** deliver should be called once for each address on the 324315Seric ** list. 334315Seric ** 34294Seric ** Parameters: 359370Seric ** e -- the envelope to deliver. 364621Seric ** firstto -- head of the address list to deliver to. 37294Seric ** 38294Seric ** Returns: 39294Seric ** zero -- successfully delivered. 40294Seric ** else -- some failure, see ExitStat for more info. 41294Seric ** 42294Seric ** Side Effects: 43294Seric ** The standard input is passed off to someone. 44294Seric */ 45294Seric 469370Seric deliver(e, firstto) 479370Seric register ENVELOPE *e; 484621Seric ADDRESS *firstto; 49294Seric { 504452Seric char *host; /* host being sent to */ 514452Seric char *user; /* user being sent to */ 52294Seric char **pvp; 533233Seric register char **mvp; 543233Seric register char *p; 5510306Seric register MAILER *m; /* mailer for this recipient */ 564397Seric ADDRESS *ctladdr; 5754967Seric register MCI *mci; 584621Seric register ADDRESS *to = firstto; 594863Seric bool clever = FALSE; /* running user smtp to this mailer */ 605032Seric ADDRESS *tochain = NULL; /* chain of users in this mailer call */ 6151951Seric int rcode; /* response code */ 6251951Seric char *from; /* pointer to from person */ 6310306Seric char *pv[MAXPV+1]; 6410306Seric char tobuf[MAXLINE-50]; /* text line of to people */ 6510306Seric char buf[MAXNAME]; 6610306Seric char tfrombuf[MAXNAME]; /* translated from person */ 6751951Seric char rpathbuf[MAXNAME]; /* translated return path */ 68*57441Seric extern int checkcompat(); 6910306Seric extern ADDRESS *getctladdr(); 7010306Seric extern char *remotename(); 7154967Seric extern MCI *openmailer(); 72294Seric 734488Seric errno = 0; 747052Seric if (bitset(QDONTSEND, to->q_flags)) 753233Seric return (0); 76294Seric 7735651Seric #ifdef NAMED_BIND 7834022Sbostic /* unless interactive, try twice, over a minute */ 7934022Sbostic if (OpMode == MD_DAEMON || OpMode == MD_SMTP) { 8034022Sbostic _res.retrans = 30; 8134022Sbostic _res.retry = 2; 8234022Sbostic } 8336788Sbostic #endif 8434022Sbostic 856974Seric m = to->q_mailer; 866974Seric host = to->q_host; 876974Seric 887672Seric if (tTd(10, 1)) 893233Seric printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n", 906974Seric m->m_mno, host, to->q_user); 91294Seric 92294Seric /* 935903Seric ** If this mailer is expensive, and if we don't want to make 945903Seric ** connections now, just mark these addresses and return. 955903Seric ** This is useful if we want to batch connections to 965903Seric ** reduce load. This will cause the messages to be 975903Seric ** queued up, and a daemon will come along to send the 985903Seric ** messages later. 995903Seric ** This should be on a per-mailer basis. 1005903Seric */ 1015903Seric 10210682Seric if (NoConnect && !QueueRun && bitnset(M_EXPENSIVE, m->m_flags) && 1038428Seric !Verbose) 1045903Seric { 1055903Seric for (; to != NULL; to = to->q_next) 1068431Seric { 1078431Seric if (bitset(QDONTSEND, to->q_flags) || to->q_mailer != m) 1088431Seric continue; 1098431Seric to->q_flags |= QQUEUEUP|QDONTSEND; 1109370Seric e->e_to = to->q_paddr; 1118496Seric message(Arpa_Info, "queued"); 1128496Seric if (LogLevel > 4) 11354967Seric logdelivery("queued", e); 1148431Seric } 1159370Seric e->e_to = NULL; 1165903Seric return (0); 1175903Seric } 1185903Seric 1195903Seric /* 1203233Seric ** Do initial argv setup. 1213233Seric ** Insert the mailer name. Notice that $x expansion is 1223233Seric ** NOT done on the mailer name. Then, if the mailer has 1233233Seric ** a picky -f flag, we insert it as appropriate. This 1243233Seric ** code does not check for 'pv' overflow; this places a 1253233Seric ** manifest lower limit of 4 for MAXPV. 1268062Seric ** The from address rewrite is expected to make 1278062Seric ** the address relative to the other end. 1282968Seric */ 1292968Seric 1304452Seric /* rewrite from address, using rewriting rules */ 13155012Seric (void) strcpy(rpathbuf, remotename(e->e_returnpath, m, TRUE, TRUE, e)); 13251951Seric if (e->e_returnpath == e->e_sender) 13351951Seric { 13451951Seric from = rpathbuf; 13551951Seric } 13651951Seric else 13751951Seric { 13855012Seric (void) strcpy(tfrombuf, remotename(e->e_sender, m, TRUE, TRUE, e)); 13951951Seric from = tfrombuf; 14051951Seric } 1414452Seric 14251951Seric define('f', e->e_returnpath, e); /* raw return path */ 14351951Seric define('<', rpathbuf, e); /* translated return path */ 14451951Seric define('g', from, e); /* translated sender */ 1459370Seric define('h', host, e); /* to host */ 1463233Seric Errors = 0; 1473233Seric pvp = pv; 1483233Seric *pvp++ = m->m_argv[0]; 1492968Seric 1503233Seric /* insert -f or -r flag as appropriate */ 15110682Seric if (FromFlag && (bitnset(M_FOPT, m->m_flags) || bitnset(M_ROPT, m->m_flags))) 1523233Seric { 15310682Seric if (bitnset(M_FOPT, m->m_flags)) 1543233Seric *pvp++ = "-f"; 1553233Seric else 1563233Seric *pvp++ = "-r"; 15751951Seric *pvp++ = newstr(rpathbuf); 1583233Seric } 159294Seric 160294Seric /* 1613233Seric ** Append the other fixed parts of the argv. These run 1623233Seric ** up to the first entry containing "$u". There can only 1633233Seric ** be one of these, and there are only a few more slots 1643233Seric ** in the pv after it. 165294Seric */ 166294Seric 1673233Seric for (mvp = m->m_argv; (p = *++mvp) != NULL; ) 168294Seric { 16956795Seric while ((p = strchr(p, '\001')) != NULL) 1703233Seric if (*++p == 'u') 1713233Seric break; 1723233Seric if (p != NULL) 1733233Seric break; 1743233Seric 1753233Seric /* this entry is safe -- go ahead and process it */ 1769370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 1773233Seric *pvp++ = newstr(buf); 1783233Seric if (pvp >= &pv[MAXPV - 3]) 1793233Seric { 1803233Seric syserr("Too many parameters to %s before $u", pv[0]); 1813233Seric return (-1); 1823233Seric } 183294Seric } 1844863Seric 1856038Seric /* 1866038Seric ** If we have no substitution for the user name in the argument 1876038Seric ** list, we know that we must supply the names otherwise -- and 1886038Seric ** SMTP is the answer!! 1896038Seric */ 1906038Seric 1913233Seric if (*mvp == NULL) 1924863Seric { 1934863Seric /* running SMTP */ 1945179Seric # ifdef SMTP 1954863Seric clever = TRUE; 1964863Seric *pvp = NULL; 19756795Seric # else /* SMTP */ 1986038Seric /* oops! we don't implement SMTP */ 1995179Seric syserr("SMTP style mailer"); 2005179Seric return (EX_SOFTWARE); 20156795Seric # endif /* SMTP */ 2024863Seric } 203294Seric 204294Seric /* 2053233Seric ** At this point *mvp points to the argument with $u. We 2063233Seric ** run through our address list and append all the addresses 2073233Seric ** we can. If we run out of space, do not fret! We can 2083233Seric ** always send another copy later. 209294Seric */ 210294Seric 2113233Seric tobuf[0] = '\0'; 2129370Seric e->e_to = tobuf; 2134397Seric ctladdr = NULL; 2143233Seric for (; to != NULL; to = to->q_next) 215294Seric { 2163233Seric /* avoid sending multiple recipients to dumb mailers */ 21710682Seric if (tobuf[0] != '\0' && !bitnset(M_MUSER, m->m_flags)) 2183233Seric break; 2193233Seric 2203233Seric /* if already sent or not for this host, don't send */ 2217052Seric if (bitset(QDONTSEND, to->q_flags) || 2227052Seric strcmp(to->q_host, host) != 0 || 2237052Seric to->q_mailer != firstto->q_mailer) 2243233Seric continue; 2254397Seric 2268225Seric /* avoid overflowing tobuf */ 22742462Sbostic if (sizeof tobuf < (strlen(to->q_paddr) + strlen(tobuf) + 2)) 2288225Seric break; 2298225Seric 2307672Seric if (tTd(10, 1)) 2315032Seric { 2325032Seric printf("\nsend to "); 2335032Seric printaddr(to, FALSE); 2345032Seric } 2355032Seric 2364397Seric /* compute effective uid/gid when sending */ 2374596Seric if (to->q_mailer == ProgMailer) 2384397Seric ctladdr = getctladdr(to); 2394397Seric 2403233Seric user = to->q_user; 2419370Seric e->e_to = to->q_paddr; 2423233Seric to->q_flags |= QDONTSEND; 2433233Seric 2443233Seric /* 2453233Seric ** Check to see that these people are allowed to 2463233Seric ** talk to each other. 2473233Seric */ 2483233Seric 24910699Seric if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize) 25010699Seric { 25129914Seric NoReturn = TRUE; 25210699Seric usrerr("Message is too large; %ld bytes max", m->m_maxsize); 25310699Seric giveresponse(EX_UNAVAILABLE, m, e); 25410699Seric continue; 25510699Seric } 256*57441Seric rcode = checkcompat(to, e); 257*57441Seric if (r <= 0) 258294Seric { 259*57441Seric giveresponse(rcode == 0 ? EX_UNAVAILABLE : EX_TEMPFAIL, 260*57441Seric m, e); 2613233Seric continue; 262294Seric } 2633233Seric 2643233Seric /* 2654099Seric ** Strip quote bits from names if the mailer is dumb 2664099Seric ** about them. 2673233Seric */ 2683233Seric 26910682Seric if (bitnset(M_STRIPQ, m->m_flags)) 270294Seric { 27154983Seric stripquotes(user); 27254983Seric stripquotes(host); 2733233Seric } 2743233Seric 2759206Seric /* hack attack -- delivermail compatibility */ 2769206Seric if (m == ProgMailer && *user == '|') 2779206Seric user++; 2789206Seric 2793233Seric /* 2804161Seric ** If an error message has already been given, don't 2814161Seric ** bother to send to this address. 2824161Seric ** 2834161Seric ** >>>>>>>>>> This clause assumes that the local mailer 2844161Seric ** >> NOTE >> cannot do any further aliasing; that 2854161Seric ** >>>>>>>>>> function is subsumed by sendmail. 2864161Seric */ 2874161Seric 2887293Seric if (bitset(QBADADDR|QQUEUEUP, to->q_flags)) 2894161Seric continue; 2904161Seric 2914283Seric /* save statistics.... */ 2929370Seric markstats(e, to); 2934283Seric 2944161Seric /* 2953233Seric ** See if this user name is "special". 2963233Seric ** If the user name has a slash in it, assume that this 2976974Seric ** is a file -- send it off without further ado. Note 2986974Seric ** that this type of addresses is not processed along 2996974Seric ** with the others, so we fudge on the To person. 3003233Seric */ 3013233Seric 30257402Seric if (m == FileMailer) 3033233Seric { 30457402Seric rcode = mailfile(user, getctladdr(to), e); 30557402Seric giveresponse(rcode, m, e); 30657402Seric if (rcode == EX_OK) 30757402Seric to->q_flags |= QSENT; 30857402Seric continue; 309294Seric } 3103233Seric 3114315Seric /* 3124315Seric ** Address is verified -- add this user to mailer 3134315Seric ** argv, and add it to the print list of recipients. 3144315Seric */ 3154315Seric 3166059Seric /* link together the chain of recipients */ 3176272Seric to->q_tchain = tochain; 3186272Seric tochain = to; 3196059Seric 3203233Seric /* create list of users for error messages */ 3219388Seric (void) strcat(tobuf, ","); 3224082Seric (void) strcat(tobuf, to->q_paddr); 3239370Seric define('u', user, e); /* to user */ 3249370Seric define('z', to->q_home, e); /* user's home */ 3253233Seric 3264863Seric /* 3276059Seric ** Expand out this user into argument list. 3284863Seric */ 3294863Seric 3306059Seric if (!clever) 3313233Seric { 3329370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 3334863Seric *pvp++ = newstr(buf); 3344863Seric if (pvp >= &pv[MAXPV - 2]) 3354863Seric { 3364863Seric /* allow some space for trailing parms */ 3374863Seric break; 3384863Seric } 3394863Seric } 340294Seric } 341294Seric 3424067Seric /* see if any addresses still exist */ 3434067Seric if (tobuf[0] == '\0') 3444863Seric { 3459370Seric define('g', (char *) NULL, e); 34651951Seric define('<', (char *) NULL, e); 3474067Seric return (0); 3484863Seric } 3494067Seric 3503233Seric /* print out messages as full list */ 3519388Seric e->e_to = tobuf + 1; 3523233Seric 353294Seric /* 3543233Seric ** Fill out any parameters after the $u parameter. 355294Seric */ 356294Seric 3574863Seric while (!clever && *++mvp != NULL) 358294Seric { 3599370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 3603233Seric *pvp++ = newstr(buf); 3613233Seric if (pvp >= &pv[MAXPV]) 3623233Seric syserr("deliver: pv overflow after $u for %s", pv[0]); 363294Seric } 3643233Seric *pvp++ = NULL; 365294Seric 366294Seric /* 367294Seric ** Call the mailer. 3682898Seric ** The argument vector gets built, pipes 369294Seric ** are created as necessary, and we fork & exec as 3702898Seric ** appropriate. 3714863Seric ** If we are running SMTP, we just need to clean up. 372294Seric */ 373294Seric 37441050Seric if (ctladdr == NULL) 37541050Seric ctladdr = &e->e_from; 37635651Seric #ifdef NAMED_BIND 37751313Seric if (ConfigLevel < 2) 37851313Seric _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ 37935651Seric #endif 38054967Seric mci = openmailer(m, pv, ctladdr, clever, e); 38154967Seric if (mci == NULL) 38254967Seric { 38354967Seric /* catastrophic error */ 38454967Seric rcode = -1; 38554967Seric goto give_up; 38654967Seric } 38754967Seric else if (mci->mci_state != MCIS_OPEN) 38854967Seric { 38954967Seric /* couldn't open the mailer */ 39054967Seric rcode = mci->mci_exitstat; 39155173Seric errno = mci->mci_errno; 39254967Seric if (rcode == EX_OK) 39354967Seric { 39454967Seric /* shouldn't happen */ 39554967Seric rcode = EX_SOFTWARE; 39654967Seric } 39754967Seric } 39854967Seric else if (!clever) 39954967Seric { 40054967Seric /* 40154967Seric ** Format and send message. 40254967Seric */ 40354967Seric 40454967Seric putfromline(mci->mci_out, m, e); 40554967Seric (*e->e_puthdr)(mci->mci_out, m, e); 40654967Seric putline("\n", mci->mci_out, m); 40754967Seric (*e->e_putbody)(mci->mci_out, m, e); 40854967Seric 40954967Seric /* get the exit status */ 41054967Seric rcode = endmailer(mci, pv[0]); 41154967Seric } 41254967Seric else 41333931Sbostic #ifdef SMTP 41435651Seric { 41554967Seric /* 41654967Seric ** Send the MAIL FROM: protocol 41754967Seric */ 41853751Seric 41954967Seric rcode = smtpmailfrom(m, mci, e); 42054967Seric if (rcode == EX_OK) 42135651Seric { 42254967Seric register char *t = tobuf; 42354967Seric register int i; 42453751Seric 42554967Seric /* send the recipient list */ 42654967Seric tobuf[0] = '\0'; 42754967Seric for (to = tochain; to != NULL; to = to->q_tchain) 42853738Seric { 42954967Seric e->e_to = to->q_paddr; 43054967Seric if ((i = smtprcpt(to, m, mci, e)) != EX_OK) 43153738Seric { 43254967Seric markfailure(e, to, i); 43354967Seric giveresponse(i, m, e); 4349388Seric } 43553738Seric else 43653738Seric { 43754967Seric *t++ = ','; 43854967Seric for (p = to->q_paddr; *p; *t++ = *p++) 43954967Seric continue; 4409388Seric } 44154967Seric } 4429388Seric 44354967Seric /* now send the data */ 44454967Seric if (tobuf[0] == '\0') 44554967Seric { 44654967Seric e->e_to = NULL; 44754967Seric if (bitset(MCIF_CACHED, mci->mci_flags)) 44854967Seric smtprset(m, mci, e); 44954967Seric } 45054967Seric else 45154967Seric { 45254967Seric e->e_to = tobuf + 1; 45354967Seric rcode = smtpdata(m, mci, e); 45454967Seric } 45554967Seric 45654967Seric /* now close the connection */ 45754967Seric if (!bitset(MCIF_CACHED, mci->mci_flags)) 45853751Seric smtpquit(m, mci, e); 4599370Seric } 4604863Seric } 46154967Seric #else /* not SMTP */ 46233935Sbostic { 46354967Seric syserr("deliver: need SMTP compiled to use clever mailer"); 46454967Seric rcode = -1; 46554967Seric goto give_up; 46633935Sbostic } 46754967Seric #endif /* SMTP */ 46835651Seric #ifdef NAMED_BIND 46951313Seric if (ConfigLevel < 2) 47051313Seric _res.options |= RES_DEFNAMES | RES_DNSRCH; /* XXX */ 47135651Seric #endif 4723233Seric 47354967Seric /* arrange a return receipt if requested */ 47454967Seric if (e->e_receiptto != NULL && bitnset(M_LOCAL, m->m_flags)) 47554967Seric { 47654967Seric e->e_flags |= EF_SENDRECEIPT; 47754967Seric /* do we want to send back more info? */ 47854967Seric } 47954967Seric 4804621Seric /* 4819388Seric ** Do final status disposal. 4829388Seric ** We check for something in tobuf for the SMTP case. 4839388Seric ** If we got a temporary failure, arrange to queue the 4849388Seric ** addressees. 4854621Seric */ 4864621Seric 48754967Seric give_up: 4889388Seric if (tobuf[0] != '\0') 48910105Seric giveresponse(rcode, m, e); 49047284Seric for (to = tochain; to != NULL; to = to->q_tchain) 49154967Seric { 49247284Seric if (rcode != EX_OK) 49310092Seric markfailure(e, to, rcode); 49447284Seric else 49547284Seric to->q_flags |= QSENT; 49654967Seric } 4974621Seric 49854967Seric /* 49954967Seric ** Restore state and return. 50054967Seric */ 50154967Seric 5024488Seric errno = 0; 5039370Seric define('g', (char *) NULL, e); 50451951Seric define('<', (char *) NULL, e); 5058003Seric return (rcode); 5063233Seric } 5073233Seric /* 50810092Seric ** MARKFAILURE -- mark a failure on a specific address. 50910092Seric ** 51010092Seric ** Parameters: 51110092Seric ** e -- the envelope we are sending. 51210092Seric ** q -- the address to mark. 51310092Seric ** rcode -- the code signifying the particular failure. 51410092Seric ** 51510092Seric ** Returns: 51610092Seric ** none. 51710092Seric ** 51810092Seric ** Side Effects: 51910092Seric ** marks the address (and possibly the envelope) with the 52010092Seric ** failure so that an error will be returned or 52110092Seric ** the message will be queued, as appropriate. 52210092Seric */ 52310092Seric 52410092Seric markfailure(e, q, rcode) 52510092Seric register ENVELOPE *e; 52610092Seric register ADDRESS *q; 52710092Seric int rcode; 52810092Seric { 52910092Seric if (rcode == EX_OK) 53010092Seric return; 53140996Sbostic else if (rcode != EX_TEMPFAIL && rcode != EX_IOERR && rcode != EX_OSERR) 53210092Seric q->q_flags |= QBADADDR; 53310092Seric else if (curtime() > e->e_ctime + TimeOut) 53410092Seric { 53510092Seric extern char *pintvl(); 53610105Seric char buf[MAXLINE]; 53710092Seric 53810092Seric if (!bitset(EF_TIMEOUT, e->e_flags)) 53910105Seric { 54010105Seric (void) sprintf(buf, "Cannot send message for %s", 54110092Seric pintvl(TimeOut, FALSE)); 54210105Seric if (e->e_message != NULL) 54310105Seric free(e->e_message); 54410105Seric e->e_message = newstr(buf); 54510105Seric message(Arpa_Info, buf); 54610105Seric } 54710092Seric q->q_flags |= QBADADDR; 54810092Seric e->e_flags |= EF_TIMEOUT; 54910092Seric } 55010092Seric else 55110092Seric q->q_flags |= QQUEUEUP; 55210092Seric } 55310092Seric /* 5544214Seric ** DOFORK -- do a fork, retrying a couple of times on failure. 5554214Seric ** 5564214Seric ** This MUST be a macro, since after a vfork we are running 5574214Seric ** two processes on the same stack!!! 5584214Seric ** 5594214Seric ** Parameters: 5604214Seric ** none. 5614214Seric ** 5624214Seric ** Returns: 5634214Seric ** From a macro??? You've got to be kidding! 5644214Seric ** 5654214Seric ** Side Effects: 5664214Seric ** Modifies the ==> LOCAL <== variable 'pid', leaving: 5674214Seric ** pid of child in parent, zero in child. 5684214Seric ** -1 on unrecoverable error. 5694214Seric ** 5704214Seric ** Notes: 5714214Seric ** I'm awfully sorry this looks so awful. That's 5724214Seric ** vfork for you..... 5734214Seric */ 5744214Seric 5754214Seric # define NFORKTRIES 5 5764214Seric 57752107Seric # ifndef FORK 57852107Seric # define FORK fork 57952107Seric # endif 58052107Seric 5814214Seric # define DOFORK(fORKfN) \ 5824214Seric {\ 5834214Seric register int i;\ 5844214Seric \ 58523504Seric for (i = NFORKTRIES; --i >= 0; )\ 5864214Seric {\ 5874214Seric pid = fORKfN();\ 5884214Seric if (pid >= 0)\ 5894214Seric break;\ 59023504Seric if (i > 0)\ 59125617Seric sleep((unsigned) NFORKTRIES - i);\ 5924214Seric }\ 5934214Seric } 5944214Seric /* 5954637Seric ** DOFORK -- simple fork interface to DOFORK. 5964637Seric ** 5974637Seric ** Parameters: 5984637Seric ** none. 5994637Seric ** 6004637Seric ** Returns: 6014637Seric ** pid of child in parent. 6024637Seric ** zero in child. 6034637Seric ** -1 on error. 6044637Seric ** 6054637Seric ** Side Effects: 6064637Seric ** returns twice, once in parent and once in child. 6074637Seric */ 6084637Seric 6094637Seric dofork() 6104637Seric { 6114637Seric register int pid; 6124637Seric 6134637Seric DOFORK(fork); 6144637Seric return (pid); 6154637Seric } 6164637Seric /* 6174863Seric ** ENDMAILER -- Wait for mailer to terminate. 6184863Seric ** 6194863Seric ** We should never get fatal errors (e.g., segmentation 6204863Seric ** violation), so we report those specially. For other 6214863Seric ** errors, we choose a status message (into statmsg), 6224863Seric ** and if it represents an error, we print it. 6234863Seric ** 6244863Seric ** Parameters: 6254863Seric ** pid -- pid of mailer. 6264863Seric ** name -- name of mailer (for error messages). 6274863Seric ** 6284863Seric ** Returns: 6294863Seric ** exit code of mailer. 6304863Seric ** 6314863Seric ** Side Effects: 6324863Seric ** none. 6334863Seric */ 6344863Seric 63553738Seric endmailer(mci, name) 63654967Seric register MCI *mci; 6374863Seric char *name; 6384863Seric { 6399370Seric int st; 6404863Seric 64153738Seric /* close any connections */ 64253738Seric if (mci->mci_in != NULL) 64353738Seric (void) fclose(mci->mci_in); 64453738Seric if (mci->mci_out != NULL) 64553738Seric (void) fclose(mci->mci_out); 64653738Seric mci->mci_in = mci->mci_out = NULL; 64753738Seric mci->mci_state = MCIS_CLOSED; 64853738Seric 6496038Seric /* in the IPC case there is nothing to wait for */ 65053738Seric if (mci->mci_pid == 0) 6516038Seric return (EX_OK); 6526038Seric 6536038Seric /* wait for the mailer process to die and collect status */ 65453738Seric st = waitfor(mci->mci_pid); 6559370Seric if (st == -1) 6568127Seric { 6579370Seric syserr("endmailer %s: wait", name); 6589370Seric return (EX_SOFTWARE); 6594863Seric } 6606038Seric 6616038Seric /* see if it died a horrid death */ 6624863Seric if ((st & 0377) != 0) 6634863Seric { 66424941Seric syserr("mailer %s died with signal %o", name, st); 66524941Seric ExitStat = EX_TEMPFAIL; 66624941Seric return (EX_TEMPFAIL); 6674863Seric } 6686038Seric 6696038Seric /* normal death -- return status */ 6709370Seric st = (st >> 8) & 0377; 6719370Seric return (st); 6724863Seric } 6734863Seric /* 6744863Seric ** OPENMAILER -- open connection to mailer. 6754863Seric ** 6764863Seric ** Parameters: 6774863Seric ** m -- mailer descriptor. 6784863Seric ** pvp -- parameter vector to pass to mailer. 6794863Seric ** ctladdr -- controlling address for user. 6804863Seric ** clever -- create a full duplex connection. 6814863Seric ** 6824863Seric ** Returns: 68353738Seric ** The mail connection info struct for this connection. 68453738Seric ** NULL on failure. 6854863Seric ** 6864863Seric ** Side Effects: 6874863Seric ** creates a mailer in a subprocess. 6884863Seric */ 6894863Seric 69054967Seric MCI * 69154967Seric openmailer(m, pvp, ctladdr, clever, e) 6929370Seric MAILER *m; 6934863Seric char **pvp; 6944863Seric ADDRESS *ctladdr; 6954863Seric bool clever; 69654967Seric ENVELOPE *e; 6974863Seric { 6984863Seric int pid; 69954967Seric register MCI *mci; 7004709Seric int mpvect[2]; 7014863Seric int rpvect[2]; 7023233Seric extern FILE *fdopen(); 7033233Seric 7047672Seric if (tTd(11, 1)) 705294Seric { 7068178Seric printf("openmailer:"); 7073233Seric printav(pvp); 708294Seric } 7094488Seric errno = 0; 7103233Seric 71125050Seric CurHostName = m->m_mailer; 71225050Seric 7136038Seric /* 7146038Seric ** Deal with the special case of mail handled through an IPC 7156038Seric ** connection. 7166038Seric ** In this case we don't actually fork. We must be 7176038Seric ** running SMTP for this to work. We will return a 7186038Seric ** zero pid to indicate that we are running IPC. 71911160Seric ** We also handle a debug version that just talks to stdin/out. 7206038Seric */ 7216038Seric 72211160Seric /* check for Local Person Communication -- not for mortals!!! */ 72311160Seric if (strcmp(m->m_mailer, "[LPC]") == 0) 72411160Seric { 72554967Seric mci = (MCI *) xalloc(sizeof *mci); 72654993Seric bzero((char *) mci, sizeof *mci); 72753738Seric mci->mci_in = stdin; 72853738Seric mci->mci_out = stdout; 72954967Seric mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN; 73053751Seric mci->mci_mailer = m; 73111160Seric } 73254967Seric else if (strcmp(m->m_mailer, "[IPC]") == 0 || 73354967Seric strcmp(m->m_mailer, "[TCP]") == 0) 7346038Seric { 73552107Seric #ifdef DAEMON 73629433Sbloom register int i, j; 7377285Seric register u_short port; 73854967Seric int nmx; 73954967Seric char *mxhosts[MAXMXHOSTS + 1]; 74054967Seric extern MCI *mci_get(); 7416038Seric 74225050Seric CurHostName = pvp[1]; 74354967Seric #ifdef NAMED_BIND 74454967Seric if (CurHostName != NULL && CurHostName[0] != '\0' && 74554967Seric CurHostName[0] != '[') 74654967Seric { 74754967Seric int rcode; 74854967Seric char buf[MAXNAME]; 74954967Seric 75054967Seric expand("\001j", buf, &buf[sizeof(buf) - 1], e); 75154967Seric nmx = getmxrr(CurHostName, mxhosts, buf, &rcode); 75254967Seric if (nmx < 0) 75354967Seric { 75454967Seric mci = mci_get(CurHostName, m); 75554967Seric mci->mci_exitstat = rcode; 75654967Seric mci->mci_errno = errno; 75754967Seric } 75854967Seric } 75954967Seric else 76054967Seric #endif 76154967Seric { 76254967Seric nmx = 1; 76354967Seric mxhosts[0] = CurHostName; 76454967Seric } 76554967Seric 7666038Seric if (!clever) 7676038Seric syserr("non-clever IPC"); 7686632Seric if (pvp[2] != NULL) 7697285Seric port = atoi(pvp[2]); 7706632Seric else 7717285Seric port = 0; 77254967Seric for (j = 0; j < nmx; j++) 77329433Sbloom { 77453738Seric /* see if we already know that this host is fried */ 77554967Seric CurHostName = mxhosts[j]; 77654967Seric mci = mci_get(CurHostName, m); 77754967Seric if (mci->mci_state != MCIS_CLOSED) 77857387Seric { 77957387Seric if (tTd(11, 1)) 78057387Seric { 78157387Seric printf("openmailer: "); 78257387Seric mci_dump(mci); 78357387Seric } 78453738Seric return mci; 78557387Seric } 78653751Seric mci->mci_mailer = m; 78754967Seric if (mci->mci_exitstat != EX_OK) 78854967Seric continue; 78954967Seric 79054967Seric /* try the connection */ 79155195Seric setproctitle("%s %s: %s", e->e_id, mxhosts[j], "user open"); 79254967Seric message(Arpa_Info, "Connecting to %s (%s)...", 79354967Seric mxhosts[j], m->m_name); 79454967Seric i = makeconnection(mxhosts[j], port, mci, 79554967Seric bitnset(M_SECURE_PORT, m->m_flags)); 79654967Seric mci->mci_exitstat = i; 79754967Seric mci->mci_errno = errno; 79854967Seric if (i == EX_OK) 79952106Seric { 80054967Seric mci->mci_state = MCIS_OPENING; 80154967Seric mci_cache(mci); 80254967Seric break; 80334022Sbostic } 80454967Seric else if (tTd(11, 1)) 80554967Seric printf("openmailer: makeconnection => stat=%d, errno=%d\n", 80654967Seric i, errno); 80753738Seric 80854967Seric 80953738Seric /* enter status of this host */ 81053738Seric setstat(i); 8116047Seric } 81254993Seric mci->mci_pid = 0; 81354967Seric #else /* no DAEMON */ 8149370Seric syserr("openmailer: no IPC"); 81557387Seric if (tTd(11, 1)) 81657387Seric printf("openmailer: NULL\n"); 81753738Seric return NULL; 81854967Seric #endif /* DAEMON */ 8196038Seric } 82054967Seric else 821294Seric { 82254967Seric /* create a pipe to shove the mail through */ 82354967Seric if (pipe(mpvect) < 0) 82454967Seric { 82554967Seric syserr("openmailer: pipe (to mailer)"); 82657387Seric if (tTd(11, 1)) 82757387Seric printf("openmailer: NULL\n"); 82854967Seric return NULL; 82954967Seric } 8304863Seric 83154967Seric /* if this mailer speaks smtp, create a return pipe */ 83254967Seric if (clever && pipe(rpvect) < 0) 83354967Seric { 83454967Seric syserr("openmailer: pipe (from mailer)"); 83554967Seric (void) close(mpvect[0]); 83654967Seric (void) close(mpvect[1]); 83757387Seric if (tTd(11, 1)) 83857387Seric printf("openmailer: NULL\n"); 83954967Seric return NULL; 84054967Seric } 8414863Seric 84254967Seric /* 84354967Seric ** Actually fork the mailer process. 84454967Seric ** DOFORK is clever about retrying. 84554967Seric ** 84654967Seric ** Dispose of SIGCHLD signal catchers that may be laying 84754967Seric ** around so that endmail will get it. 84854967Seric */ 8496038Seric 85054967Seric if (e->e_xfp != NULL) 85154967Seric (void) fflush(e->e_xfp); /* for debugging */ 85254967Seric (void) fflush(stdout); 85326434Seric # ifdef SIGCHLD 85454967Seric (void) signal(SIGCHLD, SIG_DFL); 85556795Seric # endif /* SIGCHLD */ 85654967Seric DOFORK(FORK); 85754967Seric /* pid is set by DOFORK */ 85854967Seric if (pid < 0) 8594863Seric { 86054967Seric /* failure */ 86154967Seric syserr("openmailer: cannot fork"); 86254967Seric (void) close(mpvect[0]); 86354967Seric (void) close(mpvect[1]); 86454967Seric if (clever) 86554967Seric { 86654967Seric (void) close(rpvect[0]); 86754967Seric (void) close(rpvect[1]); 86854967Seric } 86957387Seric if (tTd(11, 1)) 87057387Seric printf("openmailer: NULL\n"); 87154967Seric return NULL; 8724863Seric } 87354967Seric else if (pid == 0) 87454967Seric { 87554967Seric int i; 87656678Seric int saveerrno; 87754967Seric extern int DtableSize; 87815772Seric 87954967Seric /* child -- set up input & exec mailer */ 88054967Seric /* make diagnostic output be standard output */ 88154967Seric (void) signal(SIGINT, SIG_IGN); 88254967Seric (void) signal(SIGHUP, SIG_IGN); 88354967Seric (void) signal(SIGTERM, SIG_DFL); 8844709Seric 88554967Seric /* arrange to filter std & diag output of command */ 88654967Seric if (clever) 88754967Seric { 88854967Seric (void) close(rpvect[0]); 88954967Seric (void) close(1); 89054967Seric (void) dup(rpvect[1]); 89154967Seric (void) close(rpvect[1]); 89254967Seric } 89354967Seric else if (OpMode == MD_SMTP || HoldErrs) 89454967Seric { 89554967Seric /* put mailer output in transcript */ 89654967Seric (void) close(1); 89754967Seric (void) dup(fileno(e->e_xfp)); 89854967Seric } 89954967Seric (void) close(2); 90054967Seric (void) dup(1); 9014709Seric 90254967Seric /* arrange to get standard input */ 90354967Seric (void) close(mpvect[1]); 90454967Seric (void) close(0); 90554967Seric if (dup(mpvect[0]) < 0) 9064417Seric { 90754967Seric syserr("Cannot dup to zero!"); 90854967Seric _exit(EX_OSERR); 9094417Seric } 91054967Seric (void) close(mpvect[0]); 91154967Seric if (!bitnset(M_RESTR, m->m_flags)) 9124415Seric { 91354967Seric if (ctladdr == NULL || ctladdr->q_uid == 0) 91454967Seric { 91554967Seric (void) setgid(DefGid); 91654967Seric (void) initgroups(DefUser, DefGid); 91754967Seric (void) setuid(DefUid); 91854967Seric } 91954967Seric else 92054967Seric { 92154967Seric (void) setgid(ctladdr->q_gid); 92254967Seric (void) initgroups(ctladdr->q_ruser? 92354967Seric ctladdr->q_ruser: ctladdr->q_user, 92454967Seric ctladdr->q_gid); 92554967Seric (void) setuid(ctladdr->q_uid); 92654967Seric } 9274415Seric } 9289370Seric 92954967Seric /* arrange for all the files to be closed */ 93054967Seric for (i = 3; i < DtableSize; i++) 93154967Seric { 93254967Seric register int j; 93354967Seric if ((j = fcntl(i, F_GETFD, 0)) != -1) 93454967Seric (void)fcntl(i, F_SETFD, j|1); 93554967Seric } 9362774Seric 93754967Seric /* try to execute the mailer */ 93854967Seric execve(m->m_mailer, pvp, UserEnviron); 93956678Seric saveerrno = errno; 94054967Seric syserr("Cannot exec %s", m->m_mailer); 94154967Seric if (m == LocalMailer) 94254967Seric _exit(EX_TEMPFAIL); 94356678Seric switch (saveerrno) 94454967Seric { 94554967Seric case EIO: 94654967Seric case EAGAIN: 94754967Seric case ENOMEM: 94851835Seric # ifdef EPROCLIM 94954967Seric case EPROCLIM: 95051835Seric # endif 95154967Seric _exit(EX_TEMPFAIL); 95254967Seric } 95354967Seric _exit(EX_UNAVAILABLE); 95451835Seric } 95554967Seric 95654967Seric /* 95754967Seric ** Set up return value. 95854967Seric */ 95954967Seric 96054967Seric mci = (MCI *) xalloc(sizeof *mci); 96154993Seric bzero((char *) mci, sizeof *mci); 96254967Seric mci->mci_mailer = m; 96354967Seric mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN; 96454993Seric mci->mci_pid = pid; 96554967Seric (void) close(mpvect[0]); 96654967Seric mci->mci_out = fdopen(mpvect[1], "w"); 96754967Seric if (clever) 96854967Seric { 96954967Seric (void) close(rpvect[1]); 97054967Seric mci->mci_in = fdopen(rpvect[0], "r"); 97154967Seric } 97254967Seric else 97354967Seric { 97454967Seric mci->mci_flags |= MCIF_TEMP; 97554967Seric mci->mci_in = NULL; 97654967Seric } 977294Seric } 978294Seric 9794709Seric /* 98054967Seric ** If we are in SMTP opening state, send initial protocol. 9814709Seric */ 9824709Seric 98354967Seric if (clever && mci->mci_state != MCIS_CLOSED) 9844863Seric { 98554967Seric smtpinit(m, mci, e); 98653738Seric } 98757387Seric if (tTd(11, 1)) 98857387Seric { 98957387Seric printf("openmailer: "); 99057387Seric mci_dump(mci); 99157387Seric } 992294Seric 99353738Seric return mci; 994294Seric } 995294Seric /* 996294Seric ** GIVERESPONSE -- Interpret an error response from a mailer 997294Seric ** 998294Seric ** Parameters: 999294Seric ** stat -- the status code from the mailer (high byte 1000294Seric ** only; core dumps must have been taken care of 1001294Seric ** already). 1002294Seric ** m -- the mailer descriptor for this mailer. 1003294Seric ** 1004294Seric ** Returns: 10054082Seric ** none. 1006294Seric ** 1007294Seric ** Side Effects: 10081518Seric ** Errors may be incremented. 1009294Seric ** ExitStat may be set. 1010294Seric */ 1011294Seric 101210105Seric giveresponse(stat, m, e) 1013294Seric int stat; 10149370Seric register MAILER *m; 101510105Seric ENVELOPE *e; 1016294Seric { 1017294Seric register char *statmsg; 1018294Seric extern char *SysExMsg[]; 1019294Seric register int i; 102036788Sbostic extern int N_SysEx; 102136788Sbostic #ifdef NAMED_BIND 102236788Sbostic extern int h_errno; 102336788Sbostic #endif 102410105Seric char buf[MAXLINE]; 1025294Seric 102612135Seric #ifdef lint 102712135Seric if (m == NULL) 102812135Seric return; 102912135Seric #endif lint 103012135Seric 10314315Seric /* 10324315Seric ** Compute status message from code. 10334315Seric */ 10344315Seric 1035294Seric i = stat - EX__BASE; 10369370Seric if (stat == 0) 10379370Seric statmsg = "250 Sent"; 10389370Seric else if (i < 0 || i > N_SysEx) 10399370Seric { 10409370Seric (void) sprintf(buf, "554 unknown mailer error %d", stat); 10419370Seric stat = EX_UNAVAILABLE; 10429370Seric statmsg = buf; 10439370Seric } 104410105Seric else if (stat == EX_TEMPFAIL) 104510105Seric { 104610124Seric (void) strcpy(buf, SysExMsg[i]); 104736788Sbostic #ifdef NAMED_BIND 104825527Smiriam if (h_errno == TRY_AGAIN) 104910105Seric { 105015137Seric extern char *errstring(); 105115137Seric 105225527Smiriam statmsg = errstring(h_errno+MAX_ERRNO); 105321061Seric } 105421061Seric else 105536788Sbostic #endif 105621061Seric { 105725527Smiriam if (errno != 0) 105825527Smiriam { 105925527Smiriam extern char *errstring(); 106025527Smiriam 106125527Smiriam statmsg = errstring(errno); 106225527Smiriam } 106325527Smiriam else 106425527Smiriam { 106521061Seric #ifdef SMTP 106625527Smiriam extern char SmtpError[]; 106721061Seric 106825527Smiriam statmsg = SmtpError; 106956795Seric #else /* SMTP */ 107025527Smiriam statmsg = NULL; 107156795Seric #endif /* SMTP */ 107225527Smiriam } 107321061Seric } 107421061Seric if (statmsg != NULL && statmsg[0] != '\0') 107521061Seric { 107610124Seric (void) strcat(buf, ": "); 107721061Seric (void) strcat(buf, statmsg); 107810105Seric } 107910105Seric statmsg = buf; 108010105Seric } 1081294Seric else 108221061Seric { 1083294Seric statmsg = SysExMsg[i]; 108421061Seric } 10859370Seric 10869370Seric /* 10879370Seric ** Print the message as appropriate 10889370Seric */ 10899370Seric 109010105Seric if (stat == EX_OK || stat == EX_TEMPFAIL) 10918003Seric message(Arpa_Info, &statmsg[4]); 1092294Seric else 1093294Seric { 10941518Seric Errors++; 10959370Seric usrerr(statmsg); 1096294Seric } 1097294Seric 1098294Seric /* 1099294Seric ** Final cleanup. 1100294Seric ** Log a record of the transaction. Compute the new 1101294Seric ** ExitStat -- if we already had an error, stick with 1102294Seric ** that. 1103294Seric */ 1104294Seric 11057680Seric if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2)) 110654967Seric logdelivery(&statmsg[4], e); 11077858Seric 11084621Seric if (stat != EX_TEMPFAIL) 11094621Seric setstat(stat); 111010105Seric if (stat != EX_OK) 111110105Seric { 111210105Seric if (e->e_message != NULL) 111310105Seric free(e->e_message); 111410105Seric e->e_message = newstr(&statmsg[4]); 111510105Seric } 111610124Seric errno = 0; 111736788Sbostic #ifdef NAMED_BIND 111825527Smiriam h_errno = 0; 111936788Sbostic #endif 1120294Seric } 1121294Seric /* 11228496Seric ** LOGDELIVERY -- log the delivery in the system log 11238496Seric ** 11248496Seric ** Parameters: 11258496Seric ** stat -- the message to print for the status 11268496Seric ** 11278496Seric ** Returns: 11288496Seric ** none 11298496Seric ** 11308496Seric ** Side Effects: 11318496Seric ** none 11328496Seric */ 11338496Seric 113454967Seric logdelivery(stat, e) 11358496Seric char *stat; 113654967Seric register ENVELOPE *e; 11378496Seric { 11388496Seric extern char *pintvl(); 11398496Seric 11408496Seric # ifdef LOG 114154967Seric syslog(LOG_INFO, "%s: to=%s, delay=%s, stat=%s", e->e_id, 114254967Seric e->e_to, pintvl(curtime() - e->e_ctime, TRUE), stat); 114356795Seric # endif /* LOG */ 11448496Seric } 11458496Seric /* 11466974Seric ** PUTFROMLINE -- output a UNIX-style from line (or whatever) 1147294Seric ** 11486974Seric ** This can be made an arbitrary message separator by changing $l 1149294Seric ** 115016150Seric ** One of the ugliest hacks seen by human eyes is contained herein: 115116150Seric ** UUCP wants those stupid "remote from <host>" lines. Why oh why 115216150Seric ** does a well-meaning programmer such as myself have to deal with 115316150Seric ** this kind of antique garbage???? 11546974Seric ** 1155294Seric ** Parameters: 11566974Seric ** fp -- the file to output to. 11576974Seric ** m -- the mailer describing this entry. 1158294Seric ** 1159294Seric ** Returns: 11606974Seric ** none 1161294Seric ** 1162294Seric ** Side Effects: 11636974Seric ** outputs some text to fp. 1164294Seric */ 1165294Seric 116654967Seric putfromline(fp, m, e) 11676974Seric register FILE *fp; 11686974Seric register MAILER *m; 116954967Seric ENVELOPE *e; 1170294Seric { 117116150Seric char *template = "\001l\n"; 11726974Seric char buf[MAXLINE]; 1173294Seric 117410682Seric if (bitnset(M_NHDR, m->m_flags)) 11756974Seric return; 11764315Seric 11776974Seric # ifdef UGLYUUCP 117810682Seric if (bitnset(M_UGLYUUCP, m->m_flags)) 11794205Seric { 118012223Seric char *bang; 118112223Seric char xbuf[MAXLINE]; 11826041Seric 118354967Seric expand("\001<", buf, &buf[sizeof buf - 1], e); 118456795Seric bang = strchr(buf, '!'); 11856974Seric if (bang == NULL) 118612223Seric syserr("No ! in UUCP! (%s)", buf); 11875099Seric else 11889370Seric { 118912223Seric *bang++ = '\0'; 119016150Seric (void) sprintf(xbuf, "From %s \001d remote from %s\n", bang, buf); 119112223Seric template = xbuf; 11929370Seric } 11936974Seric } 119456795Seric # endif /* UGLYUUCP */ 119554967Seric expand(template, buf, &buf[sizeof buf - 1], e); 119610168Seric putline(buf, fp, m); 11975981Seric } 11985981Seric /* 11996974Seric ** PUTBODY -- put the body of a message. 12006974Seric ** 12016974Seric ** Parameters: 12026974Seric ** fp -- file to output onto. 120310168Seric ** m -- a mailer descriptor to control output format. 12049538Seric ** e -- the envelope to put out. 12056974Seric ** 12066974Seric ** Returns: 12076974Seric ** none. 12086974Seric ** 12096974Seric ** Side Effects: 12106974Seric ** The message is written onto fp. 12116974Seric */ 12126974Seric 121310168Seric putbody(fp, m, e) 12146974Seric FILE *fp; 12159370Seric MAILER *m; 12169538Seric register ENVELOPE *e; 12176974Seric { 121810168Seric char buf[MAXLINE]; 12196974Seric 12206974Seric /* 12216974Seric ** Output the body of the message 12226974Seric */ 12236974Seric 12249538Seric if (e->e_dfp == NULL) 12256974Seric { 12269538Seric if (e->e_df != NULL) 12279538Seric { 12289538Seric e->e_dfp = fopen(e->e_df, "r"); 12299538Seric if (e->e_dfp == NULL) 123040931Srick syserr("putbody: Cannot open %s for %s from %s", 123140931Srick e->e_df, e->e_to, e->e_from); 12329538Seric } 12339538Seric else 123410168Seric putline("<<< No Message Collected >>>", fp, m); 12359538Seric } 12369538Seric if (e->e_dfp != NULL) 12379538Seric { 12389538Seric rewind(e->e_dfp); 123910168Seric while (!ferror(fp) && fgets(buf, sizeof buf, e->e_dfp) != NULL) 124016875Seric { 124116875Seric if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) && 124240995Sbostic strncmp(buf, "From ", 5) == 0) 124323102Seric (void) putc('>', fp); 124410168Seric putline(buf, fp, m); 124516875Seric } 12466974Seric 12479538Seric if (ferror(e->e_dfp)) 12486974Seric { 12496974Seric syserr("putbody: read error"); 12506974Seric ExitStat = EX_IOERR; 12516974Seric } 12526974Seric } 12536974Seric 12546974Seric (void) fflush(fp); 12556974Seric if (ferror(fp) && errno != EPIPE) 12566974Seric { 12576974Seric syserr("putbody: write error"); 12586974Seric ExitStat = EX_IOERR; 12596974Seric } 12606974Seric errno = 0; 12616974Seric } 12626974Seric /* 1263294Seric ** MAILFILE -- Send a message to a file. 1264294Seric ** 12654327Seric ** If the file has the setuid/setgid bits set, but NO execute 12664327Seric ** bits, sendmail will try to become the owner of that file 12674327Seric ** rather than the real user. Obviously, this only works if 12684327Seric ** sendmail runs as root. 12694327Seric ** 12709370Seric ** This could be done as a subordinate mailer, except that it 12719370Seric ** is used implicitly to save messages in ~/dead.letter. We 12729370Seric ** view this as being sufficiently important as to include it 12739370Seric ** here. For example, if the system is dying, we shouldn't have 12749370Seric ** to create another process plus some pipes to save the message. 12759370Seric ** 1276294Seric ** Parameters: 1277294Seric ** filename -- the name of the file to send to. 12784397Seric ** ctladdr -- the controlling address header -- includes 12794397Seric ** the userid/groupid to be when sending. 1280294Seric ** 1281294Seric ** Returns: 1282294Seric ** The exit code associated with the operation. 1283294Seric ** 1284294Seric ** Side Effects: 1285294Seric ** none. 1286294Seric */ 1287294Seric 128854967Seric mailfile(filename, ctladdr, e) 1289294Seric char *filename; 12904397Seric ADDRESS *ctladdr; 129154967Seric register ENVELOPE *e; 1292294Seric { 1293294Seric register FILE *f; 12944214Seric register int pid; 129553751Seric int mode; 1296294Seric 12974214Seric /* 12984214Seric ** Fork so we can change permissions here. 12994214Seric ** Note that we MUST use fork, not vfork, because of 13004214Seric ** the complications of calling subroutines, etc. 13014214Seric */ 13024067Seric 13034214Seric DOFORK(fork); 13044214Seric 13054214Seric if (pid < 0) 13064214Seric return (EX_OSERR); 13074214Seric else if (pid == 0) 13084214Seric { 13094214Seric /* child -- actually write to file */ 13104327Seric struct stat stb; 13114327Seric 13124215Seric (void) signal(SIGINT, SIG_DFL); 13134215Seric (void) signal(SIGHUP, SIG_DFL); 13144215Seric (void) signal(SIGTERM, SIG_DFL); 131523102Seric (void) umask(OldUmask); 131652673Seric 13174327Seric if (stat(filename, &stb) < 0) 13184431Seric stb.st_mode = 0666; 131953751Seric mode = stb.st_mode; 132052673Seric 132152673Seric /* limit the errors to those actually caused in the child */ 132252673Seric errno = 0; 132352673Seric ExitStat = EX_OK; 132452673Seric 13254327Seric if (bitset(0111, stb.st_mode)) 13264327Seric exit(EX_CANTCREAT); 13274401Seric if (ctladdr == NULL) 132840931Srick ctladdr = &e->e_from; 132953751Seric else 133053751Seric { 133153751Seric /* ignore setuid and setgid bits */ 133253751Seric mode &= ~(S_ISGID|S_ISUID); 133353751Seric } 133453751Seric 133540931Srick /* we have to open the dfile BEFORE setuid */ 133653751Seric if (e->e_dfp == NULL && e->e_df != NULL) 133740931Srick { 133840931Srick e->e_dfp = fopen(e->e_df, "r"); 133952673Seric if (e->e_dfp == NULL) 134052673Seric { 134140931Srick syserr("mailfile: Cannot open %s for %s from %s", 134253751Seric e->e_df, e->e_to, e->e_from); 134340931Srick } 134440931Srick } 134540931Srick 134653751Seric if (!bitset(S_ISGID, mode) || setgid(stb.st_gid) < 0) 13474417Seric { 134852673Seric if (ctladdr->q_uid == 0) 134952673Seric { 13504417Seric (void) setgid(DefGid); 135140972Sbostic (void) initgroups(DefUser, DefGid); 135252673Seric } 135352673Seric else 135452673Seric { 13554417Seric (void) setgid(ctladdr->q_gid); 135653751Seric (void) initgroups(ctladdr->q_ruser ? 135753751Seric ctladdr->q_ruser : ctladdr->q_user, 135840972Sbostic ctladdr->q_gid); 135940972Sbostic } 13604417Seric } 136153751Seric if (!bitset(S_ISUID, mode) || setuid(stb.st_uid) < 0) 13624417Seric { 13634417Seric if (ctladdr->q_uid == 0) 13644417Seric (void) setuid(DefUid); 13654417Seric else 13664417Seric (void) setuid(ctladdr->q_uid); 13674417Seric } 136852673Seric FileName = filename; 136952673Seric LineNumber = 0; 13706887Seric f = dfopen(filename, "a"); 13714214Seric if (f == NULL) 137252673Seric { 137352673Seric message("cannot open"); 13744214Seric exit(EX_CANTCREAT); 137552673Seric } 13764214Seric 137754967Seric putfromline(f, ProgMailer, e); 137855012Seric (*e->e_puthdr)(f, ProgMailer, e); 137910168Seric putline("\n", f, ProgMailer); 138055012Seric (*e->e_putbody)(f, ProgMailer, e); 138110168Seric putline("\n", f, ProgMailer); 138252673Seric if (ferror(f)) 138352673Seric { 138452673Seric message("I/O error"); 138552673Seric setstat(EX_IOERR); 138652673Seric } 13874214Seric (void) fclose(f); 13884214Seric (void) fflush(stdout); 13894417Seric 13906887Seric /* reset ISUID & ISGID bits for paranoid systems */ 13914621Seric (void) chmod(filename, (int) stb.st_mode); 139252673Seric exit(ExitStat); 13934315Seric /*NOTREACHED*/ 13944214Seric } 13954214Seric else 13964214Seric { 13974214Seric /* parent -- wait for exit status */ 13989370Seric int st; 13994214Seric 14009370Seric st = waitfor(pid); 14019370Seric if ((st & 0377) != 0) 14029370Seric return (EX_UNAVAILABLE); 14039370Seric else 14049370Seric return ((st >> 8) & 0377); 140540931Srick /*NOTREACHED*/ 14064214Seric } 1407294Seric } 14084550Seric /* 14094550Seric ** SENDALL -- actually send all the messages. 14104550Seric ** 14114550Seric ** Parameters: 14127043Seric ** e -- the envelope to send. 141314874Seric ** mode -- the delivery mode to use. If SM_DEFAULT, use 141414874Seric ** the current SendMode. 14154550Seric ** 14164550Seric ** Returns: 14174550Seric ** none. 14184550Seric ** 14194550Seric ** Side Effects: 14204550Seric ** Scans the send lists and sends everything it finds. 14217043Seric ** Delivers any appropriate error messages. 14229275Seric ** If we are running in a non-interactive mode, takes the 14239275Seric ** appropriate action. 14244550Seric */ 14254550Seric 14269275Seric sendall(e, mode) 14277043Seric ENVELOPE *e; 14289275Seric char mode; 14294550Seric { 14305008Seric register ADDRESS *q; 14317779Seric bool oldverbose; 14329275Seric int pid; 143347284Seric int nsent; 143451937Seric # ifdef LOCKF 143551937Seric struct flock lfd; 143651937Seric # endif 14374550Seric 143814874Seric /* determine actual delivery mode */ 143914874Seric if (mode == SM_DEFAULT) 144014874Seric { 144124941Seric extern bool shouldqueue(); 144214874Seric 144357438Seric if (shouldqueue(e->e_msgpriority, e->e_ctime)) 144414874Seric mode = SM_QUEUE; 144514874Seric else 144614874Seric mode = SendMode; 144714874Seric } 144814874Seric 14498248Seric if (tTd(13, 1)) 14505032Seric { 14519275Seric printf("\nSENDALL: mode %c, sendqueue:\n", mode); 14527043Seric printaddr(e->e_sendqueue, TRUE); 14535032Seric } 14545008Seric 14557043Seric /* 14569275Seric ** Do any preprocessing necessary for the mode we are running. 14579370Seric ** Check to make sure the hop count is reasonable. 14589370Seric ** Delete sends to the sender in mailing lists. 14597043Seric */ 14607043Seric 14619370Seric CurEnv = e; 14629370Seric 146351305Seric if (e->e_hopcount > MaxHopCount) 14649275Seric { 146540931Srick errno = 0; 146640931Srick syserr("sendall: too many hops %d (%d max): from %s, to %s", 146755194Seric e->e_hopcount, MaxHopCount, e->e_from.q_paddr, e->e_to); 14689370Seric return; 14699370Seric } 14709275Seric 14719370Seric if (!MeToo) 14729370Seric { 147312611Seric extern ADDRESS *recipient(); 147412611Seric 14759370Seric e->e_from.q_flags |= QDONTSEND; 147655012Seric (void) recipient(&e->e_from, &e->e_sendqueue, e); 14779275Seric } 14789370Seric 14799370Seric # ifdef QUEUE 14809335Seric if ((mode == SM_QUEUE || mode == SM_FORK || 14819335Seric (mode != SM_VERIFY && SuperSafe)) && 14829335Seric !bitset(EF_INQUEUE, e->e_flags)) 148351920Seric queueup(e, TRUE, mode == SM_QUEUE); 148456795Seric #endif /* QUEUE */ 14859275Seric 14867779Seric oldverbose = Verbose; 14879275Seric switch (mode) 14889275Seric { 14899275Seric case SM_VERIFY: 14907779Seric Verbose = TRUE; 14919275Seric break; 14929275Seric 14939275Seric case SM_QUEUE: 149451916Seric queueonly: 14959335Seric e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; 14969275Seric return; 14979275Seric 14989275Seric case SM_FORK: 14999538Seric if (e->e_xfp != NULL) 15009538Seric (void) fflush(e->e_xfp); 150151916Seric 150251916Seric # ifdef LOCKF 150351916Seric /* 150451916Seric ** Since lockf has the interesting semantic that the 150551937Seric ** lock is lost when we fork, we have to risk losing 150651937Seric ** the lock here by closing before the fork, and then 150751937Seric ** trying to get it back in the child. 150851916Seric */ 150951916Seric 151051920Seric if (e->e_lockfp != NULL) 151151916Seric { 151251920Seric (void) fclose(e->e_lockfp); 151351920Seric e->e_lockfp = NULL; 151451916Seric } 151551916Seric # endif /* LOCKF */ 151651916Seric 15179275Seric pid = fork(); 15189275Seric if (pid < 0) 15199275Seric { 152051916Seric goto queueonly; 15219275Seric } 15229275Seric else if (pid > 0) 15239293Seric { 15249293Seric /* be sure we leave the temp files to our child */ 15259335Seric e->e_id = e->e_df = NULL; 152651916Seric # ifndef LOCKF 152751920Seric if (e->e_lockfp != NULL) 152851920Seric (void) fclose(e->e_lockfp); 152951916Seric # endif 15309275Seric return; 15319293Seric } 15329275Seric 15339275Seric /* double fork to avoid zombies */ 15349275Seric if (fork() > 0) 15359275Seric exit(EX_OK); 15369275Seric 15379293Seric /* be sure we are immune from the terminal */ 153810133Seric disconnect(FALSE); 15399293Seric 154051911Seric # ifdef LOCKF 154151911Seric /* 154251916Seric ** Now try to get our lock back. 154351911Seric */ 154451911Seric 154551937Seric lfd.l_type = F_WRLCK; 154651937Seric lfd.l_whence = lfd.l_start = lfd.l_len = 0; 154751920Seric e->e_lockfp = fopen(queuename(e, 'q'), "r+"); 154851920Seric if (e->e_lockfp == NULL || 154951937Seric fcntl(fileno(e->e_lockfp), F_SETLK, &lfd) < 0) 155051911Seric { 155151916Seric /* oops.... lost it */ 155251911Seric # ifdef LOG 155351916Seric if (LogLevel > 5) 155451916Seric syslog(LOG_NOTICE, "%s: lost lock: %m", 155554967Seric e->e_id); 155651911Seric # endif /* LOG */ 155751916Seric exit(EX_OK); 155851911Seric } 155951911Seric # endif /* LOCKF */ 156051911Seric 15619275Seric break; 15629275Seric } 15639275Seric 15649275Seric /* 15659275Seric ** Run through the list and send everything. 15669275Seric */ 15679275Seric 156847284Seric nsent = 0; 15697043Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 15704550Seric { 15719275Seric if (mode == SM_VERIFY) 15724550Seric { 15739293Seric e->e_to = q->q_paddr; 15745008Seric if (!bitset(QDONTSEND|QBADADDR, q->q_flags)) 15757052Seric message(Arpa_Info, "deliverable"); 15764550Seric } 157747284Seric else if (!bitset(QDONTSEND, q->q_flags)) 157847284Seric { 157950533Seric # ifdef QUEUE 158047284Seric /* 158147284Seric ** Checkpoint the send list every few addresses 158247284Seric */ 158347284Seric 158447284Seric if (nsent >= CheckpointInterval) 158547284Seric { 158651920Seric queueup(e, TRUE, FALSE); 158747284Seric nsent = 0; 158847284Seric } 158950533Seric # endif /* QUEUE */ 159047284Seric if (deliver(e, q) == EX_OK) 159147284Seric nsent++; 159247284Seric } 15934550Seric } 15947779Seric Verbose = oldverbose; 15957043Seric 15967043Seric /* 15977043Seric ** Now run through and check for errors. 15987043Seric */ 15997043Seric 160051920Seric if (mode == SM_VERIFY) 16017043Seric return; 16027043Seric 16037043Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 16047043Seric { 16057043Seric register ADDRESS *qq; 16067043Seric 16078248Seric if (tTd(13, 3)) 16088248Seric { 16098248Seric printf("Checking "); 16108248Seric printaddr(q, FALSE); 16118248Seric } 16128248Seric 16139335Seric /* only send errors if the message failed */ 16149335Seric if (!bitset(QBADADDR, q->q_flags)) 16159335Seric continue; 16167043Seric 16177043Seric /* we have an address that failed -- find the parent */ 16187043Seric for (qq = q; qq != NULL; qq = qq->q_alias) 16197043Seric { 16207043Seric char obuf[MAXNAME + 6]; 16217043Seric extern char *aliaslookup(); 16227043Seric 16237043Seric /* we can only have owners for local addresses */ 162410682Seric if (!bitnset(M_LOCAL, qq->q_mailer->m_flags)) 16257043Seric continue; 16267043Seric 16277043Seric /* see if the owner list exists */ 16287043Seric (void) strcpy(obuf, "owner-"); 16297047Seric if (strncmp(qq->q_user, "owner-", 6) == 0) 16307047Seric (void) strcat(obuf, "owner"); 16317047Seric else 16327047Seric (void) strcat(obuf, qq->q_user); 163357438Seric if (!bitnset(M_USR_UPPER, qq->q_mailer->m_flags)) 163457438Seric makelower(obuf); 16357043Seric if (aliaslookup(obuf) == NULL) 16367043Seric continue; 16377043Seric 16388248Seric if (tTd(13, 4)) 16398248Seric printf("Errors to %s\n", obuf); 16408248Seric 16417043Seric /* owner list exists -- add it to the error queue */ 164255012Seric sendtolist(obuf, (ADDRESS *) NULL, &e->e_errorqueue, e); 164357438Seric 164457438Seric /* and set the return path to point to it */ 164557438Seric e->e_returnpath = newstr(obuf); 164657438Seric 164716883Seric ErrorMode = EM_MAIL; 16487043Seric break; 16497043Seric } 16507043Seric 16517043Seric /* if we did not find an owner, send to the sender */ 16528426Seric if (qq == NULL && bitset(QBADADDR, q->q_flags)) 165355012Seric sendtolist(e->e_from.q_paddr, qq, &e->e_errorqueue, e); 16547043Seric } 16559275Seric 16569275Seric if (mode == SM_FORK) 16579275Seric finis(); 16584550Seric } 1659