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*63993Seric static char sccsid[] = "@(#)deliver.c 8.7 (Berkeley) 07/22/93"; 1133728Sbostic #endif /* not lint */ 1222701Sdist 1340961Sbostic #include "sendmail.h" 1458153Seric #include <signal.h> 1533931Sbostic #include <netdb.h> 1633931Sbostic #include <errno.h> 1735651Seric #ifdef NAMED_BIND 1834022Sbostic #include <arpa/nameser.h> 1934022Sbostic #include <resolv.h> 2063753Seric 2163753Seric extern int h_errno; 2235651Seric #endif 23294Seric 24294Seric /* 2558820Seric ** SENDALL -- actually send all the messages. 2658820Seric ** 2758820Seric ** Parameters: 2858820Seric ** e -- the envelope to send. 2958820Seric ** mode -- the delivery mode to use. If SM_DEFAULT, use 3058820Seric ** the current e->e_sendmode. 3158820Seric ** 3258820Seric ** Returns: 3358820Seric ** none. 3458820Seric ** 3558820Seric ** Side Effects: 3658820Seric ** Scans the send lists and sends everything it finds. 3758820Seric ** Delivers any appropriate error messages. 3858820Seric ** If we are running in a non-interactive mode, takes the 3958820Seric ** appropriate action. 4058820Seric */ 4158820Seric 4258820Seric sendall(e, mode) 4358820Seric ENVELOPE *e; 4458820Seric char mode; 4558820Seric { 4658820Seric register ADDRESS *q; 4758820Seric char *owner; 4858820Seric int otherowners; 4958820Seric register ENVELOPE *ee; 5058820Seric ENVELOPE *splitenv = NULL; 5158929Seric bool announcequeueup; 5258820Seric 5363839Seric /* 5463839Seric ** If we have had global, fatal errors, don't bother sending 5563839Seric ** the message at all if we are in SMTP mode. Local errors 5663839Seric ** (e.g., a single address failing) will still cause the other 5763839Seric ** addresses to be sent. 5863839Seric */ 5963839Seric 6063839Seric if (bitset(EF_FATALERRS, e->e_flags) && OpMode == MD_SMTP) 6161092Seric { 6261092Seric e->e_flags |= EF_CLRQUEUE; 6361092Seric return; 6461092Seric } 6561092Seric 6658820Seric /* determine actual delivery mode */ 6758820Seric if (mode == SM_DEFAULT) 6858820Seric { 6958820Seric mode = e->e_sendmode; 7058820Seric if (mode != SM_VERIFY && 7158820Seric shouldqueue(e->e_msgpriority, e->e_ctime)) 7258820Seric mode = SM_QUEUE; 7358929Seric announcequeueup = mode == SM_QUEUE; 7458820Seric } 7558929Seric else 7658929Seric announcequeueup = FALSE; 7758820Seric 7858820Seric if (tTd(13, 1)) 7958820Seric { 8058820Seric printf("\nSENDALL: mode %c, e_from ", mode); 8158820Seric printaddr(&e->e_from, FALSE); 8258820Seric printf("sendqueue:\n"); 8358820Seric printaddr(e->e_sendqueue, TRUE); 8458820Seric } 8558820Seric 8658820Seric /* 8758820Seric ** Do any preprocessing necessary for the mode we are running. 8858820Seric ** Check to make sure the hop count is reasonable. 8958820Seric ** Delete sends to the sender in mailing lists. 9058820Seric */ 9158820Seric 9258820Seric CurEnv = e; 9358820Seric 9458820Seric if (e->e_hopcount > MaxHopCount) 9558820Seric { 9658820Seric errno = 0; 9758820Seric syserr("554 too many hops %d (%d max): from %s, to %s", 9858820Seric e->e_hopcount, MaxHopCount, e->e_from.q_paddr, 9958820Seric e->e_sendqueue->q_paddr); 10058820Seric return; 10158820Seric } 10258820Seric 10359435Seric /* 10459435Seric ** Do sender deletion. 10559435Seric ** 10659435Seric ** If the sender has the QQUEUEUP flag set, skip this. 10759435Seric ** This can happen if the name server is hosed when you 10859435Seric ** are trying to send mail. The result is that the sender 10959435Seric ** is instantiated in the queue as a recipient. 11059435Seric */ 11159435Seric 11259435Seric if (!MeToo && !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; 22858820Seric ee->e_df = newstr(queuename(ee, 'd')); 22958820Seric if (link(e->e_df, ee->e_df) < 0) 23058820Seric { 23158820Seric syserr("sendall: link(%s, %s)", 23258820Seric e->e_df, ee->e_df); 23358820Seric } 23458820Seric } 23558820Seric 23658820Seric if (mode != SM_VERIFY) 23758820Seric openxscript(ee); 23858820Seric #ifdef LOG 23958820Seric if (LogLevel > 4) 24058820Seric syslog(LOG_INFO, "%s: clone %s", 24158820Seric ee->e_id, e->e_id); 24258820Seric #endif 24358820Seric } 24458820Seric } 24558820Seric 24658820Seric if (owner != NULL) 24758820Seric { 24858820Seric setsender(owner, e, NULL, TRUE); 24958820Seric if (tTd(13, 5)) 25058820Seric { 25158820Seric printf("sendall(owner): QDONTSEND "); 25258820Seric printaddr(&e->e_from, FALSE); 25358820Seric } 25458820Seric e->e_from.q_flags |= QDONTSEND; 25558820Seric e->e_errormode = EM_MAIL; 25658820Seric } 25758820Seric 25858916Seric # ifdef QUEUE 25958916Seric if ((mode == SM_QUEUE || mode == SM_FORK || 26058916Seric (mode != SM_VERIFY && SuperSafe)) && 26158916Seric !bitset(EF_INQUEUE, e->e_flags)) 26258916Seric { 26358916Seric /* be sure everything is instantiated in the queue */ 26458929Seric queueup(e, TRUE, announcequeueup); 26558916Seric for (ee = splitenv; ee != NULL; ee = ee->e_sibling) 26658929Seric queueup(ee, TRUE, announcequeueup); 26758916Seric } 26858916Seric #endif /* QUEUE */ 26958916Seric 27058820Seric if (splitenv != NULL) 27158820Seric { 27258820Seric if (tTd(13, 1)) 27358820Seric { 27458820Seric printf("\nsendall: Split queue; remaining queue:\n"); 27558820Seric printaddr(e->e_sendqueue, TRUE); 27658820Seric } 27758820Seric 27858820Seric for (ee = splitenv; ee != NULL; ee = ee->e_sibling) 27958820Seric { 28058820Seric CurEnv = ee; 28158820Seric sendenvelope(ee, mode); 28258820Seric } 28358820Seric 28458820Seric CurEnv = e; 28558820Seric } 28658820Seric sendenvelope(e, mode); 28758820Seric 28858820Seric for (; splitenv != NULL; splitenv = splitenv->e_sibling) 28958820Seric dropenvelope(splitenv); 29058820Seric } 29158820Seric 29258820Seric sendenvelope(e, mode) 29358820Seric register ENVELOPE *e; 29458820Seric char mode; 29558820Seric { 29658916Seric bool oldverbose; 29758916Seric int pid; 29858820Seric register ADDRESS *q; 29958916Seric #ifdef LOCKF 30058916Seric struct flock lfd; 30158916Seric #endif 30258820Seric 30363839Seric /* 30463839Seric ** If we have had global, fatal errors, don't bother sending 30563839Seric ** the message at all if we are in SMTP mode. Local errors 30663839Seric ** (e.g., a single address failing) will still cause the other 30763839Seric ** addresses to be sent. 30863839Seric */ 30963839Seric 31063839Seric if (bitset(EF_FATALERRS, e->e_flags) && OpMode == MD_SMTP) 31163839Seric { 31263839Seric e->e_flags |= EF_CLRQUEUE; 31363839Seric return; 31463839Seric } 31563839Seric 31658916Seric oldverbose = Verbose; 31758916Seric switch (mode) 31858916Seric { 31958916Seric case SM_VERIFY: 32058916Seric Verbose = TRUE; 32158916Seric break; 32258916Seric 32358916Seric case SM_QUEUE: 32458916Seric queueonly: 32558916Seric e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; 32658916Seric return; 32758916Seric 32858916Seric case SM_FORK: 32958916Seric if (e->e_xfp != NULL) 33058916Seric (void) fflush(e->e_xfp); 33158916Seric 33258916Seric # ifdef LOCKF 33358916Seric /* 33458916Seric ** Since lockf has the interesting semantic that the 33558916Seric ** lock is lost when we fork, we have to risk losing 33658916Seric ** the lock here by closing before the fork, and then 33758916Seric ** trying to get it back in the child. 33858916Seric */ 33958916Seric 34058916Seric if (e->e_lockfp != NULL) 34158916Seric { 34258916Seric (void) xfclose(e->e_lockfp, "sendenvelope", "lockfp"); 34358916Seric e->e_lockfp = NULL; 34458916Seric } 34558916Seric # endif /* LOCKF */ 34658916Seric 34758916Seric pid = fork(); 34858916Seric if (pid < 0) 34958916Seric { 35058916Seric goto queueonly; 35158916Seric } 35258916Seric else if (pid > 0) 35358916Seric { 35458916Seric /* be sure we leave the temp files to our child */ 35558916Seric e->e_id = e->e_df = NULL; 35658916Seric # ifndef LOCKF 35758916Seric if (e->e_lockfp != NULL) 35858916Seric { 35958916Seric (void) xfclose(e->e_lockfp, "sendenvelope", "lockfp"); 36058916Seric e->e_lockfp = NULL; 36158916Seric } 36258916Seric # endif 36358916Seric 36458916Seric /* close any random open files in the envelope */ 36558916Seric if (e->e_dfp != NULL) 36658916Seric { 36758916Seric (void) xfclose(e->e_dfp, "sendenvelope", "dfp"); 36858916Seric e->e_dfp = NULL; 36958916Seric } 37058916Seric if (e->e_xfp != NULL) 37158916Seric { 37258916Seric (void) xfclose(e->e_xfp, "sendenvelope", "xfp"); 37358916Seric e->e_xfp = NULL; 37458916Seric } 37558916Seric return; 37658916Seric } 37758916Seric 37858916Seric /* double fork to avoid zombies */ 37958916Seric if (fork() > 0) 38058916Seric exit(EX_OK); 38158916Seric 38258916Seric /* be sure we are immune from the terminal */ 38363839Seric disconnect(1, e); 38458916Seric 38558916Seric # ifdef LOCKF 38658916Seric /* 38758916Seric ** Now try to get our lock back. 38858916Seric */ 38958916Seric 39058916Seric lfd.l_type = F_WRLCK; 39158916Seric lfd.l_whence = lfd.l_start = lfd.l_len = 0; 39258916Seric e->e_lockfp = fopen(queuename(e, 'q'), "r+"); 39358916Seric if (e->e_lockfp == NULL || 39458916Seric fcntl(fileno(e->e_lockfp), F_SETLK, &lfd) < 0) 39558916Seric { 39658916Seric /* oops.... lost it */ 39758916Seric if (tTd(13, 1)) 39858916Seric printf("sendenvelope: %s lost lock: lockfp=%x, %s\n", 39958916Seric e->e_id, e->e_lockfp, errstring(errno)); 40058916Seric 40158916Seric # ifdef LOG 40258916Seric if (LogLevel > 29) 40358916Seric syslog(LOG_NOTICE, "%s: lost lock: %m", 40458916Seric e->e_id); 40558916Seric # endif /* LOG */ 40658916Seric exit(EX_OK); 40758916Seric } 40858916Seric # endif /* LOCKF */ 40958916Seric 41058916Seric /* 41158916Seric ** Close any cached connections. 41258916Seric ** 41358916Seric ** We don't send the QUIT protocol because the parent 41458916Seric ** still knows about the connection. 41558916Seric ** 41658916Seric ** This should only happen when delivering an error 41758916Seric ** message. 41858916Seric */ 41958916Seric 42058916Seric mci_flush(FALSE, NULL); 42158916Seric 42258916Seric break; 42358916Seric } 42458916Seric 42558820Seric /* 42658820Seric ** Run through the list and send everything. 42763965Seric ** 42863965Seric ** Set EF_GLOBALERRS so that error messages during delivery 42963965Seric ** result in returned mail. 43058820Seric */ 43158820Seric 43258820Seric e->e_nsent = 0; 43363965Seric e->e_flags |= EF_GLOBALERRS; 43458820Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 43558820Seric { 43658820Seric if (mode == SM_VERIFY) 43758820Seric { 43858820Seric e->e_to = q->q_paddr; 43958820Seric if (!bitset(QDONTSEND|QBADADDR, q->q_flags)) 44060173Seric { 44160173Seric message("deliverable: mailer %s, host %s, user %s", 44260173Seric q->q_mailer->m_name, 44360173Seric q->q_host, 44460173Seric q->q_user); 44560173Seric } 44658820Seric } 44758820Seric else if (!bitset(QDONTSEND|QBADADDR, q->q_flags)) 44858820Seric { 44958820Seric # ifdef QUEUE 45058820Seric /* 45158820Seric ** Checkpoint the send list every few addresses 45258820Seric */ 45358820Seric 45458820Seric if (e->e_nsent >= CheckpointInterval) 45558820Seric { 45658820Seric queueup(e, TRUE, FALSE); 45758820Seric e->e_nsent = 0; 45858820Seric } 45958820Seric # endif /* QUEUE */ 46058820Seric (void) deliver(e, q); 46158820Seric } 46258820Seric } 46358820Seric Verbose = oldverbose; 46458820Seric 46558820Seric if (mode == SM_FORK) 46658820Seric finis(); 46758820Seric } 46858820Seric /* 46958820Seric ** DOFORK -- do a fork, retrying a couple of times on failure. 47058820Seric ** 47158820Seric ** This MUST be a macro, since after a vfork we are running 47258820Seric ** two processes on the same stack!!! 47358820Seric ** 47458820Seric ** Parameters: 47558820Seric ** none. 47658820Seric ** 47758820Seric ** Returns: 47858820Seric ** From a macro??? You've got to be kidding! 47958820Seric ** 48058820Seric ** Side Effects: 48158820Seric ** Modifies the ==> LOCAL <== variable 'pid', leaving: 48258820Seric ** pid of child in parent, zero in child. 48358820Seric ** -1 on unrecoverable error. 48458820Seric ** 48558820Seric ** Notes: 48658820Seric ** I'm awfully sorry this looks so awful. That's 48758820Seric ** vfork for you..... 48858820Seric */ 48958820Seric 49058820Seric # define NFORKTRIES 5 49158820Seric 49258820Seric # ifndef FORK 49358820Seric # define FORK fork 49458820Seric # endif 49558820Seric 49658820Seric # define DOFORK(fORKfN) \ 49758820Seric {\ 49858820Seric register int i;\ 49958820Seric \ 50058820Seric for (i = NFORKTRIES; --i >= 0; )\ 50158820Seric {\ 50258820Seric pid = fORKfN();\ 50358820Seric if (pid >= 0)\ 50458820Seric break;\ 50558820Seric if (i > 0)\ 50658820Seric sleep((unsigned) NFORKTRIES - i);\ 50758820Seric }\ 50858820Seric } 50958820Seric /* 51058820Seric ** DOFORK -- simple fork interface to DOFORK. 51158820Seric ** 51258820Seric ** Parameters: 51358820Seric ** none. 51458820Seric ** 51558820Seric ** Returns: 51658820Seric ** pid of child in parent. 51758820Seric ** zero in child. 51858820Seric ** -1 on error. 51958820Seric ** 52058820Seric ** Side Effects: 52158820Seric ** returns twice, once in parent and once in child. 52258820Seric */ 52358820Seric 52458820Seric dofork() 52558820Seric { 52658820Seric register int pid; 52758820Seric 52858820Seric DOFORK(fork); 52958820Seric return (pid); 53058820Seric } 53158820Seric /* 5324315Seric ** DELIVER -- Deliver a message to a list of addresses. 533294Seric ** 5344315Seric ** This routine delivers to everyone on the same host as the 5354315Seric ** user on the head of the list. It is clever about mailers 5364315Seric ** that don't handle multiple users. It is NOT guaranteed 5374315Seric ** that it will deliver to all these addresses however -- so 5384315Seric ** deliver should be called once for each address on the 5394315Seric ** list. 5404315Seric ** 541294Seric ** Parameters: 5429370Seric ** e -- the envelope to deliver. 5434621Seric ** firstto -- head of the address list to deliver to. 544294Seric ** 545294Seric ** Returns: 546294Seric ** zero -- successfully delivered. 547294Seric ** else -- some failure, see ExitStat for more info. 548294Seric ** 549294Seric ** Side Effects: 550294Seric ** The standard input is passed off to someone. 551294Seric */ 552294Seric 5539370Seric deliver(e, firstto) 5549370Seric register ENVELOPE *e; 5554621Seric ADDRESS *firstto; 556294Seric { 5574452Seric char *host; /* host being sent to */ 5584452Seric char *user; /* user being sent to */ 559294Seric char **pvp; 5603233Seric register char **mvp; 5613233Seric register char *p; 56210306Seric register MAILER *m; /* mailer for this recipient */ 5634397Seric ADDRESS *ctladdr; 56454967Seric register MCI *mci; 5654621Seric register ADDRESS *to = firstto; 5664863Seric bool clever = FALSE; /* running user smtp to this mailer */ 5675032Seric ADDRESS *tochain = NULL; /* chain of users in this mailer call */ 56851951Seric int rcode; /* response code */ 56957454Seric char *firstsig; /* signature of firstto */ 57058820Seric int pid; 57158820Seric char *curhost; 57258820Seric int mpvect[2]; 57358820Seric int rpvect[2]; 57410306Seric char *pv[MAXPV+1]; 57558704Seric char tobuf[TOBUFSIZE]; /* text line of to people */ 57610306Seric char buf[MAXNAME]; 57751951Seric char rpathbuf[MAXNAME]; /* translated return path */ 57857441Seric extern int checkcompat(); 57958820Seric extern FILE *fdopen(); 580294Seric 5814488Seric errno = 0; 58258680Seric if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags)) 5833233Seric return (0); 584294Seric 58535651Seric #ifdef NAMED_BIND 58634022Sbostic /* unless interactive, try twice, over a minute */ 58734022Sbostic if (OpMode == MD_DAEMON || OpMode == MD_SMTP) { 58834022Sbostic _res.retrans = 30; 58934022Sbostic _res.retry = 2; 59034022Sbostic } 59136788Sbostic #endif 59234022Sbostic 5936974Seric m = to->q_mailer; 5946974Seric host = to->q_host; 59558803Seric CurEnv = e; /* just in case */ 59659044Seric e->e_statmsg = NULL; 5976974Seric 5987672Seric if (tTd(10, 1)) 5993233Seric printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n", 6006974Seric m->m_mno, host, to->q_user); 601294Seric 602294Seric /* 6035903Seric ** If this mailer is expensive, and if we don't want to make 6045903Seric ** connections now, just mark these addresses and return. 6055903Seric ** This is useful if we want to batch connections to 6065903Seric ** reduce load. This will cause the messages to be 6075903Seric ** queued up, and a daemon will come along to send the 6085903Seric ** messages later. 6095903Seric ** This should be on a per-mailer basis. 6105903Seric */ 6115903Seric 61258737Seric if (NoConnect && !bitset(EF_QUEUERUN, e->e_flags) && 61358737Seric bitnset(M_EXPENSIVE, m->m_flags) && !Verbose) 6145903Seric { 6155903Seric for (; to != NULL; to = to->q_next) 6168431Seric { 61758680Seric if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags) || 61858247Seric to->q_mailer != m) 6198431Seric continue; 62063853Seric to->q_flags |= QQUEUEUP; 6219370Seric e->e_to = to->q_paddr; 62258151Seric message("queued"); 62358020Seric if (LogLevel > 8) 62458337Seric logdelivery(m, NULL, "queued", e); 6258431Seric } 6269370Seric e->e_to = NULL; 6275903Seric return (0); 6285903Seric } 6295903Seric 6305903Seric /* 6313233Seric ** Do initial argv setup. 6323233Seric ** Insert the mailer name. Notice that $x expansion is 6333233Seric ** NOT done on the mailer name. Then, if the mailer has 6343233Seric ** a picky -f flag, we insert it as appropriate. This 6353233Seric ** code does not check for 'pv' overflow; this places a 6363233Seric ** manifest lower limit of 4 for MAXPV. 6378062Seric ** The from address rewrite is expected to make 6388062Seric ** the address relative to the other end. 6392968Seric */ 6402968Seric 6414452Seric /* rewrite from address, using rewriting rules */ 64259163Seric rcode = EX_OK; 64359163Seric (void) strcpy(rpathbuf, remotename(e->e_from.q_paddr, m, 64459163Seric RF_SENDERADDR|RF_CANONICAL, 64559163Seric &rcode, e)); 64658680Seric define('g', rpathbuf, e); /* translated return path */ 6479370Seric define('h', host, e); /* to host */ 6483233Seric Errors = 0; 6493233Seric pvp = pv; 6503233Seric *pvp++ = m->m_argv[0]; 6512968Seric 6523233Seric /* insert -f or -r flag as appropriate */ 65310682Seric if (FromFlag && (bitnset(M_FOPT, m->m_flags) || bitnset(M_ROPT, m->m_flags))) 6543233Seric { 65510682Seric if (bitnset(M_FOPT, m->m_flags)) 6563233Seric *pvp++ = "-f"; 6573233Seric else 6583233Seric *pvp++ = "-r"; 65951951Seric *pvp++ = newstr(rpathbuf); 6603233Seric } 661294Seric 662294Seric /* 6633233Seric ** Append the other fixed parts of the argv. These run 6643233Seric ** up to the first entry containing "$u". There can only 6653233Seric ** be one of these, and there are only a few more slots 6663233Seric ** in the pv after it. 667294Seric */ 668294Seric 6693233Seric for (mvp = m->m_argv; (p = *++mvp) != NULL; ) 670294Seric { 67158050Seric /* can't use strchr here because of sign extension problems */ 67258050Seric while (*p != '\0') 67358050Seric { 67458050Seric if ((*p++ & 0377) == MACROEXPAND) 67558050Seric { 67658050Seric if (*p == 'u') 67758050Seric break; 67858050Seric } 67958050Seric } 68058050Seric 68158050Seric if (*p != '\0') 6823233Seric break; 6833233Seric 6843233Seric /* this entry is safe -- go ahead and process it */ 6859370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 6863233Seric *pvp++ = newstr(buf); 6873233Seric if (pvp >= &pv[MAXPV - 3]) 6883233Seric { 68958151Seric syserr("554 Too many parameters to %s before $u", pv[0]); 6903233Seric return (-1); 6913233Seric } 692294Seric } 6934863Seric 6946038Seric /* 6956038Seric ** If we have no substitution for the user name in the argument 6966038Seric ** list, we know that we must supply the names otherwise -- and 6976038Seric ** SMTP is the answer!! 6986038Seric */ 6996038Seric 7003233Seric if (*mvp == NULL) 7014863Seric { 7024863Seric /* running SMTP */ 7035179Seric # ifdef SMTP 7044863Seric clever = TRUE; 7054863Seric *pvp = NULL; 70656795Seric # else /* SMTP */ 7076038Seric /* oops! we don't implement SMTP */ 70858151Seric syserr("554 SMTP style mailer"); 7095179Seric return (EX_SOFTWARE); 71056795Seric # endif /* SMTP */ 7114863Seric } 712294Seric 713294Seric /* 7143233Seric ** At this point *mvp points to the argument with $u. We 7153233Seric ** run through our address list and append all the addresses 7163233Seric ** we can. If we run out of space, do not fret! We can 7173233Seric ** always send another copy later. 718294Seric */ 719294Seric 7203233Seric tobuf[0] = '\0'; 7219370Seric e->e_to = tobuf; 7224397Seric ctladdr = NULL; 72357454Seric firstsig = hostsignature(firstto->q_mailer, firstto->q_host, e); 7243233Seric for (; to != NULL; to = to->q_next) 725294Seric { 7263233Seric /* avoid sending multiple recipients to dumb mailers */ 72710682Seric if (tobuf[0] != '\0' && !bitnset(M_MUSER, m->m_flags)) 7283233Seric break; 7293233Seric 7303233Seric /* if already sent or not for this host, don't send */ 73158680Seric if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags) || 73257454Seric to->q_mailer != firstto->q_mailer || 73357454Seric strcmp(hostsignature(to->q_mailer, to->q_host, e), firstsig) != 0) 7343233Seric continue; 7354397Seric 7368225Seric /* avoid overflowing tobuf */ 73742462Sbostic if (sizeof tobuf < (strlen(to->q_paddr) + strlen(tobuf) + 2)) 7388225Seric break; 7398225Seric 7407672Seric if (tTd(10, 1)) 7415032Seric { 7425032Seric printf("\nsend to "); 7435032Seric printaddr(to, FALSE); 7445032Seric } 7455032Seric 7464397Seric /* compute effective uid/gid when sending */ 7474596Seric if (to->q_mailer == ProgMailer) 7484397Seric ctladdr = getctladdr(to); 7494397Seric 7503233Seric user = to->q_user; 7519370Seric e->e_to = to->q_paddr; 75257731Seric if (tTd(10, 5)) 75357731Seric { 75457731Seric printf("deliver: QDONTSEND "); 75557731Seric printaddr(to, FALSE); 75657731Seric } 75758680Seric to->q_flags |= QDONTSEND; 7583233Seric 7593233Seric /* 7603233Seric ** Check to see that these people are allowed to 7613233Seric ** talk to each other. 7623233Seric */ 7633233Seric 76410699Seric if (m->m_maxsize != 0 && e->e_msgsize > m->m_maxsize) 76510699Seric { 76629914Seric NoReturn = TRUE; 76758151Seric usrerr("552 Message is too large; %ld bytes max", m->m_maxsize); 76858337Seric giveresponse(EX_UNAVAILABLE, m, NULL, e); 76910699Seric continue; 77010699Seric } 77157441Seric rcode = checkcompat(to, e); 77257459Seric if (rcode != EX_OK) 773294Seric { 77463787Seric markfailure(e, to, rcode); 77558337Seric giveresponse(rcode, m, NULL, e); 7763233Seric continue; 777294Seric } 7783233Seric 7793233Seric /* 7804099Seric ** Strip quote bits from names if the mailer is dumb 7814099Seric ** about them. 7823233Seric */ 7833233Seric 78410682Seric if (bitnset(M_STRIPQ, m->m_flags)) 785294Seric { 78654983Seric stripquotes(user); 78754983Seric stripquotes(host); 7883233Seric } 7893233Seric 7909206Seric /* hack attack -- delivermail compatibility */ 7919206Seric if (m == ProgMailer && *user == '|') 7929206Seric user++; 7939206Seric 7943233Seric /* 7954161Seric ** If an error message has already been given, don't 7964161Seric ** bother to send to this address. 7974161Seric ** 7984161Seric ** >>>>>>>>>> This clause assumes that the local mailer 7994161Seric ** >> NOTE >> cannot do any further aliasing; that 8004161Seric ** >>>>>>>>>> function is subsumed by sendmail. 8014161Seric */ 8024161Seric 8037293Seric if (bitset(QBADADDR|QQUEUEUP, to->q_flags)) 8044161Seric continue; 8054161Seric 8064283Seric /* save statistics.... */ 8079370Seric markstats(e, to); 8084283Seric 8094161Seric /* 8103233Seric ** See if this user name is "special". 8113233Seric ** If the user name has a slash in it, assume that this 8126974Seric ** is a file -- send it off without further ado. Note 8136974Seric ** that this type of addresses is not processed along 8146974Seric ** with the others, so we fudge on the To person. 8153233Seric */ 8163233Seric 81757402Seric if (m == FileMailer) 8183233Seric { 81957402Seric rcode = mailfile(user, getctladdr(to), e); 82058337Seric giveresponse(rcode, m, NULL, e); 82157402Seric if (rcode == EX_OK) 82257402Seric to->q_flags |= QSENT; 82357402Seric continue; 824294Seric } 8253233Seric 8264315Seric /* 8274315Seric ** Address is verified -- add this user to mailer 8284315Seric ** argv, and add it to the print list of recipients. 8294315Seric */ 8304315Seric 8316059Seric /* link together the chain of recipients */ 8326272Seric to->q_tchain = tochain; 8336272Seric tochain = to; 8346059Seric 8353233Seric /* create list of users for error messages */ 8369388Seric (void) strcat(tobuf, ","); 8374082Seric (void) strcat(tobuf, to->q_paddr); 8389370Seric define('u', user, e); /* to user */ 8399370Seric define('z', to->q_home, e); /* user's home */ 8403233Seric 8414863Seric /* 8426059Seric ** Expand out this user into argument list. 8434863Seric */ 8444863Seric 8456059Seric if (!clever) 8463233Seric { 8479370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 8484863Seric *pvp++ = newstr(buf); 8494863Seric if (pvp >= &pv[MAXPV - 2]) 8504863Seric { 8514863Seric /* allow some space for trailing parms */ 8524863Seric break; 8534863Seric } 8544863Seric } 855294Seric } 856294Seric 8574067Seric /* see if any addresses still exist */ 8584067Seric if (tobuf[0] == '\0') 8594863Seric { 8609370Seric define('g', (char *) NULL, e); 8614067Seric return (0); 8624863Seric } 8634067Seric 8643233Seric /* print out messages as full list */ 8659388Seric e->e_to = tobuf + 1; 8663233Seric 867294Seric /* 8683233Seric ** Fill out any parameters after the $u parameter. 869294Seric */ 870294Seric 8714863Seric while (!clever && *++mvp != NULL) 872294Seric { 8739370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 8743233Seric *pvp++ = newstr(buf); 8753233Seric if (pvp >= &pv[MAXPV]) 87658151Seric syserr("554 deliver: pv overflow after $u for %s", pv[0]); 877294Seric } 8783233Seric *pvp++ = NULL; 879294Seric 880294Seric /* 881294Seric ** Call the mailer. 8822898Seric ** The argument vector gets built, pipes 883294Seric ** are created as necessary, and we fork & exec as 8842898Seric ** appropriate. 8854863Seric ** If we are running SMTP, we just need to clean up. 886294Seric */ 887294Seric 88858309Seric if (ctladdr == NULL && m != ProgMailer) 88941050Seric ctladdr = &e->e_from; 89035651Seric #ifdef NAMED_BIND 89151313Seric if (ConfigLevel < 2) 89251313Seric _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ 89335651Seric #endif 89454967Seric 8957672Seric if (tTd(11, 1)) 896294Seric { 8978178Seric printf("openmailer:"); 89858820Seric printav(pv); 899294Seric } 9004488Seric errno = 0; 9013233Seric 90225050Seric CurHostName = m->m_mailer; 90325050Seric 9046038Seric /* 9056038Seric ** Deal with the special case of mail handled through an IPC 9066038Seric ** connection. 9076038Seric ** In this case we don't actually fork. We must be 9086038Seric ** running SMTP for this to work. We will return a 9096038Seric ** zero pid to indicate that we are running IPC. 91011160Seric ** We also handle a debug version that just talks to stdin/out. 9116038Seric */ 9126038Seric 91358820Seric curhost = NULL; 91458820Seric 91511160Seric /* check for Local Person Communication -- not for mortals!!! */ 91611160Seric if (strcmp(m->m_mailer, "[LPC]") == 0) 91711160Seric { 91854967Seric mci = (MCI *) xalloc(sizeof *mci); 91954993Seric bzero((char *) mci, sizeof *mci); 92053738Seric mci->mci_in = stdin; 92153738Seric mci->mci_out = stdout; 92254967Seric mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN; 92353751Seric mci->mci_mailer = m; 92411160Seric } 92554967Seric else if (strcmp(m->m_mailer, "[IPC]") == 0 || 92654967Seric strcmp(m->m_mailer, "[TCP]") == 0) 9276038Seric { 92852107Seric #ifdef DAEMON 92957454Seric register int i; 9307285Seric register u_short port; 9316038Seric 93258820Seric CurHostName = pv[1]; 93358820Seric curhost = hostsignature(m, pv[1], e); 93454967Seric 93558479Seric if (curhost == NULL || curhost[0] == '\0') 93658479Seric { 93758479Seric syserr("null signature"); 93858820Seric rcode = EX_OSERR; 93958820Seric goto give_up; 94058479Seric } 94158479Seric 9426038Seric if (!clever) 94358479Seric { 94458151Seric syserr("554 non-clever IPC"); 94558820Seric rcode = EX_OSERR; 94658820Seric goto give_up; 94758479Seric } 94858820Seric if (pv[2] != NULL) 94958820Seric port = atoi(pv[2]); 9506632Seric else 9517285Seric port = 0; 95258820Seric tryhost: 95358820Seric mci = NULL; 95457454Seric while (*curhost != '\0') 95529433Sbloom { 95657454Seric register char *p; 95758664Seric static char hostbuf[MAXNAME]; 95857454Seric 95958820Seric mci = NULL; 96058820Seric 96157454Seric /* pull the next host from the signature */ 96257454Seric p = strchr(curhost, ':'); 96357454Seric if (p == NULL) 96457454Seric p = &curhost[strlen(curhost)]; 96557454Seric strncpy(hostbuf, curhost, p - curhost); 96657454Seric hostbuf[p - curhost] = '\0'; 96757454Seric if (*p != '\0') 96857454Seric p++; 96957454Seric curhost = p; 97057454Seric 97153738Seric /* see if we already know that this host is fried */ 97257454Seric CurHostName = hostbuf; 97357454Seric mci = mci_get(hostbuf, m); 97454967Seric if (mci->mci_state != MCIS_CLOSED) 97557387Seric { 97657387Seric if (tTd(11, 1)) 97757387Seric { 97857387Seric printf("openmailer: "); 97957387Seric mci_dump(mci); 98057387Seric } 98157943Seric CurHostName = mci->mci_host; 98258820Seric break; 98357387Seric } 98453751Seric mci->mci_mailer = m; 98554967Seric if (mci->mci_exitstat != EX_OK) 98654967Seric continue; 98754967Seric 98854967Seric /* try the connection */ 98957454Seric setproctitle("%s %s: %s", e->e_id, hostbuf, "user open"); 99058151Seric message("Connecting to %s (%s)...", 99157454Seric hostbuf, m->m_name); 99257454Seric i = makeconnection(hostbuf, port, mci, 99354967Seric bitnset(M_SECURE_PORT, m->m_flags)); 99454967Seric mci->mci_exitstat = i; 99554967Seric mci->mci_errno = errno; 99663753Seric #ifdef NAMED_BIND 99763753Seric mci->mci_herrno = h_errno; 99863753Seric #endif 99954967Seric if (i == EX_OK) 100052106Seric { 100154967Seric mci->mci_state = MCIS_OPENING; 100254967Seric mci_cache(mci); 100363753Seric if (TrafficLogFile != NULL) 100463753Seric fprintf(TrafficLogFile, "%05d == CONNECT %s\n", 100563753Seric getpid(), hostbuf); 100654967Seric break; 100734022Sbostic } 100854967Seric else if (tTd(11, 1)) 100954967Seric printf("openmailer: makeconnection => stat=%d, errno=%d\n", 101054967Seric i, errno); 101153738Seric 101254967Seric 101353738Seric /* enter status of this host */ 101453738Seric setstat(i); 10156047Seric } 101654993Seric mci->mci_pid = 0; 101754967Seric #else /* no DAEMON */ 101858151Seric syserr("554 openmailer: no IPC"); 101957387Seric if (tTd(11, 1)) 102057387Seric printf("openmailer: NULL\n"); 102153738Seric return NULL; 102254967Seric #endif /* DAEMON */ 10236038Seric } 102454967Seric else 1025294Seric { 102663753Seric #ifdef XDEBUG 102763753Seric char wbuf[MAXLINE]; 102858852Seric 102958852Seric /* make absolutely certain 0, 1, and 2 are in use */ 103063753Seric sprintf(wbuf, "%s... openmailer(%s)", e->e_to, m->m_name); 103163753Seric checkfd012(wbuf); 103263753Seric #endif 103363753Seric 103463753Seric if (TrafficLogFile != NULL) 103558852Seric { 103663753Seric char **av; 103758925Seric 103863753Seric fprintf(TrafficLogFile, "%05d === EXEC", getpid()); 103963753Seric for (av = pv; *av != NULL; av++) 104063753Seric fprintf(TrafficLogFile, " %s", *av); 104163753Seric fprintf(TrafficLogFile, "\n"); 104258852Seric } 104358852Seric 104454967Seric /* create a pipe to shove the mail through */ 104554967Seric if (pipe(mpvect) < 0) 104654967Seric { 104758925Seric syserr("%s... openmailer(%s): pipe (to mailer)", 104858925Seric e->e_to, m->m_name); 104957387Seric if (tTd(11, 1)) 105057387Seric printf("openmailer: NULL\n"); 105158820Seric rcode = EX_OSERR; 105258820Seric goto give_up; 105354967Seric } 10544863Seric 105554967Seric /* if this mailer speaks smtp, create a return pipe */ 105654967Seric if (clever && pipe(rpvect) < 0) 105754967Seric { 105858925Seric syserr("%s... openmailer(%s): pipe (from mailer)", 105958925Seric e->e_to, m->m_name); 106054967Seric (void) close(mpvect[0]); 106154967Seric (void) close(mpvect[1]); 106257387Seric if (tTd(11, 1)) 106357387Seric printf("openmailer: NULL\n"); 106458820Seric rcode = EX_OSERR; 106558820Seric goto give_up; 106654967Seric } 10674863Seric 106854967Seric /* 106954967Seric ** Actually fork the mailer process. 107054967Seric ** DOFORK is clever about retrying. 107154967Seric ** 107254967Seric ** Dispose of SIGCHLD signal catchers that may be laying 107354967Seric ** around so that endmail will get it. 107454967Seric */ 10756038Seric 107654967Seric if (e->e_xfp != NULL) 107754967Seric (void) fflush(e->e_xfp); /* for debugging */ 107854967Seric (void) fflush(stdout); 107926434Seric # ifdef SIGCHLD 108054967Seric (void) signal(SIGCHLD, SIG_DFL); 108156795Seric # endif /* SIGCHLD */ 108254967Seric DOFORK(FORK); 108354967Seric /* pid is set by DOFORK */ 108454967Seric if (pid < 0) 10854863Seric { 108654967Seric /* failure */ 108758925Seric syserr("%s... openmailer(%s): cannot fork", 108858925Seric e->e_to, m->m_name); 108954967Seric (void) close(mpvect[0]); 109054967Seric (void) close(mpvect[1]); 109154967Seric if (clever) 109254967Seric { 109354967Seric (void) close(rpvect[0]); 109454967Seric (void) close(rpvect[1]); 109554967Seric } 109657387Seric if (tTd(11, 1)) 109757387Seric printf("openmailer: NULL\n"); 109858820Seric rcode = EX_OSERR; 109958820Seric goto give_up; 11004863Seric } 110154967Seric else if (pid == 0) 110254967Seric { 110354967Seric int i; 110456678Seric int saveerrno; 110558675Seric char **ep; 110658675Seric char *env[MAXUSERENVIRON]; 110758675Seric extern char **environ; 110854967Seric extern int DtableSize; 110915772Seric 111054967Seric /* child -- set up input & exec mailer */ 111154967Seric /* make diagnostic output be standard output */ 111254967Seric (void) signal(SIGINT, SIG_IGN); 111354967Seric (void) signal(SIGHUP, SIG_IGN); 111454967Seric (void) signal(SIGTERM, SIG_DFL); 11154709Seric 111658082Seric /* close any other cached connections */ 111758082Seric mci_flush(FALSE, mci); 111858082Seric 111958935Seric /* move into some "safe" directory */ 112058935Seric if (m->m_execdir != NULL) 112158935Seric { 112258935Seric char *p, *q; 112358935Seric char buf[MAXLINE]; 112458935Seric 112558935Seric for (p = m->m_execdir; p != NULL; p = q) 112658935Seric { 112758935Seric q = strchr(p, ':'); 112858935Seric if (q != NULL) 112958935Seric *q = '\0'; 113058935Seric expand(p, buf, &buf[sizeof buf] - 1, e); 113158935Seric if (q != NULL) 113258935Seric *q++ = ':'; 113358935Seric if (tTd(11, 20)) 113458935Seric printf("openmailer: trydir %s\n", 113558935Seric buf); 113658935Seric if (buf[0] != '\0' && chdir(buf) >= 0) 113758935Seric break; 113858935Seric } 113958935Seric } 114058935Seric 114154967Seric /* arrange to filter std & diag output of command */ 114254967Seric if (clever) 114354967Seric { 114454967Seric (void) close(rpvect[0]); 114558852Seric if (dup2(rpvect[1], STDOUT_FILENO) < 0) 114658852Seric { 114758925Seric syserr("%s... openmailer(%s): cannot dup pipe %d for stdout", 114858925Seric e->e_to, m->m_name, rpvect[1]); 114958852Seric _exit(EX_OSERR); 115058852Seric } 115154967Seric (void) close(rpvect[1]); 115254967Seric } 115354967Seric else if (OpMode == MD_SMTP || HoldErrs) 115454967Seric { 115554967Seric /* put mailer output in transcript */ 115658852Seric if (dup2(fileno(e->e_xfp), STDOUT_FILENO) < 0) 115758852Seric { 115858925Seric syserr("%s... openmailer(%s): cannot dup xscript %d for stdout", 115958925Seric e->e_to, m->m_name, 116058852Seric fileno(e->e_xfp)); 116158852Seric _exit(EX_OSERR); 116258852Seric } 116354967Seric } 116458852Seric if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) 116558852Seric { 116658925Seric syserr("%s... openmailer(%s): cannot dup stdout for stderr", 116758925Seric e->e_to, m->m_name); 116858852Seric _exit(EX_OSERR); 116958852Seric } 11704709Seric 117154967Seric /* arrange to get standard input */ 117254967Seric (void) close(mpvect[1]); 117358731Seric if (dup2(mpvect[0], STDIN_FILENO) < 0) 11744417Seric { 117558925Seric syserr("%s... openmailer(%s): cannot dup pipe %d for stdin", 117658925Seric e->e_to, m->m_name, mpvect[0]); 117754967Seric _exit(EX_OSERR); 11784417Seric } 117954967Seric (void) close(mpvect[0]); 118054967Seric if (!bitnset(M_RESTR, m->m_flags)) 11814415Seric { 118254967Seric if (ctladdr == NULL || ctladdr->q_uid == 0) 118354967Seric { 118454967Seric (void) setgid(DefGid); 118554967Seric (void) initgroups(DefUser, DefGid); 118654967Seric (void) setuid(DefUid); 118754967Seric } 118854967Seric else 118954967Seric { 119054967Seric (void) setgid(ctladdr->q_gid); 119154967Seric (void) initgroups(ctladdr->q_ruser? 119254967Seric ctladdr->q_ruser: ctladdr->q_user, 119354967Seric ctladdr->q_gid); 119454967Seric (void) setuid(ctladdr->q_uid); 119554967Seric } 11964415Seric } 11979370Seric 119854967Seric /* arrange for all the files to be closed */ 119954967Seric for (i = 3; i < DtableSize; i++) 120054967Seric { 120154967Seric register int j; 120254967Seric if ((j = fcntl(i, F_GETFD, 0)) != -1) 120354967Seric (void)fcntl(i, F_SETFD, j|1); 120454967Seric } 12052774Seric 120658675Seric /* set up the mailer environment */ 120758675Seric i = 0; 120858675Seric env[i++] = "AGENT=sendmail"; 120958675Seric for (ep = environ; *ep != NULL; ep++) 121058675Seric { 121158675Seric if (strncmp(*ep, "TZ=", 3) == 0) 121258675Seric env[i++] = *ep; 121358675Seric } 121458675Seric env[i++] = NULL; 121558675Seric 121654967Seric /* try to execute the mailer */ 121758820Seric execve(m->m_mailer, pv, env); 121856678Seric saveerrno = errno; 121954967Seric syserr("Cannot exec %s", m->m_mailer); 122060008Seric if (m == LocalMailer || transienterror(saveerrno)) 122160008Seric _exit(EX_OSERR); 122254967Seric _exit(EX_UNAVAILABLE); 122351835Seric } 122454967Seric 122554967Seric /* 122654967Seric ** Set up return value. 122754967Seric */ 122854967Seric 122954967Seric mci = (MCI *) xalloc(sizeof *mci); 123054993Seric bzero((char *) mci, sizeof *mci); 123154967Seric mci->mci_mailer = m; 123254967Seric mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN; 123354993Seric mci->mci_pid = pid; 123454967Seric (void) close(mpvect[0]); 123554967Seric mci->mci_out = fdopen(mpvect[1], "w"); 123654967Seric if (clever) 123754967Seric { 123854967Seric (void) close(rpvect[1]); 123954967Seric mci->mci_in = fdopen(rpvect[0], "r"); 124054967Seric } 124154967Seric else 124254967Seric { 124354967Seric mci->mci_flags |= MCIF_TEMP; 124454967Seric mci->mci_in = NULL; 124554967Seric } 1246294Seric } 1247294Seric 12484709Seric /* 124954967Seric ** If we are in SMTP opening state, send initial protocol. 12504709Seric */ 12514709Seric 125254967Seric if (clever && mci->mci_state != MCIS_CLOSED) 12534863Seric { 125454967Seric smtpinit(m, mci, e); 125553738Seric } 125657387Seric if (tTd(11, 1)) 125757387Seric { 125857387Seric printf("openmailer: "); 125957387Seric mci_dump(mci); 126057387Seric } 1261294Seric 126258820Seric if (mci->mci_state != MCIS_OPEN) 126358820Seric { 126458820Seric /* couldn't open the mailer */ 126558820Seric rcode = mci->mci_exitstat; 126658820Seric errno = mci->mci_errno; 126763753Seric #ifdef NAMED_BIND 126863753Seric h_errno = mci->mci_herrno; 126963753Seric #endif 127058820Seric if (rcode == EX_OK) 127158820Seric { 127258820Seric /* shouldn't happen */ 127358820Seric syserr("554 deliver: rcode=%d, mci_state=%d, sig=%s", 127458820Seric rcode, mci->mci_state, firstsig); 127558820Seric rcode = EX_SOFTWARE; 127658820Seric } 127759993Seric else if (rcode == EX_TEMPFAIL && *curhost != '\0') 127859958Seric { 127959958Seric /* try next MX site */ 128059958Seric goto tryhost; 128159958Seric } 128258820Seric } 128358820Seric else if (!clever) 128458820Seric { 128558820Seric /* 128658820Seric ** Format and send message. 128758820Seric */ 128858820Seric 128958820Seric putfromline(mci->mci_out, m, e); 129058820Seric (*e->e_puthdr)(mci->mci_out, m, e); 129158820Seric putline("\n", mci->mci_out, m); 129259730Seric (*e->e_putbody)(mci->mci_out, m, e, NULL); 129358820Seric 129458820Seric /* get the exit status */ 129558820Seric rcode = endmailer(mci, e, pv); 129658820Seric } 129758820Seric else 129858820Seric #ifdef SMTP 129958820Seric { 130058820Seric /* 130158820Seric ** Send the MAIL FROM: protocol 130258820Seric */ 130358820Seric 130458820Seric rcode = smtpmailfrom(m, mci, e); 130558820Seric if (rcode == EX_OK) 130658820Seric { 130758820Seric register char *t = tobuf; 130858820Seric register int i; 130958820Seric 131058820Seric /* send the recipient list */ 131158820Seric tobuf[0] = '\0'; 131258820Seric for (to = tochain; to != NULL; to = to->q_tchain) 131358820Seric { 131458820Seric e->e_to = to->q_paddr; 131558820Seric if ((i = smtprcpt(to, m, mci, e)) != EX_OK) 131658820Seric { 131758820Seric markfailure(e, to, i); 131858820Seric giveresponse(i, m, mci, e); 131958820Seric } 132058820Seric else 132158820Seric { 132258820Seric *t++ = ','; 132358820Seric for (p = to->q_paddr; *p; *t++ = *p++) 132458820Seric continue; 132558820Seric } 132658820Seric } 132758820Seric 132858820Seric /* now send the data */ 132958820Seric if (tobuf[0] == '\0') 133058820Seric { 133158820Seric rcode = EX_OK; 133258820Seric e->e_to = NULL; 133358820Seric if (bitset(MCIF_CACHED, mci->mci_flags)) 133458820Seric smtprset(m, mci, e); 133558820Seric } 133658820Seric else 133758820Seric { 133858820Seric e->e_to = tobuf + 1; 133958820Seric rcode = smtpdata(m, mci, e); 134058820Seric } 134158820Seric 134258820Seric /* now close the connection */ 134358820Seric if (!bitset(MCIF_CACHED, mci->mci_flags)) 134458820Seric smtpquit(m, mci, e); 134558820Seric } 134658820Seric if (rcode != EX_OK && *curhost != '\0') 134758820Seric { 134858820Seric /* try next MX site */ 134958820Seric goto tryhost; 135058820Seric } 135158820Seric } 135258820Seric #else /* not SMTP */ 135358820Seric { 135458820Seric syserr("554 deliver: need SMTP compiled to use clever mailer"); 135558820Seric rcode = EX_CONFIG; 135658820Seric goto give_up; 135758820Seric } 135858820Seric #endif /* SMTP */ 135958820Seric #ifdef NAMED_BIND 136058820Seric if (ConfigLevel < 2) 136158820Seric _res.options |= RES_DEFNAMES | RES_DNSRCH; /* XXX */ 136258820Seric #endif 136358820Seric 136458820Seric /* arrange a return receipt if requested */ 136558820Seric if (e->e_receiptto != NULL && bitnset(M_LOCALMAILER, m->m_flags)) 136658820Seric { 136758820Seric e->e_flags |= EF_SENDRECEIPT; 136858820Seric /* do we want to send back more info? */ 136958820Seric } 137058820Seric 137158820Seric /* 137258820Seric ** Do final status disposal. 137358820Seric ** We check for something in tobuf for the SMTP case. 137458820Seric ** If we got a temporary failure, arrange to queue the 137558820Seric ** addressees. 137658820Seric */ 137758820Seric 137858820Seric give_up: 137958820Seric if (tobuf[0] != '\0') 138058820Seric giveresponse(rcode, m, mci, e); 138158820Seric for (to = tochain; to != NULL; to = to->q_tchain) 138258820Seric { 138358820Seric if (rcode != EX_OK) 138458820Seric markfailure(e, to, rcode); 138558820Seric else 138658820Seric { 138758820Seric to->q_flags |= QSENT; 138858820Seric e->e_nsent++; 138958820Seric } 139058820Seric } 139158820Seric 139258820Seric /* 139358820Seric ** Restore state and return. 139458820Seric */ 139558820Seric 139658820Seric errno = 0; 139758820Seric define('g', (char *) NULL, e); 139858820Seric return (rcode); 1399294Seric } 1400294Seric /* 140158820Seric ** MARKFAILURE -- mark a failure on a specific address. 140258820Seric ** 140358820Seric ** Parameters: 140458820Seric ** e -- the envelope we are sending. 140558820Seric ** q -- the address to mark. 140658820Seric ** rcode -- the code signifying the particular failure. 140758820Seric ** 140858820Seric ** Returns: 140958820Seric ** none. 141058820Seric ** 141158820Seric ** Side Effects: 141258820Seric ** marks the address (and possibly the envelope) with the 141358820Seric ** failure so that an error will be returned or 141458820Seric ** the message will be queued, as appropriate. 141558820Seric */ 141658820Seric 141758820Seric markfailure(e, q, rcode) 141858820Seric register ENVELOPE *e; 141958820Seric register ADDRESS *q; 142058820Seric int rcode; 142158820Seric { 142258820Seric char buf[MAXLINE]; 142358820Seric 142458820Seric if (rcode == EX_OK) 142558820Seric return; 142663753Seric else if (rcode == EX_TEMPFAIL) 142763753Seric q->q_flags |= QQUEUEUP; 142863753Seric else if (rcode != EX_IOERR && rcode != EX_OSERR) 142958820Seric q->q_flags |= QBADADDR; 143058820Seric } 143158820Seric /* 143258820Seric ** ENDMAILER -- Wait for mailer to terminate. 143358820Seric ** 143458820Seric ** We should never get fatal errors (e.g., segmentation 143558820Seric ** violation), so we report those specially. For other 143658820Seric ** errors, we choose a status message (into statmsg), 143758820Seric ** and if it represents an error, we print it. 143858820Seric ** 143958820Seric ** Parameters: 144058820Seric ** pid -- pid of mailer. 144158820Seric ** e -- the current envelope. 144258820Seric ** pv -- the parameter vector that invoked the mailer 144358820Seric ** (for error messages). 144458820Seric ** 144558820Seric ** Returns: 144658820Seric ** exit code of mailer. 144758820Seric ** 144858820Seric ** Side Effects: 144958820Seric ** none. 145058820Seric */ 145158820Seric 145258820Seric endmailer(mci, e, pv) 145358820Seric register MCI *mci; 145458820Seric register ENVELOPE *e; 145558820Seric char **pv; 145658820Seric { 145758820Seric int st; 145858820Seric 145958820Seric /* close any connections */ 146058820Seric if (mci->mci_in != NULL) 146158820Seric (void) xfclose(mci->mci_in, pv[0], "mci_in"); 146258820Seric if (mci->mci_out != NULL) 146358820Seric (void) xfclose(mci->mci_out, pv[0], "mci_out"); 146458820Seric mci->mci_in = mci->mci_out = NULL; 146558820Seric mci->mci_state = MCIS_CLOSED; 146658820Seric 146758820Seric /* in the IPC case there is nothing to wait for */ 146858820Seric if (mci->mci_pid == 0) 146958820Seric return (EX_OK); 147058820Seric 147158820Seric /* wait for the mailer process to die and collect status */ 147258820Seric st = waitfor(mci->mci_pid); 147358820Seric if (st == -1) 147458820Seric { 147558820Seric syserr("endmailer %s: wait", pv[0]); 147658820Seric return (EX_SOFTWARE); 147758820Seric } 147858820Seric 147958820Seric /* see if it died a horrid death */ 148058820Seric if ((st & 0377) != 0) 148158820Seric { 148258820Seric syserr("mailer %s died with signal %o", pv[0], st); 148358820Seric 148458820Seric /* log the arguments */ 148558820Seric if (e->e_xfp != NULL) 148658820Seric { 148758820Seric register char **av; 148858820Seric 148958820Seric fprintf(e->e_xfp, "Arguments:"); 149058820Seric for (av = pv; *av != NULL; av++) 149158820Seric fprintf(e->e_xfp, " %s", *av); 149258820Seric fprintf(e->e_xfp, "\n"); 149358820Seric } 149458820Seric 149558820Seric ExitStat = EX_TEMPFAIL; 149658820Seric return (EX_TEMPFAIL); 149758820Seric } 149858820Seric 149958820Seric /* normal death -- return status */ 150058820Seric st = (st >> 8) & 0377; 150158820Seric return (st); 150258820Seric } 150358820Seric /* 1504294Seric ** GIVERESPONSE -- Interpret an error response from a mailer 1505294Seric ** 1506294Seric ** Parameters: 1507294Seric ** stat -- the status code from the mailer (high byte 1508294Seric ** only; core dumps must have been taken care of 1509294Seric ** already). 151058337Seric ** m -- the mailer info for this mailer. 151158337Seric ** mci -- the mailer connection info -- can be NULL if the 151258337Seric ** response is given before the connection is made. 151358337Seric ** e -- the current envelope. 1514294Seric ** 1515294Seric ** Returns: 15164082Seric ** none. 1517294Seric ** 1518294Seric ** Side Effects: 15191518Seric ** Errors may be incremented. 1520294Seric ** ExitStat may be set. 1521294Seric */ 1522294Seric 152358337Seric giveresponse(stat, m, mci, e) 1524294Seric int stat; 15259370Seric register MAILER *m; 152658337Seric register MCI *mci; 152710105Seric ENVELOPE *e; 1528294Seric { 152960094Seric register const char *statmsg; 1530294Seric extern char *SysExMsg[]; 1531294Seric register int i; 153236788Sbostic extern int N_SysEx; 153310105Seric char buf[MAXLINE]; 1534294Seric 15354315Seric /* 15364315Seric ** Compute status message from code. 15374315Seric */ 15384315Seric 1539294Seric i = stat - EX__BASE; 15409370Seric if (stat == 0) 154158852Seric { 15429370Seric statmsg = "250 Sent"; 154358916Seric if (e->e_statmsg != NULL) 154458852Seric { 154558916Seric (void) sprintf(buf, "%s (%s)", statmsg, e->e_statmsg); 154658852Seric statmsg = buf; 154758852Seric } 154858852Seric } 15499370Seric else if (i < 0 || i > N_SysEx) 15509370Seric { 15519370Seric (void) sprintf(buf, "554 unknown mailer error %d", stat); 15529370Seric stat = EX_UNAVAILABLE; 15539370Seric statmsg = buf; 15549370Seric } 155510105Seric else if (stat == EX_TEMPFAIL) 155610105Seric { 155758664Seric (void) strcpy(buf, SysExMsg[i] + 1); 155836788Sbostic #ifdef NAMED_BIND 155925527Smiriam if (h_errno == TRY_AGAIN) 1560*63993Seric statmsg = errstring(h_errno+E_DNSBASE); 156121061Seric else 156236788Sbostic #endif 156321061Seric { 156425527Smiriam if (errno != 0) 156525527Smiriam statmsg = errstring(errno); 156625527Smiriam else 156725527Smiriam { 156821061Seric #ifdef SMTP 156925527Smiriam extern char SmtpError[]; 157021061Seric 157125527Smiriam statmsg = SmtpError; 157256795Seric #else /* SMTP */ 157325527Smiriam statmsg = NULL; 157456795Seric #endif /* SMTP */ 157525527Smiriam } 157621061Seric } 157721061Seric if (statmsg != NULL && statmsg[0] != '\0') 157821061Seric { 157910124Seric (void) strcat(buf, ": "); 158021061Seric (void) strcat(buf, statmsg); 158110105Seric } 158210105Seric statmsg = buf; 158310105Seric } 158463753Seric #ifdef NAMED_BIND 158563753Seric else if (stat == EX_NOHOST && h_errno != 0) 158663753Seric { 1587*63993Seric statmsg = errstring(h_errno + E_DNSBASE); 158863753Seric (void) sprintf(buf, "%s (%s)", SysExMsg[i], statmsg); 158963753Seric statmsg = buf; 159063753Seric } 159163753Seric #endif 1592294Seric else 159321061Seric { 1594294Seric statmsg = SysExMsg[i]; 159558664Seric if (*statmsg++ == ':') 159658664Seric { 159758664Seric (void) sprintf(buf, "%s: %s", statmsg, errstring(errno)); 159858664Seric statmsg = buf; 159958664Seric } 160021061Seric } 16019370Seric 16029370Seric /* 16039370Seric ** Print the message as appropriate 16049370Seric */ 16059370Seric 160610105Seric if (stat == EX_OK || stat == EX_TEMPFAIL) 160758524Seric message(&statmsg[4], errstring(errno)); 1608294Seric else 1609294Seric { 16101518Seric Errors++; 161158524Seric usrerr(statmsg, errstring(errno)); 1612294Seric } 1613294Seric 1614294Seric /* 1615294Seric ** Final cleanup. 1616294Seric ** Log a record of the transaction. Compute the new 1617294Seric ** ExitStat -- if we already had an error, stick with 1618294Seric ** that. 1619294Seric */ 1620294Seric 162158020Seric if (LogLevel > ((stat == EX_TEMPFAIL) ? 8 : (stat == EX_OK) ? 7 : 6)) 162258337Seric logdelivery(m, mci, &statmsg[4], e); 16237858Seric 16244621Seric if (stat != EX_TEMPFAIL) 16254621Seric setstat(stat); 162610105Seric if (stat != EX_OK) 162710105Seric { 162810105Seric if (e->e_message != NULL) 162910105Seric free(e->e_message); 163010105Seric e->e_message = newstr(&statmsg[4]); 163110105Seric } 163210124Seric errno = 0; 163336788Sbostic #ifdef NAMED_BIND 163425527Smiriam h_errno = 0; 163536788Sbostic #endif 1636294Seric } 1637294Seric /* 16388496Seric ** LOGDELIVERY -- log the delivery in the system log 16398496Seric ** 16408496Seric ** Parameters: 164158337Seric ** m -- the mailer info. Can be NULL for initial queue. 164258337Seric ** mci -- the mailer connection info -- can be NULL if the 164358337Seric ** log is occuring when no connection is active. 164458337Seric ** stat -- the message to print for the status. 164558337Seric ** e -- the current envelope. 16468496Seric ** 16478496Seric ** Returns: 16488496Seric ** none 16498496Seric ** 16508496Seric ** Side Effects: 16518496Seric ** none 16528496Seric */ 16538496Seric 165458337Seric logdelivery(m, mci, stat, e) 165558337Seric MAILER *m; 165658337Seric register MCI *mci; 16578496Seric char *stat; 165854967Seric register ENVELOPE *e; 16598496Seric { 166058343Seric # ifdef LOG 166158418Seric char buf[512]; 16628496Seric 166358513Seric (void) sprintf(buf, "delay=%s", pintvl(curtime() - e->e_ctime, TRUE)); 166458337Seric 166558513Seric if (m != NULL) 166658305Seric { 166758513Seric (void) strcat(buf, ", mailer="); 166858513Seric (void) strcat(buf, m->m_name); 166958305Seric } 167058513Seric 167158513Seric if (mci != NULL && mci->mci_host != NULL) 167258305Seric { 167358305Seric # ifdef DAEMON 167458755Seric extern SOCKADDR CurHostAddr; 167558513Seric # endif 167658305Seric 167758513Seric (void) strcat(buf, ", relay="); 167858513Seric (void) strcat(buf, mci->mci_host); 167958513Seric 168058513Seric # ifdef DAEMON 168158513Seric (void) strcat(buf, " ("); 168258755Seric (void) strcat(buf, anynet_ntoa(&CurHostAddr)); 168358513Seric (void) strcat(buf, ")"); 168458305Seric # endif 168558305Seric } 168658343Seric else 168758513Seric { 168858513Seric char *p = macvalue('h', e); 168958343Seric 169058513Seric if (p != NULL && p[0] != '\0') 169158513Seric { 169258513Seric (void) strcat(buf, ", relay="); 169358513Seric (void) strcat(buf, p); 169458513Seric } 169558513Seric } 169658418Seric 169758418Seric syslog(LOG_INFO, "%s: to=%s, %s, stat=%s", 169858418Seric e->e_id, e->e_to, buf, stat); 169956795Seric # endif /* LOG */ 17008496Seric } 17018496Seric /* 17026974Seric ** PUTFROMLINE -- output a UNIX-style from line (or whatever) 1703294Seric ** 17046974Seric ** This can be made an arbitrary message separator by changing $l 1705294Seric ** 170616150Seric ** One of the ugliest hacks seen by human eyes is contained herein: 170716150Seric ** UUCP wants those stupid "remote from <host>" lines. Why oh why 170816150Seric ** does a well-meaning programmer such as myself have to deal with 170916150Seric ** this kind of antique garbage???? 17106974Seric ** 1711294Seric ** Parameters: 17126974Seric ** fp -- the file to output to. 17136974Seric ** m -- the mailer describing this entry. 1714294Seric ** 1715294Seric ** Returns: 17166974Seric ** none 1717294Seric ** 1718294Seric ** Side Effects: 17196974Seric ** outputs some text to fp. 1720294Seric */ 1721294Seric 172254967Seric putfromline(fp, m, e) 17236974Seric register FILE *fp; 17246974Seric register MAILER *m; 172554967Seric ENVELOPE *e; 1726294Seric { 172758050Seric char *template = "\201l\n"; 17286974Seric char buf[MAXLINE]; 1729294Seric 173010682Seric if (bitnset(M_NHDR, m->m_flags)) 17316974Seric return; 17324315Seric 17336974Seric # ifdef UGLYUUCP 173410682Seric if (bitnset(M_UGLYUUCP, m->m_flags)) 17354205Seric { 173612223Seric char *bang; 173712223Seric char xbuf[MAXLINE]; 17386041Seric 173958680Seric expand("\201g", buf, &buf[sizeof buf - 1], e); 174056795Seric bang = strchr(buf, '!'); 17416974Seric if (bang == NULL) 174258151Seric syserr("554 No ! in UUCP! (%s)", buf); 17435099Seric else 17449370Seric { 174512223Seric *bang++ = '\0'; 174658050Seric (void) sprintf(xbuf, "From %s \201d remote from %s\n", bang, buf); 174712223Seric template = xbuf; 17489370Seric } 17496974Seric } 175056795Seric # endif /* UGLYUUCP */ 175154967Seric expand(template, buf, &buf[sizeof buf - 1], e); 175210168Seric putline(buf, fp, m); 17535981Seric } 17545981Seric /* 17556974Seric ** PUTBODY -- put the body of a message. 17566974Seric ** 17576974Seric ** Parameters: 17586974Seric ** fp -- file to output onto. 175910168Seric ** m -- a mailer descriptor to control output format. 17609538Seric ** e -- the envelope to put out. 176159730Seric ** separator -- if non-NULL, a message separator that must 176259730Seric ** not be permitted in the resulting message. 17636974Seric ** 17646974Seric ** Returns: 17656974Seric ** none. 17666974Seric ** 17676974Seric ** Side Effects: 17686974Seric ** The message is written onto fp. 17696974Seric */ 17706974Seric 177159730Seric putbody(fp, m, e, separator) 17726974Seric FILE *fp; 17739370Seric MAILER *m; 17749538Seric register ENVELOPE *e; 177559730Seric char *separator; 17766974Seric { 177710168Seric char buf[MAXLINE]; 17786974Seric 17796974Seric /* 17806974Seric ** Output the body of the message 17816974Seric */ 17826974Seric 17839538Seric if (e->e_dfp == NULL) 17846974Seric { 17859538Seric if (e->e_df != NULL) 17869538Seric { 17879538Seric e->e_dfp = fopen(e->e_df, "r"); 17889538Seric if (e->e_dfp == NULL) 178940931Srick syserr("putbody: Cannot open %s for %s from %s", 179040931Srick e->e_df, e->e_to, e->e_from); 17919538Seric } 17929538Seric else 179310168Seric putline("<<< No Message Collected >>>", fp, m); 17949538Seric } 17959538Seric if (e->e_dfp != NULL) 17969538Seric { 17979538Seric rewind(e->e_dfp); 179810168Seric while (!ferror(fp) && fgets(buf, sizeof buf, e->e_dfp) != NULL) 179916875Seric { 180016875Seric if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) && 180140995Sbostic strncmp(buf, "From ", 5) == 0) 180223102Seric (void) putc('>', fp); 180359730Seric if (buf[0] == '-' && buf[1] == '-' && separator != NULL) 180459730Seric { 180559730Seric /* possible separator */ 180659730Seric int sl = strlen(separator); 180759730Seric 180859730Seric if (strncmp(&buf[2], separator, sl) == 0) 180959730Seric (void) putc(' ', fp); 181059730Seric } 181110168Seric putline(buf, fp, m); 181216875Seric } 18136974Seric 18149538Seric if (ferror(e->e_dfp)) 18156974Seric { 18166974Seric syserr("putbody: read error"); 18176974Seric ExitStat = EX_IOERR; 18186974Seric } 18196974Seric } 18206974Seric 182159542Seric /* some mailers want extra blank line at end of message */ 182259542Seric if (bitnset(M_BLANKEND, m->m_flags) && buf[0] != '\0' && buf[0] != '\n') 182359542Seric putline("", fp, m); 182459542Seric 18256974Seric (void) fflush(fp); 18266974Seric if (ferror(fp) && errno != EPIPE) 18276974Seric { 18286974Seric syserr("putbody: write error"); 18296974Seric ExitStat = EX_IOERR; 18306974Seric } 18316974Seric errno = 0; 18326974Seric } 18336974Seric /* 1834294Seric ** MAILFILE -- Send a message to a file. 1835294Seric ** 18364327Seric ** If the file has the setuid/setgid bits set, but NO execute 18374327Seric ** bits, sendmail will try to become the owner of that file 18384327Seric ** rather than the real user. Obviously, this only works if 18394327Seric ** sendmail runs as root. 18404327Seric ** 18419370Seric ** This could be done as a subordinate mailer, except that it 18429370Seric ** is used implicitly to save messages in ~/dead.letter. We 18439370Seric ** view this as being sufficiently important as to include it 18449370Seric ** here. For example, if the system is dying, we shouldn't have 18459370Seric ** to create another process plus some pipes to save the message. 18469370Seric ** 1847294Seric ** Parameters: 1848294Seric ** filename -- the name of the file to send to. 18494397Seric ** ctladdr -- the controlling address header -- includes 18504397Seric ** the userid/groupid to be when sending. 1851294Seric ** 1852294Seric ** Returns: 1853294Seric ** The exit code associated with the operation. 1854294Seric ** 1855294Seric ** Side Effects: 1856294Seric ** none. 1857294Seric */ 1858294Seric 185954967Seric mailfile(filename, ctladdr, e) 1860294Seric char *filename; 18614397Seric ADDRESS *ctladdr; 186254967Seric register ENVELOPE *e; 1863294Seric { 1864294Seric register FILE *f; 18654214Seric register int pid; 186653751Seric int mode; 1867294Seric 186859267Seric if (tTd(11, 1)) 186959267Seric { 187059267Seric printf("mailfile %s\n ctladdr=", filename); 187159267Seric printaddr(ctladdr, FALSE); 187259267Seric } 187359267Seric 187463753Seric if (e->e_xfp != NULL) 187563753Seric fflush(e->e_xfp); 187663753Seric 18774214Seric /* 18784214Seric ** Fork so we can change permissions here. 18794214Seric ** Note that we MUST use fork, not vfork, because of 18804214Seric ** the complications of calling subroutines, etc. 18814214Seric */ 18824067Seric 18834214Seric DOFORK(fork); 18844214Seric 18854214Seric if (pid < 0) 18864214Seric return (EX_OSERR); 18874214Seric else if (pid == 0) 18884214Seric { 18894214Seric /* child -- actually write to file */ 18904327Seric struct stat stb; 18914327Seric 18924215Seric (void) signal(SIGINT, SIG_DFL); 18934215Seric (void) signal(SIGHUP, SIG_DFL); 18944215Seric (void) signal(SIGTERM, SIG_DFL); 189523102Seric (void) umask(OldUmask); 189652673Seric 18974327Seric if (stat(filename, &stb) < 0) 189859745Seric stb.st_mode = FileMode; 189953751Seric mode = stb.st_mode; 190052673Seric 190152673Seric /* limit the errors to those actually caused in the child */ 190252673Seric errno = 0; 190352673Seric ExitStat = EX_OK; 190452673Seric 19054327Seric if (bitset(0111, stb.st_mode)) 19064327Seric exit(EX_CANTCREAT); 19074401Seric if (ctladdr == NULL) 190840931Srick ctladdr = &e->e_from; 190953751Seric else 191053751Seric { 191153751Seric /* ignore setuid and setgid bits */ 191253751Seric mode &= ~(S_ISGID|S_ISUID); 191353751Seric } 191453751Seric 191540931Srick /* we have to open the dfile BEFORE setuid */ 191653751Seric if (e->e_dfp == NULL && e->e_df != NULL) 191740931Srick { 191840931Srick e->e_dfp = fopen(e->e_df, "r"); 191952673Seric if (e->e_dfp == NULL) 192052673Seric { 192140931Srick syserr("mailfile: Cannot open %s for %s from %s", 192253751Seric e->e_df, e->e_to, e->e_from); 192340931Srick } 192440931Srick } 192540931Srick 192653751Seric if (!bitset(S_ISGID, mode) || setgid(stb.st_gid) < 0) 19274417Seric { 192852673Seric if (ctladdr->q_uid == 0) 192952673Seric { 19304417Seric (void) setgid(DefGid); 193140972Sbostic (void) initgroups(DefUser, DefGid); 193252673Seric } 193352673Seric else 193452673Seric { 19354417Seric (void) setgid(ctladdr->q_gid); 193653751Seric (void) initgroups(ctladdr->q_ruser ? 193753751Seric ctladdr->q_ruser : ctladdr->q_user, 193840972Sbostic ctladdr->q_gid); 193940972Sbostic } 19404417Seric } 194153751Seric if (!bitset(S_ISUID, mode) || setuid(stb.st_uid) < 0) 19424417Seric { 19434417Seric if (ctladdr->q_uid == 0) 19444417Seric (void) setuid(DefUid); 19454417Seric else 19464417Seric (void) setuid(ctladdr->q_uid); 19474417Seric } 194852673Seric FileName = filename; 194952673Seric LineNumber = 0; 195059745Seric f = dfopen(filename, O_WRONLY|O_CREAT|O_APPEND, FileMode); 19514214Seric if (f == NULL) 195252673Seric { 195358151Seric message("554 cannot open"); 19544214Seric exit(EX_CANTCREAT); 195552673Seric } 19564214Seric 195759275Seric putfromline(f, FileMailer, e); 195859275Seric (*e->e_puthdr)(f, FileMailer, e); 195959275Seric putline("\n", f, FileMailer); 196059730Seric (*e->e_putbody)(f, FileMailer, e, NULL); 196159275Seric putline("\n", f, FileMailer); 196252673Seric if (ferror(f)) 196352673Seric { 196458151Seric message("451 I/O error"); 196552673Seric setstat(EX_IOERR); 196652673Seric } 196758680Seric (void) xfclose(f, "mailfile", filename); 19684214Seric (void) fflush(stdout); 19694417Seric 19706887Seric /* reset ISUID & ISGID bits for paranoid systems */ 19714621Seric (void) chmod(filename, (int) stb.st_mode); 197252673Seric exit(ExitStat); 19734315Seric /*NOTREACHED*/ 19744214Seric } 19754214Seric else 19764214Seric { 19774214Seric /* parent -- wait for exit status */ 19789370Seric int st; 19794214Seric 19809370Seric st = waitfor(pid); 19819370Seric if ((st & 0377) != 0) 19829370Seric return (EX_UNAVAILABLE); 19839370Seric else 19849370Seric return ((st >> 8) & 0377); 198540931Srick /*NOTREACHED*/ 19864214Seric } 1987294Seric } 19884550Seric /* 198957454Seric ** HOSTSIGNATURE -- return the "signature" for a host. 199057454Seric ** 199157454Seric ** The signature describes how we are going to send this -- it 199257454Seric ** can be just the hostname (for non-Internet hosts) or can be 199357454Seric ** an ordered list of MX hosts. 199457454Seric ** 199557454Seric ** Parameters: 199657454Seric ** m -- the mailer describing this host. 199757454Seric ** host -- the host name. 199857454Seric ** e -- the current envelope. 199957454Seric ** 200057454Seric ** Returns: 200157454Seric ** The signature for this host. 200257454Seric ** 200357454Seric ** Side Effects: 200457454Seric ** Can tweak the symbol table. 200557454Seric */ 200657454Seric 200757454Seric char * 200857454Seric hostsignature(m, host, e) 200957454Seric register MAILER *m; 201057454Seric char *host; 201157454Seric ENVELOPE *e; 201257454Seric { 201357454Seric register char *p; 201457454Seric register STAB *s; 201557454Seric int i; 201657454Seric int len; 201757454Seric #ifdef NAMED_BIND 201857454Seric int nmx; 201957454Seric auto int rcode; 202059076Seric char *hp; 202159076Seric char *endp; 202259111Seric int oldoptions; 202357454Seric char *mxhosts[MAXMXHOSTS + 1]; 202457454Seric #endif 202557454Seric 202657454Seric /* 202757454Seric ** Check to see if this uses IPC -- if not, it can't have MX records. 202857454Seric */ 202957454Seric 203057454Seric p = m->m_mailer; 203157454Seric if (strcmp(p, "[IPC]") != 0 && strcmp(p, "[TCP]") != 0) 203257454Seric { 203357454Seric /* just an ordinary mailer */ 203457454Seric return host; 203557454Seric } 203657454Seric 203757454Seric /* 203857454Seric ** If it is a numeric address, just return it. 203957454Seric */ 204057454Seric 204157454Seric if (host[0] == '[') 204257454Seric return host; 204357454Seric 204457454Seric /* 204557454Seric ** Look it up in the symbol table. 204657454Seric */ 204757454Seric 204857454Seric s = stab(host, ST_HOSTSIG, ST_ENTER); 204957454Seric if (s->s_hostsig != NULL) 205057454Seric return s->s_hostsig; 205157454Seric 205257454Seric /* 205357454Seric ** Not already there -- create a signature. 205457454Seric */ 205557454Seric 205657454Seric #ifdef NAMED_BIND 205759111Seric if (ConfigLevel < 2) 205859111Seric { 205959111Seric oldoptions = _res.options; 206059111Seric _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ 206159111Seric } 206259111Seric 206359076Seric for (hp = host; hp != NULL; hp = endp) 206457454Seric { 206559076Seric endp = strchr(hp, ':'); 206659076Seric if (endp != NULL) 206759076Seric *endp = '\0'; 206857454Seric 206959273Seric nmx = getmxrr(hp, mxhosts, TRUE, &rcode); 207057454Seric 207159076Seric if (nmx <= 0) 207259076Seric { 207359076Seric register MCI *mci; 207459076Seric extern int errno; 207557454Seric 207659076Seric /* update the connection info for this host */ 207759076Seric mci = mci_get(hp, m); 207859076Seric mci->mci_exitstat = rcode; 207959076Seric mci->mci_errno = errno; 208063753Seric #ifdef NAMED_BIND 208163753Seric mci->mci_herrno = h_errno; 208263753Seric #endif 208359076Seric 208459076Seric /* and return the original host name as the signature */ 208559076Seric nmx = 1; 208659076Seric mxhosts[0] = hp; 208759076Seric } 208859076Seric 208959076Seric len = 0; 209059076Seric for (i = 0; i < nmx; i++) 209159076Seric { 209259076Seric len += strlen(mxhosts[i]) + 1; 209359076Seric } 209459076Seric if (s->s_hostsig != NULL) 209559076Seric len += strlen(s->s_hostsig) + 1; 209659076Seric p = xalloc(len); 209759076Seric if (s->s_hostsig != NULL) 209859076Seric { 209959076Seric (void) strcpy(p, s->s_hostsig); 210059076Seric free(s->s_hostsig); 210159076Seric s->s_hostsig = p; 210259076Seric p += strlen(p); 210357454Seric *p++ = ':'; 210459076Seric } 210559076Seric else 210659076Seric s->s_hostsig = p; 210759076Seric for (i = 0; i < nmx; i++) 210859076Seric { 210959076Seric if (i != 0) 211059076Seric *p++ = ':'; 211159076Seric strcpy(p, mxhosts[i]); 211259076Seric p += strlen(p); 211359076Seric } 211459076Seric if (endp != NULL) 211559076Seric *endp++ = ':'; 211657454Seric } 211757454Seric makelower(s->s_hostsig); 211859111Seric if (ConfigLevel < 2) 211959111Seric _res.options = oldoptions; 212057454Seric #else 212157454Seric /* not using BIND -- the signature is just the host name */ 212257454Seric s->s_hostsig = host; 212357454Seric #endif 212457454Seric if (tTd(17, 1)) 212557454Seric printf("hostsignature(%s) = %s\n", host, s->s_hostsig); 212657454Seric return s->s_hostsig; 212757454Seric } 2128