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*65919Seric static char sccsid[] = "@(#)deliver.c 8.66 (Berkeley) 01/27/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 6165580Seric if (bitset(EF_FATALERRS, e->e_flags) && 6265580Seric (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 31465580Seric if (bitset(EF_FATALERRS, e->e_flags) && 31565580Seric (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 33765830Seric # if !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 */ 58365580Seric if (OpMode == MD_DAEMON || OpMode == MD_SMTP) 58465580Seric { 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 */ 89365750Seric if (ctladdr == NULL && m != ProgMailer && 89465750Seric bitset(QGOODUID, e->e_from.q_flags)) 89565137Seric ctladdr = &e->e_from; 89665137Seric 89735651Seric #ifdef NAMED_BIND 89851313Seric if (ConfigLevel < 2) 89951313Seric _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ 90035651Seric #endif 90154967Seric 9027672Seric if (tTd(11, 1)) 903294Seric { 9048178Seric printf("openmailer:"); 90558820Seric printav(pv); 906294Seric } 9074488Seric errno = 0; 9083233Seric 90925050Seric CurHostName = m->m_mailer; 91025050Seric 9116038Seric /* 9126038Seric ** Deal with the special case of mail handled through an IPC 9136038Seric ** connection. 9146038Seric ** In this case we don't actually fork. We must be 9156038Seric ** running SMTP for this to work. We will return a 9166038Seric ** zero pid to indicate that we are running IPC. 91711160Seric ** We also handle a debug version that just talks to stdin/out. 9186038Seric */ 9196038Seric 92058820Seric curhost = NULL; 92164334Seric SmtpPhase = NULL; 92264718Seric mci = NULL; 92358820Seric 92464401Seric #ifdef XDEBUG 92564401Seric { 92664401Seric char wbuf[MAXLINE]; 92764401Seric 92864401Seric /* make absolutely certain 0, 1, and 2 are in use */ 92964401Seric sprintf(wbuf, "%s... openmailer(%s)", e->e_to, m->m_name); 93064401Seric checkfd012(wbuf); 93164401Seric } 93264401Seric #endif 93364401Seric 93411160Seric /* check for Local Person Communication -- not for mortals!!! */ 93511160Seric if (strcmp(m->m_mailer, "[LPC]") == 0) 93611160Seric { 93754967Seric mci = (MCI *) xalloc(sizeof *mci); 93854993Seric bzero((char *) mci, sizeof *mci); 93953738Seric mci->mci_in = stdin; 94053738Seric mci->mci_out = stdout; 94154967Seric mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN; 94253751Seric mci->mci_mailer = m; 94311160Seric } 94454967Seric else if (strcmp(m->m_mailer, "[IPC]") == 0 || 94554967Seric strcmp(m->m_mailer, "[TCP]") == 0) 9466038Seric { 94752107Seric #ifdef DAEMON 94857454Seric register int i; 9497285Seric register u_short port; 9506038Seric 95164844Seric if (pv[0] == NULL || pv[1] == NULL || pv[1][0] == '\0') 95264844Seric { 95364844Seric syserr("null host name for %s mailer", m->m_mailer); 95464844Seric rcode = EX_CONFIG; 95564844Seric goto give_up; 95664844Seric } 95764844Seric 95858820Seric CurHostName = pv[1]; 95958820Seric curhost = hostsignature(m, pv[1], e); 96054967Seric 96158479Seric if (curhost == NULL || curhost[0] == '\0') 96258479Seric { 96364844Seric syserr("null host signature for %s", pv[1]); 96458820Seric rcode = EX_OSERR; 96558820Seric goto give_up; 96658479Seric } 96758479Seric 9686038Seric if (!clever) 96958479Seric { 97058151Seric syserr("554 non-clever IPC"); 97164718Seric rcode = EX_CONFIG; 97258820Seric goto give_up; 97358479Seric } 97458820Seric if (pv[2] != NULL) 97558820Seric port = atoi(pv[2]); 9766632Seric else 9777285Seric port = 0; 97858820Seric tryhost: 97957454Seric while (*curhost != '\0') 98029433Sbloom { 98157454Seric register char *p; 98258664Seric static char hostbuf[MAXNAME]; 98357454Seric 98457454Seric /* pull the next host from the signature */ 98557454Seric p = strchr(curhost, ':'); 98657454Seric if (p == NULL) 98757454Seric p = &curhost[strlen(curhost)]; 98864718Seric if (p == curhost) 98964718Seric { 99064718Seric syserr("deliver: null host name in signature"); 99164726Seric curhost++; 99264718Seric continue; 99364718Seric } 99457454Seric strncpy(hostbuf, curhost, p - curhost); 99557454Seric hostbuf[p - curhost] = '\0'; 99657454Seric if (*p != '\0') 99757454Seric p++; 99857454Seric curhost = p; 99957454Seric 100053738Seric /* see if we already know that this host is fried */ 100157454Seric CurHostName = hostbuf; 100257454Seric mci = mci_get(hostbuf, m); 100354967Seric if (mci->mci_state != MCIS_CLOSED) 100457387Seric { 100557387Seric if (tTd(11, 1)) 100657387Seric { 100757387Seric printf("openmailer: "); 100864731Seric mci_dump(mci, FALSE); 100957387Seric } 101057943Seric CurHostName = mci->mci_host; 101158820Seric break; 101257387Seric } 101353751Seric mci->mci_mailer = m; 101454967Seric if (mci->mci_exitstat != EX_OK) 101554967Seric continue; 101654967Seric 101754967Seric /* try the connection */ 101857454Seric setproctitle("%s %s: %s", e->e_id, hostbuf, "user open"); 101958151Seric message("Connecting to %s (%s)...", 102057454Seric hostbuf, m->m_name); 102157454Seric i = makeconnection(hostbuf, port, mci, 102254967Seric bitnset(M_SECURE_PORT, m->m_flags)); 102354967Seric mci->mci_exitstat = i; 102454967Seric mci->mci_errno = errno; 102563753Seric #ifdef NAMED_BIND 102663753Seric mci->mci_herrno = h_errno; 102763753Seric #endif 102854967Seric if (i == EX_OK) 102952106Seric { 103054967Seric mci->mci_state = MCIS_OPENING; 103154967Seric mci_cache(mci); 103263753Seric if (TrafficLogFile != NULL) 103363753Seric fprintf(TrafficLogFile, "%05d == CONNECT %s\n", 103463753Seric getpid(), hostbuf); 103554967Seric break; 103634022Sbostic } 103754967Seric else if (tTd(11, 1)) 103854967Seric printf("openmailer: makeconnection => stat=%d, errno=%d\n", 103954967Seric i, errno); 104053738Seric 104153738Seric /* enter status of this host */ 104253738Seric setstat(i); 104364718Seric 104464718Seric /* should print some message here for -v mode */ 10456047Seric } 104664718Seric if (mci == NULL) 104764718Seric { 104864718Seric syserr("deliver: no host name"); 104964718Seric rcode = EX_OSERR; 105064718Seric goto give_up; 105164718Seric } 105254993Seric mci->mci_pid = 0; 105354967Seric #else /* no DAEMON */ 105458151Seric syserr("554 openmailer: no IPC"); 105557387Seric if (tTd(11, 1)) 105657387Seric printf("openmailer: NULL\n"); 105764718Seric rcode = EX_UNAVAILABLE; 105864718Seric goto give_up; 105954967Seric #endif /* DAEMON */ 10606038Seric } 106154967Seric else 1062294Seric { 106363753Seric if (TrafficLogFile != NULL) 106458852Seric { 106563753Seric char **av; 106658925Seric 106763753Seric fprintf(TrafficLogFile, "%05d === EXEC", getpid()); 106863753Seric for (av = pv; *av != NULL; av++) 106963753Seric fprintf(TrafficLogFile, " %s", *av); 107063753Seric fprintf(TrafficLogFile, "\n"); 107158852Seric } 107258852Seric 107354967Seric /* create a pipe to shove the mail through */ 107454967Seric if (pipe(mpvect) < 0) 107554967Seric { 107658925Seric syserr("%s... openmailer(%s): pipe (to mailer)", 107758925Seric e->e_to, m->m_name); 107857387Seric if (tTd(11, 1)) 107957387Seric printf("openmailer: NULL\n"); 108058820Seric rcode = EX_OSERR; 108158820Seric goto give_up; 108254967Seric } 10834863Seric 108454967Seric /* if this mailer speaks smtp, create a return pipe */ 108554967Seric if (clever && pipe(rpvect) < 0) 108654967Seric { 108758925Seric syserr("%s... openmailer(%s): pipe (from mailer)", 108858925Seric e->e_to, m->m_name); 108954967Seric (void) close(mpvect[0]); 109054967Seric (void) close(mpvect[1]); 109157387Seric if (tTd(11, 1)) 109257387Seric printf("openmailer: NULL\n"); 109358820Seric rcode = EX_OSERR; 109458820Seric goto give_up; 109554967Seric } 10964863Seric 109754967Seric /* 109854967Seric ** Actually fork the mailer process. 109954967Seric ** DOFORK is clever about retrying. 110054967Seric ** 110154967Seric ** Dispose of SIGCHLD signal catchers that may be laying 110254967Seric ** around so that endmail will get it. 110354967Seric */ 11046038Seric 110554967Seric if (e->e_xfp != NULL) 110654967Seric (void) fflush(e->e_xfp); /* for debugging */ 110754967Seric (void) fflush(stdout); 110826434Seric # ifdef SIGCHLD 110964035Seric (void) setsignal(SIGCHLD, SIG_DFL); 111056795Seric # endif /* SIGCHLD */ 111154967Seric DOFORK(FORK); 111254967Seric /* pid is set by DOFORK */ 111354967Seric if (pid < 0) 11144863Seric { 111554967Seric /* failure */ 111658925Seric syserr("%s... openmailer(%s): cannot fork", 111758925Seric e->e_to, m->m_name); 111854967Seric (void) close(mpvect[0]); 111954967Seric (void) close(mpvect[1]); 112054967Seric if (clever) 112154967Seric { 112254967Seric (void) close(rpvect[0]); 112354967Seric (void) close(rpvect[1]); 112454967Seric } 112557387Seric if (tTd(11, 1)) 112657387Seric printf("openmailer: NULL\n"); 112758820Seric rcode = EX_OSERR; 112858820Seric goto give_up; 11294863Seric } 113054967Seric else if (pid == 0) 113154967Seric { 113254967Seric int i; 113356678Seric int saveerrno; 113458675Seric char **ep; 113558675Seric char *env[MAXUSERENVIRON]; 113658675Seric extern char **environ; 113754967Seric extern int DtableSize; 113815772Seric 113954967Seric /* child -- set up input & exec mailer */ 114064035Seric (void) setsignal(SIGINT, SIG_IGN); 114164035Seric (void) setsignal(SIGHUP, SIG_IGN); 114264035Seric (void) setsignal(SIGTERM, SIG_DFL); 11434709Seric 114464145Seric /* reset user and group */ 114564145Seric if (!bitnset(M_RESTR, m->m_flags)) 114664145Seric { 114764145Seric if (ctladdr == NULL || ctladdr->q_uid == 0) 114864145Seric { 114964145Seric (void) initgroups(DefUser, DefGid); 115064837Seric (void) setgid(DefGid); 115164145Seric (void) setuid(DefUid); 115264145Seric } 115364145Seric else 115464145Seric { 115564145Seric (void) initgroups(ctladdr->q_ruser? 115664145Seric ctladdr->q_ruser: ctladdr->q_user, 115764145Seric ctladdr->q_gid); 115864970Seric (void) setgid(ctladdr->q_gid); 115964145Seric (void) setuid(ctladdr->q_uid); 116064145Seric } 116164145Seric } 116264145Seric 116364145Seric if (tTd(11, 2)) 116464145Seric printf("openmailer: running as r/euid=%d/%d\n", 116564145Seric getuid(), geteuid()); 116664145Seric 116758935Seric /* move into some "safe" directory */ 116858935Seric if (m->m_execdir != NULL) 116958935Seric { 117058935Seric char *p, *q; 117158935Seric char buf[MAXLINE]; 117258935Seric 117358935Seric for (p = m->m_execdir; p != NULL; p = q) 117458935Seric { 117558935Seric q = strchr(p, ':'); 117658935Seric if (q != NULL) 117758935Seric *q = '\0'; 117858935Seric expand(p, buf, &buf[sizeof buf] - 1, e); 117958935Seric if (q != NULL) 118058935Seric *q++ = ':'; 118158935Seric if (tTd(11, 20)) 118258935Seric printf("openmailer: trydir %s\n", 118358935Seric buf); 118458935Seric if (buf[0] != '\0' && chdir(buf) >= 0) 118558935Seric break; 118658935Seric } 118758935Seric } 118858935Seric 118954967Seric /* arrange to filter std & diag output of command */ 119054967Seric if (clever) 119154967Seric { 119254967Seric (void) close(rpvect[0]); 119358852Seric if (dup2(rpvect[1], STDOUT_FILENO) < 0) 119458852Seric { 119558925Seric syserr("%s... openmailer(%s): cannot dup pipe %d for stdout", 119658925Seric e->e_to, m->m_name, rpvect[1]); 119758852Seric _exit(EX_OSERR); 119858852Seric } 119954967Seric (void) close(rpvect[1]); 120054967Seric } 120165580Seric else if (OpMode == MD_SMTP || OpMode == MD_DAEMON || HoldErrs) 120254967Seric { 120354967Seric /* put mailer output in transcript */ 120458852Seric if (dup2(fileno(e->e_xfp), STDOUT_FILENO) < 0) 120558852Seric { 120658925Seric syserr("%s... openmailer(%s): cannot dup xscript %d for stdout", 120758925Seric e->e_to, m->m_name, 120858852Seric fileno(e->e_xfp)); 120958852Seric _exit(EX_OSERR); 121058852Seric } 121154967Seric } 121258852Seric if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) 121358852Seric { 121458925Seric syserr("%s... openmailer(%s): cannot dup stdout for stderr", 121558925Seric e->e_to, m->m_name); 121658852Seric _exit(EX_OSERR); 121758852Seric } 12184709Seric 121954967Seric /* arrange to get standard input */ 122054967Seric (void) close(mpvect[1]); 122158731Seric if (dup2(mpvect[0], STDIN_FILENO) < 0) 12224417Seric { 122358925Seric syserr("%s... openmailer(%s): cannot dup pipe %d for stdin", 122458925Seric e->e_to, m->m_name, mpvect[0]); 122554967Seric _exit(EX_OSERR); 12264417Seric } 122754967Seric (void) close(mpvect[0]); 12289370Seric 122954967Seric /* arrange for all the files to be closed */ 123054967Seric for (i = 3; i < DtableSize; i++) 123154967Seric { 123254967Seric register int j; 123364145Seric 123454967Seric if ((j = fcntl(i, F_GETFD, 0)) != -1) 123564145Seric (void) fcntl(i, F_SETFD, j | 1); 123654967Seric } 12372774Seric 123858675Seric /* set up the mailer environment */ 123958675Seric i = 0; 124058675Seric env[i++] = "AGENT=sendmail"; 124158675Seric for (ep = environ; *ep != NULL; ep++) 124258675Seric { 124358675Seric if (strncmp(*ep, "TZ=", 3) == 0) 124458675Seric env[i++] = *ep; 124558675Seric } 124658675Seric env[i++] = NULL; 124758675Seric 124854967Seric /* try to execute the mailer */ 124958820Seric execve(m->m_mailer, pv, env); 125056678Seric saveerrno = errno; 125154967Seric syserr("Cannot exec %s", m->m_mailer); 125260008Seric if (m == LocalMailer || transienterror(saveerrno)) 125360008Seric _exit(EX_OSERR); 125454967Seric _exit(EX_UNAVAILABLE); 125551835Seric } 125654967Seric 125754967Seric /* 125854967Seric ** Set up return value. 125954967Seric */ 126054967Seric 126154967Seric mci = (MCI *) xalloc(sizeof *mci); 126254993Seric bzero((char *) mci, sizeof *mci); 126354967Seric mci->mci_mailer = m; 126454967Seric mci->mci_state = clever ? MCIS_OPENING : MCIS_OPEN; 126554993Seric mci->mci_pid = pid; 126654967Seric (void) close(mpvect[0]); 126754967Seric mci->mci_out = fdopen(mpvect[1], "w"); 126864724Seric if (mci->mci_out == NULL) 126964724Seric { 127064724Seric syserr("deliver: cannot create mailer output channel, fd=%d", 127164724Seric mpvect[1]); 127264724Seric (void) close(mpvect[1]); 127364724Seric if (clever) 127464724Seric { 127564724Seric (void) close(rpvect[0]); 127664724Seric (void) close(rpvect[1]); 127764724Seric } 127864724Seric rcode = EX_OSERR; 127964724Seric goto give_up; 128064724Seric } 128154967Seric if (clever) 128254967Seric { 128354967Seric (void) close(rpvect[1]); 128454967Seric mci->mci_in = fdopen(rpvect[0], "r"); 128564724Seric if (mci->mci_in == NULL) 128664724Seric { 128764724Seric syserr("deliver: cannot create mailer input channel, fd=%d", 128864724Seric mpvect[1]); 128964724Seric (void) close(rpvect[0]); 129064724Seric fclose(mci->mci_out); 129164724Seric mci->mci_out = NULL; 129264724Seric rcode = EX_OSERR; 129364724Seric goto give_up; 129464724Seric } 129554967Seric } 129654967Seric else 129754967Seric { 129854967Seric mci->mci_flags |= MCIF_TEMP; 129954967Seric mci->mci_in = NULL; 130054967Seric } 1301294Seric } 1302294Seric 13034709Seric /* 130454967Seric ** If we are in SMTP opening state, send initial protocol. 13054709Seric */ 13064709Seric 130754967Seric if (clever && mci->mci_state != MCIS_CLOSED) 13084863Seric { 130954967Seric smtpinit(m, mci, e); 131053738Seric } 131157387Seric if (tTd(11, 1)) 131257387Seric { 131357387Seric printf("openmailer: "); 131464731Seric mci_dump(mci, FALSE); 131557387Seric } 1316294Seric 131758820Seric if (mci->mci_state != MCIS_OPEN) 131858820Seric { 131958820Seric /* couldn't open the mailer */ 132058820Seric rcode = mci->mci_exitstat; 132158820Seric errno = mci->mci_errno; 132263753Seric #ifdef NAMED_BIND 132363753Seric h_errno = mci->mci_herrno; 132463753Seric #endif 132558820Seric if (rcode == EX_OK) 132658820Seric { 132758820Seric /* shouldn't happen */ 132858820Seric syserr("554 deliver: rcode=%d, mci_state=%d, sig=%s", 132958820Seric rcode, mci->mci_state, firstsig); 133058820Seric rcode = EX_SOFTWARE; 133158820Seric } 133264922Seric else if (rcode == EX_TEMPFAIL && curhost != NULL && *curhost != '\0') 133359958Seric { 133459958Seric /* try next MX site */ 133559958Seric goto tryhost; 133659958Seric } 133758820Seric } 133858820Seric else if (!clever) 133958820Seric { 134058820Seric /* 134158820Seric ** Format and send message. 134258820Seric */ 134358820Seric 134465870Seric putfromline(mci, e); 134565870Seric (*e->e_puthdr)(mci, e); 134665870Seric putline("\n", mci); 134765870Seric (*e->e_putbody)(mci, e, NULL); 134858820Seric 134958820Seric /* get the exit status */ 135058820Seric rcode = endmailer(mci, e, pv); 135158820Seric } 135258820Seric else 135358820Seric #ifdef SMTP 135458820Seric { 135558820Seric /* 135658820Seric ** Send the MAIL FROM: protocol 135758820Seric */ 135858820Seric 135958820Seric rcode = smtpmailfrom(m, mci, e); 136058820Seric if (rcode == EX_OK) 136158820Seric { 136258820Seric register char *t = tobuf; 136358820Seric register int i; 136458820Seric 136558820Seric /* send the recipient list */ 136658820Seric tobuf[0] = '\0'; 136758820Seric for (to = tochain; to != NULL; to = to->q_tchain) 136858820Seric { 136958820Seric e->e_to = to->q_paddr; 137058820Seric if ((i = smtprcpt(to, m, mci, e)) != EX_OK) 137158820Seric { 137258820Seric markfailure(e, to, i); 137364771Seric giveresponse(i, m, mci, ctladdr, e); 137458820Seric } 137558820Seric else 137658820Seric { 137758820Seric *t++ = ','; 137858820Seric for (p = to->q_paddr; *p; *t++ = *p++) 137958820Seric continue; 138064372Seric *t = '\0'; 138158820Seric } 138258820Seric } 138358820Seric 138458820Seric /* now send the data */ 138558820Seric if (tobuf[0] == '\0') 138658820Seric { 138758820Seric rcode = EX_OK; 138858820Seric e->e_to = NULL; 138958820Seric if (bitset(MCIF_CACHED, mci->mci_flags)) 139058820Seric smtprset(m, mci, e); 139158820Seric } 139258820Seric else 139358820Seric { 139458820Seric e->e_to = tobuf + 1; 139558820Seric rcode = smtpdata(m, mci, e); 139658820Seric } 139758820Seric 139858820Seric /* now close the connection */ 139958820Seric if (!bitset(MCIF_CACHED, mci->mci_flags)) 140058820Seric smtpquit(m, mci, e); 140158820Seric } 140264922Seric if (rcode != EX_OK && curhost != NULL && *curhost != '\0') 140358820Seric { 140458820Seric /* try next MX site */ 140558820Seric goto tryhost; 140658820Seric } 140758820Seric } 140858820Seric #else /* not SMTP */ 140958820Seric { 141058820Seric syserr("554 deliver: need SMTP compiled to use clever mailer"); 141158820Seric rcode = EX_CONFIG; 141258820Seric goto give_up; 141358820Seric } 141458820Seric #endif /* SMTP */ 141558820Seric #ifdef NAMED_BIND 141658820Seric if (ConfigLevel < 2) 141758820Seric _res.options |= RES_DEFNAMES | RES_DNSRCH; /* XXX */ 141858820Seric #endif 141958820Seric 142058820Seric /* arrange a return receipt if requested */ 142164718Seric if (rcode == EX_OK && e->e_receiptto != NULL && 142264718Seric bitnset(M_LOCALMAILER, m->m_flags)) 142358820Seric { 142458820Seric e->e_flags |= EF_SENDRECEIPT; 142558820Seric /* do we want to send back more info? */ 142658820Seric } 142758820Seric 142858820Seric /* 142958820Seric ** Do final status disposal. 143058820Seric ** We check for something in tobuf for the SMTP case. 143158820Seric ** If we got a temporary failure, arrange to queue the 143258820Seric ** addressees. 143358820Seric */ 143458820Seric 143558820Seric give_up: 143658820Seric if (tobuf[0] != '\0') 143764771Seric giveresponse(rcode, m, mci, ctladdr, e); 143858820Seric for (to = tochain; to != NULL; to = to->q_tchain) 143958820Seric { 144058820Seric if (rcode != EX_OK) 144158820Seric markfailure(e, to, rcode); 144258820Seric else 144358820Seric { 144458820Seric to->q_flags |= QSENT; 144558820Seric e->e_nsent++; 144664718Seric if (e->e_receiptto != NULL && 144764718Seric bitnset(M_LOCALMAILER, m->m_flags)) 144864718Seric { 144964718Seric fprintf(e->e_xfp, "%s... Successfully delivered\n", 145064718Seric to->q_paddr); 145164718Seric } 145258820Seric } 145358820Seric } 145458820Seric 145558820Seric /* 145658820Seric ** Restore state and return. 145758820Seric */ 145858820Seric 145964401Seric #ifdef XDEBUG 146064401Seric { 146164401Seric char wbuf[MAXLINE]; 146264401Seric 146364401Seric /* make absolutely certain 0, 1, and 2 are in use */ 146464554Seric sprintf(wbuf, "%s... end of deliver(%s)", 146564554Seric e->e_to == NULL ? "NO-TO-LIST" : e->e_to, 146664554Seric m->m_name); 146764401Seric checkfd012(wbuf); 146864401Seric } 146964401Seric #endif 147064401Seric 147158820Seric errno = 0; 147258820Seric define('g', (char *) NULL, e); 147358820Seric return (rcode); 1474294Seric } 1475294Seric /* 147658820Seric ** MARKFAILURE -- mark a failure on a specific address. 147758820Seric ** 147858820Seric ** Parameters: 147958820Seric ** e -- the envelope we are sending. 148058820Seric ** q -- the address to mark. 148158820Seric ** rcode -- the code signifying the particular failure. 148258820Seric ** 148358820Seric ** Returns: 148458820Seric ** none. 148558820Seric ** 148658820Seric ** Side Effects: 148758820Seric ** marks the address (and possibly the envelope) with the 148858820Seric ** failure so that an error will be returned or 148958820Seric ** the message will be queued, as appropriate. 149058820Seric */ 149158820Seric 149258820Seric markfailure(e, q, rcode) 149358820Seric register ENVELOPE *e; 149458820Seric register ADDRESS *q; 149558820Seric int rcode; 149658820Seric { 149758820Seric char buf[MAXLINE]; 149858820Seric 149965051Seric switch (rcode) 150065051Seric { 150165051Seric case EX_OK: 150265051Seric break; 150365051Seric 150465051Seric case EX_TEMPFAIL: 150565051Seric case EX_IOERR: 150665051Seric case EX_OSERR: 150763753Seric q->q_flags |= QQUEUEUP; 150865051Seric break; 150965051Seric 151065051Seric default: 151158820Seric q->q_flags |= QBADADDR; 151265051Seric break; 151365051Seric } 151458820Seric } 151558820Seric /* 151658820Seric ** ENDMAILER -- Wait for mailer to terminate. 151758820Seric ** 151858820Seric ** We should never get fatal errors (e.g., segmentation 151958820Seric ** violation), so we report those specially. For other 152058820Seric ** errors, we choose a status message (into statmsg), 152158820Seric ** and if it represents an error, we print it. 152258820Seric ** 152358820Seric ** Parameters: 152458820Seric ** pid -- pid of mailer. 152558820Seric ** e -- the current envelope. 152658820Seric ** pv -- the parameter vector that invoked the mailer 152758820Seric ** (for error messages). 152858820Seric ** 152958820Seric ** Returns: 153058820Seric ** exit code of mailer. 153158820Seric ** 153258820Seric ** Side Effects: 153358820Seric ** none. 153458820Seric */ 153558820Seric 153658820Seric endmailer(mci, e, pv) 153758820Seric register MCI *mci; 153858820Seric register ENVELOPE *e; 153958820Seric char **pv; 154058820Seric { 154158820Seric int st; 154258820Seric 154358820Seric /* close any connections */ 154458820Seric if (mci->mci_in != NULL) 154565198Seric (void) xfclose(mci->mci_in, mci->mci_mailer->m_name, "mci_in"); 154658820Seric if (mci->mci_out != NULL) 154765198Seric (void) xfclose(mci->mci_out, mci->mci_mailer->m_name, "mci_out"); 154858820Seric mci->mci_in = mci->mci_out = NULL; 154958820Seric mci->mci_state = MCIS_CLOSED; 155058820Seric 155158820Seric /* in the IPC case there is nothing to wait for */ 155258820Seric if (mci->mci_pid == 0) 155358820Seric return (EX_OK); 155458820Seric 155558820Seric /* wait for the mailer process to die and collect status */ 155658820Seric st = waitfor(mci->mci_pid); 155758820Seric if (st == -1) 155858820Seric { 155958820Seric syserr("endmailer %s: wait", pv[0]); 156058820Seric return (EX_SOFTWARE); 156158820Seric } 156258820Seric 156364379Seric if (WIFEXITED(st)) 156458820Seric { 156564379Seric /* normal death -- return status */ 156664379Seric return (WEXITSTATUS(st)); 156764379Seric } 156858820Seric 156964379Seric /* it died a horrid death */ 157065545Seric syserr("451 mailer %s died with signal %o", 157165545Seric mci->mci_mailer->m_name, st); 157258820Seric 157364379Seric /* log the arguments */ 157465194Seric if (pv != NULL && e->e_xfp != NULL) 157564379Seric { 157664379Seric register char **av; 157758820Seric 157864379Seric fprintf(e->e_xfp, "Arguments:"); 157964379Seric for (av = pv; *av != NULL; av++) 158064379Seric fprintf(e->e_xfp, " %s", *av); 158164379Seric fprintf(e->e_xfp, "\n"); 158258820Seric } 158358820Seric 158464379Seric ExitStat = EX_TEMPFAIL; 158564379Seric return (EX_TEMPFAIL); 158658820Seric } 158758820Seric /* 1588294Seric ** GIVERESPONSE -- Interpret an error response from a mailer 1589294Seric ** 1590294Seric ** Parameters: 1591294Seric ** stat -- the status code from the mailer (high byte 1592294Seric ** only; core dumps must have been taken care of 1593294Seric ** already). 159458337Seric ** m -- the mailer info for this mailer. 159558337Seric ** mci -- the mailer connection info -- can be NULL if the 159658337Seric ** response is given before the connection is made. 159764771Seric ** ctladdr -- the controlling address for the recipient 159864771Seric ** address(es). 159958337Seric ** e -- the current envelope. 1600294Seric ** 1601294Seric ** Returns: 16024082Seric ** none. 1603294Seric ** 1604294Seric ** Side Effects: 16051518Seric ** Errors may be incremented. 1606294Seric ** ExitStat may be set. 1607294Seric */ 1608294Seric 160964771Seric giveresponse(stat, m, mci, ctladdr, e) 1610294Seric int stat; 16119370Seric register MAILER *m; 161258337Seric register MCI *mci; 161364771Seric ADDRESS *ctladdr; 161410105Seric ENVELOPE *e; 1615294Seric { 161660094Seric register const char *statmsg; 1617294Seric extern char *SysExMsg[]; 1618294Seric register int i; 161936788Sbostic extern int N_SysEx; 162010105Seric char buf[MAXLINE]; 1621294Seric 16224315Seric /* 16234315Seric ** Compute status message from code. 16244315Seric */ 16254315Seric 1626294Seric i = stat - EX__BASE; 16279370Seric if (stat == 0) 162858852Seric { 16299370Seric statmsg = "250 Sent"; 163058916Seric if (e->e_statmsg != NULL) 163158852Seric { 163258916Seric (void) sprintf(buf, "%s (%s)", statmsg, e->e_statmsg); 163358852Seric statmsg = buf; 163458852Seric } 163558852Seric } 16369370Seric else if (i < 0 || i > N_SysEx) 16379370Seric { 16389370Seric (void) sprintf(buf, "554 unknown mailer error %d", stat); 16399370Seric stat = EX_UNAVAILABLE; 16409370Seric statmsg = buf; 16419370Seric } 164210105Seric else if (stat == EX_TEMPFAIL) 164310105Seric { 164458664Seric (void) strcpy(buf, SysExMsg[i] + 1); 164536788Sbostic #ifdef NAMED_BIND 164625527Smiriam if (h_errno == TRY_AGAIN) 164763993Seric statmsg = errstring(h_errno+E_DNSBASE); 164821061Seric else 164936788Sbostic #endif 165021061Seric { 165125527Smiriam if (errno != 0) 165225527Smiriam statmsg = errstring(errno); 165325527Smiriam else 165425527Smiriam { 165521061Seric #ifdef SMTP 165625527Smiriam statmsg = SmtpError; 165756795Seric #else /* SMTP */ 165825527Smiriam statmsg = NULL; 165956795Seric #endif /* SMTP */ 166025527Smiriam } 166121061Seric } 166221061Seric if (statmsg != NULL && statmsg[0] != '\0') 166321061Seric { 166410124Seric (void) strcat(buf, ": "); 166521061Seric (void) strcat(buf, statmsg); 166610105Seric } 166710105Seric statmsg = buf; 166810105Seric } 166963753Seric #ifdef NAMED_BIND 167063753Seric else if (stat == EX_NOHOST && h_errno != 0) 167163753Seric { 167263993Seric statmsg = errstring(h_errno + E_DNSBASE); 167363753Seric (void) sprintf(buf, "%s (%s)", SysExMsg[i], statmsg); 167463753Seric statmsg = buf; 167563753Seric } 167663753Seric #endif 1677294Seric else 167821061Seric { 1679294Seric statmsg = SysExMsg[i]; 168058664Seric if (*statmsg++ == ':') 168158664Seric { 168258664Seric (void) sprintf(buf, "%s: %s", statmsg, errstring(errno)); 168358664Seric statmsg = buf; 168458664Seric } 168521061Seric } 16869370Seric 16879370Seric /* 16889370Seric ** Print the message as appropriate 16899370Seric */ 16909370Seric 169110105Seric if (stat == EX_OK || stat == EX_TEMPFAIL) 169264718Seric { 169364718Seric extern char MsgBuf[]; 169464718Seric 169558524Seric message(&statmsg[4], errstring(errno)); 169664718Seric if (stat == EX_TEMPFAIL && e->e_xfp != NULL) 169764718Seric fprintf(e->e_xfp, "%s\n", &MsgBuf[4]); 169864718Seric } 1699294Seric else 1700294Seric { 17011518Seric Errors++; 170258524Seric usrerr(statmsg, errstring(errno)); 1703294Seric } 1704294Seric 1705294Seric /* 1706294Seric ** Final cleanup. 1707294Seric ** Log a record of the transaction. Compute the new 1708294Seric ** ExitStat -- if we already had an error, stick with 1709294Seric ** that. 1710294Seric */ 1711294Seric 171258020Seric if (LogLevel > ((stat == EX_TEMPFAIL) ? 8 : (stat == EX_OK) ? 7 : 6)) 171364771Seric logdelivery(m, mci, &statmsg[4], ctladdr, e); 17147858Seric 17154621Seric if (stat != EX_TEMPFAIL) 17164621Seric setstat(stat); 171764952Seric if (stat != EX_OK && (stat != EX_TEMPFAIL || e->e_message == NULL)) 171810105Seric { 171910105Seric if (e->e_message != NULL) 172010105Seric free(e->e_message); 172110105Seric e->e_message = newstr(&statmsg[4]); 172210105Seric } 172310124Seric errno = 0; 172436788Sbostic #ifdef NAMED_BIND 172525527Smiriam h_errno = 0; 172636788Sbostic #endif 1727294Seric } 1728294Seric /* 17298496Seric ** LOGDELIVERY -- log the delivery in the system log 17308496Seric ** 173164969Seric ** Care is taken to avoid logging lines that are too long, because 173264969Seric ** some versions of syslog have an unfortunate proclivity for core 173364969Seric ** dumping. This is a hack, to be sure, that is at best empirical. 173464969Seric ** 17358496Seric ** Parameters: 173658337Seric ** m -- the mailer info. Can be NULL for initial queue. 173758337Seric ** mci -- the mailer connection info -- can be NULL if the 173858337Seric ** log is occuring when no connection is active. 173958337Seric ** stat -- the message to print for the status. 174064771Seric ** ctladdr -- the controlling address for the to list. 174158337Seric ** e -- the current envelope. 17428496Seric ** 17438496Seric ** Returns: 17448496Seric ** none 17458496Seric ** 17468496Seric ** Side Effects: 17478496Seric ** none 17488496Seric */ 17498496Seric 175064771Seric logdelivery(m, mci, stat, ctladdr, e) 175158337Seric MAILER *m; 175258337Seric register MCI *mci; 17538496Seric char *stat; 175464771Seric ADDRESS *ctladdr; 175554967Seric register ENVELOPE *e; 17568496Seric { 175758343Seric # ifdef LOG 175864771Seric register char *bp; 175964969Seric register char *p; 176064969Seric int l; 176158418Seric char buf[512]; 17628496Seric 176365059Seric # if (SYSLOG_BUFSIZE) >= 256 176464771Seric bp = buf; 176564771Seric if (ctladdr != NULL) 176664771Seric { 176764771Seric strcpy(bp, ", ctladdr="); 176865016Seric strcat(bp, shortenstring(ctladdr->q_paddr, 83)); 176964771Seric bp += strlen(bp); 177064771Seric if (bitset(QGOODUID, ctladdr->q_flags)) 177164771Seric { 177264771Seric (void) sprintf(bp, " (%d/%d)", 177364771Seric ctladdr->q_uid, ctladdr->q_gid); 177464771Seric bp += strlen(bp); 177564771Seric } 177664771Seric } 177758337Seric 177864771Seric (void) sprintf(bp, ", delay=%s", pintvl(curtime() - e->e_ctime, TRUE)); 177964771Seric bp += strlen(bp); 178064771Seric 178158513Seric if (m != NULL) 178258305Seric { 178364771Seric (void) strcpy(bp, ", mailer="); 178464771Seric (void) strcat(bp, m->m_name); 178564771Seric bp += strlen(bp); 178658305Seric } 178758513Seric 178858513Seric if (mci != NULL && mci->mci_host != NULL) 178958305Seric { 179058305Seric # ifdef DAEMON 179158755Seric extern SOCKADDR CurHostAddr; 179258513Seric # endif 179358305Seric 179464771Seric (void) strcpy(bp, ", relay="); 179564771Seric (void) strcat(bp, mci->mci_host); 179658513Seric 179758513Seric # ifdef DAEMON 1798*65919Seric (void) strcat(bp, " ["); 179964771Seric (void) strcat(bp, anynet_ntoa(&CurHostAddr)); 1800*65919Seric (void) strcat(bp, "]"); 180158305Seric # endif 180258305Seric } 180358343Seric else 180458513Seric { 180558513Seric char *p = macvalue('h', e); 180658343Seric 180758513Seric if (p != NULL && p[0] != '\0') 180858513Seric { 180964771Seric (void) strcpy(bp, ", relay="); 181064771Seric (void) strcat(bp, p); 181158513Seric } 181258513Seric } 181364922Seric bp += strlen(bp); 181464969Seric 181565059Seric #define STATLEN (((SYSLOG_BUFSIZE) - 100) / 4) 181665059Seric #if (STATLEN) < 63 181765059Seric # undef STATLEN 181865059Seric # define STATLEN 63 181965059Seric #endif 182065059Seric #if (STATLEN) > 203 182165059Seric # undef STATLEN 182265059Seric # define STATLEN 203 182365059Seric #endif 182465059Seric 182565059Seric if ((bp - buf) > (sizeof buf - ((STATLEN) + 20))) 182664969Seric { 182764969Seric /* desperation move -- truncate data */ 182865059Seric bp = buf + sizeof buf - ((STATLEN) + 17); 182964969Seric strcpy(bp, "..."); 183064969Seric bp += 3; 183164969Seric } 183264969Seric 183364969Seric (void) strcpy(bp, ", stat="); 183464969Seric bp += strlen(bp); 183565059Seric 183665059Seric (void) strcpy(bp, shortenstring(stat, (STATLEN))); 183758418Seric 183864969Seric l = SYSLOG_BUFSIZE - 100 - strlen(buf); 183964969Seric p = e->e_to; 184064969Seric while (strlen(p) >= l) 184164969Seric { 184264969Seric register char *q = strchr(p + l, ','); 184364969Seric 184465008Seric if (q == NULL) 184564969Seric break; 184664969Seric syslog(LOG_INFO, "%s: to=%.*s [more]%s", 184764969Seric e->e_id, ++q - p, p, buf); 184864969Seric p = q; 184964969Seric } 185064969Seric syslog(LOG_INFO, "%s: to=%s%s", e->e_id, p, buf); 185165059Seric 185265059Seric # else /* we have a very short log buffer size */ 185365059Seric 185465650Seric l = SYSLOG_BUFSIZE - 80; 185565059Seric p = e->e_to; 185665059Seric while (strlen(p) >= l) 185765059Seric { 185865059Seric register char *q = strchr(p + l, ','); 185965059Seric 186065059Seric if (q == NULL) 186165059Seric break; 186265059Seric syslog(LOG_INFO, "%s: to=%.*s [more]", 186365059Seric e->e_id, ++q - p, p); 186465059Seric p = q; 186565059Seric } 186665059Seric syslog(LOG_INFO, "%s: to=%s", e->e_id, p); 186765059Seric 186865059Seric if (ctladdr != NULL) 186965059Seric { 187065059Seric bp = buf; 187165059Seric strcpy(buf, "ctladdr="); 187265059Seric bp += strlen(buf); 187365059Seric strcpy(bp, shortenstring(ctladdr->q_paddr, 83)); 187465059Seric bp += strlen(buf); 187565059Seric if (bitset(QGOODUID, ctladdr->q_flags)) 187665059Seric { 187765059Seric (void) sprintf(bp, " (%d/%d)", 187865059Seric ctladdr->q_uid, ctladdr->q_gid); 187965059Seric bp += strlen(bp); 188065059Seric } 188165059Seric syslog(LOG_INFO, "%s: %s", e->e_id, buf); 188265059Seric } 188365650Seric bp = buf; 188465650Seric sprintf(bp, "delay=%s", pintvl(curtime() - e->e_ctime, TRUE)); 188565650Seric bp += strlen(bp); 188665059Seric 188765059Seric if (m != NULL) 188865650Seric { 188965650Seric sprintf(bp, ", mailer=%s", m->m_name); 189065650Seric bp += strlen(bp); 189165650Seric } 189265059Seric 189365059Seric if (mci != NULL && mci->mci_host != NULL) 189465059Seric { 189565059Seric # ifdef DAEMON 189665059Seric extern SOCKADDR CurHostAddr; 189765059Seric # endif 189865059Seric 189965650Seric sprintf(bp, ", relay=%s", mci->mci_host); 190065059Seric 190165059Seric # ifdef DAEMON 1902*65919Seric (void) strcat(bp, " ["); 190365650Seric (void) strcat(bp, anynet_ntoa(&CurHostAddr)); 1904*65919Seric (void) strcat(bp, "]"); 190565059Seric # endif 190665059Seric } 190765059Seric else 190865059Seric { 190965059Seric char *p = macvalue('h', e); 191065059Seric 191165059Seric if (p != NULL && p[0] != '\0') 191265650Seric sprintf(bp, ", relay=%s", p); 191365059Seric } 191465650Seric syslog(LOG_INFO, "%s: %s", e->e_id, buf); 191565059Seric 191665059Seric syslog(LOG_INFO, "%s: stat=%s", e->e_id, shortenstring(stat, 63)); 191765059Seric # endif /* short log buffer */ 191856795Seric # endif /* LOG */ 19198496Seric } 19208496Seric /* 19216974Seric ** PUTFROMLINE -- output a UNIX-style from line (or whatever) 1922294Seric ** 19236974Seric ** This can be made an arbitrary message separator by changing $l 1924294Seric ** 192516150Seric ** One of the ugliest hacks seen by human eyes is contained herein: 192616150Seric ** UUCP wants those stupid "remote from <host>" lines. Why oh why 192716150Seric ** does a well-meaning programmer such as myself have to deal with 192816150Seric ** this kind of antique garbage???? 19296974Seric ** 1930294Seric ** Parameters: 193165870Seric ** mci -- the connection information. 193265870Seric ** e -- the envelope. 1933294Seric ** 1934294Seric ** Returns: 19356974Seric ** none 1936294Seric ** 1937294Seric ** Side Effects: 19386974Seric ** outputs some text to fp. 1939294Seric */ 1940294Seric 194165870Seric putfromline(mci, e) 194265870Seric register MCI *mci; 194354967Seric ENVELOPE *e; 1944294Seric { 194558050Seric char *template = "\201l\n"; 19466974Seric char buf[MAXLINE]; 1947294Seric 194865870Seric if (bitnset(M_NHDR, mci->mci_mailer->m_flags)) 19496974Seric return; 19504315Seric 19516974Seric # ifdef UGLYUUCP 195265870Seric if (bitnset(M_UGLYUUCP, mci->mci_mailer->m_flags)) 19534205Seric { 195412223Seric char *bang; 195512223Seric char xbuf[MAXLINE]; 19566041Seric 195758680Seric expand("\201g", buf, &buf[sizeof buf - 1], e); 195856795Seric bang = strchr(buf, '!'); 19596974Seric if (bang == NULL) 196064370Seric { 196164370Seric errno = 0; 196264370Seric syserr("554 No ! in UUCP From address! (%s given)", buf); 196364370Seric } 19645099Seric else 19659370Seric { 196612223Seric *bang++ = '\0'; 196758050Seric (void) sprintf(xbuf, "From %s \201d remote from %s\n", bang, buf); 196812223Seric template = xbuf; 19699370Seric } 19706974Seric } 197156795Seric # endif /* UGLYUUCP */ 197254967Seric expand(template, buf, &buf[sizeof buf - 1], e); 197365870Seric putline(buf, mci); 19745981Seric } 19755981Seric /* 19766974Seric ** PUTBODY -- put the body of a message. 19776974Seric ** 19786974Seric ** Parameters: 197965870Seric ** mci -- the connection information. 19809538Seric ** e -- the envelope to put out. 198159730Seric ** separator -- if non-NULL, a message separator that must 198259730Seric ** not be permitted in the resulting message. 19836974Seric ** 19846974Seric ** Returns: 19856974Seric ** none. 19866974Seric ** 19876974Seric ** Side Effects: 19886974Seric ** The message is written onto fp. 19896974Seric */ 19906974Seric 199165870Seric putbody(mci, e, separator) 199265870Seric register MCI *mci; 19939538Seric register ENVELOPE *e; 199459730Seric char *separator; 19956974Seric { 199610168Seric char buf[MAXLINE]; 19976974Seric 19986974Seric /* 19996974Seric ** Output the body of the message 20006974Seric */ 20016974Seric 20029538Seric if (e->e_dfp == NULL) 20036974Seric { 20049538Seric if (e->e_df != NULL) 20059538Seric { 20069538Seric e->e_dfp = fopen(e->e_df, "r"); 20079538Seric if (e->e_dfp == NULL) 200840931Srick syserr("putbody: Cannot open %s for %s from %s", 200964118Seric e->e_df, e->e_to, e->e_from.q_paddr); 20109538Seric } 20119538Seric else 201265870Seric putline("<<< No Message Collected >>>", mci); 20139538Seric } 20149538Seric if (e->e_dfp != NULL) 20159538Seric { 20169538Seric rewind(e->e_dfp); 201765870Seric while (!ferror(mci->mci_out) && fgets(buf, sizeof buf, e->e_dfp) != NULL) 201816875Seric { 201965870Seric if (buf[0] == 'F' && 202065870Seric bitnset(M_ESCFROM, mci->mci_mailer->m_flags) && 202140995Sbostic strncmp(buf, "From ", 5) == 0) 202265870Seric (void) putc('>', mci->mci_out); 202359730Seric if (buf[0] == '-' && buf[1] == '-' && separator != NULL) 202459730Seric { 202559730Seric /* possible separator */ 202659730Seric int sl = strlen(separator); 202759730Seric 202859730Seric if (strncmp(&buf[2], separator, sl) == 0) 202965870Seric (void) putc(' ', mci->mci_out); 203059730Seric } 203165870Seric putline(buf, mci); 203216875Seric } 20336974Seric 20349538Seric if (ferror(e->e_dfp)) 20356974Seric { 203664718Seric syserr("putbody: %s: read error", e->e_df); 20376974Seric ExitStat = EX_IOERR; 20386974Seric } 20396974Seric } 20406974Seric 204159542Seric /* some mailers want extra blank line at end of message */ 204265870Seric if (bitnset(M_BLANKEND, mci->mci_mailer->m_flags) && 204365870Seric buf[0] != '\0' && buf[0] != '\n') 204465870Seric putline("", mci); 204559542Seric 204665870Seric (void) fflush(mci->mci_out); 204765870Seric if (ferror(mci->mci_out) && errno != EPIPE) 20486974Seric { 20496974Seric syserr("putbody: write error"); 20506974Seric ExitStat = EX_IOERR; 20516974Seric } 20526974Seric errno = 0; 20536974Seric } 20546974Seric /* 2055294Seric ** MAILFILE -- Send a message to a file. 2056294Seric ** 20574327Seric ** If the file has the setuid/setgid bits set, but NO execute 20584327Seric ** bits, sendmail will try to become the owner of that file 20594327Seric ** rather than the real user. Obviously, this only works if 20604327Seric ** sendmail runs as root. 20614327Seric ** 20629370Seric ** This could be done as a subordinate mailer, except that it 20639370Seric ** is used implicitly to save messages in ~/dead.letter. We 20649370Seric ** view this as being sufficiently important as to include it 20659370Seric ** here. For example, if the system is dying, we shouldn't have 20669370Seric ** to create another process plus some pipes to save the message. 20679370Seric ** 2068294Seric ** Parameters: 2069294Seric ** filename -- the name of the file to send to. 20704397Seric ** ctladdr -- the controlling address header -- includes 20714397Seric ** the userid/groupid to be when sending. 2072294Seric ** 2073294Seric ** Returns: 2074294Seric ** The exit code associated with the operation. 2075294Seric ** 2076294Seric ** Side Effects: 2077294Seric ** none. 2078294Seric */ 2079294Seric 208054967Seric mailfile(filename, ctladdr, e) 2081294Seric char *filename; 20824397Seric ADDRESS *ctladdr; 208354967Seric register ENVELOPE *e; 2084294Seric { 2085294Seric register FILE *f; 20864214Seric register int pid; 208753751Seric int mode; 2088294Seric 208959267Seric if (tTd(11, 1)) 209059267Seric { 209159267Seric printf("mailfile %s\n ctladdr=", filename); 209259267Seric printaddr(ctladdr, FALSE); 209359267Seric } 209459267Seric 209563753Seric if (e->e_xfp != NULL) 209663753Seric fflush(e->e_xfp); 209763753Seric 20984214Seric /* 20994214Seric ** Fork so we can change permissions here. 21004214Seric ** Note that we MUST use fork, not vfork, because of 21014214Seric ** the complications of calling subroutines, etc. 21024214Seric */ 21034067Seric 21044214Seric DOFORK(fork); 21054214Seric 21064214Seric if (pid < 0) 21074214Seric return (EX_OSERR); 21084214Seric else if (pid == 0) 21094214Seric { 21104214Seric /* child -- actually write to file */ 21114327Seric struct stat stb; 211265870Seric MCI mcibuf; 21134327Seric 211464035Seric (void) setsignal(SIGINT, SIG_DFL); 211564035Seric (void) setsignal(SIGHUP, SIG_DFL); 211664035Seric (void) setsignal(SIGTERM, SIG_DFL); 211723102Seric (void) umask(OldUmask); 211852673Seric 21194327Seric if (stat(filename, &stb) < 0) 212059745Seric stb.st_mode = FileMode; 212153751Seric mode = stb.st_mode; 212252673Seric 212352673Seric /* limit the errors to those actually caused in the child */ 212452673Seric errno = 0; 212552673Seric ExitStat = EX_OK; 212652673Seric 21274327Seric if (bitset(0111, stb.st_mode)) 21284327Seric exit(EX_CANTCREAT); 212964823Seric if (ctladdr != NULL) 213053751Seric { 213153751Seric /* ignore setuid and setgid bits */ 213253751Seric mode &= ~(S_ISGID|S_ISUID); 213353751Seric } 213453751Seric 213540931Srick /* we have to open the dfile BEFORE setuid */ 213653751Seric if (e->e_dfp == NULL && e->e_df != NULL) 213740931Srick { 213840931Srick e->e_dfp = fopen(e->e_df, "r"); 213952673Seric if (e->e_dfp == NULL) 214052673Seric { 214140931Srick syserr("mailfile: Cannot open %s for %s from %s", 214264118Seric e->e_df, e->e_to, e->e_from.q_paddr); 214340931Srick } 214440931Srick } 214540931Srick 214653751Seric if (!bitset(S_ISGID, mode) || setgid(stb.st_gid) < 0) 21474417Seric { 214864823Seric if (ctladdr == NULL || ctladdr->q_uid == 0) 214952673Seric { 215040972Sbostic (void) initgroups(DefUser, DefGid); 215152673Seric } 215252673Seric else 215352673Seric { 215453751Seric (void) initgroups(ctladdr->q_ruser ? 215553751Seric ctladdr->q_ruser : ctladdr->q_user, 215640972Sbostic ctladdr->q_gid); 215740972Sbostic } 21584417Seric } 215953751Seric if (!bitset(S_ISUID, mode) || setuid(stb.st_uid) < 0) 21604417Seric { 216164823Seric if (ctladdr == NULL || ctladdr->q_uid == 0) 21624417Seric (void) setuid(DefUid); 21634417Seric else 21644417Seric (void) setuid(ctladdr->q_uid); 21654417Seric } 216652673Seric FileName = filename; 216752673Seric LineNumber = 0; 216859745Seric f = dfopen(filename, O_WRONLY|O_CREAT|O_APPEND, FileMode); 21694214Seric if (f == NULL) 217052673Seric { 217164387Seric message("554 cannot open: %s", errstring(errno)); 21724214Seric exit(EX_CANTCREAT); 217352673Seric } 21744214Seric 217565870Seric bzero(&mcibuf, sizeof mcibuf); 217665870Seric mcibuf.mci_mailer = FileMailer; 217765870Seric mcibuf.mci_out = f; 217865870Seric if (bitnset(M_7BITS, FileMailer->m_flags)) 217965870Seric mcibuf.mci_flags |= MCIF_7BIT; 218065870Seric 218165870Seric putfromline(&mcibuf, e); 218265870Seric (*e->e_puthdr)(&mcibuf, e); 218365870Seric putline("\n", &mcibuf); 218465870Seric (*e->e_putbody)(&mcibuf, e, NULL); 218565870Seric putline("\n", &mcibuf); 218652673Seric if (ferror(f)) 218752673Seric { 218864387Seric message("451 I/O error: %s", errstring(errno)); 218952673Seric setstat(EX_IOERR); 219052673Seric } 219158680Seric (void) xfclose(f, "mailfile", filename); 21924214Seric (void) fflush(stdout); 21934417Seric 21946887Seric /* reset ISUID & ISGID bits for paranoid systems */ 21954621Seric (void) chmod(filename, (int) stb.st_mode); 219652673Seric exit(ExitStat); 21974315Seric /*NOTREACHED*/ 21984214Seric } 21994214Seric else 22004214Seric { 22014214Seric /* parent -- wait for exit status */ 22029370Seric int st; 22034214Seric 22049370Seric st = waitfor(pid); 220564379Seric if (WIFEXITED(st)) 220664379Seric return (WEXITSTATUS(st)); 220764379Seric else 220864387Seric { 220964387Seric syserr("child died on signal %d", st); 22109370Seric return (EX_UNAVAILABLE); 221164387Seric } 221240931Srick /*NOTREACHED*/ 22134214Seric } 2214294Seric } 22154550Seric /* 221657454Seric ** HOSTSIGNATURE -- return the "signature" for a host. 221757454Seric ** 221857454Seric ** The signature describes how we are going to send this -- it 221957454Seric ** can be just the hostname (for non-Internet hosts) or can be 222057454Seric ** an ordered list of MX hosts. 222157454Seric ** 222257454Seric ** Parameters: 222357454Seric ** m -- the mailer describing this host. 222457454Seric ** host -- the host name. 222557454Seric ** e -- the current envelope. 222657454Seric ** 222757454Seric ** Returns: 222857454Seric ** The signature for this host. 222957454Seric ** 223057454Seric ** Side Effects: 223157454Seric ** Can tweak the symbol table. 223257454Seric */ 223357454Seric 223457454Seric char * 223557454Seric hostsignature(m, host, e) 223657454Seric register MAILER *m; 223757454Seric char *host; 223857454Seric ENVELOPE *e; 223957454Seric { 224057454Seric register char *p; 224157454Seric register STAB *s; 224257454Seric int i; 224357454Seric int len; 224457454Seric #ifdef NAMED_BIND 224557454Seric int nmx; 224657454Seric auto int rcode; 224759076Seric char *hp; 224859076Seric char *endp; 224959111Seric int oldoptions; 225057454Seric char *mxhosts[MAXMXHOSTS + 1]; 225157454Seric #endif 225257454Seric 225357454Seric /* 225457454Seric ** Check to see if this uses IPC -- if not, it can't have MX records. 225557454Seric */ 225657454Seric 225757454Seric p = m->m_mailer; 225857454Seric if (strcmp(p, "[IPC]") != 0 && strcmp(p, "[TCP]") != 0) 225957454Seric { 226057454Seric /* just an ordinary mailer */ 226157454Seric return host; 226257454Seric } 226357454Seric 226457454Seric /* 226557454Seric ** Look it up in the symbol table. 226657454Seric */ 226757454Seric 226857454Seric s = stab(host, ST_HOSTSIG, ST_ENTER); 226957454Seric if (s->s_hostsig != NULL) 227057454Seric return s->s_hostsig; 227157454Seric 227257454Seric /* 227357454Seric ** Not already there -- create a signature. 227457454Seric */ 227557454Seric 227657454Seric #ifdef NAMED_BIND 227759111Seric if (ConfigLevel < 2) 227859111Seric { 227959111Seric oldoptions = _res.options; 228059111Seric _res.options &= ~(RES_DEFNAMES | RES_DNSRCH); /* XXX */ 228159111Seric } 228259111Seric 228359076Seric for (hp = host; hp != NULL; hp = endp) 228457454Seric { 228559076Seric endp = strchr(hp, ':'); 228659076Seric if (endp != NULL) 228759076Seric *endp = '\0'; 228857454Seric 228959273Seric nmx = getmxrr(hp, mxhosts, TRUE, &rcode); 229057454Seric 229159076Seric if (nmx <= 0) 229259076Seric { 229359076Seric register MCI *mci; 229457454Seric 229559076Seric /* update the connection info for this host */ 229659076Seric mci = mci_get(hp, m); 229759076Seric mci->mci_exitstat = rcode; 229859076Seric mci->mci_errno = errno; 229963753Seric #ifdef NAMED_BIND 230063753Seric mci->mci_herrno = h_errno; 230163753Seric #endif 230259076Seric 230359076Seric /* and return the original host name as the signature */ 230459076Seric nmx = 1; 230559076Seric mxhosts[0] = hp; 230659076Seric } 230759076Seric 230859076Seric len = 0; 230959076Seric for (i = 0; i < nmx; i++) 231059076Seric { 231159076Seric len += strlen(mxhosts[i]) + 1; 231259076Seric } 231359076Seric if (s->s_hostsig != NULL) 231459076Seric len += strlen(s->s_hostsig) + 1; 231559076Seric p = xalloc(len); 231659076Seric if (s->s_hostsig != NULL) 231759076Seric { 231859076Seric (void) strcpy(p, s->s_hostsig); 231959076Seric free(s->s_hostsig); 232059076Seric s->s_hostsig = p; 232159076Seric p += strlen(p); 232257454Seric *p++ = ':'; 232359076Seric } 232459076Seric else 232559076Seric s->s_hostsig = p; 232659076Seric for (i = 0; i < nmx; i++) 232759076Seric { 232859076Seric if (i != 0) 232959076Seric *p++ = ':'; 233059076Seric strcpy(p, mxhosts[i]); 233159076Seric p += strlen(p); 233259076Seric } 233359076Seric if (endp != NULL) 233459076Seric *endp++ = ':'; 233557454Seric } 233657454Seric makelower(s->s_hostsig); 233759111Seric if (ConfigLevel < 2) 233859111Seric _res.options = oldoptions; 233957454Seric #else 234057454Seric /* not using BIND -- the signature is just the host name */ 234157454Seric s->s_hostsig = host; 234257454Seric #endif 234357454Seric if (tTd(17, 1)) 234457454Seric printf("hostsignature(%s) = %s\n", host, s->s_hostsig); 234557454Seric return s->s_hostsig; 234657454Seric } 2347