122701Sdist /* 222701Sdist ** Sendmail 322701Sdist ** Copyright (c) 1983 Eric P. Allman 422701Sdist ** Berkeley, California 522701Sdist ** 622701Sdist ** Copyright (c) 1983 Regents of the University of California. 722701Sdist ** All rights reserved. The Berkeley software License Agreement 822701Sdist ** specifies the terms and conditions for redistribution. 922701Sdist */ 1022701Sdist 1122701Sdist #ifndef lint 12*26434Seric static char SccsId[] = "@(#)deliver.c 5.10 (Berkeley) 03/02/86"; 1322701Sdist #endif not lint 1422701Sdist 15294Seric # include <signal.h> 164123Seric # include <errno.h> 174621Seric # include "sendmail.h" 184327Seric # include <sys/stat.h> 1925527Smiriam # include <netdb.h> 20294Seric 21294Seric /* 224315Seric ** DELIVER -- Deliver a message to a list of addresses. 23294Seric ** 244315Seric ** This routine delivers to everyone on the same host as the 254315Seric ** user on the head of the list. It is clever about mailers 264315Seric ** that don't handle multiple users. It is NOT guaranteed 274315Seric ** that it will deliver to all these addresses however -- so 284315Seric ** deliver should be called once for each address on the 294315Seric ** list. 304315Seric ** 31294Seric ** Parameters: 329370Seric ** e -- the envelope to deliver. 334621Seric ** firstto -- head of the address list to deliver to. 34294Seric ** 35294Seric ** Returns: 36294Seric ** zero -- successfully delivered. 37294Seric ** else -- some failure, see ExitStat for more info. 38294Seric ** 39294Seric ** Side Effects: 40294Seric ** The standard input is passed off to someone. 41294Seric */ 42294Seric 439370Seric deliver(e, firstto) 449370Seric register ENVELOPE *e; 454621Seric ADDRESS *firstto; 46294Seric { 474452Seric char *host; /* host being sent to */ 484452Seric char *user; /* user being sent to */ 49294Seric char **pvp; 503233Seric register char **mvp; 513233Seric register char *p; 5210306Seric register MAILER *m; /* mailer for this recipient */ 534397Seric ADDRESS *ctladdr; 544621Seric register ADDRESS *to = firstto; 554863Seric bool clever = FALSE; /* running user smtp to this mailer */ 565032Seric ADDRESS *tochain = NULL; /* chain of users in this mailer call */ 578003Seric register int rcode; /* response code */ 5810306Seric char *pv[MAXPV+1]; 5910306Seric char tobuf[MAXLINE-50]; /* text line of to people */ 6010306Seric char buf[MAXNAME]; 6110306Seric char tfrombuf[MAXNAME]; /* translated from person */ 6210306Seric extern bool checkcompat(); 6310306Seric extern ADDRESS *getctladdr(); 6410306Seric extern char *remotename(); 65294Seric 664488Seric errno = 0; 677052Seric if (bitset(QDONTSEND, to->q_flags)) 683233Seric return (0); 69294Seric 706974Seric m = to->q_mailer; 716974Seric host = to->q_host; 726974Seric 73294Seric # ifdef DEBUG 747672Seric if (tTd(10, 1)) 753233Seric printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n", 766974Seric m->m_mno, host, to->q_user); 77294Seric # endif DEBUG 78294Seric 79294Seric /* 805903Seric ** If this mailer is expensive, and if we don't want to make 815903Seric ** connections now, just mark these addresses and return. 825903Seric ** This is useful if we want to batch connections to 835903Seric ** reduce load. This will cause the messages to be 845903Seric ** queued up, and a daemon will come along to send the 855903Seric ** messages later. 865903Seric ** This should be on a per-mailer basis. 875903Seric */ 885903Seric 8910682Seric if (NoConnect && !QueueRun && bitnset(M_EXPENSIVE, m->m_flags) && 908428Seric !Verbose) 915903Seric { 925903Seric for (; to != NULL; to = to->q_next) 938431Seric { 948431Seric if (bitset(QDONTSEND, to->q_flags) || to->q_mailer != m) 958431Seric continue; 968431Seric to->q_flags |= QQUEUEUP|QDONTSEND; 979370Seric e->e_to = to->q_paddr; 988496Seric message(Arpa_Info, "queued"); 998496Seric if (LogLevel > 4) 1008496Seric logdelivery("queued"); 1018431Seric } 1029370Seric e->e_to = NULL; 1035903Seric return (0); 1045903Seric } 1055903Seric 1065903Seric /* 1073233Seric ** Do initial argv setup. 1083233Seric ** Insert the mailer name. Notice that $x expansion is 1093233Seric ** NOT done on the mailer name. Then, if the mailer has 1103233Seric ** a picky -f flag, we insert it as appropriate. This 1113233Seric ** code does not check for 'pv' overflow; this places a 1123233Seric ** manifest lower limit of 4 for MAXPV. 1138062Seric ** The from address rewrite is expected to make 1148062Seric ** the address relative to the other end. 1152968Seric */ 1162968Seric 1174452Seric /* rewrite from address, using rewriting rules */ 11816150Seric expand("\001f", buf, &buf[sizeof buf - 1], e); 11910306Seric (void) strcpy(tfrombuf, remotename(buf, m, TRUE, TRUE)); 1204452Seric 1219370Seric define('g', tfrombuf, e); /* translated sender address */ 1229370Seric define('h', host, e); /* to host */ 1233233Seric Errors = 0; 1243233Seric pvp = pv; 1253233Seric *pvp++ = m->m_argv[0]; 1262968Seric 1273233Seric /* insert -f or -r flag as appropriate */ 12810682Seric if (FromFlag && (bitnset(M_FOPT, m->m_flags) || bitnset(M_ROPT, m->m_flags))) 1293233Seric { 13010682Seric if (bitnset(M_FOPT, m->m_flags)) 1313233Seric *pvp++ = "-f"; 1323233Seric else 1333233Seric *pvp++ = "-r"; 13416150Seric expand("\001g", buf, &buf[sizeof buf - 1], e); 1353233Seric *pvp++ = newstr(buf); 1363233Seric } 137294Seric 138294Seric /* 1393233Seric ** Append the other fixed parts of the argv. These run 1403233Seric ** up to the first entry containing "$u". There can only 1413233Seric ** be one of these, and there are only a few more slots 1423233Seric ** in the pv after it. 143294Seric */ 144294Seric 1453233Seric for (mvp = m->m_argv; (p = *++mvp) != NULL; ) 146294Seric { 14716150Seric while ((p = index(p, '\001')) != NULL) 1483233Seric if (*++p == 'u') 1493233Seric break; 1503233Seric if (p != NULL) 1513233Seric break; 1523233Seric 1533233Seric /* this entry is safe -- go ahead and process it */ 1549370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 1553233Seric *pvp++ = newstr(buf); 1563233Seric if (pvp >= &pv[MAXPV - 3]) 1573233Seric { 1583233Seric syserr("Too many parameters to %s before $u", pv[0]); 1593233Seric return (-1); 1603233Seric } 161294Seric } 1624863Seric 1636038Seric /* 1646038Seric ** If we have no substitution for the user name in the argument 1656038Seric ** list, we know that we must supply the names otherwise -- and 1666038Seric ** SMTP is the answer!! 1676038Seric */ 1686038Seric 1693233Seric if (*mvp == NULL) 1704863Seric { 1714863Seric /* running SMTP */ 1725179Seric # ifdef SMTP 1734863Seric clever = TRUE; 1744863Seric *pvp = NULL; 1755179Seric # else SMTP 1766038Seric /* oops! we don't implement SMTP */ 1775179Seric syserr("SMTP style mailer"); 1785179Seric return (EX_SOFTWARE); 1795179Seric # endif SMTP 1804863Seric } 181294Seric 182294Seric /* 1833233Seric ** At this point *mvp points to the argument with $u. We 1843233Seric ** run through our address list and append all the addresses 1853233Seric ** we can. If we run out of space, do not fret! We can 1863233Seric ** always send another copy later. 187294Seric */ 188294Seric 1893233Seric tobuf[0] = '\0'; 1909370Seric e->e_to = tobuf; 1914397Seric ctladdr = NULL; 1923233Seric for (; to != NULL; to = to->q_next) 193294Seric { 1943233Seric /* avoid sending multiple recipients to dumb mailers */ 19510682Seric if (tobuf[0] != '\0' && !bitnset(M_MUSER, m->m_flags)) 1963233Seric break; 1973233Seric 1983233Seric /* if already sent or not for this host, don't send */ 1997052Seric if (bitset(QDONTSEND, to->q_flags) || 2007052Seric strcmp(to->q_host, host) != 0 || 2017052Seric to->q_mailer != firstto->q_mailer) 2023233Seric continue; 2034397Seric 2048225Seric /* avoid overflowing tobuf */ 2059370Seric if (sizeof tobuf - (strlen(to->q_paddr) + strlen(tobuf) + 2) < 0) 2068225Seric break; 2078225Seric 2085032Seric # ifdef DEBUG 2097672Seric if (tTd(10, 1)) 2105032Seric { 2115032Seric printf("\nsend to "); 2125032Seric printaddr(to, FALSE); 2135032Seric } 2145032Seric # endif DEBUG 2155032Seric 2164397Seric /* compute effective uid/gid when sending */ 2174596Seric if (to->q_mailer == ProgMailer) 2184397Seric ctladdr = getctladdr(to); 2194397Seric 2203233Seric user = to->q_user; 2219370Seric e->e_to = to->q_paddr; 2223233Seric to->q_flags |= QDONTSEND; 2233233Seric 2243233Seric /* 2253233Seric ** Check to see that these people are allowed to 2263233Seric ** talk to each other. 2273233Seric */ 2283233Seric 22910699Seric if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize) 23010699Seric { 23110699Seric usrerr("Message is too large; %ld bytes max", m->m_maxsize); 23210699Seric NoReturn = TRUE; 23310699Seric giveresponse(EX_UNAVAILABLE, m, e); 23410699Seric continue; 23510699Seric } 2363233Seric if (!checkcompat(to)) 237294Seric { 23810105Seric giveresponse(EX_UNAVAILABLE, m, e); 2393233Seric continue; 240294Seric } 2413233Seric 2423233Seric /* 2434099Seric ** Strip quote bits from names if the mailer is dumb 2444099Seric ** about them. 2453233Seric */ 2463233Seric 24710682Seric if (bitnset(M_STRIPQ, m->m_flags)) 248294Seric { 2494099Seric stripquotes(user, TRUE); 2504099Seric stripquotes(host, TRUE); 2513233Seric } 2524099Seric else 2534099Seric { 2544099Seric stripquotes(user, FALSE); 2554099Seric stripquotes(host, FALSE); 2564099Seric } 2573233Seric 2589206Seric /* hack attack -- delivermail compatibility */ 2599206Seric if (m == ProgMailer && *user == '|') 2609206Seric user++; 2619206Seric 2623233Seric /* 2634161Seric ** If an error message has already been given, don't 2644161Seric ** bother to send to this address. 2654161Seric ** 2664161Seric ** >>>>>>>>>> This clause assumes that the local mailer 2674161Seric ** >> NOTE >> cannot do any further aliasing; that 2684161Seric ** >>>>>>>>>> function is subsumed by sendmail. 2694161Seric */ 2704161Seric 2717293Seric if (bitset(QBADADDR|QQUEUEUP, to->q_flags)) 2724161Seric continue; 2734161Seric 2744283Seric /* save statistics.... */ 2759370Seric markstats(e, to); 2764283Seric 2774161Seric /* 2783233Seric ** See if this user name is "special". 2793233Seric ** If the user name has a slash in it, assume that this 2806974Seric ** is a file -- send it off without further ado. Note 2816974Seric ** that this type of addresses is not processed along 2826974Seric ** with the others, so we fudge on the To person. 2833233Seric */ 2843233Seric 2854596Seric if (m == LocalMailer) 2863233Seric { 2875599Seric if (user[0] == '/') 288294Seric { 2898003Seric rcode = mailfile(user, getctladdr(to)); 29010105Seric giveresponse(rcode, m, e); 2913233Seric continue; 292294Seric } 293294Seric } 2943233Seric 2954315Seric /* 2964315Seric ** Address is verified -- add this user to mailer 2974315Seric ** argv, and add it to the print list of recipients. 2984315Seric */ 2994315Seric 3006059Seric /* link together the chain of recipients */ 3016272Seric to->q_tchain = tochain; 3026272Seric tochain = to; 3036059Seric 3043233Seric /* create list of users for error messages */ 3059388Seric (void) strcat(tobuf, ","); 3064082Seric (void) strcat(tobuf, to->q_paddr); 3079370Seric define('u', user, e); /* to user */ 3089370Seric define('z', to->q_home, e); /* user's home */ 3093233Seric 3104863Seric /* 3116059Seric ** Expand out this user into argument list. 3124863Seric */ 3134863Seric 3146059Seric if (!clever) 3153233Seric { 3169370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 3174863Seric *pvp++ = newstr(buf); 3184863Seric if (pvp >= &pv[MAXPV - 2]) 3194863Seric { 3204863Seric /* allow some space for trailing parms */ 3214863Seric break; 3224863Seric } 3234863Seric } 324294Seric } 325294Seric 3264067Seric /* see if any addresses still exist */ 3274067Seric if (tobuf[0] == '\0') 3284863Seric { 3299370Seric define('g', (char *) NULL, e); 3304067Seric return (0); 3314863Seric } 3324067Seric 3333233Seric /* print out messages as full list */ 3349388Seric e->e_to = tobuf + 1; 3353233Seric 336294Seric /* 3373233Seric ** Fill out any parameters after the $u parameter. 338294Seric */ 339294Seric 3404863Seric while (!clever && *++mvp != NULL) 341294Seric { 3429370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 3433233Seric *pvp++ = newstr(buf); 3443233Seric if (pvp >= &pv[MAXPV]) 3453233Seric syserr("deliver: pv overflow after $u for %s", pv[0]); 346294Seric } 3473233Seric *pvp++ = NULL; 348294Seric 349294Seric /* 350294Seric ** Call the mailer. 3512898Seric ** The argument vector gets built, pipes 352294Seric ** are created as necessary, and we fork & exec as 3532898Seric ** appropriate. 3544863Seric ** If we are running SMTP, we just need to clean up. 355294Seric */ 356294Seric 3579370Seric message(Arpa_Info, "Connecting to %s.%s...", host, m->m_name); 3589370Seric 3594397Seric if (ctladdr == NULL) 3609370Seric ctladdr = &e->e_from; 3615179Seric # ifdef SMTP 3624863Seric if (clever) 3634863Seric { 3649370Seric /* send the initial SMTP protocol */ 36510168Seric rcode = smtpinit(m, pv); 3669370Seric 3679388Seric if (rcode == EX_OK) 3689370Seric { 3699388Seric /* send the recipient list */ 3709388Seric tobuf[0] = '\0'; 3719388Seric for (to = tochain; to != NULL; to = to->q_tchain) 3729388Seric { 3739388Seric int i; 3749370Seric 3759388Seric e->e_to = to->q_paddr; 37610168Seric i = smtprcpt(to, m); 3779388Seric if (i != EX_OK) 3789388Seric { 37910092Seric markfailure(e, to, i); 38010105Seric giveresponse(i, m, e); 3819388Seric } 3829388Seric else 3839388Seric { 38423102Seric (void) strcat(tobuf, ","); 38523102Seric (void) strcat(tobuf, to->q_paddr); 3869388Seric } 3879388Seric } 3889388Seric 3899388Seric /* now send the data */ 3909388Seric if (tobuf[0] == '\0') 3919388Seric e->e_to = NULL; 3929370Seric else 3939370Seric { 3949388Seric e->e_to = tobuf + 1; 39510168Seric rcode = smtpdata(m, e); 3969370Seric } 3979388Seric 3989388Seric /* now close the connection */ 39915531Seric smtpquit(m); 4009370Seric } 4014863Seric } 4024863Seric else 4035179Seric # endif SMTP 40410168Seric rcode = sendoff(e, m, pv, ctladdr); 4053233Seric 4064621Seric /* 4079388Seric ** Do final status disposal. 4089388Seric ** We check for something in tobuf for the SMTP case. 4099388Seric ** If we got a temporary failure, arrange to queue the 4109388Seric ** addressees. 4114621Seric */ 4124621Seric 4139388Seric if (tobuf[0] != '\0') 41410105Seric giveresponse(rcode, m, e); 4159388Seric if (rcode != EX_OK) 4164621Seric { 4175032Seric for (to = tochain; to != NULL; to = to->q_tchain) 41810092Seric markfailure(e, to, rcode); 4194621Seric } 4204621Seric 4214488Seric errno = 0; 4229370Seric define('g', (char *) NULL, e); 4238003Seric return (rcode); 4243233Seric } 4253233Seric /* 42610092Seric ** MARKFAILURE -- mark a failure on a specific address. 42710092Seric ** 42810092Seric ** Parameters: 42910092Seric ** e -- the envelope we are sending. 43010092Seric ** q -- the address to mark. 43110092Seric ** rcode -- the code signifying the particular failure. 43210092Seric ** 43310092Seric ** Returns: 43410092Seric ** none. 43510092Seric ** 43610092Seric ** Side Effects: 43710092Seric ** marks the address (and possibly the envelope) with the 43810092Seric ** failure so that an error will be returned or 43910092Seric ** the message will be queued, as appropriate. 44010092Seric */ 44110092Seric 44210092Seric markfailure(e, q, rcode) 44310092Seric register ENVELOPE *e; 44410092Seric register ADDRESS *q; 44510092Seric int rcode; 44610092Seric { 44710092Seric if (rcode == EX_OK) 44810092Seric return; 44910092Seric else if (rcode != EX_TEMPFAIL) 45010092Seric q->q_flags |= QBADADDR; 45110092Seric else if (curtime() > e->e_ctime + TimeOut) 45210092Seric { 45310092Seric extern char *pintvl(); 45410105Seric char buf[MAXLINE]; 45510092Seric 45610092Seric if (!bitset(EF_TIMEOUT, e->e_flags)) 45710105Seric { 45810105Seric (void) sprintf(buf, "Cannot send message for %s", 45910092Seric pintvl(TimeOut, FALSE)); 46010105Seric if (e->e_message != NULL) 46110105Seric free(e->e_message); 46210105Seric e->e_message = newstr(buf); 46310105Seric message(Arpa_Info, buf); 46410105Seric } 46510092Seric q->q_flags |= QBADADDR; 46610092Seric e->e_flags |= EF_TIMEOUT; 46710092Seric } 46810092Seric else 46910092Seric q->q_flags |= QQUEUEUP; 47010092Seric } 47110092Seric /* 4724214Seric ** DOFORK -- do a fork, retrying a couple of times on failure. 4734214Seric ** 4744214Seric ** This MUST be a macro, since after a vfork we are running 4754214Seric ** two processes on the same stack!!! 4764214Seric ** 4774214Seric ** Parameters: 4784214Seric ** none. 4794214Seric ** 4804214Seric ** Returns: 4814214Seric ** From a macro??? You've got to be kidding! 4824214Seric ** 4834214Seric ** Side Effects: 4844214Seric ** Modifies the ==> LOCAL <== variable 'pid', leaving: 4854214Seric ** pid of child in parent, zero in child. 4864214Seric ** -1 on unrecoverable error. 4874214Seric ** 4884214Seric ** Notes: 4894214Seric ** I'm awfully sorry this looks so awful. That's 4904214Seric ** vfork for you..... 4914214Seric */ 4924214Seric 4934214Seric # define NFORKTRIES 5 4949148Seric # ifdef VMUNIX 4954214Seric # define XFORK vfork 4969148Seric # else VMUNIX 4974214Seric # define XFORK fork 4989148Seric # endif VMUNIX 4994214Seric 5004214Seric # define DOFORK(fORKfN) \ 5014214Seric {\ 5024214Seric register int i;\ 5034214Seric \ 50423504Seric for (i = NFORKTRIES; --i >= 0; )\ 5054214Seric {\ 5064214Seric pid = fORKfN();\ 5074214Seric if (pid >= 0)\ 5084214Seric break;\ 50923504Seric if (i > 0)\ 51025617Seric sleep((unsigned) NFORKTRIES - i);\ 5114214Seric }\ 5124214Seric } 5134214Seric /* 5144637Seric ** DOFORK -- simple fork interface to DOFORK. 5154637Seric ** 5164637Seric ** Parameters: 5174637Seric ** none. 5184637Seric ** 5194637Seric ** Returns: 5204637Seric ** pid of child in parent. 5214637Seric ** zero in child. 5224637Seric ** -1 on error. 5234637Seric ** 5244637Seric ** Side Effects: 5254637Seric ** returns twice, once in parent and once in child. 5264637Seric */ 5274637Seric 5284637Seric dofork() 5294637Seric { 5304637Seric register int pid; 5314637Seric 5324637Seric DOFORK(fork); 5334637Seric return (pid); 5344637Seric } 5354637Seric /* 5363233Seric ** SENDOFF -- send off call to mailer & collect response. 5373233Seric ** 5383233Seric ** Parameters: 5399370Seric ** e -- the envelope to mail. 5403233Seric ** m -- mailer descriptor. 5413233Seric ** pvp -- parameter vector to send to it. 5424397Seric ** ctladdr -- an address pointer controlling the 5434397Seric ** user/groupid etc. of the mailer. 5443233Seric ** 5453233Seric ** Returns: 5463233Seric ** exit status of mailer. 5473233Seric ** 5483233Seric ** Side Effects: 5493233Seric ** none. 5503233Seric */ 5513233Seric 55210168Seric sendoff(e, m, pvp, ctladdr) 5539370Seric register ENVELOPE *e; 5549370Seric MAILER *m; 5553233Seric char **pvp; 5564397Seric ADDRESS *ctladdr; 5573233Seric { 5584863Seric auto FILE *mfile; 5594863Seric auto FILE *rfile; 5603233Seric register int i; 5613233Seric int pid; 5624863Seric 5634863Seric /* 5644863Seric ** Create connection to mailer. 5654863Seric */ 5664863Seric 5674863Seric pid = openmailer(m, pvp, ctladdr, FALSE, &mfile, &rfile); 5684863Seric if (pid < 0) 5694863Seric return (-1); 5704863Seric 5714863Seric /* 5724863Seric ** Format and send message. 5734863Seric */ 5744863Seric 57510168Seric putfromline(mfile, m); 57610168Seric (*e->e_puthdr)(mfile, m, e); 57710168Seric putline("\n", mfile, m); 57810168Seric (*e->e_putbody)(mfile, m, e); 5794863Seric (void) fclose(mfile); 5804863Seric 5814863Seric i = endmailer(pid, pvp[0]); 5825981Seric 5835981Seric /* arrange a return receipt if requested */ 58410682Seric if (e->e_receiptto != NULL && bitnset(M_LOCAL, m->m_flags)) 5855981Seric { 5869370Seric e->e_flags |= EF_SENDRECEIPT; 5875981Seric /* do we want to send back more info? */ 5885981Seric } 5895981Seric 5904863Seric return (i); 5914863Seric } 5924863Seric /* 5934863Seric ** ENDMAILER -- Wait for mailer to terminate. 5944863Seric ** 5954863Seric ** We should never get fatal errors (e.g., segmentation 5964863Seric ** violation), so we report those specially. For other 5974863Seric ** errors, we choose a status message (into statmsg), 5984863Seric ** and if it represents an error, we print it. 5994863Seric ** 6004863Seric ** Parameters: 6014863Seric ** pid -- pid of mailer. 6024863Seric ** name -- name of mailer (for error messages). 6034863Seric ** 6044863Seric ** Returns: 6054863Seric ** exit code of mailer. 6064863Seric ** 6074863Seric ** Side Effects: 6084863Seric ** none. 6094863Seric */ 6104863Seric 6114863Seric endmailer(pid, name) 6124863Seric int pid; 6134863Seric char *name; 6144863Seric { 6159370Seric int st; 6164863Seric 6176038Seric /* in the IPC case there is nothing to wait for */ 6186038Seric if (pid == 0) 6196038Seric return (EX_OK); 6206038Seric 6216038Seric /* wait for the mailer process to die and collect status */ 6229370Seric st = waitfor(pid); 6239370Seric if (st == -1) 6248127Seric { 6259370Seric syserr("endmailer %s: wait", name); 6269370Seric return (EX_SOFTWARE); 6274863Seric } 6286038Seric 6296038Seric /* see if it died a horrid death */ 6304863Seric if ((st & 0377) != 0) 6314863Seric { 63224941Seric syserr("mailer %s died with signal %o", name, st); 63324941Seric ExitStat = EX_TEMPFAIL; 63424941Seric return (EX_TEMPFAIL); 6354863Seric } 6366038Seric 6376038Seric /* normal death -- return status */ 6389370Seric st = (st >> 8) & 0377; 6399370Seric return (st); 6404863Seric } 6414863Seric /* 6424863Seric ** OPENMAILER -- open connection to mailer. 6434863Seric ** 6444863Seric ** Parameters: 6454863Seric ** m -- mailer descriptor. 6464863Seric ** pvp -- parameter vector to pass to mailer. 6474863Seric ** ctladdr -- controlling address for user. 6484863Seric ** clever -- create a full duplex connection. 6494863Seric ** pmfile -- pointer to mfile (to mailer) connection. 6504863Seric ** prfile -- pointer to rfile (from mailer) connection. 6514863Seric ** 6524863Seric ** Returns: 6536038Seric ** pid of mailer ( > 0 ). 6544863Seric ** -1 on error. 6556038Seric ** zero on an IPC connection. 6564863Seric ** 6574863Seric ** Side Effects: 6584863Seric ** creates a mailer in a subprocess. 6594863Seric */ 6604863Seric 6614863Seric openmailer(m, pvp, ctladdr, clever, pmfile, prfile) 6629370Seric MAILER *m; 6634863Seric char **pvp; 6644863Seric ADDRESS *ctladdr; 6654863Seric bool clever; 6664863Seric FILE **pmfile; 6674863Seric FILE **prfile; 6684863Seric { 6694863Seric int pid; 6704709Seric int mpvect[2]; 6714863Seric int rpvect[2]; 6723233Seric FILE *mfile; 6734863Seric FILE *rfile; 6743233Seric extern FILE *fdopen(); 6753233Seric 6763233Seric # ifdef DEBUG 6777672Seric if (tTd(11, 1)) 678294Seric { 6798178Seric printf("openmailer:"); 6803233Seric printav(pvp); 681294Seric } 6823233Seric # endif DEBUG 6834488Seric errno = 0; 6843233Seric 68525050Seric CurHostName = m->m_mailer; 68625050Seric 6876038Seric /* 6886038Seric ** Deal with the special case of mail handled through an IPC 6896038Seric ** connection. 6906038Seric ** In this case we don't actually fork. We must be 6916038Seric ** running SMTP for this to work. We will return a 6926038Seric ** zero pid to indicate that we are running IPC. 69311160Seric ** We also handle a debug version that just talks to stdin/out. 6946038Seric */ 6956038Seric 69611160Seric #ifdef DEBUG 69711160Seric /* check for Local Person Communication -- not for mortals!!! */ 69811160Seric if (strcmp(m->m_mailer, "[LPC]") == 0) 69911160Seric { 70011160Seric *pmfile = stdout; 70111160Seric *prfile = stdin; 70211160Seric return (0); 70311160Seric } 70411160Seric #endif DEBUG 70511160Seric 7066038Seric if (strcmp(m->m_mailer, "[IPC]") == 0) 7076038Seric { 70824941Seric #ifdef HOSTINFO 70924941Seric register STAB *st; 71024941Seric extern STAB *stab(); 71124941Seric #endif HOSTINFO 7129370Seric #ifdef DAEMON 7136038Seric register int i; 7147285Seric register u_short port; 7156038Seric 71625050Seric CurHostName = pvp[1]; 7176038Seric if (!clever) 7186038Seric syserr("non-clever IPC"); 7196632Seric if (pvp[2] != NULL) 7207285Seric port = atoi(pvp[2]); 7216632Seric else 7227285Seric port = 0; 72324941Seric #ifdef HOSTINFO 72424941Seric /* see if we have already determined that this host is fried */ 72524941Seric st = stab(pvp[1], ST_HOST, ST_FIND); 72624941Seric if (st == NULL || st->s_host.ho_exitstat == EX_OK) 72724941Seric i = makeconnection(pvp[1], port, pmfile, prfile); 72824941Seric else 72925050Seric { 73024941Seric i = st->s_host.ho_exitstat; 73125050Seric errno = st->s_host.ho_errno; 73225050Seric } 73324941Seric #else HOSTINFO 7347285Seric i = makeconnection(pvp[1], port, pmfile, prfile); 73524941Seric #endif HOSTINFO 7366038Seric if (i != EX_OK) 7376047Seric { 73824941Seric #ifdef HOSTINFO 73924941Seric /* enter status of this host */ 74024941Seric if (st == NULL) 74124941Seric st = stab(pvp[1], ST_HOST, ST_ENTER); 74224941Seric st->s_host.ho_exitstat = i; 74324941Seric st->s_host.ho_errno = errno; 74424941Seric #endif HOSTINFO 7456047Seric ExitStat = i; 7466038Seric return (-1); 7476047Seric } 7486038Seric else 7496038Seric return (0); 7509370Seric #else DAEMON 7519370Seric syserr("openmailer: no IPC"); 7529370Seric return (-1); 7539370Seric #endif DAEMON 7546038Seric } 7556038Seric 7562898Seric /* create a pipe to shove the mail through */ 7574709Seric if (pipe(mpvect) < 0) 758294Seric { 7599370Seric syserr("openmailer: pipe (to mailer)"); 760294Seric return (-1); 761294Seric } 7624863Seric 7639370Seric #ifdef SMTP 7644863Seric /* if this mailer speaks smtp, create a return pipe */ 7654863Seric if (clever && pipe(rpvect) < 0) 7664863Seric { 7679370Seric syserr("openmailer: pipe (from mailer)"); 7684863Seric (void) close(mpvect[0]); 7694863Seric (void) close(mpvect[1]); 7704863Seric return (-1); 7714863Seric } 7729370Seric #endif SMTP 7734863Seric 7746038Seric /* 7756038Seric ** Actually fork the mailer process. 7766038Seric ** DOFORK is clever about retrying. 777*26434Seric ** 778*26434Seric ** Dispose of SIGCHLD signal catchers that may be laying 779*26434Seric ** around so that endmail will get it. 7806038Seric */ 7816038Seric 7829538Seric if (CurEnv->e_xfp != NULL) 7839538Seric (void) fflush(CurEnv->e_xfp); /* for debugging */ 7849370Seric (void) fflush(stdout); 785*26434Seric # ifdef SIGCHLD 786*26434Seric (void) signal(SIGCHLD, SIG_DFL); 787*26434Seric # endif SIGCHLD 7884214Seric DOFORK(XFORK); 7894327Seric /* pid is set by DOFORK */ 790294Seric if (pid < 0) 791294Seric { 7926038Seric /* failure */ 7939370Seric syserr("openmailer: cannot fork"); 7944709Seric (void) close(mpvect[0]); 7954709Seric (void) close(mpvect[1]); 7969370Seric #ifdef SMTP 7974863Seric if (clever) 7984863Seric { 7994863Seric (void) close(rpvect[0]); 8004863Seric (void) close(rpvect[1]); 8014863Seric } 8029370Seric #endif SMTP 803294Seric return (-1); 804294Seric } 805294Seric else if (pid == 0) 806294Seric { 80715772Seric int i; 80824941Seric extern int DtableSize; 80915772Seric 810294Seric /* child -- set up input & exec mailer */ 8111621Seric /* make diagnostic output be standard output */ 8124477Seric (void) signal(SIGINT, SIG_IGN); 8134477Seric (void) signal(SIGHUP, SIG_IGN); 8144215Seric (void) signal(SIGTERM, SIG_DFL); 8154709Seric 8164709Seric /* arrange to filter standard & diag output of command */ 8174863Seric if (clever) 8184709Seric { 8194863Seric (void) close(rpvect[0]); 8204709Seric (void) close(1); 8214863Seric (void) dup(rpvect[1]); 8224863Seric (void) close(rpvect[1]); 8234863Seric } 8249275Seric else if (OpMode == MD_SMTP || HoldErrs) 8254863Seric { 8269370Seric /* put mailer output in transcript */ 8274863Seric (void) close(1); 8289538Seric (void) dup(fileno(CurEnv->e_xfp)); 8294709Seric } 8304082Seric (void) close(2); 8314082Seric (void) dup(1); 8324709Seric 8334709Seric /* arrange to get standard input */ 8344709Seric (void) close(mpvect[1]); 8354082Seric (void) close(0); 8364709Seric if (dup(mpvect[0]) < 0) 837294Seric { 8382898Seric syserr("Cannot dup to zero!"); 8392898Seric _exit(EX_OSERR); 840294Seric } 8414709Seric (void) close(mpvect[0]); 84210682Seric if (!bitnset(M_RESTR, m->m_flags)) 8434215Seric { 84416883Seric if (ctladdr == NULL || ctladdr->q_uid == 0) 8454417Seric { 8464417Seric (void) setgid(DefGid); 8474417Seric (void) setuid(DefUid); 8484417Seric } 8494417Seric else 8504415Seric { 8514417Seric (void) setgid(ctladdr->q_gid); 8524417Seric (void) setuid(ctladdr->q_uid); 8534415Seric } 8544215Seric } 8559370Seric 85615772Seric /* arrange for all the files to be closed */ 85724941Seric for (i = 3; i < DtableSize; i++) 85815772Seric #ifdef FIOCLEX 85915772Seric (void) ioctl(i, FIOCLEX, 0); 86015772Seric #else FIOCLEX 86115772Seric (void) close(i); 86215772Seric #endif FIOCLEX 8632774Seric 8646038Seric /* try to execute the mailer */ 86525026Seric execve(m->m_mailer, pvp, UserEnviron); 8666038Seric 86715772Seric #ifdef FIOCLEX 86815772Seric syserr("Cannot exec %s", m->m_mailer); 86915772Seric #else FIOCLEX 8704214Seric printf("Cannot exec '%s' errno=%d\n", m->m_mailer, errno); 8714082Seric (void) fflush(stdout); 87215772Seric #endif FIOCLEX 87324941Seric if (m == LocalMailer || errno == EIO || errno == EAGAIN || 87424941Seric errno == ENOMEM || errno == EPROCLIM) 87516902Seric _exit(EX_TEMPFAIL); 87616902Seric else 87716902Seric _exit(EX_UNAVAILABLE); 878294Seric } 879294Seric 8804709Seric /* 8814863Seric ** Set up return value. 8824709Seric */ 8834709Seric 8844709Seric (void) close(mpvect[0]); 8854709Seric mfile = fdopen(mpvect[1], "w"); 8864863Seric if (clever) 8874863Seric { 8884863Seric (void) close(rpvect[1]); 8894863Seric rfile = fdopen(rpvect[0], "r"); 8904863Seric } 891294Seric 8924863Seric *pmfile = mfile; 8934863Seric *prfile = rfile; 894294Seric 8954863Seric return (pid); 896294Seric } 897294Seric /* 898294Seric ** GIVERESPONSE -- Interpret an error response from a mailer 899294Seric ** 900294Seric ** Parameters: 901294Seric ** stat -- the status code from the mailer (high byte 902294Seric ** only; core dumps must have been taken care of 903294Seric ** already). 904294Seric ** m -- the mailer descriptor for this mailer. 905294Seric ** 906294Seric ** Returns: 9074082Seric ** none. 908294Seric ** 909294Seric ** Side Effects: 9101518Seric ** Errors may be incremented. 911294Seric ** ExitStat may be set. 912294Seric */ 913294Seric 91410105Seric giveresponse(stat, m, e) 915294Seric int stat; 9169370Seric register MAILER *m; 91710105Seric ENVELOPE *e; 918294Seric { 919294Seric register char *statmsg; 920294Seric extern char *SysExMsg[]; 921294Seric register int i; 922294Seric extern int N_SysEx; 92310105Seric char buf[MAXLINE]; 924294Seric 92512135Seric #ifdef lint 92612135Seric if (m == NULL) 92712135Seric return; 92812135Seric #endif lint 92912135Seric 9304315Seric /* 9314315Seric ** Compute status message from code. 9324315Seric */ 9334315Seric 934294Seric i = stat - EX__BASE; 9359370Seric if (stat == 0) 9369370Seric statmsg = "250 Sent"; 9379370Seric else if (i < 0 || i > N_SysEx) 9389370Seric { 9399370Seric (void) sprintf(buf, "554 unknown mailer error %d", stat); 9409370Seric stat = EX_UNAVAILABLE; 9419370Seric statmsg = buf; 9429370Seric } 94310105Seric else if (stat == EX_TEMPFAIL) 94410105Seric { 94510124Seric (void) strcpy(buf, SysExMsg[i]); 94625527Smiriam if (h_errno == TRY_AGAIN) 94710105Seric { 94815137Seric extern char *errstring(); 94915137Seric 95025527Smiriam statmsg = errstring(h_errno+MAX_ERRNO); 95121061Seric } 95221061Seric else 95321061Seric { 95425527Smiriam if (errno != 0) 95525527Smiriam { 95625527Smiriam extern char *errstring(); 95725527Smiriam 95825527Smiriam statmsg = errstring(errno); 95925527Smiriam } 96025527Smiriam else 96125527Smiriam { 96221061Seric #ifdef SMTP 96325527Smiriam extern char SmtpError[]; 96421061Seric 96525527Smiriam statmsg = SmtpError; 96621061Seric #else SMTP 96725527Smiriam statmsg = NULL; 96821061Seric #endif SMTP 96925527Smiriam } 97021061Seric } 97121061Seric if (statmsg != NULL && statmsg[0] != '\0') 97221061Seric { 97310124Seric (void) strcat(buf, ": "); 97421061Seric (void) strcat(buf, statmsg); 97510105Seric } 97610105Seric statmsg = buf; 97710105Seric } 978294Seric else 97921061Seric { 980294Seric statmsg = SysExMsg[i]; 98121061Seric } 9829370Seric 9839370Seric /* 9849370Seric ** Print the message as appropriate 9859370Seric */ 9869370Seric 98710105Seric if (stat == EX_OK || stat == EX_TEMPFAIL) 9888003Seric message(Arpa_Info, &statmsg[4]); 989294Seric else 990294Seric { 9911518Seric Errors++; 9929370Seric usrerr(statmsg); 993294Seric } 994294Seric 995294Seric /* 996294Seric ** Final cleanup. 997294Seric ** Log a record of the transaction. Compute the new 998294Seric ** ExitStat -- if we already had an error, stick with 999294Seric ** that. 1000294Seric */ 1001294Seric 10027680Seric if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2)) 10038496Seric logdelivery(&statmsg[4]); 10047858Seric 10054621Seric if (stat != EX_TEMPFAIL) 10064621Seric setstat(stat); 100710105Seric if (stat != EX_OK) 100810105Seric { 100910105Seric if (e->e_message != NULL) 101010105Seric free(e->e_message); 101110105Seric e->e_message = newstr(&statmsg[4]); 101210105Seric } 101310124Seric errno = 0; 101425527Smiriam h_errno = 0; 1015294Seric } 1016294Seric /* 10178496Seric ** LOGDELIVERY -- log the delivery in the system log 10188496Seric ** 10198496Seric ** Parameters: 10208496Seric ** stat -- the message to print for the status 10218496Seric ** 10228496Seric ** Returns: 10238496Seric ** none 10248496Seric ** 10258496Seric ** Side Effects: 10268496Seric ** none 10278496Seric */ 10288496Seric 10298496Seric logdelivery(stat) 10308496Seric char *stat; 10318496Seric { 10328496Seric extern char *pintvl(); 10338496Seric 10348496Seric # ifdef LOG 10358496Seric syslog(LOG_INFO, "%s: to=%s, delay=%s, stat=%s", CurEnv->e_id, 10368496Seric CurEnv->e_to, pintvl(curtime() - CurEnv->e_ctime, TRUE), stat); 10378496Seric # endif LOG 10388496Seric } 10398496Seric /* 10406974Seric ** PUTFROMLINE -- output a UNIX-style from line (or whatever) 1041294Seric ** 10426974Seric ** This can be made an arbitrary message separator by changing $l 1043294Seric ** 104416150Seric ** One of the ugliest hacks seen by human eyes is contained herein: 104516150Seric ** UUCP wants those stupid "remote from <host>" lines. Why oh why 104616150Seric ** does a well-meaning programmer such as myself have to deal with 104716150Seric ** this kind of antique garbage???? 10486974Seric ** 1049294Seric ** Parameters: 10506974Seric ** fp -- the file to output to. 10516974Seric ** m -- the mailer describing this entry. 1052294Seric ** 1053294Seric ** Returns: 10546974Seric ** none 1055294Seric ** 1056294Seric ** Side Effects: 10576974Seric ** outputs some text to fp. 1058294Seric */ 1059294Seric 106010168Seric putfromline(fp, m) 10616974Seric register FILE *fp; 10626974Seric register MAILER *m; 1063294Seric { 106416150Seric char *template = "\001l\n"; 10656974Seric char buf[MAXLINE]; 1066294Seric 106710682Seric if (bitnset(M_NHDR, m->m_flags)) 10686974Seric return; 10694315Seric 10706974Seric # ifdef UGLYUUCP 107110682Seric if (bitnset(M_UGLYUUCP, m->m_flags)) 10724205Seric { 107312223Seric char *bang; 107412223Seric char xbuf[MAXLINE]; 10756041Seric 107616150Seric expand("\001g", buf, &buf[sizeof buf - 1], CurEnv); 107712223Seric bang = index(buf, '!'); 10786974Seric if (bang == NULL) 107912223Seric syserr("No ! in UUCP! (%s)", buf); 10805099Seric else 10819370Seric { 108212223Seric *bang++ = '\0'; 108316150Seric (void) sprintf(xbuf, "From %s \001d remote from %s\n", bang, buf); 108412223Seric template = xbuf; 10859370Seric } 10866974Seric } 10875179Seric # endif UGLYUUCP 108812223Seric expand(template, buf, &buf[sizeof buf - 1], CurEnv); 108910168Seric putline(buf, fp, m); 10905981Seric } 10915981Seric /* 10926974Seric ** PUTBODY -- put the body of a message. 10936974Seric ** 10946974Seric ** Parameters: 10956974Seric ** fp -- file to output onto. 109610168Seric ** m -- a mailer descriptor to control output format. 10979538Seric ** e -- the envelope to put out. 10986974Seric ** 10996974Seric ** Returns: 11006974Seric ** none. 11016974Seric ** 11026974Seric ** Side Effects: 11036974Seric ** The message is written onto fp. 11046974Seric */ 11056974Seric 110610168Seric putbody(fp, m, e) 11076974Seric FILE *fp; 11089370Seric MAILER *m; 11099538Seric register ENVELOPE *e; 11106974Seric { 111110168Seric char buf[MAXLINE]; 11126974Seric 11136974Seric /* 11146974Seric ** Output the body of the message 11156974Seric */ 11166974Seric 11179538Seric if (e->e_dfp == NULL) 11186974Seric { 11199538Seric if (e->e_df != NULL) 11209538Seric { 11219538Seric e->e_dfp = fopen(e->e_df, "r"); 11229538Seric if (e->e_dfp == NULL) 11239538Seric syserr("Cannot open %s", e->e_df); 11249538Seric } 11259538Seric else 112610168Seric putline("<<< No Message Collected >>>", fp, m); 11279538Seric } 11289538Seric if (e->e_dfp != NULL) 11299538Seric { 11309538Seric rewind(e->e_dfp); 113110168Seric while (!ferror(fp) && fgets(buf, sizeof buf, e->e_dfp) != NULL) 113216875Seric { 113316875Seric if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) && 113416875Seric strncmp(buf, "From", 4) == 0) 113523102Seric (void) putc('>', fp); 113610168Seric putline(buf, fp, m); 113716875Seric } 11386974Seric 11399538Seric if (ferror(e->e_dfp)) 11406974Seric { 11416974Seric syserr("putbody: read error"); 11426974Seric ExitStat = EX_IOERR; 11436974Seric } 11446974Seric } 11456974Seric 11466974Seric (void) fflush(fp); 11476974Seric if (ferror(fp) && errno != EPIPE) 11486974Seric { 11496974Seric syserr("putbody: write error"); 11506974Seric ExitStat = EX_IOERR; 11516974Seric } 11526974Seric errno = 0; 11536974Seric } 11546974Seric /* 1155294Seric ** MAILFILE -- Send a message to a file. 1156294Seric ** 11574327Seric ** If the file has the setuid/setgid bits set, but NO execute 11584327Seric ** bits, sendmail will try to become the owner of that file 11594327Seric ** rather than the real user. Obviously, this only works if 11604327Seric ** sendmail runs as root. 11614327Seric ** 11629370Seric ** This could be done as a subordinate mailer, except that it 11639370Seric ** is used implicitly to save messages in ~/dead.letter. We 11649370Seric ** view this as being sufficiently important as to include it 11659370Seric ** here. For example, if the system is dying, we shouldn't have 11669370Seric ** to create another process plus some pipes to save the message. 11679370Seric ** 1168294Seric ** Parameters: 1169294Seric ** filename -- the name of the file to send to. 11704397Seric ** ctladdr -- the controlling address header -- includes 11714397Seric ** the userid/groupid to be when sending. 1172294Seric ** 1173294Seric ** Returns: 1174294Seric ** The exit code associated with the operation. 1175294Seric ** 1176294Seric ** Side Effects: 1177294Seric ** none. 1178294Seric */ 1179294Seric 11804397Seric mailfile(filename, ctladdr) 1181294Seric char *filename; 11824397Seric ADDRESS *ctladdr; 1183294Seric { 1184294Seric register FILE *f; 11854214Seric register int pid; 1186294Seric 11874214Seric /* 11884214Seric ** Fork so we can change permissions here. 11894214Seric ** Note that we MUST use fork, not vfork, because of 11904214Seric ** the complications of calling subroutines, etc. 11914214Seric */ 11924067Seric 11934214Seric DOFORK(fork); 11944214Seric 11954214Seric if (pid < 0) 11964214Seric return (EX_OSERR); 11974214Seric else if (pid == 0) 11984214Seric { 11994214Seric /* child -- actually write to file */ 12004327Seric struct stat stb; 12014327Seric 12024215Seric (void) signal(SIGINT, SIG_DFL); 12034215Seric (void) signal(SIGHUP, SIG_DFL); 12044215Seric (void) signal(SIGTERM, SIG_DFL); 120523102Seric (void) umask(OldUmask); 12064327Seric if (stat(filename, &stb) < 0) 120711935Seric { 120811935Seric errno = 0; 12094431Seric stb.st_mode = 0666; 121011935Seric } 12114327Seric if (bitset(0111, stb.st_mode)) 12124327Seric exit(EX_CANTCREAT); 12134401Seric if (ctladdr == NULL) 12146900Seric ctladdr = &CurEnv->e_from; 12154327Seric if (!bitset(S_ISGID, stb.st_mode) || setgid(stb.st_gid) < 0) 12164417Seric { 12174417Seric if (ctladdr->q_uid == 0) 12184417Seric (void) setgid(DefGid); 12194417Seric else 12204417Seric (void) setgid(ctladdr->q_gid); 12214417Seric } 12224327Seric if (!bitset(S_ISUID, stb.st_mode) || setuid(stb.st_uid) < 0) 12234417Seric { 12244417Seric if (ctladdr->q_uid == 0) 12254417Seric (void) setuid(DefUid); 12264417Seric else 12274417Seric (void) setuid(ctladdr->q_uid); 12284417Seric } 12296887Seric f = dfopen(filename, "a"); 12304214Seric if (f == NULL) 12314214Seric exit(EX_CANTCREAT); 12324214Seric 123310168Seric putfromline(f, ProgMailer); 123410168Seric (*CurEnv->e_puthdr)(f, ProgMailer, CurEnv); 123510168Seric putline("\n", f, ProgMailer); 123610168Seric (*CurEnv->e_putbody)(f, ProgMailer, CurEnv); 123710168Seric putline("\n", f, ProgMailer); 12384214Seric (void) fclose(f); 12394214Seric (void) fflush(stdout); 12404417Seric 12416887Seric /* reset ISUID & ISGID bits for paranoid systems */ 12424621Seric (void) chmod(filename, (int) stb.st_mode); 12434214Seric exit(EX_OK); 12444315Seric /*NOTREACHED*/ 12454214Seric } 12464214Seric else 12474214Seric { 12484214Seric /* parent -- wait for exit status */ 12499370Seric int st; 12504214Seric 12519370Seric st = waitfor(pid); 12529370Seric if ((st & 0377) != 0) 12539370Seric return (EX_UNAVAILABLE); 12549370Seric else 12559370Seric return ((st >> 8) & 0377); 12564214Seric } 1257294Seric } 12584550Seric /* 12594550Seric ** SENDALL -- actually send all the messages. 12604550Seric ** 12614550Seric ** Parameters: 12627043Seric ** e -- the envelope to send. 126314874Seric ** mode -- the delivery mode to use. If SM_DEFAULT, use 126414874Seric ** the current SendMode. 12654550Seric ** 12664550Seric ** Returns: 12674550Seric ** none. 12684550Seric ** 12694550Seric ** Side Effects: 12704550Seric ** Scans the send lists and sends everything it finds. 12717043Seric ** Delivers any appropriate error messages. 12729275Seric ** If we are running in a non-interactive mode, takes the 12739275Seric ** appropriate action. 12744550Seric */ 12754550Seric 12769275Seric sendall(e, mode) 12777043Seric ENVELOPE *e; 12789275Seric char mode; 12794550Seric { 12805008Seric register ADDRESS *q; 12817779Seric bool oldverbose; 12829275Seric int pid; 12834550Seric 128414874Seric /* determine actual delivery mode */ 128514874Seric if (mode == SM_DEFAULT) 128614874Seric { 128724941Seric extern bool shouldqueue(); 128814874Seric 128924941Seric if (shouldqueue(e->e_msgpriority)) 129014874Seric mode = SM_QUEUE; 129114874Seric else 129214874Seric mode = SendMode; 129314874Seric } 129414874Seric 12959370Seric #ifdef DEBUG 12968248Seric if (tTd(13, 1)) 12975032Seric { 12989275Seric printf("\nSENDALL: mode %c, sendqueue:\n", mode); 12997043Seric printaddr(e->e_sendqueue, TRUE); 13005032Seric } 13019370Seric #endif DEBUG 13025008Seric 13037043Seric /* 13049275Seric ** Do any preprocessing necessary for the mode we are running. 13059370Seric ** Check to make sure the hop count is reasonable. 13069370Seric ** Delete sends to the sender in mailing lists. 13077043Seric */ 13087043Seric 13099370Seric CurEnv = e; 13109370Seric 13119370Seric if (e->e_hopcount > MAXHOP) 13129275Seric { 13139370Seric syserr("sendall: too many hops (%d max)", MAXHOP); 13149370Seric return; 13159370Seric } 13169275Seric 13179370Seric if (!MeToo) 13189370Seric { 131912611Seric extern ADDRESS *recipient(); 132012611Seric 13219370Seric e->e_from.q_flags |= QDONTSEND; 132212611Seric (void) recipient(&e->e_from, &e->e_sendqueue); 13239275Seric } 13249370Seric 13259370Seric # ifdef QUEUE 13269335Seric if ((mode == SM_QUEUE || mode == SM_FORK || 13279335Seric (mode != SM_VERIFY && SuperSafe)) && 13289335Seric !bitset(EF_INQUEUE, e->e_flags)) 13299370Seric queueup(e, TRUE, mode == SM_QUEUE); 13309275Seric #endif QUEUE 13319275Seric 13327779Seric oldverbose = Verbose; 13339275Seric switch (mode) 13349275Seric { 13359275Seric case SM_VERIFY: 13367779Seric Verbose = TRUE; 13379275Seric break; 13389275Seric 13399275Seric case SM_QUEUE: 13409335Seric e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; 13419275Seric return; 13429275Seric 13439275Seric case SM_FORK: 13449538Seric if (e->e_xfp != NULL) 13459538Seric (void) fflush(e->e_xfp); 13469275Seric pid = fork(); 13479275Seric if (pid < 0) 13489275Seric { 13499275Seric mode = SM_DELIVER; 13509275Seric break; 13519275Seric } 13529275Seric else if (pid > 0) 13539293Seric { 13549293Seric /* be sure we leave the temp files to our child */ 13559335Seric e->e_id = e->e_df = NULL; 13569275Seric return; 13579293Seric } 13589275Seric 13599275Seric /* double fork to avoid zombies */ 13609275Seric if (fork() > 0) 13619275Seric exit(EX_OK); 13629275Seric 13639293Seric /* be sure we are immune from the terminal */ 136410133Seric disconnect(FALSE); 13659293Seric 13669275Seric break; 13679275Seric } 13689275Seric 13699275Seric /* 13709275Seric ** Run through the list and send everything. 13719275Seric */ 13729275Seric 13737043Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 13744550Seric { 13759275Seric if (mode == SM_VERIFY) 13764550Seric { 13779293Seric e->e_to = q->q_paddr; 13785008Seric if (!bitset(QDONTSEND|QBADADDR, q->q_flags)) 13797052Seric message(Arpa_Info, "deliverable"); 13804550Seric } 13815008Seric else 13829370Seric (void) deliver(e, q); 13834550Seric } 13847779Seric Verbose = oldverbose; 13857043Seric 13867043Seric /* 13877043Seric ** Now run through and check for errors. 13887043Seric */ 13897043Seric 13909275Seric if (mode == SM_VERIFY) 13917043Seric return; 13927043Seric 13937043Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 13947043Seric { 13957043Seric register ADDRESS *qq; 13967043Seric 13978248Seric # ifdef DEBUG 13988248Seric if (tTd(13, 3)) 13998248Seric { 14008248Seric printf("Checking "); 14018248Seric printaddr(q, FALSE); 14028248Seric } 14038248Seric # endif DEBUG 14048248Seric 14059335Seric /* only send errors if the message failed */ 14069335Seric if (!bitset(QBADADDR, q->q_flags)) 14079335Seric continue; 14087043Seric 14097043Seric /* we have an address that failed -- find the parent */ 14107043Seric for (qq = q; qq != NULL; qq = qq->q_alias) 14117043Seric { 14127043Seric char obuf[MAXNAME + 6]; 14137043Seric extern char *aliaslookup(); 14147043Seric 14157043Seric /* we can only have owners for local addresses */ 141610682Seric if (!bitnset(M_LOCAL, qq->q_mailer->m_flags)) 14177043Seric continue; 14187043Seric 14197043Seric /* see if the owner list exists */ 14207043Seric (void) strcpy(obuf, "owner-"); 14217047Seric if (strncmp(qq->q_user, "owner-", 6) == 0) 14227047Seric (void) strcat(obuf, "owner"); 14237047Seric else 14247047Seric (void) strcat(obuf, qq->q_user); 14257043Seric if (aliaslookup(obuf) == NULL) 14267043Seric continue; 14277043Seric 14288248Seric # ifdef DEBUG 14298248Seric if (tTd(13, 4)) 14308248Seric printf("Errors to %s\n", obuf); 14318248Seric # endif DEBUG 14328248Seric 14337043Seric /* owner list exists -- add it to the error queue */ 14349615Seric sendtolist(obuf, (ADDRESS *) NULL, &e->e_errorqueue); 143516883Seric ErrorMode = EM_MAIL; 14367043Seric break; 14377043Seric } 14387043Seric 14397043Seric /* if we did not find an owner, send to the sender */ 14408426Seric if (qq == NULL && bitset(QBADADDR, q->q_flags)) 14419615Seric sendtolist(e->e_from.q_paddr, qq, &e->e_errorqueue); 14427043Seric } 14439275Seric 14449275Seric if (mode == SM_FORK) 14459275Seric finis(); 14464550Seric } 1447