122701Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 333728Sbostic * Copyright (c) 1988 Regents of the University of California. 433728Sbostic * All rights reserved. 533728Sbostic * 633728Sbostic * Redistribution and use in source and binary forms are permitted 734920Sbostic * provided that the above copyright notice and this paragraph are 834920Sbostic * duplicated in all such forms and that any documentation, 934920Sbostic * advertising materials, and other materials related to such 1034920Sbostic * distribution and use acknowledge that the software was developed 1134920Sbostic * by the University of California, Berkeley. The name of the 1234920Sbostic * University may not be used to endorse or promote products derived 1334920Sbostic * from this software without specific prior written permission. 1434920Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1534920Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1634920Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1733728Sbostic */ 1822701Sdist 1922701Sdist #ifndef lint 20*40972Sbostic static char sccsid[] = "@(#)deliver.c 5.31 (Berkeley) 04/18/90"; 2133728Sbostic #endif /* not lint */ 2222701Sdist 2340961Sbostic #include "sendmail.h" 2433931Sbostic #include <sys/signal.h> 2533931Sbostic #include <sys/stat.h> 2633931Sbostic #include <netdb.h> 2736030Sbostic #include <fcntl.h> 2833931Sbostic #include <errno.h> 2935651Seric #ifdef NAMED_BIND 3034022Sbostic #include <arpa/nameser.h> 3134022Sbostic #include <resolv.h> 3235651Seric #endif 33294Seric 34294Seric /* 354315Seric ** DELIVER -- Deliver a message to a list of addresses. 36294Seric ** 374315Seric ** This routine delivers to everyone on the same host as the 384315Seric ** user on the head of the list. It is clever about mailers 394315Seric ** that don't handle multiple users. It is NOT guaranteed 404315Seric ** that it will deliver to all these addresses however -- so 414315Seric ** deliver should be called once for each address on the 424315Seric ** list. 434315Seric ** 44294Seric ** Parameters: 459370Seric ** e -- the envelope to deliver. 464621Seric ** firstto -- head of the address list to deliver to. 47294Seric ** 48294Seric ** Returns: 49294Seric ** zero -- successfully delivered. 50294Seric ** else -- some failure, see ExitStat for more info. 51294Seric ** 52294Seric ** Side Effects: 53294Seric ** The standard input is passed off to someone. 54294Seric */ 55294Seric 569370Seric deliver(e, firstto) 579370Seric register ENVELOPE *e; 584621Seric ADDRESS *firstto; 59294Seric { 604452Seric char *host; /* host being sent to */ 614452Seric char *user; /* user being sent to */ 62294Seric char **pvp; 633233Seric register char **mvp; 643233Seric register char *p; 6510306Seric register MAILER *m; /* mailer for this recipient */ 664397Seric ADDRESS *ctladdr; 674621Seric register ADDRESS *to = firstto; 684863Seric bool clever = FALSE; /* running user smtp to this mailer */ 695032Seric ADDRESS *tochain = NULL; /* chain of users in this mailer call */ 7033931Sbostic int rcode; /* response code */ 7110306Seric char *pv[MAXPV+1]; 7210306Seric char tobuf[MAXLINE-50]; /* text line of to people */ 7310306Seric char buf[MAXNAME]; 7410306Seric char tfrombuf[MAXNAME]; /* translated from person */ 7510306Seric extern bool checkcompat(); 7610306Seric extern ADDRESS *getctladdr(); 7710306Seric extern char *remotename(); 78294Seric 794488Seric errno = 0; 807052Seric if (bitset(QDONTSEND, to->q_flags)) 813233Seric return (0); 82294Seric 8335651Seric #ifdef NAMED_BIND 8434022Sbostic /* unless interactive, try twice, over a minute */ 8534022Sbostic if (OpMode == MD_DAEMON || OpMode == MD_SMTP) { 8634022Sbostic _res.retrans = 30; 8734022Sbostic _res.retry = 2; 8834022Sbostic } 8936788Sbostic #endif 9034022Sbostic 916974Seric m = to->q_mailer; 926974Seric host = to->q_host; 936974Seric 947672Seric if (tTd(10, 1)) 953233Seric printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n", 966974Seric m->m_mno, host, to->q_user); 97294Seric 98294Seric /* 995903Seric ** If this mailer is expensive, and if we don't want to make 1005903Seric ** connections now, just mark these addresses and return. 1015903Seric ** This is useful if we want to batch connections to 1025903Seric ** reduce load. This will cause the messages to be 1035903Seric ** queued up, and a daemon will come along to send the 1045903Seric ** messages later. 1055903Seric ** This should be on a per-mailer basis. 1065903Seric */ 1075903Seric 10810682Seric if (NoConnect && !QueueRun && bitnset(M_EXPENSIVE, m->m_flags) && 1098428Seric !Verbose) 1105903Seric { 1115903Seric for (; to != NULL; to = to->q_next) 1128431Seric { 1138431Seric if (bitset(QDONTSEND, to->q_flags) || to->q_mailer != m) 1148431Seric continue; 1158431Seric to->q_flags |= QQUEUEUP|QDONTSEND; 1169370Seric e->e_to = to->q_paddr; 1178496Seric message(Arpa_Info, "queued"); 1188496Seric if (LogLevel > 4) 1198496Seric logdelivery("queued"); 1208431Seric } 1219370Seric e->e_to = NULL; 1225903Seric return (0); 1235903Seric } 1245903Seric 1255903Seric /* 1263233Seric ** Do initial argv setup. 1273233Seric ** Insert the mailer name. Notice that $x expansion is 1283233Seric ** NOT done on the mailer name. Then, if the mailer has 1293233Seric ** a picky -f flag, we insert it as appropriate. This 1303233Seric ** code does not check for 'pv' overflow; this places a 1313233Seric ** manifest lower limit of 4 for MAXPV. 1328062Seric ** The from address rewrite is expected to make 1338062Seric ** the address relative to the other end. 1342968Seric */ 1352968Seric 1364452Seric /* rewrite from address, using rewriting rules */ 13716150Seric expand("\001f", buf, &buf[sizeof buf - 1], e); 13810306Seric (void) strcpy(tfrombuf, remotename(buf, m, TRUE, TRUE)); 1394452Seric 1409370Seric define('g', tfrombuf, e); /* translated sender address */ 1419370Seric define('h', host, e); /* to host */ 1423233Seric Errors = 0; 1433233Seric pvp = pv; 1443233Seric *pvp++ = m->m_argv[0]; 1452968Seric 1463233Seric /* insert -f or -r flag as appropriate */ 14710682Seric if (FromFlag && (bitnset(M_FOPT, m->m_flags) || bitnset(M_ROPT, m->m_flags))) 1483233Seric { 14910682Seric if (bitnset(M_FOPT, m->m_flags)) 1503233Seric *pvp++ = "-f"; 1513233Seric else 1523233Seric *pvp++ = "-r"; 15316150Seric expand("\001g", buf, &buf[sizeof buf - 1], e); 1543233Seric *pvp++ = newstr(buf); 1553233Seric } 156294Seric 157294Seric /* 1583233Seric ** Append the other fixed parts of the argv. These run 1593233Seric ** up to the first entry containing "$u". There can only 1603233Seric ** be one of these, and there are only a few more slots 1613233Seric ** in the pv after it. 162294Seric */ 163294Seric 1643233Seric for (mvp = m->m_argv; (p = *++mvp) != NULL; ) 165294Seric { 16616150Seric while ((p = index(p, '\001')) != NULL) 1673233Seric if (*++p == 'u') 1683233Seric break; 1693233Seric if (p != NULL) 1703233Seric break; 1713233Seric 1723233Seric /* this entry is safe -- go ahead and process it */ 1739370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 1743233Seric *pvp++ = newstr(buf); 1753233Seric if (pvp >= &pv[MAXPV - 3]) 1763233Seric { 1773233Seric syserr("Too many parameters to %s before $u", pv[0]); 1783233Seric return (-1); 1793233Seric } 180294Seric } 1814863Seric 1826038Seric /* 1836038Seric ** If we have no substitution for the user name in the argument 1846038Seric ** list, we know that we must supply the names otherwise -- and 1856038Seric ** SMTP is the answer!! 1866038Seric */ 1876038Seric 1883233Seric if (*mvp == NULL) 1894863Seric { 1904863Seric /* running SMTP */ 1915179Seric # ifdef SMTP 1924863Seric clever = TRUE; 1934863Seric *pvp = NULL; 1945179Seric # else SMTP 1956038Seric /* oops! we don't implement SMTP */ 1965179Seric syserr("SMTP style mailer"); 1975179Seric return (EX_SOFTWARE); 1985179Seric # endif SMTP 1994863Seric } 200294Seric 201294Seric /* 2023233Seric ** At this point *mvp points to the argument with $u. We 2033233Seric ** run through our address list and append all the addresses 2043233Seric ** we can. If we run out of space, do not fret! We can 2053233Seric ** always send another copy later. 206294Seric */ 207294Seric 2083233Seric tobuf[0] = '\0'; 2099370Seric e->e_to = tobuf; 2104397Seric ctladdr = NULL; 2113233Seric for (; to != NULL; to = to->q_next) 212294Seric { 2133233Seric /* avoid sending multiple recipients to dumb mailers */ 21410682Seric if (tobuf[0] != '\0' && !bitnset(M_MUSER, m->m_flags)) 2153233Seric break; 2163233Seric 2173233Seric /* if already sent or not for this host, don't send */ 2187052Seric if (bitset(QDONTSEND, to->q_flags) || 2197052Seric strcmp(to->q_host, host) != 0 || 2207052Seric to->q_mailer != firstto->q_mailer) 2213233Seric continue; 2224397Seric 2238225Seric /* avoid overflowing tobuf */ 2249370Seric if (sizeof tobuf - (strlen(to->q_paddr) + strlen(tobuf) + 2) < 0) 2258225Seric break; 2268225Seric 2277672Seric if (tTd(10, 1)) 2285032Seric { 2295032Seric printf("\nsend to "); 2305032Seric printaddr(to, FALSE); 2315032Seric } 2325032Seric 2334397Seric /* compute effective uid/gid when sending */ 2344596Seric if (to->q_mailer == ProgMailer) 2354397Seric ctladdr = getctladdr(to); 2364397Seric 2373233Seric user = to->q_user; 2389370Seric e->e_to = to->q_paddr; 2393233Seric to->q_flags |= QDONTSEND; 2403233Seric 2413233Seric /* 2423233Seric ** Check to see that these people are allowed to 2433233Seric ** talk to each other. 2443233Seric */ 2453233Seric 24610699Seric if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize) 24710699Seric { 24829914Seric NoReturn = TRUE; 24910699Seric usrerr("Message is too large; %ld bytes max", m->m_maxsize); 25010699Seric giveresponse(EX_UNAVAILABLE, m, e); 25110699Seric continue; 25210699Seric } 2533233Seric if (!checkcompat(to)) 254294Seric { 25510105Seric giveresponse(EX_UNAVAILABLE, m, e); 2563233Seric continue; 257294Seric } 2583233Seric 2593233Seric /* 2604099Seric ** Strip quote bits from names if the mailer is dumb 2614099Seric ** about them. 2623233Seric */ 2633233Seric 26410682Seric if (bitnset(M_STRIPQ, m->m_flags)) 265294Seric { 2664099Seric stripquotes(user, TRUE); 2674099Seric stripquotes(host, TRUE); 2683233Seric } 2694099Seric else 2704099Seric { 2714099Seric stripquotes(user, FALSE); 2724099Seric stripquotes(host, FALSE); 2734099Seric } 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 3024596Seric if (m == LocalMailer) 3033233Seric { 3045599Seric if (user[0] == '/') 305294Seric { 3068003Seric rcode = mailfile(user, getctladdr(to)); 30710105Seric giveresponse(rcode, m, e); 3083233Seric continue; 309294Seric } 310294Seric } 3113233Seric 3124315Seric /* 3134315Seric ** Address is verified -- add this user to mailer 3144315Seric ** argv, and add it to the print list of recipients. 3154315Seric */ 3164315Seric 3176059Seric /* link together the chain of recipients */ 3186272Seric to->q_tchain = tochain; 3196272Seric tochain = to; 3206059Seric 3213233Seric /* create list of users for error messages */ 3229388Seric (void) strcat(tobuf, ","); 3234082Seric (void) strcat(tobuf, to->q_paddr); 3249370Seric define('u', user, e); /* to user */ 3259370Seric define('z', to->q_home, e); /* user's home */ 3263233Seric 3274863Seric /* 3286059Seric ** Expand out this user into argument list. 3294863Seric */ 3304863Seric 3316059Seric if (!clever) 3323233Seric { 3339370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 3344863Seric *pvp++ = newstr(buf); 3354863Seric if (pvp >= &pv[MAXPV - 2]) 3364863Seric { 3374863Seric /* allow some space for trailing parms */ 3384863Seric break; 3394863Seric } 3404863Seric } 341294Seric } 342294Seric 3434067Seric /* see if any addresses still exist */ 3444067Seric if (tobuf[0] == '\0') 3454863Seric { 3469370Seric define('g', (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 37435651Seric #ifdef NAMED_BIND 37534022Sbostic _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ 37635651Seric #endif 37733931Sbostic #ifdef SMTP 37835651Seric if (clever) 37935651Seric { 38033931Sbostic rcode = EX_OK; 38135651Seric #ifdef NAMED_BIND 38236810Sbostic if (host[0] && host[0] != '[') 38335651Seric { 38436810Sbostic expand("\001w", buf, &buf[sizeof(buf) - 1], e); 38535651Seric Nmx = getmxrr(host, MxHosts, buf, &rcode); 38635651Seric } 38735651Seric else 38835651Seric #endif 38935651Seric { 39031952Sbostic Nmx = 1; 39131952Sbostic MxHosts[0] = host; 39235651Seric } 39335651Seric if (Nmx >= 0) 39435651Seric { 39534022Sbostic message(Arpa_Info, "Connecting to %s (%s)...", 39634022Sbostic MxHosts[0], m->m_name); 39734022Sbostic if ((rcode = smtpinit(m, pv)) == EX_OK) { 39836239Skarels register char *t = tobuf; 39936239Skarels register int i; 40036239Skarels 40134022Sbostic /* send the recipient list */ 40234022Sbostic tobuf[0] = '\0'; 40334022Sbostic for (to = tochain; to; to = to->q_tchain) { 40434022Sbostic e->e_to = to->q_paddr; 40534022Sbostic if ((i = smtprcpt(to, m)) != EX_OK) { 40634022Sbostic markfailure(e, to, i); 40734022Sbostic giveresponse(i, m, e); 40834022Sbostic } 40934022Sbostic else { 41034022Sbostic *t++ = ','; 41134022Sbostic for (p = to->q_paddr; *p; *t++ = *p++); 41234022Sbostic } 4139388Seric } 41434022Sbostic 41534022Sbostic /* now send the data */ 41634022Sbostic if (tobuf[0] == '\0') 41734022Sbostic e->e_to = NULL; 41833931Sbostic else { 41934022Sbostic e->e_to = tobuf + 1; 42034022Sbostic rcode = smtpdata(m, e); 4219388Seric } 4229388Seric 42334022Sbostic /* now close the connection */ 42434022Sbostic smtpquit(m); 4259370Seric } 4269370Seric } 4274863Seric } 4284863Seric else 42933931Sbostic #endif /* SMTP */ 43033935Sbostic { 43134022Sbostic message(Arpa_Info, "Connecting to %s (%s)...", host, m->m_name); 43210168Seric rcode = sendoff(e, m, pv, ctladdr); 43333935Sbostic } 43435651Seric #ifdef NAMED_BIND 43534022Sbostic _res.options |= RES_DEFNAMES | RES_DNSRCH; /* XXX */ 43635651Seric #endif 4373233Seric 4384621Seric /* 4399388Seric ** Do final status disposal. 4409388Seric ** We check for something in tobuf for the SMTP case. 4419388Seric ** If we got a temporary failure, arrange to queue the 4429388Seric ** addressees. 4434621Seric */ 4444621Seric 4459388Seric if (tobuf[0] != '\0') 44610105Seric giveresponse(rcode, m, e); 4479388Seric if (rcode != EX_OK) 4485032Seric for (to = tochain; to != NULL; to = to->q_tchain) 44910092Seric markfailure(e, to, rcode); 4504621Seric 4514488Seric errno = 0; 4529370Seric define('g', (char *) NULL, e); 4538003Seric return (rcode); 4543233Seric } 4553233Seric /* 45610092Seric ** MARKFAILURE -- mark a failure on a specific address. 45710092Seric ** 45810092Seric ** Parameters: 45910092Seric ** e -- the envelope we are sending. 46010092Seric ** q -- the address to mark. 46110092Seric ** rcode -- the code signifying the particular failure. 46210092Seric ** 46310092Seric ** Returns: 46410092Seric ** none. 46510092Seric ** 46610092Seric ** Side Effects: 46710092Seric ** marks the address (and possibly the envelope) with the 46810092Seric ** failure so that an error will be returned or 46910092Seric ** the message will be queued, as appropriate. 47010092Seric */ 47110092Seric 47210092Seric markfailure(e, q, rcode) 47310092Seric register ENVELOPE *e; 47410092Seric register ADDRESS *q; 47510092Seric int rcode; 47610092Seric { 47710092Seric if (rcode == EX_OK) 47810092Seric return; 47910092Seric else if (rcode != EX_TEMPFAIL) 48010092Seric q->q_flags |= QBADADDR; 48110092Seric else if (curtime() > e->e_ctime + TimeOut) 48210092Seric { 48310092Seric extern char *pintvl(); 48410105Seric char buf[MAXLINE]; 48510092Seric 48610092Seric if (!bitset(EF_TIMEOUT, e->e_flags)) 48710105Seric { 48810105Seric (void) sprintf(buf, "Cannot send message for %s", 48910092Seric pintvl(TimeOut, FALSE)); 49010105Seric if (e->e_message != NULL) 49110105Seric free(e->e_message); 49210105Seric e->e_message = newstr(buf); 49310105Seric message(Arpa_Info, buf); 49410105Seric } 49510092Seric q->q_flags |= QBADADDR; 49610092Seric e->e_flags |= EF_TIMEOUT; 49710092Seric } 49810092Seric else 49910092Seric q->q_flags |= QQUEUEUP; 50010092Seric } 50110092Seric /* 5024214Seric ** DOFORK -- do a fork, retrying a couple of times on failure. 5034214Seric ** 5044214Seric ** This MUST be a macro, since after a vfork we are running 5054214Seric ** two processes on the same stack!!! 5064214Seric ** 5074214Seric ** Parameters: 5084214Seric ** none. 5094214Seric ** 5104214Seric ** Returns: 5114214Seric ** From a macro??? You've got to be kidding! 5124214Seric ** 5134214Seric ** Side Effects: 5144214Seric ** Modifies the ==> LOCAL <== variable 'pid', leaving: 5154214Seric ** pid of child in parent, zero in child. 5164214Seric ** -1 on unrecoverable error. 5174214Seric ** 5184214Seric ** Notes: 5194214Seric ** I'm awfully sorry this looks so awful. That's 5204214Seric ** vfork for you..... 5214214Seric */ 5224214Seric 5234214Seric # define NFORKTRIES 5 5249148Seric # ifdef VMUNIX 5254214Seric # define XFORK vfork 5269148Seric # else VMUNIX 5274214Seric # define XFORK fork 5289148Seric # endif VMUNIX 5294214Seric 5304214Seric # define DOFORK(fORKfN) \ 5314214Seric {\ 5324214Seric register int i;\ 5334214Seric \ 53423504Seric for (i = NFORKTRIES; --i >= 0; )\ 5354214Seric {\ 5364214Seric pid = fORKfN();\ 5374214Seric if (pid >= 0)\ 5384214Seric break;\ 53923504Seric if (i > 0)\ 54025617Seric sleep((unsigned) NFORKTRIES - i);\ 5414214Seric }\ 5424214Seric } 5434214Seric /* 5444637Seric ** DOFORK -- simple fork interface to DOFORK. 5454637Seric ** 5464637Seric ** Parameters: 5474637Seric ** none. 5484637Seric ** 5494637Seric ** Returns: 5504637Seric ** pid of child in parent. 5514637Seric ** zero in child. 5524637Seric ** -1 on error. 5534637Seric ** 5544637Seric ** Side Effects: 5554637Seric ** returns twice, once in parent and once in child. 5564637Seric */ 5574637Seric 5584637Seric dofork() 5594637Seric { 5604637Seric register int pid; 5614637Seric 5624637Seric DOFORK(fork); 5634637Seric return (pid); 5644637Seric } 5654637Seric /* 5663233Seric ** SENDOFF -- send off call to mailer & collect response. 5673233Seric ** 5683233Seric ** Parameters: 5699370Seric ** e -- the envelope to mail. 5703233Seric ** m -- mailer descriptor. 5713233Seric ** pvp -- parameter vector to send to it. 5724397Seric ** ctladdr -- an address pointer controlling the 5734397Seric ** user/groupid etc. of the mailer. 5743233Seric ** 5753233Seric ** Returns: 5763233Seric ** exit status of mailer. 5773233Seric ** 5783233Seric ** Side Effects: 5793233Seric ** none. 5803233Seric */ 58134022Sbostic static 58210168Seric sendoff(e, m, pvp, ctladdr) 5839370Seric register ENVELOPE *e; 5849370Seric MAILER *m; 5853233Seric char **pvp; 5864397Seric ADDRESS *ctladdr; 5873233Seric { 5884863Seric auto FILE *mfile; 5894863Seric auto FILE *rfile; 5903233Seric register int i; 5913233Seric int pid; 5924863Seric 5934863Seric /* 5944863Seric ** Create connection to mailer. 5954863Seric */ 5964863Seric 5974863Seric pid = openmailer(m, pvp, ctladdr, FALSE, &mfile, &rfile); 5984863Seric if (pid < 0) 5994863Seric return (-1); 6004863Seric 6014863Seric /* 6024863Seric ** Format and send message. 6034863Seric */ 6044863Seric 60510168Seric putfromline(mfile, m); 60610168Seric (*e->e_puthdr)(mfile, m, e); 60710168Seric putline("\n", mfile, m); 60810168Seric (*e->e_putbody)(mfile, m, e); 6094863Seric (void) fclose(mfile); 6104863Seric 6114863Seric i = endmailer(pid, pvp[0]); 6125981Seric 6135981Seric /* arrange a return receipt if requested */ 61410682Seric if (e->e_receiptto != NULL && bitnset(M_LOCAL, m->m_flags)) 6155981Seric { 6169370Seric e->e_flags |= EF_SENDRECEIPT; 6175981Seric /* do we want to send back more info? */ 6185981Seric } 6195981Seric 6204863Seric return (i); 6214863Seric } 6224863Seric /* 6234863Seric ** ENDMAILER -- Wait for mailer to terminate. 6244863Seric ** 6254863Seric ** We should never get fatal errors (e.g., segmentation 6264863Seric ** violation), so we report those specially. For other 6274863Seric ** errors, we choose a status message (into statmsg), 6284863Seric ** and if it represents an error, we print it. 6294863Seric ** 6304863Seric ** Parameters: 6314863Seric ** pid -- pid of mailer. 6324863Seric ** name -- name of mailer (for error messages). 6334863Seric ** 6344863Seric ** Returns: 6354863Seric ** exit code of mailer. 6364863Seric ** 6374863Seric ** Side Effects: 6384863Seric ** none. 6394863Seric */ 6404863Seric 6414863Seric endmailer(pid, name) 6424863Seric int pid; 6434863Seric char *name; 6444863Seric { 6459370Seric int st; 6464863Seric 6476038Seric /* in the IPC case there is nothing to wait for */ 6486038Seric if (pid == 0) 6496038Seric return (EX_OK); 6506038Seric 6516038Seric /* wait for the mailer process to die and collect status */ 6529370Seric st = waitfor(pid); 6539370Seric if (st == -1) 6548127Seric { 6559370Seric syserr("endmailer %s: wait", name); 6569370Seric return (EX_SOFTWARE); 6574863Seric } 6586038Seric 6596038Seric /* see if it died a horrid death */ 6604863Seric if ((st & 0377) != 0) 6614863Seric { 66224941Seric syserr("mailer %s died with signal %o", name, st); 66324941Seric ExitStat = EX_TEMPFAIL; 66424941Seric return (EX_TEMPFAIL); 6654863Seric } 6666038Seric 6676038Seric /* normal death -- return status */ 6689370Seric st = (st >> 8) & 0377; 6699370Seric return (st); 6704863Seric } 6714863Seric /* 6724863Seric ** OPENMAILER -- open connection to mailer. 6734863Seric ** 6744863Seric ** Parameters: 6754863Seric ** m -- mailer descriptor. 6764863Seric ** pvp -- parameter vector to pass to mailer. 6774863Seric ** ctladdr -- controlling address for user. 6784863Seric ** clever -- create a full duplex connection. 6794863Seric ** pmfile -- pointer to mfile (to mailer) connection. 6804863Seric ** prfile -- pointer to rfile (from mailer) connection. 6814863Seric ** 6824863Seric ** Returns: 6836038Seric ** pid of mailer ( > 0 ). 6844863Seric ** -1 on error. 6856038Seric ** zero on an IPC connection. 6864863Seric ** 6874863Seric ** Side Effects: 6884863Seric ** creates a mailer in a subprocess. 6894863Seric */ 6904863Seric 6914863Seric openmailer(m, pvp, ctladdr, clever, pmfile, prfile) 6929370Seric MAILER *m; 6934863Seric char **pvp; 6944863Seric ADDRESS *ctladdr; 6954863Seric bool clever; 6964863Seric FILE **pmfile; 6974863Seric FILE **prfile; 6984863Seric { 6994863Seric int pid; 7004709Seric int mpvect[2]; 7014863Seric int rpvect[2]; 7023233Seric FILE *mfile; 7034863Seric FILE *rfile; 7043233Seric extern FILE *fdopen(); 7053233Seric 7067672Seric if (tTd(11, 1)) 707294Seric { 7088178Seric printf("openmailer:"); 7093233Seric printav(pvp); 710294Seric } 7114488Seric errno = 0; 7123233Seric 71325050Seric CurHostName = m->m_mailer; 71425050Seric 7156038Seric /* 7166038Seric ** Deal with the special case of mail handled through an IPC 7176038Seric ** connection. 7186038Seric ** In this case we don't actually fork. We must be 7196038Seric ** running SMTP for this to work. We will return a 7206038Seric ** zero pid to indicate that we are running IPC. 72111160Seric ** We also handle a debug version that just talks to stdin/out. 7226038Seric */ 7236038Seric 72411160Seric /* check for Local Person Communication -- not for mortals!!! */ 72511160Seric if (strcmp(m->m_mailer, "[LPC]") == 0) 72611160Seric { 72711160Seric *pmfile = stdout; 72811160Seric *prfile = stdin; 72911160Seric return (0); 73011160Seric } 73111160Seric 7326038Seric if (strcmp(m->m_mailer, "[IPC]") == 0) 7336038Seric { 73424941Seric #ifdef HOSTINFO 73524941Seric register STAB *st; 73624941Seric extern STAB *stab(); 73724941Seric #endif HOSTINFO 7389370Seric #ifdef DAEMON 73929433Sbloom register int i, j; 7407285Seric register u_short port; 7416038Seric 74225050Seric CurHostName = pvp[1]; 7436038Seric if (!clever) 7446038Seric syserr("non-clever IPC"); 7456632Seric if (pvp[2] != NULL) 7467285Seric port = atoi(pvp[2]); 7476632Seric else 7487285Seric port = 0; 74929865Seric for (j = 0; j < Nmx; j++) 75029433Sbloom { 75129865Seric CurHostName = MxHosts[j]; 75224941Seric #ifdef HOSTINFO 75324941Seric /* see if we have already determined that this host is fried */ 75429865Seric st = stab(MxHosts[j], ST_HOST, ST_FIND); 75534022Sbostic if (st == NULL || st->s_host.ho_exitstat == EX_OK) { 75634022Sbostic if (j > 1) 75734022Sbostic message(Arpa_Info, 75834022Sbostic "Connecting to %s (%s)...", 75934022Sbostic MxHosts[j], m->m_name); 76029865Seric i = makeconnection(MxHosts[j], port, pmfile, prfile); 76134022Sbostic } 76229433Sbloom else 76329433Sbloom { 76429433Sbloom i = st->s_host.ho_exitstat; 76529433Sbloom errno = st->s_host.ho_errno; 76629433Sbloom } 76724941Seric #else HOSTINFO 76829865Seric i = makeconnection(MxHosts[j], port, pmfile, prfile); 76924941Seric #endif HOSTINFO 77029433Sbloom if (i != EX_OK) 77129433Sbloom { 77224941Seric #ifdef HOSTINFO 77329433Sbloom /* enter status of this host */ 77429433Sbloom if (st == NULL) 77529865Seric st = stab(MxHosts[j], ST_HOST, ST_ENTER); 77629433Sbloom st->s_host.ho_exitstat = i; 77729433Sbloom st->s_host.ho_errno = errno; 77824941Seric #endif HOSTINFO 77929433Sbloom ExitStat = i; 78029433Sbloom continue; 78129433Sbloom } 78229433Sbloom else 78329433Sbloom return (0); 7846047Seric } 78529433Sbloom return (-1); 7869370Seric #else DAEMON 7879370Seric syserr("openmailer: no IPC"); 7889370Seric return (-1); 7899370Seric #endif DAEMON 7906038Seric } 7916038Seric 7922898Seric /* create a pipe to shove the mail through */ 7934709Seric if (pipe(mpvect) < 0) 794294Seric { 7959370Seric syserr("openmailer: pipe (to mailer)"); 796294Seric return (-1); 797294Seric } 7984863Seric 7999370Seric #ifdef SMTP 8004863Seric /* if this mailer speaks smtp, create a return pipe */ 8014863Seric if (clever && pipe(rpvect) < 0) 8024863Seric { 8039370Seric syserr("openmailer: pipe (from mailer)"); 8044863Seric (void) close(mpvect[0]); 8054863Seric (void) close(mpvect[1]); 8064863Seric return (-1); 8074863Seric } 8089370Seric #endif SMTP 8094863Seric 8106038Seric /* 8116038Seric ** Actually fork the mailer process. 8126038Seric ** DOFORK is clever about retrying. 81326434Seric ** 81426434Seric ** Dispose of SIGCHLD signal catchers that may be laying 81526434Seric ** around so that endmail will get it. 8166038Seric */ 8176038Seric 8189538Seric if (CurEnv->e_xfp != NULL) 8199538Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 8209370Seric (void) fflush(stdout); 82126434Seric # ifdef SIGCHLD 82226434Seric (void) signal(SIGCHLD, SIG_DFL); 82326434Seric # endif SIGCHLD 8244214Seric DOFORK(XFORK); 8254327Seric /* pid is set by DOFORK */ 826294Seric if (pid < 0) 827294Seric { 8286038Seric /* failure */ 8299370Seric syserr("openmailer: cannot fork"); 8304709Seric (void) close(mpvect[0]); 8314709Seric (void) close(mpvect[1]); 8329370Seric #ifdef SMTP 8334863Seric if (clever) 8344863Seric { 8354863Seric (void) close(rpvect[0]); 8364863Seric (void) close(rpvect[1]); 8374863Seric } 8389370Seric #endif SMTP 839294Seric return (-1); 840294Seric } 841294Seric else if (pid == 0) 842294Seric { 84315772Seric int i; 84424941Seric extern int DtableSize; 84515772Seric 846294Seric /* child -- set up input & exec mailer */ 8471621Seric /* make diagnostic output be standard output */ 8484477Seric (void) signal(SIGINT, SIG_IGN); 8494477Seric (void) signal(SIGHUP, SIG_IGN); 8504215Seric (void) signal(SIGTERM, SIG_DFL); 8514709Seric 8524709Seric /* arrange to filter standard & diag output of command */ 8534863Seric if (clever) 8544709Seric { 8554863Seric (void) close(rpvect[0]); 8564709Seric (void) close(1); 8574863Seric (void) dup(rpvect[1]); 8584863Seric (void) close(rpvect[1]); 8594863Seric } 8609275Seric else if (OpMode == MD_SMTP || HoldErrs) 8614863Seric { 8629370Seric /* put mailer output in transcript */ 8634863Seric (void) close(1); 8649538Seric (void) dup(fileno(CurEnv->e_xfp)); 8654709Seric } 8664082Seric (void) close(2); 8674082Seric (void) dup(1); 8684709Seric 8694709Seric /* arrange to get standard input */ 8704709Seric (void) close(mpvect[1]); 8714082Seric (void) close(0); 8724709Seric if (dup(mpvect[0]) < 0) 873294Seric { 8742898Seric syserr("Cannot dup to zero!"); 8752898Seric _exit(EX_OSERR); 876294Seric } 8774709Seric (void) close(mpvect[0]); 87810682Seric if (!bitnset(M_RESTR, m->m_flags)) 8794215Seric { 88016883Seric if (ctladdr == NULL || ctladdr->q_uid == 0) 8814417Seric { 8824417Seric (void) setgid(DefGid); 883*40972Sbostic (void) initgroups(DefUser, DefGid); 8844417Seric (void) setuid(DefUid); 8854417Seric } 8864417Seric else 8874415Seric { 8884417Seric (void) setgid(ctladdr->q_gid); 889*40972Sbostic (void) initgroups(ctladdr->q_ruser? 890*40972Sbostic ctladdr->q_ruser: ctladdr->q_user, 891*40972Sbostic ctladdr->q_gid); 8924417Seric (void) setuid(ctladdr->q_uid); 8934415Seric } 8944215Seric } 8959370Seric 89615772Seric /* arrange for all the files to be closed */ 89736030Sbostic for (i = 3; i < DtableSize; i++) { 89836030Sbostic register int j; 89936030Sbostic if ((j = fcntl(i, F_GETFD, 0)) != -1) 90036030Sbostic (void)fcntl(i, F_SETFD, j|1); 90136030Sbostic } 9022774Seric 9036038Seric /* try to execute the mailer */ 90425026Seric execve(m->m_mailer, pvp, UserEnviron); 90515772Seric syserr("Cannot exec %s", m->m_mailer); 90624941Seric if (m == LocalMailer || errno == EIO || errno == EAGAIN || 90724941Seric errno == ENOMEM || errno == EPROCLIM) 90816902Seric _exit(EX_TEMPFAIL); 90916902Seric else 91016902Seric _exit(EX_UNAVAILABLE); 911294Seric } 912294Seric 9134709Seric /* 9144863Seric ** Set up return value. 9154709Seric */ 9164709Seric 9174709Seric (void) close(mpvect[0]); 9184709Seric mfile = fdopen(mpvect[1], "w"); 9194863Seric if (clever) 9204863Seric { 9214863Seric (void) close(rpvect[1]); 9224863Seric rfile = fdopen(rpvect[0], "r"); 9234863Seric } 924294Seric 9254863Seric *pmfile = mfile; 9264863Seric *prfile = rfile; 927294Seric 9284863Seric return (pid); 929294Seric } 930294Seric /* 931294Seric ** GIVERESPONSE -- Interpret an error response from a mailer 932294Seric ** 933294Seric ** Parameters: 934294Seric ** stat -- the status code from the mailer (high byte 935294Seric ** only; core dumps must have been taken care of 936294Seric ** already). 937294Seric ** m -- the mailer descriptor for this mailer. 938294Seric ** 939294Seric ** Returns: 9404082Seric ** none. 941294Seric ** 942294Seric ** Side Effects: 9431518Seric ** Errors may be incremented. 944294Seric ** ExitStat may be set. 945294Seric */ 946294Seric 94710105Seric giveresponse(stat, m, e) 948294Seric int stat; 9499370Seric register MAILER *m; 95010105Seric ENVELOPE *e; 951294Seric { 952294Seric register char *statmsg; 953294Seric extern char *SysExMsg[]; 954294Seric register int i; 95536788Sbostic extern int N_SysEx; 95636788Sbostic #ifdef NAMED_BIND 95736788Sbostic extern int h_errno; 95836788Sbostic #endif 95910105Seric char buf[MAXLINE]; 960294Seric 96112135Seric #ifdef lint 96212135Seric if (m == NULL) 96312135Seric return; 96412135Seric #endif lint 96512135Seric 9664315Seric /* 9674315Seric ** Compute status message from code. 9684315Seric */ 9694315Seric 970294Seric i = stat - EX__BASE; 9719370Seric if (stat == 0) 9729370Seric statmsg = "250 Sent"; 9739370Seric else if (i < 0 || i > N_SysEx) 9749370Seric { 9759370Seric (void) sprintf(buf, "554 unknown mailer error %d", stat); 9769370Seric stat = EX_UNAVAILABLE; 9779370Seric statmsg = buf; 9789370Seric } 97910105Seric else if (stat == EX_TEMPFAIL) 98010105Seric { 98110124Seric (void) strcpy(buf, SysExMsg[i]); 98236788Sbostic #ifdef NAMED_BIND 98325527Smiriam if (h_errno == TRY_AGAIN) 98410105Seric { 98515137Seric extern char *errstring(); 98615137Seric 98725527Smiriam statmsg = errstring(h_errno+MAX_ERRNO); 98821061Seric } 98921061Seric else 99036788Sbostic #endif 99121061Seric { 99225527Smiriam if (errno != 0) 99325527Smiriam { 99425527Smiriam extern char *errstring(); 99525527Smiriam 99625527Smiriam statmsg = errstring(errno); 99725527Smiriam } 99825527Smiriam else 99925527Smiriam { 100021061Seric #ifdef SMTP 100125527Smiriam extern char SmtpError[]; 100221061Seric 100325527Smiriam statmsg = SmtpError; 100421061Seric #else SMTP 100525527Smiriam statmsg = NULL; 100621061Seric #endif SMTP 100725527Smiriam } 100821061Seric } 100921061Seric if (statmsg != NULL && statmsg[0] != '\0') 101021061Seric { 101110124Seric (void) strcat(buf, ": "); 101221061Seric (void) strcat(buf, statmsg); 101310105Seric } 101410105Seric statmsg = buf; 101510105Seric } 1016294Seric else 101721061Seric { 1018294Seric statmsg = SysExMsg[i]; 101921061Seric } 10209370Seric 10219370Seric /* 10229370Seric ** Print the message as appropriate 10239370Seric */ 10249370Seric 102510105Seric if (stat == EX_OK || stat == EX_TEMPFAIL) 10268003Seric message(Arpa_Info, &statmsg[4]); 1027294Seric else 1028294Seric { 10291518Seric Errors++; 10309370Seric usrerr(statmsg); 1031294Seric } 1032294Seric 1033294Seric /* 1034294Seric ** Final cleanup. 1035294Seric ** Log a record of the transaction. Compute the new 1036294Seric ** ExitStat -- if we already had an error, stick with 1037294Seric ** that. 1038294Seric */ 1039294Seric 10407680Seric if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2)) 10418496Seric logdelivery(&statmsg[4]); 10427858Seric 10434621Seric if (stat != EX_TEMPFAIL) 10444621Seric setstat(stat); 104510105Seric if (stat != EX_OK) 104610105Seric { 104710105Seric if (e->e_message != NULL) 104810105Seric free(e->e_message); 104910105Seric e->e_message = newstr(&statmsg[4]); 105010105Seric } 105110124Seric errno = 0; 105236788Sbostic #ifdef NAMED_BIND 105325527Smiriam h_errno = 0; 105436788Sbostic #endif 1055294Seric } 1056294Seric /* 10578496Seric ** LOGDELIVERY -- log the delivery in the system log 10588496Seric ** 10598496Seric ** Parameters: 10608496Seric ** stat -- the message to print for the status 10618496Seric ** 10628496Seric ** Returns: 10638496Seric ** none 10648496Seric ** 10658496Seric ** Side Effects: 10668496Seric ** none 10678496Seric */ 10688496Seric 10698496Seric logdelivery(stat) 10708496Seric char *stat; 10718496Seric { 10728496Seric extern char *pintvl(); 10738496Seric 10748496Seric # ifdef LOG 10758496Seric syslog(LOG_INFO, "%s: to=%s, delay=%s, stat=%s", CurEnv->e_id, 10768496Seric CurEnv->e_to, pintvl(curtime() - CurEnv->e_ctime, TRUE), stat); 10778496Seric # endif LOG 10788496Seric } 10798496Seric /* 10806974Seric ** PUTFROMLINE -- output a UNIX-style from line (or whatever) 1081294Seric ** 10826974Seric ** This can be made an arbitrary message separator by changing $l 1083294Seric ** 108416150Seric ** One of the ugliest hacks seen by human eyes is contained herein: 108516150Seric ** UUCP wants those stupid "remote from <host>" lines. Why oh why 108616150Seric ** does a well-meaning programmer such as myself have to deal with 108716150Seric ** this kind of antique garbage???? 10886974Seric ** 1089294Seric ** Parameters: 10906974Seric ** fp -- the file to output to. 10916974Seric ** m -- the mailer describing this entry. 1092294Seric ** 1093294Seric ** Returns: 10946974Seric ** none 1095294Seric ** 1096294Seric ** Side Effects: 10976974Seric ** outputs some text to fp. 1098294Seric */ 1099294Seric 110010168Seric putfromline(fp, m) 11016974Seric register FILE *fp; 11026974Seric register MAILER *m; 1103294Seric { 110416150Seric char *template = "\001l\n"; 11056974Seric char buf[MAXLINE]; 1106294Seric 110710682Seric if (bitnset(M_NHDR, m->m_flags)) 11086974Seric return; 11094315Seric 11106974Seric # ifdef UGLYUUCP 111110682Seric if (bitnset(M_UGLYUUCP, m->m_flags)) 11124205Seric { 111312223Seric char *bang; 111412223Seric char xbuf[MAXLINE]; 11156041Seric 111616150Seric expand("\001g", buf, &buf[sizeof buf - 1], CurEnv); 111712223Seric bang = index(buf, '!'); 11186974Seric if (bang == NULL) 111912223Seric syserr("No ! in UUCP! (%s)", buf); 11205099Seric else 11219370Seric { 112212223Seric *bang++ = '\0'; 112316150Seric (void) sprintf(xbuf, "From %s \001d remote from %s\n", bang, buf); 112412223Seric template = xbuf; 11259370Seric } 11266974Seric } 11275179Seric # endif UGLYUUCP 112812223Seric expand(template, buf, &buf[sizeof buf - 1], CurEnv); 112910168Seric putline(buf, fp, m); 11305981Seric } 11315981Seric /* 11326974Seric ** PUTBODY -- put the body of a message. 11336974Seric ** 11346974Seric ** Parameters: 11356974Seric ** fp -- file to output onto. 113610168Seric ** m -- a mailer descriptor to control output format. 11379538Seric ** e -- the envelope to put out. 11386974Seric ** 11396974Seric ** Returns: 11406974Seric ** none. 11416974Seric ** 11426974Seric ** Side Effects: 11436974Seric ** The message is written onto fp. 11446974Seric */ 11456974Seric 114610168Seric putbody(fp, m, e) 11476974Seric FILE *fp; 11489370Seric MAILER *m; 11499538Seric register ENVELOPE *e; 11506974Seric { 115110168Seric char buf[MAXLINE]; 11526974Seric 11536974Seric /* 11546974Seric ** Output the body of the message 11556974Seric */ 11566974Seric 11579538Seric if (e->e_dfp == NULL) 11586974Seric { 11599538Seric if (e->e_df != NULL) 11609538Seric { 11619538Seric e->e_dfp = fopen(e->e_df, "r"); 11629538Seric if (e->e_dfp == NULL) 116340931Srick syserr("putbody: Cannot open %s for %s from %s", 116440931Srick e->e_df, e->e_to, e->e_from); 11659538Seric } 11669538Seric else 116710168Seric putline("<<< No Message Collected >>>", fp, m); 11689538Seric } 11699538Seric if (e->e_dfp != NULL) 11709538Seric { 11719538Seric rewind(e->e_dfp); 117210168Seric while (!ferror(fp) && fgets(buf, sizeof buf, e->e_dfp) != NULL) 117316875Seric { 117416875Seric if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) && 117516875Seric strncmp(buf, "From", 4) == 0) 117623102Seric (void) putc('>', fp); 117710168Seric putline(buf, fp, m); 117816875Seric } 11796974Seric 11809538Seric if (ferror(e->e_dfp)) 11816974Seric { 11826974Seric syserr("putbody: read error"); 11836974Seric ExitStat = EX_IOERR; 11846974Seric } 11856974Seric } 11866974Seric 11876974Seric (void) fflush(fp); 11886974Seric if (ferror(fp) && errno != EPIPE) 11896974Seric { 11906974Seric syserr("putbody: write error"); 11916974Seric ExitStat = EX_IOERR; 11926974Seric } 11936974Seric errno = 0; 11946974Seric } 11956974Seric /* 1196294Seric ** MAILFILE -- Send a message to a file. 1197294Seric ** 11984327Seric ** If the file has the setuid/setgid bits set, but NO execute 11994327Seric ** bits, sendmail will try to become the owner of that file 12004327Seric ** rather than the real user. Obviously, this only works if 12014327Seric ** sendmail runs as root. 12024327Seric ** 12039370Seric ** This could be done as a subordinate mailer, except that it 12049370Seric ** is used implicitly to save messages in ~/dead.letter. We 12059370Seric ** view this as being sufficiently important as to include it 12069370Seric ** here. For example, if the system is dying, we shouldn't have 12079370Seric ** to create another process plus some pipes to save the message. 12089370Seric ** 1209294Seric ** Parameters: 1210294Seric ** filename -- the name of the file to send to. 12114397Seric ** ctladdr -- the controlling address header -- includes 12124397Seric ** the userid/groupid to be when sending. 1213294Seric ** 1214294Seric ** Returns: 1215294Seric ** The exit code associated with the operation. 1216294Seric ** 1217294Seric ** Side Effects: 1218294Seric ** none. 1219294Seric */ 1220294Seric 12214397Seric mailfile(filename, ctladdr) 1222294Seric char *filename; 12234397Seric ADDRESS *ctladdr; 1224294Seric { 1225294Seric register FILE *f; 12264214Seric register int pid; 122740931Srick ENVELOPE *e = CurEnv; 1228294Seric 12294214Seric /* 12304214Seric ** Fork so we can change permissions here. 12314214Seric ** Note that we MUST use fork, not vfork, because of 12324214Seric ** the complications of calling subroutines, etc. 12334214Seric */ 12344067Seric 12354214Seric DOFORK(fork); 12364214Seric 12374214Seric if (pid < 0) 12384214Seric return (EX_OSERR); 12394214Seric else if (pid == 0) 12404214Seric { 12414214Seric /* child -- actually write to file */ 12424327Seric struct stat stb; 12434327Seric 12444215Seric (void) signal(SIGINT, SIG_DFL); 12454215Seric (void) signal(SIGHUP, SIG_DFL); 12464215Seric (void) signal(SIGTERM, SIG_DFL); 124723102Seric (void) umask(OldUmask); 12484327Seric if (stat(filename, &stb) < 0) 124911935Seric { 125011935Seric errno = 0; 12514431Seric stb.st_mode = 0666; 125211935Seric } 12534327Seric if (bitset(0111, stb.st_mode)) 12544327Seric exit(EX_CANTCREAT); 12554401Seric if (ctladdr == NULL) 125640931Srick ctladdr = &e->e_from; 125740931Srick /* we have to open the dfile BEFORE setuid */ 125840931Srick if (e->e_dfp == NULL && e->e_df != NULL) 125940931Srick { 126040931Srick e->e_dfp = fopen(e->e_df, "r"); 126140931Srick if (e->e_dfp == NULL) { 126240931Srick syserr("mailfile: Cannot open %s for %s from %s", 126340931Srick e->e_df, e->e_to, e->e_from); 126440931Srick } 126540931Srick } 126640931Srick 12674327Seric if (!bitset(S_ISGID, stb.st_mode) || setgid(stb.st_gid) < 0) 12684417Seric { 1269*40972Sbostic if (ctladdr->q_uid == 0) { 12704417Seric (void) setgid(DefGid); 1271*40972Sbostic (void) initgroups(DefUser, DefGid); 1272*40972Sbostic } else { 12734417Seric (void) setgid(ctladdr->q_gid); 1274*40972Sbostic (void) initgroups(ctladdr->q_ruser? 1275*40972Sbostic ctladdr->q_ruser: ctladdr->q_user, 1276*40972Sbostic ctladdr->q_gid); 1277*40972Sbostic } 12784417Seric } 12794327Seric if (!bitset(S_ISUID, stb.st_mode) || setuid(stb.st_uid) < 0) 12804417Seric { 12814417Seric if (ctladdr->q_uid == 0) 12824417Seric (void) setuid(DefUid); 12834417Seric else 12844417Seric (void) setuid(ctladdr->q_uid); 12854417Seric } 12866887Seric f = dfopen(filename, "a"); 12874214Seric if (f == NULL) 12884214Seric exit(EX_CANTCREAT); 12894214Seric 129010168Seric putfromline(f, ProgMailer); 129110168Seric (*CurEnv->e_puthdr)(f, ProgMailer, CurEnv); 129210168Seric putline("\n", f, ProgMailer); 129310168Seric (*CurEnv->e_putbody)(f, ProgMailer, CurEnv); 129410168Seric putline("\n", f, ProgMailer); 12954214Seric (void) fclose(f); 12964214Seric (void) fflush(stdout); 12974417Seric 12986887Seric /* reset ISUID & ISGID bits for paranoid systems */ 12994621Seric (void) chmod(filename, (int) stb.st_mode); 13004214Seric exit(EX_OK); 13014315Seric /*NOTREACHED*/ 13024214Seric } 13034214Seric else 13044214Seric { 13054214Seric /* parent -- wait for exit status */ 13069370Seric int st; 13074214Seric 13089370Seric st = waitfor(pid); 13099370Seric if ((st & 0377) != 0) 13109370Seric return (EX_UNAVAILABLE); 13119370Seric else 13129370Seric return ((st >> 8) & 0377); 131340931Srick /*NOTREACHED*/ 13144214Seric } 1315294Seric } 13164550Seric /* 13174550Seric ** SENDALL -- actually send all the messages. 13184550Seric ** 13194550Seric ** Parameters: 13207043Seric ** e -- the envelope to send. 132114874Seric ** mode -- the delivery mode to use. If SM_DEFAULT, use 132214874Seric ** the current SendMode. 13234550Seric ** 13244550Seric ** Returns: 13254550Seric ** none. 13264550Seric ** 13274550Seric ** Side Effects: 13284550Seric ** Scans the send lists and sends everything it finds. 13297043Seric ** Delivers any appropriate error messages. 13309275Seric ** If we are running in a non-interactive mode, takes the 13319275Seric ** appropriate action. 13324550Seric */ 13334550Seric 13349275Seric sendall(e, mode) 13357043Seric ENVELOPE *e; 13369275Seric char mode; 13374550Seric { 13385008Seric register ADDRESS *q; 13397779Seric bool oldverbose; 13409275Seric int pid; 134140931Srick FILE *lockfp, *queueup(); 13424550Seric 134314874Seric /* determine actual delivery mode */ 134414874Seric if (mode == SM_DEFAULT) 134514874Seric { 134624941Seric extern bool shouldqueue(); 134714874Seric 134824941Seric if (shouldqueue(e->e_msgpriority)) 134914874Seric mode = SM_QUEUE; 135014874Seric else 135114874Seric mode = SendMode; 135214874Seric } 135314874Seric 13548248Seric if (tTd(13, 1)) 13555032Seric { 13569275Seric printf("\nSENDALL: mode %c, sendqueue:\n", mode); 13577043Seric printaddr(e->e_sendqueue, TRUE); 13585032Seric } 13595008Seric 13607043Seric /* 13619275Seric ** Do any preprocessing necessary for the mode we are running. 13629370Seric ** Check to make sure the hop count is reasonable. 13639370Seric ** Delete sends to the sender in mailing lists. 13647043Seric */ 13657043Seric 13669370Seric CurEnv = e; 13679370Seric 13689370Seric if (e->e_hopcount > MAXHOP) 13699275Seric { 137040931Srick errno = 0; 137140931Srick syserr("sendall: too many hops %d (%d max): from %s, to %s", 137240931Srick e->e_hopcount, MAXHOP, e->e_from, e->e_to); 13739370Seric return; 13749370Seric } 13759275Seric 13769370Seric if (!MeToo) 13779370Seric { 137812611Seric extern ADDRESS *recipient(); 137912611Seric 13809370Seric e->e_from.q_flags |= QDONTSEND; 138112611Seric (void) recipient(&e->e_from, &e->e_sendqueue); 13829275Seric } 13839370Seric 13849370Seric # ifdef QUEUE 13859335Seric if ((mode == SM_QUEUE || mode == SM_FORK || 13869335Seric (mode != SM_VERIFY && SuperSafe)) && 13879335Seric !bitset(EF_INQUEUE, e->e_flags)) 138840931Srick lockfp = queueup(e, TRUE, mode == SM_QUEUE); 13899275Seric #endif QUEUE 13909275Seric 13917779Seric oldverbose = Verbose; 13929275Seric switch (mode) 13939275Seric { 13949275Seric case SM_VERIFY: 13957779Seric Verbose = TRUE; 13969275Seric break; 13979275Seric 13989275Seric case SM_QUEUE: 13999335Seric e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; 14009275Seric return; 14019275Seric 14029275Seric case SM_FORK: 14039538Seric if (e->e_xfp != NULL) 14049538Seric (void) fflush(e->e_xfp); 14059275Seric pid = fork(); 14069275Seric if (pid < 0) 14079275Seric { 14089275Seric mode = SM_DELIVER; 14099275Seric break; 14109275Seric } 14119275Seric else if (pid > 0) 14129293Seric { 14139293Seric /* be sure we leave the temp files to our child */ 14149335Seric e->e_id = e->e_df = NULL; 141540931Srick if (lockfp != NULL) 141640931Srick (void) fclose(lockfp); 14179275Seric return; 14189293Seric } 14199275Seric 14209275Seric /* double fork to avoid zombies */ 14219275Seric if (fork() > 0) 14229275Seric exit(EX_OK); 14239275Seric 14249293Seric /* be sure we are immune from the terminal */ 142510133Seric disconnect(FALSE); 14269293Seric 14279275Seric break; 14289275Seric } 14299275Seric 14309275Seric /* 14319275Seric ** Run through the list and send everything. 14329275Seric */ 14339275Seric 14347043Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 14354550Seric { 14369275Seric if (mode == SM_VERIFY) 14374550Seric { 14389293Seric e->e_to = q->q_paddr; 14395008Seric if (!bitset(QDONTSEND|QBADADDR, q->q_flags)) 14407052Seric message(Arpa_Info, "deliverable"); 14414550Seric } 14425008Seric else 14439370Seric (void) deliver(e, q); 14444550Seric } 14457779Seric Verbose = oldverbose; 14467043Seric 14477043Seric /* 14487043Seric ** Now run through and check for errors. 14497043Seric */ 14507043Seric 145140931Srick if (mode == SM_VERIFY) { 145240931Srick if (lockfp != NULL) 145340931Srick (void) fclose(lockfp); 14547043Seric return; 145540931Srick } 14567043Seric 14577043Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 14587043Seric { 14597043Seric register ADDRESS *qq; 14607043Seric 14618248Seric if (tTd(13, 3)) 14628248Seric { 14638248Seric printf("Checking "); 14648248Seric printaddr(q, FALSE); 14658248Seric } 14668248Seric 14679335Seric /* only send errors if the message failed */ 14689335Seric if (!bitset(QBADADDR, q->q_flags)) 14699335Seric continue; 14707043Seric 14717043Seric /* we have an address that failed -- find the parent */ 14727043Seric for (qq = q; qq != NULL; qq = qq->q_alias) 14737043Seric { 14747043Seric char obuf[MAXNAME + 6]; 14757043Seric extern char *aliaslookup(); 14767043Seric 14777043Seric /* we can only have owners for local addresses */ 147810682Seric if (!bitnset(M_LOCAL, qq->q_mailer->m_flags)) 14797043Seric continue; 14807043Seric 14817043Seric /* see if the owner list exists */ 14827043Seric (void) strcpy(obuf, "owner-"); 14837047Seric if (strncmp(qq->q_user, "owner-", 6) == 0) 14847047Seric (void) strcat(obuf, "owner"); 14857047Seric else 14867047Seric (void) strcat(obuf, qq->q_user); 14877043Seric if (aliaslookup(obuf) == NULL) 14887043Seric continue; 14897043Seric 14908248Seric if (tTd(13, 4)) 14918248Seric printf("Errors to %s\n", obuf); 14928248Seric 14937043Seric /* owner list exists -- add it to the error queue */ 14949615Seric sendtolist(obuf, (ADDRESS *) NULL, &e->e_errorqueue); 149516883Seric ErrorMode = EM_MAIL; 14967043Seric break; 14977043Seric } 14987043Seric 14997043Seric /* if we did not find an owner, send to the sender */ 15008426Seric if (qq == NULL && bitset(QBADADDR, q->q_flags)) 15019615Seric sendtolist(e->e_from.q_paddr, qq, &e->e_errorqueue); 15027043Seric } 15039275Seric 150440931Srick /* this removes the lock on the file */ 150540931Srick if (lockfp != NULL) 150640931Srick (void) fclose(lockfp); 150740931Srick 15089275Seric if (mode == SM_FORK) 15099275Seric finis(); 15104550Seric } 1511