122701Sdist /* 234920Sbostic * Copyright (c) 1983 Eric P. Allman 362523Sbostic * Copyright (c) 1988, 1993 462523Sbostic * The Regents of the University of California. All rights reserved. 533728Sbostic * 642825Sbostic * %sccs.include.redist.c% 733728Sbostic */ 822701Sdist 922701Sdist #ifndef lint 10*64145Seric static char sccsid[] = "@(#)deliver.c 8.11 (Berkeley) 08/08/93"; 1133728Sbostic #endif /* not lint */ 1222701Sdist 1340961Sbostic #include "sendmail.h" 1433931Sbostic #include <netdb.h> 1533931Sbostic #include <errno.h> 1635651Seric #ifdef NAMED_BIND 1734022Sbostic #include <arpa/nameser.h> 1834022Sbostic #include <resolv.h> 1963753Seric 2063753Seric extern int h_errno; 2135651Seric #endif 22294Seric 23294Seric /* 2458820Seric ** SENDALL -- actually send all the messages. 2558820Seric ** 2658820Seric ** Parameters: 2758820Seric ** e -- the envelope to send. 2858820Seric ** mode -- the delivery mode to use. If SM_DEFAULT, use 2958820Seric ** the current e->e_sendmode. 3058820Seric ** 3158820Seric ** Returns: 3258820Seric ** none. 3358820Seric ** 3458820Seric ** Side Effects: 3558820Seric ** Scans the send lists and sends everything it finds. 3658820Seric ** Delivers any appropriate error messages. 3758820Seric ** If we are running in a non-interactive mode, takes the 3858820Seric ** appropriate action. 3958820Seric */ 4058820Seric 4158820Seric sendall(e, mode) 4258820Seric ENVELOPE *e; 4358820Seric char mode; 4458820Seric { 4558820Seric register ADDRESS *q; 4658820Seric char *owner; 4758820Seric int otherowners; 4858820Seric register ENVELOPE *ee; 4958820Seric ENVELOPE *splitenv = NULL; 5058929Seric bool announcequeueup; 5158820Seric 5263839Seric /* 5363839Seric ** If we have had global, fatal errors, don't bother sending 5463839Seric ** the message at all if we are in SMTP mode. Local errors 5563839Seric ** (e.g., a single address failing) will still cause the other 5663839Seric ** addresses to be sent. 5763839Seric */ 5863839Seric 5963839Seric if (bitset(EF_FATALERRS, e->e_flags) && OpMode == MD_SMTP) 6061092Seric { 6161092Seric e->e_flags |= EF_CLRQUEUE; 6261092Seric return; 6361092Seric } 6461092Seric 6558820Seric /* determine actual delivery mode */ 6658820Seric if (mode == SM_DEFAULT) 6758820Seric { 6858820Seric mode = e->e_sendmode; 6958820Seric if (mode != SM_VERIFY && 7058820Seric shouldqueue(e->e_msgpriority, e->e_ctime)) 7158820Seric mode = SM_QUEUE; 7258929Seric announcequeueup = mode == SM_QUEUE; 7358820Seric } 7458929Seric else 7558929Seric announcequeueup = FALSE; 7658820Seric 7758820Seric if (tTd(13, 1)) 7858820Seric { 7958820Seric printf("\nSENDALL: mode %c, e_from ", mode); 8058820Seric printaddr(&e->e_from, FALSE); 8158820Seric printf("sendqueue:\n"); 8258820Seric printaddr(e->e_sendqueue, TRUE); 8358820Seric } 8458820Seric 8558820Seric /* 8658820Seric ** Do any preprocessing necessary for the mode we are running. 8758820Seric ** Check to make sure the hop count is reasonable. 8858820Seric ** Delete sends to the sender in mailing lists. 8958820Seric */ 9058820Seric 9158820Seric CurEnv = e; 9258820Seric 9358820Seric if (e->e_hopcount > MaxHopCount) 9458820Seric { 9558820Seric errno = 0; 9658820Seric syserr("554 too many hops %d (%d max): from %s, to %s", 9758820Seric e->e_hopcount, MaxHopCount, e->e_from.q_paddr, 9858820Seric e->e_sendqueue->q_paddr); 9958820Seric return; 10058820Seric } 10158820Seric 10259435Seric /* 10359435Seric ** Do sender deletion. 10459435Seric ** 10559435Seric ** If the sender has the QQUEUEUP flag set, skip this. 10659435Seric ** This can happen if the name server is hosed when you 10759435Seric ** are trying to send mail. The result is that the sender 10859435Seric ** is instantiated in the queue as a recipient. 10959435Seric */ 11059435Seric 11164118Seric if (!bitset(EF_METOO, e->e_flags) && 11264118Seric !bitset(QQUEUEUP, e->e_from.q_flags)) 11358820Seric { 11458820Seric if (tTd(13, 5)) 11558820Seric { 11658820Seric printf("sendall: QDONTSEND "); 11758820Seric printaddr(&e->e_from, FALSE); 11858820Seric } 11958820Seric e->e_from.q_flags |= QDONTSEND; 12058820Seric (void) recipient(&e->e_from, &e->e_sendqueue, e); 12158820Seric } 12258820Seric 12358820Seric /* 12458820Seric ** Handle alias owners. 12558820Seric ** 12658820Seric ** We scan up the q_alias chain looking for owners. 12758820Seric ** We discard owners that are the same as the return path. 12858820Seric */ 12958820Seric 13058820Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 13158820Seric { 13258820Seric register struct address *a; 13358820Seric 13458820Seric for (a = q; a != NULL && a->q_owner == NULL; a = a->q_alias) 13558820Seric continue; 13658820Seric if (a != NULL) 13758820Seric q->q_owner = a->q_owner; 13858820Seric 13958820Seric if (q->q_owner != NULL && 14058820Seric !bitset(QDONTSEND, q->q_flags) && 14158820Seric strcmp(q->q_owner, e->e_from.q_paddr) == 0) 14258820Seric q->q_owner = NULL; 14358820Seric } 14458820Seric 14558820Seric owner = ""; 14658820Seric otherowners = 1; 14758820Seric while (owner != NULL && otherowners > 0) 14858820Seric { 14958820Seric owner = NULL; 15058820Seric otherowners = 0; 15158820Seric 15258820Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 15358820Seric { 15458820Seric if (bitset(QDONTSEND, q->q_flags)) 15558820Seric continue; 15658820Seric 15758820Seric if (q->q_owner != NULL) 15858820Seric { 15958820Seric if (owner == NULL) 16058820Seric owner = q->q_owner; 16158820Seric else if (owner != q->q_owner) 16258820Seric { 16358820Seric if (strcmp(owner, q->q_owner) == 0) 16458820Seric { 16558820Seric /* make future comparisons cheap */ 16658820Seric q->q_owner = owner; 16758820Seric } 16858820Seric else 16958820Seric { 17058820Seric otherowners++; 17158820Seric } 17258820Seric owner = q->q_owner; 17358820Seric } 17458820Seric } 17558820Seric else 17658820Seric { 17758820Seric otherowners++; 17858820Seric } 17958820Seric } 18058820Seric 18158820Seric if (owner != NULL && otherowners > 0) 18258820Seric { 18358820Seric extern HDR *copyheader(); 18458820Seric extern ADDRESS *copyqueue(); 18558820Seric 18658820Seric /* 18758820Seric ** Split this envelope into two. 18858820Seric */ 18958820Seric 19058820Seric ee = (ENVELOPE *) xalloc(sizeof(ENVELOPE)); 19158820Seric *ee = *e; 19258820Seric ee->e_id = NULL; 19358820Seric (void) queuename(ee, '\0'); 19458820Seric 19558820Seric if (tTd(13, 1)) 19658820Seric printf("sendall: split %s into %s\n", 19758820Seric e->e_id, ee->e_id); 19858820Seric 19958820Seric ee->e_header = copyheader(e->e_header); 20058820Seric ee->e_sendqueue = copyqueue(e->e_sendqueue); 20158820Seric ee->e_errorqueue = copyqueue(e->e_errorqueue); 20258916Seric ee->e_flags = e->e_flags & ~(EF_INQUEUE|EF_CLRQUEUE|EF_FATALERRS); 20358820Seric setsender(owner, ee, NULL, TRUE); 20458820Seric if (tTd(13, 5)) 20558820Seric { 20658820Seric printf("sendall(split): QDONTSEND "); 20758820Seric printaddr(&ee->e_from, FALSE); 20858820Seric } 20958820Seric ee->e_from.q_flags |= QDONTSEND; 21058820Seric ee->e_dfp = NULL; 21158820Seric ee->e_xfp = NULL; 21258820Seric ee->e_lockfp = NULL; 21358820Seric ee->e_df = NULL; 21458820Seric ee->e_errormode = EM_MAIL; 21558820Seric ee->e_sibling = splitenv; 21658820Seric splitenv = ee; 21758820Seric 21858820Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 21958820Seric if (q->q_owner == owner) 22058820Seric q->q_flags |= QDONTSEND; 22158820Seric for (q = ee->e_sendqueue; q != NULL; q = q->q_next) 22258820Seric if (q->q_owner != owner) 22358820Seric q->q_flags |= QDONTSEND; 22458820Seric 22558820Seric if (e->e_df != NULL && mode != SM_VERIFY) 22658820Seric { 22758820Seric ee->e_dfp = NULL; 22864086Seric ee->e_df = queuename(ee, 'd'); 22964086Seric ee->e_df = newstr(ee->e_df); 23058820Seric if (link(e->e_df, ee->e_df) < 0) 23158820Seric { 23258820Seric syserr("sendall: link(%s, %s)", 23358820Seric e->e_df, ee->e_df); 23458820Seric } 23558820Seric } 23658820Seric 23758820Seric if (mode != SM_VERIFY) 23858820Seric openxscript(ee); 23958820Seric #ifdef LOG 24058820Seric if (LogLevel > 4) 24158820Seric syslog(LOG_INFO, "%s: clone %s", 24258820Seric ee->e_id, e->e_id); 24358820Seric #endif 24458820Seric } 24558820Seric } 24658820Seric 24758820Seric if (owner != NULL) 24858820Seric { 24958820Seric setsender(owner, e, NULL, TRUE); 25058820Seric if (tTd(13, 5)) 25158820Seric { 25258820Seric printf("sendall(owner): QDONTSEND "); 25358820Seric printaddr(&e->e_from, FALSE); 25458820Seric } 25558820Seric e->e_from.q_flags |= QDONTSEND; 25658820Seric e->e_errormode = EM_MAIL; 25758820Seric } 25858820Seric 25958916Seric # ifdef QUEUE 26058916Seric if ((mode == SM_QUEUE || mode == SM_FORK || 26158916Seric (mode != SM_VERIFY && SuperSafe)) && 26258916Seric !bitset(EF_INQUEUE, e->e_flags)) 26358916Seric { 26458916Seric /* be sure everything is instantiated in the queue */ 26558929Seric queueup(e, TRUE, announcequeueup); 26658916Seric for (ee = splitenv; ee != NULL; ee = ee->e_sibling) 26758929Seric queueup(ee, TRUE, announcequeueup); 26858916Seric } 26958916Seric #endif /* QUEUE */ 27058916Seric 27158820Seric if (splitenv != NULL) 27258820Seric { 27358820Seric if (tTd(13, 1)) 27458820Seric { 27558820Seric printf("\nsendall: Split queue; remaining queue:\n"); 27658820Seric printaddr(e->e_sendqueue, TRUE); 27758820Seric } 27858820Seric 27958820Seric for (ee = splitenv; ee != NULL; ee = ee->e_sibling) 28058820Seric { 28158820Seric CurEnv = ee; 28258820Seric sendenvelope(ee, mode); 28358820Seric } 28458820Seric 28558820Seric CurEnv = e; 28658820Seric } 28758820Seric sendenvelope(e, mode); 28858820Seric 28958820Seric for (; splitenv != NULL; splitenv = splitenv->e_sibling) 29058820Seric dropenvelope(splitenv); 29158820Seric } 29258820Seric 29358820Seric sendenvelope(e, mode) 29458820Seric register ENVELOPE *e; 29558820Seric char mode; 29658820Seric { 29758916Seric bool oldverbose; 29858916Seric int pid; 29958820Seric register ADDRESS *q; 30064035Seric #ifndef HASFLOCK 30158916Seric struct flock lfd; 30258916Seric #endif 30358820Seric 30463839Seric /* 30563839Seric ** If we have had global, fatal errors, don't bother sending 30663839Seric ** the message at all if we are in SMTP mode. Local errors 30763839Seric ** (e.g., a single address failing) will still cause the other 30863839Seric ** addresses to be sent. 30963839Seric */ 31063839Seric 31163839Seric if (bitset(EF_FATALERRS, e->e_flags) && OpMode == MD_SMTP) 31263839Seric { 31363839Seric e->e_flags |= EF_CLRQUEUE; 31463839Seric return; 31563839Seric } 31663839Seric 31758916Seric oldverbose = Verbose; 31858916Seric switch (mode) 31958916Seric { 32058916Seric case SM_VERIFY: 32158916Seric Verbose = TRUE; 32258916Seric break; 32358916Seric 32458916Seric case SM_QUEUE: 32558916Seric queueonly: 32658916Seric e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; 32758916Seric return; 32858916Seric 32958916Seric case SM_FORK: 33058916Seric if (e->e_xfp != NULL) 33158916Seric (void) fflush(e->e_xfp); 33258916Seric 33364035Seric # ifndef HASFLOCK 33458916Seric /* 33564035Seric ** Since fcntl lockin has the interesting semantic that 33664035Seric ** the lock is lost when we fork, we have to risk losing 33758916Seric ** the lock here by closing before the fork, and then 33858916Seric ** trying to get it back in the child. 33958916Seric */ 34058916Seric 34158916Seric if (e->e_lockfp != NULL) 34258916Seric { 34358916Seric (void) xfclose(e->e_lockfp, "sendenvelope", "lockfp"); 34458916Seric e->e_lockfp = NULL; 34558916Seric } 34664035Seric # endif /* HASFLOCK */ 34758916Seric 34858916Seric pid = fork(); 34958916Seric if (pid < 0) 35058916Seric { 35158916Seric goto queueonly; 35258916Seric } 35358916Seric else if (pid > 0) 35458916Seric { 35558916Seric /* be sure we leave the temp files to our child */ 35658916Seric e->e_id = e->e_df = NULL; 35764035Seric # ifdef HASFLOCK 35858916Seric if (e->e_lockfp != NULL) 35958916Seric { 36058916Seric (void) xfclose(e->e_lockfp, "sendenvelope", "lockfp"); 36158916Seric e->e_lockfp = NULL; 36258916Seric } 36358916Seric # endif 36458916Seric 36558916Seric /* close any random open files in the envelope */ 36658916Seric if (e->e_dfp != NULL) 36758916Seric { 36858916Seric (void) xfclose(e->e_dfp, "sendenvelope", "dfp"); 36958916Seric e->e_dfp = NULL; 37058916Seric } 37158916Seric if (e->e_xfp != NULL) 37258916Seric { 37358916Seric (void) xfclose(e->e_xfp, "sendenvelope", "xfp"); 37458916Seric e->e_xfp = NULL; 37558916Seric } 37658916Seric return; 37758916Seric } 37858916Seric 37958916Seric /* double fork to avoid zombies */ 38058916Seric if (fork() > 0) 38158916Seric exit(EX_OK); 38258916Seric 38358916Seric /* be sure we are immune from the terminal */ 38463839Seric disconnect(1, e); 38558916Seric 38664035Seric # ifndef HASFLOCK 38758916Seric /* 38858916Seric ** Now try to get our lock back. 38958916Seric */ 39058916Seric 39158916Seric lfd.l_type = F_WRLCK; 39258916Seric lfd.l_whence = lfd.l_start = lfd.l_len = 0; 39358916Seric e->e_lockfp = fopen(queuename(e, 'q'), "r+"); 39458916Seric if (e->e_lockfp == NULL || 39558916Seric fcntl(fileno(e->e_lockfp), F_SETLK, &lfd) < 0) 39658916Seric { 39758916Seric /* oops.... lost it */ 39858916Seric if (tTd(13, 1)) 39958916Seric printf("sendenvelope: %s lost lock: lockfp=%x, %s\n", 40058916Seric e->e_id, e->e_lockfp, errstring(errno)); 40158916Seric 40258916Seric # ifdef LOG 40358916Seric if (LogLevel > 29) 40458916Seric syslog(LOG_NOTICE, "%s: lost lock: %m", 40558916Seric e->e_id); 40658916Seric # endif /* LOG */ 40758916Seric exit(EX_OK); 40858916Seric } 40964035Seric # endif /* HASFLOCK */ 41058916Seric 41158916Seric /* 41258916Seric ** Close any cached connections. 41358916Seric ** 41458916Seric ** We don't send the QUIT protocol because the parent 41558916Seric ** still knows about the connection. 41658916Seric ** 41758916Seric ** This should only happen when delivering an error 41858916Seric ** message. 41958916Seric */ 42058916Seric 42158916Seric mci_flush(FALSE, NULL); 42258916Seric 42358916Seric break; 42458916Seric } 42558916Seric 42658820Seric /* 42758820Seric ** Run through the list and send everything. 42863965Seric ** 42963965Seric ** Set EF_GLOBALERRS so that error messages during delivery 43063965Seric ** result in returned mail. 43158820Seric */ 43258820Seric 43358820Seric e->e_nsent = 0; 43463965Seric e->e_flags |= EF_GLOBALERRS; 43558820Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 43658820Seric { 43758820Seric if (mode == SM_VERIFY) 43858820Seric { 43958820Seric e->e_to = q->q_paddr; 44058820Seric if (!bitset(QDONTSEND|QBADADDR, q->q_flags)) 44160173Seric { 44260173Seric message("deliverable: mailer %s, host %s, user %s", 44360173Seric q->q_mailer->m_name, 44460173Seric q->q_host, 44560173Seric q->q_user); 44660173Seric } 44758820Seric } 44858820Seric else if (!bitset(QDONTSEND|QBADADDR, q->q_flags)) 44958820Seric { 45058820Seric # ifdef QUEUE 45158820Seric /* 45258820Seric ** Checkpoint the send list every few addresses 45358820Seric */ 45458820Seric 45558820Seric if (e->e_nsent >= CheckpointInterval) 45658820Seric { 45758820Seric queueup(e, TRUE, FALSE); 45858820Seric e->e_nsent = 0; 45958820Seric } 46058820Seric # endif /* QUEUE */ 46158820Seric (void) deliver(e, q); 46258820Seric } 46358820Seric } 46458820Seric Verbose = oldverbose; 46558820Seric 46658820Seric if (mode == SM_FORK) 46758820Seric finis(); 46858820Seric } 46958820Seric /* 47058820Seric ** DOFORK -- do a fork, retrying a couple of times on failure. 47158820Seric ** 47258820Seric ** This MUST be a macro, since after a vfork we are running 47358820Seric ** two processes on the same stack!!! 47458820Seric ** 47558820Seric ** Parameters: 47658820Seric ** none. 47758820Seric ** 47858820Seric ** Returns: 47958820Seric ** From a macro??? You've got to be kidding! 48058820Seric ** 48158820Seric ** Side Effects: 48258820Seric ** Modifies the ==> LOCAL <== variable 'pid', leaving: 48358820Seric ** pid of child in parent, zero in child. 48458820Seric ** -1 on unrecoverable error. 48558820Seric ** 48658820Seric ** Notes: 48758820Seric ** I'm awfully sorry this looks so awful. That's 48858820Seric ** vfork for you..... 48958820Seric */ 49058820Seric 49158820Seric # define NFORKTRIES 5 49258820Seric 49358820Seric # ifndef FORK 49458820Seric # define FORK fork 49558820Seric # endif 49658820Seric 49758820Seric # define DOFORK(fORKfN) \ 49858820Seric {\ 49958820Seric register int i;\ 50058820Seric \ 50158820Seric for (i = NFORKTRIES; --i >= 0; )\ 50258820Seric {\ 50358820Seric pid = fORKfN();\ 50458820Seric if (pid >= 0)\ 50558820Seric break;\ 50658820Seric if (i > 0)\ 50758820Seric sleep((unsigned) NFORKTRIES - i);\ 50858820Seric }\ 50958820Seric } 51058820Seric /* 51158820Seric ** DOFORK -- simple fork interface to DOFORK. 51258820Seric ** 51358820Seric ** Parameters: 51458820Seric ** none. 51558820Seric ** 51658820Seric ** Returns: 51758820Seric ** pid of child in parent. 51858820Seric ** zero in child. 51958820Seric ** -1 on error. 52058820Seric ** 52158820Seric ** Side Effects: 52258820Seric ** returns twice, once in parent and once in child. 52358820Seric */ 52458820Seric 52558820Seric dofork() 52658820Seric { 52758820Seric register int pid; 52858820Seric 52958820Seric DOFORK(fork); 53058820Seric return (pid); 53158820Seric } 53258820Seric /* 5334315Seric ** DELIVER -- Deliver a message to a list of addresses. 534294Seric ** 5354315Seric ** This routine delivers to everyone on the same host as the 5364315Seric ** user on the head of the list. It is clever about mailers 5374315Seric ** that don't handle multiple users. It is NOT guaranteed 5384315Seric ** that it will deliver to all these addresses however -- so 5394315Seric ** deliver should be called once for each address on the 5404315Seric ** list. 5414315Seric ** 542294Seric ** Parameters: 5439370Seric ** e -- the envelope to deliver. 5444621Seric ** firstto -- head of the address list to deliver to. 545294Seric ** 546294Seric ** Returns: 547294Seric ** zero -- successfully delivered. 548294Seric ** else -- some failure, see ExitStat for more info. 549294Seric ** 550294Seric ** Side Effects: 551294Seric ** The standard input is passed off to someone. 552294Seric */ 553294Seric 5549370Seric deliver(e, firstto) 5559370Seric register ENVELOPE *e; 5564621Seric ADDRESS *firstto; 557294Seric { 5584452Seric char *host; /* host being sent to */ 5594452Seric char *user; /* user being sent to */ 560294Seric char **pvp; 5613233Seric register char **mvp; 5623233Seric register char *p; 56310306Seric register MAILER *m; /* mailer for this recipient */ 5644397Seric ADDRESS *ctladdr; 56554967Seric register MCI *mci; 5664621Seric register ADDRESS *to = firstto; 5674863Seric bool clever = FALSE; /* running user smtp to this mailer */ 5685032Seric ADDRESS *tochain = NULL; /* chain of users in this mailer call */ 56951951Seric int rcode; /* response code */ 57057454Seric char *firstsig; /* signature of firstto */ 57158820Seric int pid; 57258820Seric char *curhost; 57358820Seric int mpvect[2]; 57458820Seric int rpvect[2]; 57510306Seric char *pv[MAXPV+1]; 57658704Seric char tobuf[TOBUFSIZE]; /* text line of to people */ 57710306Seric char buf[MAXNAME]; 57851951Seric char rpathbuf[MAXNAME]; /* translated return path */ 57957441Seric extern int checkcompat(); 58058820Seric extern FILE *fdopen(); 581294Seric 5824488Seric errno = 0; 58358680Seric if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags)) 5843233Seric return (0); 585294Seric 58635651Seric #ifdef NAMED_BIND 58734022Sbostic /* unless interactive, try twice, over a minute */ 58834022Sbostic if (OpMode == MD_DAEMON || OpMode == MD_SMTP) { 58934022Sbostic _res.retrans = 30; 59034022Sbostic _res.retry = 2; 59134022Sbostic } 59236788Sbostic #endif 59334022Sbostic 5946974Seric m = to->q_mailer; 5956974Seric host = to->q_host; 59658803Seric CurEnv = e; /* just in case */ 59759044Seric e->e_statmsg = NULL; 5986974Seric 5997672Seric if (tTd(10, 1)) 6003233Seric printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n", 6016974Seric m->m_mno, host, to->q_user); 602294Seric 603294Seric /* 6045903Seric ** If this mailer is expensive, and if we don't want to make 6055903Seric ** connections now, just mark these addresses and return. 6065903Seric ** This is useful if we want to batch connections to 6075903Seric ** reduce load. This will cause the messages to be 6085903Seric ** queued up, and a daemon will come along to send the 6095903Seric ** messages later. 6105903Seric ** This should be on a per-mailer basis. 6115903Seric */ 6125903Seric 61358737Seric if (NoConnect && !bitset(EF_QUEUERUN, e->e_flags) && 61458737Seric bitnset(M_EXPENSIVE, m->m_flags) && !Verbose) 6155903Seric { 6165903Seric for (; to != NULL; to = to->q_next) 6178431Seric { 61858680Seric if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags) || 61958247Seric to->q_mailer != m) 6208431Seric continue; 62163853Seric to->q_flags |= QQUEUEUP; 6229370Seric e->e_to = to->q_paddr; 62358151Seric message("queued"); 62458020Seric if (LogLevel > 8) 62558337Seric logdelivery(m, NULL, "queued", e); 6268431Seric } 6279370Seric e->e_to = NULL; 6285903Seric return (0); 6295903Seric } 6305903Seric 6315903Seric /* 6323233Seric ** Do initial argv setup. 6333233Seric ** Insert the mailer name. Notice that $x expansion is 6343233Seric ** NOT done on the mailer name. Then, if the mailer has 6353233Seric ** a picky -f flag, we insert it as appropriate. This 6363233Seric ** code does not check for 'pv' overflow; this places a 6373233Seric ** manifest lower limit of 4 for MAXPV. 6388062Seric ** The from address rewrite is expected to make 6398062Seric ** the address relative to the other end. 6402968Seric */ 6412968Seric 6424452Seric /* rewrite from address, using rewriting rules */ 64359163Seric rcode = EX_OK; 64459163Seric (void) strcpy(rpathbuf, remotename(e->e_from.q_paddr, m, 64559163Seric RF_SENDERADDR|RF_CANONICAL, 64659163Seric &rcode, e)); 64758680Seric define('g', rpathbuf, e); /* translated return path */ 6489370Seric define('h', host, e); /* to host */ 6493233Seric Errors = 0; 6503233Seric pvp = pv; 6513233Seric *pvp++ = m->m_argv[0]; 6522968Seric 6533233Seric /* insert -f or -r flag as appropriate */ 65410682Seric if (FromFlag && (bitnset(M_FOPT, m->m_flags) || bitnset(M_ROPT, m->m_flags))) 6553233Seric { 65610682Seric if (bitnset(M_FOPT, m->m_flags)) 6573233Seric *pvp++ = "-f"; 6583233Seric else 6593233Seric *pvp++ = "-r"; 66051951Seric *pvp++ = newstr(rpathbuf); 6613233Seric } 662294Seric 663294Seric /* 6643233Seric ** Append the other fixed parts of the argv. These run 6653233Seric ** up to the first entry containing "$u". There can only 6663233Seric ** be one of these, and there are only a few more slots 6673233Seric ** in the pv after it. 668294Seric */ 669294Seric 6703233Seric for (mvp = m->m_argv; (p = *++mvp) != NULL; ) 671294Seric { 67258050Seric /* can't use strchr here because of sign extension problems */ 67358050Seric while (*p != '\0') 67458050Seric { 67558050Seric if ((*p++ & 0377) == MACROEXPAND) 67658050Seric { 67758050Seric if (*p == 'u') 67858050Seric break; 67958050Seric } 68058050Seric } 68158050Seric 68258050Seric if (*p != '\0') 6833233Seric break; 6843233Seric 6853233Seric /* this entry is safe -- go ahead and process it */ 6869370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 6873233Seric *pvp++ = newstr(buf); 6883233Seric if (pvp >= &pv[MAXPV - 3]) 6893233Seric { 69058151Seric syserr("554 Too many parameters to %s before $u", pv[0]); 6913233Seric return (-1); 6923233Seric } 693294Seric } 6944863Seric 6956038Seric /* 6966038Seric ** If we have no substitution for the user name in the argument 6976038Seric ** list, we know that we must supply the names otherwise -- and 6986038Seric ** SMTP is the answer!! 6996038Seric */ 7006038Seric 7013233Seric if (*mvp == NULL) 7024863Seric { 7034863Seric /* running SMTP */ 7045179Seric # ifdef SMTP 7054863Seric clever = TRUE; 7064863Seric *pvp = NULL; 70756795Seric # else /* SMTP */ 7086038Seric /* oops! we don't implement SMTP */ 70958151Seric syserr("554 SMTP style mailer"); 7105179Seric return (EX_SOFTWARE); 71156795Seric # endif /* SMTP */ 7124863Seric } 713294Seric 714294Seric /* 7153233Seric ** At this point *mvp points to the argument with $u. We 7163233Seric ** run through our address list and append all the addresses 7173233Seric ** we can. If we run out of space, do not fret! We can 7183233Seric ** always send another copy later. 719294Seric */ 720294Seric 7213233Seric tobuf[0] = '\0'; 7229370Seric e->e_to = tobuf; 7234397Seric ctladdr = NULL; 72457454Seric firstsig = hostsignature(firstto->q_mailer, firstto->q_host, e); 7253233Seric for (; to != NULL; to = to->q_next) 726294Seric { 7273233Seric /* avoid sending multiple recipients to dumb mailers */ 72810682Seric if (tobuf[0] != '\0' && !bitnset(M_MUSER, m->m_flags)) 7293233Seric break; 7303233Seric 7313233Seric /* if already sent or not for this host, don't send */ 73258680Seric if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags) || 73357454Seric to->q_mailer != firstto->q_mailer || 73457454Seric strcmp(hostsignature(to->q_mailer, to->q_host, e), firstsig) != 0) 7353233Seric continue; 7364397Seric 7378225Seric /* avoid overflowing tobuf */ 73842462Sbostic if (sizeof tobuf < (strlen(to->q_paddr) + strlen(tobuf) + 2)) 7398225Seric break; 7408225Seric 7417672Seric if (tTd(10, 1)) 7425032Seric { 7435032Seric printf("\nsend to "); 7445032Seric printaddr(to, FALSE); 7455032Seric } 7465032Seric 7474397Seric /* compute effective uid/gid when sending */ 7484596Seric if (to->q_mailer == ProgMailer) 7494397Seric ctladdr = getctladdr(to); 7504397Seric 7513233Seric user = to->q_user; 7529370Seric e->e_to = to->q_paddr; 75357731Seric if (tTd(10, 5)) 75457731Seric { 75557731Seric printf("deliver: QDONTSEND "); 75657731Seric printaddr(to, FALSE); 75757731Seric } 75858680Seric to->q_flags |= QDONTSEND; 7593233Seric 7603233Seric /* 7613233Seric ** Check to see that these people are allowed to 7623233Seric ** talk to each other. 7633233Seric */ 7643233Seric 76510699Seric if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize) 76610699Seric { 76729914Seric NoReturn = TRUE; 76858151Seric usrerr("552 Message is too large; %ld bytes max", m->m_maxsize); 76958337Seric giveresponse(EX_UNAVAILABLE, m, NULL, e); 77010699Seric continue; 77110699Seric } 77257441Seric rcode = checkcompat(to, e); 77357459Seric if (rcode != EX_OK) 774294Seric { 77563787Seric markfailure(e, to, rcode); 77658337Seric giveresponse(rcode, m, NULL, e); 7773233Seric continue; 778294Seric } 7793233Seric 7803233Seric /* 7814099Seric ** Strip quote bits from names if the mailer is dumb 7824099Seric ** about them. 7833233Seric */ 7843233Seric 78510682Seric if (bitnset(M_STRIPQ, m->m_flags)) 786294Seric { 78754983Seric stripquotes(user); 78854983Seric stripquotes(host); 7893233Seric } 7903233Seric 7919206Seric /* hack attack -- delivermail compatibility */ 7929206Seric if (m == ProgMailer && *user == '|') 7939206Seric user++; 7949206Seric 7953233Seric /* 7964161Seric ** If an error message has already been given, don't 7974161Seric ** bother to send to this address. 7984161Seric ** 7994161Seric ** >>>>>>>>>> This clause assumes that the local mailer 8004161Seric ** >> NOTE >> cannot do any further aliasing; that 8014161Seric ** >>>>>>>>>> function is subsumed by sendmail. 8024161Seric */ 8034161Seric 8047293Seric if (bitset(QBADADDR|QQUEUEUP, to->q_flags)) 8054161Seric continue; 8064161Seric 8074283Seric /* save statistics.... */ 8089370Seric markstats(e, to); 8094283Seric 8104161Seric /* 8113233Seric ** See if this user name is "special". 8123233Seric ** If the user name has a slash in it, assume that this 8136974Seric ** is a file -- send it off without further ado. Note 8146974Seric ** that this type of addresses is not processed along 8156974Seric ** with the others, so we fudge on the To person. 8163233Seric */ 8173233Seric 81857402Seric if (m == FileMailer) 8193233Seric { 82057402Seric rcode = mailfile(user, getctladdr(to), e); 82158337Seric giveresponse(rcode, m, NULL, e); 82257402Seric if (rcode == EX_OK) 82357402Seric to->q_flags |= QSENT; 82457402Seric continue; 825294Seric } 8263233Seric 8274315Seric /* 8284315Seric ** Address is verified -- add this user to mailer 8294315Seric ** argv, and add it to the print list of recipients. 8304315Seric */ 8314315Seric 8326059Seric /* link together the chain of recipients */ 8336272Seric to->q_tchain = tochain; 8346272Seric tochain = to; 8356059Seric 8363233Seric /* create list of users for error messages */ 8379388Seric (void) strcat(tobuf, ","); 8384082Seric (void) strcat(tobuf, to->q_paddr); 8399370Seric define('u', user, e); /* to user */ 8409370Seric define('z', to->q_home, e); /* user's home */ 8413233Seric 8424863Seric /* 8436059Seric ** Expand out this user into argument list. 8444863Seric */ 8454863Seric 8466059Seric if (!clever) 8473233Seric { 8489370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 8494863Seric *pvp++ = newstr(buf); 8504863Seric if (pvp >= &pv[MAXPV - 2]) 8514863Seric { 8524863Seric /* allow some space for trailing parms */ 8534863Seric break; 8544863Seric } 8554863Seric } 856294Seric } 857294Seric 8584067Seric /* see if any addresses still exist */ 8594067Seric if (tobuf[0] == '\0') 8604863Seric { 8619370Seric define('g', (char *) NULL, e); 8624067Seric return (0); 8634863Seric } 8644067Seric 8653233Seric /* print out messages as full list */ 8669388Seric e->e_to = tobuf + 1; 8673233Seric 868294Seric /* 8693233Seric ** Fill out any parameters after the $u parameter. 870294Seric */ 871294Seric 8724863Seric while (!clever && *++mvp != NULL) 873294Seric { 8749370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 8753233Seric *pvp++ = newstr(buf); 8763233Seric if (pvp >= &pv[MAXPV]) 87758151Seric syserr("554 deliver: pv overflow after $u for %s", pv[0]); 878294Seric } 8793233Seric *pvp++ = NULL; 880294Seric 881294Seric /* 882294Seric ** Call the mailer. 8832898Seric ** The argument vector gets built, pipes 884294Seric ** are created as necessary, and we fork & exec as 8852898Seric ** appropriate. 8864863Seric ** If we are running SMTP, we just need to clean up. 887294Seric */ 888294Seric 88958309Seric if (ctladdr == NULL && m != ProgMailer) 89041050Seric ctladdr = &e->e_from; 89135651Seric #ifdef NAMED_BIND 89251313Seric if (ConfigLevel < 2) 89351313Seric _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ 89435651Seric #endif 89554967Seric 8967672Seric if (tTd(11, 1)) 897294Seric { 8988178Seric printf("openmailer:"); 89958820Seric printav(pv); 900294Seric } 9014488Seric errno = 0; 9023233Seric 90325050Seric CurHostName = m->m_mailer; 90425050Seric 9056038Seric /* 9066038Seric ** Deal with the special case of mail handled through an IPC 9076038Seric ** connection. 9086038Seric ** In this case we don't actually fork. We must be 9096038Seric ** running SMTP for this to work. We will return a 9106038Seric ** zero pid to indicate that we are running IPC. 91111160Seric ** We also handle a debug version that just talks to stdin/out. 9126038Seric */ 9136038Seric 91458820Seric curhost = NULL; 91558820Seric 91611160Seric /* check for Local Person Communication -- not for mortals!!! */ 91711160Seric if (strcmp(m->m_mailer, "[LPC]") == 0) 91811160Seric { 91954967Seric mci = (MCI *) xalloc(sizeof *mci); 92054993Seric bzero((char *) mci, sizeof *mci); 92153738Seric mci->mci_in = stdin; 92253738Seric mci->mci_out = stdout; 92354967Seric mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN; 92453751Seric mci->mci_mailer = m; 92511160Seric } 92654967Seric else if (strcmp(m->m_mailer, "[IPC]") == 0 || 92754967Seric strcmp(m->m_mailer, "[TCP]") == 0) 9286038Seric { 92952107Seric #ifdef DAEMON 93057454Seric register int i; 9317285Seric register u_short port; 9326038Seric 93358820Seric CurHostName = pv[1]; 93458820Seric curhost = hostsignature(m, pv[1], e); 93554967Seric 93658479Seric if (curhost == NULL || curhost[0] == '\0') 93758479Seric { 93858479Seric syserr("null signature"); 93958820Seric rcode = EX_OSERR; 94058820Seric goto give_up; 94158479Seric } 94258479Seric 9436038Seric if (!clever) 94458479Seric { 94558151Seric syserr("554 non-clever IPC"); 94658820Seric rcode = EX_OSERR; 94758820Seric goto give_up; 94858479Seric } 94958820Seric if (pv[2] != NULL) 95058820Seric port = atoi(pv[2]); 9516632Seric else 9527285Seric port = 0; 95358820Seric tryhost: 95458820Seric mci = NULL; 95557454Seric while (*curhost != '\0') 95629433Sbloom { 95757454Seric register char *p; 95858664Seric static char hostbuf[MAXNAME]; 95957454Seric 96058820Seric mci = NULL; 96158820Seric 96257454Seric /* pull the next host from the signature */ 96357454Seric p = strchr(curhost, ':'); 96457454Seric if (p == NULL) 96557454Seric p = &curhost[strlen(curhost)]; 96657454Seric strncpy(hostbuf, curhost, p - curhost); 96757454Seric hostbuf[p - curhost] = '\0'; 96857454Seric if (*p != '\0') 96957454Seric p++; 97057454Seric curhost = p; 97157454Seric 97253738Seric /* see if we already know that this host is fried */ 97357454Seric CurHostName = hostbuf; 97457454Seric mci = mci_get(hostbuf, m); 97554967Seric if (mci->mci_state != MCIS_CLOSED) 97657387Seric { 97757387Seric if (tTd(11, 1)) 97857387Seric { 97957387Seric printf("openmailer: "); 98057387Seric mci_dump(mci); 98157387Seric } 98257943Seric CurHostName = mci->mci_host; 98358820Seric break; 98457387Seric } 98553751Seric mci->mci_mailer = m; 98654967Seric if (mci->mci_exitstat != EX_OK) 98754967Seric continue; 98854967Seric 98954967Seric /* try the connection */ 99057454Seric setproctitle("%s %s: %s", e->e_id, hostbuf, "user open"); 99158151Seric message("Connecting to %s (%s)...", 99257454Seric hostbuf, m->m_name); 99357454Seric i = makeconnection(hostbuf, port, mci, 99454967Seric bitnset(M_SECURE_PORT, m->m_flags)); 99554967Seric mci->mci_exitstat = i; 99654967Seric mci->mci_errno = errno; 99763753Seric #ifdef NAMED_BIND 99863753Seric mci->mci_herrno = h_errno; 99963753Seric #endif 100054967Seric if (i == EX_OK) 100152106Seric { 100254967Seric mci->mci_state = MCIS_OPENING; 100354967Seric mci_cache(mci); 100463753Seric if (TrafficLogFile != NULL) 100563753Seric fprintf(TrafficLogFile, "%05d == CONNECT %s\n", 100663753Seric getpid(), hostbuf); 100754967Seric break; 100834022Sbostic } 100954967Seric else if (tTd(11, 1)) 101054967Seric printf("openmailer: makeconnection => stat=%d, errno=%d\n", 101154967Seric i, errno); 101253738Seric 101354967Seric 101453738Seric /* enter status of this host */ 101553738Seric setstat(i); 10166047Seric } 101754993Seric mci->mci_pid = 0; 101854967Seric #else /* no DAEMON */ 101958151Seric syserr("554 openmailer: no IPC"); 102057387Seric if (tTd(11, 1)) 102157387Seric printf("openmailer: NULL\n"); 102253738Seric return NULL; 102354967Seric #endif /* DAEMON */ 10246038Seric } 102554967Seric else 1026294Seric { 102763753Seric #ifdef XDEBUG 102863753Seric char wbuf[MAXLINE]; 102958852Seric 103058852Seric /* make absolutely certain 0, 1, and 2 are in use */ 103163753Seric sprintf(wbuf, "%s... openmailer(%s)", e->e_to, m->m_name); 103263753Seric checkfd012(wbuf); 103363753Seric #endif 103463753Seric 103563753Seric if (TrafficLogFile != NULL) 103658852Seric { 103763753Seric char **av; 103858925Seric 103963753Seric fprintf(TrafficLogFile, "%05d === EXEC", getpid()); 104063753Seric for (av = pv; *av != NULL; av++) 104163753Seric fprintf(TrafficLogFile, " %s", *av); 104263753Seric fprintf(TrafficLogFile, "\n"); 104358852Seric } 104458852Seric 104554967Seric /* create a pipe to shove the mail through */ 104654967Seric if (pipe(mpvect) < 0) 104754967Seric { 104858925Seric syserr("%s... openmailer(%s): pipe (to mailer)", 104958925Seric e->e_to, m->m_name); 105057387Seric if (tTd(11, 1)) 105157387Seric printf("openmailer: NULL\n"); 105258820Seric rcode = EX_OSERR; 105358820Seric goto give_up; 105454967Seric } 10554863Seric 105654967Seric /* if this mailer speaks smtp, create a return pipe */ 105754967Seric if (clever && pipe(rpvect) < 0) 105854967Seric { 105958925Seric syserr("%s... openmailer(%s): pipe (from mailer)", 106058925Seric e->e_to, m->m_name); 106154967Seric (void) close(mpvect[0]); 106254967Seric (void) close(mpvect[1]); 106357387Seric if (tTd(11, 1)) 106457387Seric printf("openmailer: NULL\n"); 106558820Seric rcode = EX_OSERR; 106658820Seric goto give_up; 106754967Seric } 10684863Seric 106954967Seric /* 107054967Seric ** Actually fork the mailer process. 107154967Seric ** DOFORK is clever about retrying. 107254967Seric ** 107354967Seric ** Dispose of SIGCHLD signal catchers that may be laying 107454967Seric ** around so that endmail will get it. 107554967Seric */ 10766038Seric 107754967Seric if (e->e_xfp != NULL) 107854967Seric (void) fflush(e->e_xfp); /* for debugging */ 107954967Seric (void) fflush(stdout); 108026434Seric # ifdef SIGCHLD 108164035Seric (void) setsignal(SIGCHLD, SIG_DFL); 108256795Seric # endif /* SIGCHLD */ 108354967Seric DOFORK(FORK); 108454967Seric /* pid is set by DOFORK */ 108554967Seric if (pid < 0) 10864863Seric { 108754967Seric /* failure */ 108858925Seric syserr("%s... openmailer(%s): cannot fork", 108958925Seric e->e_to, m->m_name); 109054967Seric (void) close(mpvect[0]); 109154967Seric (void) close(mpvect[1]); 109254967Seric if (clever) 109354967Seric { 109454967Seric (void) close(rpvect[0]); 109554967Seric (void) close(rpvect[1]); 109654967Seric } 109757387Seric if (tTd(11, 1)) 109857387Seric printf("openmailer: NULL\n"); 109958820Seric rcode = EX_OSERR; 110058820Seric goto give_up; 11014863Seric } 110254967Seric else if (pid == 0) 110354967Seric { 110454967Seric int i; 110556678Seric int saveerrno; 110658675Seric char **ep; 110758675Seric char *env[MAXUSERENVIRON]; 110858675Seric extern char **environ; 110954967Seric extern int DtableSize; 111015772Seric 111154967Seric /* child -- set up input & exec mailer */ 111264035Seric (void) setsignal(SIGINT, SIG_IGN); 111364035Seric (void) setsignal(SIGHUP, SIG_IGN); 111464035Seric (void) setsignal(SIGTERM, SIG_DFL); 11154709Seric 111658082Seric /* close any other cached connections */ 111758082Seric mci_flush(FALSE, mci); 111858082Seric 1119*64145Seric /* reset user and group */ 1120*64145Seric if (!bitnset(M_RESTR, m->m_flags)) 1121*64145Seric { 1122*64145Seric if (ctladdr == NULL || ctladdr->q_uid == 0) 1123*64145Seric { 1124*64145Seric (void) setgid(DefGid); 1125*64145Seric (void) initgroups(DefUser, DefGid); 1126*64145Seric (void) setuid(DefUid); 1127*64145Seric } 1128*64145Seric else 1129*64145Seric { 1130*64145Seric (void) setgid(ctladdr->q_gid); 1131*64145Seric (void) initgroups(ctladdr->q_ruser? 1132*64145Seric ctladdr->q_ruser: ctladdr->q_user, 1133*64145Seric ctladdr->q_gid); 1134*64145Seric (void) setuid(ctladdr->q_uid); 1135*64145Seric } 1136*64145Seric } 1137*64145Seric 1138*64145Seric if (tTd(11, 2)) 1139*64145Seric printf("openmailer: running as r/euid=%d/%d\n", 1140*64145Seric getuid(), geteuid()); 1141*64145Seric 114258935Seric /* move into some "safe" directory */ 114358935Seric if (m->m_execdir != NULL) 114458935Seric { 114558935Seric char *p, *q; 114658935Seric char buf[MAXLINE]; 114758935Seric 114858935Seric for (p = m->m_execdir; p != NULL; p = q) 114958935Seric { 115058935Seric q = strchr(p, ':'); 115158935Seric if (q != NULL) 115258935Seric *q = '\0'; 115358935Seric expand(p, buf, &buf[sizeof buf] - 1, e); 115458935Seric if (q != NULL) 115558935Seric *q++ = ':'; 115658935Seric if (tTd(11, 20)) 115758935Seric printf("openmailer: trydir %s\n", 115858935Seric buf); 115958935Seric if (buf[0] != '\0' && chdir(buf) >= 0) 116058935Seric break; 116158935Seric } 116258935Seric } 116358935Seric 116454967Seric /* arrange to filter std & diag output of command */ 116554967Seric if (clever) 116654967Seric { 116754967Seric (void) close(rpvect[0]); 116858852Seric if (dup2(rpvect[1], STDOUT_FILENO) < 0) 116958852Seric { 117058925Seric syserr("%s... openmailer(%s): cannot dup pipe %d for stdout", 117158925Seric e->e_to, m->m_name, rpvect[1]); 117258852Seric _exit(EX_OSERR); 117358852Seric } 117454967Seric (void) close(rpvect[1]); 117554967Seric } 117654967Seric else if (OpMode == MD_SMTP || HoldErrs) 117754967Seric { 117854967Seric /* put mailer output in transcript */ 117958852Seric if (dup2(fileno(e->e_xfp), STDOUT_FILENO) < 0) 118058852Seric { 118158925Seric syserr("%s... openmailer(%s): cannot dup xscript %d for stdout", 118258925Seric e->e_to, m->m_name, 118358852Seric fileno(e->e_xfp)); 118458852Seric _exit(EX_OSERR); 118558852Seric } 118654967Seric } 118758852Seric if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) 118858852Seric { 118958925Seric syserr("%s... openmailer(%s): cannot dup stdout for stderr", 119058925Seric e->e_to, m->m_name); 119158852Seric _exit(EX_OSERR); 119258852Seric } 11934709Seric 119454967Seric /* arrange to get standard input */ 119554967Seric (void) close(mpvect[1]); 119658731Seric if (dup2(mpvect[0], STDIN_FILENO) < 0) 11974417Seric { 119858925Seric syserr("%s... openmailer(%s): cannot dup pipe %d for stdin", 119958925Seric e->e_to, m->m_name, mpvect[0]); 120054967Seric _exit(EX_OSERR); 12014417Seric } 120254967Seric (void) close(mpvect[0]); 12039370Seric 120454967Seric /* arrange for all the files to be closed */ 120554967Seric for (i = 3; i < DtableSize; i++) 120654967Seric { 120754967Seric register int j; 1208*64145Seric 120954967Seric if ((j = fcntl(i, F_GETFD, 0)) != -1) 1210*64145Seric (void) fcntl(i, F_SETFD, j | 1); 121154967Seric } 12122774Seric 121358675Seric /* set up the mailer environment */ 121458675Seric i = 0; 121558675Seric env[i++] = "AGENT=sendmail"; 121658675Seric for (ep = environ; *ep != NULL; ep++) 121758675Seric { 121858675Seric if (strncmp(*ep, "TZ=", 3) == 0) 121958675Seric env[i++] = *ep; 122058675Seric } 122158675Seric env[i++] = NULL; 122258675Seric 122354967Seric /* try to execute the mailer */ 122458820Seric execve(m->m_mailer, pv, env); 122556678Seric saveerrno = errno; 122654967Seric syserr("Cannot exec %s", m->m_mailer); 122760008Seric if (m == LocalMailer || transienterror(saveerrno)) 122860008Seric _exit(EX_OSERR); 122954967Seric _exit(EX_UNAVAILABLE); 123051835Seric } 123154967Seric 123254967Seric /* 123354967Seric ** Set up return value. 123454967Seric */ 123554967Seric 123654967Seric mci = (MCI *) xalloc(sizeof *mci); 123754993Seric bzero((char *) mci, sizeof *mci); 123854967Seric mci->mci_mailer = m; 123954967Seric mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN; 124054993Seric mci->mci_pid = pid; 124154967Seric (void) close(mpvect[0]); 124254967Seric mci->mci_out = fdopen(mpvect[1], "w"); 124354967Seric if (clever) 124454967Seric { 124554967Seric (void) close(rpvect[1]); 124654967Seric mci->mci_in = fdopen(rpvect[0], "r"); 124754967Seric } 124854967Seric else 124954967Seric { 125054967Seric mci->mci_flags |= MCIF_TEMP; 125154967Seric mci->mci_in = NULL; 125254967Seric } 1253294Seric } 1254294Seric 12554709Seric /* 125654967Seric ** If we are in SMTP opening state, send initial protocol. 12574709Seric */ 12584709Seric 125954967Seric if (clever && mci->mci_state != MCIS_CLOSED) 12604863Seric { 126154967Seric smtpinit(m, mci, e); 126253738Seric } 126357387Seric if (tTd(11, 1)) 126457387Seric { 126557387Seric printf("openmailer: "); 126657387Seric mci_dump(mci); 126757387Seric } 1268294Seric 126958820Seric if (mci->mci_state != MCIS_OPEN) 127058820Seric { 127158820Seric /* couldn't open the mailer */ 127258820Seric rcode = mci->mci_exitstat; 127358820Seric errno = mci->mci_errno; 127463753Seric #ifdef NAMED_BIND 127563753Seric h_errno = mci->mci_herrno; 127663753Seric #endif 127758820Seric if (rcode == EX_OK) 127858820Seric { 127958820Seric /* shouldn't happen */ 128058820Seric syserr("554 deliver: rcode=%d, mci_state=%d, sig=%s", 128158820Seric rcode, mci->mci_state, firstsig); 128258820Seric rcode = EX_SOFTWARE; 128358820Seric } 128459993Seric else if (rcode == EX_TEMPFAIL && *curhost != '\0') 128559958Seric { 128659958Seric /* try next MX site */ 128759958Seric goto tryhost; 128859958Seric } 128958820Seric } 129058820Seric else if (!clever) 129158820Seric { 129258820Seric /* 129358820Seric ** Format and send message. 129458820Seric */ 129558820Seric 129658820Seric putfromline(mci->mci_out, m, e); 129758820Seric (*e->e_puthdr)(mci->mci_out, m, e); 129858820Seric putline("\n", mci->mci_out, m); 129959730Seric (*e->e_putbody)(mci->mci_out, m, e, NULL); 130058820Seric 130158820Seric /* get the exit status */ 130258820Seric rcode = endmailer(mci, e, pv); 130358820Seric } 130458820Seric else 130558820Seric #ifdef SMTP 130658820Seric { 130758820Seric /* 130858820Seric ** Send the MAIL FROM: protocol 130958820Seric */ 131058820Seric 131158820Seric rcode = smtpmailfrom(m, mci, e); 131258820Seric if (rcode == EX_OK) 131358820Seric { 131458820Seric register char *t = tobuf; 131558820Seric register int i; 131658820Seric 131758820Seric /* send the recipient list */ 131858820Seric tobuf[0] = '\0'; 131958820Seric for (to = tochain; to != NULL; to = to->q_tchain) 132058820Seric { 132158820Seric e->e_to = to->q_paddr; 132258820Seric if ((i = smtprcpt(to, m, mci, e)) != EX_OK) 132358820Seric { 132458820Seric markfailure(e, to, i); 132558820Seric giveresponse(i, m, mci, e); 132658820Seric } 132758820Seric else 132858820Seric { 132958820Seric *t++ = ','; 133058820Seric for (p = to->q_paddr; *p; *t++ = *p++) 133158820Seric continue; 133258820Seric } 133358820Seric } 133458820Seric 133558820Seric /* now send the data */ 133658820Seric if (tobuf[0] == '\0') 133758820Seric { 133858820Seric rcode = EX_OK; 133958820Seric e->e_to = NULL; 134058820Seric if (bitset(MCIF_CACHED, mci->mci_flags)) 134158820Seric smtprset(m, mci, e); 134258820Seric } 134358820Seric else 134458820Seric { 134558820Seric e->e_to = tobuf + 1; 134658820Seric rcode = smtpdata(m, mci, e); 134758820Seric } 134858820Seric 134958820Seric /* now close the connection */ 135058820Seric if (!bitset(MCIF_CACHED, mci->mci_flags)) 135158820Seric smtpquit(m, mci, e); 135258820Seric } 135358820Seric if (rcode != EX_OK && *curhost != '\0') 135458820Seric { 135558820Seric /* try next MX site */ 135658820Seric goto tryhost; 135758820Seric } 135858820Seric } 135958820Seric #else /* not SMTP */ 136058820Seric { 136158820Seric syserr("554 deliver: need SMTP compiled to use clever mailer"); 136258820Seric rcode = EX_CONFIG; 136358820Seric goto give_up; 136458820Seric } 136558820Seric #endif /* SMTP */ 136658820Seric #ifdef NAMED_BIND 136758820Seric if (ConfigLevel < 2) 136858820Seric _res.options |= RES_DEFNAMES | RES_DNSRCH; /* XXX */ 136958820Seric #endif 137058820Seric 137158820Seric /* arrange a return receipt if requested */ 137258820Seric if (e->e_receiptto != NULL && bitnset(M_LOCALMAILER, m->m_flags)) 137358820Seric { 137458820Seric e->e_flags |= EF_SENDRECEIPT; 137558820Seric /* do we want to send back more info? */ 137658820Seric } 137758820Seric 137858820Seric /* 137958820Seric ** Do final status disposal. 138058820Seric ** We check for something in tobuf for the SMTP case. 138158820Seric ** If we got a temporary failure, arrange to queue the 138258820Seric ** addressees. 138358820Seric */ 138458820Seric 138558820Seric give_up: 138658820Seric if (tobuf[0] != '\0') 138758820Seric giveresponse(rcode, m, mci, e); 138858820Seric for (to = tochain; to != NULL; to = to->q_tchain) 138958820Seric { 139058820Seric if (rcode != EX_OK) 139158820Seric markfailure(e, to, rcode); 139258820Seric else 139358820Seric { 139458820Seric to->q_flags |= QSENT; 139558820Seric e->e_nsent++; 139658820Seric } 139758820Seric } 139858820Seric 139958820Seric /* 140058820Seric ** Restore state and return. 140158820Seric */ 140258820Seric 140358820Seric errno = 0; 140458820Seric define('g', (char *) NULL, e); 140558820Seric return (rcode); 1406294Seric } 1407294Seric /* 140858820Seric ** MARKFAILURE -- mark a failure on a specific address. 140958820Seric ** 141058820Seric ** Parameters: 141158820Seric ** e -- the envelope we are sending. 141258820Seric ** q -- the address to mark. 141358820Seric ** rcode -- the code signifying the particular failure. 141458820Seric ** 141558820Seric ** Returns: 141658820Seric ** none. 141758820Seric ** 141858820Seric ** Side Effects: 141958820Seric ** marks the address (and possibly the envelope) with the 142058820Seric ** failure so that an error will be returned or 142158820Seric ** the message will be queued, as appropriate. 142258820Seric */ 142358820Seric 142458820Seric markfailure(e, q, rcode) 142558820Seric register ENVELOPE *e; 142658820Seric register ADDRESS *q; 142758820Seric int rcode; 142858820Seric { 142958820Seric char buf[MAXLINE]; 143058820Seric 143158820Seric if (rcode == EX_OK) 143258820Seric return; 143363753Seric else if (rcode == EX_TEMPFAIL) 143463753Seric q->q_flags |= QQUEUEUP; 143563753Seric else if (rcode != EX_IOERR && rcode != EX_OSERR) 143658820Seric q->q_flags |= QBADADDR; 143758820Seric } 143858820Seric /* 143958820Seric ** ENDMAILER -- Wait for mailer to terminate. 144058820Seric ** 144158820Seric ** We should never get fatal errors (e.g., segmentation 144258820Seric ** violation), so we report those specially. For other 144358820Seric ** errors, we choose a status message (into statmsg), 144458820Seric ** and if it represents an error, we print it. 144558820Seric ** 144658820Seric ** Parameters: 144758820Seric ** pid -- pid of mailer. 144858820Seric ** e -- the current envelope. 144958820Seric ** pv -- the parameter vector that invoked the mailer 145058820Seric ** (for error messages). 145158820Seric ** 145258820Seric ** Returns: 145358820Seric ** exit code of mailer. 145458820Seric ** 145558820Seric ** Side Effects: 145658820Seric ** none. 145758820Seric */ 145858820Seric 145958820Seric endmailer(mci, e, pv) 146058820Seric register MCI *mci; 146158820Seric register ENVELOPE *e; 146258820Seric char **pv; 146358820Seric { 146458820Seric int st; 146558820Seric 146658820Seric /* close any connections */ 146758820Seric if (mci->mci_in != NULL) 146858820Seric (void) xfclose(mci->mci_in, pv[0], "mci_in"); 146958820Seric if (mci->mci_out != NULL) 147058820Seric (void) xfclose(mci->mci_out, pv[0], "mci_out"); 147158820Seric mci->mci_in = mci->mci_out = NULL; 147258820Seric mci->mci_state = MCIS_CLOSED; 147358820Seric 147458820Seric /* in the IPC case there is nothing to wait for */ 147558820Seric if (mci->mci_pid == 0) 147658820Seric return (EX_OK); 147758820Seric 147858820Seric /* wait for the mailer process to die and collect status */ 147958820Seric st = waitfor(mci->mci_pid); 148058820Seric if (st == -1) 148158820Seric { 148258820Seric syserr("endmailer %s: wait", pv[0]); 148358820Seric return (EX_SOFTWARE); 148458820Seric } 148558820Seric 148658820Seric /* see if it died a horrid death */ 148758820Seric if ((st & 0377) != 0) 148858820Seric { 148958820Seric syserr("mailer %s died with signal %o", pv[0], st); 149058820Seric 149158820Seric /* log the arguments */ 149258820Seric if (e->e_xfp != NULL) 149358820Seric { 149458820Seric register char **av; 149558820Seric 149658820Seric fprintf(e->e_xfp, "Arguments:"); 149758820Seric for (av = pv; *av != NULL; av++) 149858820Seric fprintf(e->e_xfp, " %s", *av); 149958820Seric fprintf(e->e_xfp, "\n"); 150058820Seric } 150158820Seric 150258820Seric ExitStat = EX_TEMPFAIL; 150358820Seric return (EX_TEMPFAIL); 150458820Seric } 150558820Seric 150658820Seric /* normal death -- return status */ 150758820Seric st = (st >> 8) & 0377; 150858820Seric return (st); 150958820Seric } 151058820Seric /* 1511294Seric ** GIVERESPONSE -- Interpret an error response from a mailer 1512294Seric ** 1513294Seric ** Parameters: 1514294Seric ** stat -- the status code from the mailer (high byte 1515294Seric ** only; core dumps must have been taken care of 1516294Seric ** already). 151758337Seric ** m -- the mailer info for this mailer. 151858337Seric ** mci -- the mailer connection info -- can be NULL if the 151958337Seric ** response is given before the connection is made. 152058337Seric ** e -- the current envelope. 1521294Seric ** 1522294Seric ** Returns: 15234082Seric ** none. 1524294Seric ** 1525294Seric ** Side Effects: 15261518Seric ** Errors may be incremented. 1527294Seric ** ExitStat may be set. 1528294Seric */ 1529294Seric 153058337Seric giveresponse(stat, m, mci, e) 1531294Seric int stat; 15329370Seric register MAILER *m; 153358337Seric register MCI *mci; 153410105Seric ENVELOPE *e; 1535294Seric { 153660094Seric register const char *statmsg; 1537294Seric extern char *SysExMsg[]; 1538294Seric register int i; 153936788Sbostic extern int N_SysEx; 154010105Seric char buf[MAXLINE]; 1541294Seric 15424315Seric /* 15434315Seric ** Compute status message from code. 15444315Seric */ 15454315Seric 1546294Seric i = stat - EX__BASE; 15479370Seric if (stat == 0) 154858852Seric { 15499370Seric statmsg = "250 Sent"; 155058916Seric if (e->e_statmsg != NULL) 155158852Seric { 155258916Seric (void) sprintf(buf, "%s (%s)", statmsg, e->e_statmsg); 155358852Seric statmsg = buf; 155458852Seric } 155558852Seric } 15569370Seric else if (i < 0 || i > N_SysEx) 15579370Seric { 15589370Seric (void) sprintf(buf, "554 unknown mailer error %d", stat); 15599370Seric stat = EX_UNAVAILABLE; 15609370Seric statmsg = buf; 15619370Seric } 156210105Seric else if (stat == EX_TEMPFAIL) 156310105Seric { 156458664Seric (void) strcpy(buf, SysExMsg[i] + 1); 156536788Sbostic #ifdef NAMED_BIND 156625527Smiriam if (h_errno == TRY_AGAIN) 156763993Seric statmsg = errstring(h_errno+E_DNSBASE); 156821061Seric else 156936788Sbostic #endif 157021061Seric { 157125527Smiriam if (errno != 0) 157225527Smiriam statmsg = errstring(errno); 157325527Smiriam else 157425527Smiriam { 157521061Seric #ifdef SMTP 157625527Smiriam extern char SmtpError[]; 157721061Seric 157825527Smiriam statmsg = SmtpError; 157956795Seric #else /* SMTP */ 158025527Smiriam statmsg = NULL; 158156795Seric #endif /* SMTP */ 158225527Smiriam } 158321061Seric } 158421061Seric if (statmsg != NULL && statmsg[0] != '\0') 158521061Seric { 158610124Seric (void) strcat(buf, ": "); 158721061Seric (void) strcat(buf, statmsg); 158810105Seric } 158910105Seric statmsg = buf; 159010105Seric } 159163753Seric #ifdef NAMED_BIND 159263753Seric else if (stat == EX_NOHOST && h_errno != 0) 159363753Seric { 159463993Seric statmsg = errstring(h_errno + E_DNSBASE); 159563753Seric (void) sprintf(buf, "%s (%s)", SysExMsg[i], statmsg); 159663753Seric statmsg = buf; 159763753Seric } 159863753Seric #endif 1599294Seric else 160021061Seric { 1601294Seric statmsg = SysExMsg[i]; 160258664Seric if (*statmsg++ == ':') 160358664Seric { 160458664Seric (void) sprintf(buf, "%s: %s", statmsg, errstring(errno)); 160558664Seric statmsg = buf; 160658664Seric } 160721061Seric } 16089370Seric 16099370Seric /* 16109370Seric ** Print the message as appropriate 16119370Seric */ 16129370Seric 161310105Seric if (stat == EX_OK || stat == EX_TEMPFAIL) 161458524Seric message(&statmsg[4], errstring(errno)); 1615294Seric else 1616294Seric { 16171518Seric Errors++; 161858524Seric usrerr(statmsg, errstring(errno)); 1619294Seric } 1620294Seric 1621294Seric /* 1622294Seric ** Final cleanup. 1623294Seric ** Log a record of the transaction. Compute the new 1624294Seric ** ExitStat -- if we already had an error, stick with 1625294Seric ** that. 1626294Seric */ 1627294Seric 162858020Seric if (LogLevel > ((stat == EX_TEMPFAIL) ? 8 : (stat == EX_OK) ? 7 : 6)) 162958337Seric logdelivery(m, mci, &statmsg[4], e); 16307858Seric 16314621Seric if (stat != EX_TEMPFAIL) 16324621Seric setstat(stat); 163310105Seric if (stat != EX_OK) 163410105Seric { 163510105Seric if (e->e_message != NULL) 163610105Seric free(e->e_message); 163710105Seric e->e_message = newstr(&statmsg[4]); 163810105Seric } 163910124Seric errno = 0; 164036788Sbostic #ifdef NAMED_BIND 164125527Smiriam h_errno = 0; 164236788Sbostic #endif 1643294Seric } 1644294Seric /* 16458496Seric ** LOGDELIVERY -- log the delivery in the system log 16468496Seric ** 16478496Seric ** Parameters: 164858337Seric ** m -- the mailer info. Can be NULL for initial queue. 164958337Seric ** mci -- the mailer connection info -- can be NULL if the 165058337Seric ** log is occuring when no connection is active. 165158337Seric ** stat -- the message to print for the status. 165258337Seric ** e -- the current envelope. 16538496Seric ** 16548496Seric ** Returns: 16558496Seric ** none 16568496Seric ** 16578496Seric ** Side Effects: 16588496Seric ** none 16598496Seric */ 16608496Seric 166158337Seric logdelivery(m, mci, stat, e) 166258337Seric MAILER *m; 166358337Seric register MCI *mci; 16648496Seric char *stat; 166554967Seric register ENVELOPE *e; 16668496Seric { 166758343Seric # ifdef LOG 166858418Seric char buf[512]; 16698496Seric 167058513Seric (void) sprintf(buf, "delay=%s", pintvl(curtime() - e->e_ctime, TRUE)); 167158337Seric 167258513Seric if (m != NULL) 167358305Seric { 167458513Seric (void) strcat(buf, ", mailer="); 167558513Seric (void) strcat(buf, m->m_name); 167658305Seric } 167758513Seric 167858513Seric if (mci != NULL && mci->mci_host != NULL) 167958305Seric { 168058305Seric # ifdef DAEMON 168158755Seric extern SOCKADDR CurHostAddr; 168258513Seric # endif 168358305Seric 168458513Seric (void) strcat(buf, ", relay="); 168558513Seric (void) strcat(buf, mci->mci_host); 168658513Seric 168758513Seric # ifdef DAEMON 168858513Seric (void) strcat(buf, " ("); 168958755Seric (void) strcat(buf, anynet_ntoa(&CurHostAddr)); 169058513Seric (void) strcat(buf, ")"); 169158305Seric # endif 169258305Seric } 169358343Seric else 169458513Seric { 169558513Seric char *p = macvalue('h', e); 169658343Seric 169758513Seric if (p != NULL && p[0] != '\0') 169858513Seric { 169958513Seric (void) strcat(buf, ", relay="); 170058513Seric (void) strcat(buf, p); 170158513Seric } 170258513Seric } 170358418Seric 170458418Seric syslog(LOG_INFO, "%s: to=%s, %s, stat=%s", 170558418Seric e->e_id, e->e_to, buf, stat); 170656795Seric # endif /* LOG */ 17078496Seric } 17088496Seric /* 17096974Seric ** PUTFROMLINE -- output a UNIX-style from line (or whatever) 1710294Seric ** 17116974Seric ** This can be made an arbitrary message separator by changing $l 1712294Seric ** 171316150Seric ** One of the ugliest hacks seen by human eyes is contained herein: 171416150Seric ** UUCP wants those stupid "remote from <host>" lines. Why oh why 171516150Seric ** does a well-meaning programmer such as myself have to deal with 171616150Seric ** this kind of antique garbage???? 17176974Seric ** 1718294Seric ** Parameters: 17196974Seric ** fp -- the file to output to. 17206974Seric ** m -- the mailer describing this entry. 1721294Seric ** 1722294Seric ** Returns: 17236974Seric ** none 1724294Seric ** 1725294Seric ** Side Effects: 17266974Seric ** outputs some text to fp. 1727294Seric */ 1728294Seric 172954967Seric putfromline(fp, m, e) 17306974Seric register FILE *fp; 17316974Seric register MAILER *m; 173254967Seric ENVELOPE *e; 1733294Seric { 173458050Seric char *template = "\201l\n"; 17356974Seric char buf[MAXLINE]; 1736294Seric 173710682Seric if (bitnset(M_NHDR, m->m_flags)) 17386974Seric return; 17394315Seric 17406974Seric # ifdef UGLYUUCP 174110682Seric if (bitnset(M_UGLYUUCP, m->m_flags)) 17424205Seric { 174312223Seric char *bang; 174412223Seric char xbuf[MAXLINE]; 17456041Seric 174658680Seric expand("\201g", buf, &buf[sizeof buf - 1], e); 174756795Seric bang = strchr(buf, '!'); 17486974Seric if (bang == NULL) 174958151Seric syserr("554 No ! in UUCP! (%s)", buf); 17505099Seric else 17519370Seric { 175212223Seric *bang++ = '\0'; 175358050Seric (void) sprintf(xbuf, "From %s \201d remote from %s\n", bang, buf); 175412223Seric template = xbuf; 17559370Seric } 17566974Seric } 175756795Seric # endif /* UGLYUUCP */ 175854967Seric expand(template, buf, &buf[sizeof buf - 1], e); 175910168Seric putline(buf, fp, m); 17605981Seric } 17615981Seric /* 17626974Seric ** PUTBODY -- put the body of a message. 17636974Seric ** 17646974Seric ** Parameters: 17656974Seric ** fp -- file to output onto. 176610168Seric ** m -- a mailer descriptor to control output format. 17679538Seric ** e -- the envelope to put out. 176859730Seric ** separator -- if non-NULL, a message separator that must 176959730Seric ** not be permitted in the resulting message. 17706974Seric ** 17716974Seric ** Returns: 17726974Seric ** none. 17736974Seric ** 17746974Seric ** Side Effects: 17756974Seric ** The message is written onto fp. 17766974Seric */ 17776974Seric 177859730Seric putbody(fp, m, e, separator) 17796974Seric FILE *fp; 17809370Seric MAILER *m; 17819538Seric register ENVELOPE *e; 178259730Seric char *separator; 17836974Seric { 178410168Seric char buf[MAXLINE]; 17856974Seric 17866974Seric /* 17876974Seric ** Output the body of the message 17886974Seric */ 17896974Seric 17909538Seric if (e->e_dfp == NULL) 17916974Seric { 17929538Seric if (e->e_df != NULL) 17939538Seric { 17949538Seric e->e_dfp = fopen(e->e_df, "r"); 17959538Seric if (e->e_dfp == NULL) 179640931Srick syserr("putbody: Cannot open %s for %s from %s", 179764118Seric e->e_df, e->e_to, e->e_from.q_paddr); 17989538Seric } 17999538Seric else 180010168Seric putline("<<< No Message Collected >>>", fp, m); 18019538Seric } 18029538Seric if (e->e_dfp != NULL) 18039538Seric { 18049538Seric rewind(e->e_dfp); 180510168Seric while (!ferror(fp) && fgets(buf, sizeof buf, e->e_dfp) != NULL) 180616875Seric { 180716875Seric if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) && 180840995Sbostic strncmp(buf, "From ", 5) == 0) 180923102Seric (void) putc('>', fp); 181059730Seric if (buf[0] == '-' && buf[1] == '-' && separator != NULL) 181159730Seric { 181259730Seric /* possible separator */ 181359730Seric int sl = strlen(separator); 181459730Seric 181559730Seric if (strncmp(&buf[2], separator, sl) == 0) 181659730Seric (void) putc(' ', fp); 181759730Seric } 181810168Seric putline(buf, fp, m); 181916875Seric } 18206974Seric 18219538Seric if (ferror(e->e_dfp)) 18226974Seric { 18236974Seric syserr("putbody: read error"); 18246974Seric ExitStat = EX_IOERR; 18256974Seric } 18266974Seric } 18276974Seric 182859542Seric /* some mailers want extra blank line at end of message */ 182959542Seric if (bitnset(M_BLANKEND, m->m_flags) && buf[0] != '\0' && buf[0] != '\n') 183059542Seric putline("", fp, m); 183159542Seric 18326974Seric (void) fflush(fp); 18336974Seric if (ferror(fp) && errno != EPIPE) 18346974Seric { 18356974Seric syserr("putbody: write error"); 18366974Seric ExitStat = EX_IOERR; 18376974Seric } 18386974Seric errno = 0; 18396974Seric } 18406974Seric /* 1841294Seric ** MAILFILE -- Send a message to a file. 1842294Seric ** 18434327Seric ** If the file has the setuid/setgid bits set, but NO execute 18444327Seric ** bits, sendmail will try to become the owner of that file 18454327Seric ** rather than the real user. Obviously, this only works if 18464327Seric ** sendmail runs as root. 18474327Seric ** 18489370Seric ** This could be done as a subordinate mailer, except that it 18499370Seric ** is used implicitly to save messages in ~/dead.letter. We 18509370Seric ** view this as being sufficiently important as to include it 18519370Seric ** here. For example, if the system is dying, we shouldn't have 18529370Seric ** to create another process plus some pipes to save the message. 18539370Seric ** 1854294Seric ** Parameters: 1855294Seric ** filename -- the name of the file to send to. 18564397Seric ** ctladdr -- the controlling address header -- includes 18574397Seric ** the userid/groupid to be when sending. 1858294Seric ** 1859294Seric ** Returns: 1860294Seric ** The exit code associated with the operation. 1861294Seric ** 1862294Seric ** Side Effects: 1863294Seric ** none. 1864294Seric */ 1865294Seric 186654967Seric mailfile(filename, ctladdr, e) 1867294Seric char *filename; 18684397Seric ADDRESS *ctladdr; 186954967Seric register ENVELOPE *e; 1870294Seric { 1871294Seric register FILE *f; 18724214Seric register int pid; 187353751Seric int mode; 1874294Seric 187559267Seric if (tTd(11, 1)) 187659267Seric { 187759267Seric printf("mailfile %s\n ctladdr=", filename); 187859267Seric printaddr(ctladdr, FALSE); 187959267Seric } 188059267Seric 188163753Seric if (e->e_xfp != NULL) 188263753Seric fflush(e->e_xfp); 188363753Seric 18844214Seric /* 18854214Seric ** Fork so we can change permissions here. 18864214Seric ** Note that we MUST use fork, not vfork, because of 18874214Seric ** the complications of calling subroutines, etc. 18884214Seric */ 18894067Seric 18904214Seric DOFORK(fork); 18914214Seric 18924214Seric if (pid < 0) 18934214Seric return (EX_OSERR); 18944214Seric else if (pid == 0) 18954214Seric { 18964214Seric /* child -- actually write to file */ 18974327Seric struct stat stb; 18984327Seric 189964035Seric (void) setsignal(SIGINT, SIG_DFL); 190064035Seric (void) setsignal(SIGHUP, SIG_DFL); 190164035Seric (void) setsignal(SIGTERM, SIG_DFL); 190223102Seric (void) umask(OldUmask); 190352673Seric 19044327Seric if (stat(filename, &stb) < 0) 190559745Seric stb.st_mode = FileMode; 190653751Seric mode = stb.st_mode; 190752673Seric 190852673Seric /* limit the errors to those actually caused in the child */ 190952673Seric errno = 0; 191052673Seric ExitStat = EX_OK; 191152673Seric 19124327Seric if (bitset(0111, stb.st_mode)) 19134327Seric exit(EX_CANTCREAT); 19144401Seric if (ctladdr == NULL) 191540931Srick ctladdr = &e->e_from; 191653751Seric else 191753751Seric { 191853751Seric /* ignore setuid and setgid bits */ 191953751Seric mode &= ~(S_ISGID|S_ISUID); 192053751Seric } 192153751Seric 192240931Srick /* we have to open the dfile BEFORE setuid */ 192353751Seric if (e->e_dfp == NULL && e->e_df != NULL) 192440931Srick { 192540931Srick e->e_dfp = fopen(e->e_df, "r"); 192652673Seric if (e->e_dfp == NULL) 192752673Seric { 192840931Srick syserr("mailfile: Cannot open %s for %s from %s", 192964118Seric e->e_df, e->e_to, e->e_from.q_paddr); 193040931Srick } 193140931Srick } 193240931Srick 193353751Seric if (!bitset(S_ISGID, mode) || setgid(stb.st_gid) < 0) 19344417Seric { 193552673Seric if (ctladdr->q_uid == 0) 193652673Seric { 19374417Seric (void) setgid(DefGid); 193840972Sbostic (void) initgroups(DefUser, DefGid); 193952673Seric } 194052673Seric else 194152673Seric { 19424417Seric (void) setgid(ctladdr->q_gid); 194353751Seric (void) initgroups(ctladdr->q_ruser ? 194453751Seric ctladdr->q_ruser : ctladdr->q_user, 194540972Sbostic ctladdr->q_gid); 194640972Sbostic } 19474417Seric } 194853751Seric if (!bitset(S_ISUID, mode) || setuid(stb.st_uid) < 0) 19494417Seric { 19504417Seric if (ctladdr->q_uid == 0) 19514417Seric (void) setuid(DefUid); 19524417Seric else 19534417Seric (void) setuid(ctladdr->q_uid); 19544417Seric } 195552673Seric FileName = filename; 195652673Seric LineNumber = 0; 195759745Seric f = dfopen(filename, O_WRONLY|O_CREAT|O_APPEND, FileMode); 19584214Seric if (f == NULL) 195952673Seric { 196058151Seric message("554 cannot open"); 19614214Seric exit(EX_CANTCREAT); 196252673Seric } 19634214Seric 196459275Seric putfromline(f, FileMailer, e); 196559275Seric (*e->e_puthdr)(f, FileMailer, e); 196659275Seric putline("\n", f, FileMailer); 196759730Seric (*e->e_putbody)(f, FileMailer, e, NULL); 196859275Seric putline("\n", f, FileMailer); 196952673Seric if (ferror(f)) 197052673Seric { 197158151Seric message("451 I/O error"); 197252673Seric setstat(EX_IOERR); 197352673Seric } 197458680Seric (void) xfclose(f, "mailfile", filename); 19754214Seric (void) fflush(stdout); 19764417Seric 19776887Seric /* reset ISUID & ISGID bits for paranoid systems */ 19784621Seric (void) chmod(filename, (int) stb.st_mode); 197952673Seric exit(ExitStat); 19804315Seric /*NOTREACHED*/ 19814214Seric } 19824214Seric else 19834214Seric { 19844214Seric /* parent -- wait for exit status */ 19859370Seric int st; 19864214Seric 19879370Seric st = waitfor(pid); 19889370Seric if ((st & 0377) != 0) 19899370Seric return (EX_UNAVAILABLE); 19909370Seric else 19919370Seric return ((st >> 8) & 0377); 199240931Srick /*NOTREACHED*/ 19934214Seric } 1994294Seric } 19954550Seric /* 199657454Seric ** HOSTSIGNATURE -- return the "signature" for a host. 199757454Seric ** 199857454Seric ** The signature describes how we are going to send this -- it 199957454Seric ** can be just the hostname (for non-Internet hosts) or can be 200057454Seric ** an ordered list of MX hosts. 200157454Seric ** 200257454Seric ** Parameters: 200357454Seric ** m -- the mailer describing this host. 200457454Seric ** host -- the host name. 200557454Seric ** e -- the current envelope. 200657454Seric ** 200757454Seric ** Returns: 200857454Seric ** The signature for this host. 200957454Seric ** 201057454Seric ** Side Effects: 201157454Seric ** Can tweak the symbol table. 201257454Seric */ 201357454Seric 201457454Seric char * 201557454Seric hostsignature(m, host, e) 201657454Seric register MAILER *m; 201757454Seric char *host; 201857454Seric ENVELOPE *e; 201957454Seric { 202057454Seric register char *p; 202157454Seric register STAB *s; 202257454Seric int i; 202357454Seric int len; 202457454Seric #ifdef NAMED_BIND 202557454Seric int nmx; 202657454Seric auto int rcode; 202759076Seric char *hp; 202859076Seric char *endp; 202959111Seric int oldoptions; 203057454Seric char *mxhosts[MAXMXHOSTS + 1]; 203157454Seric #endif 203257454Seric 203357454Seric /* 203457454Seric ** Check to see if this uses IPC -- if not, it can't have MX records. 203557454Seric */ 203657454Seric 203757454Seric p = m->m_mailer; 203857454Seric if (strcmp(p, "[IPC]") != 0 && strcmp(p, "[TCP]") != 0) 203957454Seric { 204057454Seric /* just an ordinary mailer */ 204157454Seric return host; 204257454Seric } 204357454Seric 204457454Seric /* 204557454Seric ** If it is a numeric address, just return it. 204657454Seric */ 204757454Seric 204857454Seric if (host[0] == '[') 204957454Seric return host; 205057454Seric 205157454Seric /* 205257454Seric ** Look it up in the symbol table. 205357454Seric */ 205457454Seric 205557454Seric s = stab(host, ST_HOSTSIG, ST_ENTER); 205657454Seric if (s->s_hostsig != NULL) 205757454Seric return s->s_hostsig; 205857454Seric 205957454Seric /* 206057454Seric ** Not already there -- create a signature. 206157454Seric */ 206257454Seric 206357454Seric #ifdef NAMED_BIND 206459111Seric if (ConfigLevel < 2) 206559111Seric { 206659111Seric oldoptions = _res.options; 206759111Seric _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ 206859111Seric } 206959111Seric 207059076Seric for (hp = host; hp != NULL; hp = endp) 207157454Seric { 207259076Seric endp = strchr(hp, ':'); 207359076Seric if (endp != NULL) 207459076Seric *endp = '\0'; 207557454Seric 207659273Seric nmx = getmxrr(hp, mxhosts, TRUE, &rcode); 207757454Seric 207859076Seric if (nmx <= 0) 207959076Seric { 208059076Seric register MCI *mci; 208159076Seric extern int errno; 208257454Seric 208359076Seric /* update the connection info for this host */ 208459076Seric mci = mci_get(hp, m); 208559076Seric mci->mci_exitstat = rcode; 208659076Seric mci->mci_errno = errno; 208763753Seric #ifdef NAMED_BIND 208863753Seric mci->mci_herrno = h_errno; 208963753Seric #endif 209059076Seric 209159076Seric /* and return the original host name as the signature */ 209259076Seric nmx = 1; 209359076Seric mxhosts[0] = hp; 209459076Seric } 209559076Seric 209659076Seric len = 0; 209759076Seric for (i = 0; i < nmx; i++) 209859076Seric { 209959076Seric len += strlen(mxhosts[i]) + 1; 210059076Seric } 210159076Seric if (s->s_hostsig != NULL) 210259076Seric len += strlen(s->s_hostsig) + 1; 210359076Seric p = xalloc(len); 210459076Seric if (s->s_hostsig != NULL) 210559076Seric { 210659076Seric (void) strcpy(p, s->s_hostsig); 210759076Seric free(s->s_hostsig); 210859076Seric s->s_hostsig = p; 210959076Seric p += strlen(p); 211057454Seric *p++ = ':'; 211159076Seric } 211259076Seric else 211359076Seric s->s_hostsig = p; 211459076Seric for (i = 0; i < nmx; i++) 211559076Seric { 211659076Seric if (i != 0) 211759076Seric *p++ = ':'; 211859076Seric strcpy(p, mxhosts[i]); 211959076Seric p += strlen(p); 212059076Seric } 212159076Seric if (endp != NULL) 212259076Seric *endp++ = ':'; 212357454Seric } 212457454Seric makelower(s->s_hostsig); 212559111Seric if (ConfigLevel < 2) 212659111Seric _res.options = oldoptions; 212757454Seric #else 212857454Seric /* not using BIND -- the signature is just the host name */ 212957454Seric s->s_hostsig = host; 213057454Seric #endif 213157454Seric if (tTd(17, 1)) 213257454Seric printf("hostsignature(%s) = %s\n", host, s->s_hostsig); 213357454Seric return s->s_hostsig; 213457454Seric } 2135