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*36810Sbostic static char sccsid[] = "@(#)deliver.c 5.28 (Berkeley) 02/16/89"; 2133728Sbostic #endif /* not lint */ 2222701Sdist 2333931Sbostic #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 3744397Seric if (ctladdr == NULL) 3759370Seric ctladdr = &e->e_from; 37635651Seric #ifdef NAMED_BIND 37734022Sbostic _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ 37835651Seric #endif 37933931Sbostic #ifdef SMTP 38035651Seric if (clever) 38135651Seric { 38233931Sbostic rcode = EX_OK; 38335651Seric #ifdef NAMED_BIND 384*36810Sbostic if (host[0] && host[0] != '[') 38535651Seric { 386*36810Sbostic expand("\001w", buf, &buf[sizeof(buf) - 1], e); 38735651Seric Nmx = getmxrr(host, MxHosts, buf, &rcode); 38835651Seric } 38935651Seric else 39035651Seric #endif 39135651Seric { 39231952Sbostic Nmx = 1; 39331952Sbostic MxHosts[0] = host; 39435651Seric } 39535651Seric if (Nmx >= 0) 39635651Seric { 39734022Sbostic message(Arpa_Info, "Connecting to %s (%s)...", 39834022Sbostic MxHosts[0], m->m_name); 39934022Sbostic if ((rcode = smtpinit(m, pv)) == EX_OK) { 40036239Skarels register char *t = tobuf; 40136239Skarels register int i; 40236239Skarels 40334022Sbostic /* send the recipient list */ 40434022Sbostic tobuf[0] = '\0'; 40534022Sbostic for (to = tochain; to; to = to->q_tchain) { 40634022Sbostic e->e_to = to->q_paddr; 40734022Sbostic if ((i = smtprcpt(to, m)) != EX_OK) { 40834022Sbostic markfailure(e, to, i); 40934022Sbostic giveresponse(i, m, e); 41034022Sbostic } 41134022Sbostic else { 41234022Sbostic *t++ = ','; 41334022Sbostic for (p = to->q_paddr; *p; *t++ = *p++); 41434022Sbostic } 4159388Seric } 41634022Sbostic 41734022Sbostic /* now send the data */ 41834022Sbostic if (tobuf[0] == '\0') 41934022Sbostic e->e_to = NULL; 42033931Sbostic else { 42134022Sbostic e->e_to = tobuf + 1; 42234022Sbostic rcode = smtpdata(m, e); 4239388Seric } 4249388Seric 42534022Sbostic /* now close the connection */ 42634022Sbostic smtpquit(m); 4279370Seric } 4289370Seric } 4294863Seric } 4304863Seric else 43133931Sbostic #endif /* SMTP */ 43233935Sbostic { 43334022Sbostic message(Arpa_Info, "Connecting to %s (%s)...", host, m->m_name); 43410168Seric rcode = sendoff(e, m, pv, ctladdr); 43533935Sbostic } 43635651Seric #ifdef NAMED_BIND 43734022Sbostic _res.options |= RES_DEFNAMES | RES_DNSRCH; /* XXX */ 43835651Seric #endif 4393233Seric 4404621Seric /* 4419388Seric ** Do final status disposal. 4429388Seric ** We check for something in tobuf for the SMTP case. 4439388Seric ** If we got a temporary failure, arrange to queue the 4449388Seric ** addressees. 4454621Seric */ 4464621Seric 4479388Seric if (tobuf[0] != '\0') 44810105Seric giveresponse(rcode, m, e); 4499388Seric if (rcode != EX_OK) 4505032Seric for (to = tochain; to != NULL; to = to->q_tchain) 45110092Seric markfailure(e, to, rcode); 4524621Seric 4534488Seric errno = 0; 4549370Seric define('g', (char *) NULL, e); 4558003Seric return (rcode); 4563233Seric } 4573233Seric /* 45810092Seric ** MARKFAILURE -- mark a failure on a specific address. 45910092Seric ** 46010092Seric ** Parameters: 46110092Seric ** e -- the envelope we are sending. 46210092Seric ** q -- the address to mark. 46310092Seric ** rcode -- the code signifying the particular failure. 46410092Seric ** 46510092Seric ** Returns: 46610092Seric ** none. 46710092Seric ** 46810092Seric ** Side Effects: 46910092Seric ** marks the address (and possibly the envelope) with the 47010092Seric ** failure so that an error will be returned or 47110092Seric ** the message will be queued, as appropriate. 47210092Seric */ 47310092Seric 47410092Seric markfailure(e, q, rcode) 47510092Seric register ENVELOPE *e; 47610092Seric register ADDRESS *q; 47710092Seric int rcode; 47810092Seric { 47910092Seric if (rcode == EX_OK) 48010092Seric return; 48110092Seric else if (rcode != EX_TEMPFAIL) 48210092Seric q->q_flags |= QBADADDR; 48310092Seric else if (curtime() > e->e_ctime + TimeOut) 48410092Seric { 48510092Seric extern char *pintvl(); 48610105Seric char buf[MAXLINE]; 48710092Seric 48810092Seric if (!bitset(EF_TIMEOUT, e->e_flags)) 48910105Seric { 49010105Seric (void) sprintf(buf, "Cannot send message for %s", 49110092Seric pintvl(TimeOut, FALSE)); 49210105Seric if (e->e_message != NULL) 49310105Seric free(e->e_message); 49410105Seric e->e_message = newstr(buf); 49510105Seric message(Arpa_Info, buf); 49610105Seric } 49710092Seric q->q_flags |= QBADADDR; 49810092Seric e->e_flags |= EF_TIMEOUT; 49910092Seric } 50010092Seric else 50110092Seric q->q_flags |= QQUEUEUP; 50210092Seric } 50310092Seric /* 5044214Seric ** DOFORK -- do a fork, retrying a couple of times on failure. 5054214Seric ** 5064214Seric ** This MUST be a macro, since after a vfork we are running 5074214Seric ** two processes on the same stack!!! 5084214Seric ** 5094214Seric ** Parameters: 5104214Seric ** none. 5114214Seric ** 5124214Seric ** Returns: 5134214Seric ** From a macro??? You've got to be kidding! 5144214Seric ** 5154214Seric ** Side Effects: 5164214Seric ** Modifies the ==> LOCAL <== variable 'pid', leaving: 5174214Seric ** pid of child in parent, zero in child. 5184214Seric ** -1 on unrecoverable error. 5194214Seric ** 5204214Seric ** Notes: 5214214Seric ** I'm awfully sorry this looks so awful. That's 5224214Seric ** vfork for you..... 5234214Seric */ 5244214Seric 5254214Seric # define NFORKTRIES 5 5269148Seric # ifdef VMUNIX 5274214Seric # define XFORK vfork 5289148Seric # else VMUNIX 5294214Seric # define XFORK fork 5309148Seric # endif VMUNIX 5314214Seric 5324214Seric # define DOFORK(fORKfN) \ 5334214Seric {\ 5344214Seric register int i;\ 5354214Seric \ 53623504Seric for (i = NFORKTRIES; --i >= 0; )\ 5374214Seric {\ 5384214Seric pid = fORKfN();\ 5394214Seric if (pid >= 0)\ 5404214Seric break;\ 54123504Seric if (i > 0)\ 54225617Seric sleep((unsigned) NFORKTRIES - i);\ 5434214Seric }\ 5444214Seric } 5454214Seric /* 5464637Seric ** DOFORK -- simple fork interface to DOFORK. 5474637Seric ** 5484637Seric ** Parameters: 5494637Seric ** none. 5504637Seric ** 5514637Seric ** Returns: 5524637Seric ** pid of child in parent. 5534637Seric ** zero in child. 5544637Seric ** -1 on error. 5554637Seric ** 5564637Seric ** Side Effects: 5574637Seric ** returns twice, once in parent and once in child. 5584637Seric */ 5594637Seric 5604637Seric dofork() 5614637Seric { 5624637Seric register int pid; 5634637Seric 5644637Seric DOFORK(fork); 5654637Seric return (pid); 5664637Seric } 5674637Seric /* 5683233Seric ** SENDOFF -- send off call to mailer & collect response. 5693233Seric ** 5703233Seric ** Parameters: 5719370Seric ** e -- the envelope to mail. 5723233Seric ** m -- mailer descriptor. 5733233Seric ** pvp -- parameter vector to send to it. 5744397Seric ** ctladdr -- an address pointer controlling the 5754397Seric ** user/groupid etc. of the mailer. 5763233Seric ** 5773233Seric ** Returns: 5783233Seric ** exit status of mailer. 5793233Seric ** 5803233Seric ** Side Effects: 5813233Seric ** none. 5823233Seric */ 58334022Sbostic static 58410168Seric sendoff(e, m, pvp, ctladdr) 5859370Seric register ENVELOPE *e; 5869370Seric MAILER *m; 5873233Seric char **pvp; 5884397Seric ADDRESS *ctladdr; 5893233Seric { 5904863Seric auto FILE *mfile; 5914863Seric auto FILE *rfile; 5923233Seric register int i; 5933233Seric int pid; 5944863Seric 5954863Seric /* 5964863Seric ** Create connection to mailer. 5974863Seric */ 5984863Seric 5994863Seric pid = openmailer(m, pvp, ctladdr, FALSE, &mfile, &rfile); 6004863Seric if (pid < 0) 6014863Seric return (-1); 6024863Seric 6034863Seric /* 6044863Seric ** Format and send message. 6054863Seric */ 6064863Seric 60710168Seric putfromline(mfile, m); 60810168Seric (*e->e_puthdr)(mfile, m, e); 60910168Seric putline("\n", mfile, m); 61010168Seric (*e->e_putbody)(mfile, m, e); 6114863Seric (void) fclose(mfile); 6124863Seric 6134863Seric i = endmailer(pid, pvp[0]); 6145981Seric 6155981Seric /* arrange a return receipt if requested */ 61610682Seric if (e->e_receiptto != NULL && bitnset(M_LOCAL, m->m_flags)) 6175981Seric { 6189370Seric e->e_flags |= EF_SENDRECEIPT; 6195981Seric /* do we want to send back more info? */ 6205981Seric } 6215981Seric 6224863Seric return (i); 6234863Seric } 6244863Seric /* 6254863Seric ** ENDMAILER -- Wait for mailer to terminate. 6264863Seric ** 6274863Seric ** We should never get fatal errors (e.g., segmentation 6284863Seric ** violation), so we report those specially. For other 6294863Seric ** errors, we choose a status message (into statmsg), 6304863Seric ** and if it represents an error, we print it. 6314863Seric ** 6324863Seric ** Parameters: 6334863Seric ** pid -- pid of mailer. 6344863Seric ** name -- name of mailer (for error messages). 6354863Seric ** 6364863Seric ** Returns: 6374863Seric ** exit code of mailer. 6384863Seric ** 6394863Seric ** Side Effects: 6404863Seric ** none. 6414863Seric */ 6424863Seric 6434863Seric endmailer(pid, name) 6444863Seric int pid; 6454863Seric char *name; 6464863Seric { 6479370Seric int st; 6484863Seric 6496038Seric /* in the IPC case there is nothing to wait for */ 6506038Seric if (pid == 0) 6516038Seric return (EX_OK); 6526038Seric 6536038Seric /* wait for the mailer process to die and collect status */ 6549370Seric st = waitfor(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 ** pmfile -- pointer to mfile (to mailer) connection. 6824863Seric ** prfile -- pointer to rfile (from mailer) connection. 6834863Seric ** 6844863Seric ** Returns: 6856038Seric ** pid of mailer ( > 0 ). 6864863Seric ** -1 on error. 6876038Seric ** zero on an IPC connection. 6884863Seric ** 6894863Seric ** Side Effects: 6904863Seric ** creates a mailer in a subprocess. 6914863Seric */ 6924863Seric 6934863Seric openmailer(m, pvp, ctladdr, clever, pmfile, prfile) 6949370Seric MAILER *m; 6954863Seric char **pvp; 6964863Seric ADDRESS *ctladdr; 6974863Seric bool clever; 6984863Seric FILE **pmfile; 6994863Seric FILE **prfile; 7004863Seric { 7014863Seric int pid; 7024709Seric int mpvect[2]; 7034863Seric int rpvect[2]; 7043233Seric FILE *mfile; 7054863Seric FILE *rfile; 7063233Seric extern FILE *fdopen(); 7073233Seric 7087672Seric if (tTd(11, 1)) 709294Seric { 7108178Seric printf("openmailer:"); 7113233Seric printav(pvp); 712294Seric } 7134488Seric errno = 0; 7143233Seric 71525050Seric CurHostName = m->m_mailer; 71625050Seric 7176038Seric /* 7186038Seric ** Deal with the special case of mail handled through an IPC 7196038Seric ** connection. 7206038Seric ** In this case we don't actually fork. We must be 7216038Seric ** running SMTP for this to work. We will return a 7226038Seric ** zero pid to indicate that we are running IPC. 72311160Seric ** We also handle a debug version that just talks to stdin/out. 7246038Seric */ 7256038Seric 72611160Seric /* check for Local Person Communication -- not for mortals!!! */ 72711160Seric if (strcmp(m->m_mailer, "[LPC]") == 0) 72811160Seric { 72911160Seric *pmfile = stdout; 73011160Seric *prfile = stdin; 73111160Seric return (0); 73211160Seric } 73311160Seric 7346038Seric if (strcmp(m->m_mailer, "[IPC]") == 0) 7356038Seric { 73624941Seric #ifdef HOSTINFO 73724941Seric register STAB *st; 73824941Seric extern STAB *stab(); 73924941Seric #endif HOSTINFO 7409370Seric #ifdef DAEMON 74129433Sbloom register int i, j; 7427285Seric register u_short port; 7436038Seric 74425050Seric CurHostName = pvp[1]; 7456038Seric if (!clever) 7466038Seric syserr("non-clever IPC"); 7476632Seric if (pvp[2] != NULL) 7487285Seric port = atoi(pvp[2]); 7496632Seric else 7507285Seric port = 0; 75129865Seric for (j = 0; j < Nmx; j++) 75229433Sbloom { 75329865Seric CurHostName = MxHosts[j]; 75424941Seric #ifdef HOSTINFO 75524941Seric /* see if we have already determined that this host is fried */ 75629865Seric st = stab(MxHosts[j], ST_HOST, ST_FIND); 75734022Sbostic if (st == NULL || st->s_host.ho_exitstat == EX_OK) { 75834022Sbostic if (j > 1) 75934022Sbostic message(Arpa_Info, 76034022Sbostic "Connecting to %s (%s)...", 76134022Sbostic MxHosts[j], m->m_name); 76229865Seric i = makeconnection(MxHosts[j], port, pmfile, prfile); 76334022Sbostic } 76429433Sbloom else 76529433Sbloom { 76629433Sbloom i = st->s_host.ho_exitstat; 76729433Sbloom errno = st->s_host.ho_errno; 76829433Sbloom } 76924941Seric #else HOSTINFO 77029865Seric i = makeconnection(MxHosts[j], port, pmfile, prfile); 77124941Seric #endif HOSTINFO 77229433Sbloom if (i != EX_OK) 77329433Sbloom { 77424941Seric #ifdef HOSTINFO 77529433Sbloom /* enter status of this host */ 77629433Sbloom if (st == NULL) 77729865Seric st = stab(MxHosts[j], ST_HOST, ST_ENTER); 77829433Sbloom st->s_host.ho_exitstat = i; 77929433Sbloom st->s_host.ho_errno = errno; 78024941Seric #endif HOSTINFO 78129433Sbloom ExitStat = i; 78229433Sbloom continue; 78329433Sbloom } 78429433Sbloom else 78529433Sbloom return (0); 7866047Seric } 78729433Sbloom return (-1); 7889370Seric #else DAEMON 7899370Seric syserr("openmailer: no IPC"); 7909370Seric return (-1); 7919370Seric #endif DAEMON 7926038Seric } 7936038Seric 7942898Seric /* create a pipe to shove the mail through */ 7954709Seric if (pipe(mpvect) < 0) 796294Seric { 7979370Seric syserr("openmailer: pipe (to mailer)"); 798294Seric return (-1); 799294Seric } 8004863Seric 8019370Seric #ifdef SMTP 8024863Seric /* if this mailer speaks smtp, create a return pipe */ 8034863Seric if (clever && pipe(rpvect) < 0) 8044863Seric { 8059370Seric syserr("openmailer: pipe (from mailer)"); 8064863Seric (void) close(mpvect[0]); 8074863Seric (void) close(mpvect[1]); 8084863Seric return (-1); 8094863Seric } 8109370Seric #endif SMTP 8114863Seric 8126038Seric /* 8136038Seric ** Actually fork the mailer process. 8146038Seric ** DOFORK is clever about retrying. 81526434Seric ** 81626434Seric ** Dispose of SIGCHLD signal catchers that may be laying 81726434Seric ** around so that endmail will get it. 8186038Seric */ 8196038Seric 8209538Seric if (CurEnv->e_xfp != NULL) 8219538Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 8229370Seric (void) fflush(stdout); 82326434Seric # ifdef SIGCHLD 82426434Seric (void) signal(SIGCHLD, SIG_DFL); 82526434Seric # endif SIGCHLD 8264214Seric DOFORK(XFORK); 8274327Seric /* pid is set by DOFORK */ 828294Seric if (pid < 0) 829294Seric { 8306038Seric /* failure */ 8319370Seric syserr("openmailer: cannot fork"); 8324709Seric (void) close(mpvect[0]); 8334709Seric (void) close(mpvect[1]); 8349370Seric #ifdef SMTP 8354863Seric if (clever) 8364863Seric { 8374863Seric (void) close(rpvect[0]); 8384863Seric (void) close(rpvect[1]); 8394863Seric } 8409370Seric #endif SMTP 841294Seric return (-1); 842294Seric } 843294Seric else if (pid == 0) 844294Seric { 84515772Seric int i; 84624941Seric extern int DtableSize; 84715772Seric 848294Seric /* child -- set up input & exec mailer */ 8491621Seric /* make diagnostic output be standard output */ 8504477Seric (void) signal(SIGINT, SIG_IGN); 8514477Seric (void) signal(SIGHUP, SIG_IGN); 8524215Seric (void) signal(SIGTERM, SIG_DFL); 8534709Seric 8544709Seric /* arrange to filter standard & diag output of command */ 8554863Seric if (clever) 8564709Seric { 8574863Seric (void) close(rpvect[0]); 8584709Seric (void) close(1); 8594863Seric (void) dup(rpvect[1]); 8604863Seric (void) close(rpvect[1]); 8614863Seric } 8629275Seric else if (OpMode == MD_SMTP || HoldErrs) 8634863Seric { 8649370Seric /* put mailer output in transcript */ 8654863Seric (void) close(1); 8669538Seric (void) dup(fileno(CurEnv->e_xfp)); 8674709Seric } 8684082Seric (void) close(2); 8694082Seric (void) dup(1); 8704709Seric 8714709Seric /* arrange to get standard input */ 8724709Seric (void) close(mpvect[1]); 8734082Seric (void) close(0); 8744709Seric if (dup(mpvect[0]) < 0) 875294Seric { 8762898Seric syserr("Cannot dup to zero!"); 8772898Seric _exit(EX_OSERR); 878294Seric } 8794709Seric (void) close(mpvect[0]); 88010682Seric if (!bitnset(M_RESTR, m->m_flags)) 8814215Seric { 88216883Seric if (ctladdr == NULL || ctladdr->q_uid == 0) 8834417Seric { 8844417Seric (void) setgid(DefGid); 8854417Seric (void) setuid(DefUid); 8864417Seric } 8874417Seric else 8884415Seric { 8894417Seric (void) setgid(ctladdr->q_gid); 8904417Seric (void) setuid(ctladdr->q_uid); 8914415Seric } 8924215Seric } 8939370Seric 89415772Seric /* arrange for all the files to be closed */ 89536030Sbostic for (i = 3; i < DtableSize; i++) { 89636030Sbostic register int j; 89736030Sbostic if ((j = fcntl(i, F_GETFD, 0)) != -1) 89836030Sbostic (void)fcntl(i, F_SETFD, j|1); 89936030Sbostic } 9002774Seric 9016038Seric /* try to execute the mailer */ 90225026Seric execve(m->m_mailer, pvp, UserEnviron); 90315772Seric syserr("Cannot exec %s", m->m_mailer); 90424941Seric if (m == LocalMailer || errno == EIO || errno == EAGAIN || 90524941Seric errno == ENOMEM || errno == EPROCLIM) 90616902Seric _exit(EX_TEMPFAIL); 90716902Seric else 90816902Seric _exit(EX_UNAVAILABLE); 909294Seric } 910294Seric 9114709Seric /* 9124863Seric ** Set up return value. 9134709Seric */ 9144709Seric 9154709Seric (void) close(mpvect[0]); 9164709Seric mfile = fdopen(mpvect[1], "w"); 9174863Seric if (clever) 9184863Seric { 9194863Seric (void) close(rpvect[1]); 9204863Seric rfile = fdopen(rpvect[0], "r"); 9214863Seric } 922294Seric 9234863Seric *pmfile = mfile; 9244863Seric *prfile = rfile; 925294Seric 9264863Seric return (pid); 927294Seric } 928294Seric /* 929294Seric ** GIVERESPONSE -- Interpret an error response from a mailer 930294Seric ** 931294Seric ** Parameters: 932294Seric ** stat -- the status code from the mailer (high byte 933294Seric ** only; core dumps must have been taken care of 934294Seric ** already). 935294Seric ** m -- the mailer descriptor for this mailer. 936294Seric ** 937294Seric ** Returns: 9384082Seric ** none. 939294Seric ** 940294Seric ** Side Effects: 9411518Seric ** Errors may be incremented. 942294Seric ** ExitStat may be set. 943294Seric */ 944294Seric 94510105Seric giveresponse(stat, m, e) 946294Seric int stat; 9479370Seric register MAILER *m; 94810105Seric ENVELOPE *e; 949294Seric { 950294Seric register char *statmsg; 951294Seric extern char *SysExMsg[]; 952294Seric register int i; 95336788Sbostic extern int N_SysEx; 95436788Sbostic #ifdef NAMED_BIND 95536788Sbostic extern int h_errno; 95636788Sbostic #endif 95710105Seric char buf[MAXLINE]; 958294Seric 95912135Seric #ifdef lint 96012135Seric if (m == NULL) 96112135Seric return; 96212135Seric #endif lint 96312135Seric 9644315Seric /* 9654315Seric ** Compute status message from code. 9664315Seric */ 9674315Seric 968294Seric i = stat - EX__BASE; 9699370Seric if (stat == 0) 9709370Seric statmsg = "250 Sent"; 9719370Seric else if (i < 0 || i > N_SysEx) 9729370Seric { 9739370Seric (void) sprintf(buf, "554 unknown mailer error %d", stat); 9749370Seric stat = EX_UNAVAILABLE; 9759370Seric statmsg = buf; 9769370Seric } 97710105Seric else if (stat == EX_TEMPFAIL) 97810105Seric { 97910124Seric (void) strcpy(buf, SysExMsg[i]); 98036788Sbostic #ifdef NAMED_BIND 98125527Smiriam if (h_errno == TRY_AGAIN) 98210105Seric { 98315137Seric extern char *errstring(); 98415137Seric 98525527Smiriam statmsg = errstring(h_errno+MAX_ERRNO); 98621061Seric } 98721061Seric else 98836788Sbostic #endif 98921061Seric { 99025527Smiriam if (errno != 0) 99125527Smiriam { 99225527Smiriam extern char *errstring(); 99325527Smiriam 99425527Smiriam statmsg = errstring(errno); 99525527Smiriam } 99625527Smiriam else 99725527Smiriam { 99821061Seric #ifdef SMTP 99925527Smiriam extern char SmtpError[]; 100021061Seric 100125527Smiriam statmsg = SmtpError; 100221061Seric #else SMTP 100325527Smiriam statmsg = NULL; 100421061Seric #endif SMTP 100525527Smiriam } 100621061Seric } 100721061Seric if (statmsg != NULL && statmsg[0] != '\0') 100821061Seric { 100910124Seric (void) strcat(buf, ": "); 101021061Seric (void) strcat(buf, statmsg); 101110105Seric } 101210105Seric statmsg = buf; 101310105Seric } 1014294Seric else 101521061Seric { 1016294Seric statmsg = SysExMsg[i]; 101721061Seric } 10189370Seric 10199370Seric /* 10209370Seric ** Print the message as appropriate 10219370Seric */ 10229370Seric 102310105Seric if (stat == EX_OK || stat == EX_TEMPFAIL) 10248003Seric message(Arpa_Info, &statmsg[4]); 1025294Seric else 1026294Seric { 10271518Seric Errors++; 10289370Seric usrerr(statmsg); 1029294Seric } 1030294Seric 1031294Seric /* 1032294Seric ** Final cleanup. 1033294Seric ** Log a record of the transaction. Compute the new 1034294Seric ** ExitStat -- if we already had an error, stick with 1035294Seric ** that. 1036294Seric */ 1037294Seric 10387680Seric if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2)) 10398496Seric logdelivery(&statmsg[4]); 10407858Seric 10414621Seric if (stat != EX_TEMPFAIL) 10424621Seric setstat(stat); 104310105Seric if (stat != EX_OK) 104410105Seric { 104510105Seric if (e->e_message != NULL) 104610105Seric free(e->e_message); 104710105Seric e->e_message = newstr(&statmsg[4]); 104810105Seric } 104910124Seric errno = 0; 105036788Sbostic #ifdef NAMED_BIND 105125527Smiriam h_errno = 0; 105236788Sbostic #endif 1053294Seric } 1054294Seric /* 10558496Seric ** LOGDELIVERY -- log the delivery in the system log 10568496Seric ** 10578496Seric ** Parameters: 10588496Seric ** stat -- the message to print for the status 10598496Seric ** 10608496Seric ** Returns: 10618496Seric ** none 10628496Seric ** 10638496Seric ** Side Effects: 10648496Seric ** none 10658496Seric */ 10668496Seric 10678496Seric logdelivery(stat) 10688496Seric char *stat; 10698496Seric { 10708496Seric extern char *pintvl(); 10718496Seric 10728496Seric # ifdef LOG 10738496Seric syslog(LOG_INFO, "%s: to=%s, delay=%s, stat=%s", CurEnv->e_id, 10748496Seric CurEnv->e_to, pintvl(curtime() - CurEnv->e_ctime, TRUE), stat); 10758496Seric # endif LOG 10768496Seric } 10778496Seric /* 10786974Seric ** PUTFROMLINE -- output a UNIX-style from line (or whatever) 1079294Seric ** 10806974Seric ** This can be made an arbitrary message separator by changing $l 1081294Seric ** 108216150Seric ** One of the ugliest hacks seen by human eyes is contained herein: 108316150Seric ** UUCP wants those stupid "remote from <host>" lines. Why oh why 108416150Seric ** does a well-meaning programmer such as myself have to deal with 108516150Seric ** this kind of antique garbage???? 10866974Seric ** 1087294Seric ** Parameters: 10886974Seric ** fp -- the file to output to. 10896974Seric ** m -- the mailer describing this entry. 1090294Seric ** 1091294Seric ** Returns: 10926974Seric ** none 1093294Seric ** 1094294Seric ** Side Effects: 10956974Seric ** outputs some text to fp. 1096294Seric */ 1097294Seric 109810168Seric putfromline(fp, m) 10996974Seric register FILE *fp; 11006974Seric register MAILER *m; 1101294Seric { 110216150Seric char *template = "\001l\n"; 11036974Seric char buf[MAXLINE]; 1104294Seric 110510682Seric if (bitnset(M_NHDR, m->m_flags)) 11066974Seric return; 11074315Seric 11086974Seric # ifdef UGLYUUCP 110910682Seric if (bitnset(M_UGLYUUCP, m->m_flags)) 11104205Seric { 111112223Seric char *bang; 111212223Seric char xbuf[MAXLINE]; 11136041Seric 111416150Seric expand("\001g", buf, &buf[sizeof buf - 1], CurEnv); 111512223Seric bang = index(buf, '!'); 11166974Seric if (bang == NULL) 111712223Seric syserr("No ! in UUCP! (%s)", buf); 11185099Seric else 11199370Seric { 112012223Seric *bang++ = '\0'; 112116150Seric (void) sprintf(xbuf, "From %s \001d remote from %s\n", bang, buf); 112212223Seric template = xbuf; 11239370Seric } 11246974Seric } 11255179Seric # endif UGLYUUCP 112612223Seric expand(template, buf, &buf[sizeof buf - 1], CurEnv); 112710168Seric putline(buf, fp, m); 11285981Seric } 11295981Seric /* 11306974Seric ** PUTBODY -- put the body of a message. 11316974Seric ** 11326974Seric ** Parameters: 11336974Seric ** fp -- file to output onto. 113410168Seric ** m -- a mailer descriptor to control output format. 11359538Seric ** e -- the envelope to put out. 11366974Seric ** 11376974Seric ** Returns: 11386974Seric ** none. 11396974Seric ** 11406974Seric ** Side Effects: 11416974Seric ** The message is written onto fp. 11426974Seric */ 11436974Seric 114410168Seric putbody(fp, m, e) 11456974Seric FILE *fp; 11469370Seric MAILER *m; 11479538Seric register ENVELOPE *e; 11486974Seric { 114910168Seric char buf[MAXLINE]; 11506974Seric 11516974Seric /* 11526974Seric ** Output the body of the message 11536974Seric */ 11546974Seric 11559538Seric if (e->e_dfp == NULL) 11566974Seric { 11579538Seric if (e->e_df != NULL) 11589538Seric { 11599538Seric e->e_dfp = fopen(e->e_df, "r"); 11609538Seric if (e->e_dfp == NULL) 11619538Seric syserr("Cannot open %s", e->e_df); 11629538Seric } 11639538Seric else 116410168Seric putline("<<< No Message Collected >>>", fp, m); 11659538Seric } 11669538Seric if (e->e_dfp != NULL) 11679538Seric { 11689538Seric rewind(e->e_dfp); 116910168Seric while (!ferror(fp) && fgets(buf, sizeof buf, e->e_dfp) != NULL) 117016875Seric { 117116875Seric if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) && 117216875Seric strncmp(buf, "From", 4) == 0) 117323102Seric (void) putc('>', fp); 117410168Seric putline(buf, fp, m); 117516875Seric } 11766974Seric 11779538Seric if (ferror(e->e_dfp)) 11786974Seric { 11796974Seric syserr("putbody: read error"); 11806974Seric ExitStat = EX_IOERR; 11816974Seric } 11826974Seric } 11836974Seric 11846974Seric (void) fflush(fp); 11856974Seric if (ferror(fp) && errno != EPIPE) 11866974Seric { 11876974Seric syserr("putbody: write error"); 11886974Seric ExitStat = EX_IOERR; 11896974Seric } 11906974Seric errno = 0; 11916974Seric } 11926974Seric /* 1193294Seric ** MAILFILE -- Send a message to a file. 1194294Seric ** 11954327Seric ** If the file has the setuid/setgid bits set, but NO execute 11964327Seric ** bits, sendmail will try to become the owner of that file 11974327Seric ** rather than the real user. Obviously, this only works if 11984327Seric ** sendmail runs as root. 11994327Seric ** 12009370Seric ** This could be done as a subordinate mailer, except that it 12019370Seric ** is used implicitly to save messages in ~/dead.letter. We 12029370Seric ** view this as being sufficiently important as to include it 12039370Seric ** here. For example, if the system is dying, we shouldn't have 12049370Seric ** to create another process plus some pipes to save the message. 12059370Seric ** 1206294Seric ** Parameters: 1207294Seric ** filename -- the name of the file to send to. 12084397Seric ** ctladdr -- the controlling address header -- includes 12094397Seric ** the userid/groupid to be when sending. 1210294Seric ** 1211294Seric ** Returns: 1212294Seric ** The exit code associated with the operation. 1213294Seric ** 1214294Seric ** Side Effects: 1215294Seric ** none. 1216294Seric */ 1217294Seric 12184397Seric mailfile(filename, ctladdr) 1219294Seric char *filename; 12204397Seric ADDRESS *ctladdr; 1221294Seric { 1222294Seric register FILE *f; 12234214Seric register int pid; 1224294Seric 12254214Seric /* 12264214Seric ** Fork so we can change permissions here. 12274214Seric ** Note that we MUST use fork, not vfork, because of 12284214Seric ** the complications of calling subroutines, etc. 12294214Seric */ 12304067Seric 12314214Seric DOFORK(fork); 12324214Seric 12334214Seric if (pid < 0) 12344214Seric return (EX_OSERR); 12354214Seric else if (pid == 0) 12364214Seric { 12374214Seric /* child -- actually write to file */ 12384327Seric struct stat stb; 12394327Seric 12404215Seric (void) signal(SIGINT, SIG_DFL); 12414215Seric (void) signal(SIGHUP, SIG_DFL); 12424215Seric (void) signal(SIGTERM, SIG_DFL); 124323102Seric (void) umask(OldUmask); 12444327Seric if (stat(filename, &stb) < 0) 124511935Seric { 124611935Seric errno = 0; 12474431Seric stb.st_mode = 0666; 124811935Seric } 12494327Seric if (bitset(0111, stb.st_mode)) 12504327Seric exit(EX_CANTCREAT); 12514401Seric if (ctladdr == NULL) 12526900Seric ctladdr = &CurEnv->e_from; 12534327Seric if (!bitset(S_ISGID, stb.st_mode) || setgid(stb.st_gid) < 0) 12544417Seric { 12554417Seric if (ctladdr->q_uid == 0) 12564417Seric (void) setgid(DefGid); 12574417Seric else 12584417Seric (void) setgid(ctladdr->q_gid); 12594417Seric } 12604327Seric if (!bitset(S_ISUID, stb.st_mode) || setuid(stb.st_uid) < 0) 12614417Seric { 12624417Seric if (ctladdr->q_uid == 0) 12634417Seric (void) setuid(DefUid); 12644417Seric else 12654417Seric (void) setuid(ctladdr->q_uid); 12664417Seric } 12676887Seric f = dfopen(filename, "a"); 12684214Seric if (f == NULL) 12694214Seric exit(EX_CANTCREAT); 12704214Seric 127110168Seric putfromline(f, ProgMailer); 127210168Seric (*CurEnv->e_puthdr)(f, ProgMailer, CurEnv); 127310168Seric putline("\n", f, ProgMailer); 127410168Seric (*CurEnv->e_putbody)(f, ProgMailer, CurEnv); 127510168Seric putline("\n", f, ProgMailer); 12764214Seric (void) fclose(f); 12774214Seric (void) fflush(stdout); 12784417Seric 12796887Seric /* reset ISUID & ISGID bits for paranoid systems */ 12804621Seric (void) chmod(filename, (int) stb.st_mode); 12814214Seric exit(EX_OK); 12824315Seric /*NOTREACHED*/ 12834214Seric } 12844214Seric else 12854214Seric { 12864214Seric /* parent -- wait for exit status */ 12879370Seric int st; 12884214Seric 12899370Seric st = waitfor(pid); 12909370Seric if ((st & 0377) != 0) 12919370Seric return (EX_UNAVAILABLE); 12929370Seric else 12939370Seric return ((st >> 8) & 0377); 12944214Seric } 1295294Seric } 12964550Seric /* 12974550Seric ** SENDALL -- actually send all the messages. 12984550Seric ** 12994550Seric ** Parameters: 13007043Seric ** e -- the envelope to send. 130114874Seric ** mode -- the delivery mode to use. If SM_DEFAULT, use 130214874Seric ** the current SendMode. 13034550Seric ** 13044550Seric ** Returns: 13054550Seric ** none. 13064550Seric ** 13074550Seric ** Side Effects: 13084550Seric ** Scans the send lists and sends everything it finds. 13097043Seric ** Delivers any appropriate error messages. 13109275Seric ** If we are running in a non-interactive mode, takes the 13119275Seric ** appropriate action. 13124550Seric */ 13134550Seric 13149275Seric sendall(e, mode) 13157043Seric ENVELOPE *e; 13169275Seric char mode; 13174550Seric { 13185008Seric register ADDRESS *q; 13197779Seric bool oldverbose; 13209275Seric int pid; 13214550Seric 132214874Seric /* determine actual delivery mode */ 132314874Seric if (mode == SM_DEFAULT) 132414874Seric { 132524941Seric extern bool shouldqueue(); 132614874Seric 132724941Seric if (shouldqueue(e->e_msgpriority)) 132814874Seric mode = SM_QUEUE; 132914874Seric else 133014874Seric mode = SendMode; 133114874Seric } 133214874Seric 13338248Seric if (tTd(13, 1)) 13345032Seric { 13359275Seric printf("\nSENDALL: mode %c, sendqueue:\n", mode); 13367043Seric printaddr(e->e_sendqueue, TRUE); 13375032Seric } 13385008Seric 13397043Seric /* 13409275Seric ** Do any preprocessing necessary for the mode we are running. 13419370Seric ** Check to make sure the hop count is reasonable. 13429370Seric ** Delete sends to the sender in mailing lists. 13437043Seric */ 13447043Seric 13459370Seric CurEnv = e; 13469370Seric 13479370Seric if (e->e_hopcount > MAXHOP) 13489275Seric { 13499370Seric syserr("sendall: too many hops (%d max)", MAXHOP); 13509370Seric return; 13519370Seric } 13529275Seric 13539370Seric if (!MeToo) 13549370Seric { 135512611Seric extern ADDRESS *recipient(); 135612611Seric 13579370Seric e->e_from.q_flags |= QDONTSEND; 135812611Seric (void) recipient(&e->e_from, &e->e_sendqueue); 13599275Seric } 13609370Seric 13619370Seric # ifdef QUEUE 13629335Seric if ((mode == SM_QUEUE || mode == SM_FORK || 13639335Seric (mode != SM_VERIFY && SuperSafe)) && 13649335Seric !bitset(EF_INQUEUE, e->e_flags)) 13659370Seric queueup(e, TRUE, mode == SM_QUEUE); 13669275Seric #endif QUEUE 13679275Seric 13687779Seric oldverbose = Verbose; 13699275Seric switch (mode) 13709275Seric { 13719275Seric case SM_VERIFY: 13727779Seric Verbose = TRUE; 13739275Seric break; 13749275Seric 13759275Seric case SM_QUEUE: 13769335Seric e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; 13779275Seric return; 13789275Seric 13799275Seric case SM_FORK: 13809538Seric if (e->e_xfp != NULL) 13819538Seric (void) fflush(e->e_xfp); 13829275Seric pid = fork(); 13839275Seric if (pid < 0) 13849275Seric { 13859275Seric mode = SM_DELIVER; 13869275Seric break; 13879275Seric } 13889275Seric else if (pid > 0) 13899293Seric { 13909293Seric /* be sure we leave the temp files to our child */ 13919335Seric e->e_id = e->e_df = NULL; 13929275Seric return; 13939293Seric } 13949275Seric 13959275Seric /* double fork to avoid zombies */ 13969275Seric if (fork() > 0) 13979275Seric exit(EX_OK); 13989275Seric 13999293Seric /* be sure we are immune from the terminal */ 140010133Seric disconnect(FALSE); 14019293Seric 14029275Seric break; 14039275Seric } 14049275Seric 14059275Seric /* 14069275Seric ** Run through the list and send everything. 14079275Seric */ 14089275Seric 14097043Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 14104550Seric { 14119275Seric if (mode == SM_VERIFY) 14124550Seric { 14139293Seric e->e_to = q->q_paddr; 14145008Seric if (!bitset(QDONTSEND|QBADADDR, q->q_flags)) 14157052Seric message(Arpa_Info, "deliverable"); 14164550Seric } 14175008Seric else 14189370Seric (void) deliver(e, q); 14194550Seric } 14207779Seric Verbose = oldverbose; 14217043Seric 14227043Seric /* 14237043Seric ** Now run through and check for errors. 14247043Seric */ 14257043Seric 14269275Seric if (mode == SM_VERIFY) 14277043Seric return; 14287043Seric 14297043Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 14307043Seric { 14317043Seric register ADDRESS *qq; 14327043Seric 14338248Seric if (tTd(13, 3)) 14348248Seric { 14358248Seric printf("Checking "); 14368248Seric printaddr(q, FALSE); 14378248Seric } 14388248Seric 14399335Seric /* only send errors if the message failed */ 14409335Seric if (!bitset(QBADADDR, q->q_flags)) 14419335Seric continue; 14427043Seric 14437043Seric /* we have an address that failed -- find the parent */ 14447043Seric for (qq = q; qq != NULL; qq = qq->q_alias) 14457043Seric { 14467043Seric char obuf[MAXNAME + 6]; 14477043Seric extern char *aliaslookup(); 14487043Seric 14497043Seric /* we can only have owners for local addresses */ 145010682Seric if (!bitnset(M_LOCAL, qq->q_mailer->m_flags)) 14517043Seric continue; 14527043Seric 14537043Seric /* see if the owner list exists */ 14547043Seric (void) strcpy(obuf, "owner-"); 14557047Seric if (strncmp(qq->q_user, "owner-", 6) == 0) 14567047Seric (void) strcat(obuf, "owner"); 14577047Seric else 14587047Seric (void) strcat(obuf, qq->q_user); 14597043Seric if (aliaslookup(obuf) == NULL) 14607043Seric continue; 14617043Seric 14628248Seric if (tTd(13, 4)) 14638248Seric printf("Errors to %s\n", obuf); 14648248Seric 14657043Seric /* owner list exists -- add it to the error queue */ 14669615Seric sendtolist(obuf, (ADDRESS *) NULL, &e->e_errorqueue); 146716883Seric ErrorMode = EM_MAIL; 14687043Seric break; 14697043Seric } 14707043Seric 14717043Seric /* if we did not find an owner, send to the sender */ 14728426Seric if (qq == NULL && bitset(QBADADDR, q->q_flags)) 14739615Seric sendtolist(e->e_from.q_paddr, qq, &e->e_errorqueue); 14747043Seric } 14759275Seric 14769275Seric if (mode == SM_FORK) 14779275Seric finis(); 14784550Seric } 1479