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*65580Seric static char sccsid[] = "@(#)deliver.c 8.61 (Berkeley) 01/08/94"; 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 2365075Seric extern char SmtpError[]; 2465075Seric 25294Seric /* 2658820Seric ** SENDALL -- actually send all the messages. 2758820Seric ** 2858820Seric ** Parameters: 2958820Seric ** e -- the envelope to send. 3058820Seric ** mode -- the delivery mode to use. If SM_DEFAULT, use 3158820Seric ** the current e->e_sendmode. 3258820Seric ** 3358820Seric ** Returns: 3458820Seric ** none. 3558820Seric ** 3658820Seric ** Side Effects: 3758820Seric ** Scans the send lists and sends everything it finds. 3858820Seric ** Delivers any appropriate error messages. 3958820Seric ** If we are running in a non-interactive mode, takes the 4058820Seric ** appropriate action. 4158820Seric */ 4258820Seric 4358820Seric sendall(e, mode) 4458820Seric ENVELOPE *e; 4558820Seric char mode; 4658820Seric { 4758820Seric register ADDRESS *q; 4858820Seric char *owner; 4958820Seric int otherowners; 5058820Seric register ENVELOPE *ee; 5158820Seric ENVELOPE *splitenv = NULL; 5258929Seric bool announcequeueup; 5358820Seric 5463839Seric /* 5563839Seric ** If we have had global, fatal errors, don't bother sending 5663839Seric ** the message at all if we are in SMTP mode. Local errors 5763839Seric ** (e.g., a single address failing) will still cause the other 5863839Seric ** addresses to be sent. 5963839Seric */ 6063839Seric 61*65580Seric if (bitset(EF_FATALERRS, e->e_flags) && 62*65580Seric (OpMode == MD_SMTP || OpMode == MD_DAEMON)) 6361092Seric { 6461092Seric e->e_flags |= EF_CLRQUEUE; 6561092Seric return; 6661092Seric } 6761092Seric 6858820Seric /* determine actual delivery mode */ 6964826Seric CurrentLA = getla(); 7058820Seric if (mode == SM_DEFAULT) 7158820Seric { 7258820Seric mode = e->e_sendmode; 7358820Seric if (mode != SM_VERIFY && 7458820Seric shouldqueue(e->e_msgpriority, e->e_ctime)) 7558820Seric mode = SM_QUEUE; 7658929Seric announcequeueup = mode == SM_QUEUE; 7758820Seric } 7858929Seric else 7958929Seric announcequeueup = FALSE; 8058820Seric 8158820Seric if (tTd(13, 1)) 8258820Seric { 8364310Seric printf("\n===== SENDALL: mode %c, id %s, e_from ", 8464310Seric mode, e->e_id); 8558820Seric printaddr(&e->e_from, FALSE); 8658820Seric printf("sendqueue:\n"); 8758820Seric printaddr(e->e_sendqueue, TRUE); 8858820Seric } 8958820Seric 9058820Seric /* 9158820Seric ** Do any preprocessing necessary for the mode we are running. 9258820Seric ** Check to make sure the hop count is reasonable. 9358820Seric ** Delete sends to the sender in mailing lists. 9458820Seric */ 9558820Seric 9658820Seric CurEnv = e; 9758820Seric 9858820Seric if (e->e_hopcount > MaxHopCount) 9958820Seric { 10058820Seric errno = 0; 10164495Seric syserr("554 too many hops %d (%d max): from %s via %s, to %s", 10258820Seric e->e_hopcount, MaxHopCount, e->e_from.q_paddr, 10364495Seric RealHostName, e->e_sendqueue->q_paddr); 10458820Seric return; 10558820Seric } 10658820Seric 10759435Seric /* 10859435Seric ** Do sender deletion. 10959435Seric ** 11059435Seric ** If the sender has the QQUEUEUP flag set, skip this. 11159435Seric ** This can happen if the name server is hosed when you 11259435Seric ** are trying to send mail. The result is that the sender 11359435Seric ** is instantiated in the queue as a recipient. 11459435Seric */ 11559435Seric 11664118Seric if (!bitset(EF_METOO, e->e_flags) && 11764118Seric !bitset(QQUEUEUP, e->e_from.q_flags)) 11858820Seric { 11958820Seric if (tTd(13, 5)) 12058820Seric { 12158820Seric printf("sendall: QDONTSEND "); 12258820Seric printaddr(&e->e_from, FALSE); 12358820Seric } 12458820Seric e->e_from.q_flags |= QDONTSEND; 12558820Seric (void) recipient(&e->e_from, &e->e_sendqueue, e); 12658820Seric } 12758820Seric 12858820Seric /* 12958820Seric ** Handle alias owners. 13058820Seric ** 13158820Seric ** We scan up the q_alias chain looking for owners. 13258820Seric ** We discard owners that are the same as the return path. 13358820Seric */ 13458820Seric 13558820Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 13658820Seric { 13758820Seric register struct address *a; 13858820Seric 13958820Seric for (a = q; a != NULL && a->q_owner == NULL; a = a->q_alias) 14058820Seric continue; 14158820Seric if (a != NULL) 14258820Seric q->q_owner = a->q_owner; 14358820Seric 14458820Seric if (q->q_owner != NULL && 14558820Seric !bitset(QDONTSEND, q->q_flags) && 14658820Seric strcmp(q->q_owner, e->e_from.q_paddr) == 0) 14758820Seric q->q_owner = NULL; 14858820Seric } 14958820Seric 15058820Seric owner = ""; 15158820Seric otherowners = 1; 15258820Seric while (owner != NULL && otherowners > 0) 15358820Seric { 15458820Seric owner = NULL; 15558820Seric otherowners = 0; 15658820Seric 15758820Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 15858820Seric { 15958820Seric if (bitset(QDONTSEND, q->q_flags)) 16058820Seric continue; 16158820Seric 16258820Seric if (q->q_owner != NULL) 16358820Seric { 16458820Seric if (owner == NULL) 16558820Seric owner = q->q_owner; 16658820Seric else if (owner != q->q_owner) 16758820Seric { 16858820Seric if (strcmp(owner, q->q_owner) == 0) 16958820Seric { 17058820Seric /* make future comparisons cheap */ 17158820Seric q->q_owner = owner; 17258820Seric } 17358820Seric else 17458820Seric { 17558820Seric otherowners++; 17658820Seric } 17758820Seric owner = q->q_owner; 17858820Seric } 17958820Seric } 18058820Seric else 18158820Seric { 18258820Seric otherowners++; 18358820Seric } 18458820Seric } 18558820Seric 18658820Seric if (owner != NULL && otherowners > 0) 18758820Seric { 18858820Seric extern HDR *copyheader(); 18958820Seric extern ADDRESS *copyqueue(); 19058820Seric 19158820Seric /* 19258820Seric ** Split this envelope into two. 19358820Seric */ 19458820Seric 19558820Seric ee = (ENVELOPE *) xalloc(sizeof(ENVELOPE)); 19658820Seric *ee = *e; 19758820Seric ee->e_id = NULL; 19858820Seric (void) queuename(ee, '\0'); 19958820Seric 20058820Seric if (tTd(13, 1)) 20158820Seric printf("sendall: split %s into %s\n", 20258820Seric e->e_id, ee->e_id); 20358820Seric 20458820Seric ee->e_header = copyheader(e->e_header); 20558820Seric ee->e_sendqueue = copyqueue(e->e_sendqueue); 20658820Seric ee->e_errorqueue = copyqueue(e->e_errorqueue); 20758916Seric ee->e_flags = e->e_flags & ~(EF_INQUEUE|EF_CLRQUEUE|EF_FATALERRS); 20858820Seric setsender(owner, ee, NULL, TRUE); 20958820Seric if (tTd(13, 5)) 21058820Seric { 21158820Seric printf("sendall(split): QDONTSEND "); 21258820Seric printaddr(&ee->e_from, FALSE); 21358820Seric } 21458820Seric ee->e_from.q_flags |= QDONTSEND; 21558820Seric ee->e_dfp = NULL; 21658820Seric ee->e_xfp = NULL; 21758820Seric ee->e_df = NULL; 21858820Seric ee->e_errormode = EM_MAIL; 21958820Seric ee->e_sibling = splitenv; 22058820Seric splitenv = ee; 22158820Seric 22258820Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 22358820Seric if (q->q_owner == owner) 22458820Seric q->q_flags |= QDONTSEND; 22558820Seric for (q = ee->e_sendqueue; q != NULL; q = q->q_next) 22658820Seric if (q->q_owner != owner) 22758820Seric q->q_flags |= QDONTSEND; 22858820Seric 22958820Seric if (e->e_df != NULL && mode != SM_VERIFY) 23058820Seric { 23158820Seric ee->e_dfp = NULL; 23264086Seric ee->e_df = queuename(ee, 'd'); 23364086Seric ee->e_df = newstr(ee->e_df); 23458820Seric if (link(e->e_df, ee->e_df) < 0) 23558820Seric { 23658820Seric syserr("sendall: link(%s, %s)", 23758820Seric e->e_df, ee->e_df); 23858820Seric } 23958820Seric } 24058820Seric 24158820Seric if (mode != SM_VERIFY) 24258820Seric openxscript(ee); 24358820Seric #ifdef LOG 24458820Seric if (LogLevel > 4) 24558820Seric syslog(LOG_INFO, "%s: clone %s", 24658820Seric ee->e_id, e->e_id); 24758820Seric #endif 24858820Seric } 24958820Seric } 25058820Seric 25158820Seric if (owner != NULL) 25258820Seric { 25358820Seric setsender(owner, e, NULL, TRUE); 25458820Seric if (tTd(13, 5)) 25558820Seric { 25658820Seric printf("sendall(owner): QDONTSEND "); 25758820Seric printaddr(&e->e_from, FALSE); 25858820Seric } 25958820Seric e->e_from.q_flags |= QDONTSEND; 26058820Seric e->e_errormode = EM_MAIL; 26158820Seric } 26258820Seric 26358916Seric # ifdef QUEUE 26458916Seric if ((mode == SM_QUEUE || mode == SM_FORK || 26558916Seric (mode != SM_VERIFY && SuperSafe)) && 26658916Seric !bitset(EF_INQUEUE, e->e_flags)) 26758916Seric { 26858916Seric /* be sure everything is instantiated in the queue */ 26958929Seric queueup(e, TRUE, announcequeueup); 27058916Seric for (ee = splitenv; ee != NULL; ee = ee->e_sibling) 27158929Seric queueup(ee, TRUE, announcequeueup); 27258916Seric } 27358916Seric #endif /* QUEUE */ 27458916Seric 27558820Seric if (splitenv != NULL) 27658820Seric { 27758820Seric if (tTd(13, 1)) 27858820Seric { 27958820Seric printf("\nsendall: Split queue; remaining queue:\n"); 28058820Seric printaddr(e->e_sendqueue, TRUE); 28158820Seric } 28258820Seric 28358820Seric for (ee = splitenv; ee != NULL; ee = ee->e_sibling) 28458820Seric { 28558820Seric CurEnv = ee; 28658820Seric sendenvelope(ee, mode); 28758820Seric } 28858820Seric 28958820Seric CurEnv = e; 29058820Seric } 29158820Seric sendenvelope(e, mode); 29258820Seric 29358820Seric for (; splitenv != NULL; splitenv = splitenv->e_sibling) 29458820Seric dropenvelope(splitenv); 29558820Seric } 29658820Seric 29758820Seric sendenvelope(e, mode) 29858820Seric register ENVELOPE *e; 29958820Seric char mode; 30058820Seric { 30158916Seric bool oldverbose; 30258916Seric int pid; 30358820Seric register ADDRESS *q; 30464296Seric char *qf; 30564296Seric char *id; 30658820Seric 30763839Seric /* 30863839Seric ** If we have had global, fatal errors, don't bother sending 30963839Seric ** the message at all if we are in SMTP mode. Local errors 31063839Seric ** (e.g., a single address failing) will still cause the other 31163839Seric ** addresses to be sent. 31263839Seric */ 31363839Seric 314*65580Seric if (bitset(EF_FATALERRS, e->e_flags) && 315*65580Seric (OpMode == MD_SMTP || OpMode == MD_DAEMON)) 31663839Seric { 31763839Seric e->e_flags |= EF_CLRQUEUE; 31863839Seric return; 31963839Seric } 32063839Seric 32158916Seric oldverbose = Verbose; 32258916Seric switch (mode) 32358916Seric { 32458916Seric case SM_VERIFY: 32558916Seric Verbose = TRUE; 32658916Seric break; 32758916Seric 32858916Seric case SM_QUEUE: 32958916Seric queueonly: 33058916Seric e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; 33158916Seric return; 33258916Seric 33358916Seric case SM_FORK: 33458916Seric if (e->e_xfp != NULL) 33558916Seric (void) fflush(e->e_xfp); 33658916Seric 33764035Seric # ifndef HASFLOCK 33858916Seric /* 33964296Seric ** Since fcntl locking has the interesting semantic that 34064296Seric ** the lock is owned by a process, not by an open file 34164296Seric ** descriptor, we have to flush this to the queue, and 34264296Seric ** then restart from scratch in the child. 34358916Seric */ 34458916Seric 34564296Seric /* save id for future use */ 34664296Seric id = e->e_id; 34758916Seric 34864296Seric /* now drop the envelope in the parent */ 34964296Seric e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE; 35064296Seric dropenvelope(e); 35164296Seric 35264296Seric /* and reacquire in the child */ 35364296Seric (void) dowork(id, TRUE, FALSE, e); 35464296Seric 35564296Seric return; 35664296Seric 35764296Seric # else /* HASFLOCK */ 35864296Seric 35958916Seric pid = fork(); 36058916Seric if (pid < 0) 36158916Seric { 36258916Seric goto queueonly; 36358916Seric } 36458916Seric else if (pid > 0) 36558916Seric { 36664310Seric /* be sure we leave the temp files to our child */ 36764310Seric /* can't call unlockqueue to avoid unlink of xfp */ 36864310Seric if (e->e_lockfp != NULL) 36964310Seric (void) xfclose(e->e_lockfp, "sendenvelope", "lockfp"); 37064310Seric e->e_lockfp = NULL; 37164310Seric 37264310Seric /* close any random open files in the envelope */ 37364310Seric closexscript(e); 37464310Seric if (e->e_dfp != NULL) 37564310Seric (void) xfclose(e->e_dfp, "sendenvelope", e->e_df); 37664310Seric e->e_dfp = NULL; 37764310Seric e->e_id = e->e_df = NULL; 37858916Seric return; 37958916Seric } 38058916Seric 38158916Seric /* double fork to avoid zombies */ 38258916Seric if (fork() > 0) 38358916Seric exit(EX_OK); 38458916Seric 38558916Seric /* be sure we are immune from the terminal */ 38663839Seric disconnect(1, e); 38758916Seric 38858916Seric /* 38958916Seric ** Close any cached connections. 39058916Seric ** 39158916Seric ** We don't send the QUIT protocol because the parent 39258916Seric ** still knows about the connection. 39358916Seric ** 39458916Seric ** This should only happen when delivering an error 39558916Seric ** message. 39658916Seric */ 39758916Seric 39858916Seric mci_flush(FALSE, NULL); 39958916Seric 40064296Seric # endif /* HASFLOCK */ 40164296Seric 40258916Seric break; 40358916Seric } 40458916Seric 40558820Seric /* 40658820Seric ** Run through the list and send everything. 40763965Seric ** 40863965Seric ** Set EF_GLOBALERRS so that error messages during delivery 40963965Seric ** result in returned mail. 41058820Seric */ 41158820Seric 41258820Seric e->e_nsent = 0; 41363965Seric e->e_flags |= EF_GLOBALERRS; 41464696Seric 41564696Seric /* now run through the queue */ 41658820Seric for (q = e->e_sendqueue; q != NULL; q = q->q_next) 41758820Seric { 41864441Seric #ifdef XDEBUG 41964441Seric char wbuf[MAXNAME + 20]; 42064441Seric 42164441Seric (void) sprintf(wbuf, "sendall(%s)", q->q_paddr); 42264441Seric checkfd012(wbuf); 42364441Seric #endif 42458820Seric if (mode == SM_VERIFY) 42558820Seric { 42658820Seric e->e_to = q->q_paddr; 42758820Seric if (!bitset(QDONTSEND|QBADADDR, q->q_flags)) 42860173Seric { 42964942Seric if (q->q_host != NULL && q->q_host[0] != '\0') 43064942Seric message("deliverable: mailer %s, host %s, user %s", 43164942Seric q->q_mailer->m_name, 43264942Seric q->q_host, 43364942Seric q->q_user); 43464942Seric else 43564942Seric message("deliverable: mailer %s, user %s", 43664942Seric q->q_mailer->m_name, 43764942Seric q->q_user); 43860173Seric } 43958820Seric } 44058820Seric else if (!bitset(QDONTSEND|QBADADDR, q->q_flags)) 44158820Seric { 44258820Seric # ifdef QUEUE 44358820Seric /* 44458820Seric ** Checkpoint the send list every few addresses 44558820Seric */ 44658820Seric 44758820Seric if (e->e_nsent >= CheckpointInterval) 44858820Seric { 44958820Seric queueup(e, TRUE, FALSE); 45058820Seric e->e_nsent = 0; 45158820Seric } 45258820Seric # endif /* QUEUE */ 45358820Seric (void) deliver(e, q); 45458820Seric } 45558820Seric } 45658820Seric Verbose = oldverbose; 45758820Seric 45864441Seric #ifdef XDEBUG 45964441Seric checkfd012("end of sendenvelope"); 46064441Seric #endif 46164441Seric 46258820Seric if (mode == SM_FORK) 46358820Seric finis(); 46458820Seric } 46558820Seric /* 46658820Seric ** DOFORK -- do a fork, retrying a couple of times on failure. 46758820Seric ** 46858820Seric ** This MUST be a macro, since after a vfork we are running 46958820Seric ** two processes on the same stack!!! 47058820Seric ** 47158820Seric ** Parameters: 47258820Seric ** none. 47358820Seric ** 47458820Seric ** Returns: 47558820Seric ** From a macro??? You've got to be kidding! 47658820Seric ** 47758820Seric ** Side Effects: 47858820Seric ** Modifies the ==> LOCAL <== variable 'pid', leaving: 47958820Seric ** pid of child in parent, zero in child. 48058820Seric ** -1 on unrecoverable error. 48158820Seric ** 48258820Seric ** Notes: 48358820Seric ** I'm awfully sorry this looks so awful. That's 48458820Seric ** vfork for you..... 48558820Seric */ 48658820Seric 48758820Seric # define NFORKTRIES 5 48858820Seric 48958820Seric # ifndef FORK 49058820Seric # define FORK fork 49158820Seric # endif 49258820Seric 49358820Seric # define DOFORK(fORKfN) \ 49458820Seric {\ 49558820Seric register int i;\ 49658820Seric \ 49758820Seric for (i = NFORKTRIES; --i >= 0; )\ 49858820Seric {\ 49958820Seric pid = fORKfN();\ 50058820Seric if (pid >= 0)\ 50158820Seric break;\ 50258820Seric if (i > 0)\ 50358820Seric sleep((unsigned) NFORKTRIES - i);\ 50458820Seric }\ 50558820Seric } 50658820Seric /* 50758820Seric ** DOFORK -- simple fork interface to DOFORK. 50858820Seric ** 50958820Seric ** Parameters: 51058820Seric ** none. 51158820Seric ** 51258820Seric ** Returns: 51358820Seric ** pid of child in parent. 51458820Seric ** zero in child. 51558820Seric ** -1 on error. 51658820Seric ** 51758820Seric ** Side Effects: 51858820Seric ** returns twice, once in parent and once in child. 51958820Seric */ 52058820Seric 52158820Seric dofork() 52258820Seric { 52358820Seric register int pid; 52458820Seric 52558820Seric DOFORK(fork); 52658820Seric return (pid); 52758820Seric } 52858820Seric /* 5294315Seric ** DELIVER -- Deliver a message to a list of addresses. 530294Seric ** 5314315Seric ** This routine delivers to everyone on the same host as the 5324315Seric ** user on the head of the list. It is clever about mailers 5334315Seric ** that don't handle multiple users. It is NOT guaranteed 5344315Seric ** that it will deliver to all these addresses however -- so 5354315Seric ** deliver should be called once for each address on the 5364315Seric ** list. 5374315Seric ** 538294Seric ** Parameters: 5399370Seric ** e -- the envelope to deliver. 5404621Seric ** firstto -- head of the address list to deliver to. 541294Seric ** 542294Seric ** Returns: 543294Seric ** zero -- successfully delivered. 544294Seric ** else -- some failure, see ExitStat for more info. 545294Seric ** 546294Seric ** Side Effects: 547294Seric ** The standard input is passed off to someone. 548294Seric */ 549294Seric 5509370Seric deliver(e, firstto) 5519370Seric register ENVELOPE *e; 5524621Seric ADDRESS *firstto; 553294Seric { 5544452Seric char *host; /* host being sent to */ 5554452Seric char *user; /* user being sent to */ 556294Seric char **pvp; 5573233Seric register char **mvp; 5583233Seric register char *p; 55910306Seric register MAILER *m; /* mailer for this recipient */ 5604397Seric ADDRESS *ctladdr; 56154967Seric register MCI *mci; 5624621Seric register ADDRESS *to = firstto; 5634863Seric bool clever = FALSE; /* running user smtp to this mailer */ 5645032Seric ADDRESS *tochain = NULL; /* chain of users in this mailer call */ 56551951Seric int rcode; /* response code */ 56657454Seric char *firstsig; /* signature of firstto */ 56758820Seric int pid; 56858820Seric char *curhost; 56958820Seric int mpvect[2]; 57058820Seric int rpvect[2]; 57110306Seric char *pv[MAXPV+1]; 57258704Seric char tobuf[TOBUFSIZE]; /* text line of to people */ 57310306Seric char buf[MAXNAME]; 57451951Seric char rpathbuf[MAXNAME]; /* translated return path */ 57557441Seric extern int checkcompat(); 576294Seric 5774488Seric errno = 0; 57858680Seric if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags)) 5793233Seric return (0); 580294Seric 58135651Seric #ifdef NAMED_BIND 58234022Sbostic /* unless interactive, try twice, over a minute */ 583*65580Seric if (OpMode == MD_DAEMON || OpMode == MD_SMTP) 584*65580Seric { 58534022Sbostic _res.retrans = 30; 58634022Sbostic _res.retry = 2; 58734022Sbostic } 58836788Sbostic #endif 58934022Sbostic 5906974Seric m = to->q_mailer; 5916974Seric host = to->q_host; 59258803Seric CurEnv = e; /* just in case */ 59359044Seric e->e_statmsg = NULL; 59464718Seric SmtpError[0] = '\0'; 5956974Seric 5967672Seric if (tTd(10, 1)) 5973233Seric printf("\n--deliver, mailer=%d, host=`%s', first user=`%s'\n", 5986974Seric m->m_mno, host, to->q_user); 59964725Seric if (tTd(10, 100)) 60064725Seric printopenfds(FALSE); 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 61264658Seric if (NoConnect && bitnset(M_EXPENSIVE, m->m_flags) && !Verbose) 6135903Seric { 6145903Seric for (; to != NULL; to = to->q_next) 6158431Seric { 61658680Seric if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags) || 61758247Seric to->q_mailer != m) 6188431Seric continue; 61963853Seric to->q_flags |= QQUEUEUP; 6209370Seric e->e_to = to->q_paddr; 62158151Seric message("queued"); 62258020Seric if (LogLevel > 8) 62364771Seric logdelivery(m, NULL, "queued", NULL, e); 6248431Seric } 6259370Seric e->e_to = NULL; 6265903Seric return (0); 6275903Seric } 6285903Seric 6295903Seric /* 6303233Seric ** Do initial argv setup. 6313233Seric ** Insert the mailer name. Notice that $x expansion is 6323233Seric ** NOT done on the mailer name. Then, if the mailer has 6333233Seric ** a picky -f flag, we insert it as appropriate. This 6343233Seric ** code does not check for 'pv' overflow; this places a 6353233Seric ** manifest lower limit of 4 for MAXPV. 6368062Seric ** The from address rewrite is expected to make 6378062Seric ** the address relative to the other end. 6382968Seric */ 6392968Seric 6404452Seric /* rewrite from address, using rewriting rules */ 64159163Seric rcode = EX_OK; 64259163Seric (void) strcpy(rpathbuf, remotename(e->e_from.q_paddr, m, 64359163Seric RF_SENDERADDR|RF_CANONICAL, 64459163Seric &rcode, e)); 64558680Seric define('g', rpathbuf, e); /* translated return path */ 6469370Seric define('h', host, e); /* to host */ 6473233Seric Errors = 0; 6483233Seric pvp = pv; 6493233Seric *pvp++ = m->m_argv[0]; 6502968Seric 6513233Seric /* insert -f or -r flag as appropriate */ 65210682Seric if (FromFlag && (bitnset(M_FOPT, m->m_flags) || bitnset(M_ROPT, m->m_flags))) 6533233Seric { 65410682Seric if (bitnset(M_FOPT, m->m_flags)) 6553233Seric *pvp++ = "-f"; 6563233Seric else 6573233Seric *pvp++ = "-r"; 65851951Seric *pvp++ = newstr(rpathbuf); 6593233Seric } 660294Seric 661294Seric /* 6623233Seric ** Append the other fixed parts of the argv. These run 6633233Seric ** up to the first entry containing "$u". There can only 6643233Seric ** be one of these, and there are only a few more slots 6653233Seric ** in the pv after it. 666294Seric */ 667294Seric 6683233Seric for (mvp = m->m_argv; (p = *++mvp) != NULL; ) 669294Seric { 67058050Seric /* can't use strchr here because of sign extension problems */ 67158050Seric while (*p != '\0') 67258050Seric { 67358050Seric if ((*p++ & 0377) == MACROEXPAND) 67458050Seric { 67558050Seric if (*p == 'u') 67658050Seric break; 67758050Seric } 67858050Seric } 67958050Seric 68058050Seric if (*p != '\0') 6813233Seric break; 6823233Seric 6833233Seric /* this entry is safe -- go ahead and process it */ 6849370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 6853233Seric *pvp++ = newstr(buf); 6863233Seric if (pvp >= &pv[MAXPV - 3]) 6873233Seric { 68858151Seric syserr("554 Too many parameters to %s before $u", pv[0]); 6893233Seric return (-1); 6903233Seric } 691294Seric } 6924863Seric 6936038Seric /* 6946038Seric ** If we have no substitution for the user name in the argument 6956038Seric ** list, we know that we must supply the names otherwise -- and 6966038Seric ** SMTP is the answer!! 6976038Seric */ 6986038Seric 6993233Seric if (*mvp == NULL) 7004863Seric { 7014863Seric /* running SMTP */ 7025179Seric # ifdef SMTP 7034863Seric clever = TRUE; 7044863Seric *pvp = NULL; 70556795Seric # else /* SMTP */ 7066038Seric /* oops! we don't implement SMTP */ 70764718Seric syserr("554 SMTP style mailer not implemented"); 7085179Seric return (EX_SOFTWARE); 70956795Seric # endif /* SMTP */ 7104863Seric } 711294Seric 712294Seric /* 7133233Seric ** At this point *mvp points to the argument with $u. We 7143233Seric ** run through our address list and append all the addresses 7153233Seric ** we can. If we run out of space, do not fret! We can 7163233Seric ** always send another copy later. 717294Seric */ 718294Seric 7193233Seric tobuf[0] = '\0'; 7209370Seric e->e_to = tobuf; 7214397Seric ctladdr = NULL; 72257454Seric firstsig = hostsignature(firstto->q_mailer, firstto->q_host, e); 7233233Seric for (; to != NULL; to = to->q_next) 724294Seric { 7253233Seric /* avoid sending multiple recipients to dumb mailers */ 72610682Seric if (tobuf[0] != '\0' && !bitnset(M_MUSER, m->m_flags)) 7273233Seric break; 7283233Seric 7293233Seric /* if already sent or not for this host, don't send */ 73058680Seric if (bitset(QDONTSEND|QBADADDR|QQUEUEUP, to->q_flags) || 73157454Seric to->q_mailer != firstto->q_mailer || 73257454Seric strcmp(hostsignature(to->q_mailer, to->q_host, e), firstsig) != 0) 7333233Seric continue; 7344397Seric 7358225Seric /* avoid overflowing tobuf */ 73642462Sbostic if (sizeof tobuf < (strlen(to->q_paddr) + strlen(tobuf) + 2)) 7378225Seric break; 7388225Seric 7397672Seric if (tTd(10, 1)) 7405032Seric { 7415032Seric printf("\nsend to "); 7425032Seric printaddr(to, FALSE); 7435032Seric } 7445032Seric 7454397Seric /* compute effective uid/gid when sending */ 74665137Seric /* XXX perhaps this should be to->q_mailer != LocalMailer ?? */ 74765137Seric /* XXX perhaps it should be a mailer flag? */ 74865137Seric if (to->q_mailer == ProgMailer || to->q_mailer == FileMailer) 74965137Seric 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); 76964771Seric giveresponse(EX_UNAVAILABLE, m, NULL, ctladdr, e); 77010699Seric continue; 77110699Seric } 77257441Seric rcode = checkcompat(to, e); 77357459Seric if (rcode != EX_OK) 774294Seric { 77563787Seric markfailure(e, to, rcode); 77664771Seric giveresponse(rcode, m, NULL, ctladdr, 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 { 82065060Seric rcode = mailfile(user, ctladdr, e); 82165060Seric giveresponse(rcode, m, NULL, ctladdr, 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 */ 84064694Seric p = to->q_home; 84164694Seric if (p == NULL && ctladdr != NULL) 84264694Seric p = ctladdr->q_home; 84364694Seric define('z', p, e); /* user's home */ 8443233Seric 8454863Seric /* 8466059Seric ** Expand out this user into argument list. 8474863Seric */ 8484863Seric 8496059Seric if (!clever) 8503233Seric { 8519370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 8524863Seric *pvp++ = newstr(buf); 8534863Seric if (pvp >= &pv[MAXPV - 2]) 8544863Seric { 8554863Seric /* allow some space for trailing parms */ 8564863Seric break; 8574863Seric } 8584863Seric } 859294Seric } 860294Seric 8614067Seric /* see if any addresses still exist */ 8624067Seric if (tobuf[0] == '\0') 8634863Seric { 8649370Seric define('g', (char *) NULL, e); 8654067Seric return (0); 8664863Seric } 8674067Seric 8683233Seric /* print out messages as full list */ 8699388Seric e->e_to = tobuf + 1; 8703233Seric 871294Seric /* 8723233Seric ** Fill out any parameters after the $u parameter. 873294Seric */ 874294Seric 8754863Seric while (!clever && *++mvp != NULL) 876294Seric { 8779370Seric expand(*mvp, buf, &buf[sizeof buf - 1], e); 8783233Seric *pvp++ = newstr(buf); 8793233Seric if (pvp >= &pv[MAXPV]) 88058151Seric syserr("554 deliver: pv overflow after $u for %s", pv[0]); 881294Seric } 8823233Seric *pvp++ = NULL; 883294Seric 884294Seric /* 885294Seric ** Call the mailer. 8862898Seric ** The argument vector gets built, pipes 887294Seric ** are created as necessary, and we fork & exec as 8882898Seric ** appropriate. 8894863Seric ** If we are running SMTP, we just need to clean up. 890294Seric */ 891294Seric 89265137Seric /*XXX this seems a bit wierd */ 89365137Seric if (ctladdr == NULL && bitset(QGOODUID, e->e_from.q_flags)) 89465137Seric ctladdr = &e->e_from; 89565137Seric 89635651Seric #ifdef NAMED_BIND 89751313Seric if (ConfigLevel < 2) 89851313Seric _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ 89935651Seric #endif 90054967Seric 9017672Seric if (tTd(11, 1)) 902294Seric { 9038178Seric printf("openmailer:"); 90458820Seric printav(pv); 905294Seric } 9064488Seric errno = 0; 9073233Seric 90825050Seric CurHostName = m->m_mailer; 90925050Seric 9106038Seric /* 9116038Seric ** Deal with the special case of mail handled through an IPC 9126038Seric ** connection. 9136038Seric ** In this case we don't actually fork. We must be 9146038Seric ** running SMTP for this to work. We will return a 9156038Seric ** zero pid to indicate that we are running IPC. 91611160Seric ** We also handle a debug version that just talks to stdin/out. 9176038Seric */ 9186038Seric 91958820Seric curhost = NULL; 92064334Seric SmtpPhase = NULL; 92164718Seric mci = NULL; 92258820Seric 92364401Seric #ifdef XDEBUG 92464401Seric { 92564401Seric char wbuf[MAXLINE]; 92664401Seric 92764401Seric /* make absolutely certain 0, 1, and 2 are in use */ 92864401Seric sprintf(wbuf, "%s... openmailer(%s)", e->e_to, m->m_name); 92964401Seric checkfd012(wbuf); 93064401Seric } 93164401Seric #endif 93264401Seric 93311160Seric /* check for Local Person Communication -- not for mortals!!! */ 93411160Seric if (strcmp(m->m_mailer, "[LPC]") == 0) 93511160Seric { 93654967Seric mci = (MCI *) xalloc(sizeof *mci); 93754993Seric bzero((char *) mci, sizeof *mci); 93853738Seric mci->mci_in = stdin; 93953738Seric mci->mci_out = stdout; 94054967Seric mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN; 94153751Seric mci->mci_mailer = m; 94211160Seric } 94354967Seric else if (strcmp(m->m_mailer, "[IPC]") == 0 || 94454967Seric strcmp(m->m_mailer, "[TCP]") == 0) 9456038Seric { 94652107Seric #ifdef DAEMON 94757454Seric register int i; 9487285Seric register u_short port; 9496038Seric 95064844Seric if (pv[0] == NULL || pv[1] == NULL || pv[1][0] == '\0') 95164844Seric { 95264844Seric syserr("null host name for %s mailer", m->m_mailer); 95364844Seric rcode = EX_CONFIG; 95464844Seric goto give_up; 95564844Seric } 95664844Seric 95758820Seric CurHostName = pv[1]; 95858820Seric curhost = hostsignature(m, pv[1], e); 95954967Seric 96058479Seric if (curhost == NULL || curhost[0] == '\0') 96158479Seric { 96264844Seric syserr("null host signature for %s", pv[1]); 96358820Seric rcode = EX_OSERR; 96458820Seric goto give_up; 96558479Seric } 96658479Seric 9676038Seric if (!clever) 96858479Seric { 96958151Seric syserr("554 non-clever IPC"); 97064718Seric rcode = EX_CONFIG; 97158820Seric goto give_up; 97258479Seric } 97358820Seric if (pv[2] != NULL) 97458820Seric port = atoi(pv[2]); 9756632Seric else 9767285Seric port = 0; 97758820Seric tryhost: 97857454Seric while (*curhost != '\0') 97929433Sbloom { 98057454Seric register char *p; 98158664Seric static char hostbuf[MAXNAME]; 98257454Seric 98357454Seric /* pull the next host from the signature */ 98457454Seric p = strchr(curhost, ':'); 98557454Seric if (p == NULL) 98657454Seric p = &curhost[strlen(curhost)]; 98764718Seric if (p == curhost) 98864718Seric { 98964718Seric syserr("deliver: null host name in signature"); 99064726Seric curhost++; 99164718Seric continue; 99264718Seric } 99357454Seric strncpy(hostbuf, curhost, p - curhost); 99457454Seric hostbuf[p - curhost] = '\0'; 99557454Seric if (*p != '\0') 99657454Seric p++; 99757454Seric curhost = p; 99857454Seric 99953738Seric /* see if we already know that this host is fried */ 100057454Seric CurHostName = hostbuf; 100157454Seric mci = mci_get(hostbuf, m); 100254967Seric if (mci->mci_state != MCIS_CLOSED) 100357387Seric { 100457387Seric if (tTd(11, 1)) 100557387Seric { 100657387Seric printf("openmailer: "); 100764731Seric mci_dump(mci, FALSE); 100857387Seric } 100957943Seric CurHostName = mci->mci_host; 101058820Seric break; 101157387Seric } 101253751Seric mci->mci_mailer = m; 101354967Seric if (mci->mci_exitstat != EX_OK) 101454967Seric continue; 101554967Seric 101654967Seric /* try the connection */ 101757454Seric setproctitle("%s %s: %s", e->e_id, hostbuf, "user open"); 101858151Seric message("Connecting to %s (%s)...", 101957454Seric hostbuf, m->m_name); 102057454Seric i = makeconnection(hostbuf, port, mci, 102154967Seric bitnset(M_SECURE_PORT, m->m_flags)); 102254967Seric mci->mci_exitstat = i; 102354967Seric mci->mci_errno = errno; 102463753Seric #ifdef NAMED_BIND 102563753Seric mci->mci_herrno = h_errno; 102663753Seric #endif 102754967Seric if (i == EX_OK) 102852106Seric { 102954967Seric mci->mci_state = MCIS_OPENING; 103054967Seric mci_cache(mci); 103163753Seric if (TrafficLogFile != NULL) 103263753Seric fprintf(TrafficLogFile, "%05d == CONNECT %s\n", 103363753Seric getpid(), hostbuf); 103454967Seric break; 103534022Sbostic } 103654967Seric else if (tTd(11, 1)) 103754967Seric printf("openmailer: makeconnection => stat=%d, errno=%d\n", 103854967Seric i, errno); 103953738Seric 104053738Seric /* enter status of this host */ 104153738Seric setstat(i); 104264718Seric 104364718Seric /* should print some message here for -v mode */ 10446047Seric } 104564718Seric if (mci == NULL) 104664718Seric { 104764718Seric syserr("deliver: no host name"); 104864718Seric rcode = EX_OSERR; 104964718Seric goto give_up; 105064718Seric } 105154993Seric mci->mci_pid = 0; 105254967Seric #else /* no DAEMON */ 105358151Seric syserr("554 openmailer: no IPC"); 105457387Seric if (tTd(11, 1)) 105557387Seric printf("openmailer: NULL\n"); 105664718Seric rcode = EX_UNAVAILABLE; 105764718Seric goto give_up; 105854967Seric #endif /* DAEMON */ 10596038Seric } 106054967Seric else 1061294Seric { 106263753Seric if (TrafficLogFile != NULL) 106358852Seric { 106463753Seric char **av; 106558925Seric 106663753Seric fprintf(TrafficLogFile, "%05d === EXEC", getpid()); 106763753Seric for (av = pv; *av != NULL; av++) 106863753Seric fprintf(TrafficLogFile, " %s", *av); 106963753Seric fprintf(TrafficLogFile, "\n"); 107058852Seric } 107158852Seric 107254967Seric /* create a pipe to shove the mail through */ 107354967Seric if (pipe(mpvect) < 0) 107454967Seric { 107558925Seric syserr("%s... openmailer(%s): pipe (to mailer)", 107658925Seric e->e_to, m->m_name); 107757387Seric if (tTd(11, 1)) 107857387Seric printf("openmailer: NULL\n"); 107958820Seric rcode = EX_OSERR; 108058820Seric goto give_up; 108154967Seric } 10824863Seric 108354967Seric /* if this mailer speaks smtp, create a return pipe */ 108454967Seric if (clever && pipe(rpvect) < 0) 108554967Seric { 108658925Seric syserr("%s... openmailer(%s): pipe (from mailer)", 108758925Seric e->e_to, m->m_name); 108854967Seric (void) close(mpvect[0]); 108954967Seric (void) close(mpvect[1]); 109057387Seric if (tTd(11, 1)) 109157387Seric printf("openmailer: NULL\n"); 109258820Seric rcode = EX_OSERR; 109358820Seric goto give_up; 109454967Seric } 10954863Seric 109654967Seric /* 109754967Seric ** Actually fork the mailer process. 109854967Seric ** DOFORK is clever about retrying. 109954967Seric ** 110054967Seric ** Dispose of SIGCHLD signal catchers that may be laying 110154967Seric ** around so that endmail will get it. 110254967Seric */ 11036038Seric 110454967Seric if (e->e_xfp != NULL) 110554967Seric (void) fflush(e->e_xfp); /* for debugging */ 110654967Seric (void) fflush(stdout); 110726434Seric # ifdef SIGCHLD 110864035Seric (void) setsignal(SIGCHLD, SIG_DFL); 110956795Seric # endif /* SIGCHLD */ 111054967Seric DOFORK(FORK); 111154967Seric /* pid is set by DOFORK */ 111254967Seric if (pid < 0) 11134863Seric { 111454967Seric /* failure */ 111558925Seric syserr("%s... openmailer(%s): cannot fork", 111658925Seric e->e_to, m->m_name); 111754967Seric (void) close(mpvect[0]); 111854967Seric (void) close(mpvect[1]); 111954967Seric if (clever) 112054967Seric { 112154967Seric (void) close(rpvect[0]); 112254967Seric (void) close(rpvect[1]); 112354967Seric } 112457387Seric if (tTd(11, 1)) 112557387Seric printf("openmailer: NULL\n"); 112658820Seric rcode = EX_OSERR; 112758820Seric goto give_up; 11284863Seric } 112954967Seric else if (pid == 0) 113054967Seric { 113154967Seric int i; 113256678Seric int saveerrno; 113358675Seric char **ep; 113458675Seric char *env[MAXUSERENVIRON]; 113558675Seric extern char **environ; 113654967Seric extern int DtableSize; 113715772Seric 113854967Seric /* child -- set up input & exec mailer */ 113964035Seric (void) setsignal(SIGINT, SIG_IGN); 114064035Seric (void) setsignal(SIGHUP, SIG_IGN); 114164035Seric (void) setsignal(SIGTERM, SIG_DFL); 11424709Seric 114364145Seric /* reset user and group */ 114464145Seric if (!bitnset(M_RESTR, m->m_flags)) 114564145Seric { 114664145Seric if (ctladdr == NULL || ctladdr->q_uid == 0) 114764145Seric { 114864145Seric (void) initgroups(DefUser, DefGid); 114964837Seric (void) setgid(DefGid); 115064145Seric (void) setuid(DefUid); 115164145Seric } 115264145Seric else 115364145Seric { 115464145Seric (void) initgroups(ctladdr->q_ruser? 115564145Seric ctladdr->q_ruser: ctladdr->q_user, 115664145Seric ctladdr->q_gid); 115764970Seric (void) setgid(ctladdr->q_gid); 115864145Seric (void) setuid(ctladdr->q_uid); 115964145Seric } 116064145Seric } 116164145Seric 116264145Seric if (tTd(11, 2)) 116364145Seric printf("openmailer: running as r/euid=%d/%d\n", 116464145Seric getuid(), geteuid()); 116564145Seric 116658935Seric /* move into some "safe" directory */ 116758935Seric if (m->m_execdir != NULL) 116858935Seric { 116958935Seric char *p, *q; 117058935Seric char buf[MAXLINE]; 117158935Seric 117258935Seric for (p = m->m_execdir; p != NULL; p = q) 117358935Seric { 117458935Seric q = strchr(p, ':'); 117558935Seric if (q != NULL) 117658935Seric *q = '\0'; 117758935Seric expand(p, buf, &buf[sizeof buf] - 1, e); 117858935Seric if (q != NULL) 117958935Seric *q++ = ':'; 118058935Seric if (tTd(11, 20)) 118158935Seric printf("openmailer: trydir %s\n", 118258935Seric buf); 118358935Seric if (buf[0] != '\0' && chdir(buf) >= 0) 118458935Seric break; 118558935Seric } 118658935Seric } 118758935Seric 118854967Seric /* arrange to filter std & diag output of command */ 118954967Seric if (clever) 119054967Seric { 119154967Seric (void) close(rpvect[0]); 119258852Seric if (dup2(rpvect[1], STDOUT_FILENO) < 0) 119358852Seric { 119458925Seric syserr("%s... openmailer(%s): cannot dup pipe %d for stdout", 119558925Seric e->e_to, m->m_name, rpvect[1]); 119658852Seric _exit(EX_OSERR); 119758852Seric } 119854967Seric (void) close(rpvect[1]); 119954967Seric } 1200*65580Seric else if (OpMode == MD_SMTP || OpMode == MD_DAEMON || HoldErrs) 120154967Seric { 120254967Seric /* put mailer output in transcript */ 120358852Seric if (dup2(fileno(e->e_xfp), STDOUT_FILENO) < 0) 120458852Seric { 120558925Seric syserr("%s... openmailer(%s): cannot dup xscript %d for stdout", 120658925Seric e->e_to, m->m_name, 120758852Seric fileno(e->e_xfp)); 120858852Seric _exit(EX_OSERR); 120958852Seric } 121054967Seric } 121158852Seric if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) 121258852Seric { 121358925Seric syserr("%s... openmailer(%s): cannot dup stdout for stderr", 121458925Seric e->e_to, m->m_name); 121558852Seric _exit(EX_OSERR); 121658852Seric } 12174709Seric 121854967Seric /* arrange to get standard input */ 121954967Seric (void) close(mpvect[1]); 122058731Seric if (dup2(mpvect[0], STDIN_FILENO) < 0) 12214417Seric { 122258925Seric syserr("%s... openmailer(%s): cannot dup pipe %d for stdin", 122358925Seric e->e_to, m->m_name, mpvect[0]); 122454967Seric _exit(EX_OSERR); 12254417Seric } 122654967Seric (void) close(mpvect[0]); 12279370Seric 122854967Seric /* arrange for all the files to be closed */ 122954967Seric for (i = 3; i < DtableSize; i++) 123054967Seric { 123154967Seric register int j; 123264145Seric 123354967Seric if ((j = fcntl(i, F_GETFD, 0)) != -1) 123464145Seric (void) fcntl(i, F_SETFD, j | 1); 123554967Seric } 12362774Seric 123758675Seric /* set up the mailer environment */ 123858675Seric i = 0; 123958675Seric env[i++] = "AGENT=sendmail"; 124058675Seric for (ep = environ; *ep != NULL; ep++) 124158675Seric { 124258675Seric if (strncmp(*ep, "TZ=", 3) == 0) 124358675Seric env[i++] = *ep; 124458675Seric } 124558675Seric env[i++] = NULL; 124658675Seric 124754967Seric /* try to execute the mailer */ 124858820Seric execve(m->m_mailer, pv, env); 124956678Seric saveerrno = errno; 125054967Seric syserr("Cannot exec %s", m->m_mailer); 125160008Seric if (m == LocalMailer || transienterror(saveerrno)) 125260008Seric _exit(EX_OSERR); 125354967Seric _exit(EX_UNAVAILABLE); 125451835Seric } 125554967Seric 125654967Seric /* 125754967Seric ** Set up return value. 125854967Seric */ 125954967Seric 126054967Seric mci = (MCI *) xalloc(sizeof *mci); 126154993Seric bzero((char *) mci, sizeof *mci); 126254967Seric mci->mci_mailer = m; 126354967Seric mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN; 126454993Seric mci->mci_pid = pid; 126554967Seric (void) close(mpvect[0]); 126654967Seric mci->mci_out = fdopen(mpvect[1], "w"); 126764724Seric if (mci->mci_out == NULL) 126864724Seric { 126964724Seric syserr("deliver: cannot create mailer output channel, fd=%d", 127064724Seric mpvect[1]); 127164724Seric (void) close(mpvect[1]); 127264724Seric if (clever) 127364724Seric { 127464724Seric (void) close(rpvect[0]); 127564724Seric (void) close(rpvect[1]); 127664724Seric } 127764724Seric rcode = EX_OSERR; 127864724Seric goto give_up; 127964724Seric } 128054967Seric if (clever) 128154967Seric { 128254967Seric (void) close(rpvect[1]); 128354967Seric mci->mci_in = fdopen(rpvect[0], "r"); 128464724Seric if (mci->mci_in == NULL) 128564724Seric { 128664724Seric syserr("deliver: cannot create mailer input channel, fd=%d", 128764724Seric mpvect[1]); 128864724Seric (void) close(rpvect[0]); 128964724Seric fclose(mci->mci_out); 129064724Seric mci->mci_out = NULL; 129164724Seric rcode = EX_OSERR; 129264724Seric goto give_up; 129364724Seric } 129454967Seric } 129554967Seric else 129654967Seric { 129754967Seric mci->mci_flags |= MCIF_TEMP; 129854967Seric mci->mci_in = NULL; 129954967Seric } 1300294Seric } 1301294Seric 13024709Seric /* 130354967Seric ** If we are in SMTP opening state, send initial protocol. 13044709Seric */ 13054709Seric 130654967Seric if (clever && mci->mci_state != MCIS_CLOSED) 13074863Seric { 130854967Seric smtpinit(m, mci, e); 130953738Seric } 131057387Seric if (tTd(11, 1)) 131157387Seric { 131257387Seric printf("openmailer: "); 131364731Seric mci_dump(mci, FALSE); 131457387Seric } 1315294Seric 131658820Seric if (mci->mci_state != MCIS_OPEN) 131758820Seric { 131858820Seric /* couldn't open the mailer */ 131958820Seric rcode = mci->mci_exitstat; 132058820Seric errno = mci->mci_errno; 132163753Seric #ifdef NAMED_BIND 132263753Seric h_errno = mci->mci_herrno; 132363753Seric #endif 132458820Seric if (rcode == EX_OK) 132558820Seric { 132658820Seric /* shouldn't happen */ 132758820Seric syserr("554 deliver: rcode=%d, mci_state=%d, sig=%s", 132858820Seric rcode, mci->mci_state, firstsig); 132958820Seric rcode = EX_SOFTWARE; 133058820Seric } 133164922Seric else if (rcode == EX_TEMPFAIL && curhost != NULL && *curhost != '\0') 133259958Seric { 133359958Seric /* try next MX site */ 133459958Seric goto tryhost; 133559958Seric } 133658820Seric } 133758820Seric else if (!clever) 133858820Seric { 133958820Seric /* 134058820Seric ** Format and send message. 134158820Seric */ 134258820Seric 134358820Seric putfromline(mci->mci_out, m, e); 134458820Seric (*e->e_puthdr)(mci->mci_out, m, e); 134558820Seric putline("\n", mci->mci_out, m); 134659730Seric (*e->e_putbody)(mci->mci_out, m, e, NULL); 134758820Seric 134858820Seric /* get the exit status */ 134958820Seric rcode = endmailer(mci, e, pv); 135058820Seric } 135158820Seric else 135258820Seric #ifdef SMTP 135358820Seric { 135458820Seric /* 135558820Seric ** Send the MAIL FROM: protocol 135658820Seric */ 135758820Seric 135858820Seric rcode = smtpmailfrom(m, mci, e); 135958820Seric if (rcode == EX_OK) 136058820Seric { 136158820Seric register char *t = tobuf; 136258820Seric register int i; 136358820Seric 136458820Seric /* send the recipient list */ 136558820Seric tobuf[0] = '\0'; 136658820Seric for (to = tochain; to != NULL; to = to->q_tchain) 136758820Seric { 136858820Seric e->e_to = to->q_paddr; 136958820Seric if ((i = smtprcpt(to, m, mci, e)) != EX_OK) 137058820Seric { 137158820Seric markfailure(e, to, i); 137264771Seric giveresponse(i, m, mci, ctladdr, e); 137358820Seric } 137458820Seric else 137558820Seric { 137658820Seric *t++ = ','; 137758820Seric for (p = to->q_paddr; *p; *t++ = *p++) 137858820Seric continue; 137964372Seric *t = '\0'; 138058820Seric } 138158820Seric } 138258820Seric 138358820Seric /* now send the data */ 138458820Seric if (tobuf[0] == '\0') 138558820Seric { 138658820Seric rcode = EX_OK; 138758820Seric e->e_to = NULL; 138858820Seric if (bitset(MCIF_CACHED, mci->mci_flags)) 138958820Seric smtprset(m, mci, e); 139058820Seric } 139158820Seric else 139258820Seric { 139358820Seric e->e_to = tobuf + 1; 139458820Seric rcode = smtpdata(m, mci, e); 139558820Seric } 139658820Seric 139758820Seric /* now close the connection */ 139858820Seric if (!bitset(MCIF_CACHED, mci->mci_flags)) 139958820Seric smtpquit(m, mci, e); 140058820Seric } 140164922Seric if (rcode != EX_OK && curhost != NULL && *curhost != '\0') 140258820Seric { 140358820Seric /* try next MX site */ 140458820Seric goto tryhost; 140558820Seric } 140658820Seric } 140758820Seric #else /* not SMTP */ 140858820Seric { 140958820Seric syserr("554 deliver: need SMTP compiled to use clever mailer"); 141058820Seric rcode = EX_CONFIG; 141158820Seric goto give_up; 141258820Seric } 141358820Seric #endif /* SMTP */ 141458820Seric #ifdef NAMED_BIND 141558820Seric if (ConfigLevel < 2) 141658820Seric _res.options |= RES_DEFNAMES | RES_DNSRCH; /* XXX */ 141758820Seric #endif 141858820Seric 141958820Seric /* arrange a return receipt if requested */ 142064718Seric if (rcode == EX_OK && e->e_receiptto != NULL && 142164718Seric bitnset(M_LOCALMAILER, m->m_flags)) 142258820Seric { 142358820Seric e->e_flags |= EF_SENDRECEIPT; 142458820Seric /* do we want to send back more info? */ 142558820Seric } 142658820Seric 142758820Seric /* 142858820Seric ** Do final status disposal. 142958820Seric ** We check for something in tobuf for the SMTP case. 143058820Seric ** If we got a temporary failure, arrange to queue the 143158820Seric ** addressees. 143258820Seric */ 143358820Seric 143458820Seric give_up: 143558820Seric if (tobuf[0] != '\0') 143664771Seric giveresponse(rcode, m, mci, ctladdr, e); 143758820Seric for (to = tochain; to != NULL; to = to->q_tchain) 143858820Seric { 143958820Seric if (rcode != EX_OK) 144058820Seric markfailure(e, to, rcode); 144158820Seric else 144258820Seric { 144358820Seric to->q_flags |= QSENT; 144458820Seric e->e_nsent++; 144564718Seric if (e->e_receiptto != NULL && 144664718Seric bitnset(M_LOCALMAILER, m->m_flags)) 144764718Seric { 144864718Seric fprintf(e->e_xfp, "%s... Successfully delivered\n", 144964718Seric to->q_paddr); 145064718Seric } 145158820Seric } 145258820Seric } 145358820Seric 145458820Seric /* 145558820Seric ** Restore state and return. 145658820Seric */ 145758820Seric 145864401Seric #ifdef XDEBUG 145964401Seric { 146064401Seric char wbuf[MAXLINE]; 146164401Seric 146264401Seric /* make absolutely certain 0, 1, and 2 are in use */ 146364554Seric sprintf(wbuf, "%s... end of deliver(%s)", 146464554Seric e->e_to == NULL ? "NO-TO-LIST" : e->e_to, 146564554Seric m->m_name); 146664401Seric checkfd012(wbuf); 146764401Seric } 146864401Seric #endif 146964401Seric 147058820Seric errno = 0; 147158820Seric define('g', (char *) NULL, e); 147258820Seric return (rcode); 1473294Seric } 1474294Seric /* 147558820Seric ** MARKFAILURE -- mark a failure on a specific address. 147658820Seric ** 147758820Seric ** Parameters: 147858820Seric ** e -- the envelope we are sending. 147958820Seric ** q -- the address to mark. 148058820Seric ** rcode -- the code signifying the particular failure. 148158820Seric ** 148258820Seric ** Returns: 148358820Seric ** none. 148458820Seric ** 148558820Seric ** Side Effects: 148658820Seric ** marks the address (and possibly the envelope) with the 148758820Seric ** failure so that an error will be returned or 148858820Seric ** the message will be queued, as appropriate. 148958820Seric */ 149058820Seric 149158820Seric markfailure(e, q, rcode) 149258820Seric register ENVELOPE *e; 149358820Seric register ADDRESS *q; 149458820Seric int rcode; 149558820Seric { 149658820Seric char buf[MAXLINE]; 149758820Seric 149865051Seric switch (rcode) 149965051Seric { 150065051Seric case EX_OK: 150165051Seric break; 150265051Seric 150365051Seric case EX_TEMPFAIL: 150465051Seric case EX_IOERR: 150565051Seric case EX_OSERR: 150663753Seric q->q_flags |= QQUEUEUP; 150765051Seric break; 150865051Seric 150965051Seric default: 151058820Seric q->q_flags |= QBADADDR; 151165051Seric break; 151265051Seric } 151358820Seric } 151458820Seric /* 151558820Seric ** ENDMAILER -- Wait for mailer to terminate. 151658820Seric ** 151758820Seric ** We should never get fatal errors (e.g., segmentation 151858820Seric ** violation), so we report those specially. For other 151958820Seric ** errors, we choose a status message (into statmsg), 152058820Seric ** and if it represents an error, we print it. 152158820Seric ** 152258820Seric ** Parameters: 152358820Seric ** pid -- pid of mailer. 152458820Seric ** e -- the current envelope. 152558820Seric ** pv -- the parameter vector that invoked the mailer 152658820Seric ** (for error messages). 152758820Seric ** 152858820Seric ** Returns: 152958820Seric ** exit code of mailer. 153058820Seric ** 153158820Seric ** Side Effects: 153258820Seric ** none. 153358820Seric */ 153458820Seric 153558820Seric endmailer(mci, e, pv) 153658820Seric register MCI *mci; 153758820Seric register ENVELOPE *e; 153858820Seric char **pv; 153958820Seric { 154058820Seric int st; 154158820Seric 154258820Seric /* close any connections */ 154358820Seric if (mci->mci_in != NULL) 154465198Seric (void) xfclose(mci->mci_in, mci->mci_mailer->m_name, "mci_in"); 154558820Seric if (mci->mci_out != NULL) 154665198Seric (void) xfclose(mci->mci_out, mci->mci_mailer->m_name, "mci_out"); 154758820Seric mci->mci_in = mci->mci_out = NULL; 154858820Seric mci->mci_state = MCIS_CLOSED; 154958820Seric 155058820Seric /* in the IPC case there is nothing to wait for */ 155158820Seric if (mci->mci_pid == 0) 155258820Seric return (EX_OK); 155358820Seric 155458820Seric /* wait for the mailer process to die and collect status */ 155558820Seric st = waitfor(mci->mci_pid); 155658820Seric if (st == -1) 155758820Seric { 155858820Seric syserr("endmailer %s: wait", pv[0]); 155958820Seric return (EX_SOFTWARE); 156058820Seric } 156158820Seric 156264379Seric if (WIFEXITED(st)) 156358820Seric { 156464379Seric /* normal death -- return status */ 156564379Seric return (WEXITSTATUS(st)); 156664379Seric } 156758820Seric 156864379Seric /* it died a horrid death */ 156965545Seric syserr("451 mailer %s died with signal %o", 157065545Seric mci->mci_mailer->m_name, st); 157158820Seric 157264379Seric /* log the arguments */ 157365194Seric if (pv != NULL && e->e_xfp != NULL) 157464379Seric { 157564379Seric register char **av; 157658820Seric 157764379Seric fprintf(e->e_xfp, "Arguments:"); 157864379Seric for (av = pv; *av != NULL; av++) 157964379Seric fprintf(e->e_xfp, " %s", *av); 158064379Seric fprintf(e->e_xfp, "\n"); 158158820Seric } 158258820Seric 158364379Seric ExitStat = EX_TEMPFAIL; 158464379Seric return (EX_TEMPFAIL); 158558820Seric } 158658820Seric /* 1587294Seric ** GIVERESPONSE -- Interpret an error response from a mailer 1588294Seric ** 1589294Seric ** Parameters: 1590294Seric ** stat -- the status code from the mailer (high byte 1591294Seric ** only; core dumps must have been taken care of 1592294Seric ** already). 159358337Seric ** m -- the mailer info for this mailer. 159458337Seric ** mci -- the mailer connection info -- can be NULL if the 159558337Seric ** response is given before the connection is made. 159664771Seric ** ctladdr -- the controlling address for the recipient 159764771Seric ** address(es). 159858337Seric ** e -- the current envelope. 1599294Seric ** 1600294Seric ** Returns: 16014082Seric ** none. 1602294Seric ** 1603294Seric ** Side Effects: 16041518Seric ** Errors may be incremented. 1605294Seric ** ExitStat may be set. 1606294Seric */ 1607294Seric 160864771Seric giveresponse(stat, m, mci, ctladdr, e) 1609294Seric int stat; 16109370Seric register MAILER *m; 161158337Seric register MCI *mci; 161264771Seric ADDRESS *ctladdr; 161310105Seric ENVELOPE *e; 1614294Seric { 161560094Seric register const char *statmsg; 1616294Seric extern char *SysExMsg[]; 1617294Seric register int i; 161836788Sbostic extern int N_SysEx; 161910105Seric char buf[MAXLINE]; 1620294Seric 16214315Seric /* 16224315Seric ** Compute status message from code. 16234315Seric */ 16244315Seric 1625294Seric i = stat - EX__BASE; 16269370Seric if (stat == 0) 162758852Seric { 16289370Seric statmsg = "250 Sent"; 162958916Seric if (e->e_statmsg != NULL) 163058852Seric { 163158916Seric (void) sprintf(buf, "%s (%s)", statmsg, e->e_statmsg); 163258852Seric statmsg = buf; 163358852Seric } 163458852Seric } 16359370Seric else if (i < 0 || i > N_SysEx) 16369370Seric { 16379370Seric (void) sprintf(buf, "554 unknown mailer error %d", stat); 16389370Seric stat = EX_UNAVAILABLE; 16399370Seric statmsg = buf; 16409370Seric } 164110105Seric else if (stat == EX_TEMPFAIL) 164210105Seric { 164358664Seric (void) strcpy(buf, SysExMsg[i] + 1); 164436788Sbostic #ifdef NAMED_BIND 164525527Smiriam if (h_errno == TRY_AGAIN) 164663993Seric statmsg = errstring(h_errno+E_DNSBASE); 164721061Seric else 164836788Sbostic #endif 164921061Seric { 165025527Smiriam if (errno != 0) 165125527Smiriam statmsg = errstring(errno); 165225527Smiriam else 165325527Smiriam { 165421061Seric #ifdef SMTP 165525527Smiriam statmsg = SmtpError; 165656795Seric #else /* SMTP */ 165725527Smiriam statmsg = NULL; 165856795Seric #endif /* SMTP */ 165925527Smiriam } 166021061Seric } 166121061Seric if (statmsg != NULL && statmsg[0] != '\0') 166221061Seric { 166310124Seric (void) strcat(buf, ": "); 166421061Seric (void) strcat(buf, statmsg); 166510105Seric } 166610105Seric statmsg = buf; 166710105Seric } 166863753Seric #ifdef NAMED_BIND 166963753Seric else if (stat == EX_NOHOST && h_errno != 0) 167063753Seric { 167163993Seric statmsg = errstring(h_errno + E_DNSBASE); 167263753Seric (void) sprintf(buf, "%s (%s)", SysExMsg[i], statmsg); 167363753Seric statmsg = buf; 167463753Seric } 167563753Seric #endif 1676294Seric else 167721061Seric { 1678294Seric statmsg = SysExMsg[i]; 167958664Seric if (*statmsg++ == ':') 168058664Seric { 168158664Seric (void) sprintf(buf, "%s: %s", statmsg, errstring(errno)); 168258664Seric statmsg = buf; 168358664Seric } 168421061Seric } 16859370Seric 16869370Seric /* 16879370Seric ** Print the message as appropriate 16889370Seric */ 16899370Seric 169010105Seric if (stat == EX_OK || stat == EX_TEMPFAIL) 169164718Seric { 169264718Seric extern char MsgBuf[]; 169364718Seric 169458524Seric message(&statmsg[4], errstring(errno)); 169564718Seric if (stat == EX_TEMPFAIL && e->e_xfp != NULL) 169664718Seric fprintf(e->e_xfp, "%s\n", &MsgBuf[4]); 169764718Seric } 1698294Seric else 1699294Seric { 17001518Seric Errors++; 170158524Seric usrerr(statmsg, errstring(errno)); 1702294Seric } 1703294Seric 1704294Seric /* 1705294Seric ** Final cleanup. 1706294Seric ** Log a record of the transaction. Compute the new 1707294Seric ** ExitStat -- if we already had an error, stick with 1708294Seric ** that. 1709294Seric */ 1710294Seric 171158020Seric if (LogLevel > ((stat == EX_TEMPFAIL) ? 8 : (stat == EX_OK) ? 7 : 6)) 171264771Seric logdelivery(m, mci, &statmsg[4], ctladdr, e); 17137858Seric 17144621Seric if (stat != EX_TEMPFAIL) 17154621Seric setstat(stat); 171664952Seric if (stat != EX_OK && (stat != EX_TEMPFAIL || e->e_message == NULL)) 171710105Seric { 171810105Seric if (e->e_message != NULL) 171910105Seric free(e->e_message); 172010105Seric e->e_message = newstr(&statmsg[4]); 172110105Seric } 172210124Seric errno = 0; 172336788Sbostic #ifdef NAMED_BIND 172425527Smiriam h_errno = 0; 172536788Sbostic #endif 1726294Seric } 1727294Seric /* 17288496Seric ** LOGDELIVERY -- log the delivery in the system log 17298496Seric ** 173064969Seric ** Care is taken to avoid logging lines that are too long, because 173164969Seric ** some versions of syslog have an unfortunate proclivity for core 173264969Seric ** dumping. This is a hack, to be sure, that is at best empirical. 173364969Seric ** 17348496Seric ** Parameters: 173558337Seric ** m -- the mailer info. Can be NULL for initial queue. 173658337Seric ** mci -- the mailer connection info -- can be NULL if the 173758337Seric ** log is occuring when no connection is active. 173858337Seric ** stat -- the message to print for the status. 173964771Seric ** ctladdr -- the controlling address for the to list. 174058337Seric ** e -- the current envelope. 17418496Seric ** 17428496Seric ** Returns: 17438496Seric ** none 17448496Seric ** 17458496Seric ** Side Effects: 17468496Seric ** none 17478496Seric */ 17488496Seric 174964771Seric logdelivery(m, mci, stat, ctladdr, e) 175058337Seric MAILER *m; 175158337Seric register MCI *mci; 17528496Seric char *stat; 175364771Seric ADDRESS *ctladdr; 175454967Seric register ENVELOPE *e; 17558496Seric { 175658343Seric # ifdef LOG 175764771Seric register char *bp; 175864969Seric register char *p; 175964969Seric int l; 176058418Seric char buf[512]; 17618496Seric 176265059Seric # if (SYSLOG_BUFSIZE) >= 256 176364771Seric bp = buf; 176464771Seric if (ctladdr != NULL) 176564771Seric { 176664771Seric strcpy(bp, ", ctladdr="); 176765016Seric strcat(bp, shortenstring(ctladdr->q_paddr, 83)); 176864771Seric bp += strlen(bp); 176964771Seric if (bitset(QGOODUID, ctladdr->q_flags)) 177064771Seric { 177164771Seric (void) sprintf(bp, " (%d/%d)", 177264771Seric ctladdr->q_uid, ctladdr->q_gid); 177364771Seric bp += strlen(bp); 177464771Seric } 177564771Seric } 177658337Seric 177764771Seric (void) sprintf(bp, ", delay=%s", pintvl(curtime() - e->e_ctime, TRUE)); 177864771Seric bp += strlen(bp); 177964771Seric 178058513Seric if (m != NULL) 178158305Seric { 178264771Seric (void) strcpy(bp, ", mailer="); 178364771Seric (void) strcat(bp, m->m_name); 178464771Seric bp += strlen(bp); 178558305Seric } 178658513Seric 178758513Seric if (mci != NULL && mci->mci_host != NULL) 178858305Seric { 178958305Seric # ifdef DAEMON 179058755Seric extern SOCKADDR CurHostAddr; 179158513Seric # endif 179258305Seric 179364771Seric (void) strcpy(bp, ", relay="); 179464771Seric (void) strcat(bp, mci->mci_host); 179558513Seric 179658513Seric # ifdef DAEMON 179764771Seric (void) strcat(bp, " ("); 179864771Seric (void) strcat(bp, anynet_ntoa(&CurHostAddr)); 179964771Seric (void) strcat(bp, ")"); 180058305Seric # endif 180158305Seric } 180258343Seric else 180358513Seric { 180458513Seric char *p = macvalue('h', e); 180558343Seric 180658513Seric if (p != NULL && p[0] != '\0') 180758513Seric { 180864771Seric (void) strcpy(bp, ", relay="); 180964771Seric (void) strcat(bp, p); 181058513Seric } 181158513Seric } 181264922Seric bp += strlen(bp); 181364969Seric 181465059Seric #define STATLEN (((SYSLOG_BUFSIZE) - 100) / 4) 181565059Seric #if (STATLEN) < 63 181665059Seric # undef STATLEN 181765059Seric # define STATLEN 63 181865059Seric #endif 181965059Seric #if (STATLEN) > 203 182065059Seric # undef STATLEN 182165059Seric # define STATLEN 203 182265059Seric #endif 182365059Seric 182465059Seric if ((bp - buf) > (sizeof buf - ((STATLEN) + 20))) 182564969Seric { 182664969Seric /* desperation move -- truncate data */ 182765059Seric bp = buf + sizeof buf - ((STATLEN) + 17); 182864969Seric strcpy(bp, "..."); 182964969Seric bp += 3; 183064969Seric } 183164969Seric 183264969Seric (void) strcpy(bp, ", stat="); 183364969Seric bp += strlen(bp); 183465059Seric 183565059Seric (void) strcpy(bp, shortenstring(stat, (STATLEN))); 183658418Seric 183764969Seric l = SYSLOG_BUFSIZE - 100 - strlen(buf); 183864969Seric p = e->e_to; 183964969Seric while (strlen(p) >= l) 184064969Seric { 184164969Seric register char *q = strchr(p + l, ','); 184264969Seric 184365008Seric if (q == NULL) 184464969Seric break; 184564969Seric syslog(LOG_INFO, "%s: to=%.*s [more]%s", 184664969Seric e->e_id, ++q - p, p, buf); 184764969Seric p = q; 184864969Seric } 184964969Seric syslog(LOG_INFO, "%s: to=%s%s", e->e_id, p, buf); 185065059Seric 185165059Seric # else /* we have a very short log buffer size */ 185265059Seric 185365059Seric l = SYSLOG_BUFSIZE - 40; 185465059Seric p = e->e_to; 185565059Seric while (strlen(p) >= l) 185665059Seric { 185765059Seric register char *q = strchr(p + l, ','); 185865059Seric 185965059Seric if (q == NULL) 186065059Seric break; 186165059Seric syslog(LOG_INFO, "%s: to=%.*s [more]", 186265059Seric e->e_id, ++q - p, p); 186365059Seric p = q; 186465059Seric } 186565059Seric syslog(LOG_INFO, "%s: to=%s", e->e_id, p); 186665059Seric 186765059Seric if (ctladdr != NULL) 186865059Seric { 186965059Seric bp = buf; 187065059Seric strcpy(buf, "ctladdr="); 187165059Seric bp += strlen(buf); 187265059Seric strcpy(bp, shortenstring(ctladdr->q_paddr, 83)); 187365059Seric bp += strlen(buf); 187465059Seric if (bitset(QGOODUID, ctladdr->q_flags)) 187565059Seric { 187665059Seric (void) sprintf(bp, " (%d/%d)", 187765059Seric ctladdr->q_uid, ctladdr->q_gid); 187865059Seric bp += strlen(bp); 187965059Seric } 188065059Seric syslog(LOG_INFO, "%s: %s", e->e_id, buf); 188165059Seric } 188265059Seric syslog(LOG_INFO, "%s: delay=%s", 188365059Seric e->e_id, pintvl(curtime() - e->e_ctime, TRUE)); 188465059Seric 188565059Seric if (m != NULL) 188665059Seric syslog(LOG_INFO, "%s: mailer=%s", e->e_id, m->m_name); 188765059Seric 188865059Seric if (mci != NULL && mci->mci_host != NULL) 188965059Seric { 189065059Seric # ifdef DAEMON 189165059Seric extern SOCKADDR CurHostAddr; 189265059Seric # endif 189365059Seric 189465059Seric (void) strcpy(buf, mci->mci_host); 189565059Seric 189665059Seric # ifdef DAEMON 189765059Seric (void) strcat(buf, " ("); 189865059Seric (void) strcat(buf, anynet_ntoa(&CurHostAddr)); 189965059Seric (void) strcat(buf, ")"); 190065059Seric # endif 190165059Seric syslog(LOG_INFO, "%s: relay=%s", e->e_id, buf); 190265059Seric } 190365059Seric else 190465059Seric { 190565059Seric char *p = macvalue('h', e); 190665059Seric 190765059Seric if (p != NULL && p[0] != '\0') 190865059Seric syslog(LOG_INFO, "%s: relay=%s", e->e_id, p); 190965059Seric } 191065059Seric 191165059Seric syslog(LOG_INFO, "%s: stat=%s", e->e_id, shortenstring(stat, 63)); 191265059Seric # endif /* short log buffer */ 191356795Seric # endif /* LOG */ 19148496Seric } 19158496Seric /* 19166974Seric ** PUTFROMLINE -- output a UNIX-style from line (or whatever) 1917294Seric ** 19186974Seric ** This can be made an arbitrary message separator by changing $l 1919294Seric ** 192016150Seric ** One of the ugliest hacks seen by human eyes is contained herein: 192116150Seric ** UUCP wants those stupid "remote from <host>" lines. Why oh why 192216150Seric ** does a well-meaning programmer such as myself have to deal with 192316150Seric ** this kind of antique garbage???? 19246974Seric ** 1925294Seric ** Parameters: 19266974Seric ** fp -- the file to output to. 19276974Seric ** m -- the mailer describing this entry. 1928294Seric ** 1929294Seric ** Returns: 19306974Seric ** none 1931294Seric ** 1932294Seric ** Side Effects: 19336974Seric ** outputs some text to fp. 1934294Seric */ 1935294Seric 193654967Seric putfromline(fp, m, e) 19376974Seric register FILE *fp; 19386974Seric register MAILER *m; 193954967Seric ENVELOPE *e; 1940294Seric { 194158050Seric char *template = "\201l\n"; 19426974Seric char buf[MAXLINE]; 1943294Seric 194410682Seric if (bitnset(M_NHDR, m->m_flags)) 19456974Seric return; 19464315Seric 19476974Seric # ifdef UGLYUUCP 194810682Seric if (bitnset(M_UGLYUUCP, m->m_flags)) 19494205Seric { 195012223Seric char *bang; 195112223Seric char xbuf[MAXLINE]; 19526041Seric 195358680Seric expand("\201g", buf, &buf[sizeof buf - 1], e); 195456795Seric bang = strchr(buf, '!'); 19556974Seric if (bang == NULL) 195664370Seric { 195764370Seric errno = 0; 195864370Seric syserr("554 No ! in UUCP From address! (%s given)", buf); 195964370Seric } 19605099Seric else 19619370Seric { 196212223Seric *bang++ = '\0'; 196358050Seric (void) sprintf(xbuf, "From %s \201d remote from %s\n", bang, buf); 196412223Seric template = xbuf; 19659370Seric } 19666974Seric } 196756795Seric # endif /* UGLYUUCP */ 196854967Seric expand(template, buf, &buf[sizeof buf - 1], e); 196910168Seric putline(buf, fp, m); 19705981Seric } 19715981Seric /* 19726974Seric ** PUTBODY -- put the body of a message. 19736974Seric ** 19746974Seric ** Parameters: 19756974Seric ** fp -- file to output onto. 197610168Seric ** m -- a mailer descriptor to control output format. 19779538Seric ** e -- the envelope to put out. 197859730Seric ** separator -- if non-NULL, a message separator that must 197959730Seric ** not be permitted in the resulting message. 19806974Seric ** 19816974Seric ** Returns: 19826974Seric ** none. 19836974Seric ** 19846974Seric ** Side Effects: 19856974Seric ** The message is written onto fp. 19866974Seric */ 19876974Seric 198859730Seric putbody(fp, m, e, separator) 19896974Seric FILE *fp; 19909370Seric MAILER *m; 19919538Seric register ENVELOPE *e; 199259730Seric char *separator; 19936974Seric { 199410168Seric char buf[MAXLINE]; 19956974Seric 19966974Seric /* 19976974Seric ** Output the body of the message 19986974Seric */ 19996974Seric 20009538Seric if (e->e_dfp == NULL) 20016974Seric { 20029538Seric if (e->e_df != NULL) 20039538Seric { 20049538Seric e->e_dfp = fopen(e->e_df, "r"); 20059538Seric if (e->e_dfp == NULL) 200640931Srick syserr("putbody: Cannot open %s for %s from %s", 200764118Seric e->e_df, e->e_to, e->e_from.q_paddr); 20089538Seric } 20099538Seric else 201010168Seric putline("<<< No Message Collected >>>", fp, m); 20119538Seric } 20129538Seric if (e->e_dfp != NULL) 20139538Seric { 20149538Seric rewind(e->e_dfp); 201510168Seric while (!ferror(fp) && fgets(buf, sizeof buf, e->e_dfp) != NULL) 201616875Seric { 201716875Seric if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) && 201840995Sbostic strncmp(buf, "From ", 5) == 0) 201923102Seric (void) putc('>', fp); 202059730Seric if (buf[0] == '-' && buf[1] == '-' && separator != NULL) 202159730Seric { 202259730Seric /* possible separator */ 202359730Seric int sl = strlen(separator); 202459730Seric 202559730Seric if (strncmp(&buf[2], separator, sl) == 0) 202659730Seric (void) putc(' ', fp); 202759730Seric } 202810168Seric putline(buf, fp, m); 202916875Seric } 20306974Seric 20319538Seric if (ferror(e->e_dfp)) 20326974Seric { 203364718Seric syserr("putbody: %s: read error", e->e_df); 20346974Seric ExitStat = EX_IOERR; 20356974Seric } 20366974Seric } 20376974Seric 203859542Seric /* some mailers want extra blank line at end of message */ 203959542Seric if (bitnset(M_BLANKEND, m->m_flags) && buf[0] != '\0' && buf[0] != '\n') 204059542Seric putline("", fp, m); 204159542Seric 20426974Seric (void) fflush(fp); 20436974Seric if (ferror(fp) && errno != EPIPE) 20446974Seric { 20456974Seric syserr("putbody: write error"); 20466974Seric ExitStat = EX_IOERR; 20476974Seric } 20486974Seric errno = 0; 20496974Seric } 20506974Seric /* 2051294Seric ** MAILFILE -- Send a message to a file. 2052294Seric ** 20534327Seric ** If the file has the setuid/setgid bits set, but NO execute 20544327Seric ** bits, sendmail will try to become the owner of that file 20554327Seric ** rather than the real user. Obviously, this only works if 20564327Seric ** sendmail runs as root. 20574327Seric ** 20589370Seric ** This could be done as a subordinate mailer, except that it 20599370Seric ** is used implicitly to save messages in ~/dead.letter. We 20609370Seric ** view this as being sufficiently important as to include it 20619370Seric ** here. For example, if the system is dying, we shouldn't have 20629370Seric ** to create another process plus some pipes to save the message. 20639370Seric ** 2064294Seric ** Parameters: 2065294Seric ** filename -- the name of the file to send to. 20664397Seric ** ctladdr -- the controlling address header -- includes 20674397Seric ** the userid/groupid to be when sending. 2068294Seric ** 2069294Seric ** Returns: 2070294Seric ** The exit code associated with the operation. 2071294Seric ** 2072294Seric ** Side Effects: 2073294Seric ** none. 2074294Seric */ 2075294Seric 207654967Seric mailfile(filename, ctladdr, e) 2077294Seric char *filename; 20784397Seric ADDRESS *ctladdr; 207954967Seric register ENVELOPE *e; 2080294Seric { 2081294Seric register FILE *f; 20824214Seric register int pid; 208353751Seric int mode; 2084294Seric 208559267Seric if (tTd(11, 1)) 208659267Seric { 208759267Seric printf("mailfile %s\n ctladdr=", filename); 208859267Seric printaddr(ctladdr, FALSE); 208959267Seric } 209059267Seric 209163753Seric if (e->e_xfp != NULL) 209263753Seric fflush(e->e_xfp); 209363753Seric 20944214Seric /* 20954214Seric ** Fork so we can change permissions here. 20964214Seric ** Note that we MUST use fork, not vfork, because of 20974214Seric ** the complications of calling subroutines, etc. 20984214Seric */ 20994067Seric 21004214Seric DOFORK(fork); 21014214Seric 21024214Seric if (pid < 0) 21034214Seric return (EX_OSERR); 21044214Seric else if (pid == 0) 21054214Seric { 21064214Seric /* child -- actually write to file */ 21074327Seric struct stat stb; 21084327Seric 210964035Seric (void) setsignal(SIGINT, SIG_DFL); 211064035Seric (void) setsignal(SIGHUP, SIG_DFL); 211164035Seric (void) setsignal(SIGTERM, SIG_DFL); 211223102Seric (void) umask(OldUmask); 211352673Seric 21144327Seric if (stat(filename, &stb) < 0) 211559745Seric stb.st_mode = FileMode; 211653751Seric mode = stb.st_mode; 211752673Seric 211852673Seric /* limit the errors to those actually caused in the child */ 211952673Seric errno = 0; 212052673Seric ExitStat = EX_OK; 212152673Seric 21224327Seric if (bitset(0111, stb.st_mode)) 21234327Seric exit(EX_CANTCREAT); 212464823Seric if (ctladdr != NULL) 212553751Seric { 212653751Seric /* ignore setuid and setgid bits */ 212753751Seric mode &= ~(S_ISGID|S_ISUID); 212853751Seric } 212953751Seric 213040931Srick /* we have to open the dfile BEFORE setuid */ 213153751Seric if (e->e_dfp == NULL && e->e_df != NULL) 213240931Srick { 213340931Srick e->e_dfp = fopen(e->e_df, "r"); 213452673Seric if (e->e_dfp == NULL) 213552673Seric { 213640931Srick syserr("mailfile: Cannot open %s for %s from %s", 213764118Seric e->e_df, e->e_to, e->e_from.q_paddr); 213840931Srick } 213940931Srick } 214040931Srick 214153751Seric if (!bitset(S_ISGID, mode) || setgid(stb.st_gid) < 0) 21424417Seric { 214364823Seric if (ctladdr == NULL || ctladdr->q_uid == 0) 214452673Seric { 214540972Sbostic (void) initgroups(DefUser, DefGid); 214652673Seric } 214752673Seric else 214852673Seric { 214953751Seric (void) initgroups(ctladdr->q_ruser ? 215053751Seric ctladdr->q_ruser : ctladdr->q_user, 215140972Sbostic ctladdr->q_gid); 215240972Sbostic } 21534417Seric } 215453751Seric if (!bitset(S_ISUID, mode) || setuid(stb.st_uid) < 0) 21554417Seric { 215664823Seric if (ctladdr == NULL || ctladdr->q_uid == 0) 21574417Seric (void) setuid(DefUid); 21584417Seric else 21594417Seric (void) setuid(ctladdr->q_uid); 21604417Seric } 216152673Seric FileName = filename; 216252673Seric LineNumber = 0; 216359745Seric f = dfopen(filename, O_WRONLY|O_CREAT|O_APPEND, FileMode); 21644214Seric if (f == NULL) 216552673Seric { 216664387Seric message("554 cannot open: %s", errstring(errno)); 21674214Seric exit(EX_CANTCREAT); 216852673Seric } 21694214Seric 217059275Seric putfromline(f, FileMailer, e); 217159275Seric (*e->e_puthdr)(f, FileMailer, e); 217259275Seric putline("\n", f, FileMailer); 217359730Seric (*e->e_putbody)(f, FileMailer, e, NULL); 217459275Seric putline("\n", f, FileMailer); 217552673Seric if (ferror(f)) 217652673Seric { 217764387Seric message("451 I/O error: %s", errstring(errno)); 217852673Seric setstat(EX_IOERR); 217952673Seric } 218058680Seric (void) xfclose(f, "mailfile", filename); 21814214Seric (void) fflush(stdout); 21824417Seric 21836887Seric /* reset ISUID & ISGID bits for paranoid systems */ 21844621Seric (void) chmod(filename, (int) stb.st_mode); 218552673Seric exit(ExitStat); 21864315Seric /*NOTREACHED*/ 21874214Seric } 21884214Seric else 21894214Seric { 21904214Seric /* parent -- wait for exit status */ 21919370Seric int st; 21924214Seric 21939370Seric st = waitfor(pid); 219464379Seric if (WIFEXITED(st)) 219564379Seric return (WEXITSTATUS(st)); 219664379Seric else 219764387Seric { 219864387Seric syserr("child died on signal %d", st); 21999370Seric return (EX_UNAVAILABLE); 220064387Seric } 220140931Srick /*NOTREACHED*/ 22024214Seric } 2203294Seric } 22044550Seric /* 220557454Seric ** HOSTSIGNATURE -- return the "signature" for a host. 220657454Seric ** 220757454Seric ** The signature describes how we are going to send this -- it 220857454Seric ** can be just the hostname (for non-Internet hosts) or can be 220957454Seric ** an ordered list of MX hosts. 221057454Seric ** 221157454Seric ** Parameters: 221257454Seric ** m -- the mailer describing this host. 221357454Seric ** host -- the host name. 221457454Seric ** e -- the current envelope. 221557454Seric ** 221657454Seric ** Returns: 221757454Seric ** The signature for this host. 221857454Seric ** 221957454Seric ** Side Effects: 222057454Seric ** Can tweak the symbol table. 222157454Seric */ 222257454Seric 222357454Seric char * 222457454Seric hostsignature(m, host, e) 222557454Seric register MAILER *m; 222657454Seric char *host; 222757454Seric ENVELOPE *e; 222857454Seric { 222957454Seric register char *p; 223057454Seric register STAB *s; 223157454Seric int i; 223257454Seric int len; 223357454Seric #ifdef NAMED_BIND 223457454Seric int nmx; 223557454Seric auto int rcode; 223659076Seric char *hp; 223759076Seric char *endp; 223859111Seric int oldoptions; 223957454Seric char *mxhosts[MAXMXHOSTS + 1]; 224057454Seric #endif 224157454Seric 224257454Seric /* 224357454Seric ** Check to see if this uses IPC -- if not, it can't have MX records. 224457454Seric */ 224557454Seric 224657454Seric p = m->m_mailer; 224757454Seric if (strcmp(p, "[IPC]") != 0 && strcmp(p, "[TCP]") != 0) 224857454Seric { 224957454Seric /* just an ordinary mailer */ 225057454Seric return host; 225157454Seric } 225257454Seric 225357454Seric /* 225457454Seric ** Look it up in the symbol table. 225557454Seric */ 225657454Seric 225757454Seric s = stab(host, ST_HOSTSIG, ST_ENTER); 225857454Seric if (s->s_hostsig != NULL) 225957454Seric return s->s_hostsig; 226057454Seric 226157454Seric /* 226257454Seric ** Not already there -- create a signature. 226357454Seric */ 226457454Seric 226557454Seric #ifdef NAMED_BIND 226659111Seric if (ConfigLevel < 2) 226759111Seric { 226859111Seric oldoptions = _res.options; 226959111Seric _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ 227059111Seric } 227159111Seric 227259076Seric for (hp = host; hp != NULL; hp = endp) 227357454Seric { 227459076Seric endp = strchr(hp, ':'); 227559076Seric if (endp != NULL) 227659076Seric *endp = '\0'; 227757454Seric 227859273Seric nmx = getmxrr(hp, mxhosts, TRUE, &rcode); 227957454Seric 228059076Seric if (nmx <= 0) 228159076Seric { 228259076Seric register MCI *mci; 228357454Seric 228459076Seric /* update the connection info for this host */ 228559076Seric mci = mci_get(hp, m); 228659076Seric mci->mci_exitstat = rcode; 228759076Seric mci->mci_errno = errno; 228863753Seric #ifdef NAMED_BIND 228963753Seric mci->mci_herrno = h_errno; 229063753Seric #endif 229159076Seric 229259076Seric /* and return the original host name as the signature */ 229359076Seric nmx = 1; 229459076Seric mxhosts[0] = hp; 229559076Seric } 229659076Seric 229759076Seric len = 0; 229859076Seric for (i = 0; i < nmx; i++) 229959076Seric { 230059076Seric len += strlen(mxhosts[i]) + 1; 230159076Seric } 230259076Seric if (s->s_hostsig != NULL) 230359076Seric len += strlen(s->s_hostsig) + 1; 230459076Seric p = xalloc(len); 230559076Seric if (s->s_hostsig != NULL) 230659076Seric { 230759076Seric (void) strcpy(p, s->s_hostsig); 230859076Seric free(s->s_hostsig); 230959076Seric s->s_hostsig = p; 231059076Seric p += strlen(p); 231157454Seric *p++ = ':'; 231259076Seric } 231359076Seric else 231459076Seric s->s_hostsig = p; 231559076Seric for (i = 0; i < nmx; i++) 231659076Seric { 231759076Seric if (i != 0) 231859076Seric *p++ = ':'; 231959076Seric strcpy(p, mxhosts[i]); 232059076Seric p += strlen(p); 232159076Seric } 232259076Seric if (endp != NULL) 232359076Seric *endp++ = ':'; 232457454Seric } 232557454Seric makelower(s->s_hostsig); 232659111Seric if (ConfigLevel < 2) 232759111Seric _res.options = oldoptions; 232857454Seric #else 232957454Seric /* not using BIND -- the signature is just the host name */ 233057454Seric s->s_hostsig = host; 233157454Seric #endif 233257454Seric if (tTd(17, 1)) 233357454Seric printf("hostsignature(%s) = %s\n", host, s->s_hostsig); 233457454Seric return s->s_hostsig; 233557454Seric } 2336