1c2aa98e2SPeter Wemm /* 2602a2b1bSGregory Neil Shapiro * Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers. 306f25ae9SGregory Neil Shapiro * All rights reserved. 4c2aa98e2SPeter Wemm * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 5c2aa98e2SPeter Wemm * Copyright (c) 1988, 1993 6c2aa98e2SPeter Wemm * The Regents of the University of California. All rights reserved. 7c2aa98e2SPeter Wemm * 8c2aa98e2SPeter Wemm * By using this file, you agree to the terms and conditions set 9c2aa98e2SPeter Wemm * forth in the LICENSE file which can be found at the top level of 10c2aa98e2SPeter Wemm * the sendmail distribution. 11c2aa98e2SPeter Wemm * 12c2aa98e2SPeter Wemm */ 13c2aa98e2SPeter Wemm 1440266059SGregory Neil Shapiro #define _DEFINE 1540266059SGregory Neil Shapiro #include <sendmail.h> 1640266059SGregory Neil Shapiro #include <sm/xtrap.h> 1740266059SGregory Neil Shapiro #include <sm/signal.h> 1840266059SGregory Neil Shapiro 19c2aa98e2SPeter Wemm #ifndef lint 2040266059SGregory Neil Shapiro SM_UNUSED(static char copyright[]) = 21602a2b1bSGregory Neil Shapiro "@(#) Copyright (c) 1998-2001 Sendmail, Inc. and its suppliers.\n\ 2206f25ae9SGregory Neil Shapiro All rights reserved.\n\ 23c2aa98e2SPeter Wemm Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.\n\ 24c2aa98e2SPeter Wemm Copyright (c) 1988, 1993\n\ 25c2aa98e2SPeter Wemm The Regents of the University of California. All rights reserved.\n"; 2606f25ae9SGregory Neil Shapiro #endif /* ! lint */ 27c2aa98e2SPeter Wemm 2840266059SGregory Neil Shapiro SM_RCSID("@(#)$Id: main.c,v 8.868 2001/12/29 04:54:38 ca Exp $") 2906f25ae9SGregory Neil Shapiro 3006f25ae9SGregory Neil Shapiro 3106f25ae9SGregory Neil Shapiro #if NETINET || NETINET6 32c2aa98e2SPeter Wemm # include <arpa/inet.h> 3306f25ae9SGregory Neil Shapiro #endif /* NETINET || NETINET6 */ 3406f25ae9SGregory Neil Shapiro 3540266059SGregory Neil Shapiro /* for getcfname() */ 3640266059SGregory Neil Shapiro #include <sendmail/pathnames.h> 3740266059SGregory Neil Shapiro 3840266059SGregory Neil Shapiro static SM_DEBUG_T 3940266059SGregory Neil Shapiro DebugNoPRestart = SM_DEBUG_INITIALIZER("no_persistent_restart", 4040266059SGregory Neil Shapiro "@(#)$Debug: no_persistent_restart - don't restart, log only $"); 4140266059SGregory Neil Shapiro 4206f25ae9SGregory Neil Shapiro static void dump_class __P((STAB *, int)); 4306f25ae9SGregory Neil Shapiro static void obsolete __P((char **)); 4406f25ae9SGregory Neil Shapiro static void testmodeline __P((char *, ENVELOPE *)); 4540266059SGregory Neil Shapiro static char *getextenv __P((const char *)); 4640266059SGregory Neil Shapiro static void sm_printoptions __P((char **)); 4740266059SGregory Neil Shapiro static SIGFUNC_DECL intindebug __P((int)); 4840266059SGregory Neil Shapiro static SIGFUNC_DECL sighup __P((int)); 4940266059SGregory Neil Shapiro static SIGFUNC_DECL sigpipe __P((int)); 5040266059SGregory Neil Shapiro static SIGFUNC_DECL sigterm __P((int)); 5140266059SGregory Neil Shapiro #ifdef SIGUSR1 5240266059SGregory Neil Shapiro static SIGFUNC_DECL sigusr1 __P((int)); 5340266059SGregory Neil Shapiro #endif /* SIGUSR1 */ 54c2aa98e2SPeter Wemm 55c2aa98e2SPeter Wemm /* 56c2aa98e2SPeter Wemm ** SENDMAIL -- Post mail to a set of destinations. 57c2aa98e2SPeter Wemm ** 58c2aa98e2SPeter Wemm ** This is the basic mail router. All user mail programs should 59c2aa98e2SPeter Wemm ** call this routine to actually deliver mail. Sendmail in 60c2aa98e2SPeter Wemm ** turn calls a bunch of mail servers that do the real work of 61c2aa98e2SPeter Wemm ** delivering the mail. 62c2aa98e2SPeter Wemm ** 6306f25ae9SGregory Neil Shapiro ** Sendmail is driven by settings read in from /etc/mail/sendmail.cf 64c2aa98e2SPeter Wemm ** (read by readcf.c). 65c2aa98e2SPeter Wemm ** 66c2aa98e2SPeter Wemm ** Usage: 67c2aa98e2SPeter Wemm ** /usr/lib/sendmail [flags] addr ... 68c2aa98e2SPeter Wemm ** 69c2aa98e2SPeter Wemm ** See the associated documentation for details. 70c2aa98e2SPeter Wemm ** 7140266059SGregory Neil Shapiro ** Authors: 72c2aa98e2SPeter Wemm ** Eric Allman, UCB/INGRES (until 10/81). 73c2aa98e2SPeter Wemm ** Britton-Lee, Inc., purveyors of fine 74c2aa98e2SPeter Wemm ** database computers (11/81 - 10/88). 75c2aa98e2SPeter Wemm ** International Computer Science Institute 76c2aa98e2SPeter Wemm ** (11/88 - 9/89). 77c2aa98e2SPeter Wemm ** UCB/Mammoth Project (10/89 - 7/95). 78c2aa98e2SPeter Wemm ** InReference, Inc. (8/95 - 1/97). 79c2aa98e2SPeter Wemm ** Sendmail, Inc. (1/98 - present). 80c2aa98e2SPeter Wemm ** The support of the my employers is gratefully acknowledged. 81c2aa98e2SPeter Wemm ** Few of them (Britton-Lee in particular) have had 82c2aa98e2SPeter Wemm ** anything to gain from my involvement in this project. 8340266059SGregory Neil Shapiro ** 8440266059SGregory Neil Shapiro ** Gregory Neil Shapiro, 8540266059SGregory Neil Shapiro ** Worcester Polytechnic Institute (until 3/98). 8640266059SGregory Neil Shapiro ** Sendmail, Inc. (3/98 - present). 8740266059SGregory Neil Shapiro ** 8840266059SGregory Neil Shapiro ** Claus Assmann, 8940266059SGregory Neil Shapiro ** Sendmail, Inc. (12/98 - present). 90c2aa98e2SPeter Wemm */ 91c2aa98e2SPeter Wemm 92c2aa98e2SPeter Wemm char *FullName; /* sender's full name */ 93c2aa98e2SPeter Wemm ENVELOPE BlankEnvelope; /* a "blank" envelope */ 9406f25ae9SGregory Neil Shapiro static ENVELOPE MainEnvelope; /* the envelope around the basic letter */ 95c2aa98e2SPeter Wemm ADDRESS NullAddress = /* a null address */ 96c2aa98e2SPeter Wemm { "", "", NULL, "" }; 97c2aa98e2SPeter Wemm char *CommandLineArgs; /* command line args for pid file */ 9840266059SGregory Neil Shapiro bool Warn_Q_option = false; /* warn about Q option use */ 9906f25ae9SGregory Neil Shapiro static int MissingFds = 0; /* bit map of fds missing on startup */ 10040266059SGregory Neil Shapiro char *Mbdb = "pw"; /* mailbox database defaults to /etc/passwd */ 101c2aa98e2SPeter Wemm 102c2aa98e2SPeter Wemm #ifdef NGROUPS_MAX 103c2aa98e2SPeter Wemm GIDSET_T InitialGidSet[NGROUPS_MAX]; 10406f25ae9SGregory Neil Shapiro #endif /* NGROUPS_MAX */ 105c2aa98e2SPeter Wemm 10640266059SGregory Neil Shapiro #define MAXCONFIGLEVEL 10 /* highest config version level known */ 10706f25ae9SGregory Neil Shapiro 10806f25ae9SGregory Neil Shapiro #if SASL 10906f25ae9SGregory Neil Shapiro static sasl_callback_t srvcallbacks[] = 11006f25ae9SGregory Neil Shapiro { 11106f25ae9SGregory Neil Shapiro { SASL_CB_VERIFYFILE, &safesaslfile, NULL }, 11206f25ae9SGregory Neil Shapiro { SASL_CB_PROXY_POLICY, &proxy_policy, NULL }, 11306f25ae9SGregory Neil Shapiro { SASL_CB_LIST_END, NULL, NULL } 11406f25ae9SGregory Neil Shapiro }; 11506f25ae9SGregory Neil Shapiro #endif /* SASL */ 11606f25ae9SGregory Neil Shapiro 11740266059SGregory Neil Shapiro unsigned int SubmitMode; 11840266059SGregory Neil Shapiro int SyslogPrefixLen; /* estimated length of syslog prefix */ 11940266059SGregory Neil Shapiro #define PIDLEN 6 /* pid length for computing SyslogPrefixLen */ 12040266059SGregory Neil Shapiro #ifndef SL_FUDGE 12140266059SGregory Neil Shapiro # define SL_FUDGE 10 /* fudge offset for SyslogPrefixLen */ 12240266059SGregory Neil Shapiro #endif /* ! SL_FUDGE */ 12340266059SGregory Neil Shapiro #define SLDLL 8 /* est. length of default syslog label */ 12440266059SGregory Neil Shapiro 12540266059SGregory Neil Shapiro 12640266059SGregory Neil Shapiro /* Some options are dangerous to allow users to use in non-submit mode */ 12740266059SGregory Neil Shapiro #define CHECK_AGAINST_OPMODE(cmd) \ 12840266059SGregory Neil Shapiro { \ 12940266059SGregory Neil Shapiro if (extraprivs && \ 13040266059SGregory Neil Shapiro OpMode != MD_DELIVER && OpMode != MD_SMTP && \ 13140266059SGregory Neil Shapiro OpMode != MD_VERIFY && OpMode != MD_TEST) \ 13240266059SGregory Neil Shapiro { \ 13340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, \ 13440266059SGregory Neil Shapiro "WARNING: Ignoring submission mode -%c option (not in submission mode)\n", \ 13540266059SGregory Neil Shapiro (cmd)); \ 13640266059SGregory Neil Shapiro break; \ 13740266059SGregory Neil Shapiro } \ 13840266059SGregory Neil Shapiro if (extraprivs && queuerun) \ 13940266059SGregory Neil Shapiro { \ 14040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, \ 14140266059SGregory Neil Shapiro "WARNING: Ignoring submission mode -%c option with -q\n", \ 14240266059SGregory Neil Shapiro (cmd)); \ 14340266059SGregory Neil Shapiro break; \ 14440266059SGregory Neil Shapiro } \ 14540266059SGregory Neil Shapiro } 146c2aa98e2SPeter Wemm 147c2aa98e2SPeter Wemm int 148c2aa98e2SPeter Wemm main(argc, argv, envp) 149c2aa98e2SPeter Wemm int argc; 150c2aa98e2SPeter Wemm char **argv; 151c2aa98e2SPeter Wemm char **envp; 152c2aa98e2SPeter Wemm { 153c2aa98e2SPeter Wemm register char *p; 154c2aa98e2SPeter Wemm char **av; 155c2aa98e2SPeter Wemm extern char Version[]; 156c2aa98e2SPeter Wemm char *ep, *from; 157c2aa98e2SPeter Wemm STAB *st; 158c2aa98e2SPeter Wemm register int i; 159c2aa98e2SPeter Wemm int j; 16006f25ae9SGregory Neil Shapiro int dp; 16140266059SGregory Neil Shapiro int fill_errno; 16240266059SGregory Neil Shapiro int qgrp = NOQGRP; /* queue group to process */ 16340266059SGregory Neil Shapiro bool safecf = true; 16406f25ae9SGregory Neil Shapiro BITMAP256 *p_flags = NULL; /* daemon flags */ 16540266059SGregory Neil Shapiro bool warn_C_flag = false; 16640266059SGregory Neil Shapiro bool auth = true; /* whether to set e_auth_param */ 167c2aa98e2SPeter Wemm char warn_f_flag = '\0'; 16840266059SGregory Neil Shapiro bool run_in_foreground = false; /* -bD mode */ 16940266059SGregory Neil Shapiro bool queuerun = false, debug = false; 170c2aa98e2SPeter Wemm struct passwd *pw; 171c2aa98e2SPeter Wemm struct hostent *hp; 172c2aa98e2SPeter Wemm char *nullserver = NULL; 17306f25ae9SGregory Neil Shapiro char *authinfo = NULL; 17406f25ae9SGregory Neil Shapiro char *sysloglabel = NULL; /* label for syslog */ 17540266059SGregory Neil Shapiro char *conffile = NULL; /* name of .cf file */ 17640266059SGregory Neil Shapiro char *queuegroup = NULL; /* queue group to process */ 17740266059SGregory Neil Shapiro #if _FFR_QUARANTINE 17840266059SGregory Neil Shapiro char *quarantining = NULL; /* quarantine queue items? */ 17940266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */ 18040266059SGregory Neil Shapiro bool extraprivs; 18140266059SGregory Neil Shapiro bool forged, negate; 18240266059SGregory Neil Shapiro bool queuepersistent = false; /* queue runner process runs forever */ 18340266059SGregory Neil Shapiro bool foregroundqueue = false; /* queue run in foreground */ 18440266059SGregory Neil Shapiro bool save_val; /* to save some bool var. */ 18540266059SGregory Neil Shapiro int cftype; /* which cf file to use? */ 18640266059SGregory Neil Shapiro static time_t starttime = 0; /* when was process started */ 18706f25ae9SGregory Neil Shapiro struct stat traf_st; /* for TrafficLog FIFO check */ 18840266059SGregory Neil Shapiro char buf[MAXLINE]; 189c2aa98e2SPeter Wemm char jbuf[MAXHOSTNAMELEN]; /* holds MyHostName */ 190c2aa98e2SPeter Wemm static char rnamebuf[MAXNAME]; /* holds RealUserName */ 191c2aa98e2SPeter Wemm char *emptyenviron[1]; 19242e5d165SGregory Neil Shapiro #if STARTTLS 19342e5d165SGregory Neil Shapiro bool tls_ok; 19442e5d165SGregory Neil Shapiro #endif /* STARTTLS */ 195c2aa98e2SPeter Wemm QUEUE_CHAR *new; 19640266059SGregory Neil Shapiro ENVELOPE *e; 197c2aa98e2SPeter Wemm extern int DtableSize; 198c2aa98e2SPeter Wemm extern int optind; 199c2aa98e2SPeter Wemm extern int opterr; 200c2aa98e2SPeter Wemm extern char *optarg; 201c2aa98e2SPeter Wemm extern char **environ; 20240266059SGregory Neil Shapiro #if SASL 20340266059SGregory Neil Shapiro extern void sm_sasl_init __P((void)); 20440266059SGregory Neil Shapiro #endif /* SASL */ 20540266059SGregory Neil Shapiro 20640266059SGregory Neil Shapiro #if USE_ENVIRON 20740266059SGregory Neil Shapiro envp = environ; 20840266059SGregory Neil Shapiro #endif /* USE_ENVIRON */ 20940266059SGregory Neil Shapiro 21040266059SGregory Neil Shapiro /* turn off profiling */ 21140266059SGregory Neil Shapiro SM_PROF(0); 21240266059SGregory Neil Shapiro 21340266059SGregory Neil Shapiro /* install default exception handler */ 21440266059SGregory Neil Shapiro sm_exc_newthread(fatal_error); 215c2aa98e2SPeter Wemm 216c2aa98e2SPeter Wemm /* 217c2aa98e2SPeter Wemm ** Check to see if we reentered. 218c2aa98e2SPeter Wemm ** This would normally happen if e_putheader or e_putbody 219c2aa98e2SPeter Wemm ** were NULL when invoked. 220c2aa98e2SPeter Wemm */ 221c2aa98e2SPeter Wemm 22240266059SGregory Neil Shapiro if (starttime != 0) 223c2aa98e2SPeter Wemm { 224c2aa98e2SPeter Wemm syserr("main: reentered!"); 225c2aa98e2SPeter Wemm abort(); 226c2aa98e2SPeter Wemm } 22740266059SGregory Neil Shapiro starttime = curtime(); 228c2aa98e2SPeter Wemm 229c2aa98e2SPeter Wemm /* avoid null pointer dereferences */ 230c2aa98e2SPeter Wemm TermEscape.te_rv_on = TermEscape.te_rv_off = ""; 231c2aa98e2SPeter Wemm 23240266059SGregory Neil Shapiro RealUid = getuid(); 23340266059SGregory Neil Shapiro RealGid = getgid(); 23440266059SGregory Neil Shapiro 23540266059SGregory Neil Shapiro /* Check if sendmail is running with extra privs */ 23640266059SGregory Neil Shapiro extraprivs = (RealUid != 0 && 23740266059SGregory Neil Shapiro (geteuid() != getuid() || getegid() != getgid())); 23840266059SGregory Neil Shapiro 23940266059SGregory Neil Shapiro CurrentPid = getpid(); 24040266059SGregory Neil Shapiro 24140266059SGregory Neil Shapiro /* get whatever .cf file is right for the opmode */ 24240266059SGregory Neil Shapiro cftype = SM_GET_RIGHT_CF; 24340266059SGregory Neil Shapiro 24440266059SGregory Neil Shapiro /* in 4.4BSD, the table can be huge; impose a reasonable limit */ 24540266059SGregory Neil Shapiro DtableSize = getdtsize(); 24640266059SGregory Neil Shapiro if (DtableSize > 256) 24740266059SGregory Neil Shapiro DtableSize = 256; 24840266059SGregory Neil Shapiro 24940266059SGregory Neil Shapiro /* 25040266059SGregory Neil Shapiro ** Be sure we have enough file descriptors. 25140266059SGregory Neil Shapiro ** But also be sure that 0, 1, & 2 are open. 25240266059SGregory Neil Shapiro */ 25340266059SGregory Neil Shapiro 25440266059SGregory Neil Shapiro /* reset errno and fill_errno; the latter is used way down below */ 25540266059SGregory Neil Shapiro errno = fill_errno = 0; 25640266059SGregory Neil Shapiro fill_fd(STDIN_FILENO, NULL); 25740266059SGregory Neil Shapiro if (errno != 0) 25840266059SGregory Neil Shapiro fill_errno = errno; 25940266059SGregory Neil Shapiro fill_fd(STDOUT_FILENO, NULL); 26040266059SGregory Neil Shapiro if (errno != 0) 26140266059SGregory Neil Shapiro fill_errno = errno; 26240266059SGregory Neil Shapiro fill_fd(STDERR_FILENO, NULL); 26340266059SGregory Neil Shapiro if (errno != 0) 26440266059SGregory Neil Shapiro fill_errno = errno; 26540266059SGregory Neil Shapiro 26640266059SGregory Neil Shapiro i = DtableSize; 26740266059SGregory Neil Shapiro while (--i > 0) 26840266059SGregory Neil Shapiro { 26940266059SGregory Neil Shapiro if (i != STDIN_FILENO && i != STDOUT_FILENO && 27040266059SGregory Neil Shapiro i != STDERR_FILENO) 27140266059SGregory Neil Shapiro (void) close(i); 27240266059SGregory Neil Shapiro } 27340266059SGregory Neil Shapiro errno = 0; 27440266059SGregory Neil Shapiro 27540266059SGregory Neil Shapiro #if LOG 27640266059SGregory Neil Shapiro # ifndef SM_LOG_STR 27740266059SGregory Neil Shapiro # define SM_LOG_STR "sendmail" 27840266059SGregory Neil Shapiro # endif /* ! SM_LOG_STR */ 27940266059SGregory Neil Shapiro # ifdef LOG_MAIL 28040266059SGregory Neil Shapiro openlog(SM_LOG_STR, LOG_PID, LOG_MAIL); 28140266059SGregory Neil Shapiro # else /* LOG_MAIL */ 28240266059SGregory Neil Shapiro openlog(SM_LOG_STR, LOG_PID); 28340266059SGregory Neil Shapiro # endif /* LOG_MAIL */ 28440266059SGregory Neil Shapiro #endif /* LOG */ 28540266059SGregory Neil Shapiro 2868774250cSGregory Neil Shapiro /* 2878774250cSGregory Neil Shapiro ** Seed the random number generator. 2888774250cSGregory Neil Shapiro ** Used for queue file names, picking a queue directory, and 2898774250cSGregory Neil Shapiro ** MX randomization. 2908774250cSGregory Neil Shapiro */ 2918774250cSGregory Neil Shapiro 2928774250cSGregory Neil Shapiro seed_random(); 2938774250cSGregory Neil Shapiro 294c2aa98e2SPeter Wemm /* do machine-dependent initializations */ 295c2aa98e2SPeter Wemm init_md(argc, argv); 296c2aa98e2SPeter Wemm 29706f25ae9SGregory Neil Shapiro 29840266059SGregory Neil Shapiro SyslogPrefixLen = PIDLEN + (MAXQFNAME - 3) + SL_FUDGE + SLDLL; 299c2aa98e2SPeter Wemm 300c2aa98e2SPeter Wemm /* reset status from syserr() calls for missing file descriptors */ 301c2aa98e2SPeter Wemm Errors = 0; 302c2aa98e2SPeter Wemm ExitStat = EX_OK; 303c2aa98e2SPeter Wemm 30406f25ae9SGregory Neil Shapiro SubmitMode = SUBMIT_UNKNOWN; 305c2aa98e2SPeter Wemm #if XDEBUG 306c2aa98e2SPeter Wemm checkfd012("after openlog"); 30706f25ae9SGregory Neil Shapiro #endif /* XDEBUG */ 30806f25ae9SGregory Neil Shapiro 30940266059SGregory Neil Shapiro tTsetup(tTdvect, sizeof tTdvect, "0-99.1,*_trace_*.1"); 310c2aa98e2SPeter Wemm 311c2aa98e2SPeter Wemm #ifdef NGROUPS_MAX 312c2aa98e2SPeter Wemm /* save initial group set for future checks */ 313c2aa98e2SPeter Wemm i = getgroups(NGROUPS_MAX, InitialGidSet); 31440266059SGregory Neil Shapiro if (i <= 0) 31540266059SGregory Neil Shapiro { 316c2aa98e2SPeter Wemm InitialGidSet[0] = (GID_T) -1; 31740266059SGregory Neil Shapiro i = 0; 31840266059SGregory Neil Shapiro } 319c2aa98e2SPeter Wemm while (i < NGROUPS_MAX) 320c2aa98e2SPeter Wemm InitialGidSet[i++] = InitialGidSet[0]; 32106f25ae9SGregory Neil Shapiro #endif /* NGROUPS_MAX */ 322c2aa98e2SPeter Wemm 323c2aa98e2SPeter Wemm /* drop group id privileges (RunAsUser not yet set) */ 32440266059SGregory Neil Shapiro dp = drop_privileges(false); 32506f25ae9SGregory Neil Shapiro setstat(dp); 326c2aa98e2SPeter Wemm 327c2aa98e2SPeter Wemm #ifdef SIGUSR1 3288774250cSGregory Neil Shapiro /* Only allow root (or non-set-*-ID binaries) to use SIGUSR1 */ 32940266059SGregory Neil Shapiro if (extraprivs) 3308774250cSGregory Neil Shapiro { 331c2aa98e2SPeter Wemm /* arrange to dump state on user-1 signal */ 33240266059SGregory Neil Shapiro (void) sm_signal(SIGUSR1, sigusr1); 3338774250cSGregory Neil Shapiro } 33406f25ae9SGregory Neil Shapiro #endif /* SIGUSR1 */ 335c2aa98e2SPeter Wemm 336c2aa98e2SPeter Wemm /* initialize for setproctitle */ 337c2aa98e2SPeter Wemm initsetproctitle(argc, argv, envp); 338c2aa98e2SPeter Wemm 339c2aa98e2SPeter Wemm /* Handle any non-getoptable constructions. */ 340c2aa98e2SPeter Wemm obsolete(argv); 341c2aa98e2SPeter Wemm 342c2aa98e2SPeter Wemm /* 343c2aa98e2SPeter Wemm ** Do a quick prescan of the argument list. 344c2aa98e2SPeter Wemm */ 345c2aa98e2SPeter Wemm 34606f25ae9SGregory Neil Shapiro 34740266059SGregory Neil Shapiro /* find initial opMode */ 34840266059SGregory Neil Shapiro OpMode = MD_DELIVER; 34940266059SGregory Neil Shapiro av = argv; 35040266059SGregory Neil Shapiro p = strrchr(*av, '/'); 35140266059SGregory Neil Shapiro if (p++ == NULL) 35240266059SGregory Neil Shapiro p = *av; 35340266059SGregory Neil Shapiro if (strcmp(p, "newaliases") == 0) 35440266059SGregory Neil Shapiro OpMode = MD_INITALIAS; 35540266059SGregory Neil Shapiro else if (strcmp(p, "mailq") == 0) 35640266059SGregory Neil Shapiro OpMode = MD_PRINT; 35740266059SGregory Neil Shapiro else if (strcmp(p, "smtpd") == 0) 35840266059SGregory Neil Shapiro OpMode = MD_DAEMON; 35940266059SGregory Neil Shapiro else if (strcmp(p, "hoststat") == 0) 36040266059SGregory Neil Shapiro OpMode = MD_HOSTSTAT; 36140266059SGregory Neil Shapiro else if (strcmp(p, "purgestat") == 0) 36240266059SGregory Neil Shapiro OpMode = MD_PURGESTAT; 36340266059SGregory Neil Shapiro 36440266059SGregory Neil Shapiro #if _FFR_QUARANTINE 365c2aa98e2SPeter Wemm # if defined(__osf__) || defined(_AIX3) 36640266059SGregory Neil Shapiro # define OPTIONS "A:B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtV:vX:xQ:" 36706f25ae9SGregory Neil Shapiro # endif /* defined(__osf__) || defined(_AIX3) */ 368c2aa98e2SPeter Wemm # if defined(sony_news) 36940266059SGregory Neil Shapiro # define OPTIONS "A:B:b:C:cd:E:e:F:f:Gh:IiJ:L:M:mN:nO:o:p:q:R:r:sTtV:vX:Q:" 37006f25ae9SGregory Neil Shapiro # endif /* defined(sony_news) */ 371c2aa98e2SPeter Wemm # ifndef OPTIONS 37240266059SGregory Neil Shapiro # define OPTIONS "A:B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtV:vX:Q:" 37306f25ae9SGregory Neil Shapiro # endif /* ! OPTIONS */ 37440266059SGregory Neil Shapiro #else /* _FFR_QUARANTINE */ 37540266059SGregory Neil Shapiro # if defined(__osf__) || defined(_AIX3) 37640266059SGregory Neil Shapiro # define OPTIONS "A:B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtV:vX:x" 37740266059SGregory Neil Shapiro # endif /* defined(__osf__) || defined(_AIX3) */ 37840266059SGregory Neil Shapiro # if defined(sony_news) 37940266059SGregory Neil Shapiro # define OPTIONS "A:B:b:C:cd:E:e:F:f:Gh:IiJ:L:M:mN:nO:o:p:q:R:r:sTtV:vX:" 38040266059SGregory Neil Shapiro # endif /* defined(sony_news) */ 38140266059SGregory Neil Shapiro # ifndef OPTIONS 38240266059SGregory Neil Shapiro # define OPTIONS "A:B:b:C:cd:e:F:f:Gh:IiL:M:mN:nO:o:p:q:R:r:sTtV:vX:" 38340266059SGregory Neil Shapiro # endif /* ! OPTIONS */ 38440266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */ 38540266059SGregory Neil Shapiro 386c2aa98e2SPeter Wemm opterr = 0; 387c2aa98e2SPeter Wemm while ((j = getopt(argc, argv, OPTIONS)) != -1) 388c2aa98e2SPeter Wemm { 389c2aa98e2SPeter Wemm switch (j) 390c2aa98e2SPeter Wemm { 39140266059SGregory Neil Shapiro case 'b': /* operations mode */ 39240266059SGregory Neil Shapiro switch (j = *optarg) 393c2aa98e2SPeter Wemm { 39440266059SGregory Neil Shapiro case MD_DAEMON: 39540266059SGregory Neil Shapiro case MD_FGDAEMON: 39640266059SGregory Neil Shapiro case MD_SMTP: 39740266059SGregory Neil Shapiro case MD_INITALIAS: 39840266059SGregory Neil Shapiro case MD_DELIVER: 39940266059SGregory Neil Shapiro case MD_VERIFY: 40040266059SGregory Neil Shapiro case MD_TEST: 40140266059SGregory Neil Shapiro case MD_PRINT: 40240266059SGregory Neil Shapiro case MD_PRINTNQE: 40340266059SGregory Neil Shapiro case MD_HOSTSTAT: 40440266059SGregory Neil Shapiro case MD_PURGESTAT: 40540266059SGregory Neil Shapiro case MD_ARPAFTP: 40640266059SGregory Neil Shapiro OpMode = j; 407c2aa98e2SPeter Wemm break; 40840266059SGregory Neil Shapiro 40940266059SGregory Neil Shapiro case MD_FREEZE: 41040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 41140266059SGregory Neil Shapiro "Frozen configurations unsupported\n"); 41240266059SGregory Neil Shapiro return EX_USAGE; 41340266059SGregory Neil Shapiro 41440266059SGregory Neil Shapiro default: 41540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 41640266059SGregory Neil Shapiro "Invalid operation mode %c\n", 41740266059SGregory Neil Shapiro j); 41840266059SGregory Neil Shapiro return EX_USAGE; 419c2aa98e2SPeter Wemm } 42040266059SGregory Neil Shapiro break; 42140266059SGregory Neil Shapiro 42240266059SGregory Neil Shapiro case 'd': 42340266059SGregory Neil Shapiro debug = true; 424c2aa98e2SPeter Wemm tTflag(optarg); 42540266059SGregory Neil Shapiro (void) sm_io_setvbuf(smioout, SM_TIME_DEFAULT, 42640266059SGregory Neil Shapiro (char *) NULL, SM_IO_NBF, 42740266059SGregory Neil Shapiro SM_IO_BUFSIZ); 428c2aa98e2SPeter Wemm break; 42906f25ae9SGregory Neil Shapiro 43006f25ae9SGregory Neil Shapiro case 'G': /* relay (gateway) submission */ 43140266059SGregory Neil Shapiro SubmitMode = SUBMIT_MTA; 43206f25ae9SGregory Neil Shapiro break; 43306f25ae9SGregory Neil Shapiro 43406f25ae9SGregory Neil Shapiro case 'L': 43540266059SGregory Neil Shapiro j = SM_MIN(strlen(optarg), 24) + 1; 43606f25ae9SGregory Neil Shapiro sysloglabel = xalloc(j); 43740266059SGregory Neil Shapiro (void) sm_strlcpy(sysloglabel, optarg, j); 43840266059SGregory Neil Shapiro SyslogPrefixLen = PIDLEN + (MAXQFNAME - 3) + 43940266059SGregory Neil Shapiro SL_FUDGE + j; 44006f25ae9SGregory Neil Shapiro break; 44106f25ae9SGregory Neil Shapiro 44240266059SGregory Neil Shapiro #if _FFR_QUARANTINE 44340266059SGregory Neil Shapiro case 'Q': 44440266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */ 44540266059SGregory Neil Shapiro case 'q': 44640266059SGregory Neil Shapiro /* just check if it is there */ 44740266059SGregory Neil Shapiro queuerun = true; 44806f25ae9SGregory Neil Shapiro break; 449c2aa98e2SPeter Wemm } 450c2aa98e2SPeter Wemm } 451c2aa98e2SPeter Wemm opterr = 1; 452c2aa98e2SPeter Wemm 45340266059SGregory Neil Shapiro /* Don't leak queue information via debug flags */ 45440266059SGregory Neil Shapiro if (extraprivs && queuerun && debug) 45540266059SGregory Neil Shapiro { 45640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 45740266059SGregory Neil Shapiro "WARNING: Can not use -d with -q. Disabling debugging.\n"); 45840266059SGregory Neil Shapiro sm_debug_setfile(NULL); 45940266059SGregory Neil Shapiro (void) memset(tTdvect, '\0', sizeof tTdvect); 46040266059SGregory Neil Shapiro } 46140266059SGregory Neil Shapiro 4628774250cSGregory Neil Shapiro #if LOG 46306f25ae9SGregory Neil Shapiro if (sysloglabel != NULL) 46406f25ae9SGregory Neil Shapiro { 4658774250cSGregory Neil Shapiro /* Sanitize the string */ 4668774250cSGregory Neil Shapiro for (p = sysloglabel; *p != '\0'; p++) 4678774250cSGregory Neil Shapiro { 4688774250cSGregory Neil Shapiro if (!isascii(*p) || !isprint(*p) || *p == '%') 4698774250cSGregory Neil Shapiro *p = '*'; 4708774250cSGregory Neil Shapiro } 47106f25ae9SGregory Neil Shapiro closelog(); 47206f25ae9SGregory Neil Shapiro # ifdef LOG_MAIL 47306f25ae9SGregory Neil Shapiro openlog(sysloglabel, LOG_PID, LOG_MAIL); 47406f25ae9SGregory Neil Shapiro # else /* LOG_MAIL */ 47506f25ae9SGregory Neil Shapiro openlog(sysloglabel, LOG_PID); 47606f25ae9SGregory Neil Shapiro # endif /* LOG_MAIL */ 47706f25ae9SGregory Neil Shapiro } 4788774250cSGregory Neil Shapiro #endif /* LOG */ 47906f25ae9SGregory Neil Shapiro 480c2aa98e2SPeter Wemm /* set up the blank envelope */ 481c2aa98e2SPeter Wemm BlankEnvelope.e_puthdr = putheader; 482c2aa98e2SPeter Wemm BlankEnvelope.e_putbody = putbody; 483c2aa98e2SPeter Wemm BlankEnvelope.e_xfp = NULL; 484c2aa98e2SPeter Wemm STRUCTCOPY(NullAddress, BlankEnvelope.e_from); 485c2aa98e2SPeter Wemm CurEnv = &BlankEnvelope; 486c2aa98e2SPeter Wemm STRUCTCOPY(NullAddress, MainEnvelope.e_from); 487c2aa98e2SPeter Wemm 488c2aa98e2SPeter Wemm /* 489c2aa98e2SPeter Wemm ** Set default values for variables. 490c2aa98e2SPeter Wemm ** These cannot be in initialized data space. 491c2aa98e2SPeter Wemm */ 492c2aa98e2SPeter Wemm 493c2aa98e2SPeter Wemm setdefaults(&BlankEnvelope); 49440266059SGregory Neil Shapiro initmacros(&BlankEnvelope); 495c2aa98e2SPeter Wemm 49640266059SGregory Neil Shapiro /* reset macro */ 49740266059SGregory Neil Shapiro set_op_mode(OpMode); 498c2aa98e2SPeter Wemm 499c2aa98e2SPeter Wemm pw = sm_getpwuid(RealUid); 500c2aa98e2SPeter Wemm if (pw != NULL) 50140266059SGregory Neil Shapiro (void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf); 502c2aa98e2SPeter Wemm else 50340266059SGregory Neil Shapiro (void) sm_snprintf(rnamebuf, sizeof rnamebuf, "Unknown UID %d", 50406f25ae9SGregory Neil Shapiro (int) RealUid); 50506f25ae9SGregory Neil Shapiro 506c2aa98e2SPeter Wemm RealUserName = rnamebuf; 507c2aa98e2SPeter Wemm 508c2aa98e2SPeter Wemm if (tTd(0, 101)) 509c2aa98e2SPeter Wemm { 51040266059SGregory Neil Shapiro sm_dprintf("Version %s\n", Version); 51140266059SGregory Neil Shapiro finis(false, true, EX_OK); 51240266059SGregory Neil Shapiro /* NOTREACHED */ 513c2aa98e2SPeter Wemm } 514c2aa98e2SPeter Wemm 515c2aa98e2SPeter Wemm /* 51640266059SGregory Neil Shapiro ** if running non-set-user-ID binary as non-root, pretend 517c2aa98e2SPeter Wemm ** we are the RunAsUid 518c2aa98e2SPeter Wemm */ 5198774250cSGregory Neil Shapiro 520c2aa98e2SPeter Wemm if (RealUid != 0 && geteuid() == RealUid) 521c2aa98e2SPeter Wemm { 522c2aa98e2SPeter Wemm if (tTd(47, 1)) 52340266059SGregory Neil Shapiro sm_dprintf("Non-set-user-ID binary: RunAsUid = RealUid = %d\n", 524c2aa98e2SPeter Wemm (int) RealUid); 525c2aa98e2SPeter Wemm RunAsUid = RealUid; 526c2aa98e2SPeter Wemm } 527c2aa98e2SPeter Wemm else if (geteuid() != 0) 528c2aa98e2SPeter Wemm RunAsUid = geteuid(); 529c2aa98e2SPeter Wemm 53040266059SGregory Neil Shapiro EffGid = getegid(); 53140266059SGregory Neil Shapiro if (RealUid != 0 && EffGid == RealGid) 532c2aa98e2SPeter Wemm RunAsGid = RealGid; 533c2aa98e2SPeter Wemm 534c2aa98e2SPeter Wemm if (tTd(47, 5)) 535c2aa98e2SPeter Wemm { 53640266059SGregory Neil Shapiro sm_dprintf("main: e/ruid = %d/%d e/rgid = %d/%d\n", 53706f25ae9SGregory Neil Shapiro (int) geteuid(), (int) getuid(), 53806f25ae9SGregory Neil Shapiro (int) getegid(), (int) getgid()); 53940266059SGregory Neil Shapiro sm_dprintf("main: RunAsUser = %d:%d\n", 54006f25ae9SGregory Neil Shapiro (int) RunAsUid, (int) RunAsGid); 541c2aa98e2SPeter Wemm } 542c2aa98e2SPeter Wemm 543c2aa98e2SPeter Wemm /* save command line arguments */ 54406f25ae9SGregory Neil Shapiro j = 0; 545c2aa98e2SPeter Wemm for (av = argv; *av != NULL; ) 54606f25ae9SGregory Neil Shapiro j += strlen(*av++) + 1; 54740266059SGregory Neil Shapiro if (j < 0 || j > SM_ARG_MAX) 54840266059SGregory Neil Shapiro { 54940266059SGregory Neil Shapiro syserr("!Arguments too long"); 55040266059SGregory Neil Shapiro 55140266059SGregory Neil Shapiro /* NOTREACHED */ 55240266059SGregory Neil Shapiro return EX_USAGE; 55340266059SGregory Neil Shapiro } 554c2aa98e2SPeter Wemm SaveArgv = (char **) xalloc(sizeof (char *) * (argc + 1)); 55506f25ae9SGregory Neil Shapiro CommandLineArgs = xalloc(j); 556c2aa98e2SPeter Wemm p = CommandLineArgs; 557c2aa98e2SPeter Wemm for (av = argv, i = 0; *av != NULL; ) 558c2aa98e2SPeter Wemm { 55906f25ae9SGregory Neil Shapiro int h; 56006f25ae9SGregory Neil Shapiro 561c2aa98e2SPeter Wemm SaveArgv[i++] = newstr(*av); 562c2aa98e2SPeter Wemm if (av != argv) 563c2aa98e2SPeter Wemm *p++ = ' '; 56440266059SGregory Neil Shapiro (void) sm_strlcpy(p, *av++, j); 56506f25ae9SGregory Neil Shapiro h = strlen(p); 56606f25ae9SGregory Neil Shapiro p += h; 56706f25ae9SGregory Neil Shapiro j -= h + 1; 568c2aa98e2SPeter Wemm } 569c2aa98e2SPeter Wemm SaveArgv[i] = NULL; 570c2aa98e2SPeter Wemm 571c2aa98e2SPeter Wemm if (tTd(0, 1)) 572c2aa98e2SPeter Wemm { 573c2aa98e2SPeter Wemm extern char *CompileOptions[]; 574c2aa98e2SPeter Wemm 57540266059SGregory Neil Shapiro sm_dprintf("Version %s\n Compiled with:", Version); 57640266059SGregory Neil Shapiro sm_printoptions(CompileOptions); 577c2aa98e2SPeter Wemm } 578c2aa98e2SPeter Wemm if (tTd(0, 10)) 579c2aa98e2SPeter Wemm { 580c2aa98e2SPeter Wemm extern char *OsCompileOptions[]; 581c2aa98e2SPeter Wemm 58240266059SGregory Neil Shapiro sm_dprintf(" OS Defines:"); 58340266059SGregory Neil Shapiro sm_printoptions(OsCompileOptions); 584c2aa98e2SPeter Wemm #ifdef _PATH_UNIX 58540266059SGregory Neil Shapiro sm_dprintf("Kernel symbols:\t%s\n", _PATH_UNIX); 58606f25ae9SGregory Neil Shapiro #endif /* _PATH_UNIX */ 58740266059SGregory Neil Shapiro 58840266059SGregory Neil Shapiro sm_dprintf(" Conf file:\t%s (default for MSP)\n", 58940266059SGregory Neil Shapiro getcfname(OpMode, SubmitMode, SM_GET_SUBMIT_CF, 59040266059SGregory Neil Shapiro conffile)); 59140266059SGregory Neil Shapiro sm_dprintf(" Conf file:\t%s (default for MTA)\n", 59240266059SGregory Neil Shapiro getcfname(OpMode, SubmitMode, SM_GET_SENDMAIL_CF, 59340266059SGregory Neil Shapiro conffile)); 59440266059SGregory Neil Shapiro sm_dprintf(" Pid file:\t%s (default)\n", PidFile); 595c2aa98e2SPeter Wemm } 596c2aa98e2SPeter Wemm 59740266059SGregory Neil Shapiro if (tTd(0, 12)) 59840266059SGregory Neil Shapiro { 59940266059SGregory Neil Shapiro extern char *SmCompileOptions[]; 60040266059SGregory Neil Shapiro 60140266059SGregory Neil Shapiro sm_dprintf(" libsm Defines:"); 60240266059SGregory Neil Shapiro sm_printoptions(SmCompileOptions); 60340266059SGregory Neil Shapiro } 60440266059SGregory Neil Shapiro 60540266059SGregory Neil Shapiro if (tTd(0, 13)) 60640266059SGregory Neil Shapiro { 60740266059SGregory Neil Shapiro extern char *FFRCompileOptions[]; 60840266059SGregory Neil Shapiro 60940266059SGregory Neil Shapiro sm_dprintf(" FFR Defines:"); 61040266059SGregory Neil Shapiro sm_printoptions(FFRCompileOptions); 61140266059SGregory Neil Shapiro } 61240266059SGregory Neil Shapiro 61340266059SGregory Neil Shapiro InChannel = smioin; 61440266059SGregory Neil Shapiro OutChannel = smioout; 615c2aa98e2SPeter Wemm 616c2aa98e2SPeter Wemm /* clear sendmail's environment */ 617c2aa98e2SPeter Wemm ExternalEnviron = environ; 618c2aa98e2SPeter Wemm emptyenviron[0] = NULL; 619c2aa98e2SPeter Wemm environ = emptyenviron; 620c2aa98e2SPeter Wemm 621c2aa98e2SPeter Wemm /* 622c2aa98e2SPeter Wemm ** restore any original TZ setting until TimeZoneSpec has been 623c2aa98e2SPeter Wemm ** determined - or early log messages may get bogus time stamps 624c2aa98e2SPeter Wemm */ 62540266059SGregory Neil Shapiro 626c2aa98e2SPeter Wemm if ((p = getextenv("TZ")) != NULL) 627c2aa98e2SPeter Wemm { 628c2aa98e2SPeter Wemm char *tz; 629c2aa98e2SPeter Wemm int tzlen; 630c2aa98e2SPeter Wemm 63140266059SGregory Neil Shapiro /* XXX check for reasonable length? */ 632c2aa98e2SPeter Wemm tzlen = strlen(p) + 4; 633c2aa98e2SPeter Wemm tz = xalloc(tzlen); 63440266059SGregory Neil Shapiro (void) sm_strlcpyn(tz, tzlen, 2, "TZ=", p); 63540266059SGregory Neil Shapiro 63640266059SGregory Neil Shapiro /* XXX check return code? */ 63706f25ae9SGregory Neil Shapiro (void) putenv(tz); 638c2aa98e2SPeter Wemm } 639c2aa98e2SPeter Wemm 640c2aa98e2SPeter Wemm /* prime the child environment */ 641c2aa98e2SPeter Wemm setuserenv("AGENT", "sendmail"); 6428774250cSGregory Neil Shapiro 64340266059SGregory Neil Shapiro (void) sm_signal(SIGPIPE, SIG_IGN); 644c2aa98e2SPeter Wemm OldUmask = umask(022); 645c2aa98e2SPeter Wemm FullName = getextenv("NAME"); 646c2aa98e2SPeter Wemm 647c2aa98e2SPeter Wemm /* 648c2aa98e2SPeter Wemm ** Initialize name server if it is going to be used. 649c2aa98e2SPeter Wemm */ 650c2aa98e2SPeter Wemm 651c2aa98e2SPeter Wemm #if NAMED_BIND 652c2aa98e2SPeter Wemm if (!bitset(RES_INIT, _res.options)) 65306f25ae9SGregory Neil Shapiro (void) res_init(); 654c2aa98e2SPeter Wemm if (tTd(8, 8)) 655c2aa98e2SPeter Wemm _res.options |= RES_DEBUG; 656c2aa98e2SPeter Wemm else 657c2aa98e2SPeter Wemm _res.options &= ~RES_DEBUG; 658c2aa98e2SPeter Wemm # ifdef RES_NOALIASES 65940266059SGregory Neil Shapiro if (bitset(RES_NOALIASES, _res.options)) 66040266059SGregory Neil Shapiro ResNoAliases = true; 661c2aa98e2SPeter Wemm _res.options |= RES_NOALIASES; 66206f25ae9SGregory Neil Shapiro # endif /* RES_NOALIASES */ 66306f25ae9SGregory Neil Shapiro TimeOuts.res_retry[RES_TO_DEFAULT] = _res.retry; 66406f25ae9SGregory Neil Shapiro TimeOuts.res_retry[RES_TO_FIRST] = _res.retry; 66506f25ae9SGregory Neil Shapiro TimeOuts.res_retry[RES_TO_NORMAL] = _res.retry; 66606f25ae9SGregory Neil Shapiro TimeOuts.res_retrans[RES_TO_DEFAULT] = _res.retrans; 66706f25ae9SGregory Neil Shapiro TimeOuts.res_retrans[RES_TO_FIRST] = _res.retrans; 66806f25ae9SGregory Neil Shapiro TimeOuts.res_retrans[RES_TO_NORMAL] = _res.retrans; 66906f25ae9SGregory Neil Shapiro #endif /* NAMED_BIND */ 670c2aa98e2SPeter Wemm 671c2aa98e2SPeter Wemm errno = 0; 672c2aa98e2SPeter Wemm from = NULL; 673c2aa98e2SPeter Wemm 674c2aa98e2SPeter Wemm /* initialize some macros, etc. */ 67540266059SGregory Neil Shapiro init_vendor_macros(&BlankEnvelope); 676c2aa98e2SPeter Wemm 677c2aa98e2SPeter Wemm /* version */ 67840266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM, 'v', Version); 679c2aa98e2SPeter Wemm 680c2aa98e2SPeter Wemm /* hostname */ 681c2aa98e2SPeter Wemm hp = myhostname(jbuf, sizeof jbuf); 682c2aa98e2SPeter Wemm if (jbuf[0] != '\0') 683c2aa98e2SPeter Wemm { 684c2aa98e2SPeter Wemm struct utsname utsname; 685c2aa98e2SPeter Wemm 686c2aa98e2SPeter Wemm if (tTd(0, 4)) 68740266059SGregory Neil Shapiro sm_dprintf("Canonical name: %s\n", jbuf); 68840266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 'w', jbuf); 68940266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 'j', jbuf); 690c2aa98e2SPeter Wemm setclass('w', jbuf); 691c2aa98e2SPeter Wemm 692c2aa98e2SPeter Wemm p = strchr(jbuf, '.'); 693c2aa98e2SPeter Wemm if (p != NULL) 694c2aa98e2SPeter Wemm { 695c2aa98e2SPeter Wemm if (p[1] != '\0') 696c2aa98e2SPeter Wemm { 69740266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 'm', 69840266059SGregory Neil Shapiro &p[1]); 699c2aa98e2SPeter Wemm } 700c2aa98e2SPeter Wemm while (p != NULL && strchr(&p[1], '.') != NULL) 701c2aa98e2SPeter Wemm { 702c2aa98e2SPeter Wemm *p = '\0'; 703c2aa98e2SPeter Wemm if (tTd(0, 4)) 70440266059SGregory Neil Shapiro sm_dprintf("\ta.k.a.: %s\n", jbuf); 705c2aa98e2SPeter Wemm setclass('w', jbuf); 706c2aa98e2SPeter Wemm *p++ = '.'; 707c2aa98e2SPeter Wemm p = strchr(p, '.'); 708c2aa98e2SPeter Wemm } 709c2aa98e2SPeter Wemm } 710c2aa98e2SPeter Wemm 711c2aa98e2SPeter Wemm if (uname(&utsname) >= 0) 712c2aa98e2SPeter Wemm p = utsname.nodename; 713c2aa98e2SPeter Wemm else 714c2aa98e2SPeter Wemm { 715c2aa98e2SPeter Wemm if (tTd(0, 22)) 71640266059SGregory Neil Shapiro sm_dprintf("uname failed (%s)\n", 71740266059SGregory Neil Shapiro sm_errstring(errno)); 718c2aa98e2SPeter Wemm makelower(jbuf); 719c2aa98e2SPeter Wemm p = jbuf; 720c2aa98e2SPeter Wemm } 721c2aa98e2SPeter Wemm if (tTd(0, 4)) 72240266059SGregory Neil Shapiro sm_dprintf(" UUCP nodename: %s\n", p); 72340266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 'k', p); 724c2aa98e2SPeter Wemm setclass('k', p); 725c2aa98e2SPeter Wemm setclass('w', p); 726c2aa98e2SPeter Wemm } 727c2aa98e2SPeter Wemm if (hp != NULL) 728c2aa98e2SPeter Wemm { 729c2aa98e2SPeter Wemm for (av = hp->h_aliases; av != NULL && *av != NULL; av++) 730c2aa98e2SPeter Wemm { 731c2aa98e2SPeter Wemm if (tTd(0, 4)) 73240266059SGregory Neil Shapiro sm_dprintf("\ta.k.a.: %s\n", *av); 733c2aa98e2SPeter Wemm setclass('w', *av); 734c2aa98e2SPeter Wemm } 73506f25ae9SGregory Neil Shapiro #if NETINET || NETINET6 73640266059SGregory Neil Shapiro for (i = 0; i >= 0 && hp->h_addr_list[i] != NULL; i++) 737c2aa98e2SPeter Wemm { 73806f25ae9SGregory Neil Shapiro # if NETINET6 73906f25ae9SGregory Neil Shapiro char *addr; 74006f25ae9SGregory Neil Shapiro char buf6[INET6_ADDRSTRLEN]; 74106f25ae9SGregory Neil Shapiro struct in6_addr ia6; 74206f25ae9SGregory Neil Shapiro # endif /* NETINET6 */ 74306f25ae9SGregory Neil Shapiro # if NETINET 74406f25ae9SGregory Neil Shapiro struct in_addr ia; 74506f25ae9SGregory Neil Shapiro # endif /* NETINET */ 746c2aa98e2SPeter Wemm char ipbuf[103]; 747c2aa98e2SPeter Wemm 74806f25ae9SGregory Neil Shapiro ipbuf[0] = '\0'; 74906f25ae9SGregory Neil Shapiro switch (hp->h_addrtype) 75006f25ae9SGregory Neil Shapiro { 75106f25ae9SGregory Neil Shapiro # if NETINET 75206f25ae9SGregory Neil Shapiro case AF_INET: 75306f25ae9SGregory Neil Shapiro if (hp->h_length != INADDRSZ) 75406f25ae9SGregory Neil Shapiro break; 75506f25ae9SGregory Neil Shapiro 75606f25ae9SGregory Neil Shapiro memmove(&ia, hp->h_addr_list[i], INADDRSZ); 75740266059SGregory Neil Shapiro (void) sm_snprintf(ipbuf, sizeof ipbuf, 75806f25ae9SGregory Neil Shapiro "[%.100s]", inet_ntoa(ia)); 75906f25ae9SGregory Neil Shapiro break; 76006f25ae9SGregory Neil Shapiro # endif /* NETINET */ 76106f25ae9SGregory Neil Shapiro 76206f25ae9SGregory Neil Shapiro # if NETINET6 76306f25ae9SGregory Neil Shapiro case AF_INET6: 76406f25ae9SGregory Neil Shapiro if (hp->h_length != IN6ADDRSZ) 76506f25ae9SGregory Neil Shapiro break; 76606f25ae9SGregory Neil Shapiro 76706f25ae9SGregory Neil Shapiro memmove(&ia6, hp->h_addr_list[i], IN6ADDRSZ); 76806f25ae9SGregory Neil Shapiro addr = anynet_ntop(&ia6, buf6, sizeof buf6); 76906f25ae9SGregory Neil Shapiro if (addr != NULL) 77040266059SGregory Neil Shapiro (void) sm_snprintf(ipbuf, sizeof ipbuf, 77106f25ae9SGregory Neil Shapiro "[%.100s]", addr); 77206f25ae9SGregory Neil Shapiro break; 77306f25ae9SGregory Neil Shapiro # endif /* NETINET6 */ 77406f25ae9SGregory Neil Shapiro } 77506f25ae9SGregory Neil Shapiro if (ipbuf[0] == '\0') 77606f25ae9SGregory Neil Shapiro break; 77706f25ae9SGregory Neil Shapiro 778c2aa98e2SPeter Wemm if (tTd(0, 4)) 77940266059SGregory Neil Shapiro sm_dprintf("\ta.k.a.: %s\n", ipbuf); 780c2aa98e2SPeter Wemm setclass('w', ipbuf); 781c2aa98e2SPeter Wemm } 78206f25ae9SGregory Neil Shapiro #endif /* NETINET || NETINET6 */ 78340266059SGregory Neil Shapiro #if NETINET6 784193538b7SGregory Neil Shapiro freehostent(hp); 785193538b7SGregory Neil Shapiro hp = NULL; 78640266059SGregory Neil Shapiro #endif /* NETINET6 */ 787c2aa98e2SPeter Wemm } 788c2aa98e2SPeter Wemm 789c2aa98e2SPeter Wemm /* current time */ 79040266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 'b', arpadate((char *) NULL)); 79140266059SGregory Neil Shapiro 79206f25ae9SGregory Neil Shapiro /* current load average */ 79340266059SGregory Neil Shapiro sm_getla(); 794c2aa98e2SPeter Wemm 795c2aa98e2SPeter Wemm QueueLimitRecipient = (QUEUE_CHAR *) NULL; 796c2aa98e2SPeter Wemm QueueLimitSender = (QUEUE_CHAR *) NULL; 797c2aa98e2SPeter Wemm QueueLimitId = (QUEUE_CHAR *) NULL; 79840266059SGregory Neil Shapiro #if _FFR_QUARANTINE 79940266059SGregory Neil Shapiro QueueLimitQuarantine = (QUEUE_CHAR *) NULL; 80040266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */ 801c2aa98e2SPeter Wemm 802c2aa98e2SPeter Wemm /* 803c2aa98e2SPeter Wemm ** Crack argv. 804c2aa98e2SPeter Wemm */ 805c2aa98e2SPeter Wemm 806c2aa98e2SPeter Wemm optind = 1; 807c2aa98e2SPeter Wemm while ((j = getopt(argc, argv, OPTIONS)) != -1) 808c2aa98e2SPeter Wemm { 809c2aa98e2SPeter Wemm switch (j) 810c2aa98e2SPeter Wemm { 811c2aa98e2SPeter Wemm case 'b': /* operations mode */ 81240266059SGregory Neil Shapiro /* already done */ 813c2aa98e2SPeter Wemm break; 814c2aa98e2SPeter Wemm 81540266059SGregory Neil Shapiro case 'A': /* use Alternate sendmail/submit.cf */ 81640266059SGregory Neil Shapiro cftype = optarg[0] == 'c' ? SM_GET_SUBMIT_CF 81740266059SGregory Neil Shapiro : SM_GET_SENDMAIL_CF; 818c2aa98e2SPeter Wemm break; 819c2aa98e2SPeter Wemm 820c2aa98e2SPeter Wemm case 'B': /* body type */ 82140266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j); 82240266059SGregory Neil Shapiro BlankEnvelope.e_bodytype = newstr(optarg); 823c2aa98e2SPeter Wemm break; 824c2aa98e2SPeter Wemm 825c2aa98e2SPeter Wemm case 'C': /* select configuration file (already done) */ 826c2aa98e2SPeter Wemm if (RealUid != 0) 82740266059SGregory Neil Shapiro warn_C_flag = true; 82840266059SGregory Neil Shapiro conffile = newstr(optarg); 82940266059SGregory Neil Shapiro dp = drop_privileges(true); 83006f25ae9SGregory Neil Shapiro setstat(dp); 83140266059SGregory Neil Shapiro safecf = false; 832c2aa98e2SPeter Wemm break; 833c2aa98e2SPeter Wemm 83440266059SGregory Neil Shapiro case 'd': /* debugging */ 83540266059SGregory Neil Shapiro /* already done */ 836c2aa98e2SPeter Wemm break; 837c2aa98e2SPeter Wemm 838c2aa98e2SPeter Wemm case 'f': /* from address */ 839c2aa98e2SPeter Wemm case 'r': /* obsolete -f flag */ 84040266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j); 841c2aa98e2SPeter Wemm if (from != NULL) 842c2aa98e2SPeter Wemm { 843c2aa98e2SPeter Wemm usrerr("More than one \"from\" person"); 844c2aa98e2SPeter Wemm ExitStat = EX_USAGE; 845c2aa98e2SPeter Wemm break; 846c2aa98e2SPeter Wemm } 84740266059SGregory Neil Shapiro from = newstr(denlstring(optarg, true, true)); 848c2aa98e2SPeter Wemm if (strcmp(RealUserName, from) != 0) 849c2aa98e2SPeter Wemm warn_f_flag = j; 850c2aa98e2SPeter Wemm break; 851c2aa98e2SPeter Wemm 852c2aa98e2SPeter Wemm case 'F': /* set full name */ 85340266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j); 854c2aa98e2SPeter Wemm FullName = newstr(optarg); 855c2aa98e2SPeter Wemm break; 856c2aa98e2SPeter Wemm 85706f25ae9SGregory Neil Shapiro case 'G': /* relay (gateway) submission */ 85806f25ae9SGregory Neil Shapiro /* already set */ 85940266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j); 86006f25ae9SGregory Neil Shapiro break; 86106f25ae9SGregory Neil Shapiro 862c2aa98e2SPeter Wemm case 'h': /* hop count */ 86340266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j); 86440266059SGregory Neil Shapiro BlankEnvelope.e_hopcount = (short) strtol(optarg, &ep, 86540266059SGregory Neil Shapiro 10); 86640266059SGregory Neil Shapiro (void) sm_snprintf(buf, sizeof buf, "%d", 86740266059SGregory Neil Shapiro BlankEnvelope.e_hopcount); 86840266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 'c', buf); 86940266059SGregory Neil Shapiro 870c2aa98e2SPeter Wemm if (*ep) 871c2aa98e2SPeter Wemm { 872c2aa98e2SPeter Wemm usrerr("Bad hop count (%s)", optarg); 873c2aa98e2SPeter Wemm ExitStat = EX_USAGE; 874c2aa98e2SPeter Wemm } 875c2aa98e2SPeter Wemm break; 876c2aa98e2SPeter Wemm 87706f25ae9SGregory Neil Shapiro case 'L': /* program label */ 87806f25ae9SGregory Neil Shapiro /* already set */ 87906f25ae9SGregory Neil Shapiro break; 88006f25ae9SGregory Neil Shapiro 881c2aa98e2SPeter Wemm case 'n': /* don't alias */ 88240266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j); 88340266059SGregory Neil Shapiro NoAlias = true; 884c2aa98e2SPeter Wemm break; 885c2aa98e2SPeter Wemm 886c2aa98e2SPeter Wemm case 'N': /* delivery status notifications */ 88740266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j); 888c2aa98e2SPeter Wemm DefaultNotify |= QHASNOTIFY; 88940266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 89040266059SGregory Neil Shapiro macid("{dsn_notify}"), optarg); 89140266059SGregory Neil Shapiro if (sm_strcasecmp(optarg, "never") == 0) 892c2aa98e2SPeter Wemm break; 893c2aa98e2SPeter Wemm for (p = optarg; p != NULL; optarg = p) 894c2aa98e2SPeter Wemm { 895c2aa98e2SPeter Wemm p = strchr(p, ','); 896c2aa98e2SPeter Wemm if (p != NULL) 897c2aa98e2SPeter Wemm *p++ = '\0'; 89840266059SGregory Neil Shapiro if (sm_strcasecmp(optarg, "success") == 0) 899c2aa98e2SPeter Wemm DefaultNotify |= QPINGONSUCCESS; 90040266059SGregory Neil Shapiro else if (sm_strcasecmp(optarg, "failure") == 0) 901c2aa98e2SPeter Wemm DefaultNotify |= QPINGONFAILURE; 90240266059SGregory Neil Shapiro else if (sm_strcasecmp(optarg, "delay") == 0) 903c2aa98e2SPeter Wemm DefaultNotify |= QPINGONDELAY; 904c2aa98e2SPeter Wemm else 905c2aa98e2SPeter Wemm { 906c2aa98e2SPeter Wemm usrerr("Invalid -N argument"); 907c2aa98e2SPeter Wemm ExitStat = EX_USAGE; 908c2aa98e2SPeter Wemm } 909c2aa98e2SPeter Wemm } 910c2aa98e2SPeter Wemm break; 911c2aa98e2SPeter Wemm 912c2aa98e2SPeter Wemm case 'o': /* set option */ 91340266059SGregory Neil Shapiro setoption(*optarg, optarg + 1, false, true, 91440266059SGregory Neil Shapiro &BlankEnvelope); 915c2aa98e2SPeter Wemm break; 916c2aa98e2SPeter Wemm 917c2aa98e2SPeter Wemm case 'O': /* set option (long form) */ 91840266059SGregory Neil Shapiro setoption(' ', optarg, false, true, &BlankEnvelope); 919c2aa98e2SPeter Wemm break; 920c2aa98e2SPeter Wemm 921c2aa98e2SPeter Wemm case 'p': /* set protocol */ 92240266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j); 923c2aa98e2SPeter Wemm p = strchr(optarg, ':'); 924c2aa98e2SPeter Wemm if (p != NULL) 925c2aa98e2SPeter Wemm { 926c2aa98e2SPeter Wemm *p++ = '\0'; 927c2aa98e2SPeter Wemm if (*p != '\0') 928c2aa98e2SPeter Wemm { 92940266059SGregory Neil Shapiro ep = sm_malloc_x(strlen(p) + 1); 930c2aa98e2SPeter Wemm cleanstrcpy(ep, p, MAXNAME); 93140266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, 93240266059SGregory Neil Shapiro A_HEAP, 's', ep); 933c2aa98e2SPeter Wemm } 934c2aa98e2SPeter Wemm } 935c2aa98e2SPeter Wemm if (*optarg != '\0') 936c2aa98e2SPeter Wemm { 93740266059SGregory Neil Shapiro ep = sm_malloc_x(strlen(optarg) + 1); 938c2aa98e2SPeter Wemm cleanstrcpy(ep, optarg, MAXNAME); 93940266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_HEAP, 94040266059SGregory Neil Shapiro 'r', ep); 941c2aa98e2SPeter Wemm } 942c2aa98e2SPeter Wemm break; 943c2aa98e2SPeter Wemm 94440266059SGregory Neil Shapiro #if _FFR_QUARANTINE 94540266059SGregory Neil Shapiro case 'Q': /* change quarantining on queued items */ 94640266059SGregory Neil Shapiro /* sanity check */ 94740266059SGregory Neil Shapiro if (OpMode != MD_DELIVER && 94840266059SGregory Neil Shapiro OpMode != MD_QUEUERUN) 94940266059SGregory Neil Shapiro { 95040266059SGregory Neil Shapiro usrerr("Can not use -Q with -b%c", OpMode); 95140266059SGregory Neil Shapiro ExitStat = EX_USAGE; 95240266059SGregory Neil Shapiro break; 95340266059SGregory Neil Shapiro } 95440266059SGregory Neil Shapiro 95540266059SGregory Neil Shapiro if (OpMode == MD_DELIVER) 95640266059SGregory Neil Shapiro set_op_mode(MD_QUEUERUN); 95740266059SGregory Neil Shapiro 95840266059SGregory Neil Shapiro FullName = NULL; 95940266059SGregory Neil Shapiro 96040266059SGregory Neil Shapiro quarantining = newstr(optarg); 96140266059SGregory Neil Shapiro break; 96240266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */ 96340266059SGregory Neil Shapiro 964c2aa98e2SPeter Wemm case 'q': /* run queue files at intervals */ 96506f25ae9SGregory Neil Shapiro /* sanity check */ 96606f25ae9SGregory Neil Shapiro if (OpMode != MD_DELIVER && 96706f25ae9SGregory Neil Shapiro OpMode != MD_DAEMON && 96806f25ae9SGregory Neil Shapiro OpMode != MD_FGDAEMON && 96906f25ae9SGregory Neil Shapiro OpMode != MD_PRINT && 97040266059SGregory Neil Shapiro OpMode != MD_PRINTNQE && 97106f25ae9SGregory Neil Shapiro OpMode != MD_QUEUERUN) 97206f25ae9SGregory Neil Shapiro { 97306f25ae9SGregory Neil Shapiro usrerr("Can not use -q with -b%c", OpMode); 97406f25ae9SGregory Neil Shapiro ExitStat = EX_USAGE; 97506f25ae9SGregory Neil Shapiro break; 97606f25ae9SGregory Neil Shapiro } 97706f25ae9SGregory Neil Shapiro 97806f25ae9SGregory Neil Shapiro /* don't override -bd, -bD or -bp */ 97906f25ae9SGregory Neil Shapiro if (OpMode == MD_DELIVER) 98040266059SGregory Neil Shapiro set_op_mode(MD_QUEUERUN); 98106f25ae9SGregory Neil Shapiro 982c2aa98e2SPeter Wemm FullName = NULL; 98340266059SGregory Neil Shapiro negate = optarg[0] == '!'; 98440266059SGregory Neil Shapiro if (negate) 98540266059SGregory Neil Shapiro { 98640266059SGregory Neil Shapiro /* negate meaning of pattern match */ 98740266059SGregory Neil Shapiro optarg++; /* skip '!' for next switch */ 98840266059SGregory Neil Shapiro } 98906f25ae9SGregory Neil Shapiro 990c2aa98e2SPeter Wemm switch (optarg[0]) 991c2aa98e2SPeter Wemm { 99240266059SGregory Neil Shapiro case 'G': /* Limit by queue group name */ 99340266059SGregory Neil Shapiro if (negate) 99440266059SGregory Neil Shapiro { 99540266059SGregory Neil Shapiro usrerr("Can not use -q!G"); 99640266059SGregory Neil Shapiro ExitStat = EX_USAGE; 99740266059SGregory Neil Shapiro break; 99840266059SGregory Neil Shapiro } 99940266059SGregory Neil Shapiro if (queuegroup != NULL) 100040266059SGregory Neil Shapiro { 100140266059SGregory Neil Shapiro usrerr("Can not use multiple -qG options"); 100240266059SGregory Neil Shapiro ExitStat = EX_USAGE; 100340266059SGregory Neil Shapiro break; 100440266059SGregory Neil Shapiro } 100540266059SGregory Neil Shapiro queuegroup = newstr(&optarg[1]); 100640266059SGregory Neil Shapiro break; 100740266059SGregory Neil Shapiro 100840266059SGregory Neil Shapiro case 'I': /* Limit by ID */ 100906f25ae9SGregory Neil Shapiro new = (QUEUE_CHAR *) xalloc(sizeof *new); 1010c2aa98e2SPeter Wemm new->queue_match = newstr(&optarg[1]); 101140266059SGregory Neil Shapiro new->queue_negate = negate; 1012c2aa98e2SPeter Wemm new->queue_next = QueueLimitId; 1013c2aa98e2SPeter Wemm QueueLimitId = new; 1014c2aa98e2SPeter Wemm break; 1015c2aa98e2SPeter Wemm 101640266059SGregory Neil Shapiro case 'R': /* Limit by recipient */ 101706f25ae9SGregory Neil Shapiro new = (QUEUE_CHAR *) xalloc(sizeof *new); 1018c2aa98e2SPeter Wemm new->queue_match = newstr(&optarg[1]); 101940266059SGregory Neil Shapiro new->queue_negate = negate; 1020c2aa98e2SPeter Wemm new->queue_next = QueueLimitRecipient; 1021c2aa98e2SPeter Wemm QueueLimitRecipient = new; 1022c2aa98e2SPeter Wemm break; 1023c2aa98e2SPeter Wemm 102440266059SGregory Neil Shapiro case 'S': /* Limit by sender */ 102506f25ae9SGregory Neil Shapiro new = (QUEUE_CHAR *) xalloc(sizeof *new); 1026c2aa98e2SPeter Wemm new->queue_match = newstr(&optarg[1]); 102740266059SGregory Neil Shapiro new->queue_negate = negate; 1028c2aa98e2SPeter Wemm new->queue_next = QueueLimitSender; 1029c2aa98e2SPeter Wemm QueueLimitSender = new; 1030c2aa98e2SPeter Wemm break; 1031c2aa98e2SPeter Wemm 103240266059SGregory Neil Shapiro case 'f': /* foreground queue run */ 103340266059SGregory Neil Shapiro foregroundqueue = true; 103440266059SGregory Neil Shapiro break; 103540266059SGregory Neil Shapiro 103640266059SGregory Neil Shapiro #if _FFR_QUARANTINE 103740266059SGregory Neil Shapiro case 'Q': /* Limit by quarantine message */ 103840266059SGregory Neil Shapiro if (optarg[1] != '\0') 103940266059SGregory Neil Shapiro { 104040266059SGregory Neil Shapiro new = (QUEUE_CHAR *) xalloc(sizeof *new); 104140266059SGregory Neil Shapiro new->queue_match = newstr(&optarg[1]); 104240266059SGregory Neil Shapiro new->queue_negate = negate; 104340266059SGregory Neil Shapiro new->queue_next = QueueLimitQuarantine; 104440266059SGregory Neil Shapiro QueueLimitQuarantine = new; 104540266059SGregory Neil Shapiro } 104640266059SGregory Neil Shapiro QueueMode = QM_QUARANTINE; 104740266059SGregory Neil Shapiro break; 104840266059SGregory Neil Shapiro 104940266059SGregory Neil Shapiro case 'L': /* act on lost items */ 105040266059SGregory Neil Shapiro QueueMode = QM_LOST; 105140266059SGregory Neil Shapiro break; 105240266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */ 105340266059SGregory Neil Shapiro 105440266059SGregory Neil Shapiro case 'p': /* Persistent queue */ 105540266059SGregory Neil Shapiro queuepersistent = true; 105640266059SGregory Neil Shapiro if (QueueIntvl == 0) 105740266059SGregory Neil Shapiro QueueIntvl = 1; 105840266059SGregory Neil Shapiro if (optarg[1] == '\0') 105940266059SGregory Neil Shapiro break; 106040266059SGregory Neil Shapiro ++optarg; 106140266059SGregory Neil Shapiro /* FALLTHROUGH */ 106240266059SGregory Neil Shapiro 1063c2aa98e2SPeter Wemm default: 106406f25ae9SGregory Neil Shapiro i = Errors; 1065c2aa98e2SPeter Wemm QueueIntvl = convtime(optarg, 'm'); 106606f25ae9SGregory Neil Shapiro 106706f25ae9SGregory Neil Shapiro /* check for bad conversion */ 106806f25ae9SGregory Neil Shapiro if (i < Errors) 106906f25ae9SGregory Neil Shapiro ExitStat = EX_USAGE; 1070c2aa98e2SPeter Wemm break; 1071c2aa98e2SPeter Wemm } 1072c2aa98e2SPeter Wemm break; 1073c2aa98e2SPeter Wemm 1074c2aa98e2SPeter Wemm case 'R': /* DSN RET: what to return */ 107540266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j); 107640266059SGregory Neil Shapiro if (bitset(EF_RET_PARAM, BlankEnvelope.e_flags)) 1077c2aa98e2SPeter Wemm { 1078c2aa98e2SPeter Wemm usrerr("Duplicate -R flag"); 1079c2aa98e2SPeter Wemm ExitStat = EX_USAGE; 1080c2aa98e2SPeter Wemm break; 1081c2aa98e2SPeter Wemm } 108240266059SGregory Neil Shapiro BlankEnvelope.e_flags |= EF_RET_PARAM; 108340266059SGregory Neil Shapiro if (sm_strcasecmp(optarg, "hdrs") == 0) 108440266059SGregory Neil Shapiro BlankEnvelope.e_flags |= EF_NO_BODY_RETN; 108540266059SGregory Neil Shapiro else if (sm_strcasecmp(optarg, "full") != 0) 1086c2aa98e2SPeter Wemm { 1087c2aa98e2SPeter Wemm usrerr("Invalid -R value"); 1088c2aa98e2SPeter Wemm ExitStat = EX_USAGE; 1089c2aa98e2SPeter Wemm } 109040266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 109140266059SGregory Neil Shapiro macid("{dsn_ret}"), optarg); 1092c2aa98e2SPeter Wemm break; 1093c2aa98e2SPeter Wemm 1094c2aa98e2SPeter Wemm case 't': /* read recipients from message */ 109540266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j); 109640266059SGregory Neil Shapiro GrabTo = true; 1097c2aa98e2SPeter Wemm break; 1098c2aa98e2SPeter Wemm 1099c2aa98e2SPeter Wemm case 'V': /* DSN ENVID: set "original" envelope id */ 110040266059SGregory Neil Shapiro CHECK_AGAINST_OPMODE(j); 1101c2aa98e2SPeter Wemm if (!xtextok(optarg)) 1102c2aa98e2SPeter Wemm { 1103c2aa98e2SPeter Wemm usrerr("Invalid syntax in -V flag"); 1104c2aa98e2SPeter Wemm ExitStat = EX_USAGE; 1105c2aa98e2SPeter Wemm } 1106c2aa98e2SPeter Wemm else 110706f25ae9SGregory Neil Shapiro { 110840266059SGregory Neil Shapiro BlankEnvelope.e_envid = newstr(optarg); 110940266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 111040266059SGregory Neil Shapiro macid("{dsn_envid}"), optarg); 111106f25ae9SGregory Neil Shapiro } 1112c2aa98e2SPeter Wemm break; 1113c2aa98e2SPeter Wemm 1114c2aa98e2SPeter Wemm case 'X': /* traffic log file */ 111540266059SGregory Neil Shapiro dp = drop_privileges(true); 111606f25ae9SGregory Neil Shapiro setstat(dp); 111706f25ae9SGregory Neil Shapiro if (stat(optarg, &traf_st) == 0 && 111806f25ae9SGregory Neil Shapiro S_ISFIFO(traf_st.st_mode)) 111940266059SGregory Neil Shapiro TrafficLogFile = sm_io_open(SmFtStdio, 112040266059SGregory Neil Shapiro SM_TIME_DEFAULT, 112140266059SGregory Neil Shapiro optarg, 112240266059SGregory Neil Shapiro SM_IO_WRONLY, NULL); 112306f25ae9SGregory Neil Shapiro else 112440266059SGregory Neil Shapiro TrafficLogFile = sm_io_open(SmFtStdio, 112540266059SGregory Neil Shapiro SM_TIME_DEFAULT, 112640266059SGregory Neil Shapiro optarg, 112740266059SGregory Neil Shapiro SM_IO_APPEND, NULL); 1128c2aa98e2SPeter Wemm if (TrafficLogFile == NULL) 1129c2aa98e2SPeter Wemm { 1130c2aa98e2SPeter Wemm syserr("cannot open %s", optarg); 1131c2aa98e2SPeter Wemm ExitStat = EX_CANTCREAT; 1132c2aa98e2SPeter Wemm break; 1133c2aa98e2SPeter Wemm } 113440266059SGregory Neil Shapiro (void) sm_io_setvbuf(TrafficLogFile, SM_TIME_DEFAULT, 113540266059SGregory Neil Shapiro NULL, SM_IO_LBF, 0); 1136c2aa98e2SPeter Wemm break; 1137c2aa98e2SPeter Wemm 1138c2aa98e2SPeter Wemm /* compatibility flags */ 1139c2aa98e2SPeter Wemm case 'c': /* connect to non-local mailers */ 1140c2aa98e2SPeter Wemm case 'i': /* don't let dot stop me */ 1141c2aa98e2SPeter Wemm case 'm': /* send to me too */ 1142c2aa98e2SPeter Wemm case 'T': /* set timeout interval */ 1143c2aa98e2SPeter Wemm case 'v': /* give blow-by-blow description */ 114440266059SGregory Neil Shapiro setoption(j, "T", false, true, &BlankEnvelope); 1145c2aa98e2SPeter Wemm break; 1146c2aa98e2SPeter Wemm 1147c2aa98e2SPeter Wemm case 'e': /* error message disposition */ 1148c2aa98e2SPeter Wemm case 'M': /* define macro */ 114940266059SGregory Neil Shapiro setoption(j, optarg, false, true, &BlankEnvelope); 1150c2aa98e2SPeter Wemm break; 1151c2aa98e2SPeter Wemm 1152c2aa98e2SPeter Wemm case 's': /* save From lines in headers */ 115340266059SGregory Neil Shapiro setoption('f', "T", false, true, &BlankEnvelope); 1154c2aa98e2SPeter Wemm break; 1155c2aa98e2SPeter Wemm 1156c2aa98e2SPeter Wemm #ifdef DBM 1157c2aa98e2SPeter Wemm case 'I': /* initialize alias DBM file */ 115840266059SGregory Neil Shapiro set_op_mode(MD_INITALIAS); 1159c2aa98e2SPeter Wemm break; 1160c2aa98e2SPeter Wemm #endif /* DBM */ 1161c2aa98e2SPeter Wemm 1162c2aa98e2SPeter Wemm #if defined(__osf__) || defined(_AIX3) 1163c2aa98e2SPeter Wemm case 'x': /* random flag that OSF/1 & AIX mailx passes */ 1164c2aa98e2SPeter Wemm break; 116506f25ae9SGregory Neil Shapiro #endif /* defined(__osf__) || defined(_AIX3) */ 1166c2aa98e2SPeter Wemm #if defined(sony_news) 1167c2aa98e2SPeter Wemm case 'E': 1168c2aa98e2SPeter Wemm case 'J': /* ignore flags for Japanese code conversion 116906f25ae9SGregory Neil Shapiro implemented on Sony NEWS */ 1170c2aa98e2SPeter Wemm break; 117106f25ae9SGregory Neil Shapiro #endif /* defined(sony_news) */ 1172c2aa98e2SPeter Wemm 1173c2aa98e2SPeter Wemm default: 117440266059SGregory Neil Shapiro finis(true, true, EX_USAGE); 117540266059SGregory Neil Shapiro /* NOTREACHED */ 1176c2aa98e2SPeter Wemm break; 1177c2aa98e2SPeter Wemm } 1178c2aa98e2SPeter Wemm } 1179c2aa98e2SPeter Wemm 118040266059SGregory Neil Shapiro /* if we've had errors so far, exit now */ 118140266059SGregory Neil Shapiro if ((ExitStat != EX_OK && OpMode != MD_TEST) || 118240266059SGregory Neil Shapiro ExitStat == EX_OSERR) 118306f25ae9SGregory Neil Shapiro { 118440266059SGregory Neil Shapiro finis(false, true, ExitStat); 118540266059SGregory Neil Shapiro /* NOTREACHED */ 118606f25ae9SGregory Neil Shapiro } 118706f25ae9SGregory Neil Shapiro 118840266059SGregory Neil Shapiro if (bitset(SUBMIT_MTA, SubmitMode)) 118906f25ae9SGregory Neil Shapiro { 119040266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM, 119140266059SGregory Neil Shapiro macid("{daemon_flags}"), "CC f"); 119206f25ae9SGregory Neil Shapiro } 119340266059SGregory Neil Shapiro else if (OpMode == MD_DELIVER || OpMode == MD_SMTP) 119406f25ae9SGregory Neil Shapiro { 119540266059SGregory Neil Shapiro SubmitMode = SUBMIT_MSA; 119640266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM, 119740266059SGregory Neil Shapiro macid("{daemon_flags}"), "c u"); 119806f25ae9SGregory Neil Shapiro } 119906f25ae9SGregory Neil Shapiro 1200c2aa98e2SPeter Wemm /* 1201c2aa98e2SPeter Wemm ** Do basic initialization. 1202c2aa98e2SPeter Wemm ** Read system control file. 1203c2aa98e2SPeter Wemm ** Extract special fields for local use. 1204c2aa98e2SPeter Wemm */ 1205c2aa98e2SPeter Wemm 1206c2aa98e2SPeter Wemm #if XDEBUG 1207c2aa98e2SPeter Wemm checkfd012("before readcf"); 120806f25ae9SGregory Neil Shapiro #endif /* XDEBUG */ 120940266059SGregory Neil Shapiro vendor_pre_defaults(&BlankEnvelope); 121006f25ae9SGregory Neil Shapiro 121140266059SGregory Neil Shapiro readcf(getcfname(OpMode, SubmitMode, cftype, conffile), 121240266059SGregory Neil Shapiro safecf, &BlankEnvelope); 121340266059SGregory Neil Shapiro #if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) 121440266059SGregory Neil Shapiro ConfigFileRead = true; 121540266059SGregory Neil Shapiro #endif /* !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) */ 121640266059SGregory Neil Shapiro vendor_post_defaults(&BlankEnvelope); 121740266059SGregory Neil Shapiro 121840266059SGregory Neil Shapiro /* now we can complain about missing fds */ 121940266059SGregory Neil Shapiro if (MissingFds != 0 && LogLevel > 8) 122040266059SGregory Neil Shapiro { 122140266059SGregory Neil Shapiro char mbuf[MAXLINE]; 122240266059SGregory Neil Shapiro 122340266059SGregory Neil Shapiro mbuf[0] = '\0'; 122440266059SGregory Neil Shapiro if (bitset(1 << STDIN_FILENO, MissingFds)) 122540266059SGregory Neil Shapiro (void) sm_strlcat(mbuf, ", stdin", sizeof mbuf); 122640266059SGregory Neil Shapiro if (bitset(1 << STDOUT_FILENO, MissingFds)) 122740266059SGregory Neil Shapiro (void) sm_strlcat(mbuf, ", stdout", sizeof mbuf); 122840266059SGregory Neil Shapiro if (bitset(1 << STDERR_FILENO, MissingFds)) 122940266059SGregory Neil Shapiro (void) sm_strlcat(mbuf, ", stderr", sizeof mbuf); 123040266059SGregory Neil Shapiro 123140266059SGregory Neil Shapiro /* Notice: fill_errno is from high above: fill_fd() */ 123240266059SGregory Neil Shapiro sm_syslog(LOG_WARNING, NOQID, 123340266059SGregory Neil Shapiro "File descriptors missing on startup: %s; %s", 123440266059SGregory Neil Shapiro &mbuf[2], sm_errstring(fill_errno)); 123540266059SGregory Neil Shapiro } 1236c2aa98e2SPeter Wemm 12378774250cSGregory Neil Shapiro /* Remove the ability for a normal user to send signals */ 123840266059SGregory Neil Shapiro if (RealUid != 0 && RealUid != geteuid()) 12398774250cSGregory Neil Shapiro { 12408774250cSGregory Neil Shapiro uid_t new_uid = geteuid(); 12418774250cSGregory Neil Shapiro 12428774250cSGregory Neil Shapiro #if HASSETREUID 12438774250cSGregory Neil Shapiro /* 12448774250cSGregory Neil Shapiro ** Since we can differentiate between uid and euid, 12458774250cSGregory Neil Shapiro ** make the uid a different user so the real user 12468774250cSGregory Neil Shapiro ** can't send signals. However, it doesn't need to be 12478774250cSGregory Neil Shapiro ** root (euid has root). 12488774250cSGregory Neil Shapiro */ 12498774250cSGregory Neil Shapiro 12508774250cSGregory Neil Shapiro if (new_uid == 0) 12518774250cSGregory Neil Shapiro new_uid = DefUid; 12528774250cSGregory Neil Shapiro if (tTd(47, 5)) 125340266059SGregory Neil Shapiro sm_dprintf("Changing real uid to %d\n", (int) new_uid); 12548774250cSGregory Neil Shapiro if (setreuid(new_uid, geteuid()) < 0) 12558774250cSGregory Neil Shapiro { 12568774250cSGregory Neil Shapiro syserr("main: setreuid(%d, %d) failed", 12578774250cSGregory Neil Shapiro (int) new_uid, (int) geteuid()); 125840266059SGregory Neil Shapiro finis(false, true, EX_OSERR); 12598774250cSGregory Neil Shapiro /* NOTREACHED */ 12608774250cSGregory Neil Shapiro } 12618774250cSGregory Neil Shapiro if (tTd(47, 10)) 126240266059SGregory Neil Shapiro sm_dprintf("Now running as e/ruid %d:%d\n", 12638774250cSGregory Neil Shapiro (int) geteuid(), (int) getuid()); 12648774250cSGregory Neil Shapiro #else /* HASSETREUID */ 12658774250cSGregory Neil Shapiro /* 12668774250cSGregory Neil Shapiro ** Have to change both effective and real so need to 12678774250cSGregory Neil Shapiro ** change them both to effective to keep privs. 12688774250cSGregory Neil Shapiro */ 12698774250cSGregory Neil Shapiro 12708774250cSGregory Neil Shapiro if (tTd(47, 5)) 127140266059SGregory Neil Shapiro sm_dprintf("Changing uid to %d\n", (int) new_uid); 12728774250cSGregory Neil Shapiro if (setuid(new_uid) < 0) 12738774250cSGregory Neil Shapiro { 12748774250cSGregory Neil Shapiro syserr("main: setuid(%d) failed", (int) new_uid); 127540266059SGregory Neil Shapiro finis(false, true, EX_OSERR); 12768774250cSGregory Neil Shapiro /* NOTREACHED */ 12778774250cSGregory Neil Shapiro } 12788774250cSGregory Neil Shapiro if (tTd(47, 10)) 127940266059SGregory Neil Shapiro sm_dprintf("Now running as e/ruid %d:%d\n", 12808774250cSGregory Neil Shapiro (int) geteuid(), (int) getuid()); 12818774250cSGregory Neil Shapiro #endif /* HASSETREUID */ 12828774250cSGregory Neil Shapiro } 12838774250cSGregory Neil Shapiro 128440266059SGregory Neil Shapiro #if NAMED_BIND 128540266059SGregory Neil Shapiro if (FallBackMX != NULL) 128640266059SGregory Neil Shapiro (void) getfallbackmxrr(FallBackMX); 128740266059SGregory Neil Shapiro #endif /* NAMED_BIND */ 128840266059SGregory Neil Shapiro 128940266059SGregory Neil Shapiro if (SuperSafe == SAFE_INTERACTIVE && CurEnv->e_sendmode != SM_DELIVER) 129040266059SGregory Neil Shapiro { 129140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 129240266059SGregory Neil Shapiro "WARNING: SuperSafe=interactive should only be used with\n DeliveryMode=interactive\n"); 129340266059SGregory Neil Shapiro } 129440266059SGregory Neil Shapiro 129540266059SGregory Neil Shapiro if (UseMSP && (OpMode == MD_DAEMON || OpMode == MD_FGDAEMON)) 129640266059SGregory Neil Shapiro { 129740266059SGregory Neil Shapiro usrerr("Mail submission program cannot be used as daemon"); 129840266059SGregory Neil Shapiro finis(false, true, EX_USAGE); 129940266059SGregory Neil Shapiro } 130040266059SGregory Neil Shapiro 130140266059SGregory Neil Shapiro if (OpMode == MD_DELIVER || OpMode == MD_SMTP || 130240266059SGregory Neil Shapiro OpMode == MD_QUEUERUN || OpMode == MD_ARPAFTP || 130340266059SGregory Neil Shapiro OpMode == MD_DAEMON || OpMode == MD_FGDAEMON) 130440266059SGregory Neil Shapiro makeworkgroups(); 130540266059SGregory Neil Shapiro 13068774250cSGregory Neil Shapiro /* set up the basic signal handlers */ 130740266059SGregory Neil Shapiro if (sm_signal(SIGINT, SIG_IGN) != SIG_IGN) 130840266059SGregory Neil Shapiro (void) sm_signal(SIGINT, intsig); 130940266059SGregory Neil Shapiro (void) sm_signal(SIGTERM, intsig); 13108774250cSGregory Neil Shapiro 1311c2aa98e2SPeter Wemm /* Enforce use of local time (null string overrides this) */ 1312c2aa98e2SPeter Wemm if (TimeZoneSpec == NULL) 1313c2aa98e2SPeter Wemm unsetenv("TZ"); 1314c2aa98e2SPeter Wemm else if (TimeZoneSpec[0] != '\0') 1315c2aa98e2SPeter Wemm setuserenv("TZ", TimeZoneSpec); 1316c2aa98e2SPeter Wemm else 1317c2aa98e2SPeter Wemm setuserenv("TZ", NULL); 1318c2aa98e2SPeter Wemm tzset(); 1319c2aa98e2SPeter Wemm 132040266059SGregory Neil Shapiro /* initialize mailbox database */ 132140266059SGregory Neil Shapiro i = sm_mbdb_initialize(Mbdb); 132240266059SGregory Neil Shapiro if (i != EX_OK) 132340266059SGregory Neil Shapiro { 132440266059SGregory Neil Shapiro usrerr("Can't initialize mailbox database \"%s\": %s", 132540266059SGregory Neil Shapiro Mbdb, sm_strexit(i)); 132640266059SGregory Neil Shapiro ExitStat = i; 132740266059SGregory Neil Shapiro } 132840266059SGregory Neil Shapiro 1329c2aa98e2SPeter Wemm /* avoid denial-of-service attacks */ 1330c2aa98e2SPeter Wemm resetlimits(); 1331c2aa98e2SPeter Wemm 133240266059SGregory Neil Shapiro if (OpMode == MD_TEST) 133340266059SGregory Neil Shapiro { 133440266059SGregory Neil Shapiro /* can't be done after readcf if RunAs* is used */ 133540266059SGregory Neil Shapiro dp = drop_privileges(true); 133640266059SGregory Neil Shapiro if (dp != EX_OK) 133740266059SGregory Neil Shapiro { 133840266059SGregory Neil Shapiro finis(false, true, dp); 133940266059SGregory Neil Shapiro /* NOTREACHED */ 134040266059SGregory Neil Shapiro } 134140266059SGregory Neil Shapiro } 134240266059SGregory Neil Shapiro else if (OpMode != MD_DAEMON && OpMode != MD_FGDAEMON) 1343c2aa98e2SPeter Wemm { 1344c2aa98e2SPeter Wemm /* drop privileges -- daemon mode done after socket/bind */ 134540266059SGregory Neil Shapiro dp = drop_privileges(false); 134606f25ae9SGregory Neil Shapiro setstat(dp); 134740266059SGregory Neil Shapiro if (dp == EX_OK && UseMSP && (geteuid() == 0 || getuid() == 0)) 134840266059SGregory Neil Shapiro { 134940266059SGregory Neil Shapiro usrerr("Mail submission program must have RunAsUser set to non root user"); 135040266059SGregory Neil Shapiro finis(false, true, EX_CONFIG); 135140266059SGregory Neil Shapiro /* NOTREACHED */ 135240266059SGregory Neil Shapiro } 1353c2aa98e2SPeter Wemm } 1354c2aa98e2SPeter Wemm 135506f25ae9SGregory Neil Shapiro #if NAMED_BIND 135606f25ae9SGregory Neil Shapiro _res.retry = TimeOuts.res_retry[RES_TO_DEFAULT]; 135706f25ae9SGregory Neil Shapiro _res.retrans = TimeOuts.res_retrans[RES_TO_DEFAULT]; 135806f25ae9SGregory Neil Shapiro #endif /* NAMED_BIND */ 135906f25ae9SGregory Neil Shapiro 1360c2aa98e2SPeter Wemm /* 1361c2aa98e2SPeter Wemm ** Find our real host name for future logging. 1362c2aa98e2SPeter Wemm */ 1363c2aa98e2SPeter Wemm 136406f25ae9SGregory Neil Shapiro authinfo = getauthinfo(STDIN_FILENO, &forged); 136540266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, '_', authinfo); 1366c2aa98e2SPeter Wemm 1367c2aa98e2SPeter Wemm /* suppress error printing if errors mailed back or whatever */ 136840266059SGregory Neil Shapiro if (BlankEnvelope.e_errormode != EM_PRINT) 136940266059SGregory Neil Shapiro HoldErrs = true; 1370c2aa98e2SPeter Wemm 1371c2aa98e2SPeter Wemm /* set up the $=m class now, after .cf has a chance to redefine $m */ 137240266059SGregory Neil Shapiro expand("\201m", jbuf, sizeof jbuf, &BlankEnvelope); 1373602a2b1bSGregory Neil Shapiro if (jbuf[0] != '\0') 1374c2aa98e2SPeter Wemm setclass('m', jbuf); 1375c2aa98e2SPeter Wemm 1376c2aa98e2SPeter Wemm /* probe interfaces and locate any additional names */ 137740266059SGregory Neil Shapiro if (DontProbeInterfaces != DPI_PROBENONE) 1378c2aa98e2SPeter Wemm load_if_names(); 1379c2aa98e2SPeter Wemm 138040266059SGregory Neil Shapiro if (tTd(0, 10)) 138140266059SGregory Neil Shapiro { 138240266059SGregory Neil Shapiro /* Now we know which .cf file we use */ 138340266059SGregory Neil Shapiro sm_dprintf(" Conf file:\t%s (selected)\n", 138440266059SGregory Neil Shapiro getcfname(OpMode, SubmitMode, cftype, conffile)); 138540266059SGregory Neil Shapiro sm_dprintf(" Pid file:\t%s (selected)\n", PidFile); 138640266059SGregory Neil Shapiro } 138740266059SGregory Neil Shapiro 1388c2aa98e2SPeter Wemm if (tTd(0, 1)) 1389c2aa98e2SPeter Wemm { 139040266059SGregory Neil Shapiro sm_dprintf("\n============ SYSTEM IDENTITY (after readcf) ============"); 139140266059SGregory Neil Shapiro sm_dprintf("\n (short domain name) $w = "); 139240266059SGregory Neil Shapiro xputs(macvalue('w', &BlankEnvelope)); 139340266059SGregory Neil Shapiro sm_dprintf("\n (canonical domain name) $j = "); 139440266059SGregory Neil Shapiro xputs(macvalue('j', &BlankEnvelope)); 139540266059SGregory Neil Shapiro sm_dprintf("\n (subdomain name) $m = "); 139640266059SGregory Neil Shapiro xputs(macvalue('m', &BlankEnvelope)); 139740266059SGregory Neil Shapiro sm_dprintf("\n (node name) $k = "); 139840266059SGregory Neil Shapiro xputs(macvalue('k', &BlankEnvelope)); 139940266059SGregory Neil Shapiro sm_dprintf("\n========================================================\n\n"); 1400c2aa98e2SPeter Wemm } 1401c2aa98e2SPeter Wemm 1402c2aa98e2SPeter Wemm /* 1403c2aa98e2SPeter Wemm ** Do more command line checking -- these are things that 1404c2aa98e2SPeter Wemm ** have to modify the results of reading the config file. 1405c2aa98e2SPeter Wemm */ 1406c2aa98e2SPeter Wemm 1407c2aa98e2SPeter Wemm /* process authorization warnings from command line */ 1408c2aa98e2SPeter Wemm if (warn_C_flag) 140940266059SGregory Neil Shapiro auth_warning(&BlankEnvelope, "Processed by %s with -C %s", 141040266059SGregory Neil Shapiro RealUserName, conffile); 141106f25ae9SGregory Neil Shapiro if (Warn_Q_option && !wordinclass(RealUserName, 't')) 141240266059SGregory Neil Shapiro auth_warning(&BlankEnvelope, "Processed from queue %s", 141340266059SGregory Neil Shapiro QueueDir); 141440266059SGregory Neil Shapiro if (sysloglabel != NULL && !wordinclass(RealUserName, 't') && 141540266059SGregory Neil Shapiro RealUid != 0 && RealUid != TrustedUid && LogLevel > 1) 141640266059SGregory Neil Shapiro sm_syslog(LOG_WARNING, NOQID, "user %d changed syslog label", 141740266059SGregory Neil Shapiro (int) RealUid); 1418c2aa98e2SPeter Wemm 1419c2aa98e2SPeter Wemm /* check body type for legality */ 142040266059SGregory Neil Shapiro i = check_bodytype(BlankEnvelope.e_bodytype); 142140266059SGregory Neil Shapiro if (i == BODYTYPE_ILLEGAL) 1422c2aa98e2SPeter Wemm { 142340266059SGregory Neil Shapiro usrerr("Illegal body type %s", BlankEnvelope.e_bodytype); 142440266059SGregory Neil Shapiro BlankEnvelope.e_bodytype = NULL; 1425c2aa98e2SPeter Wemm } 142640266059SGregory Neil Shapiro else if (i != BODYTYPE_NONE) 142740266059SGregory Neil Shapiro SevenBitInput = (i == BODYTYPE_7BIT); 1428c2aa98e2SPeter Wemm 1429c2aa98e2SPeter Wemm /* tweak default DSN notifications */ 1430c2aa98e2SPeter Wemm if (DefaultNotify == 0) 1431c2aa98e2SPeter Wemm DefaultNotify = QPINGONFAILURE|QPINGONDELAY; 1432c2aa98e2SPeter Wemm 1433c2aa98e2SPeter Wemm /* be sure we don't pick up bogus HOSTALIASES environment variable */ 143406f25ae9SGregory Neil Shapiro if (OpMode == MD_QUEUERUN && RealUid != 0) 1435c2aa98e2SPeter Wemm (void) unsetenv("HOSTALIASES"); 1436c2aa98e2SPeter Wemm 1437c2aa98e2SPeter Wemm /* check for sane configuration level */ 1438c2aa98e2SPeter Wemm if (ConfigLevel > MAXCONFIGLEVEL) 1439c2aa98e2SPeter Wemm { 1440c2aa98e2SPeter Wemm syserr("Warning: .cf version level (%d) exceeds sendmail version %s functionality (%d)", 1441c2aa98e2SPeter Wemm ConfigLevel, Version, MAXCONFIGLEVEL); 1442c2aa98e2SPeter Wemm } 1443c2aa98e2SPeter Wemm 1444c2aa98e2SPeter Wemm /* need MCI cache to have persistence */ 1445c2aa98e2SPeter Wemm if (HostStatDir != NULL && MaxMciCache == 0) 1446c2aa98e2SPeter Wemm { 1447c2aa98e2SPeter Wemm HostStatDir = NULL; 144840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 144940266059SGregory Neil Shapiro "Warning: HostStatusDirectory disabled with ConnectionCacheSize = 0\n"); 1450c2aa98e2SPeter Wemm } 1451c2aa98e2SPeter Wemm 1452c2aa98e2SPeter Wemm /* need HostStatusDir in order to have SingleThreadDelivery */ 1453c2aa98e2SPeter Wemm if (SingleThreadDelivery && HostStatDir == NULL) 1454c2aa98e2SPeter Wemm { 145540266059SGregory Neil Shapiro SingleThreadDelivery = false; 145640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 145740266059SGregory Neil Shapiro "Warning: HostStatusDirectory required for SingleThreadDelivery\n"); 1458c2aa98e2SPeter Wemm } 1459c2aa98e2SPeter Wemm 1460c2aa98e2SPeter Wemm /* check for permissions */ 146140266059SGregory Neil Shapiro if (RealUid != 0 && 1462065a643dSPeter Wemm RealUid != TrustedUid) 1463c2aa98e2SPeter Wemm { 146440266059SGregory Neil Shapiro char *action = NULL; 146540266059SGregory Neil Shapiro 146640266059SGregory Neil Shapiro switch (OpMode) 146740266059SGregory Neil Shapiro { 146840266059SGregory Neil Shapiro case MD_QUEUERUN: 146940266059SGregory Neil Shapiro #if _FFR_QUARANTINE 147040266059SGregory Neil Shapiro if (quarantining != NULL) 147140266059SGregory Neil Shapiro action = "quarantine jobs"; 147240266059SGregory Neil Shapiro else 147340266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */ 147440266059SGregory Neil Shapiro /* Normal users can do a single queue run */ 147540266059SGregory Neil Shapiro if (QueueIntvl == 0) 147640266059SGregory Neil Shapiro break; 147740266059SGregory Neil Shapiro 147840266059SGregory Neil Shapiro /* but not persistent queue runners */ 147940266059SGregory Neil Shapiro if (action == NULL) 148040266059SGregory Neil Shapiro action = "start a queue runner daemon"; 148140266059SGregory Neil Shapiro /* FALLTHROUGH */ 148240266059SGregory Neil Shapiro 148340266059SGregory Neil Shapiro case MD_PURGESTAT: 148440266059SGregory Neil Shapiro if (action == NULL) 148540266059SGregory Neil Shapiro action = "purge host status"; 148640266059SGregory Neil Shapiro /* FALLTHROUGH */ 148740266059SGregory Neil Shapiro 148840266059SGregory Neil Shapiro case MD_DAEMON: 148940266059SGregory Neil Shapiro case MD_FGDAEMON: 149040266059SGregory Neil Shapiro if (action == NULL) 149140266059SGregory Neil Shapiro action = "run daemon"; 149240266059SGregory Neil Shapiro 149340266059SGregory Neil Shapiro if (tTd(65, 1)) 149440266059SGregory Neil Shapiro sm_dprintf("Deny user %d attempt to %s\n", 149540266059SGregory Neil Shapiro (int) RealUid, action); 149640266059SGregory Neil Shapiro 1497c2aa98e2SPeter Wemm if (LogLevel > 1) 1498c2aa98e2SPeter Wemm sm_syslog(LOG_ALERT, NOQID, 1499c2aa98e2SPeter Wemm "user %d attempted to %s", 150040266059SGregory Neil Shapiro (int) RealUid, action); 150140266059SGregory Neil Shapiro HoldErrs = false; 150240266059SGregory Neil Shapiro usrerr("Permission denied (real uid not trusted)"); 150340266059SGregory Neil Shapiro finis(false, true, EX_USAGE); 150440266059SGregory Neil Shapiro /* NOTREACHED */ 150540266059SGregory Neil Shapiro break; 150640266059SGregory Neil Shapiro 150740266059SGregory Neil Shapiro case MD_VERIFY: 150840266059SGregory Neil Shapiro if (bitset(PRIV_RESTRICTEXPAND, PrivacyFlags)) 1509b518ca7dSPeter Wemm { 151040266059SGregory Neil Shapiro /* 151140266059SGregory Neil Shapiro ** If -bv and RestrictExpand, 151240266059SGregory Neil Shapiro ** drop privs to prevent normal 151340266059SGregory Neil Shapiro ** users from reading private 151440266059SGregory Neil Shapiro ** aliases/forwards/:include:s 151540266059SGregory Neil Shapiro */ 151640266059SGregory Neil Shapiro 151740266059SGregory Neil Shapiro if (tTd(65, 1)) 151840266059SGregory Neil Shapiro sm_dprintf("Drop privs for user %d attempt to expand (RestrictExpand)\n", 151940266059SGregory Neil Shapiro (int) RealUid); 152040266059SGregory Neil Shapiro 152140266059SGregory Neil Shapiro dp = drop_privileges(true); 152240266059SGregory Neil Shapiro 152340266059SGregory Neil Shapiro /* Fake address safety */ 152440266059SGregory Neil Shapiro if (tTd(65, 1)) 152540266059SGregory Neil Shapiro sm_dprintf("Faking DontBlameSendmail=NonRootSafeAddr\n"); 152640266059SGregory Neil Shapiro setbitn(DBS_NONROOTSAFEADDR, DontBlameSendmail); 152740266059SGregory Neil Shapiro 152840266059SGregory Neil Shapiro if (dp != EX_OK) 152940266059SGregory Neil Shapiro { 153040266059SGregory Neil Shapiro if (tTd(65, 1)) 153140266059SGregory Neil Shapiro sm_dprintf("Failed to drop privs for user %d attempt to expand, exiting\n", 153240266059SGregory Neil Shapiro (int) RealUid); 153340266059SGregory Neil Shapiro CurEnv->e_id = NULL; 153440266059SGregory Neil Shapiro finis(true, true, dp); 153540266059SGregory Neil Shapiro /* NOTREACHED */ 153640266059SGregory Neil Shapiro } 153740266059SGregory Neil Shapiro } 153840266059SGregory Neil Shapiro break; 153940266059SGregory Neil Shapiro 154040266059SGregory Neil Shapiro case MD_TEST: 154140266059SGregory Neil Shapiro case MD_PRINT: 154240266059SGregory Neil Shapiro case MD_PRINTNQE: 154340266059SGregory Neil Shapiro case MD_FREEZE: 154440266059SGregory Neil Shapiro case MD_HOSTSTAT: 154540266059SGregory Neil Shapiro /* Nothing special to check */ 154640266059SGregory Neil Shapiro break; 154740266059SGregory Neil Shapiro 154840266059SGregory Neil Shapiro case MD_INITALIAS: 154940266059SGregory Neil Shapiro if (!wordinclass(RealUserName, 't')) 155040266059SGregory Neil Shapiro { 155140266059SGregory Neil Shapiro if (tTd(65, 1)) 155240266059SGregory Neil Shapiro sm_dprintf("Deny user %d attempt to rebuild the alias map\n", 155340266059SGregory Neil Shapiro (int) RealUid); 1554b518ca7dSPeter Wemm if (LogLevel > 1) 1555b518ca7dSPeter Wemm sm_syslog(LOG_ALERT, NOQID, 1556b518ca7dSPeter Wemm "user %d attempted to rebuild the alias map", 155740266059SGregory Neil Shapiro (int) RealUid); 155840266059SGregory Neil Shapiro HoldErrs = false; 155940266059SGregory Neil Shapiro usrerr("Permission denied (real uid not trusted)"); 156040266059SGregory Neil Shapiro finis(false, true, EX_USAGE); 156140266059SGregory Neil Shapiro /* NOTREACHED */ 156240266059SGregory Neil Shapiro } 156340266059SGregory Neil Shapiro if (UseMSP) 156440266059SGregory Neil Shapiro { 156540266059SGregory Neil Shapiro HoldErrs = false; 156640266059SGregory Neil Shapiro usrerr("User %d cannot rebuild aliases in mail submission program", 156740266059SGregory Neil Shapiro (int) RealUid); 156840266059SGregory Neil Shapiro finis(false, true, EX_USAGE); 156940266059SGregory Neil Shapiro /* NOTREACHED */ 157040266059SGregory Neil Shapiro } 157140266059SGregory Neil Shapiro /* FALLTHROUGH */ 157240266059SGregory Neil Shapiro 157340266059SGregory Neil Shapiro default: 157440266059SGregory Neil Shapiro if (bitset(PRIV_RESTRICTEXPAND, PrivacyFlags) && 157540266059SGregory Neil Shapiro Verbose != 0) 157640266059SGregory Neil Shapiro { 157740266059SGregory Neil Shapiro /* 157840266059SGregory Neil Shapiro ** If -v and RestrictExpand, reset 157940266059SGregory Neil Shapiro ** Verbose to prevent normal users 158040266059SGregory Neil Shapiro ** from seeing the expansion of 158140266059SGregory Neil Shapiro ** aliases/forwards/:include:s 158240266059SGregory Neil Shapiro */ 158340266059SGregory Neil Shapiro 158440266059SGregory Neil Shapiro if (tTd(65, 1)) 158540266059SGregory Neil Shapiro sm_dprintf("Dropping verbosity for user %d (RestrictExpand)\n", 158640266059SGregory Neil Shapiro (int) RealUid); 158740266059SGregory Neil Shapiro Verbose = 0; 158840266059SGregory Neil Shapiro } 158940266059SGregory Neil Shapiro break; 159040266059SGregory Neil Shapiro } 1591b518ca7dSPeter Wemm } 1592c2aa98e2SPeter Wemm 1593c2aa98e2SPeter Wemm if (MeToo) 1594c2aa98e2SPeter Wemm BlankEnvelope.e_flags |= EF_METOO; 1595c2aa98e2SPeter Wemm 1596c2aa98e2SPeter Wemm switch (OpMode) 1597c2aa98e2SPeter Wemm { 1598c2aa98e2SPeter Wemm case MD_TEST: 1599c2aa98e2SPeter Wemm /* don't have persistent host status in test mode */ 1600c2aa98e2SPeter Wemm HostStatDir = NULL; 1601c2aa98e2SPeter Wemm if (Verbose == 0) 1602c2aa98e2SPeter Wemm Verbose = 2; 160340266059SGregory Neil Shapiro BlankEnvelope.e_errormode = EM_PRINT; 160440266059SGregory Neil Shapiro HoldErrs = false; 1605c2aa98e2SPeter Wemm break; 1606c2aa98e2SPeter Wemm 1607c2aa98e2SPeter Wemm case MD_VERIFY: 160840266059SGregory Neil Shapiro BlankEnvelope.e_errormode = EM_PRINT; 160940266059SGregory Neil Shapiro HoldErrs = false; 1610c2aa98e2SPeter Wemm /* arrange to exit cleanly on hangup signal */ 161140266059SGregory Neil Shapiro if (sm_signal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL) 161240266059SGregory Neil Shapiro (void) sm_signal(SIGHUP, intsig); 161340266059SGregory Neil Shapiro if (geteuid() != 0) 161440266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 161540266059SGregory Neil Shapiro "Notice: -bv may give misleading output for non-privileged user\n"); 1616c2aa98e2SPeter Wemm break; 1617c2aa98e2SPeter Wemm 1618c2aa98e2SPeter Wemm case MD_FGDAEMON: 161940266059SGregory Neil Shapiro run_in_foreground = true; 162040266059SGregory Neil Shapiro set_op_mode(MD_DAEMON); 162106f25ae9SGregory Neil Shapiro /* FALLTHROUGH */ 1622c2aa98e2SPeter Wemm 1623c2aa98e2SPeter Wemm case MD_DAEMON: 162440266059SGregory Neil Shapiro vendor_daemon_setup(&BlankEnvelope); 1625c2aa98e2SPeter Wemm 1626c2aa98e2SPeter Wemm /* remove things that don't make sense in daemon mode */ 1627c2aa98e2SPeter Wemm FullName = NULL; 162840266059SGregory Neil Shapiro GrabTo = false; 1629c2aa98e2SPeter Wemm 1630c2aa98e2SPeter Wemm /* arrange to restart on hangup signal */ 1631c2aa98e2SPeter Wemm if (SaveArgv[0] == NULL || SaveArgv[0][0] != '/') 1632c2aa98e2SPeter Wemm sm_syslog(LOG_WARNING, NOQID, 1633c2aa98e2SPeter Wemm "daemon invoked without full pathname; kill -1 won't work"); 1634c2aa98e2SPeter Wemm break; 1635c2aa98e2SPeter Wemm 1636c2aa98e2SPeter Wemm case MD_INITALIAS: 1637c2aa98e2SPeter Wemm Verbose = 2; 163840266059SGregory Neil Shapiro BlankEnvelope.e_errormode = EM_PRINT; 163940266059SGregory Neil Shapiro HoldErrs = false; 164006f25ae9SGregory Neil Shapiro /* FALLTHROUGH */ 1641c2aa98e2SPeter Wemm 1642c2aa98e2SPeter Wemm default: 1643c2aa98e2SPeter Wemm /* arrange to exit cleanly on hangup signal */ 164440266059SGregory Neil Shapiro if (sm_signal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL) 164540266059SGregory Neil Shapiro (void) sm_signal(SIGHUP, intsig); 1646c2aa98e2SPeter Wemm break; 1647c2aa98e2SPeter Wemm } 1648c2aa98e2SPeter Wemm 1649c2aa98e2SPeter Wemm /* special considerations for FullName */ 1650c2aa98e2SPeter Wemm if (FullName != NULL) 1651c2aa98e2SPeter Wemm { 1652c2aa98e2SPeter Wemm char *full = NULL; 1653c2aa98e2SPeter Wemm 1654c2aa98e2SPeter Wemm /* full names can't have newlines */ 1655c2aa98e2SPeter Wemm if (strchr(FullName, '\n') != NULL) 1656c2aa98e2SPeter Wemm { 165740266059SGregory Neil Shapiro full = newstr(denlstring(FullName, true, true)); 1658602a2b1bSGregory Neil Shapiro FullName = full; 1659c2aa98e2SPeter Wemm } 1660602a2b1bSGregory Neil Shapiro 1661c2aa98e2SPeter Wemm /* check for characters that may have to be quoted */ 1662c2aa98e2SPeter Wemm if (!rfc822_string(FullName)) 1663c2aa98e2SPeter Wemm { 1664c2aa98e2SPeter Wemm /* 1665c2aa98e2SPeter Wemm ** Quote a full name with special characters 1666c2aa98e2SPeter Wemm ** as a comment so crackaddr() doesn't destroy 1667c2aa98e2SPeter Wemm ** the name portion of the address. 1668c2aa98e2SPeter Wemm */ 1669602a2b1bSGregory Neil Shapiro 167040266059SGregory Neil Shapiro FullName = addquotes(FullName, NULL); 1671c2aa98e2SPeter Wemm if (full != NULL) 167240266059SGregory Neil Shapiro sm_free(full); /* XXX */ 1673c2aa98e2SPeter Wemm } 1674c2aa98e2SPeter Wemm } 1675c2aa98e2SPeter Wemm 1676c2aa98e2SPeter Wemm /* do heuristic mode adjustment */ 1677c2aa98e2SPeter Wemm if (Verbose) 1678c2aa98e2SPeter Wemm { 1679c2aa98e2SPeter Wemm /* turn off noconnect option */ 168040266059SGregory Neil Shapiro setoption('c', "F", true, false, &BlankEnvelope); 1681c2aa98e2SPeter Wemm 1682c2aa98e2SPeter Wemm /* turn on interactive delivery */ 168340266059SGregory Neil Shapiro setoption('d', "", true, false, &BlankEnvelope); 1684c2aa98e2SPeter Wemm } 1685c2aa98e2SPeter Wemm 1686065a643dSPeter Wemm #ifdef VENDOR_CODE 1687065a643dSPeter Wemm /* check for vendor mismatch */ 1688065a643dSPeter Wemm if (VendorCode != VENDOR_CODE) 1689065a643dSPeter Wemm { 1690065a643dSPeter Wemm message("Warning: .cf file vendor code mismatch: sendmail expects vendor %s, .cf file vendor is %s", 1691065a643dSPeter Wemm getvendor(VENDOR_CODE), getvendor(VendorCode)); 1692065a643dSPeter Wemm } 169306f25ae9SGregory Neil Shapiro #endif /* VENDOR_CODE */ 1694065a643dSPeter Wemm 1695c2aa98e2SPeter Wemm /* check for out of date configuration level */ 1696c2aa98e2SPeter Wemm if (ConfigLevel < MAXCONFIGLEVEL) 1697c2aa98e2SPeter Wemm { 1698c2aa98e2SPeter Wemm message("Warning: .cf file is out of date: sendmail %s supports version %d, .cf file is version %d", 1699c2aa98e2SPeter Wemm Version, MAXCONFIGLEVEL, ConfigLevel); 1700c2aa98e2SPeter Wemm } 1701c2aa98e2SPeter Wemm 1702c2aa98e2SPeter Wemm if (ConfigLevel < 3) 170340266059SGregory Neil Shapiro UseErrorsTo = true; 1704c2aa98e2SPeter Wemm 1705c2aa98e2SPeter Wemm /* set options that were previous macros */ 1706c2aa98e2SPeter Wemm if (SmtpGreeting == NULL) 1707c2aa98e2SPeter Wemm { 170840266059SGregory Neil Shapiro if (ConfigLevel < 7 && 170940266059SGregory Neil Shapiro (p = macvalue('e', &BlankEnvelope)) != NULL) 1710c2aa98e2SPeter Wemm SmtpGreeting = newstr(p); 1711c2aa98e2SPeter Wemm else 1712c2aa98e2SPeter Wemm SmtpGreeting = "\201j Sendmail \201v ready at \201b"; 1713c2aa98e2SPeter Wemm } 1714c2aa98e2SPeter Wemm if (UnixFromLine == NULL) 1715c2aa98e2SPeter Wemm { 171640266059SGregory Neil Shapiro if (ConfigLevel < 7 && 171740266059SGregory Neil Shapiro (p = macvalue('l', &BlankEnvelope)) != NULL) 1718c2aa98e2SPeter Wemm UnixFromLine = newstr(p); 1719c2aa98e2SPeter Wemm else 1720c2aa98e2SPeter Wemm UnixFromLine = "From \201g \201d"; 1721c2aa98e2SPeter Wemm } 172206f25ae9SGregory Neil Shapiro SmtpError[0] = '\0'; 1723c2aa98e2SPeter Wemm 1724c2aa98e2SPeter Wemm /* our name for SMTP codes */ 172540266059SGregory Neil Shapiro expand("\201j", jbuf, sizeof jbuf, &BlankEnvelope); 1726602a2b1bSGregory Neil Shapiro if (jbuf[0] == '\0') 172740266059SGregory Neil Shapiro PSTRSET(MyHostName, "localhost"); 1728602a2b1bSGregory Neil Shapiro else 172940266059SGregory Neil Shapiro PSTRSET(MyHostName, jbuf); 1730602a2b1bSGregory Neil Shapiro if (strchr(MyHostName, '.') == NULL) 1731c2aa98e2SPeter Wemm message("WARNING: local host name (%s) is not qualified; fix $j in config file", 1732602a2b1bSGregory Neil Shapiro MyHostName); 1733c2aa98e2SPeter Wemm 1734c2aa98e2SPeter Wemm /* make certain that this name is part of the $=w class */ 1735c2aa98e2SPeter Wemm setclass('w', MyHostName); 1736c2aa98e2SPeter Wemm 173740266059SGregory Neil Shapiro /* fill in the structure of the *default* queue */ 173840266059SGregory Neil Shapiro st = stab("mqueue", ST_QUEUE, ST_FIND); 173940266059SGregory Neil Shapiro if (st == NULL) 174040266059SGregory Neil Shapiro syserr("No default queue (mqueue) defined"); 174140266059SGregory Neil Shapiro else 174240266059SGregory Neil Shapiro set_def_queueval(st->s_quegrp, true); 174340266059SGregory Neil Shapiro 1744c2aa98e2SPeter Wemm /* the indices of built-in mailers */ 1745c2aa98e2SPeter Wemm st = stab("local", ST_MAILER, ST_FIND); 1746c2aa98e2SPeter Wemm if (st != NULL) 1747c2aa98e2SPeter Wemm LocalMailer = st->s_mailer; 1748c2aa98e2SPeter Wemm else if (OpMode != MD_TEST || !warn_C_flag) 1749c2aa98e2SPeter Wemm syserr("No local mailer defined"); 1750c2aa98e2SPeter Wemm 1751c2aa98e2SPeter Wemm st = stab("prog", ST_MAILER, ST_FIND); 1752c2aa98e2SPeter Wemm if (st == NULL) 1753c2aa98e2SPeter Wemm syserr("No prog mailer defined"); 1754c2aa98e2SPeter Wemm else 1755c2aa98e2SPeter Wemm { 1756c2aa98e2SPeter Wemm ProgMailer = st->s_mailer; 1757c2aa98e2SPeter Wemm clrbitn(M_MUSER, ProgMailer->m_flags); 1758c2aa98e2SPeter Wemm } 1759c2aa98e2SPeter Wemm 1760c2aa98e2SPeter Wemm st = stab("*file*", ST_MAILER, ST_FIND); 1761c2aa98e2SPeter Wemm if (st == NULL) 1762c2aa98e2SPeter Wemm syserr("No *file* mailer defined"); 1763c2aa98e2SPeter Wemm else 1764c2aa98e2SPeter Wemm { 1765c2aa98e2SPeter Wemm FileMailer = st->s_mailer; 1766c2aa98e2SPeter Wemm clrbitn(M_MUSER, FileMailer->m_flags); 1767c2aa98e2SPeter Wemm } 1768c2aa98e2SPeter Wemm 1769c2aa98e2SPeter Wemm st = stab("*include*", ST_MAILER, ST_FIND); 1770c2aa98e2SPeter Wemm if (st == NULL) 1771c2aa98e2SPeter Wemm syserr("No *include* mailer defined"); 1772c2aa98e2SPeter Wemm else 1773c2aa98e2SPeter Wemm InclMailer = st->s_mailer; 1774c2aa98e2SPeter Wemm 1775c2aa98e2SPeter Wemm if (ConfigLevel < 6) 1776c2aa98e2SPeter Wemm { 1777c2aa98e2SPeter Wemm /* heuristic tweaking of local mailer for back compat */ 1778c2aa98e2SPeter Wemm if (LocalMailer != NULL) 1779c2aa98e2SPeter Wemm { 1780c2aa98e2SPeter Wemm setbitn(M_ALIASABLE, LocalMailer->m_flags); 1781c2aa98e2SPeter Wemm setbitn(M_HASPWENT, LocalMailer->m_flags); 1782c2aa98e2SPeter Wemm setbitn(M_TRYRULESET5, LocalMailer->m_flags); 1783c2aa98e2SPeter Wemm setbitn(M_CHECKINCLUDE, LocalMailer->m_flags); 1784c2aa98e2SPeter Wemm setbitn(M_CHECKPROG, LocalMailer->m_flags); 1785c2aa98e2SPeter Wemm setbitn(M_CHECKFILE, LocalMailer->m_flags); 1786c2aa98e2SPeter Wemm setbitn(M_CHECKUDB, LocalMailer->m_flags); 1787c2aa98e2SPeter Wemm } 1788c2aa98e2SPeter Wemm if (ProgMailer != NULL) 1789c2aa98e2SPeter Wemm setbitn(M_RUNASRCPT, ProgMailer->m_flags); 1790c2aa98e2SPeter Wemm if (FileMailer != NULL) 1791c2aa98e2SPeter Wemm setbitn(M_RUNASRCPT, FileMailer->m_flags); 1792c2aa98e2SPeter Wemm } 1793c2aa98e2SPeter Wemm if (ConfigLevel < 7) 1794c2aa98e2SPeter Wemm { 1795c2aa98e2SPeter Wemm if (LocalMailer != NULL) 1796c2aa98e2SPeter Wemm setbitn(M_VRFY250, LocalMailer->m_flags); 1797c2aa98e2SPeter Wemm if (ProgMailer != NULL) 1798c2aa98e2SPeter Wemm setbitn(M_VRFY250, ProgMailer->m_flags); 1799c2aa98e2SPeter Wemm if (FileMailer != NULL) 1800c2aa98e2SPeter Wemm setbitn(M_VRFY250, FileMailer->m_flags); 1801c2aa98e2SPeter Wemm } 1802c2aa98e2SPeter Wemm 1803c2aa98e2SPeter Wemm /* MIME Content-Types that cannot be transfer encoded */ 1804c2aa98e2SPeter Wemm setclass('n', "multipart/signed"); 1805c2aa98e2SPeter Wemm 1806c2aa98e2SPeter Wemm /* MIME message/xxx subtypes that can be treated as messages */ 1807c2aa98e2SPeter Wemm setclass('s', "rfc822"); 1808c2aa98e2SPeter Wemm 1809c2aa98e2SPeter Wemm /* MIME Content-Transfer-Encodings that can be encoded */ 1810c2aa98e2SPeter Wemm setclass('e', "7bit"); 1811c2aa98e2SPeter Wemm setclass('e', "8bit"); 1812c2aa98e2SPeter Wemm setclass('e', "binary"); 1813c2aa98e2SPeter Wemm 1814c2aa98e2SPeter Wemm #ifdef USE_B_CLASS 1815c2aa98e2SPeter Wemm /* MIME Content-Types that should be treated as binary */ 1816c2aa98e2SPeter Wemm setclass('b', "image"); 1817c2aa98e2SPeter Wemm setclass('b', "audio"); 1818c2aa98e2SPeter Wemm setclass('b', "video"); 1819c2aa98e2SPeter Wemm setclass('b', "application/octet-stream"); 182006f25ae9SGregory Neil Shapiro #endif /* USE_B_CLASS */ 1821c2aa98e2SPeter Wemm 1822065a643dSPeter Wemm /* MIME headers which have fields to check for overflow */ 182340266059SGregory Neil Shapiro setclass(macid("{checkMIMEFieldHeaders}"), "content-disposition"); 182440266059SGregory Neil Shapiro setclass(macid("{checkMIMEFieldHeaders}"), "content-type"); 1825065a643dSPeter Wemm 1826065a643dSPeter Wemm /* MIME headers to check for length overflow */ 182740266059SGregory Neil Shapiro setclass(macid("{checkMIMETextHeaders}"), "content-description"); 1828065a643dSPeter Wemm 1829065a643dSPeter Wemm /* MIME headers to check for overflow and rebalance */ 183040266059SGregory Neil Shapiro setclass(macid("{checkMIMEHeaders}"), "content-disposition"); 183140266059SGregory Neil Shapiro setclass(macid("{checkMIMEHeaders}"), "content-id"); 183240266059SGregory Neil Shapiro setclass(macid("{checkMIMEHeaders}"), "content-transfer-encoding"); 183340266059SGregory Neil Shapiro setclass(macid("{checkMIMEHeaders}"), "content-type"); 183440266059SGregory Neil Shapiro setclass(macid("{checkMIMEHeaders}"), "mime-version"); 183506f25ae9SGregory Neil Shapiro 183640266059SGregory Neil Shapiro /* Macros to save in the queue file -- don't remove any */ 183740266059SGregory Neil Shapiro setclass(macid("{persistentMacros}"), "r"); 183840266059SGregory Neil Shapiro setclass(macid("{persistentMacros}"), "s"); 183940266059SGregory Neil Shapiro setclass(macid("{persistentMacros}"), "_"); 184040266059SGregory Neil Shapiro setclass(macid("{persistentMacros}"), "{if_addr}"); 184140266059SGregory Neil Shapiro setclass(macid("{persistentMacros}"), "{daemon_flags}"); 1842065a643dSPeter Wemm 1843c2aa98e2SPeter Wemm /* operate in queue directory */ 184440266059SGregory Neil Shapiro if (QueueDir == NULL || *QueueDir == '\0') 1845c2aa98e2SPeter Wemm { 1846c2aa98e2SPeter Wemm if (OpMode != MD_TEST) 1847c2aa98e2SPeter Wemm { 1848c2aa98e2SPeter Wemm syserr("QueueDirectory (Q) option must be set"); 1849c2aa98e2SPeter Wemm ExitStat = EX_CONFIG; 1850c2aa98e2SPeter Wemm } 1851c2aa98e2SPeter Wemm } 1852c2aa98e2SPeter Wemm else 1853c2aa98e2SPeter Wemm { 185406f25ae9SGregory Neil Shapiro if (OpMode != MD_TEST) 185540266059SGregory Neil Shapiro setup_queues(OpMode == MD_DAEMON); 1856c2aa98e2SPeter Wemm } 1857c2aa98e2SPeter Wemm 1858c2aa98e2SPeter Wemm /* check host status directory for validity */ 185940266059SGregory Neil Shapiro if (HostStatDir != NULL && !path_is_dir(HostStatDir, false)) 1860c2aa98e2SPeter Wemm { 1861c2aa98e2SPeter Wemm /* cannot use this value */ 186240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 186340266059SGregory Neil Shapiro "Warning: Cannot use HostStatusDirectory = %s: %s\n", 186440266059SGregory Neil Shapiro HostStatDir, sm_errstring(errno)); 1865c2aa98e2SPeter Wemm HostStatDir = NULL; 1866c2aa98e2SPeter Wemm } 1867c2aa98e2SPeter Wemm 186840266059SGregory Neil Shapiro if (OpMode == MD_QUEUERUN && 186940266059SGregory Neil Shapiro RealUid != 0 && bitset(PRIV_RESTRICTQRUN, PrivacyFlags)) 1870c2aa98e2SPeter Wemm { 1871c2aa98e2SPeter Wemm struct stat stbuf; 1872c2aa98e2SPeter Wemm 1873c2aa98e2SPeter Wemm /* check to see if we own the queue directory */ 1874c2aa98e2SPeter Wemm if (stat(".", &stbuf) < 0) 1875c2aa98e2SPeter Wemm syserr("main: cannot stat %s", QueueDir); 1876c2aa98e2SPeter Wemm if (stbuf.st_uid != RealUid) 1877c2aa98e2SPeter Wemm { 1878c2aa98e2SPeter Wemm /* nope, really a botch */ 187940266059SGregory Neil Shapiro HoldErrs = false; 1880c2aa98e2SPeter Wemm usrerr("You do not have permission to process the queue"); 188140266059SGregory Neil Shapiro finis(false, true, EX_NOPERM); 188240266059SGregory Neil Shapiro /* NOTREACHED */ 1883c2aa98e2SPeter Wemm } 1884c2aa98e2SPeter Wemm } 1885c2aa98e2SPeter Wemm 188640266059SGregory Neil Shapiro #if MILTER 188706f25ae9SGregory Neil Shapiro /* sanity checks on milter filters */ 188806f25ae9SGregory Neil Shapiro if (OpMode == MD_DAEMON || OpMode == MD_SMTP) 188940266059SGregory Neil Shapiro { 189040266059SGregory Neil Shapiro milter_config(InputFilterList, InputFilters, MAXFILTERS); 189140266059SGregory Neil Shapiro # if _FFR_MILTER_PERDAEMON 189240266059SGregory Neil Shapiro setup_daemon_milters(); 189340266059SGregory Neil Shapiro # endif /* _FFR_MILTER_PERDAEMON */ 189440266059SGregory Neil Shapiro } 189540266059SGregory Neil Shapiro #endif /* MILTER */ 189606f25ae9SGregory Neil Shapiro 189740266059SGregory Neil Shapiro /* Convert queuegroup string to qgrp number */ 189840266059SGregory Neil Shapiro if (queuegroup != NULL) 189940266059SGregory Neil Shapiro { 190040266059SGregory Neil Shapiro qgrp = name2qid(queuegroup); 190140266059SGregory Neil Shapiro if (qgrp == NOQGRP) 190240266059SGregory Neil Shapiro { 190340266059SGregory Neil Shapiro HoldErrs = false; 190440266059SGregory Neil Shapiro usrerr("Queue group %s unknown", queuegroup); 190540266059SGregory Neil Shapiro finis(false, true, ExitStat); 190640266059SGregory Neil Shapiro /* NOTREACHED */ 190740266059SGregory Neil Shapiro } 190840266059SGregory Neil Shapiro } 190942e5d165SGregory Neil Shapiro 1910c2aa98e2SPeter Wemm /* if we've had errors so far, exit now */ 1911c2aa98e2SPeter Wemm if (ExitStat != EX_OK && OpMode != MD_TEST) 191240266059SGregory Neil Shapiro { 191340266059SGregory Neil Shapiro finis(false, true, ExitStat); 191440266059SGregory Neil Shapiro /* NOTREACHED */ 191540266059SGregory Neil Shapiro } 191640266059SGregory Neil Shapiro 191740266059SGregory Neil Shapiro #if SASL 191840266059SGregory Neil Shapiro /* sendmail specific SASL initialization */ 191940266059SGregory Neil Shapiro sm_sasl_init(); 192040266059SGregory Neil Shapiro #endif /* SASL */ 1921c2aa98e2SPeter Wemm 1922c2aa98e2SPeter Wemm #if XDEBUG 1923c2aa98e2SPeter Wemm checkfd012("before main() initmaps"); 192406f25ae9SGregory Neil Shapiro #endif /* XDEBUG */ 1925c2aa98e2SPeter Wemm 1926c2aa98e2SPeter Wemm /* 1927c2aa98e2SPeter Wemm ** Do operation-mode-dependent initialization. 1928c2aa98e2SPeter Wemm */ 1929c2aa98e2SPeter Wemm 1930c2aa98e2SPeter Wemm switch (OpMode) 1931c2aa98e2SPeter Wemm { 1932c2aa98e2SPeter Wemm case MD_PRINT: 1933c2aa98e2SPeter Wemm /* print the queue */ 193440266059SGregory Neil Shapiro HoldErrs = false; 193540266059SGregory Neil Shapiro dropenvelope(&BlankEnvelope, true, false); 193640266059SGregory Neil Shapiro (void) sm_signal(SIGPIPE, sigpipe); 193740266059SGregory Neil Shapiro if (qgrp != NOQGRP) 193840266059SGregory Neil Shapiro { 193940266059SGregory Neil Shapiro int j; 194040266059SGregory Neil Shapiro 194140266059SGregory Neil Shapiro /* Selecting a particular queue group to run */ 194240266059SGregory Neil Shapiro for (j = 0; j < Queue[qgrp]->qg_numqueues; j++) 194340266059SGregory Neil Shapiro { 194440266059SGregory Neil Shapiro if (StopRequest) 194540266059SGregory Neil Shapiro stop_sendmail(); 194640266059SGregory Neil Shapiro (void) print_single_queue(qgrp, j); 194740266059SGregory Neil Shapiro } 194840266059SGregory Neil Shapiro finis(false, true, EX_OK); 194940266059SGregory Neil Shapiro /* NOTREACHED */ 195040266059SGregory Neil Shapiro } 1951c2aa98e2SPeter Wemm printqueue(); 195240266059SGregory Neil Shapiro finis(false, true, EX_OK); 195340266059SGregory Neil Shapiro /* NOTREACHED */ 1954065a643dSPeter Wemm break; 1955c2aa98e2SPeter Wemm 195640266059SGregory Neil Shapiro case MD_PRINTNQE: 195740266059SGregory Neil Shapiro /* print number of entries in queue */ 195840266059SGregory Neil Shapiro dropenvelope(&BlankEnvelope, true, false); 195940266059SGregory Neil Shapiro (void) sm_signal(SIGPIPE, sigpipe); 196040266059SGregory Neil Shapiro printnqe(smioout, NULL); 196140266059SGregory Neil Shapiro finis(false, true, EX_OK); 196240266059SGregory Neil Shapiro /* NOTREACHED */ 196340266059SGregory Neil Shapiro break; 196440266059SGregory Neil Shapiro 196540266059SGregory Neil Shapiro #if _FFR_QUARANTINE 196640266059SGregory Neil Shapiro case MD_QUEUERUN: 196740266059SGregory Neil Shapiro /* only handle quarantining here */ 196840266059SGregory Neil Shapiro if (quarantining == NULL) 196940266059SGregory Neil Shapiro break; 197040266059SGregory Neil Shapiro 197140266059SGregory Neil Shapiro if (QueueMode != QM_QUARANTINE && 197240266059SGregory Neil Shapiro QueueMode != QM_NORMAL) 197340266059SGregory Neil Shapiro { 197440266059SGregory Neil Shapiro HoldErrs = false; 197540266059SGregory Neil Shapiro usrerr("Can not use -Q with -q%c", QueueMode); 197640266059SGregory Neil Shapiro ExitStat = EX_USAGE; 197740266059SGregory Neil Shapiro finis(false, true, ExitStat); 197840266059SGregory Neil Shapiro /* NOTREACHED */ 197940266059SGregory Neil Shapiro } 198040266059SGregory Neil Shapiro quarantine_queue(quarantining, qgrp); 198140266059SGregory Neil Shapiro finis(false, true, EX_OK); 198240266059SGregory Neil Shapiro break; 198340266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */ 198440266059SGregory Neil Shapiro 1985c2aa98e2SPeter Wemm case MD_HOSTSTAT: 198640266059SGregory Neil Shapiro (void) sm_signal(SIGPIPE, sigpipe); 198706f25ae9SGregory Neil Shapiro (void) mci_traverse_persistent(mci_print_persistent, NULL); 198840266059SGregory Neil Shapiro finis(false, true, EX_OK); 198940266059SGregory Neil Shapiro /* NOTREACHED */ 1990c2aa98e2SPeter Wemm break; 1991c2aa98e2SPeter Wemm 1992c2aa98e2SPeter Wemm case MD_PURGESTAT: 199306f25ae9SGregory Neil Shapiro (void) mci_traverse_persistent(mci_purge_persistent, NULL); 199440266059SGregory Neil Shapiro finis(false, true, EX_OK); 199540266059SGregory Neil Shapiro /* NOTREACHED */ 1996c2aa98e2SPeter Wemm break; 1997c2aa98e2SPeter Wemm 1998c2aa98e2SPeter Wemm case MD_INITALIAS: 1999065a643dSPeter Wemm /* initialize maps */ 200006f25ae9SGregory Neil Shapiro initmaps(); 200140266059SGregory Neil Shapiro finis(false, true, ExitStat); 200240266059SGregory Neil Shapiro /* NOTREACHED */ 2003065a643dSPeter Wemm break; 2004c2aa98e2SPeter Wemm 2005c2aa98e2SPeter Wemm case MD_SMTP: 2006c2aa98e2SPeter Wemm case MD_DAEMON: 2007c2aa98e2SPeter Wemm /* reset DSN parameters */ 2008c2aa98e2SPeter Wemm DefaultNotify = QPINGONFAILURE|QPINGONDELAY; 200940266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM, 201040266059SGregory Neil Shapiro macid("{dsn_notify}"), NULL); 201140266059SGregory Neil Shapiro BlankEnvelope.e_envid = NULL; 201240266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM, 201340266059SGregory Neil Shapiro macid("{dsn_envid}"), NULL); 201440266059SGregory Neil Shapiro BlankEnvelope.e_flags &= ~(EF_RET_PARAM|EF_NO_BODY_RETN); 201540266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM, 201640266059SGregory Neil Shapiro macid("{dsn_ret}"), NULL); 2017c2aa98e2SPeter Wemm 2018065a643dSPeter Wemm /* don't open maps for daemon -- done below in child */ 2019c2aa98e2SPeter Wemm break; 2020c2aa98e2SPeter Wemm } 2021c2aa98e2SPeter Wemm 2022c2aa98e2SPeter Wemm if (tTd(0, 15)) 2023c2aa98e2SPeter Wemm { 2024c2aa98e2SPeter Wemm /* print configuration table (or at least part of it) */ 2025c2aa98e2SPeter Wemm if (tTd(0, 90)) 2026c2aa98e2SPeter Wemm printrules(); 2027c2aa98e2SPeter Wemm for (i = 0; i < MAXMAILERS; i++) 2028c2aa98e2SPeter Wemm { 2029c2aa98e2SPeter Wemm if (Mailer[i] != NULL) 2030c2aa98e2SPeter Wemm printmailer(Mailer[i]); 2031c2aa98e2SPeter Wemm } 2032c2aa98e2SPeter Wemm } 2033c2aa98e2SPeter Wemm 2034c2aa98e2SPeter Wemm /* 2035c2aa98e2SPeter Wemm ** Switch to the main envelope. 2036c2aa98e2SPeter Wemm */ 2037c2aa98e2SPeter Wemm 203840266059SGregory Neil Shapiro CurEnv = newenvelope(&MainEnvelope, &BlankEnvelope, 203940266059SGregory Neil Shapiro sm_rpool_new_x(NULL)); 2040c2aa98e2SPeter Wemm MainEnvelope.e_flags = BlankEnvelope.e_flags; 2041c2aa98e2SPeter Wemm 2042c2aa98e2SPeter Wemm /* 2043c2aa98e2SPeter Wemm ** If test mode, read addresses from stdin and process. 2044c2aa98e2SPeter Wemm */ 2045c2aa98e2SPeter Wemm 2046c2aa98e2SPeter Wemm if (OpMode == MD_TEST) 2047c2aa98e2SPeter Wemm { 204840266059SGregory Neil Shapiro if (isatty(sm_io_getinfo(smioin, SM_IO_WHAT_FD, NULL))) 2049c2aa98e2SPeter Wemm Verbose = 2; 2050c2aa98e2SPeter Wemm 2051c2aa98e2SPeter Wemm if (Verbose) 2052c2aa98e2SPeter Wemm { 205340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 205440266059SGregory Neil Shapiro "ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)\n"); 205540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 205640266059SGregory Neil Shapiro "Enter <ruleset> <address>\n"); 2057c2aa98e2SPeter Wemm } 205840266059SGregory Neil Shapiro macdefine(&(MainEnvelope.e_macro), A_PERM, 205940266059SGregory Neil Shapiro macid("{addr_type}"), "e r"); 2060c2aa98e2SPeter Wemm for (;;) 2061c2aa98e2SPeter Wemm { 206240266059SGregory Neil Shapiro SM_TRY 206340266059SGregory Neil Shapiro { 206440266059SGregory Neil Shapiro (void) sm_signal(SIGINT, intindebug); 206540266059SGregory Neil Shapiro (void) sm_releasesignal(SIGINT); 2066c2aa98e2SPeter Wemm if (Verbose == 2) 206740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, 206840266059SGregory Neil Shapiro SM_TIME_DEFAULT, 206940266059SGregory Neil Shapiro "> "); 207040266059SGregory Neil Shapiro (void) sm_io_flush(smioout, SM_TIME_DEFAULT); 207140266059SGregory Neil Shapiro if (sm_io_fgets(smioin, SM_TIME_DEFAULT, buf, 207240266059SGregory Neil Shapiro sizeof buf) == NULL) 207340266059SGregory Neil Shapiro testmodeline("/quit", &MainEnvelope); 2074c2aa98e2SPeter Wemm p = strchr(buf, '\n'); 2075c2aa98e2SPeter Wemm if (p != NULL) 2076c2aa98e2SPeter Wemm *p = '\0'; 2077c2aa98e2SPeter Wemm if (Verbose < 2) 207840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, 207940266059SGregory Neil Shapiro SM_TIME_DEFAULT, 208040266059SGregory Neil Shapiro "> %s\n", buf); 208140266059SGregory Neil Shapiro testmodeline(buf, &MainEnvelope); 208240266059SGregory Neil Shapiro } 208340266059SGregory Neil Shapiro SM_EXCEPT(exc, "[!F]*") 208440266059SGregory Neil Shapiro { 208540266059SGregory Neil Shapiro /* 208640266059SGregory Neil Shapiro ** 8.10 just prints \n on interrupt. 208740266059SGregory Neil Shapiro ** I'm printing the exception here in case 208840266059SGregory Neil Shapiro ** sendmail is extended to raise additional 208940266059SGregory Neil Shapiro ** exceptions in this context. 209040266059SGregory Neil Shapiro */ 209140266059SGregory Neil Shapiro 209240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 209340266059SGregory Neil Shapiro "\n"); 209440266059SGregory Neil Shapiro sm_exc_print(exc, smioout); 209540266059SGregory Neil Shapiro } 209640266059SGregory Neil Shapiro SM_END_TRY 2097c2aa98e2SPeter Wemm } 2098c2aa98e2SPeter Wemm } 2099c2aa98e2SPeter Wemm 210006f25ae9SGregory Neil Shapiro #if STARTTLS 210140266059SGregory Neil Shapiro tls_ok = true; 210240266059SGregory Neil Shapiro if (OpMode == MD_QUEUERUN || OpMode == MD_DELIVER) 210340266059SGregory Neil Shapiro { 210440266059SGregory Neil Shapiro /* check whether STARTTLS is turned off for the client */ 210540266059SGregory Neil Shapiro if (chkclientmodifiers(D_NOTLS)) 210640266059SGregory Neil Shapiro tls_ok = false; 210740266059SGregory Neil Shapiro } 210840266059SGregory Neil Shapiro else if (OpMode == MD_DAEMON || OpMode == MD_FGDAEMON || 210940266059SGregory Neil Shapiro OpMode == MD_SMTP) 211040266059SGregory Neil Shapiro { 211140266059SGregory Neil Shapiro /* check whether STARTTLS is turned off for the server */ 211240266059SGregory Neil Shapiro if (chkdaemonmodifiers(D_NOTLS)) 211340266059SGregory Neil Shapiro tls_ok = false; 211440266059SGregory Neil Shapiro } 211540266059SGregory Neil Shapiro else /* other modes don't need STARTTLS */ 211640266059SGregory Neil Shapiro tls_ok = false; 211706f25ae9SGregory Neil Shapiro 211840266059SGregory Neil Shapiro if (tls_ok) 211940266059SGregory Neil Shapiro { 212040266059SGregory Neil Shapiro /* basic TLS initialization */ 212140266059SGregory Neil Shapiro tls_ok = init_tls_library(); 212240266059SGregory Neil Shapiro } 212340266059SGregory Neil Shapiro 212440266059SGregory Neil Shapiro if (!tls_ok && (OpMode == MD_QUEUERUN || OpMode == MD_DELIVER)) 212540266059SGregory Neil Shapiro { 212640266059SGregory Neil Shapiro /* disable TLS for client */ 212740266059SGregory Neil Shapiro setclttls(false); 212840266059SGregory Neil Shapiro } 212940266059SGregory Neil Shapiro #endif /* STARTTLS */ 213040266059SGregory Neil Shapiro 2131c2aa98e2SPeter Wemm /* 2132c2aa98e2SPeter Wemm ** If collecting stuff from the queue, go start doing that. 2133c2aa98e2SPeter Wemm */ 2134c2aa98e2SPeter Wemm 213506f25ae9SGregory Neil Shapiro if (OpMode == MD_QUEUERUN && QueueIntvl == 0) 2136c2aa98e2SPeter Wemm { 213740266059SGregory Neil Shapiro pid_t pid = -1; 213840266059SGregory Neil Shapiro 213906f25ae9SGregory Neil Shapiro #if STARTTLS 214006f25ae9SGregory Neil Shapiro /* init TLS for client, ignore result for now */ 214140266059SGregory Neil Shapiro (void) initclttls(tls_ok); 214206f25ae9SGregory Neil Shapiro #endif /* STARTTLS */ 214340266059SGregory Neil Shapiro 214440266059SGregory Neil Shapiro /* 214540266059SGregory Neil Shapiro ** The parent process of the caller of runqueue() needs 214640266059SGregory Neil Shapiro ** to stay around for a possible SIGTERM. The SIGTERM will 214740266059SGregory Neil Shapiro ** tell this process that all of the queue runners children 214840266059SGregory Neil Shapiro ** need to be sent SIGTERM as well. At the same time, we 214940266059SGregory Neil Shapiro ** want to return control to the command line. So we do an 215040266059SGregory Neil Shapiro ** extra fork(). 215140266059SGregory Neil Shapiro */ 215240266059SGregory Neil Shapiro 215340266059SGregory Neil Shapiro if (Verbose || foregroundqueue || (pid = fork()) <= 0) 215440266059SGregory Neil Shapiro { 215540266059SGregory Neil Shapiro /* 215640266059SGregory Neil Shapiro ** If the fork() failed we should still try to do 215740266059SGregory Neil Shapiro ** the queue run. If it succeeded then the child 215840266059SGregory Neil Shapiro ** is going to start the run and wait for all 215940266059SGregory Neil Shapiro ** of the children to finish. 216040266059SGregory Neil Shapiro */ 216140266059SGregory Neil Shapiro 216240266059SGregory Neil Shapiro if (pid == 0) 216340266059SGregory Neil Shapiro { 216440266059SGregory Neil Shapiro /* Reset global flags */ 216540266059SGregory Neil Shapiro RestartRequest = NULL; 216640266059SGregory Neil Shapiro ShutdownRequest = NULL; 216740266059SGregory Neil Shapiro PendingSignal = 0; 216840266059SGregory Neil Shapiro 216940266059SGregory Neil Shapiro /* disconnect from terminal */ 217040266059SGregory Neil Shapiro disconnect(2, CurEnv); 2171c2aa98e2SPeter Wemm } 217240266059SGregory Neil Shapiro 217340266059SGregory Neil Shapiro CurrentPid = getpid(); 217440266059SGregory Neil Shapiro if (qgrp != NOQGRP) 217540266059SGregory Neil Shapiro { 217640266059SGregory Neil Shapiro /* 217740266059SGregory Neil Shapiro ** To run a specific queue group mark it to 217840266059SGregory Neil Shapiro ** be run, select the work group it's in and 217940266059SGregory Neil Shapiro ** increment the work counter. 218040266059SGregory Neil Shapiro */ 218140266059SGregory Neil Shapiro 218240266059SGregory Neil Shapiro runqueueevent(qgrp); 218340266059SGregory Neil Shapiro (void) run_work_group(Queue[qgrp]->qg_wgrp, 218440266059SGregory Neil Shapiro false, Verbose, 218540266059SGregory Neil Shapiro queuepersistent, false); 218640266059SGregory Neil Shapiro } 218740266059SGregory Neil Shapiro else 218840266059SGregory Neil Shapiro (void) runqueue(false, Verbose, 218940266059SGregory Neil Shapiro queuepersistent, true); 219040266059SGregory Neil Shapiro 219140266059SGregory Neil Shapiro /* set the title to make it easier to find */ 219240266059SGregory Neil Shapiro sm_setproctitle(true, CurEnv, "Queue control"); 219340266059SGregory Neil Shapiro (void) sm_signal(SIGCHLD, SIG_DFL); 219440266059SGregory Neil Shapiro while (CurChildren > 0) 219540266059SGregory Neil Shapiro { 219640266059SGregory Neil Shapiro int status; 219740266059SGregory Neil Shapiro pid_t ret; 219840266059SGregory Neil Shapiro 219940266059SGregory Neil Shapiro while ((ret = sm_wait(&status)) <= 0) 220040266059SGregory Neil Shapiro continue; 220140266059SGregory Neil Shapiro 220240266059SGregory Neil Shapiro /* Only drop when a child gives status */ 220340266059SGregory Neil Shapiro if (WIFSTOPPED(status)) 220440266059SGregory Neil Shapiro continue; 220540266059SGregory Neil Shapiro 220640266059SGregory Neil Shapiro proc_list_drop(ret, status, NULL); 220740266059SGregory Neil Shapiro } 220840266059SGregory Neil Shapiro } 220940266059SGregory Neil Shapiro finis(true, true, ExitStat); 221040266059SGregory Neil Shapiro /* NOTREACHED */ 221140266059SGregory Neil Shapiro } 2212c2aa98e2SPeter Wemm 2213193538b7SGregory Neil Shapiro # if SASL 2214193538b7SGregory Neil Shapiro if (OpMode == MD_SMTP || OpMode == MD_DAEMON) 2215193538b7SGregory Neil Shapiro { 221640266059SGregory Neil Shapiro /* check whether AUTH is turned off for the server */ 221740266059SGregory Neil Shapiro if (!chkdaemonmodifiers(D_NOAUTH) && 221840266059SGregory Neil Shapiro (i = sasl_server_init(srvcallbacks, "Sendmail")) != SASL_OK) 2219193538b7SGregory Neil Shapiro syserr("!sasl_server_init failed! [%s]", 2220193538b7SGregory Neil Shapiro sasl_errstring(i, NULL, NULL)); 2221193538b7SGregory Neil Shapiro } 2222193538b7SGregory Neil Shapiro # endif /* SASL */ 2223193538b7SGregory Neil Shapiro 222440266059SGregory Neil Shapiro if (OpMode == MD_SMTP) 222540266059SGregory Neil Shapiro { 222640266059SGregory Neil Shapiro proc_list_add(CurrentPid, "Sendmail SMTP Agent", 222740266059SGregory Neil Shapiro PROC_DAEMON, 0, -1); 222840266059SGregory Neil Shapiro 222940266059SGregory Neil Shapiro /* clean up background delivery children */ 223040266059SGregory Neil Shapiro (void) sm_signal(SIGCHLD, reapchild); 223140266059SGregory Neil Shapiro } 223240266059SGregory Neil Shapiro 2233c2aa98e2SPeter Wemm /* 2234c2aa98e2SPeter Wemm ** If a daemon, wait for a request. 2235c2aa98e2SPeter Wemm ** getrequests will always return in a child. 2236c2aa98e2SPeter Wemm ** If we should also be processing the queue, start 2237c2aa98e2SPeter Wemm ** doing it in background. 2238c2aa98e2SPeter Wemm ** We check for any errors that might have happened 2239c2aa98e2SPeter Wemm ** during startup. 2240c2aa98e2SPeter Wemm */ 2241c2aa98e2SPeter Wemm 2242c2aa98e2SPeter Wemm if (OpMode == MD_DAEMON || QueueIntvl != 0) 2243c2aa98e2SPeter Wemm { 2244c2aa98e2SPeter Wemm char dtype[200]; 2245c2aa98e2SPeter Wemm 2246c2aa98e2SPeter Wemm if (!run_in_foreground && !tTd(99, 100)) 2247c2aa98e2SPeter Wemm { 2248c2aa98e2SPeter Wemm /* put us in background */ 2249c2aa98e2SPeter Wemm i = fork(); 2250c2aa98e2SPeter Wemm if (i < 0) 2251c2aa98e2SPeter Wemm syserr("daemon: cannot fork"); 2252c2aa98e2SPeter Wemm if (i != 0) 225340266059SGregory Neil Shapiro { 225440266059SGregory Neil Shapiro finis(false, true, EX_OK); 225540266059SGregory Neil Shapiro /* NOTREACHED */ 225640266059SGregory Neil Shapiro } 225740266059SGregory Neil Shapiro 225840266059SGregory Neil Shapiro /* 225940266059SGregory Neil Shapiro ** Initialize exception stack and default exception 226040266059SGregory Neil Shapiro ** handler for child process. 226140266059SGregory Neil Shapiro */ 226240266059SGregory Neil Shapiro 226340266059SGregory Neil Shapiro /* Reset global flags */ 226440266059SGregory Neil Shapiro RestartRequest = NULL; 226540266059SGregory Neil Shapiro RestartWorkGroup = false; 226640266059SGregory Neil Shapiro ShutdownRequest = NULL; 226740266059SGregory Neil Shapiro PendingSignal = 0; 226840266059SGregory Neil Shapiro CurrentPid = getpid(); 226940266059SGregory Neil Shapiro 227040266059SGregory Neil Shapiro sm_exc_newthread(fatal_error); 2271c2aa98e2SPeter Wemm 2272c2aa98e2SPeter Wemm /* disconnect from our controlling tty */ 227340266059SGregory Neil Shapiro disconnect(2, &MainEnvelope); 2274c2aa98e2SPeter Wemm } 2275c2aa98e2SPeter Wemm 2276c2aa98e2SPeter Wemm dtype[0] = '\0'; 2277c2aa98e2SPeter Wemm if (OpMode == MD_DAEMON) 227840266059SGregory Neil Shapiro { 227940266059SGregory Neil Shapiro (void) sm_strlcat(dtype, "+SMTP", sizeof dtype); 228040266059SGregory Neil Shapiro DaemonPid = CurrentPid; 228140266059SGregory Neil Shapiro } 2282c2aa98e2SPeter Wemm if (QueueIntvl != 0) 2283c2aa98e2SPeter Wemm { 228440266059SGregory Neil Shapiro (void) sm_strlcat2(dtype, 228540266059SGregory Neil Shapiro queuepersistent 228640266059SGregory Neil Shapiro ? "+persistent-queueing@" 228740266059SGregory Neil Shapiro : "+queueing@", 228840266059SGregory Neil Shapiro pintvl(QueueIntvl, true), 228906f25ae9SGregory Neil Shapiro sizeof dtype); 2290c2aa98e2SPeter Wemm } 2291c2aa98e2SPeter Wemm if (tTd(0, 1)) 229240266059SGregory Neil Shapiro (void) sm_strlcat(dtype, "+debugging", sizeof dtype); 2293c2aa98e2SPeter Wemm 2294c2aa98e2SPeter Wemm sm_syslog(LOG_INFO, NOQID, 2295c2aa98e2SPeter Wemm "starting daemon (%s): %s", Version, dtype + 1); 229640266059SGregory Neil Shapiro #if XLA 2297c2aa98e2SPeter Wemm xla_create_file(); 229806f25ae9SGregory Neil Shapiro #endif /* XLA */ 229906f25ae9SGregory Neil Shapiro 230006f25ae9SGregory Neil Shapiro /* save daemon type in a macro for possible PidFile use */ 230140266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 230240266059SGregory Neil Shapiro macid("{daemon_info}"), dtype + 1); 230306f25ae9SGregory Neil Shapiro 230406f25ae9SGregory Neil Shapiro /* save queue interval in a macro for possible PidFile use */ 230540266059SGregory Neil Shapiro macdefine(&MainEnvelope.e_macro, A_TEMP, 230640266059SGregory Neil Shapiro macid("{queue_interval}"), pintvl(QueueIntvl, true)); 2307c2aa98e2SPeter Wemm 230840266059SGregory Neil Shapiro /* workaround: can't seem to release the signal in the parent */ 230940266059SGregory Neil Shapiro (void) sm_signal(SIGHUP, sighup); 231040266059SGregory Neil Shapiro (void) sm_releasesignal(SIGHUP); 231140266059SGregory Neil Shapiro (void) sm_signal(SIGTERM, sigterm); 231240266059SGregory Neil Shapiro 231306f25ae9SGregory Neil Shapiro if (QueueIntvl != 0) 2314c2aa98e2SPeter Wemm { 231540266059SGregory Neil Shapiro (void) runqueue(true, false, queuepersistent, true); 231640266059SGregory Neil Shapiro 231740266059SGregory Neil Shapiro /* 231840266059SGregory Neil Shapiro ** If queuepersistent but not in daemon mode then 231940266059SGregory Neil Shapiro ** we're going to do the queue runner monitoring here. 232040266059SGregory Neil Shapiro ** If in daemon mode then the monitoring will happen 232140266059SGregory Neil Shapiro ** elsewhere. 232240266059SGregory Neil Shapiro */ 232340266059SGregory Neil Shapiro 232440266059SGregory Neil Shapiro if (OpMode != MD_DAEMON && queuepersistent) 232540266059SGregory Neil Shapiro { 232640266059SGregory Neil Shapiro /* set the title to make it easier to find */ 232740266059SGregory Neil Shapiro sm_setproctitle(true, CurEnv, "Queue control"); 232840266059SGregory Neil Shapiro (void) sm_signal(SIGCHLD, SIG_DFL); 232940266059SGregory Neil Shapiro while (CurChildren > 0) 233040266059SGregory Neil Shapiro { 233140266059SGregory Neil Shapiro int status; 233240266059SGregory Neil Shapiro pid_t ret; 233340266059SGregory Neil Shapiro int group; 233440266059SGregory Neil Shapiro 233540266059SGregory Neil Shapiro if (ShutdownRequest != NULL) 233640266059SGregory Neil Shapiro shutdown_daemon(); 233740266059SGregory Neil Shapiro else if (RestartRequest != NULL) 233840266059SGregory Neil Shapiro restart_daemon(); 233940266059SGregory Neil Shapiro else if (RestartWorkGroup) 234040266059SGregory Neil Shapiro restart_marked_work_groups(); 234140266059SGregory Neil Shapiro 234240266059SGregory Neil Shapiro while ((ret = sm_wait(&status)) <= 0) 234340266059SGregory Neil Shapiro continue; 234440266059SGregory Neil Shapiro 234540266059SGregory Neil Shapiro if (WIFSTOPPED(status)) 234640266059SGregory Neil Shapiro continue; 234740266059SGregory Neil Shapiro 234840266059SGregory Neil Shapiro /* Probe only on a child status */ 234940266059SGregory Neil Shapiro proc_list_drop(ret, status, &group); 235040266059SGregory Neil Shapiro 235140266059SGregory Neil Shapiro if (WIFSIGNALED(status)) 235240266059SGregory Neil Shapiro { 235340266059SGregory Neil Shapiro if (WCOREDUMP(status)) 235440266059SGregory Neil Shapiro { 235540266059SGregory Neil Shapiro sm_syslog(LOG_ERR, NOQID, 235640266059SGregory Neil Shapiro "persistent queue runner=%d core dumped, signal=%d", 235740266059SGregory Neil Shapiro group, WTERMSIG(status)); 235840266059SGregory Neil Shapiro 235940266059SGregory Neil Shapiro /* don't restart this one */ 236040266059SGregory Neil Shapiro mark_work_group_restart(group, -1); 236140266059SGregory Neil Shapiro continue; 236240266059SGregory Neil Shapiro } 236340266059SGregory Neil Shapiro 236440266059SGregory Neil Shapiro sm_syslog(LOG_ERR, NOQID, 236540266059SGregory Neil Shapiro "persistent queue runner=%d died, signal=%d", 236640266059SGregory Neil Shapiro group, WTERMSIG(status)); 236740266059SGregory Neil Shapiro } 236840266059SGregory Neil Shapiro 236940266059SGregory Neil Shapiro /* 237040266059SGregory Neil Shapiro ** When debugging active, don't 237140266059SGregory Neil Shapiro ** restart the persistent queues. 237240266059SGregory Neil Shapiro ** But do log this as info. 237340266059SGregory Neil Shapiro */ 237440266059SGregory Neil Shapiro 237540266059SGregory Neil Shapiro if (sm_debug_active(&DebugNoPRestart, 237640266059SGregory Neil Shapiro 1)) 237740266059SGregory Neil Shapiro { 237840266059SGregory Neil Shapiro sm_syslog(LOG_DEBUG, NOQID, 237940266059SGregory Neil Shapiro "persistent queue runner=%d, exited", 238040266059SGregory Neil Shapiro group); 238140266059SGregory Neil Shapiro mark_work_group_restart(group, -1); 238240266059SGregory Neil Shapiro } 238340266059SGregory Neil Shapiro } 238440266059SGregory Neil Shapiro finis(true, true, ExitStat); 238540266059SGregory Neil Shapiro /* NOTREACHED */ 238640266059SGregory Neil Shapiro } 238740266059SGregory Neil Shapiro 2388c2aa98e2SPeter Wemm if (OpMode != MD_DAEMON) 2389c2aa98e2SPeter Wemm { 239040266059SGregory Neil Shapiro char qtype[200]; 239140266059SGregory Neil Shapiro 239240266059SGregory Neil Shapiro /* 239340266059SGregory Neil Shapiro ** Write the pid to file 239440266059SGregory Neil Shapiro ** XXX Overwrites sendmail.pid 239540266059SGregory Neil Shapiro */ 239640266059SGregory Neil Shapiro 239740266059SGregory Neil Shapiro log_sendmail_pid(&MainEnvelope); 239840266059SGregory Neil Shapiro 239940266059SGregory Neil Shapiro /* set the title to make it easier to find */ 240040266059SGregory Neil Shapiro qtype[0] = '\0'; 240140266059SGregory Neil Shapiro (void) sm_strlcpyn(qtype, sizeof qtype, 4, 240240266059SGregory Neil Shapiro "Queue runner@", 240340266059SGregory Neil Shapiro pintvl(QueueIntvl, true), 240440266059SGregory Neil Shapiro " for ", 240540266059SGregory Neil Shapiro QueueDir); 240640266059SGregory Neil Shapiro sm_setproctitle(true, CurEnv, qtype); 2407c2aa98e2SPeter Wemm for (;;) 2408c2aa98e2SPeter Wemm { 240906f25ae9SGregory Neil Shapiro (void) pause(); 24108774250cSGregory Neil Shapiro if (ShutdownRequest != NULL) 24118774250cSGregory Neil Shapiro shutdown_daemon(); 241240266059SGregory Neil Shapiro else if (RestartRequest != NULL) 241340266059SGregory Neil Shapiro restart_daemon(); 241440266059SGregory Neil Shapiro else if (RestartWorkGroup) 241540266059SGregory Neil Shapiro restart_marked_work_groups(); 2416c2aa98e2SPeter Wemm 241740266059SGregory Neil Shapiro if (doqueuerun()) 241840266059SGregory Neil Shapiro (void) runqueue(true, false, 241940266059SGregory Neil Shapiro false, false); 242040266059SGregory Neil Shapiro } 242140266059SGregory Neil Shapiro } 242240266059SGregory Neil Shapiro } 242340266059SGregory Neil Shapiro dropenvelope(&MainEnvelope, true, false); 242440266059SGregory Neil Shapiro 242506f25ae9SGregory Neil Shapiro #if STARTTLS 242606f25ae9SGregory Neil Shapiro /* init TLS for server, ignore result for now */ 242740266059SGregory Neil Shapiro (void) initsrvtls(tls_ok); 242806f25ae9SGregory Neil Shapiro #endif /* STARTTLS */ 242940266059SGregory Neil Shapiro #if PROFILING 243040266059SGregory Neil Shapiro nextreq: 243140266059SGregory Neil Shapiro #endif /* PROFILING */ 243240266059SGregory Neil Shapiro p_flags = getrequests(&MainEnvelope); 2433c2aa98e2SPeter Wemm 2434c2aa98e2SPeter Wemm /* drop privileges */ 243540266059SGregory Neil Shapiro (void) drop_privileges(false); 2436c2aa98e2SPeter Wemm 2437c2aa98e2SPeter Wemm /* 2438c2aa98e2SPeter Wemm ** Get authentication data 243940266059SGregory Neil Shapiro ** Set _ macro in BlankEnvelope before calling newenvelope(). 2440c2aa98e2SPeter Wemm */ 2441c2aa98e2SPeter Wemm 244240266059SGregory Neil Shapiro authinfo = getauthinfo(sm_io_getinfo(InChannel, SM_IO_WHAT_FD, 244340266059SGregory Neil Shapiro NULL), &forged); 244440266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, '_', authinfo); 244540266059SGregory Neil Shapiro 244640266059SGregory Neil Shapiro /* at this point we are in a child: reset state */ 244740266059SGregory Neil Shapiro sm_rpool_free(MainEnvelope.e_rpool); 244840266059SGregory Neil Shapiro (void) newenvelope(&MainEnvelope, &MainEnvelope, 244940266059SGregory Neil Shapiro sm_rpool_new_x(NULL)); 2450c2aa98e2SPeter Wemm } 2451c2aa98e2SPeter Wemm 245206f25ae9SGregory Neil Shapiro if (LogLevel > 9) 245306f25ae9SGregory Neil Shapiro { 245406f25ae9SGregory Neil Shapiro /* log connection information */ 245506f25ae9SGregory Neil Shapiro sm_syslog(LOG_INFO, NULL, "connect from %.100s", authinfo); 245606f25ae9SGregory Neil Shapiro } 245706f25ae9SGregory Neil Shapiro 2458c2aa98e2SPeter Wemm /* 2459c2aa98e2SPeter Wemm ** If running SMTP protocol, start collecting and executing 2460c2aa98e2SPeter Wemm ** commands. This will never return. 2461c2aa98e2SPeter Wemm */ 2462c2aa98e2SPeter Wemm 2463c2aa98e2SPeter Wemm if (OpMode == MD_SMTP || OpMode == MD_DAEMON) 2464c2aa98e2SPeter Wemm { 2465c2aa98e2SPeter Wemm char pbuf[20]; 2466c2aa98e2SPeter Wemm 2467c2aa98e2SPeter Wemm /* 2468c2aa98e2SPeter Wemm ** Save some macros for check_* rulesets. 2469c2aa98e2SPeter Wemm */ 2470c2aa98e2SPeter Wemm 2471c2aa98e2SPeter Wemm if (forged) 2472c2aa98e2SPeter Wemm { 2473c2aa98e2SPeter Wemm char ipbuf[103]; 2474c2aa98e2SPeter Wemm 247540266059SGregory Neil Shapiro (void) sm_snprintf(ipbuf, sizeof ipbuf, "[%.100s]", 247606f25ae9SGregory Neil Shapiro anynet_ntoa(&RealHostAddr)); 247740266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 247840266059SGregory Neil Shapiro macid("{client_name}"), ipbuf); 2479c2aa98e2SPeter Wemm } 2480c2aa98e2SPeter Wemm else 248140266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_PERM, 248240266059SGregory Neil Shapiro macid("{client_name}"), RealHostName); 248340266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 248440266059SGregory Neil Shapiro macid("{client_addr}"), anynet_ntoa(&RealHostAddr)); 248540266059SGregory Neil Shapiro sm_getla(); 2486c2aa98e2SPeter Wemm 248706f25ae9SGregory Neil Shapiro switch (RealHostAddr.sa.sa_family) 248806f25ae9SGregory Neil Shapiro { 248906f25ae9SGregory Neil Shapiro #if NETINET 249006f25ae9SGregory Neil Shapiro case AF_INET: 249140266059SGregory Neil Shapiro (void) sm_snprintf(pbuf, sizeof pbuf, "%d", 249206f25ae9SGregory Neil Shapiro RealHostAddr.sin.sin_port); 249306f25ae9SGregory Neil Shapiro break; 249406f25ae9SGregory Neil Shapiro #endif /* NETINET */ 249506f25ae9SGregory Neil Shapiro #if NETINET6 249606f25ae9SGregory Neil Shapiro case AF_INET6: 249740266059SGregory Neil Shapiro (void) sm_snprintf(pbuf, sizeof pbuf, "%d", 249806f25ae9SGregory Neil Shapiro RealHostAddr.sin6.sin6_port); 249906f25ae9SGregory Neil Shapiro break; 250006f25ae9SGregory Neil Shapiro #endif /* NETINET6 */ 250106f25ae9SGregory Neil Shapiro default: 250240266059SGregory Neil Shapiro (void) sm_snprintf(pbuf, sizeof pbuf, "0"); 250306f25ae9SGregory Neil Shapiro break; 250406f25ae9SGregory Neil Shapiro } 250540266059SGregory Neil Shapiro macdefine(&BlankEnvelope.e_macro, A_TEMP, 250640266059SGregory Neil Shapiro macid("{client_port}"), pbuf); 250706f25ae9SGregory Neil Shapiro 2508c2aa98e2SPeter Wemm if (OpMode == MD_DAEMON) 2509c2aa98e2SPeter Wemm { 2510c2aa98e2SPeter Wemm /* validate the connection */ 251140266059SGregory Neil Shapiro HoldErrs = true; 2512c2aa98e2SPeter Wemm nullserver = validate_connection(&RealHostAddr, 251340266059SGregory Neil Shapiro RealHostName, 251440266059SGregory Neil Shapiro &MainEnvelope); 251540266059SGregory Neil Shapiro HoldErrs = false; 2516c2aa98e2SPeter Wemm } 251706f25ae9SGregory Neil Shapiro else if (p_flags == NULL) 251806f25ae9SGregory Neil Shapiro { 251906f25ae9SGregory Neil Shapiro p_flags = (BITMAP256 *) xalloc(sizeof *p_flags); 252006f25ae9SGregory Neil Shapiro clrbitmap(p_flags); 252106f25ae9SGregory Neil Shapiro } 252206f25ae9SGregory Neil Shapiro #if STARTTLS 252306f25ae9SGregory Neil Shapiro if (OpMode == MD_SMTP) 252440266059SGregory Neil Shapiro (void) initsrvtls(tls_ok); 252506f25ae9SGregory Neil Shapiro #endif /* STARTTLS */ 2526193538b7SGregory Neil Shapiro 252740266059SGregory Neil Shapiro /* turn off profiling */ 252840266059SGregory Neil Shapiro SM_PROF(1); 252940266059SGregory Neil Shapiro smtp(nullserver, *p_flags, &MainEnvelope); 253040266059SGregory Neil Shapiro #if PROFILING 253140266059SGregory Neil Shapiro /* turn off profiling */ 253240266059SGregory Neil Shapiro SM_PROF(0); 253340266059SGregory Neil Shapiro if (OpMode == MD_DAEMON) 253440266059SGregory Neil Shapiro goto nextreq; 253540266059SGregory Neil Shapiro #endif /* PROFILING */ 2536c2aa98e2SPeter Wemm } 2537c2aa98e2SPeter Wemm 253840266059SGregory Neil Shapiro sm_rpool_free(MainEnvelope.e_rpool); 253940266059SGregory Neil Shapiro clearenvelope(&MainEnvelope, false, sm_rpool_new_x(NULL)); 2540c2aa98e2SPeter Wemm if (OpMode == MD_VERIFY) 2541c2aa98e2SPeter Wemm { 254240266059SGregory Neil Shapiro set_delivery_mode(SM_VERIFY, &MainEnvelope); 2543c2aa98e2SPeter Wemm PostMasterCopy = NULL; 2544c2aa98e2SPeter Wemm } 2545c2aa98e2SPeter Wemm else 2546c2aa98e2SPeter Wemm { 2547c2aa98e2SPeter Wemm /* interactive -- all errors are global */ 254840266059SGregory Neil Shapiro MainEnvelope.e_flags |= EF_GLOBALERRS|EF_LOGSENDER; 2549c2aa98e2SPeter Wemm } 2550c2aa98e2SPeter Wemm 2551c2aa98e2SPeter Wemm /* 2552c2aa98e2SPeter Wemm ** Do basic system initialization and set the sender 2553c2aa98e2SPeter Wemm */ 2554c2aa98e2SPeter Wemm 255540266059SGregory Neil Shapiro initsys(&MainEnvelope); 255640266059SGregory Neil Shapiro macdefine(&MainEnvelope.e_macro, A_PERM, macid("{ntries}"), "0"); 255740266059SGregory Neil Shapiro macdefine(&MainEnvelope.e_macro, A_PERM, macid("{nrcpts}"), "0"); 255840266059SGregory Neil Shapiro setsender(from, &MainEnvelope, NULL, '\0', false); 255906f25ae9SGregory Neil Shapiro if (warn_f_flag != '\0' && !wordinclass(RealUserName, 't') && 256040266059SGregory Neil Shapiro (!bitnset(M_LOCALMAILER, MainEnvelope.e_from.q_mailer->m_flags) || 256140266059SGregory Neil Shapiro strcmp(MainEnvelope.e_from.q_user, RealUserName) != 0)) 256206f25ae9SGregory Neil Shapiro { 256340266059SGregory Neil Shapiro auth_warning(&MainEnvelope, "%s set sender to %s using -%c", 2564c2aa98e2SPeter Wemm RealUserName, from, warn_f_flag); 256506f25ae9SGregory Neil Shapiro #if SASL 256640266059SGregory Neil Shapiro auth = false; 256706f25ae9SGregory Neil Shapiro #endif /* SASL */ 256806f25ae9SGregory Neil Shapiro } 256906f25ae9SGregory Neil Shapiro if (auth) 257006f25ae9SGregory Neil Shapiro { 257106f25ae9SGregory Neil Shapiro char *fv; 257206f25ae9SGregory Neil Shapiro 257306f25ae9SGregory Neil Shapiro /* set the initial sender for AUTH= to $f@$j */ 257440266059SGregory Neil Shapiro fv = macvalue('f', &MainEnvelope); 257506f25ae9SGregory Neil Shapiro if (fv == NULL || *fv == '\0') 257640266059SGregory Neil Shapiro MainEnvelope.e_auth_param = NULL; 257706f25ae9SGregory Neil Shapiro else 257806f25ae9SGregory Neil Shapiro { 257906f25ae9SGregory Neil Shapiro if (strchr(fv, '@') == NULL) 258006f25ae9SGregory Neil Shapiro { 258140266059SGregory Neil Shapiro i = strlen(fv) + strlen(macvalue('j', 258240266059SGregory Neil Shapiro &MainEnvelope)) + 2; 258340266059SGregory Neil Shapiro p = sm_malloc_x(i); 258440266059SGregory Neil Shapiro (void) sm_strlcpyn(p, i, 3, fv, "@", 258540266059SGregory Neil Shapiro macvalue('j', 258640266059SGregory Neil Shapiro &MainEnvelope)); 258706f25ae9SGregory Neil Shapiro } 258806f25ae9SGregory Neil Shapiro else 258940266059SGregory Neil Shapiro p = sm_strdup_x(fv); 259040266059SGregory Neil Shapiro MainEnvelope.e_auth_param = sm_rpool_strdup_x(MainEnvelope.e_rpool, 259140266059SGregory Neil Shapiro xtextify(p, "=")); 259240266059SGregory Neil Shapiro sm_free(p); /* XXX */ 259306f25ae9SGregory Neil Shapiro } 259406f25ae9SGregory Neil Shapiro } 259540266059SGregory Neil Shapiro if (macvalue('s', &MainEnvelope) == NULL) 259640266059SGregory Neil Shapiro macdefine(&MainEnvelope.e_macro, A_PERM, 's', RealHostName); 2597c2aa98e2SPeter Wemm 259840266059SGregory Neil Shapiro av = argv + optind; 2599c2aa98e2SPeter Wemm if (*av == NULL && !GrabTo) 2600c2aa98e2SPeter Wemm { 260140266059SGregory Neil Shapiro MainEnvelope.e_to = NULL; 260240266059SGregory Neil Shapiro MainEnvelope.e_flags |= EF_GLOBALERRS; 260340266059SGregory Neil Shapiro HoldErrs = false; 260440266059SGregory Neil Shapiro SuperSafe = SAFE_NO; 2605c2aa98e2SPeter Wemm usrerr("Recipient names must be specified"); 2606c2aa98e2SPeter Wemm 2607c2aa98e2SPeter Wemm /* collect body for UUCP return */ 2608c2aa98e2SPeter Wemm if (OpMode != MD_VERIFY) 260940266059SGregory Neil Shapiro collect(InChannel, false, NULL, &MainEnvelope); 261040266059SGregory Neil Shapiro finis(true, true, EX_USAGE); 261140266059SGregory Neil Shapiro /* NOTREACHED */ 2612c2aa98e2SPeter Wemm } 2613c2aa98e2SPeter Wemm 2614c2aa98e2SPeter Wemm /* 2615c2aa98e2SPeter Wemm ** Scan argv and deliver the message to everyone. 2616c2aa98e2SPeter Wemm */ 2617c2aa98e2SPeter Wemm 261840266059SGregory Neil Shapiro save_val = LogUsrErrs; 261940266059SGregory Neil Shapiro LogUsrErrs = true; 262040266059SGregory Neil Shapiro sendtoargv(av, &MainEnvelope); 262140266059SGregory Neil Shapiro LogUsrErrs = save_val; 2622c2aa98e2SPeter Wemm 2623c2aa98e2SPeter Wemm /* if we have had errors sofar, arrange a meaningful exit stat */ 2624c2aa98e2SPeter Wemm if (Errors > 0 && ExitStat == EX_OK) 2625c2aa98e2SPeter Wemm ExitStat = EX_USAGE; 2626c2aa98e2SPeter Wemm 2627c2aa98e2SPeter Wemm #if _FFR_FIX_DASHT 2628c2aa98e2SPeter Wemm /* 2629c2aa98e2SPeter Wemm ** If using -t, force not sending to argv recipients, even 2630c2aa98e2SPeter Wemm ** if they are mentioned in the headers. 2631c2aa98e2SPeter Wemm */ 2632c2aa98e2SPeter Wemm 2633c2aa98e2SPeter Wemm if (GrabTo) 2634c2aa98e2SPeter Wemm { 2635c2aa98e2SPeter Wemm ADDRESS *q; 2636c2aa98e2SPeter Wemm 263740266059SGregory Neil Shapiro for (q = MainEnvelope.e_sendqueue; q != NULL; q = q->q_next) 263806f25ae9SGregory Neil Shapiro q->q_state = QS_REMOVED; 2639c2aa98e2SPeter Wemm } 264006f25ae9SGregory Neil Shapiro #endif /* _FFR_FIX_DASHT */ 2641c2aa98e2SPeter Wemm 2642c2aa98e2SPeter Wemm /* 2643c2aa98e2SPeter Wemm ** Read the input mail. 2644c2aa98e2SPeter Wemm */ 2645c2aa98e2SPeter Wemm 264640266059SGregory Neil Shapiro MainEnvelope.e_to = NULL; 2647c2aa98e2SPeter Wemm if (OpMode != MD_VERIFY || GrabTo) 2648c2aa98e2SPeter Wemm { 264940266059SGregory Neil Shapiro int savederrors; 265040266059SGregory Neil Shapiro unsigned long savedflags; 2651c2aa98e2SPeter Wemm 265240266059SGregory Neil Shapiro /* 265340266059SGregory Neil Shapiro ** workaround for compiler warning on Irix: 265440266059SGregory Neil Shapiro ** do not initialize variable in the definition, but 265540266059SGregory Neil Shapiro ** later on: 265640266059SGregory Neil Shapiro ** warning(1548): transfer of control bypasses 265740266059SGregory Neil Shapiro ** initialization of: 265840266059SGregory Neil Shapiro ** variable "savederrors" (declared at line 2570) 265940266059SGregory Neil Shapiro ** variable "savedflags" (declared at line 2571) 266040266059SGregory Neil Shapiro ** goto giveup; 266140266059SGregory Neil Shapiro */ 266240266059SGregory Neil Shapiro 266340266059SGregory Neil Shapiro savederrors = Errors; 266440266059SGregory Neil Shapiro savedflags = MainEnvelope.e_flags & EF_FATALERRS; 266540266059SGregory Neil Shapiro MainEnvelope.e_flags |= EF_GLOBALERRS; 266640266059SGregory Neil Shapiro MainEnvelope.e_flags &= ~EF_FATALERRS; 266706f25ae9SGregory Neil Shapiro Errors = 0; 266806f25ae9SGregory Neil Shapiro buffer_errors(); 266940266059SGregory Neil Shapiro collect(InChannel, false, NULL, &MainEnvelope); 2670c2aa98e2SPeter Wemm 267106f25ae9SGregory Neil Shapiro /* header checks failed */ 267206f25ae9SGregory Neil Shapiro if (Errors > 0) 2673c2aa98e2SPeter Wemm { 267440266059SGregory Neil Shapiro giveup: 267540266059SGregory Neil Shapiro if (!GrabTo) 267640266059SGregory Neil Shapiro { 267706f25ae9SGregory Neil Shapiro /* Log who the mail would have gone to */ 267840266059SGregory Neil Shapiro logundelrcpts(&MainEnvelope, 267940266059SGregory Neil Shapiro MainEnvelope.e_message, 268040266059SGregory Neil Shapiro 8, false); 268106f25ae9SGregory Neil Shapiro } 268240266059SGregory Neil Shapiro flush_errors(true); 268340266059SGregory Neil Shapiro finis(true, true, ExitStat); 2684c2aa98e2SPeter Wemm /* NOTREACHED */ 2685c2aa98e2SPeter Wemm return -1; 2686c2aa98e2SPeter Wemm } 268706f25ae9SGregory Neil Shapiro 268806f25ae9SGregory Neil Shapiro /* bail out if message too large */ 268940266059SGregory Neil Shapiro if (bitset(EF_CLRQUEUE, MainEnvelope.e_flags)) 269006f25ae9SGregory Neil Shapiro { 269140266059SGregory Neil Shapiro finis(true, true, ExitStat != EX_OK ? ExitStat 269240266059SGregory Neil Shapiro : EX_DATAERR); 269306f25ae9SGregory Neil Shapiro /* NOTREACHED */ 269406f25ae9SGregory Neil Shapiro return -1; 269506f25ae9SGregory Neil Shapiro } 269606f25ae9SGregory Neil Shapiro Errors = savederrors; 269740266059SGregory Neil Shapiro MainEnvelope.e_flags |= savedflags; 2698c2aa98e2SPeter Wemm } 2699c2aa98e2SPeter Wemm errno = 0; 2700c2aa98e2SPeter Wemm 2701c2aa98e2SPeter Wemm if (tTd(1, 1)) 270240266059SGregory Neil Shapiro sm_dprintf("From person = \"%s\"\n", 270340266059SGregory Neil Shapiro MainEnvelope.e_from.q_paddr); 270440266059SGregory Neil Shapiro 270540266059SGregory Neil Shapiro #if _FFR_QUARANTINE 270640266059SGregory Neil Shapiro /* Check if quarantining stats should be updated */ 270740266059SGregory Neil Shapiro if (MainEnvelope.e_quarmsg != NULL) 270840266059SGregory Neil Shapiro markstats(&MainEnvelope, NULL, STATS_QUARANTINE); 270940266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */ 2710c2aa98e2SPeter Wemm 2711c2aa98e2SPeter Wemm /* 2712c2aa98e2SPeter Wemm ** Actually send everything. 2713c2aa98e2SPeter Wemm ** If verifying, just ack. 2714c2aa98e2SPeter Wemm */ 2715c2aa98e2SPeter Wemm 271640266059SGregory Neil Shapiro if (Errors == 0) 271740266059SGregory Neil Shapiro { 271840266059SGregory Neil Shapiro if (!split_by_recipient(&MainEnvelope) && 271940266059SGregory Neil Shapiro bitset(EF_FATALERRS, MainEnvelope.e_flags)) 272040266059SGregory Neil Shapiro goto giveup; 272140266059SGregory Neil Shapiro } 272240266059SGregory Neil Shapiro 272340266059SGregory Neil Shapiro /* make sure we deliver at least the first envelope */ 272440266059SGregory Neil Shapiro i = FastSplit > 0 ? 0 : -1; 272540266059SGregory Neil Shapiro for (e = &MainEnvelope; e != NULL; e = e->e_sibling, i++) 272640266059SGregory Neil Shapiro { 272740266059SGregory Neil Shapiro ENVELOPE *next; 272840266059SGregory Neil Shapiro 272940266059SGregory Neil Shapiro e->e_from.q_state = QS_SENDER; 2730c2aa98e2SPeter Wemm if (tTd(1, 5)) 2731c2aa98e2SPeter Wemm { 273240266059SGregory Neil Shapiro sm_dprintf("main[%d]: QS_SENDER ", i); 273340266059SGregory Neil Shapiro printaddr(&e->e_from, false); 2734c2aa98e2SPeter Wemm } 273540266059SGregory Neil Shapiro e->e_to = NULL; 273640266059SGregory Neil Shapiro sm_getla(); 273740266059SGregory Neil Shapiro GrabTo = false; 273806f25ae9SGregory Neil Shapiro #if NAMED_BIND 273906f25ae9SGregory Neil Shapiro _res.retry = TimeOuts.res_retry[RES_TO_FIRST]; 274006f25ae9SGregory Neil Shapiro _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST]; 274106f25ae9SGregory Neil Shapiro #endif /* NAMED_BIND */ 274240266059SGregory Neil Shapiro next = e->e_sibling; 274340266059SGregory Neil Shapiro e->e_sibling = NULL; 274440266059SGregory Neil Shapiro 274540266059SGregory Neil Shapiro /* after FastSplit envelopes: queue up */ 274640266059SGregory Neil Shapiro sendall(e, i >= FastSplit ? SM_QUEUE : SM_DEFAULT); 274740266059SGregory Neil Shapiro e->e_sibling = next; 274840266059SGregory Neil Shapiro } 2749c2aa98e2SPeter Wemm 2750c2aa98e2SPeter Wemm /* 2751c2aa98e2SPeter Wemm ** All done. 2752c2aa98e2SPeter Wemm ** Don't send return error message if in VERIFY mode. 2753c2aa98e2SPeter Wemm */ 2754c2aa98e2SPeter Wemm 275540266059SGregory Neil Shapiro finis(true, true, ExitStat); 2756c2aa98e2SPeter Wemm /* NOTREACHED */ 275706f25ae9SGregory Neil Shapiro return ExitStat; 2758c2aa98e2SPeter Wemm } 275940266059SGregory Neil Shapiro /* 27608774250cSGregory Neil Shapiro ** STOP_SENDMAIL -- Stop the running program 27618774250cSGregory Neil Shapiro ** 27628774250cSGregory Neil Shapiro ** Parameters: 27638774250cSGregory Neil Shapiro ** none. 27648774250cSGregory Neil Shapiro ** 27658774250cSGregory Neil Shapiro ** Returns: 27668774250cSGregory Neil Shapiro ** none. 27678774250cSGregory Neil Shapiro ** 27688774250cSGregory Neil Shapiro ** Side Effects: 27698774250cSGregory Neil Shapiro ** exits. 27708774250cSGregory Neil Shapiro */ 27718774250cSGregory Neil Shapiro 27728774250cSGregory Neil Shapiro void 27738774250cSGregory Neil Shapiro stop_sendmail() 27748774250cSGregory Neil Shapiro { 27758774250cSGregory Neil Shapiro /* reset uid for process accounting */ 27768774250cSGregory Neil Shapiro endpwent(); 27778774250cSGregory Neil Shapiro (void) setuid(RealUid); 27788774250cSGregory Neil Shapiro exit(EX_OK); 2779065a643dSPeter Wemm } 278040266059SGregory Neil Shapiro /* 278140266059SGregory Neil Shapiro ** FINIS -- Clean up and exit. 278240266059SGregory Neil Shapiro ** 278340266059SGregory Neil Shapiro ** Parameters: 278440266059SGregory Neil Shapiro ** drop -- whether or not to drop CurEnv envelope 278540266059SGregory Neil Shapiro ** cleanup -- call exit() or _exit()? 278640266059SGregory Neil Shapiro ** exitstat -- exit status to use for exit() call 278740266059SGregory Neil Shapiro ** 278840266059SGregory Neil Shapiro ** Returns: 278940266059SGregory Neil Shapiro ** never 279040266059SGregory Neil Shapiro ** 279140266059SGregory Neil Shapiro ** Side Effects: 279240266059SGregory Neil Shapiro ** exits sendmail 279340266059SGregory Neil Shapiro */ 2794c2aa98e2SPeter Wemm 279540266059SGregory Neil Shapiro void 279640266059SGregory Neil Shapiro finis(drop, cleanup, exitstat) 279740266059SGregory Neil Shapiro bool drop; 279840266059SGregory Neil Shapiro bool cleanup; 279940266059SGregory Neil Shapiro volatile int exitstat; 280040266059SGregory Neil Shapiro { 280140266059SGregory Neil Shapiro /* Still want to process new timeouts added below */ 280240266059SGregory Neil Shapiro sm_clear_events(); 280340266059SGregory Neil Shapiro (void) sm_releasesignal(SIGALRM); 280440266059SGregory Neil Shapiro 280540266059SGregory Neil Shapiro if (tTd(2, 1)) 280640266059SGregory Neil Shapiro { 280740266059SGregory Neil Shapiro sm_dprintf("\n====finis: stat %d e_id=%s e_flags=", 280840266059SGregory Neil Shapiro exitstat, 280940266059SGregory Neil Shapiro CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id); 281040266059SGregory Neil Shapiro printenvflags(CurEnv); 281140266059SGregory Neil Shapiro } 281240266059SGregory Neil Shapiro if (tTd(2, 9)) 281340266059SGregory Neil Shapiro printopenfds(false); 281440266059SGregory Neil Shapiro 281540266059SGregory Neil Shapiro SM_TRY 281640266059SGregory Neil Shapiro /* 281740266059SGregory Neil Shapiro ** Clean up. This might raise E:mta.quickabort 281840266059SGregory Neil Shapiro */ 281940266059SGregory Neil Shapiro 282040266059SGregory Neil Shapiro /* clean up temp files */ 282140266059SGregory Neil Shapiro CurEnv->e_to = NULL; 282240266059SGregory Neil Shapiro if (drop) 282340266059SGregory Neil Shapiro { 282440266059SGregory Neil Shapiro if (CurEnv->e_id != NULL) 282540266059SGregory Neil Shapiro { 282640266059SGregory Neil Shapiro dropenvelope(CurEnv, true, false); 282740266059SGregory Neil Shapiro sm_rpool_free(CurEnv->e_rpool); 282840266059SGregory Neil Shapiro CurEnv->e_rpool = NULL; 282940266059SGregory Neil Shapiro } 283040266059SGregory Neil Shapiro else 283140266059SGregory Neil Shapiro poststats(StatFile); 283240266059SGregory Neil Shapiro } 283340266059SGregory Neil Shapiro 283440266059SGregory Neil Shapiro /* flush any cached connections */ 283540266059SGregory Neil Shapiro mci_flush(true, NULL); 283640266059SGregory Neil Shapiro 283740266059SGregory Neil Shapiro /* close maps belonging to this pid */ 283840266059SGregory Neil Shapiro closemaps(false); 283940266059SGregory Neil Shapiro 284040266059SGregory Neil Shapiro #if USERDB 284140266059SGregory Neil Shapiro /* close UserDatabase */ 284240266059SGregory Neil Shapiro _udbx_close(); 284340266059SGregory Neil Shapiro #endif /* USERDB */ 284440266059SGregory Neil Shapiro 284540266059SGregory Neil Shapiro #if SASL 284640266059SGregory Neil Shapiro stop_sasl_client(); 284740266059SGregory Neil Shapiro #endif /* SASL */ 284840266059SGregory Neil Shapiro 284940266059SGregory Neil Shapiro #if XLA 285040266059SGregory Neil Shapiro /* clean up extended load average stuff */ 285140266059SGregory Neil Shapiro xla_all_end(); 285240266059SGregory Neil Shapiro #endif /* XLA */ 285340266059SGregory Neil Shapiro 285440266059SGregory Neil Shapiro SM_FINALLY 285540266059SGregory Neil Shapiro /* 285640266059SGregory Neil Shapiro ** And exit. 285740266059SGregory Neil Shapiro */ 285840266059SGregory Neil Shapiro 285940266059SGregory Neil Shapiro if (LogLevel > 78) 286040266059SGregory Neil Shapiro sm_syslog(LOG_DEBUG, CurEnv->e_id, "finis, pid=%d", 286140266059SGregory Neil Shapiro (int) CurrentPid); 286240266059SGregory Neil Shapiro if (exitstat == EX_TEMPFAIL || 286340266059SGregory Neil Shapiro CurEnv->e_errormode == EM_BERKNET) 286440266059SGregory Neil Shapiro exitstat = EX_OK; 286540266059SGregory Neil Shapiro 286640266059SGregory Neil Shapiro /* XXX clean up queues and related data structures */ 286740266059SGregory Neil Shapiro cleanup_queues(); 286840266059SGregory Neil Shapiro #if SM_CONF_SHM 286940266059SGregory Neil Shapiro cleanup_shm(DaemonPid == getpid()); 287040266059SGregory Neil Shapiro #endif /* SM_CONF_SHM */ 287140266059SGregory Neil Shapiro 287240266059SGregory Neil Shapiro /* reset uid for process accounting */ 287340266059SGregory Neil Shapiro endpwent(); 287440266059SGregory Neil Shapiro sm_mbdb_terminate(); 287540266059SGregory Neil Shapiro (void) setuid(RealUid); 287640266059SGregory Neil Shapiro #if SM_HEAP_CHECK 287740266059SGregory Neil Shapiro /* dump the heap, if we are checking for memory leaks */ 287840266059SGregory Neil Shapiro if (sm_debug_active(&SmHeapCheck, 2)) 287940266059SGregory Neil Shapiro sm_heap_report(smioout, 288040266059SGregory Neil Shapiro sm_debug_level(&SmHeapCheck) - 1); 288140266059SGregory Neil Shapiro #endif /* SM_HEAP_CHECK */ 288240266059SGregory Neil Shapiro if (sm_debug_active(&SmXtrapReport, 1)) 288340266059SGregory Neil Shapiro sm_dprintf("xtrap count = %d\n", SmXtrapCount); 288440266059SGregory Neil Shapiro if (cleanup) 288540266059SGregory Neil Shapiro exit(exitstat); 288640266059SGregory Neil Shapiro else 288740266059SGregory Neil Shapiro _exit(exitstat); 288840266059SGregory Neil Shapiro SM_END_TRY 288940266059SGregory Neil Shapiro } 289040266059SGregory Neil Shapiro /* 28918774250cSGregory Neil Shapiro ** INTINDEBUG -- signal handler for SIGINT in -bt mode 28928774250cSGregory Neil Shapiro ** 28938774250cSGregory Neil Shapiro ** Parameters: 28948774250cSGregory Neil Shapiro ** sig -- incoming signal. 28958774250cSGregory Neil Shapiro ** 28968774250cSGregory Neil Shapiro ** Returns: 28978774250cSGregory Neil Shapiro ** none. 28988774250cSGregory Neil Shapiro ** 28998774250cSGregory Neil Shapiro ** Side Effects: 29008774250cSGregory Neil Shapiro ** longjmps back to test mode loop. 29018774250cSGregory Neil Shapiro ** 29028774250cSGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 29038774250cSGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 29048774250cSGregory Neil Shapiro ** DOING. 29058774250cSGregory Neil Shapiro */ 29068774250cSGregory Neil Shapiro 290740266059SGregory Neil Shapiro /* Type of an exception generated on SIGINT during address test mode. */ 290840266059SGregory Neil Shapiro static const SM_EXC_TYPE_T EtypeInterrupt = 290940266059SGregory Neil Shapiro { 291040266059SGregory Neil Shapiro SmExcTypeMagic, 291140266059SGregory Neil Shapiro "S:mta.interrupt", 291240266059SGregory Neil Shapiro "", 291340266059SGregory Neil Shapiro sm_etype_printf, 291440266059SGregory Neil Shapiro "interrupt", 291540266059SGregory Neil Shapiro }; 291640266059SGregory Neil Shapiro 2917c2aa98e2SPeter Wemm /* ARGSUSED */ 29188774250cSGregory Neil Shapiro static SIGFUNC_DECL 2919c2aa98e2SPeter Wemm intindebug(sig) 2920c2aa98e2SPeter Wemm int sig; 2921c2aa98e2SPeter Wemm { 29228774250cSGregory Neil Shapiro int save_errno = errno; 29238774250cSGregory Neil Shapiro 29248774250cSGregory Neil Shapiro FIX_SYSV_SIGNAL(sig, intindebug); 29258774250cSGregory Neil Shapiro errno = save_errno; 29268774250cSGregory Neil Shapiro CHECK_CRITICAL(sig); 29278774250cSGregory Neil Shapiro errno = save_errno; 292840266059SGregory Neil Shapiro sm_exc_raisenew_x(&EtypeInterrupt); 292940266059SGregory Neil Shapiro errno = save_errno; 2930c2aa98e2SPeter Wemm return SIGFUNC_RETURN; 2931c2aa98e2SPeter Wemm } 293240266059SGregory Neil Shapiro /* 293340266059SGregory Neil Shapiro ** SIGTERM -- SIGTERM handler for the daemon 29348774250cSGregory Neil Shapiro ** 29358774250cSGregory Neil Shapiro ** Parameters: 29368774250cSGregory Neil Shapiro ** sig -- signal number. 29378774250cSGregory Neil Shapiro ** 29388774250cSGregory Neil Shapiro ** Returns: 29398774250cSGregory Neil Shapiro ** none. 29408774250cSGregory Neil Shapiro ** 29418774250cSGregory Neil Shapiro ** Side Effects: 29428774250cSGregory Neil Shapiro ** Sets ShutdownRequest which will hopefully trigger 29438774250cSGregory Neil Shapiro ** the daemon to exit. 29448774250cSGregory Neil Shapiro ** 29458774250cSGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 29468774250cSGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 29478774250cSGregory Neil Shapiro ** DOING. 29488774250cSGregory Neil Shapiro */ 29498774250cSGregory Neil Shapiro 29508774250cSGregory Neil Shapiro /* ARGSUSED */ 29518774250cSGregory Neil Shapiro static SIGFUNC_DECL 295240266059SGregory Neil Shapiro sigterm(sig) 29538774250cSGregory Neil Shapiro int sig; 29548774250cSGregory Neil Shapiro { 29558774250cSGregory Neil Shapiro int save_errno = errno; 29568774250cSGregory Neil Shapiro 295740266059SGregory Neil Shapiro FIX_SYSV_SIGNAL(sig, sigterm); 29588774250cSGregory Neil Shapiro ShutdownRequest = "signal"; 29598774250cSGregory Neil Shapiro errno = save_errno; 29608774250cSGregory Neil Shapiro return SIGFUNC_RETURN; 29618774250cSGregory Neil Shapiro } 296240266059SGregory Neil Shapiro /* 296340266059SGregory Neil Shapiro ** SIGHUP -- handle a SIGHUP signal 29648774250cSGregory Neil Shapiro ** 29658774250cSGregory Neil Shapiro ** Parameters: 296640266059SGregory Neil Shapiro ** sig -- incoming signal. 29678774250cSGregory Neil Shapiro ** 29688774250cSGregory Neil Shapiro ** Returns: 29698774250cSGregory Neil Shapiro ** none. 29708774250cSGregory Neil Shapiro ** 29718774250cSGregory Neil Shapiro ** Side Effects: 297240266059SGregory Neil Shapiro ** Sets RestartRequest which should cause the daemon 297340266059SGregory Neil Shapiro ** to restart. 297440266059SGregory Neil Shapiro ** 297540266059SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 297640266059SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 297740266059SGregory Neil Shapiro ** DOING. 29788774250cSGregory Neil Shapiro */ 29798774250cSGregory Neil Shapiro 298040266059SGregory Neil Shapiro /* ARGSUSED */ 298140266059SGregory Neil Shapiro static SIGFUNC_DECL 298240266059SGregory Neil Shapiro sighup(sig) 298340266059SGregory Neil Shapiro int sig; 29848774250cSGregory Neil Shapiro { 298540266059SGregory Neil Shapiro int save_errno = errno; 29868774250cSGregory Neil Shapiro 298740266059SGregory Neil Shapiro FIX_SYSV_SIGNAL(sig, sighup); 298840266059SGregory Neil Shapiro RestartRequest = "signal"; 298940266059SGregory Neil Shapiro errno = save_errno; 299040266059SGregory Neil Shapiro return SIGFUNC_RETURN; 29918774250cSGregory Neil Shapiro } 299240266059SGregory Neil Shapiro /* 299340266059SGregory Neil Shapiro ** SIGPIPE -- signal handler for SIGPIPE 299440266059SGregory Neil Shapiro ** 299540266059SGregory Neil Shapiro ** Parameters: 299640266059SGregory Neil Shapiro ** sig -- incoming signal. 299740266059SGregory Neil Shapiro ** 299840266059SGregory Neil Shapiro ** Returns: 299940266059SGregory Neil Shapiro ** none. 300040266059SGregory Neil Shapiro ** 300140266059SGregory Neil Shapiro ** Side Effects: 300240266059SGregory Neil Shapiro ** Sets StopRequest which should cause the mailq/hoststatus 300340266059SGregory Neil Shapiro ** display to stop. 300440266059SGregory Neil Shapiro ** 300540266059SGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 300640266059SGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 300740266059SGregory Neil Shapiro ** DOING. 300840266059SGregory Neil Shapiro */ 300940266059SGregory Neil Shapiro 301040266059SGregory Neil Shapiro /* ARGSUSED */ 301140266059SGregory Neil Shapiro static SIGFUNC_DECL 301240266059SGregory Neil Shapiro sigpipe(sig) 301340266059SGregory Neil Shapiro int sig; 301440266059SGregory Neil Shapiro { 301540266059SGregory Neil Shapiro int save_errno = errno; 301640266059SGregory Neil Shapiro 301740266059SGregory Neil Shapiro FIX_SYSV_SIGNAL(sig, sigpipe); 301840266059SGregory Neil Shapiro StopRequest = true; 301940266059SGregory Neil Shapiro errno = save_errno; 302040266059SGregory Neil Shapiro return SIGFUNC_RETURN; 302140266059SGregory Neil Shapiro } 302240266059SGregory Neil Shapiro /* 3023c2aa98e2SPeter Wemm ** INTSIG -- clean up on interrupt 3024c2aa98e2SPeter Wemm ** 302506f25ae9SGregory Neil Shapiro ** This just arranges to exit. It pessimizes in that it 3026c2aa98e2SPeter Wemm ** may resend a message. 3027c2aa98e2SPeter Wemm ** 3028c2aa98e2SPeter Wemm ** Parameters: 3029c2aa98e2SPeter Wemm ** none. 3030c2aa98e2SPeter Wemm ** 3031c2aa98e2SPeter Wemm ** Returns: 3032c2aa98e2SPeter Wemm ** none. 3033c2aa98e2SPeter Wemm ** 3034c2aa98e2SPeter Wemm ** Side Effects: 3035c2aa98e2SPeter Wemm ** Unlocks the current job. 30368774250cSGregory Neil Shapiro ** 30378774250cSGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 30388774250cSGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 30398774250cSGregory Neil Shapiro ** DOING. 30408774250cSGregory Neil Shapiro ** 30418774250cSGregory Neil Shapiro ** XXX: More work is needed for this signal handler. 3042c2aa98e2SPeter Wemm */ 3043c2aa98e2SPeter Wemm 3044c2aa98e2SPeter Wemm /* ARGSUSED */ 3045c2aa98e2SPeter Wemm SIGFUNC_DECL 3046c2aa98e2SPeter Wemm intsig(sig) 3047c2aa98e2SPeter Wemm int sig; 3048c2aa98e2SPeter Wemm { 304940266059SGregory Neil Shapiro bool drop = false; 30508774250cSGregory Neil Shapiro int save_errno = errno; 305106f25ae9SGregory Neil Shapiro 30528774250cSGregory Neil Shapiro FIX_SYSV_SIGNAL(sig, intsig); 30538774250cSGregory Neil Shapiro errno = save_errno; 30548774250cSGregory Neil Shapiro CHECK_CRITICAL(sig); 305540266059SGregory Neil Shapiro sm_allsignals(true); 305640266059SGregory Neil Shapiro 305706f25ae9SGregory Neil Shapiro if (sig != 0 && LogLevel > 79) 3058c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt"); 3059c2aa98e2SPeter Wemm FileName = NULL; 306006f25ae9SGregory Neil Shapiro 306106f25ae9SGregory Neil Shapiro /* Clean-up on aborted stdin message submission */ 306206f25ae9SGregory Neil Shapiro if (CurEnv->e_id != NULL && 306306f25ae9SGregory Neil Shapiro (OpMode == MD_SMTP || 306406f25ae9SGregory Neil Shapiro OpMode == MD_DELIVER || 306506f25ae9SGregory Neil Shapiro OpMode == MD_ARPAFTP)) 306606f25ae9SGregory Neil Shapiro { 306706f25ae9SGregory Neil Shapiro register ADDRESS *q; 306806f25ae9SGregory Neil Shapiro 306906f25ae9SGregory Neil Shapiro /* don't return an error indication */ 307006f25ae9SGregory Neil Shapiro CurEnv->e_to = NULL; 307106f25ae9SGregory Neil Shapiro CurEnv->e_flags &= ~EF_FATALERRS; 307206f25ae9SGregory Neil Shapiro CurEnv->e_flags |= EF_CLRQUEUE; 307306f25ae9SGregory Neil Shapiro 307406f25ae9SGregory Neil Shapiro /* 307506f25ae9SGregory Neil Shapiro ** Spin through the addresses and 307606f25ae9SGregory Neil Shapiro ** mark them dead to prevent bounces 307706f25ae9SGregory Neil Shapiro */ 307806f25ae9SGregory Neil Shapiro 307906f25ae9SGregory Neil Shapiro for (q = CurEnv->e_sendqueue; q != NULL; q = q->q_next) 308006f25ae9SGregory Neil Shapiro q->q_state = QS_DONTSEND; 308106f25ae9SGregory Neil Shapiro 308240266059SGregory Neil Shapiro drop = true; 308306f25ae9SGregory Neil Shapiro } 308413058a91SGregory Neil Shapiro else if (OpMode != MD_TEST) 308540266059SGregory Neil Shapiro { 308606f25ae9SGregory Neil Shapiro unlockqueue(CurEnv); 3087c2aa98e2SPeter Wemm } 3088c2aa98e2SPeter Wemm 308940266059SGregory Neil Shapiro finis(drop, false, EX_OK); 309040266059SGregory Neil Shapiro /* NOTREACHED */ 3091c2aa98e2SPeter Wemm } 309240266059SGregory Neil Shapiro /* 3093c2aa98e2SPeter Wemm ** DISCONNECT -- remove our connection with any foreground process 3094c2aa98e2SPeter Wemm ** 3095c2aa98e2SPeter Wemm ** Parameters: 3096c2aa98e2SPeter Wemm ** droplev -- how "deeply" we should drop the line. 3097c2aa98e2SPeter Wemm ** 0 -- ignore signals, mail back errors, make sure 3098c2aa98e2SPeter Wemm ** output goes to stdout. 309906f25ae9SGregory Neil Shapiro ** 1 -- also, make stdout go to /dev/null. 3100c2aa98e2SPeter Wemm ** 2 -- also, disconnect from controlling terminal 3101c2aa98e2SPeter Wemm ** (only for daemon mode). 3102c2aa98e2SPeter Wemm ** e -- the current envelope. 3103c2aa98e2SPeter Wemm ** 3104c2aa98e2SPeter Wemm ** Returns: 3105c2aa98e2SPeter Wemm ** none 3106c2aa98e2SPeter Wemm ** 3107c2aa98e2SPeter Wemm ** Side Effects: 3108c2aa98e2SPeter Wemm ** Trys to insure that we are immune to vagaries of 3109c2aa98e2SPeter Wemm ** the controlling tty. 3110c2aa98e2SPeter Wemm */ 3111c2aa98e2SPeter Wemm 3112c2aa98e2SPeter Wemm void 3113c2aa98e2SPeter Wemm disconnect(droplev, e) 3114c2aa98e2SPeter Wemm int droplev; 3115c2aa98e2SPeter Wemm register ENVELOPE *e; 3116c2aa98e2SPeter Wemm { 3117c2aa98e2SPeter Wemm int fd; 3118c2aa98e2SPeter Wemm 3119c2aa98e2SPeter Wemm if (tTd(52, 1)) 312040266059SGregory Neil Shapiro sm_dprintf("disconnect: In %d Out %d, e=%p\n", 312140266059SGregory Neil Shapiro sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL), 312240266059SGregory Neil Shapiro sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL), e); 3123c2aa98e2SPeter Wemm if (tTd(52, 100)) 3124c2aa98e2SPeter Wemm { 312540266059SGregory Neil Shapiro sm_dprintf("don't\n"); 3126c2aa98e2SPeter Wemm return; 3127c2aa98e2SPeter Wemm } 3128c2aa98e2SPeter Wemm if (LogLevel > 93) 3129c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, e->e_id, 3130c2aa98e2SPeter Wemm "disconnect level %d", 3131c2aa98e2SPeter Wemm droplev); 3132c2aa98e2SPeter Wemm 3133c2aa98e2SPeter Wemm /* be sure we don't get nasty signals */ 313440266059SGregory Neil Shapiro (void) sm_signal(SIGINT, SIG_IGN); 313540266059SGregory Neil Shapiro (void) sm_signal(SIGQUIT, SIG_IGN); 3136c2aa98e2SPeter Wemm 3137c2aa98e2SPeter Wemm /* we can't communicate with our caller, so.... */ 313840266059SGregory Neil Shapiro HoldErrs = true; 3139c2aa98e2SPeter Wemm CurEnv->e_errormode = EM_MAIL; 3140c2aa98e2SPeter Wemm Verbose = 0; 314140266059SGregory Neil Shapiro DisConnected = true; 3142c2aa98e2SPeter Wemm 3143c2aa98e2SPeter Wemm /* all input from /dev/null */ 314440266059SGregory Neil Shapiro if (InChannel != smioin) 3145c2aa98e2SPeter Wemm { 314640266059SGregory Neil Shapiro (void) sm_io_close(InChannel, SM_TIME_DEFAULT); 314740266059SGregory Neil Shapiro InChannel = smioin; 3148c2aa98e2SPeter Wemm } 314940266059SGregory Neil Shapiro if (sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, SM_PATH_DEVNULL, 315040266059SGregory Neil Shapiro SM_IO_RDONLY, NULL, smioin) == NULL) 3151c2aa98e2SPeter Wemm sm_syslog(LOG_ERR, e->e_id, 315240266059SGregory Neil Shapiro "disconnect: sm_io_reopen(\"%s\") failed: %s", 315340266059SGregory Neil Shapiro SM_PATH_DEVNULL, sm_errstring(errno)); 3154c2aa98e2SPeter Wemm 315540266059SGregory Neil Shapiro /* 315640266059SGregory Neil Shapiro ** output to the transcript 315740266059SGregory Neil Shapiro ** We also compare the fd numbers here since OutChannel 315840266059SGregory Neil Shapiro ** might be a layer on top of smioout due to encryption 315940266059SGregory Neil Shapiro ** (see sfsasl.c). 316040266059SGregory Neil Shapiro */ 316140266059SGregory Neil Shapiro 316240266059SGregory Neil Shapiro if (OutChannel != smioout && 316340266059SGregory Neil Shapiro sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL) != 316440266059SGregory Neil Shapiro sm_io_getinfo(smioout, SM_IO_WHAT_FD, NULL)) 3165c2aa98e2SPeter Wemm { 316640266059SGregory Neil Shapiro (void) sm_io_close(OutChannel, SM_TIME_DEFAULT); 316740266059SGregory Neil Shapiro OutChannel = smioout; 316840266059SGregory Neil Shapiro 316940266059SGregory Neil Shapiro #if 0 317040266059SGregory Neil Shapiro /* 317140266059SGregory Neil Shapiro ** Has smioout been closed? Reopen it. 317240266059SGregory Neil Shapiro ** This shouldn't happen anymore, the code is here 317340266059SGregory Neil Shapiro ** just as a reminder. 317440266059SGregory Neil Shapiro */ 317540266059SGregory Neil Shapiro 317640266059SGregory Neil Shapiro if (smioout->sm_magic == NULL && 317740266059SGregory Neil Shapiro sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, SM_PATH_DEVNULL, 317840266059SGregory Neil Shapiro SM_IO_WRONLY, NULL, smioout) == NULL) 317940266059SGregory Neil Shapiro sm_syslog(LOG_ERR, e->e_id, 318040266059SGregory Neil Shapiro "disconnect: sm_io_reopen(\"%s\") failed: %s", 318140266059SGregory Neil Shapiro SM_PATH_DEVNULL, sm_errstring(errno)); 318240266059SGregory Neil Shapiro #endif /* 0 */ 3183c2aa98e2SPeter Wemm } 3184c2aa98e2SPeter Wemm if (droplev > 0) 3185c2aa98e2SPeter Wemm { 318640266059SGregory Neil Shapiro fd = open(SM_PATH_DEVNULL, O_WRONLY, 0666); 3187c2aa98e2SPeter Wemm if (fd == -1) 3188c2aa98e2SPeter Wemm sm_syslog(LOG_ERR, e->e_id, 318940266059SGregory Neil Shapiro "disconnect: open(\"%s\") failed: %s", 319040266059SGregory Neil Shapiro SM_PATH_DEVNULL, sm_errstring(errno)); 319140266059SGregory Neil Shapiro (void) sm_io_flush(smioout, SM_TIME_DEFAULT); 319206f25ae9SGregory Neil Shapiro (void) dup2(fd, STDOUT_FILENO); 319306f25ae9SGregory Neil Shapiro (void) dup2(fd, STDERR_FILENO); 319406f25ae9SGregory Neil Shapiro (void) close(fd); 3195c2aa98e2SPeter Wemm } 3196c2aa98e2SPeter Wemm 3197c2aa98e2SPeter Wemm /* drop our controlling TTY completely if possible */ 3198c2aa98e2SPeter Wemm if (droplev > 1) 3199c2aa98e2SPeter Wemm { 3200c2aa98e2SPeter Wemm (void) setsid(); 3201c2aa98e2SPeter Wemm errno = 0; 3202c2aa98e2SPeter Wemm } 3203c2aa98e2SPeter Wemm 3204c2aa98e2SPeter Wemm #if XDEBUG 3205c2aa98e2SPeter Wemm checkfd012("disconnect"); 320606f25ae9SGregory Neil Shapiro #endif /* XDEBUG */ 3207c2aa98e2SPeter Wemm 3208c2aa98e2SPeter Wemm if (LogLevel > 71) 320940266059SGregory Neil Shapiro sm_syslog(LOG_DEBUG, e->e_id, "in background, pid=%d", 321040266059SGregory Neil Shapiro (int) CurrentPid); 3211c2aa98e2SPeter Wemm 3212c2aa98e2SPeter Wemm errno = 0; 3213c2aa98e2SPeter Wemm } 3214c2aa98e2SPeter Wemm 3215c2aa98e2SPeter Wemm static void 3216c2aa98e2SPeter Wemm obsolete(argv) 3217c2aa98e2SPeter Wemm char *argv[]; 3218c2aa98e2SPeter Wemm { 3219c2aa98e2SPeter Wemm register char *ap; 3220c2aa98e2SPeter Wemm register char *op; 3221c2aa98e2SPeter Wemm 3222c2aa98e2SPeter Wemm while ((ap = *++argv) != NULL) 3223c2aa98e2SPeter Wemm { 3224c2aa98e2SPeter Wemm /* Return if "--" or not an option of any form. */ 3225c2aa98e2SPeter Wemm if (ap[0] != '-' || ap[1] == '-') 3226c2aa98e2SPeter Wemm return; 3227c2aa98e2SPeter Wemm 322840266059SGregory Neil Shapiro #if _FFR_QUARANTINE 322940266059SGregory Neil Shapiro /* Don't allow users to use "-Q." or "-Q ." */ 323040266059SGregory Neil Shapiro if ((ap[1] == 'Q' && ap[2] == '.') || 323140266059SGregory Neil Shapiro (ap[1] == 'Q' && argv[1] != NULL && 323240266059SGregory Neil Shapiro argv[1][0] == '.' && argv[1][1] == '\0')) 323340266059SGregory Neil Shapiro { 323440266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 323540266059SGregory Neil Shapiro "Can not use -Q.\n"); 323640266059SGregory Neil Shapiro exit(EX_USAGE); 323740266059SGregory Neil Shapiro } 323840266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */ 323940266059SGregory Neil Shapiro 3240c2aa98e2SPeter Wemm /* skip over options that do have a value */ 3241c2aa98e2SPeter Wemm op = strchr(OPTIONS, ap[1]); 3242c2aa98e2SPeter Wemm if (op != NULL && *++op == ':' && ap[2] == '\0' && 3243c2aa98e2SPeter Wemm ap[1] != 'd' && 3244c2aa98e2SPeter Wemm #if defined(sony_news) 3245c2aa98e2SPeter Wemm ap[1] != 'E' && ap[1] != 'J' && 324606f25ae9SGregory Neil Shapiro #endif /* defined(sony_news) */ 3247c2aa98e2SPeter Wemm argv[1] != NULL && argv[1][0] != '-') 3248c2aa98e2SPeter Wemm { 3249c2aa98e2SPeter Wemm argv++; 3250c2aa98e2SPeter Wemm continue; 3251c2aa98e2SPeter Wemm } 3252c2aa98e2SPeter Wemm 3253c2aa98e2SPeter Wemm /* If -C doesn't have an argument, use sendmail.cf. */ 3254c2aa98e2SPeter Wemm #define __DEFPATH "sendmail.cf" 3255c2aa98e2SPeter Wemm if (ap[1] == 'C' && ap[2] == '\0') 3256c2aa98e2SPeter Wemm { 3257c2aa98e2SPeter Wemm *argv = xalloc(sizeof(__DEFPATH) + 2); 325840266059SGregory Neil Shapiro (void) sm_strlcpyn(argv[0], sizeof(__DEFPATH) + 2, 2, 325940266059SGregory Neil Shapiro "-C", __DEFPATH); 3260c2aa98e2SPeter Wemm } 3261c2aa98e2SPeter Wemm 3262c2aa98e2SPeter Wemm /* If -q doesn't have an argument, run it once. */ 3263c2aa98e2SPeter Wemm if (ap[1] == 'q' && ap[2] == '\0') 3264c2aa98e2SPeter Wemm *argv = "-q0"; 3265c2aa98e2SPeter Wemm 326640266059SGregory Neil Shapiro #if _FFR_QUARANTINE 326740266059SGregory Neil Shapiro /* If -Q doesn't have an argument, disable quarantining */ 326840266059SGregory Neil Shapiro if (ap[1] == 'Q' && ap[2] == '\0') 326940266059SGregory Neil Shapiro *argv = "-Q."; 327040266059SGregory Neil Shapiro #endif /* _FFR_QUARANTINE */ 327140266059SGregory Neil Shapiro 3272c2aa98e2SPeter Wemm /* if -d doesn't have an argument, use 0-99.1 */ 3273c2aa98e2SPeter Wemm if (ap[1] == 'd' && ap[2] == '\0') 3274c2aa98e2SPeter Wemm *argv = "-d0-99.1"; 3275c2aa98e2SPeter Wemm 3276c2aa98e2SPeter Wemm #if defined(sony_news) 3277c2aa98e2SPeter Wemm /* if -E doesn't have an argument, use -EC */ 3278c2aa98e2SPeter Wemm if (ap[1] == 'E' && ap[2] == '\0') 3279c2aa98e2SPeter Wemm *argv = "-EC"; 3280c2aa98e2SPeter Wemm 3281c2aa98e2SPeter Wemm /* if -J doesn't have an argument, use -JJ */ 3282c2aa98e2SPeter Wemm if (ap[1] == 'J' && ap[2] == '\0') 3283c2aa98e2SPeter Wemm *argv = "-JJ"; 328406f25ae9SGregory Neil Shapiro #endif /* defined(sony_news) */ 3285c2aa98e2SPeter Wemm } 3286c2aa98e2SPeter Wemm } 328740266059SGregory Neil Shapiro /* 3288c2aa98e2SPeter Wemm ** AUTH_WARNING -- specify authorization warning 3289c2aa98e2SPeter Wemm ** 3290c2aa98e2SPeter Wemm ** Parameters: 3291c2aa98e2SPeter Wemm ** e -- the current envelope. 3292c2aa98e2SPeter Wemm ** msg -- the text of the message. 3293c2aa98e2SPeter Wemm ** args -- arguments to the message. 3294c2aa98e2SPeter Wemm ** 3295c2aa98e2SPeter Wemm ** Returns: 3296c2aa98e2SPeter Wemm ** none. 3297c2aa98e2SPeter Wemm */ 3298c2aa98e2SPeter Wemm 3299c2aa98e2SPeter Wemm void 3300c2aa98e2SPeter Wemm #ifdef __STDC__ 3301c2aa98e2SPeter Wemm auth_warning(register ENVELOPE *e, const char *msg, ...) 330206f25ae9SGregory Neil Shapiro #else /* __STDC__ */ 3303c2aa98e2SPeter Wemm auth_warning(e, msg, va_alist) 3304c2aa98e2SPeter Wemm register ENVELOPE *e; 3305c2aa98e2SPeter Wemm const char *msg; 3306c2aa98e2SPeter Wemm va_dcl 330706f25ae9SGregory Neil Shapiro #endif /* __STDC__ */ 3308c2aa98e2SPeter Wemm { 3309c2aa98e2SPeter Wemm char buf[MAXLINE]; 331040266059SGregory Neil Shapiro SM_VA_LOCAL_DECL 3311c2aa98e2SPeter Wemm 3312c2aa98e2SPeter Wemm if (bitset(PRIV_AUTHWARNINGS, PrivacyFlags)) 3313c2aa98e2SPeter Wemm { 3314c2aa98e2SPeter Wemm register char *p; 3315c2aa98e2SPeter Wemm static char hostbuf[48]; 3316c2aa98e2SPeter Wemm 3317c2aa98e2SPeter Wemm if (hostbuf[0] == '\0') 3318193538b7SGregory Neil Shapiro { 3319193538b7SGregory Neil Shapiro struct hostent *hp; 3320193538b7SGregory Neil Shapiro 3321193538b7SGregory Neil Shapiro hp = myhostname(hostbuf, sizeof hostbuf); 332240266059SGregory Neil Shapiro #if NETINET6 3323193538b7SGregory Neil Shapiro if (hp != NULL) 3324193538b7SGregory Neil Shapiro { 3325193538b7SGregory Neil Shapiro freehostent(hp); 3326193538b7SGregory Neil Shapiro hp = NULL; 3327193538b7SGregory Neil Shapiro } 332840266059SGregory Neil Shapiro #endif /* NETINET6 */ 3329193538b7SGregory Neil Shapiro } 3330c2aa98e2SPeter Wemm 333140266059SGregory Neil Shapiro (void) sm_strlcpyn(buf, sizeof buf, 2, hostbuf, ": "); 3332c2aa98e2SPeter Wemm p = &buf[strlen(buf)]; 333340266059SGregory Neil Shapiro SM_VA_START(ap, msg); 333440266059SGregory Neil Shapiro (void) sm_vsnprintf(p, SPACELEFT(buf, p), msg, ap); 333540266059SGregory Neil Shapiro SM_VA_END(ap); 333640266059SGregory Neil Shapiro addheader("X-Authentication-Warning", buf, 0, e); 3337c2aa98e2SPeter Wemm if (LogLevel > 3) 3338c2aa98e2SPeter Wemm sm_syslog(LOG_INFO, e->e_id, 3339c2aa98e2SPeter Wemm "Authentication-Warning: %.400s", 3340c2aa98e2SPeter Wemm buf); 3341c2aa98e2SPeter Wemm } 3342c2aa98e2SPeter Wemm } 334340266059SGregory Neil Shapiro /* 3344c2aa98e2SPeter Wemm ** GETEXTENV -- get from external environment 3345c2aa98e2SPeter Wemm ** 3346c2aa98e2SPeter Wemm ** Parameters: 3347c2aa98e2SPeter Wemm ** envar -- the name of the variable to retrieve 3348c2aa98e2SPeter Wemm ** 3349c2aa98e2SPeter Wemm ** Returns: 3350c2aa98e2SPeter Wemm ** The value, if any. 3351c2aa98e2SPeter Wemm */ 3352c2aa98e2SPeter Wemm 335340266059SGregory Neil Shapiro static char * 3354c2aa98e2SPeter Wemm getextenv(envar) 3355c2aa98e2SPeter Wemm const char *envar; 3356c2aa98e2SPeter Wemm { 3357c2aa98e2SPeter Wemm char **envp; 3358c2aa98e2SPeter Wemm int l; 3359c2aa98e2SPeter Wemm 3360c2aa98e2SPeter Wemm l = strlen(envar); 3361c2aa98e2SPeter Wemm for (envp = ExternalEnviron; *envp != NULL; envp++) 3362c2aa98e2SPeter Wemm { 3363c2aa98e2SPeter Wemm if (strncmp(*envp, envar, l) == 0 && (*envp)[l] == '=') 3364c2aa98e2SPeter Wemm return &(*envp)[l + 1]; 3365c2aa98e2SPeter Wemm } 3366c2aa98e2SPeter Wemm return NULL; 3367c2aa98e2SPeter Wemm } 336840266059SGregory Neil Shapiro /* 336940266059SGregory Neil Shapiro ** SETUSERENV -- set an environment in the propagated environment 3370c2aa98e2SPeter Wemm ** 3371c2aa98e2SPeter Wemm ** Parameters: 3372c2aa98e2SPeter Wemm ** envar -- the name of the environment variable. 3373c2aa98e2SPeter Wemm ** value -- the value to which it should be set. If 3374c2aa98e2SPeter Wemm ** null, this is extracted from the incoming 3375c2aa98e2SPeter Wemm ** environment. If that is not set, the call 3376c2aa98e2SPeter Wemm ** to setuserenv is ignored. 3377c2aa98e2SPeter Wemm ** 3378c2aa98e2SPeter Wemm ** Returns: 3379c2aa98e2SPeter Wemm ** none. 3380c2aa98e2SPeter Wemm */ 3381c2aa98e2SPeter Wemm 3382c2aa98e2SPeter Wemm void 3383c2aa98e2SPeter Wemm setuserenv(envar, value) 3384c2aa98e2SPeter Wemm const char *envar; 3385c2aa98e2SPeter Wemm const char *value; 3386c2aa98e2SPeter Wemm { 338706f25ae9SGregory Neil Shapiro int i, l; 3388c2aa98e2SPeter Wemm char **evp = UserEnviron; 3389c2aa98e2SPeter Wemm char *p; 3390c2aa98e2SPeter Wemm 3391c2aa98e2SPeter Wemm if (value == NULL) 3392c2aa98e2SPeter Wemm { 3393c2aa98e2SPeter Wemm value = getextenv(envar); 3394c2aa98e2SPeter Wemm if (value == NULL) 3395c2aa98e2SPeter Wemm return; 3396c2aa98e2SPeter Wemm } 3397c2aa98e2SPeter Wemm 339840266059SGregory Neil Shapiro /* XXX enforce reasonable size? */ 339906f25ae9SGregory Neil Shapiro i = strlen(envar) + 1; 340006f25ae9SGregory Neil Shapiro l = strlen(value) + i + 1; 340106f25ae9SGregory Neil Shapiro p = (char *) xalloc(l); 340240266059SGregory Neil Shapiro (void) sm_strlcpyn(p, l, 3, envar, "=", value); 3403c2aa98e2SPeter Wemm 3404c2aa98e2SPeter Wemm while (*evp != NULL && strncmp(*evp, p, i) != 0) 3405c2aa98e2SPeter Wemm evp++; 3406c2aa98e2SPeter Wemm if (*evp != NULL) 3407c2aa98e2SPeter Wemm { 3408c2aa98e2SPeter Wemm *evp++ = p; 3409c2aa98e2SPeter Wemm } 3410c2aa98e2SPeter Wemm else if (evp < &UserEnviron[MAXUSERENVIRON]) 3411c2aa98e2SPeter Wemm { 3412c2aa98e2SPeter Wemm *evp++ = p; 3413c2aa98e2SPeter Wemm *evp = NULL; 3414c2aa98e2SPeter Wemm } 3415c2aa98e2SPeter Wemm 3416c2aa98e2SPeter Wemm /* make sure it is in our environment as well */ 3417c2aa98e2SPeter Wemm if (putenv(p) < 0) 3418c2aa98e2SPeter Wemm syserr("setuserenv: putenv(%s) failed", p); 3419c2aa98e2SPeter Wemm } 342040266059SGregory Neil Shapiro /* 3421c2aa98e2SPeter Wemm ** DUMPSTATE -- dump state 3422c2aa98e2SPeter Wemm ** 3423c2aa98e2SPeter Wemm ** For debugging. 3424c2aa98e2SPeter Wemm */ 3425c2aa98e2SPeter Wemm 3426c2aa98e2SPeter Wemm void 3427c2aa98e2SPeter Wemm dumpstate(when) 3428c2aa98e2SPeter Wemm char *when; 3429c2aa98e2SPeter Wemm { 3430c2aa98e2SPeter Wemm register char *j = macvalue('j', CurEnv); 3431c2aa98e2SPeter Wemm int rs; 343206f25ae9SGregory Neil Shapiro extern int NextMacroId; 3433c2aa98e2SPeter Wemm 3434c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 3435c2aa98e2SPeter Wemm "--- dumping state on %s: $j = %s ---", 3436c2aa98e2SPeter Wemm when, 3437c2aa98e2SPeter Wemm j == NULL ? "<NULL>" : j); 3438c2aa98e2SPeter Wemm if (j != NULL) 3439c2aa98e2SPeter Wemm { 3440c2aa98e2SPeter Wemm if (!wordinclass(j, 'w')) 3441c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 3442c2aa98e2SPeter Wemm "*** $j not in $=w ***"); 3443c2aa98e2SPeter Wemm } 3444c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, "CurChildren = %d", CurChildren); 344540266059SGregory Neil Shapiro sm_syslog(LOG_DEBUG, CurEnv->e_id, "NextMacroId = %d (Max %d)", 344606f25ae9SGregory Neil Shapiro NextMacroId, MAXMACROID); 3447c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- open file descriptors: ---"); 344840266059SGregory Neil Shapiro printopenfds(true); 3449c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- connection cache: ---"); 345040266059SGregory Neil Shapiro mci_dump_all(true); 3451c2aa98e2SPeter Wemm rs = strtorwset("debug_dumpstate", NULL, ST_FIND); 3452c2aa98e2SPeter Wemm if (rs > 0) 3453c2aa98e2SPeter Wemm { 345406f25ae9SGregory Neil Shapiro int status; 3455c2aa98e2SPeter Wemm register char **pvp; 3456c2aa98e2SPeter Wemm char *pv[MAXATOM + 1]; 3457c2aa98e2SPeter Wemm 3458c2aa98e2SPeter Wemm pv[0] = NULL; 345940266059SGregory Neil Shapiro status = REWRITE(pv, rs, CurEnv); 3460c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, 3461c2aa98e2SPeter Wemm "--- ruleset debug_dumpstate returns stat %d, pv: ---", 346206f25ae9SGregory Neil Shapiro status); 3463c2aa98e2SPeter Wemm for (pvp = pv; *pvp != NULL; pvp++) 3464c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, "%s", *pvp); 3465c2aa98e2SPeter Wemm } 3466c2aa98e2SPeter Wemm sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- end of state dump ---"); 3467c2aa98e2SPeter Wemm } 346840266059SGregory Neil Shapiro 346913058a91SGregory Neil Shapiro #ifdef SIGUSR1 347040266059SGregory Neil Shapiro /* 34718774250cSGregory Neil Shapiro ** SIGUSR1 -- Signal a request to dump state. 34728774250cSGregory Neil Shapiro ** 34738774250cSGregory Neil Shapiro ** Parameters: 34748774250cSGregory Neil Shapiro ** sig -- calling signal. 34758774250cSGregory Neil Shapiro ** 34768774250cSGregory Neil Shapiro ** Returns: 34778774250cSGregory Neil Shapiro ** none. 34788774250cSGregory Neil Shapiro ** 34798774250cSGregory Neil Shapiro ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 34808774250cSGregory Neil Shapiro ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 34818774250cSGregory Neil Shapiro ** DOING. 34828774250cSGregory Neil Shapiro ** 34838774250cSGregory Neil Shapiro ** XXX: More work is needed for this signal handler. 34848774250cSGregory Neil Shapiro */ 3485c2aa98e2SPeter Wemm 3486c2aa98e2SPeter Wemm /* ARGSUSED */ 34878774250cSGregory Neil Shapiro static SIGFUNC_DECL 3488c2aa98e2SPeter Wemm sigusr1(sig) 3489c2aa98e2SPeter Wemm int sig; 3490c2aa98e2SPeter Wemm { 34918774250cSGregory Neil Shapiro int save_errno = errno; 349240266059SGregory Neil Shapiro # if SM_HEAP_CHECK 349340266059SGregory Neil Shapiro extern void dumpstab __P((void)); 349440266059SGregory Neil Shapiro # endif /* SM_HEAP_CHECK */ 34958774250cSGregory Neil Shapiro 34968774250cSGregory Neil Shapiro FIX_SYSV_SIGNAL(sig, sigusr1); 34978774250cSGregory Neil Shapiro errno = save_errno; 34988774250cSGregory Neil Shapiro CHECK_CRITICAL(sig); 3499c2aa98e2SPeter Wemm dumpstate("user signal"); 350040266059SGregory Neil Shapiro # if SM_HEAP_CHECK 350140266059SGregory Neil Shapiro dumpstab(); 350240266059SGregory Neil Shapiro # endif /* SM_HEAP_CHECK */ 35038774250cSGregory Neil Shapiro errno = save_errno; 3504c2aa98e2SPeter Wemm return SIGFUNC_RETURN; 3505c2aa98e2SPeter Wemm } 350613058a91SGregory Neil Shapiro #endif /* SIGUSR1 */ 350740266059SGregory Neil Shapiro 350840266059SGregory Neil Shapiro /* 3509c2aa98e2SPeter Wemm ** DROP_PRIVILEGES -- reduce privileges to those of the RunAsUser option 3510c2aa98e2SPeter Wemm ** 3511c2aa98e2SPeter Wemm ** Parameters: 3512c2aa98e2SPeter Wemm ** to_real_uid -- if set, drop to the real uid instead 3513c2aa98e2SPeter Wemm ** of the RunAsUser. 3514c2aa98e2SPeter Wemm ** 3515c2aa98e2SPeter Wemm ** Returns: 3516c2aa98e2SPeter Wemm ** EX_OSERR if the setuid failed. 3517c2aa98e2SPeter Wemm ** EX_OK otherwise. 3518c2aa98e2SPeter Wemm */ 3519c2aa98e2SPeter Wemm 3520c2aa98e2SPeter Wemm int 3521c2aa98e2SPeter Wemm drop_privileges(to_real_uid) 3522c2aa98e2SPeter Wemm bool to_real_uid; 3523c2aa98e2SPeter Wemm { 3524c2aa98e2SPeter Wemm int rval = EX_OK; 3525c2aa98e2SPeter Wemm GIDSET_T emptygidset[1]; 3526c2aa98e2SPeter Wemm 3527c2aa98e2SPeter Wemm if (tTd(47, 1)) 352840266059SGregory Neil Shapiro sm_dprintf("drop_privileges(%d): Real[UG]id=%d:%d, get[ug]id=%d:%d, gete[ug]id=%d:%d, RunAs[UG]id=%d:%d\n", 352940266059SGregory Neil Shapiro (int) to_real_uid, 353040266059SGregory Neil Shapiro (int) RealUid, (int) RealGid, 353140266059SGregory Neil Shapiro (int) getuid(), (int) getgid(), 353240266059SGregory Neil Shapiro (int) geteuid(), (int) getegid(), 353340266059SGregory Neil Shapiro (int) RunAsUid, (int) RunAsGid); 3534c2aa98e2SPeter Wemm 3535c2aa98e2SPeter Wemm if (to_real_uid) 3536c2aa98e2SPeter Wemm { 3537c2aa98e2SPeter Wemm RunAsUserName = RealUserName; 3538c2aa98e2SPeter Wemm RunAsUid = RealUid; 3539c2aa98e2SPeter Wemm RunAsGid = RealGid; 3540c2aa98e2SPeter Wemm } 3541c2aa98e2SPeter Wemm 3542c2aa98e2SPeter Wemm /* make sure no one can grab open descriptors for secret files */ 3543c2aa98e2SPeter Wemm endpwent(); 354440266059SGregory Neil Shapiro sm_mbdb_terminate(); 3545c2aa98e2SPeter Wemm 3546c2aa98e2SPeter Wemm /* reset group permissions; these can be set later */ 3547c2aa98e2SPeter Wemm emptygidset[0] = (to_real_uid || RunAsGid != 0) ? RunAsGid : getegid(); 354840266059SGregory Neil Shapiro 354940266059SGregory Neil Shapiro /* 355040266059SGregory Neil Shapiro ** Notice: on some OS (Linux...) the setgroups() call causes 355140266059SGregory Neil Shapiro ** a logfile entry if sendmail is not run by root. 355240266059SGregory Neil Shapiro ** However, it is unclear (no POSIX standard) whether 355340266059SGregory Neil Shapiro ** setgroups() can only succeed if executed by root. 355440266059SGregory Neil Shapiro ** So for now we keep it as it is; if you want to change it, use 355540266059SGregory Neil Shapiro ** if (geteuid() == 0 && setgroups(1, emptygidset) == -1) 355640266059SGregory Neil Shapiro */ 355740266059SGregory Neil Shapiro 3558c2aa98e2SPeter Wemm if (setgroups(1, emptygidset) == -1 && geteuid() == 0) 355906f25ae9SGregory Neil Shapiro { 356006f25ae9SGregory Neil Shapiro syserr("drop_privileges: setgroups(1, %d) failed", 356106f25ae9SGregory Neil Shapiro (int) emptygidset[0]); 3562c2aa98e2SPeter Wemm rval = EX_OSERR; 356306f25ae9SGregory Neil Shapiro } 3564c2aa98e2SPeter Wemm 356540266059SGregory Neil Shapiro /* reset primary group id */ 356640266059SGregory Neil Shapiro if (to_real_uid) 356706f25ae9SGregory Neil Shapiro { 356840266059SGregory Neil Shapiro /* 356940266059SGregory Neil Shapiro ** Drop gid to real gid. 357040266059SGregory Neil Shapiro ** On some OS we must reset the effective[/real[/saved]] gid, 357140266059SGregory Neil Shapiro ** and then use setgid() to finally drop all group privileges. 357240266059SGregory Neil Shapiro ** Later on we check whether we can get back the 357340266059SGregory Neil Shapiro ** effective gid. 357440266059SGregory Neil Shapiro */ 357540266059SGregory Neil Shapiro 357640266059SGregory Neil Shapiro #if HASSETEGID 357740266059SGregory Neil Shapiro if (setegid(RunAsGid) < 0) 357840266059SGregory Neil Shapiro { 357940266059SGregory Neil Shapiro syserr("drop_privileges: setegid(%d) failed", 358040266059SGregory Neil Shapiro (int) RunAsGid); 3581c2aa98e2SPeter Wemm rval = EX_OSERR; 358206f25ae9SGregory Neil Shapiro } 358340266059SGregory Neil Shapiro #else /* HASSETEGID */ 358440266059SGregory Neil Shapiro # if HASSETREGID 358540266059SGregory Neil Shapiro if (setregid(RunAsGid, RunAsGid) < 0) 358640266059SGregory Neil Shapiro { 358740266059SGregory Neil Shapiro syserr("drop_privileges: setregid(%d, %d) failed", 358840266059SGregory Neil Shapiro (int) RunAsGid, (int) RunAsGid); 358940266059SGregory Neil Shapiro rval = EX_OSERR; 359040266059SGregory Neil Shapiro } 359140266059SGregory Neil Shapiro # else /* HASSETREGID */ 359240266059SGregory Neil Shapiro # if HASSETRESGID 359340266059SGregory Neil Shapiro if (setresgid(RunAsGid, RunAsGid, RunAsGid) < 0) 359440266059SGregory Neil Shapiro { 359540266059SGregory Neil Shapiro syserr("drop_privileges: setresgid(%d, %d, %d) failed", 359640266059SGregory Neil Shapiro (int) RunAsGid, (int) RunAsGid, (int) RunAsGid); 359740266059SGregory Neil Shapiro rval = EX_OSERR; 359840266059SGregory Neil Shapiro } 359940266059SGregory Neil Shapiro # endif /* HASSETRESGID */ 360040266059SGregory Neil Shapiro # endif /* HASSETREGID */ 360140266059SGregory Neil Shapiro #endif /* HASSETEGID */ 360240266059SGregory Neil Shapiro } 360340266059SGregory Neil Shapiro if (rval == EX_OK && (to_real_uid || RunAsGid != 0)) 360440266059SGregory Neil Shapiro { 360540266059SGregory Neil Shapiro if (setgid(RunAsGid) < 0 && (!UseMSP || getegid() != RunAsGid)) 360640266059SGregory Neil Shapiro { 360740266059SGregory Neil Shapiro syserr("drop_privileges: setgid(%d) failed", 360840266059SGregory Neil Shapiro (int) RunAsGid); 360940266059SGregory Neil Shapiro rval = EX_OSERR; 361040266059SGregory Neil Shapiro } 361140266059SGregory Neil Shapiro errno = 0; 361240266059SGregory Neil Shapiro if (rval == EX_OK && getegid() != RunAsGid) 361340266059SGregory Neil Shapiro { 361440266059SGregory Neil Shapiro syserr("drop_privileges: Unable to set effective gid=%d to RunAsGid=%d", 361540266059SGregory Neil Shapiro (int) getegid(), (int) RunAsGid); 361640266059SGregory Neil Shapiro rval = EX_OSERR; 361740266059SGregory Neil Shapiro } 361840266059SGregory Neil Shapiro } 361940266059SGregory Neil Shapiro 362040266059SGregory Neil Shapiro /* fiddle with uid */ 362106f25ae9SGregory Neil Shapiro if (to_real_uid || RunAsUid != 0) 362206f25ae9SGregory Neil Shapiro { 362306f25ae9SGregory Neil Shapiro uid_t euid = geteuid(); 362406f25ae9SGregory Neil Shapiro 362540266059SGregory Neil Shapiro /* 362640266059SGregory Neil Shapiro ** Try to setuid(RunAsUid). 362740266059SGregory Neil Shapiro ** euid must be RunAsUid, 362840266059SGregory Neil Shapiro ** ruid must be RunAsUid unless it's the MSP and the euid 362940266059SGregory Neil Shapiro ** wasn't 0 and we didn't have to drop privileges to the 363040266059SGregory Neil Shapiro ** real uid. 363140266059SGregory Neil Shapiro */ 363240266059SGregory Neil Shapiro 363340266059SGregory Neil Shapiro if (setuid(RunAsUid) < 0 || 363440266059SGregory Neil Shapiro (getuid() != RunAsUid && 363540266059SGregory Neil Shapiro (!UseMSP || euid == 0 || to_real_uid )) || 363640266059SGregory Neil Shapiro geteuid() != RunAsUid) 363740266059SGregory Neil Shapiro { 363840266059SGregory Neil Shapiro #if HASSETREUID 363940266059SGregory Neil Shapiro /* 364040266059SGregory Neil Shapiro ** if ruid != RunAsUid, euid == RunAsUid, then 364140266059SGregory Neil Shapiro ** try resetting just the real uid, then using 364240266059SGregory Neil Shapiro ** setuid() to drop the saved-uid as well. 364340266059SGregory Neil Shapiro */ 364440266059SGregory Neil Shapiro 364540266059SGregory Neil Shapiro if (euid == RunAsUid) 364640266059SGregory Neil Shapiro { 364740266059SGregory Neil Shapiro if (setreuid(RunAsUid, -1) < 0) 364840266059SGregory Neil Shapiro { 364940266059SGregory Neil Shapiro syserr("drop_privileges: setreuid(%d, -1) failed", 365040266059SGregory Neil Shapiro (int) RunAsUid); 365140266059SGregory Neil Shapiro rval = EX_OSERR; 365240266059SGregory Neil Shapiro } 365306f25ae9SGregory Neil Shapiro if (setuid(RunAsUid) < 0) 365406f25ae9SGregory Neil Shapiro { 365540266059SGregory Neil Shapiro syserr("drop_privileges: second setuid(%d) attempt failed", 365640266059SGregory Neil Shapiro (int) RunAsUid); 365740266059SGregory Neil Shapiro rval = EX_OSERR; 365840266059SGregory Neil Shapiro } 365940266059SGregory Neil Shapiro } 366040266059SGregory Neil Shapiro else 366140266059SGregory Neil Shapiro #endif /* HASSETREUID */ 366240266059SGregory Neil Shapiro { 366306f25ae9SGregory Neil Shapiro syserr("drop_privileges: setuid(%d) failed", 366406f25ae9SGregory Neil Shapiro (int) RunAsUid); 3665c2aa98e2SPeter Wemm rval = EX_OSERR; 366606f25ae9SGregory Neil Shapiro } 366740266059SGregory Neil Shapiro } 366840266059SGregory Neil Shapiro if (RunAsUid != 0 && setuid(0) == 0) 366906f25ae9SGregory Neil Shapiro { 367006f25ae9SGregory Neil Shapiro /* 367106f25ae9SGregory Neil Shapiro ** Believe it or not, the Linux capability model 367206f25ae9SGregory Neil Shapiro ** allows a non-root process to override setuid() 367306f25ae9SGregory Neil Shapiro ** on a process running as root and prevent that 367406f25ae9SGregory Neil Shapiro ** process from dropping privileges. 367506f25ae9SGregory Neil Shapiro */ 367606f25ae9SGregory Neil Shapiro 367706f25ae9SGregory Neil Shapiro syserr("drop_privileges: setuid(0) succeeded (when it should not)"); 367806f25ae9SGregory Neil Shapiro rval = EX_OSERR; 367906f25ae9SGregory Neil Shapiro } 368006f25ae9SGregory Neil Shapiro else if (RunAsUid != euid && setuid(euid) == 0) 368106f25ae9SGregory Neil Shapiro { 368206f25ae9SGregory Neil Shapiro /* 368306f25ae9SGregory Neil Shapiro ** Some operating systems will keep the saved-uid 368406f25ae9SGregory Neil Shapiro ** if a non-root effective-uid calls setuid(real-uid) 368506f25ae9SGregory Neil Shapiro ** making it possible to set it back again later. 368606f25ae9SGregory Neil Shapiro */ 368706f25ae9SGregory Neil Shapiro 368840266059SGregory Neil Shapiro syserr("drop_privileges: Unable to drop non-root set-user-ID privileges"); 368906f25ae9SGregory Neil Shapiro rval = EX_OSERR; 369006f25ae9SGregory Neil Shapiro } 369106f25ae9SGregory Neil Shapiro } 369240266059SGregory Neil Shapiro 369340266059SGregory Neil Shapiro if ((to_real_uid || RunAsGid != 0) && 369440266059SGregory Neil Shapiro rval == EX_OK && RunAsGid != EffGid && 369540266059SGregory Neil Shapiro getuid() != 0 && geteuid() != 0) 369640266059SGregory Neil Shapiro { 369740266059SGregory Neil Shapiro errno = 0; 369840266059SGregory Neil Shapiro if (setgid(EffGid) == 0) 369940266059SGregory Neil Shapiro { 370040266059SGregory Neil Shapiro syserr("drop_privileges: setgid(%d) succeeded (when it should not)", 370140266059SGregory Neil Shapiro (int) EffGid); 370240266059SGregory Neil Shapiro rval = EX_OSERR; 370340266059SGregory Neil Shapiro } 370440266059SGregory Neil Shapiro } 370540266059SGregory Neil Shapiro 3706c2aa98e2SPeter Wemm if (tTd(47, 5)) 3707c2aa98e2SPeter Wemm { 370840266059SGregory Neil Shapiro sm_dprintf("drop_privileges: e/ruid = %d/%d e/rgid = %d/%d\n", 370906f25ae9SGregory Neil Shapiro (int) geteuid(), (int) getuid(), 371006f25ae9SGregory Neil Shapiro (int) getegid(), (int) getgid()); 371140266059SGregory Neil Shapiro sm_dprintf("drop_privileges: RunAsUser = %d:%d\n", 371206f25ae9SGregory Neil Shapiro (int) RunAsUid, (int) RunAsGid); 371306f25ae9SGregory Neil Shapiro if (tTd(47, 10)) 371440266059SGregory Neil Shapiro sm_dprintf("drop_privileges: rval = %d\n", rval); 3715c2aa98e2SPeter Wemm } 3716c2aa98e2SPeter Wemm return rval; 3717c2aa98e2SPeter Wemm } 371840266059SGregory Neil Shapiro /* 3719c2aa98e2SPeter Wemm ** FILL_FD -- make sure a file descriptor has been properly allocated 3720c2aa98e2SPeter Wemm ** 3721c2aa98e2SPeter Wemm ** Used to make sure that stdin/out/err are allocated on startup 3722c2aa98e2SPeter Wemm ** 3723c2aa98e2SPeter Wemm ** Parameters: 3724c2aa98e2SPeter Wemm ** fd -- the file descriptor to be filled. 3725c2aa98e2SPeter Wemm ** where -- a string used for logging. If NULL, this is 3726c2aa98e2SPeter Wemm ** being called on startup, and logging should 3727c2aa98e2SPeter Wemm ** not be done. 3728c2aa98e2SPeter Wemm ** 3729c2aa98e2SPeter Wemm ** Returns: 3730c2aa98e2SPeter Wemm ** none 373140266059SGregory Neil Shapiro ** 373240266059SGregory Neil Shapiro ** Side Effects: 373340266059SGregory Neil Shapiro ** possibly changes MissingFds 3734c2aa98e2SPeter Wemm */ 3735c2aa98e2SPeter Wemm 3736c2aa98e2SPeter Wemm void 3737c2aa98e2SPeter Wemm fill_fd(fd, where) 3738c2aa98e2SPeter Wemm int fd; 3739c2aa98e2SPeter Wemm char *where; 3740c2aa98e2SPeter Wemm { 3741c2aa98e2SPeter Wemm int i; 3742c2aa98e2SPeter Wemm struct stat stbuf; 3743c2aa98e2SPeter Wemm 3744c2aa98e2SPeter Wemm if (fstat(fd, &stbuf) >= 0 || errno != EBADF) 3745c2aa98e2SPeter Wemm return; 3746c2aa98e2SPeter Wemm 3747c2aa98e2SPeter Wemm if (where != NULL) 3748c2aa98e2SPeter Wemm syserr("fill_fd: %s: fd %d not open", where, fd); 3749c2aa98e2SPeter Wemm else 3750c2aa98e2SPeter Wemm MissingFds |= 1 << fd; 375140266059SGregory Neil Shapiro i = open(SM_PATH_DEVNULL, fd == 0 ? O_RDONLY : O_WRONLY, 0666); 3752c2aa98e2SPeter Wemm if (i < 0) 3753c2aa98e2SPeter Wemm { 375440266059SGregory Neil Shapiro syserr("!fill_fd: %s: cannot open %s", 375540266059SGregory Neil Shapiro where == NULL ? "startup" : where, SM_PATH_DEVNULL); 3756c2aa98e2SPeter Wemm } 3757c2aa98e2SPeter Wemm if (fd != i) 3758c2aa98e2SPeter Wemm { 3759c2aa98e2SPeter Wemm (void) dup2(i, fd); 3760c2aa98e2SPeter Wemm (void) close(i); 3761c2aa98e2SPeter Wemm } 3762c2aa98e2SPeter Wemm } 376340266059SGregory Neil Shapiro /* 376440266059SGregory Neil Shapiro ** SM_PRINTOPTIONS -- print options 376540266059SGregory Neil Shapiro ** 376640266059SGregory Neil Shapiro ** Parameters: 376740266059SGregory Neil Shapiro ** options -- array of options. 376840266059SGregory Neil Shapiro ** 376940266059SGregory Neil Shapiro ** Returns: 377040266059SGregory Neil Shapiro ** none. 377140266059SGregory Neil Shapiro */ 377240266059SGregory Neil Shapiro 377340266059SGregory Neil Shapiro static void 377440266059SGregory Neil Shapiro sm_printoptions(options) 377540266059SGregory Neil Shapiro char **options; 377640266059SGregory Neil Shapiro { 377740266059SGregory Neil Shapiro int ll; 377840266059SGregory Neil Shapiro char **av; 377940266059SGregory Neil Shapiro 378040266059SGregory Neil Shapiro av = options; 378140266059SGregory Neil Shapiro ll = 7; 378240266059SGregory Neil Shapiro while (*av != NULL) 378340266059SGregory Neil Shapiro { 378440266059SGregory Neil Shapiro if (ll + strlen(*av) > 63) 378540266059SGregory Neil Shapiro { 378640266059SGregory Neil Shapiro sm_dprintf("\n"); 378740266059SGregory Neil Shapiro ll = 0; 378840266059SGregory Neil Shapiro } 378940266059SGregory Neil Shapiro if (ll == 0) 379040266059SGregory Neil Shapiro sm_dprintf("\t\t"); 379140266059SGregory Neil Shapiro else 379240266059SGregory Neil Shapiro sm_dprintf(" "); 379340266059SGregory Neil Shapiro sm_dprintf("%s", *av); 379440266059SGregory Neil Shapiro ll += strlen(*av++) + 1; 379540266059SGregory Neil Shapiro } 379640266059SGregory Neil Shapiro sm_dprintf("\n"); 379740266059SGregory Neil Shapiro } 379840266059SGregory Neil Shapiro /* 3799c2aa98e2SPeter Wemm ** TESTMODELINE -- process a test mode input line 3800c2aa98e2SPeter Wemm ** 3801c2aa98e2SPeter Wemm ** Parameters: 3802c2aa98e2SPeter Wemm ** line -- the input line. 3803c2aa98e2SPeter Wemm ** e -- the current environment. 3804c2aa98e2SPeter Wemm ** Syntax: 3805c2aa98e2SPeter Wemm ** # a comment 3806c2aa98e2SPeter Wemm ** .X process X as a configuration line 3807c2aa98e2SPeter Wemm ** =X dump a configuration item (such as mailers) 3808c2aa98e2SPeter Wemm ** $X dump a macro or class 3809c2aa98e2SPeter Wemm ** /X try an activity 3810c2aa98e2SPeter Wemm ** X normal process through rule set X 3811c2aa98e2SPeter Wemm */ 3812c2aa98e2SPeter Wemm 381306f25ae9SGregory Neil Shapiro static void 3814c2aa98e2SPeter Wemm testmodeline(line, e) 3815c2aa98e2SPeter Wemm char *line; 3816c2aa98e2SPeter Wemm ENVELOPE *e; 3817c2aa98e2SPeter Wemm { 3818c2aa98e2SPeter Wemm register char *p; 3819c2aa98e2SPeter Wemm char *q; 3820c2aa98e2SPeter Wemm auto char *delimptr; 3821c2aa98e2SPeter Wemm int mid; 3822c2aa98e2SPeter Wemm int i, rs; 3823c2aa98e2SPeter Wemm STAB *map; 3824c2aa98e2SPeter Wemm char **s; 3825c2aa98e2SPeter Wemm struct rewrite *rw; 3826c2aa98e2SPeter Wemm ADDRESS a; 3827c2aa98e2SPeter Wemm static int tryflags = RF_COPYNONE; 3828c2aa98e2SPeter Wemm char exbuf[MAXLINE]; 382940266059SGregory Neil Shapiro extern unsigned char TokTypeNoC[]; 383042e5d165SGregory Neil Shapiro 383142e5d165SGregory Neil Shapiro /* skip leading spaces */ 383242e5d165SGregory Neil Shapiro while (*line == ' ') 383342e5d165SGregory Neil Shapiro line++; 383442e5d165SGregory Neil Shapiro 3835c2aa98e2SPeter Wemm switch (line[0]) 3836c2aa98e2SPeter Wemm { 3837c2aa98e2SPeter Wemm case '#': 383806f25ae9SGregory Neil Shapiro case '\0': 3839c2aa98e2SPeter Wemm return; 3840c2aa98e2SPeter Wemm 3841c2aa98e2SPeter Wemm case '?': 384206f25ae9SGregory Neil Shapiro help("-bt", e); 3843c2aa98e2SPeter Wemm return; 3844c2aa98e2SPeter Wemm 3845c2aa98e2SPeter Wemm case '.': /* config-style settings */ 3846c2aa98e2SPeter Wemm switch (line[1]) 3847c2aa98e2SPeter Wemm { 3848c2aa98e2SPeter Wemm case 'D': 384940266059SGregory Neil Shapiro mid = macid_parse(&line[2], &delimptr); 3850193538b7SGregory Neil Shapiro if (mid == 0) 3851c2aa98e2SPeter Wemm return; 3852c2aa98e2SPeter Wemm translate_dollars(delimptr); 385340266059SGregory Neil Shapiro macdefine(&e->e_macro, A_TEMP, mid, delimptr); 3854c2aa98e2SPeter Wemm break; 3855c2aa98e2SPeter Wemm 3856c2aa98e2SPeter Wemm case 'C': 3857c2aa98e2SPeter Wemm if (line[2] == '\0') /* not to call syserr() */ 3858c2aa98e2SPeter Wemm return; 3859c2aa98e2SPeter Wemm 386040266059SGregory Neil Shapiro mid = macid_parse(&line[2], &delimptr); 3861193538b7SGregory Neil Shapiro if (mid == 0) 3862c2aa98e2SPeter Wemm return; 3863c2aa98e2SPeter Wemm translate_dollars(delimptr); 3864c2aa98e2SPeter Wemm expand(delimptr, exbuf, sizeof exbuf, e); 3865c2aa98e2SPeter Wemm p = exbuf; 3866c2aa98e2SPeter Wemm while (*p != '\0') 3867c2aa98e2SPeter Wemm { 3868c2aa98e2SPeter Wemm register char *wd; 3869c2aa98e2SPeter Wemm char delim; 3870c2aa98e2SPeter Wemm 3871c2aa98e2SPeter Wemm while (*p != '\0' && isascii(*p) && isspace(*p)) 3872c2aa98e2SPeter Wemm p++; 3873c2aa98e2SPeter Wemm wd = p; 3874c2aa98e2SPeter Wemm while (*p != '\0' && !(isascii(*p) && isspace(*p))) 3875c2aa98e2SPeter Wemm p++; 3876c2aa98e2SPeter Wemm delim = *p; 3877c2aa98e2SPeter Wemm *p = '\0'; 3878c2aa98e2SPeter Wemm if (wd[0] != '\0') 3879c2aa98e2SPeter Wemm setclass(mid, wd); 3880c2aa98e2SPeter Wemm *p = delim; 3881c2aa98e2SPeter Wemm } 3882c2aa98e2SPeter Wemm break; 3883c2aa98e2SPeter Wemm 3884c2aa98e2SPeter Wemm case '\0': 388540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 388640266059SGregory Neil Shapiro "Usage: .[DC]macro value(s)\n"); 3887c2aa98e2SPeter Wemm break; 3888c2aa98e2SPeter Wemm 3889c2aa98e2SPeter Wemm default: 389040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 389140266059SGregory Neil Shapiro "Unknown \".\" command %s\n", line); 3892c2aa98e2SPeter Wemm break; 3893c2aa98e2SPeter Wemm } 3894c2aa98e2SPeter Wemm return; 3895c2aa98e2SPeter Wemm 3896c2aa98e2SPeter Wemm case '=': /* config-style settings */ 3897c2aa98e2SPeter Wemm switch (line[1]) 3898c2aa98e2SPeter Wemm { 3899c2aa98e2SPeter Wemm case 'S': /* dump rule set */ 3900c2aa98e2SPeter Wemm rs = strtorwset(&line[2], NULL, ST_FIND); 3901c2aa98e2SPeter Wemm if (rs < 0) 3902c2aa98e2SPeter Wemm { 390340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 390440266059SGregory Neil Shapiro "Undefined ruleset %s\n", &line[2]); 3905c2aa98e2SPeter Wemm return; 3906c2aa98e2SPeter Wemm } 3907c2aa98e2SPeter Wemm rw = RewriteRules[rs]; 3908c2aa98e2SPeter Wemm if (rw == NULL) 3909c2aa98e2SPeter Wemm return; 3910c2aa98e2SPeter Wemm do 3911c2aa98e2SPeter Wemm { 391240266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, 391340266059SGregory Neil Shapiro 'R'); 3914c2aa98e2SPeter Wemm s = rw->r_lhs; 3915c2aa98e2SPeter Wemm while (*s != NULL) 3916c2aa98e2SPeter Wemm { 3917c2aa98e2SPeter Wemm xputs(*s++); 391840266059SGregory Neil Shapiro (void) sm_io_putc(smioout, 391940266059SGregory Neil Shapiro SM_TIME_DEFAULT, ' '); 3920c2aa98e2SPeter Wemm } 392140266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, 392240266059SGregory Neil Shapiro '\t'); 392340266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, 392440266059SGregory Neil Shapiro '\t'); 3925c2aa98e2SPeter Wemm s = rw->r_rhs; 3926c2aa98e2SPeter Wemm while (*s != NULL) 3927c2aa98e2SPeter Wemm { 3928c2aa98e2SPeter Wemm xputs(*s++); 392940266059SGregory Neil Shapiro (void) sm_io_putc(smioout, 393040266059SGregory Neil Shapiro SM_TIME_DEFAULT, ' '); 3931c2aa98e2SPeter Wemm } 393240266059SGregory Neil Shapiro (void) sm_io_putc(smioout, SM_TIME_DEFAULT, 393340266059SGregory Neil Shapiro '\n'); 3934c2aa98e2SPeter Wemm } while ((rw = rw->r_next) != NULL); 3935c2aa98e2SPeter Wemm break; 3936c2aa98e2SPeter Wemm 3937c2aa98e2SPeter Wemm case 'M': 3938c2aa98e2SPeter Wemm for (i = 0; i < MAXMAILERS; i++) 3939c2aa98e2SPeter Wemm { 3940c2aa98e2SPeter Wemm if (Mailer[i] != NULL) 3941c2aa98e2SPeter Wemm printmailer(Mailer[i]); 3942c2aa98e2SPeter Wemm } 3943c2aa98e2SPeter Wemm break; 3944c2aa98e2SPeter Wemm 3945c2aa98e2SPeter Wemm case '\0': 394640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 394740266059SGregory Neil Shapiro "Usage: =Sruleset or =M\n"); 3948c2aa98e2SPeter Wemm break; 3949c2aa98e2SPeter Wemm 3950c2aa98e2SPeter Wemm default: 395140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 395240266059SGregory Neil Shapiro "Unknown \"=\" command %s\n", line); 3953c2aa98e2SPeter Wemm break; 3954c2aa98e2SPeter Wemm } 3955c2aa98e2SPeter Wemm return; 3956c2aa98e2SPeter Wemm 3957c2aa98e2SPeter Wemm case '-': /* set command-line-like opts */ 3958c2aa98e2SPeter Wemm switch (line[1]) 3959c2aa98e2SPeter Wemm { 3960c2aa98e2SPeter Wemm case 'd': 3961c2aa98e2SPeter Wemm tTflag(&line[2]); 3962c2aa98e2SPeter Wemm break; 3963c2aa98e2SPeter Wemm 3964c2aa98e2SPeter Wemm case '\0': 396540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 396640266059SGregory Neil Shapiro "Usage: -d{debug arguments}\n"); 3967c2aa98e2SPeter Wemm break; 3968c2aa98e2SPeter Wemm 3969c2aa98e2SPeter Wemm default: 397040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 397140266059SGregory Neil Shapiro "Unknown \"-\" command %s\n", line); 3972c2aa98e2SPeter Wemm break; 3973c2aa98e2SPeter Wemm } 3974c2aa98e2SPeter Wemm return; 3975c2aa98e2SPeter Wemm 3976c2aa98e2SPeter Wemm case '$': 3977c2aa98e2SPeter Wemm if (line[1] == '=') 3978c2aa98e2SPeter Wemm { 397940266059SGregory Neil Shapiro mid = macid(&line[2]); 3980193538b7SGregory Neil Shapiro if (mid != 0) 3981c2aa98e2SPeter Wemm stabapply(dump_class, mid); 3982c2aa98e2SPeter Wemm return; 3983c2aa98e2SPeter Wemm } 398440266059SGregory Neil Shapiro mid = macid(&line[1]); 3985193538b7SGregory Neil Shapiro if (mid == 0) 3986c2aa98e2SPeter Wemm return; 3987c2aa98e2SPeter Wemm p = macvalue(mid, e); 3988c2aa98e2SPeter Wemm if (p == NULL) 398940266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 399040266059SGregory Neil Shapiro "Undefined\n"); 3991c2aa98e2SPeter Wemm else 3992c2aa98e2SPeter Wemm { 3993c2aa98e2SPeter Wemm xputs(p); 399440266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 399540266059SGregory Neil Shapiro "\n"); 3996c2aa98e2SPeter Wemm } 3997c2aa98e2SPeter Wemm return; 3998c2aa98e2SPeter Wemm 3999c2aa98e2SPeter Wemm case '/': /* miscellaneous commands */ 4000c2aa98e2SPeter Wemm p = &line[strlen(line)]; 4001c2aa98e2SPeter Wemm while (--p >= line && isascii(*p) && isspace(*p)) 4002c2aa98e2SPeter Wemm *p = '\0'; 4003c2aa98e2SPeter Wemm p = strpbrk(line, " \t"); 4004c2aa98e2SPeter Wemm if (p != NULL) 4005c2aa98e2SPeter Wemm { 4006c2aa98e2SPeter Wemm while (isascii(*p) && isspace(*p)) 4007c2aa98e2SPeter Wemm *p++ = '\0'; 4008c2aa98e2SPeter Wemm } 4009c2aa98e2SPeter Wemm else 4010c2aa98e2SPeter Wemm p = ""; 4011c2aa98e2SPeter Wemm if (line[1] == '\0') 4012c2aa98e2SPeter Wemm { 401340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 401440266059SGregory Neil Shapiro "Usage: /[canon|map|mx|parse|try|tryflags]\n"); 4015c2aa98e2SPeter Wemm return; 4016c2aa98e2SPeter Wemm } 401740266059SGregory Neil Shapiro if (sm_strcasecmp(&line[1], "quit") == 0) 401806f25ae9SGregory Neil Shapiro { 401906f25ae9SGregory Neil Shapiro CurEnv->e_id = NULL; 402040266059SGregory Neil Shapiro finis(true, true, ExitStat); 402140266059SGregory Neil Shapiro /* NOTREACHED */ 402206f25ae9SGregory Neil Shapiro } 402340266059SGregory Neil Shapiro if (sm_strcasecmp(&line[1], "mx") == 0) 4024c2aa98e2SPeter Wemm { 4025c2aa98e2SPeter Wemm #if NAMED_BIND 4026c2aa98e2SPeter Wemm /* look up MX records */ 4027c2aa98e2SPeter Wemm int nmx; 4028c2aa98e2SPeter Wemm auto int rcode; 4029c2aa98e2SPeter Wemm char *mxhosts[MAXMXHOSTS + 1]; 4030c2aa98e2SPeter Wemm 4031c2aa98e2SPeter Wemm if (*p == '\0') 4032c2aa98e2SPeter Wemm { 403340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 403440266059SGregory Neil Shapiro "Usage: /mx address\n"); 4035c2aa98e2SPeter Wemm return; 4036c2aa98e2SPeter Wemm } 403740266059SGregory Neil Shapiro nmx = getmxrr(p, mxhosts, NULL, false, &rcode, true, 403840266059SGregory Neil Shapiro NULL); 403940266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 404040266059SGregory Neil Shapiro "getmxrr(%s) returns %d value(s):\n", 404140266059SGregory Neil Shapiro p, nmx); 4042c2aa98e2SPeter Wemm for (i = 0; i < nmx; i++) 404340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 404440266059SGregory Neil Shapiro "\t%s\n", mxhosts[i]); 404506f25ae9SGregory Neil Shapiro #else /* NAMED_BIND */ 404640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 404740266059SGregory Neil Shapiro "No MX code compiled in\n"); 404806f25ae9SGregory Neil Shapiro #endif /* NAMED_BIND */ 4049c2aa98e2SPeter Wemm } 405040266059SGregory Neil Shapiro else if (sm_strcasecmp(&line[1], "canon") == 0) 4051c2aa98e2SPeter Wemm { 4052c2aa98e2SPeter Wemm char host[MAXHOSTNAMELEN]; 4053c2aa98e2SPeter Wemm 4054c2aa98e2SPeter Wemm if (*p == '\0') 4055c2aa98e2SPeter Wemm { 405640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 405740266059SGregory Neil Shapiro "Usage: /canon address\n"); 4058c2aa98e2SPeter Wemm return; 4059c2aa98e2SPeter Wemm } 406040266059SGregory Neil Shapiro else if (sm_strlcpy(host, p, sizeof host) >= sizeof host) 4061c2aa98e2SPeter Wemm { 406240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 406340266059SGregory Neil Shapiro "Name too long\n"); 4064c2aa98e2SPeter Wemm return; 4065c2aa98e2SPeter Wemm } 406640266059SGregory Neil Shapiro (void) getcanonname(host, sizeof host, HasWildcardMX, 406740266059SGregory Neil Shapiro NULL); 406840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 406940266059SGregory Neil Shapiro "getcanonname(%s) returns %s\n", 407040266059SGregory Neil Shapiro p, host); 4071c2aa98e2SPeter Wemm } 407240266059SGregory Neil Shapiro else if (sm_strcasecmp(&line[1], "map") == 0) 4073c2aa98e2SPeter Wemm { 4074c2aa98e2SPeter Wemm auto int rcode = EX_OK; 4075c2aa98e2SPeter Wemm char *av[2]; 4076c2aa98e2SPeter Wemm 4077c2aa98e2SPeter Wemm if (*p == '\0') 4078c2aa98e2SPeter Wemm { 407940266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 408040266059SGregory Neil Shapiro "Usage: /map mapname key\n"); 4081c2aa98e2SPeter Wemm return; 4082c2aa98e2SPeter Wemm } 4083c2aa98e2SPeter Wemm for (q = p; *q != '\0' && !(isascii(*q) && isspace(*q)); q++) 4084c2aa98e2SPeter Wemm continue; 4085c2aa98e2SPeter Wemm if (*q == '\0') 4086c2aa98e2SPeter Wemm { 408740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 408840266059SGregory Neil Shapiro "No key specified\n"); 4089c2aa98e2SPeter Wemm return; 4090c2aa98e2SPeter Wemm } 4091c2aa98e2SPeter Wemm *q++ = '\0'; 4092c2aa98e2SPeter Wemm map = stab(p, ST_MAP, ST_FIND); 4093c2aa98e2SPeter Wemm if (map == NULL) 4094c2aa98e2SPeter Wemm { 409540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 409640266059SGregory Neil Shapiro "Map named \"%s\" not found\n", p); 4097c2aa98e2SPeter Wemm return; 4098c2aa98e2SPeter Wemm } 409906f25ae9SGregory Neil Shapiro if (!bitset(MF_OPEN, map->s_map.map_mflags) && 410006f25ae9SGregory Neil Shapiro !openmap(&(map->s_map))) 4101c2aa98e2SPeter Wemm { 410240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 410340266059SGregory Neil Shapiro "Map named \"%s\" not open\n", p); 4104c2aa98e2SPeter Wemm return; 4105c2aa98e2SPeter Wemm } 410640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 410740266059SGregory Neil Shapiro "map_lookup: %s (%s) ", p, q); 4108c2aa98e2SPeter Wemm av[0] = q; 4109c2aa98e2SPeter Wemm av[1] = NULL; 4110c2aa98e2SPeter Wemm p = (*map->s_map.map_class->map_lookup) 4111c2aa98e2SPeter Wemm (&map->s_map, q, av, &rcode); 4112c2aa98e2SPeter Wemm if (p == NULL) 411340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 411440266059SGregory Neil Shapiro "no match (%d)\n", 411540266059SGregory Neil Shapiro rcode); 4116c2aa98e2SPeter Wemm else 411740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 411840266059SGregory Neil Shapiro "returns %s (%d)\n", p, 411940266059SGregory Neil Shapiro rcode); 4120c2aa98e2SPeter Wemm } 412140266059SGregory Neil Shapiro else if (sm_strcasecmp(&line[1], "try") == 0) 4122c2aa98e2SPeter Wemm { 4123c2aa98e2SPeter Wemm MAILER *m; 412406f25ae9SGregory Neil Shapiro STAB *st; 4125c2aa98e2SPeter Wemm auto int rcode = EX_OK; 4126c2aa98e2SPeter Wemm 4127c2aa98e2SPeter Wemm q = strpbrk(p, " \t"); 4128c2aa98e2SPeter Wemm if (q != NULL) 4129c2aa98e2SPeter Wemm { 4130c2aa98e2SPeter Wemm while (isascii(*q) && isspace(*q)) 4131c2aa98e2SPeter Wemm *q++ = '\0'; 4132c2aa98e2SPeter Wemm } 4133c2aa98e2SPeter Wemm if (q == NULL || *q == '\0') 4134c2aa98e2SPeter Wemm { 413540266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 413640266059SGregory Neil Shapiro "Usage: /try mailer address\n"); 4137c2aa98e2SPeter Wemm return; 4138c2aa98e2SPeter Wemm } 413906f25ae9SGregory Neil Shapiro st = stab(p, ST_MAILER, ST_FIND); 414006f25ae9SGregory Neil Shapiro if (st == NULL) 4141c2aa98e2SPeter Wemm { 414240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 414340266059SGregory Neil Shapiro "Unknown mailer %s\n", p); 4144c2aa98e2SPeter Wemm return; 4145c2aa98e2SPeter Wemm } 414606f25ae9SGregory Neil Shapiro m = st->s_mailer; 414740266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 414840266059SGregory Neil Shapiro "Trying %s %s address %s for mailer %s\n", 414940266059SGregory Neil Shapiro bitset(RF_HEADERADDR, tryflags) ? "header" 415040266059SGregory Neil Shapiro : "envelope", 415140266059SGregory Neil Shapiro bitset(RF_SENDERADDR, tryflags) ? "sender" 415240266059SGregory Neil Shapiro : "recipient", q, p); 4153c2aa98e2SPeter Wemm p = remotename(q, m, tryflags, &rcode, CurEnv); 415440266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 415540266059SGregory Neil Shapiro "Rcode = %d, addr = %s\n", 4156c2aa98e2SPeter Wemm rcode, p == NULL ? "<NULL>" : p); 4157c2aa98e2SPeter Wemm e->e_to = NULL; 4158c2aa98e2SPeter Wemm } 415940266059SGregory Neil Shapiro else if (sm_strcasecmp(&line[1], "tryflags") == 0) 4160c2aa98e2SPeter Wemm { 4161c2aa98e2SPeter Wemm if (*p == '\0') 4162c2aa98e2SPeter Wemm { 416340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 416440266059SGregory Neil Shapiro "Usage: /tryflags [Hh|Ee][Ss|Rr]\n"); 4165c2aa98e2SPeter Wemm return; 4166c2aa98e2SPeter Wemm } 4167c2aa98e2SPeter Wemm for (; *p != '\0'; p++) 4168c2aa98e2SPeter Wemm { 4169c2aa98e2SPeter Wemm switch (*p) 4170c2aa98e2SPeter Wemm { 4171c2aa98e2SPeter Wemm case 'H': 4172c2aa98e2SPeter Wemm case 'h': 4173c2aa98e2SPeter Wemm tryflags |= RF_HEADERADDR; 4174c2aa98e2SPeter Wemm break; 4175c2aa98e2SPeter Wemm 4176c2aa98e2SPeter Wemm case 'E': 4177c2aa98e2SPeter Wemm case 'e': 4178c2aa98e2SPeter Wemm tryflags &= ~RF_HEADERADDR; 4179c2aa98e2SPeter Wemm break; 4180c2aa98e2SPeter Wemm 4181c2aa98e2SPeter Wemm case 'S': 4182c2aa98e2SPeter Wemm case 's': 4183c2aa98e2SPeter Wemm tryflags |= RF_SENDERADDR; 4184c2aa98e2SPeter Wemm break; 4185c2aa98e2SPeter Wemm 4186c2aa98e2SPeter Wemm case 'R': 4187c2aa98e2SPeter Wemm case 'r': 4188c2aa98e2SPeter Wemm tryflags &= ~RF_SENDERADDR; 4189c2aa98e2SPeter Wemm break; 4190c2aa98e2SPeter Wemm } 4191c2aa98e2SPeter Wemm } 419206f25ae9SGregory Neil Shapiro exbuf[0] = bitset(RF_HEADERADDR, tryflags) ? 'h' : 'e'; 419306f25ae9SGregory Neil Shapiro exbuf[1] = ' '; 419406f25ae9SGregory Neil Shapiro exbuf[2] = bitset(RF_SENDERADDR, tryflags) ? 's' : 'r'; 419506f25ae9SGregory Neil Shapiro exbuf[3] = '\0'; 419640266059SGregory Neil Shapiro macdefine(&e->e_macro, A_TEMP, 419740266059SGregory Neil Shapiro macid("{addr_type}"), exbuf); 4198c2aa98e2SPeter Wemm } 419940266059SGregory Neil Shapiro else if (sm_strcasecmp(&line[1], "parse") == 0) 4200c2aa98e2SPeter Wemm { 4201c2aa98e2SPeter Wemm if (*p == '\0') 4202c2aa98e2SPeter Wemm { 420340266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 420440266059SGregory Neil Shapiro "Usage: /parse address\n"); 4205c2aa98e2SPeter Wemm return; 4206c2aa98e2SPeter Wemm } 4207c2aa98e2SPeter Wemm q = crackaddr(p); 420840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 420940266059SGregory Neil Shapiro "Cracked address = "); 4210c2aa98e2SPeter Wemm xputs(q); 421140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 421240266059SGregory Neil Shapiro "\nParsing %s %s address\n", 421340266059SGregory Neil Shapiro bitset(RF_HEADERADDR, tryflags) ? 421440266059SGregory Neil Shapiro "header" : "envelope", 421540266059SGregory Neil Shapiro bitset(RF_SENDERADDR, tryflags) ? 421640266059SGregory Neil Shapiro "sender" : "recipient"); 421740266059SGregory Neil Shapiro if (parseaddr(p, &a, tryflags, '\0', NULL, e, true) 421840266059SGregory Neil Shapiro == NULL) 421940266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 422040266059SGregory Neil Shapiro "Cannot parse\n"); 4221c2aa98e2SPeter Wemm else if (a.q_host != NULL && a.q_host[0] != '\0') 422240266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 422340266059SGregory Neil Shapiro "mailer %s, host %s, user %s\n", 422440266059SGregory Neil Shapiro a.q_mailer->m_name, 422540266059SGregory Neil Shapiro a.q_host, 422640266059SGregory Neil Shapiro a.q_user); 4227c2aa98e2SPeter Wemm else 422840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 422940266059SGregory Neil Shapiro "mailer %s, user %s\n", 423040266059SGregory Neil Shapiro a.q_mailer->m_name, 423140266059SGregory Neil Shapiro a.q_user); 4232c2aa98e2SPeter Wemm e->e_to = NULL; 4233c2aa98e2SPeter Wemm } 4234c2aa98e2SPeter Wemm else 4235c2aa98e2SPeter Wemm { 423640266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 423740266059SGregory Neil Shapiro "Unknown \"/\" command %s\n", 423840266059SGregory Neil Shapiro line); 4239c2aa98e2SPeter Wemm } 4240c2aa98e2SPeter Wemm return; 4241c2aa98e2SPeter Wemm } 4242c2aa98e2SPeter Wemm 4243c2aa98e2SPeter Wemm for (p = line; isascii(*p) && isspace(*p); p++) 4244c2aa98e2SPeter Wemm continue; 4245c2aa98e2SPeter Wemm q = p; 4246c2aa98e2SPeter Wemm while (*p != '\0' && !(isascii(*p) && isspace(*p))) 4247c2aa98e2SPeter Wemm p++; 4248c2aa98e2SPeter Wemm if (*p == '\0') 4249c2aa98e2SPeter Wemm { 425040266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 425140266059SGregory Neil Shapiro "No address!\n"); 4252c2aa98e2SPeter Wemm return; 4253c2aa98e2SPeter Wemm } 4254c2aa98e2SPeter Wemm *p = '\0'; 425540266059SGregory Neil Shapiro if (invalidaddr(p + 1, NULL, true)) 4256c2aa98e2SPeter Wemm return; 4257c2aa98e2SPeter Wemm do 4258c2aa98e2SPeter Wemm { 4259c2aa98e2SPeter Wemm register char **pvp; 4260c2aa98e2SPeter Wemm char pvpbuf[PSBUFSIZE]; 4261c2aa98e2SPeter Wemm 4262c2aa98e2SPeter Wemm pvp = prescan(++p, ',', pvpbuf, sizeof pvpbuf, 426306f25ae9SGregory Neil Shapiro &delimptr, ConfigLevel >= 9 ? TokTypeNoC : NULL); 4264c2aa98e2SPeter Wemm if (pvp == NULL) 4265c2aa98e2SPeter Wemm continue; 4266c2aa98e2SPeter Wemm p = q; 4267c2aa98e2SPeter Wemm while (*p != '\0') 4268c2aa98e2SPeter Wemm { 426906f25ae9SGregory Neil Shapiro int status; 4270c2aa98e2SPeter Wemm 4271c2aa98e2SPeter Wemm rs = strtorwset(p, NULL, ST_FIND); 4272c2aa98e2SPeter Wemm if (rs < 0) 4273c2aa98e2SPeter Wemm { 427440266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 427540266059SGregory Neil Shapiro "Undefined ruleset %s\n", 427640266059SGregory Neil Shapiro p); 4277c2aa98e2SPeter Wemm break; 4278c2aa98e2SPeter Wemm } 427940266059SGregory Neil Shapiro status = REWRITE(pvp, rs, e); 428006f25ae9SGregory Neil Shapiro if (status != EX_OK) 428140266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 428240266059SGregory Neil Shapiro "== Ruleset %s (%d) status %d\n", 428306f25ae9SGregory Neil Shapiro p, rs, status); 4284c2aa98e2SPeter Wemm while (*p != '\0' && *p++ != ',') 4285c2aa98e2SPeter Wemm continue; 4286c2aa98e2SPeter Wemm } 4287c2aa98e2SPeter Wemm } while (*(p = delimptr) != '\0'); 4288c2aa98e2SPeter Wemm } 4289c2aa98e2SPeter Wemm 429006f25ae9SGregory Neil Shapiro static void 4291c2aa98e2SPeter Wemm dump_class(s, id) 4292c2aa98e2SPeter Wemm register STAB *s; 4293c2aa98e2SPeter Wemm int id; 4294c2aa98e2SPeter Wemm { 429540266059SGregory Neil Shapiro if (s->s_symtype != ST_CLASS) 4296c2aa98e2SPeter Wemm return; 4297193538b7SGregory Neil Shapiro if (bitnset(bitidx(id), s->s_class)) 429840266059SGregory Neil Shapiro (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 429940266059SGregory Neil Shapiro "%s\n", s->s_name); 4300c2aa98e2SPeter Wemm } 430140266059SGregory Neil Shapiro 430240266059SGregory Neil Shapiro /* 430340266059SGregory Neil Shapiro ** An exception type used to create QuickAbort exceptions. 430440266059SGregory Neil Shapiro ** This is my first cut at converting QuickAbort from longjmp to exceptions. 430540266059SGregory Neil Shapiro ** These exceptions have a single integer argument, which is the argument 430640266059SGregory Neil Shapiro ** to longjmp in the original code (either 1 or 2). I don't know the 430740266059SGregory Neil Shapiro ** significance of 1 vs 2: the calls to setjmp don't care. 430840266059SGregory Neil Shapiro */ 430940266059SGregory Neil Shapiro 431040266059SGregory Neil Shapiro const SM_EXC_TYPE_T EtypeQuickAbort = 431140266059SGregory Neil Shapiro { 431240266059SGregory Neil Shapiro SmExcTypeMagic, 431340266059SGregory Neil Shapiro "E:mta.quickabort", 431440266059SGregory Neil Shapiro "i", 431540266059SGregory Neil Shapiro sm_etype_printf, 431640266059SGregory Neil Shapiro "quick abort %0", 431740266059SGregory Neil Shapiro }; 4318