17c478bd9Sstevel@tonic-gate /* 2*3ee0e492Sjbeck * Copyright (c) 1998-2006 Sendmail, Inc. and its suppliers. 37c478bd9Sstevel@tonic-gate * All rights reserved. 47c478bd9Sstevel@tonic-gate * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved. 57c478bd9Sstevel@tonic-gate * Copyright (c) 1988, 1993 67c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set 97c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of 107c478bd9Sstevel@tonic-gate * the sendmail distribution. 117c478bd9Sstevel@tonic-gate * 127c478bd9Sstevel@tonic-gate */ 137c478bd9Sstevel@tonic-gate 147c478bd9Sstevel@tonic-gate /* 15445f2479Sjbeck * Copyright 1996-2006 Sun Microsystems, Inc. All rights reserved. 167c478bd9Sstevel@tonic-gate * Use is subject to license terms. 177c478bd9Sstevel@tonic-gate */ 187c478bd9Sstevel@tonic-gate 197c478bd9Sstevel@tonic-gate #define _DEFINE 207c478bd9Sstevel@tonic-gate #include <sendmail.h> 217c478bd9Sstevel@tonic-gate #include <sm/xtrap.h> 227c478bd9Sstevel@tonic-gate #include <sm/signal.h> 237c478bd9Sstevel@tonic-gate 247c478bd9Sstevel@tonic-gate #ifndef lint 257c478bd9Sstevel@tonic-gate SM_UNUSED(static char copyright[]) = 267c478bd9Sstevel@tonic-gate "@(#) Copyright (c) 1998-2003 Sendmail, Inc. and its suppliers.\n\ 277c478bd9Sstevel@tonic-gate @(#) All rights reserved.\n\ 287c478bd9Sstevel@tonic-gate @(#) Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.\n\ 297c478bd9Sstevel@tonic-gate @(#) Copyright (c) 1988, 1993\n\ 307c478bd9Sstevel@tonic-gate @(#) The Regents of the University of California. All rights reserved.\n\ 31445f2479Sjbeck @(#) Copyright 1996-2006 Sun Microsystems, Inc. All rights reserved.\n\ 327c478bd9Sstevel@tonic-gate @(#) Use is subject to license terms.\n"; 337c478bd9Sstevel@tonic-gate #endif /* ! lint */ 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 367c478bd9Sstevel@tonic-gate 37*3ee0e492Sjbeck SM_RCSID("@(#)$Id: main.c,v 8.944 2006/04/21 23:56:42 ca Exp $") 387c478bd9Sstevel@tonic-gate SM_IDSTR(i2, "%W% (Sun) %G%") 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate #if NETINET || NETINET6 417c478bd9Sstevel@tonic-gate # include <arpa/inet.h> 427c478bd9Sstevel@tonic-gate #endif /* NETINET || NETINET6 */ 437c478bd9Sstevel@tonic-gate 447c478bd9Sstevel@tonic-gate /* for getcfname() */ 457c478bd9Sstevel@tonic-gate #include <sendmail/pathnames.h> 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate static SM_DEBUG_T 487c478bd9Sstevel@tonic-gate DebugNoPRestart = SM_DEBUG_INITIALIZER("no_persistent_restart", 497c478bd9Sstevel@tonic-gate "@(#)$Debug: no_persistent_restart - don't restart, log only $"); 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate static void dump_class __P((STAB *, int)); 527c478bd9Sstevel@tonic-gate static void obsolete __P((char **)); 537c478bd9Sstevel@tonic-gate static void testmodeline __P((char *, ENVELOPE *)); 547c478bd9Sstevel@tonic-gate static char *getextenv __P((const char *)); 557c478bd9Sstevel@tonic-gate static void sm_printoptions __P((char **)); 567c478bd9Sstevel@tonic-gate static SIGFUNC_DECL intindebug __P((int)); 577c478bd9Sstevel@tonic-gate static SIGFUNC_DECL sighup __P((int)); 587c478bd9Sstevel@tonic-gate static SIGFUNC_DECL sigpipe __P((int)); 597c478bd9Sstevel@tonic-gate static SIGFUNC_DECL sigterm __P((int)); 607c478bd9Sstevel@tonic-gate #ifdef SIGUSR1 617c478bd9Sstevel@tonic-gate static SIGFUNC_DECL sigusr1 __P((int)); 627c478bd9Sstevel@tonic-gate #endif /* SIGUSR1 */ 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate /* 657c478bd9Sstevel@tonic-gate ** SENDMAIL -- Post mail to a set of destinations. 667c478bd9Sstevel@tonic-gate ** 677c478bd9Sstevel@tonic-gate ** This is the basic mail router. All user mail programs should 687c478bd9Sstevel@tonic-gate ** call this routine to actually deliver mail. Sendmail in 697c478bd9Sstevel@tonic-gate ** turn calls a bunch of mail servers that do the real work of 707c478bd9Sstevel@tonic-gate ** delivering the mail. 717c478bd9Sstevel@tonic-gate ** 727c478bd9Sstevel@tonic-gate ** Sendmail is driven by settings read in from /etc/mail/sendmail.cf 737c478bd9Sstevel@tonic-gate ** (read by readcf.c). 747c478bd9Sstevel@tonic-gate ** 757c478bd9Sstevel@tonic-gate ** Usage: 767c478bd9Sstevel@tonic-gate ** /usr/lib/sendmail [flags] addr ... 777c478bd9Sstevel@tonic-gate ** 787c478bd9Sstevel@tonic-gate ** See the associated documentation for details. 797c478bd9Sstevel@tonic-gate ** 807c478bd9Sstevel@tonic-gate ** Authors: 817c478bd9Sstevel@tonic-gate ** Eric Allman, UCB/INGRES (until 10/81). 827c478bd9Sstevel@tonic-gate ** Britton-Lee, Inc., purveyors of fine 837c478bd9Sstevel@tonic-gate ** database computers (11/81 - 10/88). 847c478bd9Sstevel@tonic-gate ** International Computer Science Institute 857c478bd9Sstevel@tonic-gate ** (11/88 - 9/89). 867c478bd9Sstevel@tonic-gate ** UCB/Mammoth Project (10/89 - 7/95). 877c478bd9Sstevel@tonic-gate ** InReference, Inc. (8/95 - 1/97). 887c478bd9Sstevel@tonic-gate ** Sendmail, Inc. (1/98 - present). 897c478bd9Sstevel@tonic-gate ** The support of my employers is gratefully acknowledged. 907c478bd9Sstevel@tonic-gate ** Few of them (Britton-Lee in particular) have had 917c478bd9Sstevel@tonic-gate ** anything to gain from my involvement in this project. 927c478bd9Sstevel@tonic-gate ** 937c478bd9Sstevel@tonic-gate ** Gregory Neil Shapiro, 947c478bd9Sstevel@tonic-gate ** Worcester Polytechnic Institute (until 3/98). 957c478bd9Sstevel@tonic-gate ** Sendmail, Inc. (3/98 - present). 967c478bd9Sstevel@tonic-gate ** 977c478bd9Sstevel@tonic-gate ** Claus Assmann, 987c478bd9Sstevel@tonic-gate ** Sendmail, Inc. (12/98 - present). 997c478bd9Sstevel@tonic-gate */ 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate char *FullName; /* sender's full name */ 1027c478bd9Sstevel@tonic-gate ENVELOPE BlankEnvelope; /* a "blank" envelope */ 1037c478bd9Sstevel@tonic-gate static ENVELOPE MainEnvelope; /* the envelope around the basic letter */ 1047c478bd9Sstevel@tonic-gate ADDRESS NullAddress = /* a null address */ 1057c478bd9Sstevel@tonic-gate { "", "", NULL, "" }; 1067c478bd9Sstevel@tonic-gate char *CommandLineArgs; /* command line args for pid file */ 1077c478bd9Sstevel@tonic-gate bool Warn_Q_option = false; /* warn about Q option use */ 1087c478bd9Sstevel@tonic-gate static int MissingFds = 0; /* bit map of fds missing on startup */ 1097c478bd9Sstevel@tonic-gate char *Mbdb = "pw"; /* mailbox database defaults to /etc/passwd */ 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate #ifdef NGROUPS_MAX 1127c478bd9Sstevel@tonic-gate GIDSET_T InitialGidSet[NGROUPS_MAX]; 1137c478bd9Sstevel@tonic-gate #endif /* NGROUPS_MAX */ 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate #define MAXCONFIGLEVEL 10 /* highest config version level known */ 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate #if SASL 1187c478bd9Sstevel@tonic-gate static sasl_callback_t srvcallbacks[] = 1197c478bd9Sstevel@tonic-gate { 1207c478bd9Sstevel@tonic-gate { SASL_CB_VERIFYFILE, &safesaslfile, NULL }, 1217c478bd9Sstevel@tonic-gate { SASL_CB_PROXY_POLICY, &proxy_policy, NULL }, 1227c478bd9Sstevel@tonic-gate { SASL_CB_LIST_END, NULL, NULL } 1237c478bd9Sstevel@tonic-gate }; 1247c478bd9Sstevel@tonic-gate #endif /* SASL */ 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate unsigned int SubmitMode; 1277c478bd9Sstevel@tonic-gate int SyslogPrefixLen; /* estimated length of syslog prefix */ 1287c478bd9Sstevel@tonic-gate #define PIDLEN 6 /* pid length for computing SyslogPrefixLen */ 1297c478bd9Sstevel@tonic-gate #ifndef SL_FUDGE 1307c478bd9Sstevel@tonic-gate # define SL_FUDGE 10 /* fudge offset for SyslogPrefixLen */ 1317c478bd9Sstevel@tonic-gate #endif /* ! SL_FUDGE */ 1327c478bd9Sstevel@tonic-gate #define SLDLL 8 /* est. length of default syslog label */ 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate /* Some options are dangerous to allow users to use in non-submit mode */ 1367c478bd9Sstevel@tonic-gate #define CHECK_AGAINST_OPMODE(cmd) \ 1377c478bd9Sstevel@tonic-gate { \ 1387c478bd9Sstevel@tonic-gate if (extraprivs && \ 1397c478bd9Sstevel@tonic-gate OpMode != MD_DELIVER && OpMode != MD_SMTP && \ 1407c478bd9Sstevel@tonic-gate OpMode != MD_ARPAFTP && \ 1417c478bd9Sstevel@tonic-gate OpMode != MD_VERIFY && OpMode != MD_TEST) \ 1427c478bd9Sstevel@tonic-gate { \ 1437c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, \ 1447c478bd9Sstevel@tonic-gate "WARNING: Ignoring submission mode -%c option (not in submission mode)\n", \ 1457c478bd9Sstevel@tonic-gate (cmd)); \ 1467c478bd9Sstevel@tonic-gate break; \ 1477c478bd9Sstevel@tonic-gate } \ 1487c478bd9Sstevel@tonic-gate if (extraprivs && queuerun) \ 1497c478bd9Sstevel@tonic-gate { \ 1507c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, \ 1517c478bd9Sstevel@tonic-gate "WARNING: Ignoring submission mode -%c option with -q\n", \ 1527c478bd9Sstevel@tonic-gate (cmd)); \ 1537c478bd9Sstevel@tonic-gate break; \ 1547c478bd9Sstevel@tonic-gate } \ 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate int 1587c478bd9Sstevel@tonic-gate main(argc, argv, envp) 1597c478bd9Sstevel@tonic-gate int argc; 1607c478bd9Sstevel@tonic-gate char **argv; 1617c478bd9Sstevel@tonic-gate char **envp; 1627c478bd9Sstevel@tonic-gate { 1637c478bd9Sstevel@tonic-gate register char *p; 1647c478bd9Sstevel@tonic-gate char **av; 1657c478bd9Sstevel@tonic-gate extern char Version[]; 1667c478bd9Sstevel@tonic-gate char *ep, *from; 1677c478bd9Sstevel@tonic-gate STAB *st; 1687c478bd9Sstevel@tonic-gate register int i; 1697c478bd9Sstevel@tonic-gate int j; 1707c478bd9Sstevel@tonic-gate int dp; 1717c478bd9Sstevel@tonic-gate int fill_errno; 1727c478bd9Sstevel@tonic-gate int qgrp = NOQGRP; /* queue group to process */ 1737c478bd9Sstevel@tonic-gate bool safecf = true; 1747c478bd9Sstevel@tonic-gate BITMAP256 *p_flags = NULL; /* daemon flags */ 1757c478bd9Sstevel@tonic-gate bool warn_C_flag = false; 1767c478bd9Sstevel@tonic-gate bool auth = true; /* whether to set e_auth_param */ 1777c478bd9Sstevel@tonic-gate char warn_f_flag = '\0'; 1787c478bd9Sstevel@tonic-gate bool run_in_foreground = false; /* -bD mode */ 1797c478bd9Sstevel@tonic-gate bool queuerun = false, debug = false; 1807c478bd9Sstevel@tonic-gate struct passwd *pw; 1817c478bd9Sstevel@tonic-gate struct hostent *hp; 1827c478bd9Sstevel@tonic-gate char *nullserver = NULL; 1837c478bd9Sstevel@tonic-gate char *authinfo = NULL; 1847c478bd9Sstevel@tonic-gate char *sysloglabel = NULL; /* label for syslog */ 1857c478bd9Sstevel@tonic-gate char *conffile = NULL; /* name of .cf file */ 1867c478bd9Sstevel@tonic-gate char *queuegroup = NULL; /* queue group to process */ 1877c478bd9Sstevel@tonic-gate char *quarantining = NULL; /* quarantine queue items? */ 1887c478bd9Sstevel@tonic-gate bool extraprivs; 1897c478bd9Sstevel@tonic-gate bool forged, negate; 1907c478bd9Sstevel@tonic-gate bool queuepersistent = false; /* queue runner process runs forever */ 1917c478bd9Sstevel@tonic-gate bool foregroundqueue = false; /* queue run in foreground */ 1927c478bd9Sstevel@tonic-gate bool save_val; /* to save some bool var. */ 1937c478bd9Sstevel@tonic-gate int cftype; /* which cf file to use? */ 1947c478bd9Sstevel@tonic-gate SM_FILE_T *smdebug; 1957c478bd9Sstevel@tonic-gate static time_t starttime = 0; /* when was process started */ 1967c478bd9Sstevel@tonic-gate struct stat traf_st; /* for TrafficLog FIFO check */ 1977c478bd9Sstevel@tonic-gate char buf[MAXLINE]; 1987c478bd9Sstevel@tonic-gate char jbuf[MAXHOSTNAMELEN]; /* holds MyHostName */ 1997c478bd9Sstevel@tonic-gate static char rnamebuf[MAXNAME]; /* holds RealUserName */ 2007c478bd9Sstevel@tonic-gate char *emptyenviron[1]; 2017c478bd9Sstevel@tonic-gate #if STARTTLS 2027c478bd9Sstevel@tonic-gate bool tls_ok; 2037c478bd9Sstevel@tonic-gate #endif /* STARTTLS */ 2047c478bd9Sstevel@tonic-gate QUEUE_CHAR *new; 2057c478bd9Sstevel@tonic-gate ENVELOPE *e; 2067c478bd9Sstevel@tonic-gate extern int DtableSize; 2077c478bd9Sstevel@tonic-gate extern int optind; 2087c478bd9Sstevel@tonic-gate extern int opterr; 2097c478bd9Sstevel@tonic-gate extern char *optarg; 2107c478bd9Sstevel@tonic-gate extern char **environ; 2117c478bd9Sstevel@tonic-gate #if SASL 2127c478bd9Sstevel@tonic-gate extern void sm_sasl_init __P((void)); 2137c478bd9Sstevel@tonic-gate #endif /* SASL */ 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate #if USE_ENVIRON 2167c478bd9Sstevel@tonic-gate envp = environ; 2177c478bd9Sstevel@tonic-gate #endif /* USE_ENVIRON */ 2187c478bd9Sstevel@tonic-gate 2197c478bd9Sstevel@tonic-gate /* turn off profiling */ 2207c478bd9Sstevel@tonic-gate SM_PROF(0); 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate /* install default exception handler */ 2237c478bd9Sstevel@tonic-gate sm_exc_newthread(fatal_error); 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* set the default in/out channel so errors reported to screen */ 2267c478bd9Sstevel@tonic-gate InChannel = smioin; 2277c478bd9Sstevel@tonic-gate OutChannel = smioout; 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate /* 2307c478bd9Sstevel@tonic-gate ** Check to see if we reentered. 2317c478bd9Sstevel@tonic-gate ** This would normally happen if e_putheader or e_putbody 2327c478bd9Sstevel@tonic-gate ** were NULL when invoked. 2337c478bd9Sstevel@tonic-gate */ 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate if (starttime != 0) 2367c478bd9Sstevel@tonic-gate { 2377c478bd9Sstevel@tonic-gate syserr("main: reentered!"); 2387c478bd9Sstevel@tonic-gate abort(); 2397c478bd9Sstevel@tonic-gate } 2407c478bd9Sstevel@tonic-gate starttime = curtime(); 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* avoid null pointer dereferences */ 2437c478bd9Sstevel@tonic-gate TermEscape.te_rv_on = TermEscape.te_rv_off = ""; 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate RealUid = getuid(); 2467c478bd9Sstevel@tonic-gate RealGid = getgid(); 2477c478bd9Sstevel@tonic-gate 2487c478bd9Sstevel@tonic-gate /* Check if sendmail is running with extra privs */ 2497c478bd9Sstevel@tonic-gate extraprivs = (RealUid != 0 && 2507c478bd9Sstevel@tonic-gate (geteuid() != getuid() || getegid() != getgid())); 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate CurrentPid = getpid(); 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate /* get whatever .cf file is right for the opmode */ 2557c478bd9Sstevel@tonic-gate cftype = SM_GET_RIGHT_CF; 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate /* in 4.4BSD, the table can be huge; impose a reasonable limit */ 2587c478bd9Sstevel@tonic-gate DtableSize = getdtsize(); 2597c478bd9Sstevel@tonic-gate if (DtableSize > 256) 2607c478bd9Sstevel@tonic-gate DtableSize = 256; 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate /* 2637c478bd9Sstevel@tonic-gate ** Be sure we have enough file descriptors. 2647c478bd9Sstevel@tonic-gate ** But also be sure that 0, 1, & 2 are open. 2657c478bd9Sstevel@tonic-gate */ 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* reset errno and fill_errno; the latter is used way down below */ 2687c478bd9Sstevel@tonic-gate errno = fill_errno = 0; 2697c478bd9Sstevel@tonic-gate fill_fd(STDIN_FILENO, NULL); 2707c478bd9Sstevel@tonic-gate if (errno != 0) 2717c478bd9Sstevel@tonic-gate fill_errno = errno; 2727c478bd9Sstevel@tonic-gate fill_fd(STDOUT_FILENO, NULL); 2737c478bd9Sstevel@tonic-gate if (errno != 0) 2747c478bd9Sstevel@tonic-gate fill_errno = errno; 2757c478bd9Sstevel@tonic-gate fill_fd(STDERR_FILENO, NULL); 2767c478bd9Sstevel@tonic-gate if (errno != 0) 2777c478bd9Sstevel@tonic-gate fill_errno = errno; 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate sm_closefrom(STDERR_FILENO + 1, DtableSize); 2807c478bd9Sstevel@tonic-gate errno = 0; 2817c478bd9Sstevel@tonic-gate smdebug = NULL; 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate #if LOG 2847c478bd9Sstevel@tonic-gate # ifndef SM_LOG_STR 2857c478bd9Sstevel@tonic-gate # define SM_LOG_STR "sendmail" 2867c478bd9Sstevel@tonic-gate # endif /* ! SM_LOG_STR */ 2877c478bd9Sstevel@tonic-gate # ifdef LOG_MAIL 2887c478bd9Sstevel@tonic-gate openlog(SM_LOG_STR, LOG_PID, LOG_MAIL); 2897c478bd9Sstevel@tonic-gate # else /* LOG_MAIL */ 2907c478bd9Sstevel@tonic-gate openlog(SM_LOG_STR, LOG_PID); 2917c478bd9Sstevel@tonic-gate # endif /* LOG_MAIL */ 2927c478bd9Sstevel@tonic-gate #endif /* LOG */ 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate /* 2957c478bd9Sstevel@tonic-gate ** Seed the random number generator. 2967c478bd9Sstevel@tonic-gate ** Used for queue file names, picking a queue directory, and 2977c478bd9Sstevel@tonic-gate ** MX randomization. 2987c478bd9Sstevel@tonic-gate */ 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate seed_random(); 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* do machine-dependent initializations */ 3037c478bd9Sstevel@tonic-gate init_md(argc, argv); 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate SyslogPrefixLen = PIDLEN + (MAXQFNAME - 3) + SL_FUDGE + SLDLL; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate /* reset status from syserr() calls for missing file descriptors */ 3097c478bd9Sstevel@tonic-gate Errors = 0; 3107c478bd9Sstevel@tonic-gate ExitStat = EX_OK; 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate SubmitMode = SUBMIT_UNKNOWN; 3137c478bd9Sstevel@tonic-gate #if XDEBUG 3147c478bd9Sstevel@tonic-gate checkfd012("after openlog"); 3157c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate tTsetup(tTdvect, sizeof tTdvect, "0-99.1,*_trace_*.1"); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate #ifdef NGROUPS_MAX 3207c478bd9Sstevel@tonic-gate /* save initial group set for future checks */ 3217c478bd9Sstevel@tonic-gate i = getgroups(NGROUPS_MAX, InitialGidSet); 3227c478bd9Sstevel@tonic-gate if (i <= 0) 3237c478bd9Sstevel@tonic-gate { 3247c478bd9Sstevel@tonic-gate InitialGidSet[0] = (GID_T) -1; 3257c478bd9Sstevel@tonic-gate i = 0; 3267c478bd9Sstevel@tonic-gate } 3277c478bd9Sstevel@tonic-gate while (i < NGROUPS_MAX) 3287c478bd9Sstevel@tonic-gate InitialGidSet[i++] = InitialGidSet[0]; 3297c478bd9Sstevel@tonic-gate #endif /* NGROUPS_MAX */ 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate /* drop group id privileges (RunAsUser not yet set) */ 3327c478bd9Sstevel@tonic-gate dp = drop_privileges(false); 3337c478bd9Sstevel@tonic-gate setstat(dp); 3347c478bd9Sstevel@tonic-gate 3357c478bd9Sstevel@tonic-gate #ifdef SIGUSR1 3367c478bd9Sstevel@tonic-gate /* Only allow root (or non-set-*-ID binaries) to use SIGUSR1 */ 3377c478bd9Sstevel@tonic-gate if (!extraprivs) 3387c478bd9Sstevel@tonic-gate { 3397c478bd9Sstevel@tonic-gate /* arrange to dump state on user-1 signal */ 3407c478bd9Sstevel@tonic-gate (void) sm_signal(SIGUSR1, sigusr1); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate else 3437c478bd9Sstevel@tonic-gate { 3447c478bd9Sstevel@tonic-gate /* ignore user-1 signal */ 3457c478bd9Sstevel@tonic-gate (void) sm_signal(SIGUSR1, SIG_IGN); 3467c478bd9Sstevel@tonic-gate } 3477c478bd9Sstevel@tonic-gate #endif /* SIGUSR1 */ 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate /* initialize for setproctitle */ 3507c478bd9Sstevel@tonic-gate initsetproctitle(argc, argv, envp); 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate /* Handle any non-getoptable constructions. */ 3537c478bd9Sstevel@tonic-gate obsolete(argv); 3547c478bd9Sstevel@tonic-gate 3557c478bd9Sstevel@tonic-gate /* 3567c478bd9Sstevel@tonic-gate ** Do a quick prescan of the argument list. 3577c478bd9Sstevel@tonic-gate */ 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate /* find initial opMode */ 3617c478bd9Sstevel@tonic-gate OpMode = MD_DELIVER; 3627c478bd9Sstevel@tonic-gate av = argv; 3637c478bd9Sstevel@tonic-gate p = strrchr(*av, '/'); 3647c478bd9Sstevel@tonic-gate if (p++ == NULL) 3657c478bd9Sstevel@tonic-gate p = *av; 3667c478bd9Sstevel@tonic-gate if (strcmp(p, "newaliases") == 0) 3677c478bd9Sstevel@tonic-gate OpMode = MD_INITALIAS; 3687c478bd9Sstevel@tonic-gate else if (strcmp(p, "mailq") == 0) 3697c478bd9Sstevel@tonic-gate OpMode = MD_PRINT; 3707c478bd9Sstevel@tonic-gate else if (strcmp(p, "smtpd") == 0) 3717c478bd9Sstevel@tonic-gate OpMode = MD_DAEMON; 3727c478bd9Sstevel@tonic-gate else if (strcmp(p, "hoststat") == 0) 3737c478bd9Sstevel@tonic-gate OpMode = MD_HOSTSTAT; 3747c478bd9Sstevel@tonic-gate else if (strcmp(p, "purgestat") == 0) 3757c478bd9Sstevel@tonic-gate OpMode = MD_PURGESTAT; 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate #if defined(__osf__) || defined(_AIX3) 3787c478bd9Sstevel@tonic-gate # define OPTIONS "A:B:b:C:cD:d:e:F:f:Gh:IiL:M:mN:nO:o:p:Q:q:R:r:sTtV:vX:x" 3797c478bd9Sstevel@tonic-gate #endif /* defined(__osf__) || defined(_AIX3) */ 3807c478bd9Sstevel@tonic-gate #if defined(sony_news) 3817c478bd9Sstevel@tonic-gate # define OPTIONS "A:B:b:C:cD:d:E:e:F:f:Gh:IiJ:L:M:mN:nO:o:p:Q:q:R:r:sTtV:vX:" 3827c478bd9Sstevel@tonic-gate #endif /* defined(sony_news) */ 3837c478bd9Sstevel@tonic-gate #ifndef OPTIONS 3847c478bd9Sstevel@tonic-gate # define OPTIONS "A:B:b:C:cD:d:e:F:f:Gh:IiL:M:mN:nO:o:p:Q:q:R:r:sTtV:vX:" 3857c478bd9Sstevel@tonic-gate #endif /* ! OPTIONS */ 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate /* Set to 0 to allow -b; need to check optarg before using it! */ 3887c478bd9Sstevel@tonic-gate opterr = 0; 3897c478bd9Sstevel@tonic-gate while ((j = getopt(argc, argv, OPTIONS)) != -1) 3907c478bd9Sstevel@tonic-gate { 3917c478bd9Sstevel@tonic-gate switch (j) 3927c478bd9Sstevel@tonic-gate { 3937c478bd9Sstevel@tonic-gate case 'b': /* operations mode */ 3947c478bd9Sstevel@tonic-gate j = (optarg == NULL) ? ' ' : *optarg; 3957c478bd9Sstevel@tonic-gate switch (j) 3967c478bd9Sstevel@tonic-gate { 3977c478bd9Sstevel@tonic-gate case MD_DAEMON: 3987c478bd9Sstevel@tonic-gate case MD_FGDAEMON: 3997c478bd9Sstevel@tonic-gate case MD_SMTP: 4007c478bd9Sstevel@tonic-gate case MD_INITALIAS: 4017c478bd9Sstevel@tonic-gate case MD_DELIVER: 4027c478bd9Sstevel@tonic-gate case MD_VERIFY: 4037c478bd9Sstevel@tonic-gate case MD_TEST: 4047c478bd9Sstevel@tonic-gate case MD_PRINT: 4057c478bd9Sstevel@tonic-gate case MD_PRINTNQE: 4067c478bd9Sstevel@tonic-gate case MD_HOSTSTAT: 4077c478bd9Sstevel@tonic-gate case MD_PURGESTAT: 4087c478bd9Sstevel@tonic-gate case MD_ARPAFTP: 4097c478bd9Sstevel@tonic-gate OpMode = j; 4107c478bd9Sstevel@tonic-gate break; 4117c478bd9Sstevel@tonic-gate 4127c478bd9Sstevel@tonic-gate case MD_FREEZE: 4137c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4147c478bd9Sstevel@tonic-gate "Frozen configurations unsupported\n"); 4157c478bd9Sstevel@tonic-gate return EX_USAGE; 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate default: 4187c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4197c478bd9Sstevel@tonic-gate "Invalid operation mode %c\n", 4207c478bd9Sstevel@tonic-gate j); 4217c478bd9Sstevel@tonic-gate return EX_USAGE; 4227c478bd9Sstevel@tonic-gate } 4237c478bd9Sstevel@tonic-gate break; 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate case 'D': 4267c478bd9Sstevel@tonic-gate if (debug) 4277c478bd9Sstevel@tonic-gate { 4287c478bd9Sstevel@tonic-gate errno = 0; 4297c478bd9Sstevel@tonic-gate syserr("-D file must be before -d"); 4307c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 4317c478bd9Sstevel@tonic-gate break; 4327c478bd9Sstevel@tonic-gate } 4337c478bd9Sstevel@tonic-gate dp = drop_privileges(true); 4347c478bd9Sstevel@tonic-gate setstat(dp); 4357c478bd9Sstevel@tonic-gate smdebug = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, 4367c478bd9Sstevel@tonic-gate optarg, SM_IO_APPEND, NULL); 4377c478bd9Sstevel@tonic-gate if (smdebug == NULL) 4387c478bd9Sstevel@tonic-gate { 4397c478bd9Sstevel@tonic-gate syserr("cannot open %s", optarg); 4407c478bd9Sstevel@tonic-gate ExitStat = EX_CANTCREAT; 4417c478bd9Sstevel@tonic-gate break; 4427c478bd9Sstevel@tonic-gate } 4437c478bd9Sstevel@tonic-gate sm_debug_setfile(smdebug); 4447c478bd9Sstevel@tonic-gate break; 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate case 'd': 4477c478bd9Sstevel@tonic-gate debug = true; 4487c478bd9Sstevel@tonic-gate tTflag(optarg); 4497c478bd9Sstevel@tonic-gate (void) sm_io_setvbuf(sm_debug_file(), SM_TIME_DEFAULT, 4507c478bd9Sstevel@tonic-gate (char *) NULL, SM_IO_NBF, 4517c478bd9Sstevel@tonic-gate SM_IO_BUFSIZ); 4527c478bd9Sstevel@tonic-gate break; 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate case 'G': /* relay (gateway) submission */ 4557c478bd9Sstevel@tonic-gate SubmitMode = SUBMIT_MTA; 4567c478bd9Sstevel@tonic-gate break; 4577c478bd9Sstevel@tonic-gate 4587c478bd9Sstevel@tonic-gate case 'L': 4597c478bd9Sstevel@tonic-gate if (optarg == NULL) 4607c478bd9Sstevel@tonic-gate { 4617c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4627c478bd9Sstevel@tonic-gate "option requires an argument -- '%c'", 4637c478bd9Sstevel@tonic-gate (char) j); 4647c478bd9Sstevel@tonic-gate return EX_USAGE; 4657c478bd9Sstevel@tonic-gate } 4667c478bd9Sstevel@tonic-gate j = SM_MIN(strlen(optarg), 32) + 1; 4677c478bd9Sstevel@tonic-gate sysloglabel = xalloc(j); 4687c478bd9Sstevel@tonic-gate (void) sm_strlcpy(sysloglabel, optarg, j); 4697c478bd9Sstevel@tonic-gate SyslogPrefixLen = PIDLEN + (MAXQFNAME - 3) + 4707c478bd9Sstevel@tonic-gate SL_FUDGE + j; 4717c478bd9Sstevel@tonic-gate break; 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate case 'Q': 4747c478bd9Sstevel@tonic-gate case 'q': 4757c478bd9Sstevel@tonic-gate /* just check if it is there */ 4767c478bd9Sstevel@tonic-gate queuerun = true; 4777c478bd9Sstevel@tonic-gate break; 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate } 4807c478bd9Sstevel@tonic-gate opterr = 1; 4817c478bd9Sstevel@tonic-gate 4827c478bd9Sstevel@tonic-gate /* Don't leak queue information via debug flags */ 4837c478bd9Sstevel@tonic-gate if (extraprivs && queuerun && debug) 4847c478bd9Sstevel@tonic-gate { 4857c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 4867c478bd9Sstevel@tonic-gate "WARNING: Can not use -d with -q. Disabling debugging.\n"); 4877c478bd9Sstevel@tonic-gate sm_debug_close(); 4887c478bd9Sstevel@tonic-gate sm_debug_setfile(NULL); 4897c478bd9Sstevel@tonic-gate (void) memset(tTdvect, '\0', sizeof tTdvect); 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate #if LOG 4937c478bd9Sstevel@tonic-gate if (sysloglabel != NULL) 4947c478bd9Sstevel@tonic-gate { 4957c478bd9Sstevel@tonic-gate /* Sanitize the string */ 4967c478bd9Sstevel@tonic-gate for (p = sysloglabel; *p != '\0'; p++) 4977c478bd9Sstevel@tonic-gate { 4987c478bd9Sstevel@tonic-gate if (!isascii(*p) || !isprint(*p) || *p == '%') 4997c478bd9Sstevel@tonic-gate *p = '*'; 5007c478bd9Sstevel@tonic-gate } 5017c478bd9Sstevel@tonic-gate closelog(); 5027c478bd9Sstevel@tonic-gate # ifdef LOG_MAIL 5037c478bd9Sstevel@tonic-gate openlog(sysloglabel, LOG_PID, LOG_MAIL); 5047c478bd9Sstevel@tonic-gate # else /* LOG_MAIL */ 5057c478bd9Sstevel@tonic-gate openlog(sysloglabel, LOG_PID); 5067c478bd9Sstevel@tonic-gate # endif /* LOG_MAIL */ 5077c478bd9Sstevel@tonic-gate } 5087c478bd9Sstevel@tonic-gate #endif /* LOG */ 5097c478bd9Sstevel@tonic-gate 5107c478bd9Sstevel@tonic-gate /* set up the blank envelope */ 5117c478bd9Sstevel@tonic-gate BlankEnvelope.e_puthdr = putheader; 5127c478bd9Sstevel@tonic-gate BlankEnvelope.e_putbody = putbody; 5137c478bd9Sstevel@tonic-gate BlankEnvelope.e_xfp = NULL; 5147c478bd9Sstevel@tonic-gate STRUCTCOPY(NullAddress, BlankEnvelope.e_from); 5157c478bd9Sstevel@tonic-gate CurEnv = &BlankEnvelope; 5167c478bd9Sstevel@tonic-gate STRUCTCOPY(NullAddress, MainEnvelope.e_from); 5177c478bd9Sstevel@tonic-gate 5187c478bd9Sstevel@tonic-gate /* 5197c478bd9Sstevel@tonic-gate ** Set default values for variables. 5207c478bd9Sstevel@tonic-gate ** These cannot be in initialized data space. 5217c478bd9Sstevel@tonic-gate */ 5227c478bd9Sstevel@tonic-gate 5237c478bd9Sstevel@tonic-gate setdefaults(&BlankEnvelope); 5247c478bd9Sstevel@tonic-gate initmacros(&BlankEnvelope); 5257c478bd9Sstevel@tonic-gate 5267c478bd9Sstevel@tonic-gate /* reset macro */ 5277c478bd9Sstevel@tonic-gate set_op_mode(OpMode); 528*3ee0e492Sjbeck if (OpMode == MD_DAEMON) 529*3ee0e492Sjbeck DaemonPid = CurrentPid; /* needed for finis() to work */ 5307c478bd9Sstevel@tonic-gate 5317c478bd9Sstevel@tonic-gate pw = sm_getpwuid(RealUid); 5327c478bd9Sstevel@tonic-gate if (pw != NULL) 5337c478bd9Sstevel@tonic-gate (void) sm_strlcpy(rnamebuf, pw->pw_name, sizeof rnamebuf); 5347c478bd9Sstevel@tonic-gate else 5357c478bd9Sstevel@tonic-gate (void) sm_snprintf(rnamebuf, sizeof rnamebuf, "Unknown UID %d", 5367c478bd9Sstevel@tonic-gate (int) RealUid); 5377c478bd9Sstevel@tonic-gate 5387c478bd9Sstevel@tonic-gate RealUserName = rnamebuf; 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate if (tTd(0, 101)) 5417c478bd9Sstevel@tonic-gate { 5427c478bd9Sstevel@tonic-gate sm_dprintf("Version %s\n", Version); 5437c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 5447c478bd9Sstevel@tonic-gate /* NOTREACHED */ 5457c478bd9Sstevel@tonic-gate } 5467c478bd9Sstevel@tonic-gate 5477c478bd9Sstevel@tonic-gate /* 5487c478bd9Sstevel@tonic-gate ** if running non-set-user-ID binary as non-root, pretend 5497c478bd9Sstevel@tonic-gate ** we are the RunAsUid 5507c478bd9Sstevel@tonic-gate */ 5517c478bd9Sstevel@tonic-gate 5527c478bd9Sstevel@tonic-gate if (RealUid != 0 && geteuid() == RealUid) 5537c478bd9Sstevel@tonic-gate { 5547c478bd9Sstevel@tonic-gate if (tTd(47, 1)) 5557c478bd9Sstevel@tonic-gate sm_dprintf("Non-set-user-ID binary: RunAsUid = RealUid = %d\n", 5567c478bd9Sstevel@tonic-gate (int) RealUid); 5577c478bd9Sstevel@tonic-gate RunAsUid = RealUid; 5587c478bd9Sstevel@tonic-gate } 5597c478bd9Sstevel@tonic-gate else if (geteuid() != 0) 5607c478bd9Sstevel@tonic-gate RunAsUid = geteuid(); 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate EffGid = getegid(); 5637c478bd9Sstevel@tonic-gate if (RealUid != 0 && EffGid == RealGid) 5647c478bd9Sstevel@tonic-gate RunAsGid = RealGid; 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate if (tTd(47, 5)) 5677c478bd9Sstevel@tonic-gate { 5687c478bd9Sstevel@tonic-gate sm_dprintf("main: e/ruid = %d/%d e/rgid = %d/%d\n", 5697c478bd9Sstevel@tonic-gate (int) geteuid(), (int) getuid(), 5707c478bd9Sstevel@tonic-gate (int) getegid(), (int) getgid()); 5717c478bd9Sstevel@tonic-gate sm_dprintf("main: RunAsUser = %d:%d\n", 5727c478bd9Sstevel@tonic-gate (int) RunAsUid, (int) RunAsGid); 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate 5757c478bd9Sstevel@tonic-gate /* save command line arguments */ 5767c478bd9Sstevel@tonic-gate j = 0; 5777c478bd9Sstevel@tonic-gate for (av = argv; *av != NULL; ) 5787c478bd9Sstevel@tonic-gate j += strlen(*av++) + 1; 5797c478bd9Sstevel@tonic-gate SaveArgv = (char **) xalloc(sizeof (char *) * (argc + 1)); 5807c478bd9Sstevel@tonic-gate CommandLineArgs = xalloc(j); 5817c478bd9Sstevel@tonic-gate p = CommandLineArgs; 5827c478bd9Sstevel@tonic-gate for (av = argv, i = 0; *av != NULL; ) 5837c478bd9Sstevel@tonic-gate { 5847c478bd9Sstevel@tonic-gate int h; 5857c478bd9Sstevel@tonic-gate 5867c478bd9Sstevel@tonic-gate SaveArgv[i++] = newstr(*av); 5877c478bd9Sstevel@tonic-gate if (av != argv) 5887c478bd9Sstevel@tonic-gate *p++ = ' '; 5897c478bd9Sstevel@tonic-gate (void) sm_strlcpy(p, *av++, j); 5907c478bd9Sstevel@tonic-gate h = strlen(p); 5917c478bd9Sstevel@tonic-gate p += h; 5927c478bd9Sstevel@tonic-gate j -= h + 1; 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate SaveArgv[i] = NULL; 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate if (tTd(0, 1)) 5977c478bd9Sstevel@tonic-gate { 5987c478bd9Sstevel@tonic-gate extern char *CompileOptions[]; 5997c478bd9Sstevel@tonic-gate 6007c478bd9Sstevel@tonic-gate sm_dprintf("Version %s\n Compiled with:", Version); 6017c478bd9Sstevel@tonic-gate sm_printoptions(CompileOptions); 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate if (tTd(0, 10)) 6047c478bd9Sstevel@tonic-gate { 6057c478bd9Sstevel@tonic-gate extern char *OsCompileOptions[]; 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate sm_dprintf(" OS Defines:"); 6087c478bd9Sstevel@tonic-gate sm_printoptions(OsCompileOptions); 6097c478bd9Sstevel@tonic-gate #ifdef _PATH_UNIX 6107c478bd9Sstevel@tonic-gate sm_dprintf("Kernel symbols:\t%s\n", _PATH_UNIX); 6117c478bd9Sstevel@tonic-gate #endif /* _PATH_UNIX */ 6127c478bd9Sstevel@tonic-gate 6137c478bd9Sstevel@tonic-gate sm_dprintf(" Conf file:\t%s (default for MSP)\n", 6147c478bd9Sstevel@tonic-gate getcfname(OpMode, SubmitMode, SM_GET_SUBMIT_CF, 6157c478bd9Sstevel@tonic-gate conffile)); 6167c478bd9Sstevel@tonic-gate sm_dprintf(" Conf file:\t%s (default for MTA)\n", 6177c478bd9Sstevel@tonic-gate getcfname(OpMode, SubmitMode, SM_GET_SENDMAIL_CF, 6187c478bd9Sstevel@tonic-gate conffile)); 6197c478bd9Sstevel@tonic-gate sm_dprintf(" Pid file:\t%s (default)\n", PidFile); 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate if (tTd(0, 12)) 6237c478bd9Sstevel@tonic-gate { 6247c478bd9Sstevel@tonic-gate extern char *SmCompileOptions[]; 6257c478bd9Sstevel@tonic-gate 6267c478bd9Sstevel@tonic-gate sm_dprintf(" libsm Defines:"); 6277c478bd9Sstevel@tonic-gate sm_printoptions(SmCompileOptions); 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate if (tTd(0, 13)) 6317c478bd9Sstevel@tonic-gate { 6327c478bd9Sstevel@tonic-gate extern char *FFRCompileOptions[]; 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate sm_dprintf(" FFR Defines:"); 6357c478bd9Sstevel@tonic-gate sm_printoptions(FFRCompileOptions); 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate /* clear sendmail's environment */ 6397c478bd9Sstevel@tonic-gate ExternalEnviron = environ; 6407c478bd9Sstevel@tonic-gate emptyenviron[0] = NULL; 6417c478bd9Sstevel@tonic-gate environ = emptyenviron; 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate /* 6447c478bd9Sstevel@tonic-gate ** restore any original TZ setting until TimeZoneSpec has been 6457c478bd9Sstevel@tonic-gate ** determined - or early log messages may get bogus time stamps 6467c478bd9Sstevel@tonic-gate */ 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate if ((p = getextenv("TZ")) != NULL) 6497c478bd9Sstevel@tonic-gate { 6507c478bd9Sstevel@tonic-gate char *tz; 6517c478bd9Sstevel@tonic-gate int tzlen; 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate /* XXX check for reasonable length? */ 6547c478bd9Sstevel@tonic-gate tzlen = strlen(p) + 4; 6557c478bd9Sstevel@tonic-gate tz = xalloc(tzlen); 6567c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(tz, tzlen, 2, "TZ=", p); 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate /* XXX check return code? */ 6597c478bd9Sstevel@tonic-gate (void) putenv(tz); 6607c478bd9Sstevel@tonic-gate } 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate /* prime the child environment */ 663445f2479Sjbeck sm_setuserenv("AGENT", "sendmail"); 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate (void) sm_signal(SIGPIPE, SIG_IGN); 6667c478bd9Sstevel@tonic-gate OldUmask = umask(022); 6677c478bd9Sstevel@tonic-gate FullName = getextenv("NAME"); 6687c478bd9Sstevel@tonic-gate if (FullName != NULL) 6697c478bd9Sstevel@tonic-gate FullName = newstr(FullName); 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate /* 6727c478bd9Sstevel@tonic-gate ** Initialize name server if it is going to be used. 6737c478bd9Sstevel@tonic-gate */ 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate #if NAMED_BIND 6767c478bd9Sstevel@tonic-gate if (!bitset(RES_INIT, _res.options)) 6777c478bd9Sstevel@tonic-gate (void) res_init(); 6787c478bd9Sstevel@tonic-gate if (tTd(8, 8)) 6797c478bd9Sstevel@tonic-gate _res.options |= RES_DEBUG; 6807c478bd9Sstevel@tonic-gate else 6817c478bd9Sstevel@tonic-gate _res.options &= ~RES_DEBUG; 6827c478bd9Sstevel@tonic-gate # ifdef RES_NOALIASES 6837c478bd9Sstevel@tonic-gate _res.options |= RES_NOALIASES; 6847c478bd9Sstevel@tonic-gate # endif /* RES_NOALIASES */ 6857c478bd9Sstevel@tonic-gate TimeOuts.res_retry[RES_TO_DEFAULT] = _res.retry; 6867c478bd9Sstevel@tonic-gate TimeOuts.res_retry[RES_TO_FIRST] = _res.retry; 6877c478bd9Sstevel@tonic-gate TimeOuts.res_retry[RES_TO_NORMAL] = _res.retry; 6887c478bd9Sstevel@tonic-gate TimeOuts.res_retrans[RES_TO_DEFAULT] = _res.retrans; 6897c478bd9Sstevel@tonic-gate TimeOuts.res_retrans[RES_TO_FIRST] = _res.retrans; 6907c478bd9Sstevel@tonic-gate TimeOuts.res_retrans[RES_TO_NORMAL] = _res.retrans; 6917c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate errno = 0; 6947c478bd9Sstevel@tonic-gate from = NULL; 6957c478bd9Sstevel@tonic-gate 6967c478bd9Sstevel@tonic-gate /* initialize some macros, etc. */ 6977c478bd9Sstevel@tonic-gate init_vendor_macros(&BlankEnvelope); 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate /* version */ 7007c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 'v', Version); 7017c478bd9Sstevel@tonic-gate 7027c478bd9Sstevel@tonic-gate /* hostname */ 7037c478bd9Sstevel@tonic-gate hp = myhostname(jbuf, sizeof jbuf); 7047c478bd9Sstevel@tonic-gate if (jbuf[0] != '\0') 7057c478bd9Sstevel@tonic-gate { 7067c478bd9Sstevel@tonic-gate struct utsname utsname; 7077c478bd9Sstevel@tonic-gate 7087c478bd9Sstevel@tonic-gate if (tTd(0, 4)) 7097c478bd9Sstevel@tonic-gate sm_dprintf("Canonical name: %s\n", jbuf); 7107c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 'w', jbuf); 7117c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 'j', jbuf); 7127c478bd9Sstevel@tonic-gate setclass('w', jbuf); 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate p = strchr(jbuf, '.'); 7157c478bd9Sstevel@tonic-gate if (p != NULL && p[1] != '\0') 7167c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 'm', &p[1]); 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate if (uname(&utsname) >= 0) 7197c478bd9Sstevel@tonic-gate p = utsname.nodename; 7207c478bd9Sstevel@tonic-gate else 7217c478bd9Sstevel@tonic-gate { 7227c478bd9Sstevel@tonic-gate if (tTd(0, 22)) 7237c478bd9Sstevel@tonic-gate sm_dprintf("uname failed (%s)\n", 7247c478bd9Sstevel@tonic-gate sm_errstring(errno)); 7257c478bd9Sstevel@tonic-gate makelower(jbuf); 7267c478bd9Sstevel@tonic-gate p = jbuf; 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate if (tTd(0, 4)) 7297c478bd9Sstevel@tonic-gate sm_dprintf(" UUCP nodename: %s\n", p); 7307c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 'k', p); 7317c478bd9Sstevel@tonic-gate setclass('k', p); 7327c478bd9Sstevel@tonic-gate setclass('w', p); 7337c478bd9Sstevel@tonic-gate } 7347c478bd9Sstevel@tonic-gate if (hp != NULL) 7357c478bd9Sstevel@tonic-gate { 7367c478bd9Sstevel@tonic-gate for (av = hp->h_aliases; av != NULL && *av != NULL; av++) 7377c478bd9Sstevel@tonic-gate { 7387c478bd9Sstevel@tonic-gate if (tTd(0, 4)) 7397c478bd9Sstevel@tonic-gate sm_dprintf("\ta.k.a.: %s\n", *av); 7407c478bd9Sstevel@tonic-gate setclass('w', *av); 7417c478bd9Sstevel@tonic-gate } 7427c478bd9Sstevel@tonic-gate #if NETINET || NETINET6 7437c478bd9Sstevel@tonic-gate for (i = 0; i >= 0 && hp->h_addr_list[i] != NULL; i++) 7447c478bd9Sstevel@tonic-gate { 7457c478bd9Sstevel@tonic-gate # if NETINET6 7467c478bd9Sstevel@tonic-gate char *addr; 7477c478bd9Sstevel@tonic-gate char buf6[INET6_ADDRSTRLEN]; 7487c478bd9Sstevel@tonic-gate struct in6_addr ia6; 7497c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 7507c478bd9Sstevel@tonic-gate # if NETINET 7517c478bd9Sstevel@tonic-gate struct in_addr ia; 7527c478bd9Sstevel@tonic-gate # endif /* NETINET */ 7537c478bd9Sstevel@tonic-gate char ipbuf[103]; 7547c478bd9Sstevel@tonic-gate 7557c478bd9Sstevel@tonic-gate ipbuf[0] = '\0'; 7567c478bd9Sstevel@tonic-gate switch (hp->h_addrtype) 7577c478bd9Sstevel@tonic-gate { 7587c478bd9Sstevel@tonic-gate # if NETINET 7597c478bd9Sstevel@tonic-gate case AF_INET: 7607c478bd9Sstevel@tonic-gate if (hp->h_length != INADDRSZ) 7617c478bd9Sstevel@tonic-gate break; 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate memmove(&ia, hp->h_addr_list[i], INADDRSZ); 7647c478bd9Sstevel@tonic-gate (void) sm_snprintf(ipbuf, sizeof ipbuf, 7657c478bd9Sstevel@tonic-gate "[%.100s]", inet_ntoa(ia)); 7667c478bd9Sstevel@tonic-gate break; 7677c478bd9Sstevel@tonic-gate # endif /* NETINET */ 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate # if NETINET6 7707c478bd9Sstevel@tonic-gate case AF_INET6: 7717c478bd9Sstevel@tonic-gate if (hp->h_length != IN6ADDRSZ) 7727c478bd9Sstevel@tonic-gate break; 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate memmove(&ia6, hp->h_addr_list[i], IN6ADDRSZ); 7757c478bd9Sstevel@tonic-gate addr = anynet_ntop(&ia6, buf6, sizeof buf6); 7767c478bd9Sstevel@tonic-gate if (addr != NULL) 7777c478bd9Sstevel@tonic-gate (void) sm_snprintf(ipbuf, sizeof ipbuf, 7787c478bd9Sstevel@tonic-gate "[%.100s]", addr); 7797c478bd9Sstevel@tonic-gate break; 7807c478bd9Sstevel@tonic-gate # endif /* NETINET6 */ 7817c478bd9Sstevel@tonic-gate } 7827c478bd9Sstevel@tonic-gate if (ipbuf[0] == '\0') 7837c478bd9Sstevel@tonic-gate break; 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate if (tTd(0, 4)) 7867c478bd9Sstevel@tonic-gate sm_dprintf("\ta.k.a.: %s\n", ipbuf); 7877c478bd9Sstevel@tonic-gate setclass('w', ipbuf); 7887c478bd9Sstevel@tonic-gate } 7897c478bd9Sstevel@tonic-gate #endif /* NETINET || NETINET6 */ 7907c478bd9Sstevel@tonic-gate #if NETINET6 7917c478bd9Sstevel@tonic-gate freehostent(hp); 7927c478bd9Sstevel@tonic-gate hp = NULL; 7937c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 7947c478bd9Sstevel@tonic-gate } 7957c478bd9Sstevel@tonic-gate 7967c478bd9Sstevel@tonic-gate /* current time */ 7977c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 'b', arpadate((char *) NULL)); 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate /* current load average */ 8007c478bd9Sstevel@tonic-gate sm_getla(); 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate QueueLimitRecipient = (QUEUE_CHAR *) NULL; 8037c478bd9Sstevel@tonic-gate QueueLimitSender = (QUEUE_CHAR *) NULL; 8047c478bd9Sstevel@tonic-gate QueueLimitId = (QUEUE_CHAR *) NULL; 8057c478bd9Sstevel@tonic-gate QueueLimitQuarantine = (QUEUE_CHAR *) NULL; 8067c478bd9Sstevel@tonic-gate 8077c478bd9Sstevel@tonic-gate /* 8087c478bd9Sstevel@tonic-gate ** Crack argv. 8097c478bd9Sstevel@tonic-gate */ 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate optind = 1; 8127c478bd9Sstevel@tonic-gate while ((j = getopt(argc, argv, OPTIONS)) != -1) 8137c478bd9Sstevel@tonic-gate { 8147c478bd9Sstevel@tonic-gate switch (j) 8157c478bd9Sstevel@tonic-gate { 8167c478bd9Sstevel@tonic-gate case 'b': /* operations mode */ 8177c478bd9Sstevel@tonic-gate /* already done */ 8187c478bd9Sstevel@tonic-gate break; 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate case 'A': /* use Alternate sendmail/submit.cf */ 8217c478bd9Sstevel@tonic-gate cftype = optarg[0] == 'c' ? SM_GET_SUBMIT_CF 8227c478bd9Sstevel@tonic-gate : SM_GET_SENDMAIL_CF; 8237c478bd9Sstevel@tonic-gate break; 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate case 'B': /* body type */ 8267c478bd9Sstevel@tonic-gate CHECK_AGAINST_OPMODE(j); 8277c478bd9Sstevel@tonic-gate BlankEnvelope.e_bodytype = newstr(optarg); 8287c478bd9Sstevel@tonic-gate break; 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate case 'C': /* select configuration file (already done) */ 8317c478bd9Sstevel@tonic-gate if (RealUid != 0) 8327c478bd9Sstevel@tonic-gate warn_C_flag = true; 8337c478bd9Sstevel@tonic-gate conffile = newstr(optarg); 8347c478bd9Sstevel@tonic-gate dp = drop_privileges(true); 8357c478bd9Sstevel@tonic-gate setstat(dp); 8367c478bd9Sstevel@tonic-gate safecf = false; 8377c478bd9Sstevel@tonic-gate break; 8387c478bd9Sstevel@tonic-gate 8397c478bd9Sstevel@tonic-gate case 'D': 8407c478bd9Sstevel@tonic-gate case 'd': /* debugging */ 8417c478bd9Sstevel@tonic-gate /* already done */ 8427c478bd9Sstevel@tonic-gate break; 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate case 'f': /* from address */ 8457c478bd9Sstevel@tonic-gate case 'r': /* obsolete -f flag */ 8467c478bd9Sstevel@tonic-gate CHECK_AGAINST_OPMODE(j); 8477c478bd9Sstevel@tonic-gate if (from != NULL) 8487c478bd9Sstevel@tonic-gate { 8497c478bd9Sstevel@tonic-gate usrerr("More than one \"from\" person"); 8507c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 8517c478bd9Sstevel@tonic-gate break; 8527c478bd9Sstevel@tonic-gate } 8537c478bd9Sstevel@tonic-gate if (optarg[0] == '\0') 8547c478bd9Sstevel@tonic-gate from = newstr("<>"); 8557c478bd9Sstevel@tonic-gate else 8567c478bd9Sstevel@tonic-gate from = newstr(denlstring(optarg, true, true)); 8577c478bd9Sstevel@tonic-gate if (strcmp(RealUserName, from) != 0) 8587c478bd9Sstevel@tonic-gate warn_f_flag = j; 8597c478bd9Sstevel@tonic-gate break; 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate case 'F': /* set full name */ 8627c478bd9Sstevel@tonic-gate CHECK_AGAINST_OPMODE(j); 8637c478bd9Sstevel@tonic-gate FullName = newstr(optarg); 8647c478bd9Sstevel@tonic-gate break; 8657c478bd9Sstevel@tonic-gate 8667c478bd9Sstevel@tonic-gate case 'G': /* relay (gateway) submission */ 8677c478bd9Sstevel@tonic-gate /* already set */ 8687c478bd9Sstevel@tonic-gate CHECK_AGAINST_OPMODE(j); 8697c478bd9Sstevel@tonic-gate break; 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate case 'h': /* hop count */ 8727c478bd9Sstevel@tonic-gate CHECK_AGAINST_OPMODE(j); 8737c478bd9Sstevel@tonic-gate BlankEnvelope.e_hopcount = (short) strtol(optarg, &ep, 8747c478bd9Sstevel@tonic-gate 10); 8757c478bd9Sstevel@tonic-gate (void) sm_snprintf(buf, sizeof buf, "%d", 8767c478bd9Sstevel@tonic-gate BlankEnvelope.e_hopcount); 8777c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 'c', buf); 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate if (*ep) 8807c478bd9Sstevel@tonic-gate { 8817c478bd9Sstevel@tonic-gate usrerr("Bad hop count (%s)", optarg); 8827c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 8837c478bd9Sstevel@tonic-gate } 8847c478bd9Sstevel@tonic-gate break; 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate case 'L': /* program label */ 8877c478bd9Sstevel@tonic-gate /* already set */ 8887c478bd9Sstevel@tonic-gate break; 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate case 'n': /* don't alias */ 8917c478bd9Sstevel@tonic-gate CHECK_AGAINST_OPMODE(j); 8927c478bd9Sstevel@tonic-gate NoAlias = true; 8937c478bd9Sstevel@tonic-gate break; 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate case 'N': /* delivery status notifications */ 8967c478bd9Sstevel@tonic-gate CHECK_AGAINST_OPMODE(j); 8977c478bd9Sstevel@tonic-gate DefaultNotify |= QHASNOTIFY; 8987c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 8997c478bd9Sstevel@tonic-gate macid("{dsn_notify}"), optarg); 9007c478bd9Sstevel@tonic-gate if (sm_strcasecmp(optarg, "never") == 0) 9017c478bd9Sstevel@tonic-gate break; 9027c478bd9Sstevel@tonic-gate for (p = optarg; p != NULL; optarg = p) 9037c478bd9Sstevel@tonic-gate { 9047c478bd9Sstevel@tonic-gate p = strchr(p, ','); 9057c478bd9Sstevel@tonic-gate if (p != NULL) 9067c478bd9Sstevel@tonic-gate *p++ = '\0'; 9077c478bd9Sstevel@tonic-gate if (sm_strcasecmp(optarg, "success") == 0) 9087c478bd9Sstevel@tonic-gate DefaultNotify |= QPINGONSUCCESS; 9097c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(optarg, "failure") == 0) 9107c478bd9Sstevel@tonic-gate DefaultNotify |= QPINGONFAILURE; 9117c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(optarg, "delay") == 0) 9127c478bd9Sstevel@tonic-gate DefaultNotify |= QPINGONDELAY; 9137c478bd9Sstevel@tonic-gate else 9147c478bd9Sstevel@tonic-gate { 9157c478bd9Sstevel@tonic-gate usrerr("Invalid -N argument"); 9167c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 9177c478bd9Sstevel@tonic-gate } 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate break; 9207c478bd9Sstevel@tonic-gate 9217c478bd9Sstevel@tonic-gate case 'o': /* set option */ 9227c478bd9Sstevel@tonic-gate setoption(*optarg, optarg + 1, false, true, 9237c478bd9Sstevel@tonic-gate &BlankEnvelope); 9247c478bd9Sstevel@tonic-gate break; 9257c478bd9Sstevel@tonic-gate 9267c478bd9Sstevel@tonic-gate case 'O': /* set option (long form) */ 9277c478bd9Sstevel@tonic-gate setoption(' ', optarg, false, true, &BlankEnvelope); 9287c478bd9Sstevel@tonic-gate break; 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate case 'p': /* set protocol */ 9317c478bd9Sstevel@tonic-gate CHECK_AGAINST_OPMODE(j); 9327c478bd9Sstevel@tonic-gate p = strchr(optarg, ':'); 9337c478bd9Sstevel@tonic-gate if (p != NULL) 9347c478bd9Sstevel@tonic-gate { 9357c478bd9Sstevel@tonic-gate *p++ = '\0'; 9367c478bd9Sstevel@tonic-gate if (*p != '\0') 9377c478bd9Sstevel@tonic-gate { 9387c478bd9Sstevel@tonic-gate i = strlen(p) + 1; 9397c478bd9Sstevel@tonic-gate ep = sm_malloc_x(i); 9407c478bd9Sstevel@tonic-gate cleanstrcpy(ep, p, i); 9417c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, 9427c478bd9Sstevel@tonic-gate A_HEAP, 's', ep); 9437c478bd9Sstevel@tonic-gate } 9447c478bd9Sstevel@tonic-gate } 9457c478bd9Sstevel@tonic-gate if (*optarg != '\0') 9467c478bd9Sstevel@tonic-gate { 9477c478bd9Sstevel@tonic-gate i = strlen(optarg) + 1; 9487c478bd9Sstevel@tonic-gate ep = sm_malloc_x(i); 9497c478bd9Sstevel@tonic-gate cleanstrcpy(ep, optarg, i); 9507c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_HEAP, 9517c478bd9Sstevel@tonic-gate 'r', ep); 9527c478bd9Sstevel@tonic-gate } 9537c478bd9Sstevel@tonic-gate break; 9547c478bd9Sstevel@tonic-gate 9557c478bd9Sstevel@tonic-gate case 'Q': /* change quarantining on queued items */ 9567c478bd9Sstevel@tonic-gate /* sanity check */ 9577c478bd9Sstevel@tonic-gate if (OpMode != MD_DELIVER && 9587c478bd9Sstevel@tonic-gate OpMode != MD_QUEUERUN) 9597c478bd9Sstevel@tonic-gate { 9607c478bd9Sstevel@tonic-gate usrerr("Can not use -Q with -b%c", OpMode); 9617c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 9627c478bd9Sstevel@tonic-gate break; 9637c478bd9Sstevel@tonic-gate } 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate if (OpMode == MD_DELIVER) 9667c478bd9Sstevel@tonic-gate set_op_mode(MD_QUEUERUN); 9677c478bd9Sstevel@tonic-gate 9687c478bd9Sstevel@tonic-gate FullName = NULL; 9697c478bd9Sstevel@tonic-gate 9707c478bd9Sstevel@tonic-gate quarantining = newstr(optarg); 9717c478bd9Sstevel@tonic-gate break; 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate case 'q': /* run queue files at intervals */ 9747c478bd9Sstevel@tonic-gate /* sanity check */ 9757c478bd9Sstevel@tonic-gate if (OpMode != MD_DELIVER && 9767c478bd9Sstevel@tonic-gate OpMode != MD_DAEMON && 9777c478bd9Sstevel@tonic-gate OpMode != MD_FGDAEMON && 9787c478bd9Sstevel@tonic-gate OpMode != MD_PRINT && 9797c478bd9Sstevel@tonic-gate OpMode != MD_PRINTNQE && 9807c478bd9Sstevel@tonic-gate OpMode != MD_QUEUERUN) 9817c478bd9Sstevel@tonic-gate { 9827c478bd9Sstevel@tonic-gate usrerr("Can not use -q with -b%c", OpMode); 9837c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 9847c478bd9Sstevel@tonic-gate break; 9857c478bd9Sstevel@tonic-gate } 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate /* don't override -bd, -bD or -bp */ 9887c478bd9Sstevel@tonic-gate if (OpMode == MD_DELIVER) 9897c478bd9Sstevel@tonic-gate set_op_mode(MD_QUEUERUN); 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate FullName = NULL; 9927c478bd9Sstevel@tonic-gate negate = optarg[0] == '!'; 9937c478bd9Sstevel@tonic-gate if (negate) 9947c478bd9Sstevel@tonic-gate { 9957c478bd9Sstevel@tonic-gate /* negate meaning of pattern match */ 9967c478bd9Sstevel@tonic-gate optarg++; /* skip '!' for next switch */ 9977c478bd9Sstevel@tonic-gate } 9987c478bd9Sstevel@tonic-gate 9997c478bd9Sstevel@tonic-gate switch (optarg[0]) 10007c478bd9Sstevel@tonic-gate { 10017c478bd9Sstevel@tonic-gate case 'G': /* Limit by queue group name */ 10027c478bd9Sstevel@tonic-gate if (negate) 10037c478bd9Sstevel@tonic-gate { 10047c478bd9Sstevel@tonic-gate usrerr("Can not use -q!G"); 10057c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 10067c478bd9Sstevel@tonic-gate break; 10077c478bd9Sstevel@tonic-gate } 10087c478bd9Sstevel@tonic-gate if (queuegroup != NULL) 10097c478bd9Sstevel@tonic-gate { 10107c478bd9Sstevel@tonic-gate usrerr("Can not use multiple -qG options"); 10117c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 10127c478bd9Sstevel@tonic-gate break; 10137c478bd9Sstevel@tonic-gate } 10147c478bd9Sstevel@tonic-gate queuegroup = newstr(&optarg[1]); 10157c478bd9Sstevel@tonic-gate break; 10167c478bd9Sstevel@tonic-gate 10177c478bd9Sstevel@tonic-gate case 'I': /* Limit by ID */ 10187c478bd9Sstevel@tonic-gate new = (QUEUE_CHAR *) xalloc(sizeof *new); 10197c478bd9Sstevel@tonic-gate new->queue_match = newstr(&optarg[1]); 10207c478bd9Sstevel@tonic-gate new->queue_negate = negate; 10217c478bd9Sstevel@tonic-gate new->queue_next = QueueLimitId; 10227c478bd9Sstevel@tonic-gate QueueLimitId = new; 10237c478bd9Sstevel@tonic-gate break; 10247c478bd9Sstevel@tonic-gate 10257c478bd9Sstevel@tonic-gate case 'R': /* Limit by recipient */ 10267c478bd9Sstevel@tonic-gate new = (QUEUE_CHAR *) xalloc(sizeof *new); 10277c478bd9Sstevel@tonic-gate new->queue_match = newstr(&optarg[1]); 10287c478bd9Sstevel@tonic-gate new->queue_negate = negate; 10297c478bd9Sstevel@tonic-gate new->queue_next = QueueLimitRecipient; 10307c478bd9Sstevel@tonic-gate QueueLimitRecipient = new; 10317c478bd9Sstevel@tonic-gate break; 10327c478bd9Sstevel@tonic-gate 10337c478bd9Sstevel@tonic-gate case 'S': /* Limit by sender */ 10347c478bd9Sstevel@tonic-gate new = (QUEUE_CHAR *) xalloc(sizeof *new); 10357c478bd9Sstevel@tonic-gate new->queue_match = newstr(&optarg[1]); 10367c478bd9Sstevel@tonic-gate new->queue_negate = negate; 10377c478bd9Sstevel@tonic-gate new->queue_next = QueueLimitSender; 10387c478bd9Sstevel@tonic-gate QueueLimitSender = new; 10397c478bd9Sstevel@tonic-gate break; 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate case 'f': /* foreground queue run */ 10427c478bd9Sstevel@tonic-gate foregroundqueue = true; 10437c478bd9Sstevel@tonic-gate break; 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate case 'Q': /* Limit by quarantine message */ 10467c478bd9Sstevel@tonic-gate if (optarg[1] != '\0') 10477c478bd9Sstevel@tonic-gate { 10487c478bd9Sstevel@tonic-gate new = (QUEUE_CHAR *) xalloc(sizeof *new); 10497c478bd9Sstevel@tonic-gate new->queue_match = newstr(&optarg[1]); 10507c478bd9Sstevel@tonic-gate new->queue_negate = negate; 10517c478bd9Sstevel@tonic-gate new->queue_next = QueueLimitQuarantine; 10527c478bd9Sstevel@tonic-gate QueueLimitQuarantine = new; 10537c478bd9Sstevel@tonic-gate } 10547c478bd9Sstevel@tonic-gate QueueMode = QM_QUARANTINE; 10557c478bd9Sstevel@tonic-gate break; 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate case 'L': /* act on lost items */ 10587c478bd9Sstevel@tonic-gate QueueMode = QM_LOST; 10597c478bd9Sstevel@tonic-gate break; 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate case 'p': /* Persistent queue */ 10627c478bd9Sstevel@tonic-gate queuepersistent = true; 10637c478bd9Sstevel@tonic-gate if (QueueIntvl == 0) 10647c478bd9Sstevel@tonic-gate QueueIntvl = 1; 10657c478bd9Sstevel@tonic-gate if (optarg[1] == '\0') 10667c478bd9Sstevel@tonic-gate break; 10677c478bd9Sstevel@tonic-gate ++optarg; 10687c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 10697c478bd9Sstevel@tonic-gate 10707c478bd9Sstevel@tonic-gate default: 10717c478bd9Sstevel@tonic-gate i = Errors; 10727c478bd9Sstevel@tonic-gate QueueIntvl = convtime(optarg, 'm'); 10737c478bd9Sstevel@tonic-gate if (QueueIntvl < 0) 10747c478bd9Sstevel@tonic-gate { 10757c478bd9Sstevel@tonic-gate usrerr("Invalid -q value"); 10767c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 10777c478bd9Sstevel@tonic-gate } 10787c478bd9Sstevel@tonic-gate 10797c478bd9Sstevel@tonic-gate /* check for bad conversion */ 10807c478bd9Sstevel@tonic-gate if (i < Errors) 10817c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 10827c478bd9Sstevel@tonic-gate break; 10837c478bd9Sstevel@tonic-gate } 10847c478bd9Sstevel@tonic-gate break; 10857c478bd9Sstevel@tonic-gate 10867c478bd9Sstevel@tonic-gate case 'R': /* DSN RET: what to return */ 10877c478bd9Sstevel@tonic-gate CHECK_AGAINST_OPMODE(j); 10887c478bd9Sstevel@tonic-gate if (bitset(EF_RET_PARAM, BlankEnvelope.e_flags)) 10897c478bd9Sstevel@tonic-gate { 10907c478bd9Sstevel@tonic-gate usrerr("Duplicate -R flag"); 10917c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 10927c478bd9Sstevel@tonic-gate break; 10937c478bd9Sstevel@tonic-gate } 10947c478bd9Sstevel@tonic-gate BlankEnvelope.e_flags |= EF_RET_PARAM; 10957c478bd9Sstevel@tonic-gate if (sm_strcasecmp(optarg, "hdrs") == 0) 10967c478bd9Sstevel@tonic-gate BlankEnvelope.e_flags |= EF_NO_BODY_RETN; 10977c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(optarg, "full") != 0) 10987c478bd9Sstevel@tonic-gate { 10997c478bd9Sstevel@tonic-gate usrerr("Invalid -R value"); 11007c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 11017c478bd9Sstevel@tonic-gate } 11027c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 11037c478bd9Sstevel@tonic-gate macid("{dsn_ret}"), optarg); 11047c478bd9Sstevel@tonic-gate break; 11057c478bd9Sstevel@tonic-gate 11067c478bd9Sstevel@tonic-gate case 't': /* read recipients from message */ 11077c478bd9Sstevel@tonic-gate CHECK_AGAINST_OPMODE(j); 11087c478bd9Sstevel@tonic-gate GrabTo = true; 11097c478bd9Sstevel@tonic-gate break; 11107c478bd9Sstevel@tonic-gate 11117c478bd9Sstevel@tonic-gate case 'V': /* DSN ENVID: set "original" envelope id */ 11127c478bd9Sstevel@tonic-gate CHECK_AGAINST_OPMODE(j); 11137c478bd9Sstevel@tonic-gate if (!xtextok(optarg)) 11147c478bd9Sstevel@tonic-gate { 11157c478bd9Sstevel@tonic-gate usrerr("Invalid syntax in -V flag"); 11167c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 11177c478bd9Sstevel@tonic-gate } 11187c478bd9Sstevel@tonic-gate else 11197c478bd9Sstevel@tonic-gate { 11207c478bd9Sstevel@tonic-gate BlankEnvelope.e_envid = newstr(optarg); 11217c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 11227c478bd9Sstevel@tonic-gate macid("{dsn_envid}"), optarg); 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate break; 11257c478bd9Sstevel@tonic-gate 11267c478bd9Sstevel@tonic-gate case 'X': /* traffic log file */ 11277c478bd9Sstevel@tonic-gate dp = drop_privileges(true); 11287c478bd9Sstevel@tonic-gate setstat(dp); 11297c478bd9Sstevel@tonic-gate if (stat(optarg, &traf_st) == 0 && 11307c478bd9Sstevel@tonic-gate S_ISFIFO(traf_st.st_mode)) 11317c478bd9Sstevel@tonic-gate TrafficLogFile = sm_io_open(SmFtStdio, 11327c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 11337c478bd9Sstevel@tonic-gate optarg, 11347c478bd9Sstevel@tonic-gate SM_IO_WRONLY, NULL); 11357c478bd9Sstevel@tonic-gate else 11367c478bd9Sstevel@tonic-gate TrafficLogFile = sm_io_open(SmFtStdio, 11377c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 11387c478bd9Sstevel@tonic-gate optarg, 11397c478bd9Sstevel@tonic-gate SM_IO_APPEND, NULL); 11407c478bd9Sstevel@tonic-gate if (TrafficLogFile == NULL) 11417c478bd9Sstevel@tonic-gate { 11427c478bd9Sstevel@tonic-gate syserr("cannot open %s", optarg); 11437c478bd9Sstevel@tonic-gate ExitStat = EX_CANTCREAT; 11447c478bd9Sstevel@tonic-gate break; 11457c478bd9Sstevel@tonic-gate } 11467c478bd9Sstevel@tonic-gate (void) sm_io_setvbuf(TrafficLogFile, SM_TIME_DEFAULT, 11477c478bd9Sstevel@tonic-gate NULL, SM_IO_LBF, 0); 11487c478bd9Sstevel@tonic-gate break; 11497c478bd9Sstevel@tonic-gate 11507c478bd9Sstevel@tonic-gate /* compatibility flags */ 11517c478bd9Sstevel@tonic-gate case 'c': /* connect to non-local mailers */ 11527c478bd9Sstevel@tonic-gate case 'i': /* don't let dot stop me */ 11537c478bd9Sstevel@tonic-gate case 'm': /* send to me too */ 11547c478bd9Sstevel@tonic-gate case 'T': /* set timeout interval */ 11557c478bd9Sstevel@tonic-gate case 'v': /* give blow-by-blow description */ 11567c478bd9Sstevel@tonic-gate setoption(j, "T", false, true, &BlankEnvelope); 11577c478bd9Sstevel@tonic-gate break; 11587c478bd9Sstevel@tonic-gate 11597c478bd9Sstevel@tonic-gate case 'e': /* error message disposition */ 11607c478bd9Sstevel@tonic-gate case 'M': /* define macro */ 11617c478bd9Sstevel@tonic-gate setoption(j, optarg, false, true, &BlankEnvelope); 11627c478bd9Sstevel@tonic-gate break; 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate case 's': /* save From lines in headers */ 11657c478bd9Sstevel@tonic-gate setoption('f', "T", false, true, &BlankEnvelope); 11667c478bd9Sstevel@tonic-gate break; 11677c478bd9Sstevel@tonic-gate 11687c478bd9Sstevel@tonic-gate #ifdef DBM 11697c478bd9Sstevel@tonic-gate case 'I': /* initialize alias DBM file */ 11707c478bd9Sstevel@tonic-gate set_op_mode(MD_INITALIAS); 11717c478bd9Sstevel@tonic-gate break; 11727c478bd9Sstevel@tonic-gate #endif /* DBM */ 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate #if defined(__osf__) || defined(_AIX3) 11757c478bd9Sstevel@tonic-gate case 'x': /* random flag that OSF/1 & AIX mailx passes */ 11767c478bd9Sstevel@tonic-gate break; 11777c478bd9Sstevel@tonic-gate #endif /* defined(__osf__) || defined(_AIX3) */ 11787c478bd9Sstevel@tonic-gate #if defined(sony_news) 11797c478bd9Sstevel@tonic-gate case 'E': 11807c478bd9Sstevel@tonic-gate case 'J': /* ignore flags for Japanese code conversion 11817c478bd9Sstevel@tonic-gate implemented on Sony NEWS */ 11827c478bd9Sstevel@tonic-gate break; 11837c478bd9Sstevel@tonic-gate #endif /* defined(sony_news) */ 11847c478bd9Sstevel@tonic-gate 11857c478bd9Sstevel@tonic-gate default: 11867c478bd9Sstevel@tonic-gate finis(true, true, EX_USAGE); 11877c478bd9Sstevel@tonic-gate /* NOTREACHED */ 11887c478bd9Sstevel@tonic-gate break; 11897c478bd9Sstevel@tonic-gate } 11907c478bd9Sstevel@tonic-gate } 11917c478bd9Sstevel@tonic-gate 11927c478bd9Sstevel@tonic-gate /* if we've had errors so far, exit now */ 11937c478bd9Sstevel@tonic-gate if ((ExitStat != EX_OK && OpMode != MD_TEST) || 11947c478bd9Sstevel@tonic-gate ExitStat == EX_OSERR) 11957c478bd9Sstevel@tonic-gate { 11967c478bd9Sstevel@tonic-gate finis(false, true, ExitStat); 11977c478bd9Sstevel@tonic-gate /* NOTREACHED */ 11987c478bd9Sstevel@tonic-gate } 11997c478bd9Sstevel@tonic-gate 12007c478bd9Sstevel@tonic-gate if (bitset(SUBMIT_MTA, SubmitMode)) 12017c478bd9Sstevel@tonic-gate { 12027c478bd9Sstevel@tonic-gate /* If set daemon_flags on command line, don't reset it */ 12037c478bd9Sstevel@tonic-gate if (macvalue(macid("{daemon_flags}"), &BlankEnvelope) == NULL) 12047c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 12057c478bd9Sstevel@tonic-gate macid("{daemon_flags}"), "CC f"); 12067c478bd9Sstevel@tonic-gate } 12077c478bd9Sstevel@tonic-gate else if (OpMode == MD_DELIVER || OpMode == MD_SMTP) 12087c478bd9Sstevel@tonic-gate { 12097c478bd9Sstevel@tonic-gate SubmitMode = SUBMIT_MSA; 12107c478bd9Sstevel@tonic-gate 12117c478bd9Sstevel@tonic-gate /* If set daemon_flags on command line, don't reset it */ 12127c478bd9Sstevel@tonic-gate if (macvalue(macid("{daemon_flags}"), &BlankEnvelope) == NULL) 12137c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 12147c478bd9Sstevel@tonic-gate macid("{daemon_flags}"), "c u"); 12157c478bd9Sstevel@tonic-gate } 12167c478bd9Sstevel@tonic-gate 12177c478bd9Sstevel@tonic-gate /* 12187c478bd9Sstevel@tonic-gate ** Do basic initialization. 12197c478bd9Sstevel@tonic-gate ** Read system control file. 12207c478bd9Sstevel@tonic-gate ** Extract special fields for local use. 12217c478bd9Sstevel@tonic-gate */ 12227c478bd9Sstevel@tonic-gate 12237c478bd9Sstevel@tonic-gate #if XDEBUG 12247c478bd9Sstevel@tonic-gate checkfd012("before readcf"); 12257c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 12267c478bd9Sstevel@tonic-gate vendor_pre_defaults(&BlankEnvelope); 12277c478bd9Sstevel@tonic-gate 12287c478bd9Sstevel@tonic-gate readcf(getcfname(OpMode, SubmitMode, cftype, conffile), 12297c478bd9Sstevel@tonic-gate safecf, &BlankEnvelope); 12307c478bd9Sstevel@tonic-gate #if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) 12317c478bd9Sstevel@tonic-gate ConfigFileRead = true; 12327c478bd9Sstevel@tonic-gate #endif /* !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) */ 12337c478bd9Sstevel@tonic-gate vendor_post_defaults(&BlankEnvelope); 12347c478bd9Sstevel@tonic-gate 12357c478bd9Sstevel@tonic-gate /* now we can complain about missing fds */ 12367c478bd9Sstevel@tonic-gate if (MissingFds != 0 && LogLevel > 8) 12377c478bd9Sstevel@tonic-gate { 12387c478bd9Sstevel@tonic-gate char mbuf[MAXLINE]; 12397c478bd9Sstevel@tonic-gate 12407c478bd9Sstevel@tonic-gate mbuf[0] = '\0'; 12417c478bd9Sstevel@tonic-gate if (bitset(1 << STDIN_FILENO, MissingFds)) 12427c478bd9Sstevel@tonic-gate (void) sm_strlcat(mbuf, ", stdin", sizeof mbuf); 12437c478bd9Sstevel@tonic-gate if (bitset(1 << STDOUT_FILENO, MissingFds)) 12447c478bd9Sstevel@tonic-gate (void) sm_strlcat(mbuf, ", stdout", sizeof mbuf); 12457c478bd9Sstevel@tonic-gate if (bitset(1 << STDERR_FILENO, MissingFds)) 12467c478bd9Sstevel@tonic-gate (void) sm_strlcat(mbuf, ", stderr", sizeof mbuf); 12477c478bd9Sstevel@tonic-gate 12487c478bd9Sstevel@tonic-gate /* Notice: fill_errno is from high above: fill_fd() */ 12497c478bd9Sstevel@tonic-gate sm_syslog(LOG_WARNING, NOQID, 12507c478bd9Sstevel@tonic-gate "File descriptors missing on startup: %s; %s", 12517c478bd9Sstevel@tonic-gate &mbuf[2], sm_errstring(fill_errno)); 12527c478bd9Sstevel@tonic-gate } 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate /* Remove the ability for a normal user to send signals */ 12557c478bd9Sstevel@tonic-gate if (RealUid != 0 && RealUid != geteuid()) 12567c478bd9Sstevel@tonic-gate { 12577c478bd9Sstevel@tonic-gate uid_t new_uid = geteuid(); 12587c478bd9Sstevel@tonic-gate 12597c478bd9Sstevel@tonic-gate #if HASSETREUID 12607c478bd9Sstevel@tonic-gate /* 12617c478bd9Sstevel@tonic-gate ** Since we can differentiate between uid and euid, 12627c478bd9Sstevel@tonic-gate ** make the uid a different user so the real user 12637c478bd9Sstevel@tonic-gate ** can't send signals. However, it doesn't need to be 12647c478bd9Sstevel@tonic-gate ** root (euid has root). 12657c478bd9Sstevel@tonic-gate */ 12667c478bd9Sstevel@tonic-gate 12677c478bd9Sstevel@tonic-gate if (new_uid == 0) 12687c478bd9Sstevel@tonic-gate new_uid = DefUid; 12697c478bd9Sstevel@tonic-gate if (tTd(47, 5)) 12707c478bd9Sstevel@tonic-gate sm_dprintf("Changing real uid to %d\n", (int) new_uid); 12717c478bd9Sstevel@tonic-gate if (setreuid(new_uid, geteuid()) < 0) 12727c478bd9Sstevel@tonic-gate { 12737c478bd9Sstevel@tonic-gate syserr("main: setreuid(%d, %d) failed", 12747c478bd9Sstevel@tonic-gate (int) new_uid, (int) geteuid()); 12757c478bd9Sstevel@tonic-gate finis(false, true, EX_OSERR); 12767c478bd9Sstevel@tonic-gate /* NOTREACHED */ 12777c478bd9Sstevel@tonic-gate } 12787c478bd9Sstevel@tonic-gate if (tTd(47, 10)) 12797c478bd9Sstevel@tonic-gate sm_dprintf("Now running as e/ruid %d:%d\n", 12807c478bd9Sstevel@tonic-gate (int) geteuid(), (int) getuid()); 12817c478bd9Sstevel@tonic-gate #else /* HASSETREUID */ 12827c478bd9Sstevel@tonic-gate /* 12837c478bd9Sstevel@tonic-gate ** Have to change both effective and real so need to 12847c478bd9Sstevel@tonic-gate ** change them both to effective to keep privs. 12857c478bd9Sstevel@tonic-gate */ 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate if (tTd(47, 5)) 12887c478bd9Sstevel@tonic-gate sm_dprintf("Changing uid to %d\n", (int) new_uid); 12897c478bd9Sstevel@tonic-gate if (setuid(new_uid) < 0) 12907c478bd9Sstevel@tonic-gate { 12917c478bd9Sstevel@tonic-gate syserr("main: setuid(%d) failed", (int) new_uid); 12927c478bd9Sstevel@tonic-gate finis(false, true, EX_OSERR); 12937c478bd9Sstevel@tonic-gate /* NOTREACHED */ 12947c478bd9Sstevel@tonic-gate } 12957c478bd9Sstevel@tonic-gate if (tTd(47, 10)) 12967c478bd9Sstevel@tonic-gate sm_dprintf("Now running as e/ruid %d:%d\n", 12977c478bd9Sstevel@tonic-gate (int) geteuid(), (int) getuid()); 12987c478bd9Sstevel@tonic-gate #endif /* HASSETREUID */ 12997c478bd9Sstevel@tonic-gate } 13007c478bd9Sstevel@tonic-gate 13017c478bd9Sstevel@tonic-gate #if NAMED_BIND 13027c478bd9Sstevel@tonic-gate if (FallbackMX != NULL) 13037c478bd9Sstevel@tonic-gate (void) getfallbackmxrr(FallbackMX); 13047c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 13057c478bd9Sstevel@tonic-gate 13067c478bd9Sstevel@tonic-gate if (SuperSafe == SAFE_INTERACTIVE && CurEnv->e_sendmode != SM_DELIVER) 13077c478bd9Sstevel@tonic-gate { 13087c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 13097c478bd9Sstevel@tonic-gate "WARNING: SuperSafe=interactive should only be used with\n DeliveryMode=interactive\n"); 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate 13127c478bd9Sstevel@tonic-gate if (UseMSP && (OpMode == MD_DAEMON || OpMode == MD_FGDAEMON)) 13137c478bd9Sstevel@tonic-gate { 13147c478bd9Sstevel@tonic-gate usrerr("Mail submission program cannot be used as daemon"); 13157c478bd9Sstevel@tonic-gate finis(false, true, EX_USAGE); 13167c478bd9Sstevel@tonic-gate } 13177c478bd9Sstevel@tonic-gate 13187c478bd9Sstevel@tonic-gate if (OpMode == MD_DELIVER || OpMode == MD_SMTP || 13197c478bd9Sstevel@tonic-gate OpMode == MD_QUEUERUN || OpMode == MD_ARPAFTP || 13207c478bd9Sstevel@tonic-gate OpMode == MD_DAEMON || OpMode == MD_FGDAEMON) 13217c478bd9Sstevel@tonic-gate makeworkgroups(); 13227c478bd9Sstevel@tonic-gate 13237c478bd9Sstevel@tonic-gate /* set up the basic signal handlers */ 13247c478bd9Sstevel@tonic-gate if (sm_signal(SIGINT, SIG_IGN) != SIG_IGN) 13257c478bd9Sstevel@tonic-gate (void) sm_signal(SIGINT, intsig); 13267c478bd9Sstevel@tonic-gate (void) sm_signal(SIGTERM, intsig); 13277c478bd9Sstevel@tonic-gate 13287c478bd9Sstevel@tonic-gate /* Enforce use of local time (null string overrides this) */ 13297c478bd9Sstevel@tonic-gate if (TimeZoneSpec == NULL) 13307c478bd9Sstevel@tonic-gate unsetenv("TZ"); 13317c478bd9Sstevel@tonic-gate else if (TimeZoneSpec[0] != '\0') 1332445f2479Sjbeck sm_setuserenv("TZ", TimeZoneSpec); 13337c478bd9Sstevel@tonic-gate else 1334445f2479Sjbeck sm_setuserenv("TZ", NULL); 13357c478bd9Sstevel@tonic-gate tzset(); 13367c478bd9Sstevel@tonic-gate 13377c478bd9Sstevel@tonic-gate /* initialize mailbox database */ 13387c478bd9Sstevel@tonic-gate i = sm_mbdb_initialize(Mbdb); 13397c478bd9Sstevel@tonic-gate if (i != EX_OK) 13407c478bd9Sstevel@tonic-gate { 13417c478bd9Sstevel@tonic-gate usrerr("Can't initialize mailbox database \"%s\": %s", 13427c478bd9Sstevel@tonic-gate Mbdb, sm_strexit(i)); 13437c478bd9Sstevel@tonic-gate ExitStat = i; 13447c478bd9Sstevel@tonic-gate } 13457c478bd9Sstevel@tonic-gate 13467c478bd9Sstevel@tonic-gate /* avoid denial-of-service attacks */ 13477c478bd9Sstevel@tonic-gate resetlimits(); 13487c478bd9Sstevel@tonic-gate 13497c478bd9Sstevel@tonic-gate if (OpMode == MD_TEST) 13507c478bd9Sstevel@tonic-gate { 13517c478bd9Sstevel@tonic-gate /* can't be done after readcf if RunAs* is used */ 13527c478bd9Sstevel@tonic-gate dp = drop_privileges(true); 13537c478bd9Sstevel@tonic-gate if (dp != EX_OK) 13547c478bd9Sstevel@tonic-gate { 13557c478bd9Sstevel@tonic-gate finis(false, true, dp); 13567c478bd9Sstevel@tonic-gate /* NOTREACHED */ 13577c478bd9Sstevel@tonic-gate } 13587c478bd9Sstevel@tonic-gate } 13597c478bd9Sstevel@tonic-gate else if (OpMode != MD_DAEMON && OpMode != MD_FGDAEMON) 13607c478bd9Sstevel@tonic-gate { 13617c478bd9Sstevel@tonic-gate /* drop privileges -- daemon mode done after socket/bind */ 13627c478bd9Sstevel@tonic-gate dp = drop_privileges(false); 13637c478bd9Sstevel@tonic-gate setstat(dp); 13647c478bd9Sstevel@tonic-gate if (dp == EX_OK && UseMSP && (geteuid() == 0 || getuid() == 0)) 13657c478bd9Sstevel@tonic-gate { 13667c478bd9Sstevel@tonic-gate usrerr("Mail submission program must have RunAsUser set to non root user"); 13677c478bd9Sstevel@tonic-gate finis(false, true, EX_CONFIG); 13687c478bd9Sstevel@tonic-gate /* NOTREACHED */ 13697c478bd9Sstevel@tonic-gate } 13707c478bd9Sstevel@tonic-gate } 13717c478bd9Sstevel@tonic-gate 13727c478bd9Sstevel@tonic-gate #if NAMED_BIND 13737c478bd9Sstevel@tonic-gate _res.retry = TimeOuts.res_retry[RES_TO_DEFAULT]; 13747c478bd9Sstevel@tonic-gate _res.retrans = TimeOuts.res_retrans[RES_TO_DEFAULT]; 13757c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate /* 13787c478bd9Sstevel@tonic-gate ** Find our real host name for future logging. 13797c478bd9Sstevel@tonic-gate */ 13807c478bd9Sstevel@tonic-gate 13817c478bd9Sstevel@tonic-gate authinfo = getauthinfo(STDIN_FILENO, &forged); 13827c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, '_', authinfo); 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate /* suppress error printing if errors mailed back or whatever */ 13857c478bd9Sstevel@tonic-gate if (BlankEnvelope.e_errormode != EM_PRINT) 13867c478bd9Sstevel@tonic-gate HoldErrs = true; 13877c478bd9Sstevel@tonic-gate 13887c478bd9Sstevel@tonic-gate /* set up the $=m class now, after .cf has a chance to redefine $m */ 13897c478bd9Sstevel@tonic-gate expand("\201m", jbuf, sizeof jbuf, &BlankEnvelope); 13907c478bd9Sstevel@tonic-gate if (jbuf[0] != '\0') 13917c478bd9Sstevel@tonic-gate setclass('m', jbuf); 13927c478bd9Sstevel@tonic-gate 13937c478bd9Sstevel@tonic-gate /* probe interfaces and locate any additional names */ 13947c478bd9Sstevel@tonic-gate if (DontProbeInterfaces != DPI_PROBENONE) 13957c478bd9Sstevel@tonic-gate load_if_names(); 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate if (tTd(0, 10)) 13987c478bd9Sstevel@tonic-gate { 13997c478bd9Sstevel@tonic-gate char pidpath[MAXPATHLEN]; 14007c478bd9Sstevel@tonic-gate 14017c478bd9Sstevel@tonic-gate /* Now we know which .cf file we use */ 14027c478bd9Sstevel@tonic-gate sm_dprintf(" Conf file:\t%s (selected)\n", 14037c478bd9Sstevel@tonic-gate getcfname(OpMode, SubmitMode, cftype, conffile)); 14047c478bd9Sstevel@tonic-gate expand(PidFile, pidpath, sizeof pidpath, &BlankEnvelope); 14057c478bd9Sstevel@tonic-gate sm_dprintf(" Pid file:\t%s (selected)\n", pidpath); 14067c478bd9Sstevel@tonic-gate } 14077c478bd9Sstevel@tonic-gate 14087c478bd9Sstevel@tonic-gate if (tTd(0, 1)) 14097c478bd9Sstevel@tonic-gate { 14107c478bd9Sstevel@tonic-gate sm_dprintf("\n============ SYSTEM IDENTITY (after readcf) ============"); 14117c478bd9Sstevel@tonic-gate sm_dprintf("\n (short domain name) $w = "); 14127c478bd9Sstevel@tonic-gate xputs(sm_debug_file(), macvalue('w', &BlankEnvelope)); 14137c478bd9Sstevel@tonic-gate sm_dprintf("\n (canonical domain name) $j = "); 14147c478bd9Sstevel@tonic-gate xputs(sm_debug_file(), macvalue('j', &BlankEnvelope)); 14157c478bd9Sstevel@tonic-gate sm_dprintf("\n (subdomain name) $m = "); 14167c478bd9Sstevel@tonic-gate xputs(sm_debug_file(), macvalue('m', &BlankEnvelope)); 14177c478bd9Sstevel@tonic-gate sm_dprintf("\n (node name) $k = "); 14187c478bd9Sstevel@tonic-gate xputs(sm_debug_file(), macvalue('k', &BlankEnvelope)); 14197c478bd9Sstevel@tonic-gate sm_dprintf("\n========================================================\n\n"); 14207c478bd9Sstevel@tonic-gate } 14217c478bd9Sstevel@tonic-gate 14227c478bd9Sstevel@tonic-gate /* 14237c478bd9Sstevel@tonic-gate ** Do more command line checking -- these are things that 14247c478bd9Sstevel@tonic-gate ** have to modify the results of reading the config file. 14257c478bd9Sstevel@tonic-gate */ 14267c478bd9Sstevel@tonic-gate 14277c478bd9Sstevel@tonic-gate /* process authorization warnings from command line */ 14287c478bd9Sstevel@tonic-gate if (warn_C_flag) 14297c478bd9Sstevel@tonic-gate auth_warning(&BlankEnvelope, "Processed by %s with -C %s", 14307c478bd9Sstevel@tonic-gate RealUserName, conffile); 14317c478bd9Sstevel@tonic-gate if (Warn_Q_option && !wordinclass(RealUserName, 't')) 14327c478bd9Sstevel@tonic-gate auth_warning(&BlankEnvelope, "Processed from queue %s", 14337c478bd9Sstevel@tonic-gate QueueDir); 14347c478bd9Sstevel@tonic-gate if (sysloglabel != NULL && !wordinclass(RealUserName, 't') && 14357c478bd9Sstevel@tonic-gate RealUid != 0 && RealUid != TrustedUid && LogLevel > 1) 14367c478bd9Sstevel@tonic-gate sm_syslog(LOG_WARNING, NOQID, "user %d changed syslog label", 14377c478bd9Sstevel@tonic-gate (int) RealUid); 14387c478bd9Sstevel@tonic-gate 14397c478bd9Sstevel@tonic-gate /* check body type for legality */ 14407c478bd9Sstevel@tonic-gate i = check_bodytype(BlankEnvelope.e_bodytype); 14417c478bd9Sstevel@tonic-gate if (i == BODYTYPE_ILLEGAL) 14427c478bd9Sstevel@tonic-gate { 14437c478bd9Sstevel@tonic-gate usrerr("Illegal body type %s", BlankEnvelope.e_bodytype); 14447c478bd9Sstevel@tonic-gate BlankEnvelope.e_bodytype = NULL; 14457c478bd9Sstevel@tonic-gate } 14467c478bd9Sstevel@tonic-gate else if (i != BODYTYPE_NONE) 14477c478bd9Sstevel@tonic-gate SevenBitInput = (i == BODYTYPE_7BIT); 14487c478bd9Sstevel@tonic-gate 14497c478bd9Sstevel@tonic-gate /* tweak default DSN notifications */ 14507c478bd9Sstevel@tonic-gate if (DefaultNotify == 0) 14517c478bd9Sstevel@tonic-gate DefaultNotify = QPINGONFAILURE|QPINGONDELAY; 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate /* check for sane configuration level */ 14547c478bd9Sstevel@tonic-gate if (ConfigLevel > MAXCONFIGLEVEL) 14557c478bd9Sstevel@tonic-gate { 14567c478bd9Sstevel@tonic-gate syserr("Warning: .cf version level (%d) exceeds sendmail version %s functionality (%d)", 14577c478bd9Sstevel@tonic-gate ConfigLevel, Version, MAXCONFIGLEVEL); 14587c478bd9Sstevel@tonic-gate } 14597c478bd9Sstevel@tonic-gate 14607c478bd9Sstevel@tonic-gate /* need MCI cache to have persistence */ 14617c478bd9Sstevel@tonic-gate if (HostStatDir != NULL && MaxMciCache == 0) 14627c478bd9Sstevel@tonic-gate { 14637c478bd9Sstevel@tonic-gate HostStatDir = NULL; 14647c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 14657c478bd9Sstevel@tonic-gate "Warning: HostStatusDirectory disabled with ConnectionCacheSize = 0\n"); 14667c478bd9Sstevel@tonic-gate } 14677c478bd9Sstevel@tonic-gate 14687c478bd9Sstevel@tonic-gate /* need HostStatusDir in order to have SingleThreadDelivery */ 14697c478bd9Sstevel@tonic-gate if (SingleThreadDelivery && HostStatDir == NULL) 14707c478bd9Sstevel@tonic-gate { 14717c478bd9Sstevel@tonic-gate SingleThreadDelivery = false; 14727c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 14737c478bd9Sstevel@tonic-gate "Warning: HostStatusDirectory required for SingleThreadDelivery\n"); 14747c478bd9Sstevel@tonic-gate } 14757c478bd9Sstevel@tonic-gate 1476445f2479Sjbeck #if _FFR_MEMSTAT 1477445f2479Sjbeck j = sm_memstat_open(); 1478445f2479Sjbeck if (j < 0 && (RefuseLowMem > 0 || QueueLowMem > 0) && LogLevel > 4) 1479445f2479Sjbeck { 1480445f2479Sjbeck sm_syslog(LOG_WARNING, NOQID, 1481445f2479Sjbeck "cannot get memory statistics, settings ignored, error=%d" 1482445f2479Sjbeck , j); 1483445f2479Sjbeck } 1484445f2479Sjbeck #endif /* _FFR_MEMSTAT */ 1485445f2479Sjbeck 14867c478bd9Sstevel@tonic-gate /* check for permissions */ 14877c478bd9Sstevel@tonic-gate if (RealUid != 0 && 14887c478bd9Sstevel@tonic-gate RealUid != TrustedUid) 14897c478bd9Sstevel@tonic-gate { 14907c478bd9Sstevel@tonic-gate char *action = NULL; 14917c478bd9Sstevel@tonic-gate 14927c478bd9Sstevel@tonic-gate switch (OpMode) 14937c478bd9Sstevel@tonic-gate { 14947c478bd9Sstevel@tonic-gate case MD_QUEUERUN: 14957c478bd9Sstevel@tonic-gate if (quarantining != NULL) 14967c478bd9Sstevel@tonic-gate action = "quarantine jobs"; 14977c478bd9Sstevel@tonic-gate else 14987c478bd9Sstevel@tonic-gate { 14997c478bd9Sstevel@tonic-gate /* Normal users can do a single queue run */ 15007c478bd9Sstevel@tonic-gate if (QueueIntvl == 0) 15017c478bd9Sstevel@tonic-gate break; 15027c478bd9Sstevel@tonic-gate } 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate /* but not persistent queue runners */ 15057c478bd9Sstevel@tonic-gate if (action == NULL) 15067c478bd9Sstevel@tonic-gate action = "start a queue runner daemon"; 15077c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 15087c478bd9Sstevel@tonic-gate 15097c478bd9Sstevel@tonic-gate case MD_PURGESTAT: 15107c478bd9Sstevel@tonic-gate if (action == NULL) 15117c478bd9Sstevel@tonic-gate action = "purge host status"; 15127c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 15137c478bd9Sstevel@tonic-gate 15147c478bd9Sstevel@tonic-gate case MD_DAEMON: 15157c478bd9Sstevel@tonic-gate case MD_FGDAEMON: 15167c478bd9Sstevel@tonic-gate if (action == NULL) 15177c478bd9Sstevel@tonic-gate action = "run daemon"; 15187c478bd9Sstevel@tonic-gate 15197c478bd9Sstevel@tonic-gate if (tTd(65, 1)) 15207c478bd9Sstevel@tonic-gate sm_dprintf("Deny user %d attempt to %s\n", 15217c478bd9Sstevel@tonic-gate (int) RealUid, action); 15227c478bd9Sstevel@tonic-gate 15237c478bd9Sstevel@tonic-gate if (LogLevel > 1) 15247c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 15257c478bd9Sstevel@tonic-gate "user %d attempted to %s", 15267c478bd9Sstevel@tonic-gate (int) RealUid, action); 15277c478bd9Sstevel@tonic-gate HoldErrs = false; 15287c478bd9Sstevel@tonic-gate usrerr("Permission denied (real uid not trusted)"); 15297c478bd9Sstevel@tonic-gate finis(false, true, EX_USAGE); 15307c478bd9Sstevel@tonic-gate /* NOTREACHED */ 15317c478bd9Sstevel@tonic-gate break; 15327c478bd9Sstevel@tonic-gate 15337c478bd9Sstevel@tonic-gate case MD_VERIFY: 15347c478bd9Sstevel@tonic-gate if (bitset(PRIV_RESTRICTEXPAND, PrivacyFlags)) 15357c478bd9Sstevel@tonic-gate { 15367c478bd9Sstevel@tonic-gate /* 15377c478bd9Sstevel@tonic-gate ** If -bv and RestrictExpand, 15387c478bd9Sstevel@tonic-gate ** drop privs to prevent normal 15397c478bd9Sstevel@tonic-gate ** users from reading private 15407c478bd9Sstevel@tonic-gate ** aliases/forwards/:include:s 15417c478bd9Sstevel@tonic-gate */ 15427c478bd9Sstevel@tonic-gate 15437c478bd9Sstevel@tonic-gate if (tTd(65, 1)) 15447c478bd9Sstevel@tonic-gate sm_dprintf("Drop privs for user %d attempt to expand (RestrictExpand)\n", 15457c478bd9Sstevel@tonic-gate (int) RealUid); 15467c478bd9Sstevel@tonic-gate 15477c478bd9Sstevel@tonic-gate dp = drop_privileges(true); 15487c478bd9Sstevel@tonic-gate 15497c478bd9Sstevel@tonic-gate /* Fake address safety */ 15507c478bd9Sstevel@tonic-gate if (tTd(65, 1)) 15517c478bd9Sstevel@tonic-gate sm_dprintf("Faking DontBlameSendmail=NonRootSafeAddr\n"); 15527c478bd9Sstevel@tonic-gate setbitn(DBS_NONROOTSAFEADDR, DontBlameSendmail); 15537c478bd9Sstevel@tonic-gate 15547c478bd9Sstevel@tonic-gate if (dp != EX_OK) 15557c478bd9Sstevel@tonic-gate { 15567c478bd9Sstevel@tonic-gate if (tTd(65, 1)) 15577c478bd9Sstevel@tonic-gate sm_dprintf("Failed to drop privs for user %d attempt to expand, exiting\n", 15587c478bd9Sstevel@tonic-gate (int) RealUid); 15597c478bd9Sstevel@tonic-gate CurEnv->e_id = NULL; 15607c478bd9Sstevel@tonic-gate finis(true, true, dp); 15617c478bd9Sstevel@tonic-gate /* NOTREACHED */ 15627c478bd9Sstevel@tonic-gate } 15637c478bd9Sstevel@tonic-gate } 15647c478bd9Sstevel@tonic-gate break; 15657c478bd9Sstevel@tonic-gate 15667c478bd9Sstevel@tonic-gate case MD_TEST: 15677c478bd9Sstevel@tonic-gate case MD_PRINT: 15687c478bd9Sstevel@tonic-gate case MD_PRINTNQE: 15697c478bd9Sstevel@tonic-gate case MD_FREEZE: 15707c478bd9Sstevel@tonic-gate case MD_HOSTSTAT: 15717c478bd9Sstevel@tonic-gate /* Nothing special to check */ 15727c478bd9Sstevel@tonic-gate break; 15737c478bd9Sstevel@tonic-gate 15747c478bd9Sstevel@tonic-gate case MD_INITALIAS: 15757c478bd9Sstevel@tonic-gate if (!wordinclass(RealUserName, 't')) 15767c478bd9Sstevel@tonic-gate { 15777c478bd9Sstevel@tonic-gate if (tTd(65, 1)) 15787c478bd9Sstevel@tonic-gate sm_dprintf("Deny user %d attempt to rebuild the alias map\n", 15797c478bd9Sstevel@tonic-gate (int) RealUid); 15807c478bd9Sstevel@tonic-gate if (LogLevel > 1) 15817c478bd9Sstevel@tonic-gate sm_syslog(LOG_ALERT, NOQID, 15827c478bd9Sstevel@tonic-gate "user %d attempted to rebuild the alias map", 15837c478bd9Sstevel@tonic-gate (int) RealUid); 15847c478bd9Sstevel@tonic-gate HoldErrs = false; 15857c478bd9Sstevel@tonic-gate usrerr("Permission denied (real uid not trusted)"); 15867c478bd9Sstevel@tonic-gate finis(false, true, EX_USAGE); 15877c478bd9Sstevel@tonic-gate /* NOTREACHED */ 15887c478bd9Sstevel@tonic-gate } 15897c478bd9Sstevel@tonic-gate if (UseMSP) 15907c478bd9Sstevel@tonic-gate { 15917c478bd9Sstevel@tonic-gate HoldErrs = false; 15927c478bd9Sstevel@tonic-gate usrerr("User %d cannot rebuild aliases in mail submission program", 15937c478bd9Sstevel@tonic-gate (int) RealUid); 15947c478bd9Sstevel@tonic-gate finis(false, true, EX_USAGE); 15957c478bd9Sstevel@tonic-gate /* NOTREACHED */ 15967c478bd9Sstevel@tonic-gate } 15977c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 15987c478bd9Sstevel@tonic-gate 15997c478bd9Sstevel@tonic-gate default: 16007c478bd9Sstevel@tonic-gate if (bitset(PRIV_RESTRICTEXPAND, PrivacyFlags) && 16017c478bd9Sstevel@tonic-gate Verbose != 0) 16027c478bd9Sstevel@tonic-gate { 16037c478bd9Sstevel@tonic-gate /* 16047c478bd9Sstevel@tonic-gate ** If -v and RestrictExpand, reset 16057c478bd9Sstevel@tonic-gate ** Verbose to prevent normal users 16067c478bd9Sstevel@tonic-gate ** from seeing the expansion of 16077c478bd9Sstevel@tonic-gate ** aliases/forwards/:include:s 16087c478bd9Sstevel@tonic-gate */ 16097c478bd9Sstevel@tonic-gate 16107c478bd9Sstevel@tonic-gate if (tTd(65, 1)) 16117c478bd9Sstevel@tonic-gate sm_dprintf("Dropping verbosity for user %d (RestrictExpand)\n", 16127c478bd9Sstevel@tonic-gate (int) RealUid); 16137c478bd9Sstevel@tonic-gate Verbose = 0; 16147c478bd9Sstevel@tonic-gate } 16157c478bd9Sstevel@tonic-gate break; 16167c478bd9Sstevel@tonic-gate } 16177c478bd9Sstevel@tonic-gate } 16187c478bd9Sstevel@tonic-gate 16197c478bd9Sstevel@tonic-gate if (MeToo) 16207c478bd9Sstevel@tonic-gate BlankEnvelope.e_flags |= EF_METOO; 16217c478bd9Sstevel@tonic-gate 16227c478bd9Sstevel@tonic-gate switch (OpMode) 16237c478bd9Sstevel@tonic-gate { 16247c478bd9Sstevel@tonic-gate case MD_TEST: 16257c478bd9Sstevel@tonic-gate /* don't have persistent host status in test mode */ 16267c478bd9Sstevel@tonic-gate HostStatDir = NULL; 16277c478bd9Sstevel@tonic-gate if (Verbose == 0) 16287c478bd9Sstevel@tonic-gate Verbose = 2; 16297c478bd9Sstevel@tonic-gate BlankEnvelope.e_errormode = EM_PRINT; 16307c478bd9Sstevel@tonic-gate HoldErrs = false; 16317c478bd9Sstevel@tonic-gate break; 16327c478bd9Sstevel@tonic-gate 16337c478bd9Sstevel@tonic-gate case MD_VERIFY: 16347c478bd9Sstevel@tonic-gate BlankEnvelope.e_errormode = EM_PRINT; 16357c478bd9Sstevel@tonic-gate HoldErrs = false; 16367c478bd9Sstevel@tonic-gate /* arrange to exit cleanly on hangup signal */ 16377c478bd9Sstevel@tonic-gate if (sm_signal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL) 16387c478bd9Sstevel@tonic-gate (void) sm_signal(SIGHUP, intsig); 16397c478bd9Sstevel@tonic-gate if (geteuid() != 0) 16407c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 16417c478bd9Sstevel@tonic-gate "Notice: -bv may give misleading output for non-privileged user\n"); 16427c478bd9Sstevel@tonic-gate break; 16437c478bd9Sstevel@tonic-gate 16447c478bd9Sstevel@tonic-gate case MD_FGDAEMON: 16457c478bd9Sstevel@tonic-gate run_in_foreground = true; 16467c478bd9Sstevel@tonic-gate set_op_mode(MD_DAEMON); 16477c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 16487c478bd9Sstevel@tonic-gate 16497c478bd9Sstevel@tonic-gate case MD_DAEMON: 16507c478bd9Sstevel@tonic-gate vendor_daemon_setup(&BlankEnvelope); 16517c478bd9Sstevel@tonic-gate 16527c478bd9Sstevel@tonic-gate /* remove things that don't make sense in daemon mode */ 16537c478bd9Sstevel@tonic-gate FullName = NULL; 16547c478bd9Sstevel@tonic-gate GrabTo = false; 16557c478bd9Sstevel@tonic-gate 16567c478bd9Sstevel@tonic-gate /* arrange to restart on hangup signal */ 16577c478bd9Sstevel@tonic-gate if (SaveArgv[0] == NULL || SaveArgv[0][0] != '/') 16587c478bd9Sstevel@tonic-gate sm_syslog(LOG_WARNING, NOQID, 16597c478bd9Sstevel@tonic-gate "daemon invoked without full pathname; kill -1 won't work"); 16607c478bd9Sstevel@tonic-gate break; 16617c478bd9Sstevel@tonic-gate 16627c478bd9Sstevel@tonic-gate case MD_INITALIAS: 16637c478bd9Sstevel@tonic-gate Verbose = 2; 16647c478bd9Sstevel@tonic-gate BlankEnvelope.e_errormode = EM_PRINT; 16657c478bd9Sstevel@tonic-gate HoldErrs = false; 16667c478bd9Sstevel@tonic-gate /* FALLTHROUGH */ 16677c478bd9Sstevel@tonic-gate 16687c478bd9Sstevel@tonic-gate default: 16697c478bd9Sstevel@tonic-gate /* arrange to exit cleanly on hangup signal */ 16707c478bd9Sstevel@tonic-gate if (sm_signal(SIGHUP, SIG_IGN) == (sigfunc_t) SIG_DFL) 16717c478bd9Sstevel@tonic-gate (void) sm_signal(SIGHUP, intsig); 16727c478bd9Sstevel@tonic-gate break; 16737c478bd9Sstevel@tonic-gate } 16747c478bd9Sstevel@tonic-gate 16757c478bd9Sstevel@tonic-gate /* special considerations for FullName */ 16767c478bd9Sstevel@tonic-gate if (FullName != NULL) 16777c478bd9Sstevel@tonic-gate { 16787c478bd9Sstevel@tonic-gate char *full = NULL; 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate /* full names can't have newlines */ 16817c478bd9Sstevel@tonic-gate if (strchr(FullName, '\n') != NULL) 16827c478bd9Sstevel@tonic-gate { 16837c478bd9Sstevel@tonic-gate full = newstr(denlstring(FullName, true, true)); 16847c478bd9Sstevel@tonic-gate FullName = full; 16857c478bd9Sstevel@tonic-gate } 16867c478bd9Sstevel@tonic-gate 16877c478bd9Sstevel@tonic-gate /* check for characters that may have to be quoted */ 16887c478bd9Sstevel@tonic-gate if (!rfc822_string(FullName)) 16897c478bd9Sstevel@tonic-gate { 16907c478bd9Sstevel@tonic-gate /* 16917c478bd9Sstevel@tonic-gate ** Quote a full name with special characters 16927c478bd9Sstevel@tonic-gate ** as a comment so crackaddr() doesn't destroy 16937c478bd9Sstevel@tonic-gate ** the name portion of the address. 16947c478bd9Sstevel@tonic-gate */ 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate FullName = addquotes(FullName, NULL); 16977c478bd9Sstevel@tonic-gate if (full != NULL) 16987c478bd9Sstevel@tonic-gate sm_free(full); /* XXX */ 16997c478bd9Sstevel@tonic-gate } 17007c478bd9Sstevel@tonic-gate } 17017c478bd9Sstevel@tonic-gate 17027c478bd9Sstevel@tonic-gate /* do heuristic mode adjustment */ 17037c478bd9Sstevel@tonic-gate if (Verbose) 17047c478bd9Sstevel@tonic-gate { 17057c478bd9Sstevel@tonic-gate /* turn off noconnect option */ 17067c478bd9Sstevel@tonic-gate setoption('c', "F", true, false, &BlankEnvelope); 17077c478bd9Sstevel@tonic-gate 17087c478bd9Sstevel@tonic-gate /* turn on interactive delivery */ 17097c478bd9Sstevel@tonic-gate setoption('d', "", true, false, &BlankEnvelope); 17107c478bd9Sstevel@tonic-gate } 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate #ifdef VENDOR_CODE 17137c478bd9Sstevel@tonic-gate /* check for vendor mismatch */ 17147c478bd9Sstevel@tonic-gate if (VendorCode != VENDOR_CODE) 17157c478bd9Sstevel@tonic-gate { 17167c478bd9Sstevel@tonic-gate message("Warning: .cf file vendor code mismatch: sendmail expects vendor %s, .cf file vendor is %s", 17177c478bd9Sstevel@tonic-gate getvendor(VENDOR_CODE), getvendor(VendorCode)); 17187c478bd9Sstevel@tonic-gate } 17197c478bd9Sstevel@tonic-gate #endif /* VENDOR_CODE */ 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate /* check for out of date configuration level */ 17227c478bd9Sstevel@tonic-gate if (ConfigLevel < MAXCONFIGLEVEL) 17237c478bd9Sstevel@tonic-gate { 17247c478bd9Sstevel@tonic-gate message("Warning: .cf file is out of date: sendmail %s supports version %d, .cf file is version %d", 17257c478bd9Sstevel@tonic-gate Version, MAXCONFIGLEVEL, ConfigLevel); 17267c478bd9Sstevel@tonic-gate } 17277c478bd9Sstevel@tonic-gate 17287c478bd9Sstevel@tonic-gate if (ConfigLevel < 3) 17297c478bd9Sstevel@tonic-gate UseErrorsTo = true; 17307c478bd9Sstevel@tonic-gate 17317c478bd9Sstevel@tonic-gate /* set options that were previous macros */ 17327c478bd9Sstevel@tonic-gate if (SmtpGreeting == NULL) 17337c478bd9Sstevel@tonic-gate { 17347c478bd9Sstevel@tonic-gate if (ConfigLevel < 7 && 17357c478bd9Sstevel@tonic-gate (p = macvalue('e', &BlankEnvelope)) != NULL) 17367c478bd9Sstevel@tonic-gate SmtpGreeting = newstr(p); 17377c478bd9Sstevel@tonic-gate else 17387c478bd9Sstevel@tonic-gate SmtpGreeting = "\201j Sendmail \201v ready at \201b"; 17397c478bd9Sstevel@tonic-gate } 17407c478bd9Sstevel@tonic-gate if (UnixFromLine == NULL) 17417c478bd9Sstevel@tonic-gate { 17427c478bd9Sstevel@tonic-gate if (ConfigLevel < 7 && 17437c478bd9Sstevel@tonic-gate (p = macvalue('l', &BlankEnvelope)) != NULL) 17447c478bd9Sstevel@tonic-gate UnixFromLine = newstr(p); 17457c478bd9Sstevel@tonic-gate else 17467c478bd9Sstevel@tonic-gate UnixFromLine = "From \201g \201d"; 17477c478bd9Sstevel@tonic-gate } 17487c478bd9Sstevel@tonic-gate SmtpError[0] = '\0'; 17497c478bd9Sstevel@tonic-gate 17507c478bd9Sstevel@tonic-gate /* our name for SMTP codes */ 17517c478bd9Sstevel@tonic-gate expand("\201j", jbuf, sizeof jbuf, &BlankEnvelope); 17527c478bd9Sstevel@tonic-gate if (jbuf[0] == '\0') 17537c478bd9Sstevel@tonic-gate PSTRSET(MyHostName, "localhost"); 17547c478bd9Sstevel@tonic-gate else 17557c478bd9Sstevel@tonic-gate PSTRSET(MyHostName, jbuf); 17567c478bd9Sstevel@tonic-gate if (strchr(MyHostName, '.') == NULL) 17577c478bd9Sstevel@tonic-gate message("WARNING: local host name (%s) is not qualified; see cf/README: WHO AM I?", 17587c478bd9Sstevel@tonic-gate MyHostName); 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate /* make certain that this name is part of the $=w class */ 17617c478bd9Sstevel@tonic-gate setclass('w', MyHostName); 17627c478bd9Sstevel@tonic-gate 17637c478bd9Sstevel@tonic-gate /* fill in the structure of the *default* queue */ 17647c478bd9Sstevel@tonic-gate st = stab("mqueue", ST_QUEUE, ST_FIND); 17657c478bd9Sstevel@tonic-gate if (st == NULL) 17667c478bd9Sstevel@tonic-gate syserr("No default queue (mqueue) defined"); 17677c478bd9Sstevel@tonic-gate else 17687c478bd9Sstevel@tonic-gate set_def_queueval(st->s_quegrp, true); 17697c478bd9Sstevel@tonic-gate 17707c478bd9Sstevel@tonic-gate /* the indices of built-in mailers */ 17717c478bd9Sstevel@tonic-gate st = stab("local", ST_MAILER, ST_FIND); 17727c478bd9Sstevel@tonic-gate if (st != NULL) 17737c478bd9Sstevel@tonic-gate LocalMailer = st->s_mailer; 17747c478bd9Sstevel@tonic-gate else if (OpMode != MD_TEST || !warn_C_flag) 17757c478bd9Sstevel@tonic-gate syserr("No local mailer defined"); 17767c478bd9Sstevel@tonic-gate 17777c478bd9Sstevel@tonic-gate st = stab("prog", ST_MAILER, ST_FIND); 17787c478bd9Sstevel@tonic-gate if (st == NULL) 17797c478bd9Sstevel@tonic-gate syserr("No prog mailer defined"); 17807c478bd9Sstevel@tonic-gate else 17817c478bd9Sstevel@tonic-gate { 17827c478bd9Sstevel@tonic-gate ProgMailer = st->s_mailer; 17837c478bd9Sstevel@tonic-gate clrbitn(M_MUSER, ProgMailer->m_flags); 17847c478bd9Sstevel@tonic-gate } 17857c478bd9Sstevel@tonic-gate 17867c478bd9Sstevel@tonic-gate st = stab("*file*", ST_MAILER, ST_FIND); 17877c478bd9Sstevel@tonic-gate if (st == NULL) 17887c478bd9Sstevel@tonic-gate syserr("No *file* mailer defined"); 17897c478bd9Sstevel@tonic-gate else 17907c478bd9Sstevel@tonic-gate { 17917c478bd9Sstevel@tonic-gate FileMailer = st->s_mailer; 17927c478bd9Sstevel@tonic-gate clrbitn(M_MUSER, FileMailer->m_flags); 17937c478bd9Sstevel@tonic-gate } 17947c478bd9Sstevel@tonic-gate 17957c478bd9Sstevel@tonic-gate st = stab("*include*", ST_MAILER, ST_FIND); 17967c478bd9Sstevel@tonic-gate if (st == NULL) 17977c478bd9Sstevel@tonic-gate syserr("No *include* mailer defined"); 17987c478bd9Sstevel@tonic-gate else 17997c478bd9Sstevel@tonic-gate InclMailer = st->s_mailer; 18007c478bd9Sstevel@tonic-gate 18017c478bd9Sstevel@tonic-gate if (ConfigLevel < 6) 18027c478bd9Sstevel@tonic-gate { 18037c478bd9Sstevel@tonic-gate /* heuristic tweaking of local mailer for back compat */ 18047c478bd9Sstevel@tonic-gate if (LocalMailer != NULL) 18057c478bd9Sstevel@tonic-gate { 18067c478bd9Sstevel@tonic-gate setbitn(M_ALIASABLE, LocalMailer->m_flags); 18077c478bd9Sstevel@tonic-gate setbitn(M_HASPWENT, LocalMailer->m_flags); 18087c478bd9Sstevel@tonic-gate setbitn(M_TRYRULESET5, LocalMailer->m_flags); 18097c478bd9Sstevel@tonic-gate setbitn(M_CHECKINCLUDE, LocalMailer->m_flags); 18107c478bd9Sstevel@tonic-gate setbitn(M_CHECKPROG, LocalMailer->m_flags); 18117c478bd9Sstevel@tonic-gate setbitn(M_CHECKFILE, LocalMailer->m_flags); 18127c478bd9Sstevel@tonic-gate setbitn(M_CHECKUDB, LocalMailer->m_flags); 18137c478bd9Sstevel@tonic-gate } 18147c478bd9Sstevel@tonic-gate if (ProgMailer != NULL) 18157c478bd9Sstevel@tonic-gate setbitn(M_RUNASRCPT, ProgMailer->m_flags); 18167c478bd9Sstevel@tonic-gate if (FileMailer != NULL) 18177c478bd9Sstevel@tonic-gate setbitn(M_RUNASRCPT, FileMailer->m_flags); 18187c478bd9Sstevel@tonic-gate } 18197c478bd9Sstevel@tonic-gate if (ConfigLevel < 7) 18207c478bd9Sstevel@tonic-gate { 18217c478bd9Sstevel@tonic-gate if (LocalMailer != NULL) 18227c478bd9Sstevel@tonic-gate setbitn(M_VRFY250, LocalMailer->m_flags); 18237c478bd9Sstevel@tonic-gate if (ProgMailer != NULL) 18247c478bd9Sstevel@tonic-gate setbitn(M_VRFY250, ProgMailer->m_flags); 18257c478bd9Sstevel@tonic-gate if (FileMailer != NULL) 18267c478bd9Sstevel@tonic-gate setbitn(M_VRFY250, FileMailer->m_flags); 18277c478bd9Sstevel@tonic-gate } 18287c478bd9Sstevel@tonic-gate 18297c478bd9Sstevel@tonic-gate /* MIME Content-Types that cannot be transfer encoded */ 18307c478bd9Sstevel@tonic-gate setclass('n', "multipart/signed"); 18317c478bd9Sstevel@tonic-gate 18327c478bd9Sstevel@tonic-gate /* MIME message/xxx subtypes that can be treated as messages */ 18337c478bd9Sstevel@tonic-gate setclass('s', "rfc822"); 18347c478bd9Sstevel@tonic-gate 18357c478bd9Sstevel@tonic-gate /* MIME Content-Transfer-Encodings that can be encoded */ 18367c478bd9Sstevel@tonic-gate setclass('e', "7bit"); 18377c478bd9Sstevel@tonic-gate setclass('e', "8bit"); 18387c478bd9Sstevel@tonic-gate setclass('e', "binary"); 18397c478bd9Sstevel@tonic-gate 18407c478bd9Sstevel@tonic-gate #ifdef USE_B_CLASS 18417c478bd9Sstevel@tonic-gate /* MIME Content-Types that should be treated as binary */ 18427c478bd9Sstevel@tonic-gate setclass('b', "image"); 18437c478bd9Sstevel@tonic-gate setclass('b', "audio"); 18447c478bd9Sstevel@tonic-gate setclass('b', "video"); 18457c478bd9Sstevel@tonic-gate setclass('b', "application/octet-stream"); 18467c478bd9Sstevel@tonic-gate #endif /* USE_B_CLASS */ 18477c478bd9Sstevel@tonic-gate 18487c478bd9Sstevel@tonic-gate /* MIME headers which have fields to check for overflow */ 18497c478bd9Sstevel@tonic-gate setclass(macid("{checkMIMEFieldHeaders}"), "content-disposition"); 18507c478bd9Sstevel@tonic-gate setclass(macid("{checkMIMEFieldHeaders}"), "content-type"); 18517c478bd9Sstevel@tonic-gate 18527c478bd9Sstevel@tonic-gate /* MIME headers to check for length overflow */ 18537c478bd9Sstevel@tonic-gate setclass(macid("{checkMIMETextHeaders}"), "content-description"); 18547c478bd9Sstevel@tonic-gate 18557c478bd9Sstevel@tonic-gate /* MIME headers to check for overflow and rebalance */ 18567c478bd9Sstevel@tonic-gate setclass(macid("{checkMIMEHeaders}"), "content-disposition"); 18577c478bd9Sstevel@tonic-gate setclass(macid("{checkMIMEHeaders}"), "content-id"); 18587c478bd9Sstevel@tonic-gate setclass(macid("{checkMIMEHeaders}"), "content-transfer-encoding"); 18597c478bd9Sstevel@tonic-gate setclass(macid("{checkMIMEHeaders}"), "content-type"); 18607c478bd9Sstevel@tonic-gate setclass(macid("{checkMIMEHeaders}"), "mime-version"); 18617c478bd9Sstevel@tonic-gate 18627c478bd9Sstevel@tonic-gate /* Macros to save in the queue file -- don't remove any */ 18637c478bd9Sstevel@tonic-gate setclass(macid("{persistentMacros}"), "r"); 18647c478bd9Sstevel@tonic-gate setclass(macid("{persistentMacros}"), "s"); 18657c478bd9Sstevel@tonic-gate setclass(macid("{persistentMacros}"), "_"); 18667c478bd9Sstevel@tonic-gate setclass(macid("{persistentMacros}"), "{if_addr}"); 18677c478bd9Sstevel@tonic-gate setclass(macid("{persistentMacros}"), "{daemon_flags}"); 18687c478bd9Sstevel@tonic-gate 18697c478bd9Sstevel@tonic-gate /* operate in queue directory */ 18707c478bd9Sstevel@tonic-gate if (QueueDir == NULL || *QueueDir == '\0') 18717c478bd9Sstevel@tonic-gate { 18727c478bd9Sstevel@tonic-gate if (OpMode != MD_TEST) 18737c478bd9Sstevel@tonic-gate { 18747c478bd9Sstevel@tonic-gate syserr("QueueDirectory (Q) option must be set"); 18757c478bd9Sstevel@tonic-gate ExitStat = EX_CONFIG; 18767c478bd9Sstevel@tonic-gate } 18777c478bd9Sstevel@tonic-gate } 18787c478bd9Sstevel@tonic-gate else 18797c478bd9Sstevel@tonic-gate { 18807c478bd9Sstevel@tonic-gate if (OpMode != MD_TEST) 18817c478bd9Sstevel@tonic-gate setup_queues(OpMode == MD_DAEMON); 18827c478bd9Sstevel@tonic-gate } 18837c478bd9Sstevel@tonic-gate 18847c478bd9Sstevel@tonic-gate /* check host status directory for validity */ 18857c478bd9Sstevel@tonic-gate if (HostStatDir != NULL && !path_is_dir(HostStatDir, false)) 18867c478bd9Sstevel@tonic-gate { 18877c478bd9Sstevel@tonic-gate /* cannot use this value */ 18887c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 18897c478bd9Sstevel@tonic-gate "Warning: Cannot use HostStatusDirectory = %s: %s\n", 18907c478bd9Sstevel@tonic-gate HostStatDir, sm_errstring(errno)); 18917c478bd9Sstevel@tonic-gate HostStatDir = NULL; 18927c478bd9Sstevel@tonic-gate } 18937c478bd9Sstevel@tonic-gate 18947c478bd9Sstevel@tonic-gate if (OpMode == MD_QUEUERUN && 18957c478bd9Sstevel@tonic-gate RealUid != 0 && bitset(PRIV_RESTRICTQRUN, PrivacyFlags)) 18967c478bd9Sstevel@tonic-gate { 18977c478bd9Sstevel@tonic-gate struct stat stbuf; 18987c478bd9Sstevel@tonic-gate 18997c478bd9Sstevel@tonic-gate /* check to see if we own the queue directory */ 19007c478bd9Sstevel@tonic-gate if (stat(".", &stbuf) < 0) 19017c478bd9Sstevel@tonic-gate syserr("main: cannot stat %s", QueueDir); 19027c478bd9Sstevel@tonic-gate if (stbuf.st_uid != RealUid) 19037c478bd9Sstevel@tonic-gate { 19047c478bd9Sstevel@tonic-gate /* nope, really a botch */ 19057c478bd9Sstevel@tonic-gate HoldErrs = false; 19067c478bd9Sstevel@tonic-gate usrerr("You do not have permission to process the queue"); 19077c478bd9Sstevel@tonic-gate finis(false, true, EX_NOPERM); 19087c478bd9Sstevel@tonic-gate /* NOTREACHED */ 19097c478bd9Sstevel@tonic-gate } 19107c478bd9Sstevel@tonic-gate } 19117c478bd9Sstevel@tonic-gate 19127c478bd9Sstevel@tonic-gate #if MILTER 19137c478bd9Sstevel@tonic-gate /* sanity checks on milter filters */ 19147c478bd9Sstevel@tonic-gate if (OpMode == MD_DAEMON || OpMode == MD_SMTP) 19157c478bd9Sstevel@tonic-gate { 19167c478bd9Sstevel@tonic-gate milter_config(InputFilterList, InputFilters, MAXFILTERS); 19177c478bd9Sstevel@tonic-gate setup_daemon_milters(); 19187c478bd9Sstevel@tonic-gate } 19197c478bd9Sstevel@tonic-gate #endif /* MILTER */ 19207c478bd9Sstevel@tonic-gate 19217c478bd9Sstevel@tonic-gate /* Convert queuegroup string to qgrp number */ 19227c478bd9Sstevel@tonic-gate if (queuegroup != NULL) 19237c478bd9Sstevel@tonic-gate { 19247c478bd9Sstevel@tonic-gate qgrp = name2qid(queuegroup); 19257c478bd9Sstevel@tonic-gate if (qgrp == NOQGRP) 19267c478bd9Sstevel@tonic-gate { 19277c478bd9Sstevel@tonic-gate HoldErrs = false; 19287c478bd9Sstevel@tonic-gate usrerr("Queue group %s unknown", queuegroup); 19297c478bd9Sstevel@tonic-gate finis(false, true, ExitStat); 19307c478bd9Sstevel@tonic-gate /* NOTREACHED */ 19317c478bd9Sstevel@tonic-gate } 19327c478bd9Sstevel@tonic-gate } 19337c478bd9Sstevel@tonic-gate 19347c478bd9Sstevel@tonic-gate /* if we've had errors so far, exit now */ 19357c478bd9Sstevel@tonic-gate if (ExitStat != EX_OK && OpMode != MD_TEST) 19367c478bd9Sstevel@tonic-gate { 19377c478bd9Sstevel@tonic-gate finis(false, true, ExitStat); 19387c478bd9Sstevel@tonic-gate /* NOTREACHED */ 19397c478bd9Sstevel@tonic-gate } 19407c478bd9Sstevel@tonic-gate 19417c478bd9Sstevel@tonic-gate #if SASL 19427c478bd9Sstevel@tonic-gate /* sendmail specific SASL initialization */ 19437c478bd9Sstevel@tonic-gate sm_sasl_init(); 19447c478bd9Sstevel@tonic-gate #endif /* SASL */ 19457c478bd9Sstevel@tonic-gate 19467c478bd9Sstevel@tonic-gate #if XDEBUG 19477c478bd9Sstevel@tonic-gate checkfd012("before main() initmaps"); 19487c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 19497c478bd9Sstevel@tonic-gate 19507c478bd9Sstevel@tonic-gate /* 19517c478bd9Sstevel@tonic-gate ** Do operation-mode-dependent initialization. 19527c478bd9Sstevel@tonic-gate */ 19537c478bd9Sstevel@tonic-gate 19547c478bd9Sstevel@tonic-gate switch (OpMode) 19557c478bd9Sstevel@tonic-gate { 19567c478bd9Sstevel@tonic-gate case MD_PRINT: 19577c478bd9Sstevel@tonic-gate /* print the queue */ 19587c478bd9Sstevel@tonic-gate HoldErrs = false; 19597c478bd9Sstevel@tonic-gate dropenvelope(&BlankEnvelope, true, false); 19607c478bd9Sstevel@tonic-gate (void) sm_signal(SIGPIPE, sigpipe); 19617c478bd9Sstevel@tonic-gate if (qgrp != NOQGRP) 19627c478bd9Sstevel@tonic-gate { 19637c478bd9Sstevel@tonic-gate int j; 19647c478bd9Sstevel@tonic-gate 19657c478bd9Sstevel@tonic-gate /* Selecting a particular queue group to run */ 19667c478bd9Sstevel@tonic-gate for (j = 0; j < Queue[qgrp]->qg_numqueues; j++) 19677c478bd9Sstevel@tonic-gate { 19687c478bd9Sstevel@tonic-gate if (StopRequest) 19697c478bd9Sstevel@tonic-gate stop_sendmail(); 19707c478bd9Sstevel@tonic-gate (void) print_single_queue(qgrp, j); 19717c478bd9Sstevel@tonic-gate } 19727c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 19737c478bd9Sstevel@tonic-gate /* NOTREACHED */ 19747c478bd9Sstevel@tonic-gate } 19757c478bd9Sstevel@tonic-gate printqueue(); 19767c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 19777c478bd9Sstevel@tonic-gate /* NOTREACHED */ 19787c478bd9Sstevel@tonic-gate break; 19797c478bd9Sstevel@tonic-gate 19807c478bd9Sstevel@tonic-gate case MD_PRINTNQE: 19817c478bd9Sstevel@tonic-gate /* print number of entries in queue */ 19827c478bd9Sstevel@tonic-gate dropenvelope(&BlankEnvelope, true, false); 19837c478bd9Sstevel@tonic-gate (void) sm_signal(SIGPIPE, sigpipe); 19847c478bd9Sstevel@tonic-gate printnqe(smioout, NULL); 19857c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 19867c478bd9Sstevel@tonic-gate /* NOTREACHED */ 19877c478bd9Sstevel@tonic-gate break; 19887c478bd9Sstevel@tonic-gate 19897c478bd9Sstevel@tonic-gate case MD_QUEUERUN: 19907c478bd9Sstevel@tonic-gate /* only handle quarantining here */ 19917c478bd9Sstevel@tonic-gate if (quarantining == NULL) 19927c478bd9Sstevel@tonic-gate break; 19937c478bd9Sstevel@tonic-gate 19947c478bd9Sstevel@tonic-gate if (QueueMode != QM_QUARANTINE && 19957c478bd9Sstevel@tonic-gate QueueMode != QM_NORMAL) 19967c478bd9Sstevel@tonic-gate { 19977c478bd9Sstevel@tonic-gate HoldErrs = false; 19987c478bd9Sstevel@tonic-gate usrerr("Can not use -Q with -q%c", QueueMode); 19997c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 20007c478bd9Sstevel@tonic-gate finis(false, true, ExitStat); 20017c478bd9Sstevel@tonic-gate /* NOTREACHED */ 20027c478bd9Sstevel@tonic-gate } 20037c478bd9Sstevel@tonic-gate quarantine_queue(quarantining, qgrp); 20047c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 20057c478bd9Sstevel@tonic-gate break; 20067c478bd9Sstevel@tonic-gate 20077c478bd9Sstevel@tonic-gate case MD_HOSTSTAT: 20087c478bd9Sstevel@tonic-gate (void) sm_signal(SIGPIPE, sigpipe); 20097c478bd9Sstevel@tonic-gate (void) mci_traverse_persistent(mci_print_persistent, NULL); 20107c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 20117c478bd9Sstevel@tonic-gate /* NOTREACHED */ 20127c478bd9Sstevel@tonic-gate break; 20137c478bd9Sstevel@tonic-gate 20147c478bd9Sstevel@tonic-gate case MD_PURGESTAT: 20157c478bd9Sstevel@tonic-gate (void) mci_traverse_persistent(mci_purge_persistent, NULL); 20167c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 20177c478bd9Sstevel@tonic-gate /* NOTREACHED */ 20187c478bd9Sstevel@tonic-gate break; 20197c478bd9Sstevel@tonic-gate 20207c478bd9Sstevel@tonic-gate case MD_INITALIAS: 20217c478bd9Sstevel@tonic-gate /* initialize maps */ 20227c478bd9Sstevel@tonic-gate initmaps(); 20237c478bd9Sstevel@tonic-gate finis(false, true, ExitStat); 20247c478bd9Sstevel@tonic-gate /* NOTREACHED */ 20257c478bd9Sstevel@tonic-gate break; 20267c478bd9Sstevel@tonic-gate 20277c478bd9Sstevel@tonic-gate case MD_SMTP: 20287c478bd9Sstevel@tonic-gate case MD_DAEMON: 20297c478bd9Sstevel@tonic-gate /* reset DSN parameters */ 20307c478bd9Sstevel@tonic-gate DefaultNotify = QPINGONFAILURE|QPINGONDELAY; 20317c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 20327c478bd9Sstevel@tonic-gate macid("{dsn_notify}"), NULL); 20337c478bd9Sstevel@tonic-gate BlankEnvelope.e_envid = NULL; 20347c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 20357c478bd9Sstevel@tonic-gate macid("{dsn_envid}"), NULL); 20367c478bd9Sstevel@tonic-gate BlankEnvelope.e_flags &= ~(EF_RET_PARAM|EF_NO_BODY_RETN); 20377c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 20387c478bd9Sstevel@tonic-gate macid("{dsn_ret}"), NULL); 20397c478bd9Sstevel@tonic-gate 20407c478bd9Sstevel@tonic-gate /* don't open maps for daemon -- done below in child */ 20417c478bd9Sstevel@tonic-gate break; 20427c478bd9Sstevel@tonic-gate } 20437c478bd9Sstevel@tonic-gate 20447c478bd9Sstevel@tonic-gate if (tTd(0, 15)) 20457c478bd9Sstevel@tonic-gate { 20467c478bd9Sstevel@tonic-gate /* print configuration table (or at least part of it) */ 20477c478bd9Sstevel@tonic-gate if (tTd(0, 90)) 20487c478bd9Sstevel@tonic-gate printrules(); 20497c478bd9Sstevel@tonic-gate for (i = 0; i < MAXMAILERS; i++) 20507c478bd9Sstevel@tonic-gate { 20517c478bd9Sstevel@tonic-gate if (Mailer[i] != NULL) 20527c478bd9Sstevel@tonic-gate printmailer(sm_debug_file(), Mailer[i]); 20537c478bd9Sstevel@tonic-gate } 20547c478bd9Sstevel@tonic-gate } 20557c478bd9Sstevel@tonic-gate 20567c478bd9Sstevel@tonic-gate /* 20577c478bd9Sstevel@tonic-gate ** Switch to the main envelope. 20587c478bd9Sstevel@tonic-gate */ 20597c478bd9Sstevel@tonic-gate 20607c478bd9Sstevel@tonic-gate CurEnv = newenvelope(&MainEnvelope, &BlankEnvelope, 20617c478bd9Sstevel@tonic-gate sm_rpool_new_x(NULL)); 20627c478bd9Sstevel@tonic-gate MainEnvelope.e_flags = BlankEnvelope.e_flags; 20637c478bd9Sstevel@tonic-gate 20647c478bd9Sstevel@tonic-gate /* 20657c478bd9Sstevel@tonic-gate ** If test mode, read addresses from stdin and process. 20667c478bd9Sstevel@tonic-gate */ 20677c478bd9Sstevel@tonic-gate 20687c478bd9Sstevel@tonic-gate if (OpMode == MD_TEST) 20697c478bd9Sstevel@tonic-gate { 20707c478bd9Sstevel@tonic-gate if (isatty(sm_io_getinfo(smioin, SM_IO_WHAT_FD, NULL))) 20717c478bd9Sstevel@tonic-gate Verbose = 2; 20727c478bd9Sstevel@tonic-gate 20737c478bd9Sstevel@tonic-gate if (Verbose) 20747c478bd9Sstevel@tonic-gate { 20757c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 20767c478bd9Sstevel@tonic-gate "ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)\n"); 20777c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 20787c478bd9Sstevel@tonic-gate "Enter <ruleset> <address>\n"); 20797c478bd9Sstevel@tonic-gate } 20807c478bd9Sstevel@tonic-gate macdefine(&(MainEnvelope.e_macro), A_PERM, 20817c478bd9Sstevel@tonic-gate macid("{addr_type}"), "e r"); 20827c478bd9Sstevel@tonic-gate for (;;) 20837c478bd9Sstevel@tonic-gate { 20847c478bd9Sstevel@tonic-gate SM_TRY 20857c478bd9Sstevel@tonic-gate { 20867c478bd9Sstevel@tonic-gate (void) sm_signal(SIGINT, intindebug); 20877c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGINT); 20887c478bd9Sstevel@tonic-gate if (Verbose == 2) 20897c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, 20907c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 20917c478bd9Sstevel@tonic-gate "> "); 20927c478bd9Sstevel@tonic-gate (void) sm_io_flush(smioout, SM_TIME_DEFAULT); 20937c478bd9Sstevel@tonic-gate if (sm_io_fgets(smioin, SM_TIME_DEFAULT, buf, 20947c478bd9Sstevel@tonic-gate sizeof buf) == NULL) 20957c478bd9Sstevel@tonic-gate testmodeline("/quit", &MainEnvelope); 20967c478bd9Sstevel@tonic-gate p = strchr(buf, '\n'); 20977c478bd9Sstevel@tonic-gate if (p != NULL) 20987c478bd9Sstevel@tonic-gate *p = '\0'; 20997c478bd9Sstevel@tonic-gate if (Verbose < 2) 21007c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, 21017c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, 21027c478bd9Sstevel@tonic-gate "> %s\n", buf); 21037c478bd9Sstevel@tonic-gate testmodeline(buf, &MainEnvelope); 21047c478bd9Sstevel@tonic-gate } 21057c478bd9Sstevel@tonic-gate SM_EXCEPT(exc, "[!F]*") 21067c478bd9Sstevel@tonic-gate { 21077c478bd9Sstevel@tonic-gate /* 21087c478bd9Sstevel@tonic-gate ** 8.10 just prints \n on interrupt. 21097c478bd9Sstevel@tonic-gate ** I'm printing the exception here in case 21107c478bd9Sstevel@tonic-gate ** sendmail is extended to raise additional 21117c478bd9Sstevel@tonic-gate ** exceptions in this context. 21127c478bd9Sstevel@tonic-gate */ 21137c478bd9Sstevel@tonic-gate 21147c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 21157c478bd9Sstevel@tonic-gate "\n"); 21167c478bd9Sstevel@tonic-gate sm_exc_print(exc, smioout); 21177c478bd9Sstevel@tonic-gate } 21187c478bd9Sstevel@tonic-gate SM_END_TRY 21197c478bd9Sstevel@tonic-gate } 21207c478bd9Sstevel@tonic-gate } 21217c478bd9Sstevel@tonic-gate 21227c478bd9Sstevel@tonic-gate #if STARTTLS 21237c478bd9Sstevel@tonic-gate tls_ok = true; 21247c478bd9Sstevel@tonic-gate if (OpMode == MD_QUEUERUN || OpMode == MD_DELIVER) 21257c478bd9Sstevel@tonic-gate { 21267c478bd9Sstevel@tonic-gate /* check whether STARTTLS is turned off for the client */ 21277c478bd9Sstevel@tonic-gate if (chkclientmodifiers(D_NOTLS)) 21287c478bd9Sstevel@tonic-gate tls_ok = false; 21297c478bd9Sstevel@tonic-gate } 21307c478bd9Sstevel@tonic-gate else if (OpMode == MD_DAEMON || OpMode == MD_FGDAEMON || 21317c478bd9Sstevel@tonic-gate OpMode == MD_SMTP) 21327c478bd9Sstevel@tonic-gate { 21337c478bd9Sstevel@tonic-gate /* check whether STARTTLS is turned off for the server */ 21347c478bd9Sstevel@tonic-gate if (chkdaemonmodifiers(D_NOTLS)) 21357c478bd9Sstevel@tonic-gate tls_ok = false; 21367c478bd9Sstevel@tonic-gate } 21377c478bd9Sstevel@tonic-gate else /* other modes don't need STARTTLS */ 21387c478bd9Sstevel@tonic-gate tls_ok = false; 21397c478bd9Sstevel@tonic-gate 21407c478bd9Sstevel@tonic-gate if (tls_ok) 21417c478bd9Sstevel@tonic-gate { 21427c478bd9Sstevel@tonic-gate /* basic TLS initialization */ 21437c478bd9Sstevel@tonic-gate tls_ok = init_tls_library(); 21447c478bd9Sstevel@tonic-gate } 21457c478bd9Sstevel@tonic-gate 21467c478bd9Sstevel@tonic-gate if (!tls_ok && (OpMode == MD_QUEUERUN || OpMode == MD_DELIVER)) 21477c478bd9Sstevel@tonic-gate { 21487c478bd9Sstevel@tonic-gate /* disable TLS for client */ 21497c478bd9Sstevel@tonic-gate setclttls(false); 21507c478bd9Sstevel@tonic-gate } 21517c478bd9Sstevel@tonic-gate #endif /* STARTTLS */ 21527c478bd9Sstevel@tonic-gate 21537c478bd9Sstevel@tonic-gate /* 21547c478bd9Sstevel@tonic-gate ** If collecting stuff from the queue, go start doing that. 21557c478bd9Sstevel@tonic-gate */ 21567c478bd9Sstevel@tonic-gate 21577c478bd9Sstevel@tonic-gate if (OpMode == MD_QUEUERUN && QueueIntvl == 0) 21587c478bd9Sstevel@tonic-gate { 21597c478bd9Sstevel@tonic-gate pid_t pid = -1; 21607c478bd9Sstevel@tonic-gate 21617c478bd9Sstevel@tonic-gate #if STARTTLS 21627c478bd9Sstevel@tonic-gate /* init TLS for client, ignore result for now */ 21637c478bd9Sstevel@tonic-gate (void) initclttls(tls_ok); 21647c478bd9Sstevel@tonic-gate #endif /* STARTTLS */ 21657c478bd9Sstevel@tonic-gate 21667c478bd9Sstevel@tonic-gate /* 21677c478bd9Sstevel@tonic-gate ** The parent process of the caller of runqueue() needs 21687c478bd9Sstevel@tonic-gate ** to stay around for a possible SIGTERM. The SIGTERM will 21697c478bd9Sstevel@tonic-gate ** tell this process that all of the queue runners children 21707c478bd9Sstevel@tonic-gate ** need to be sent SIGTERM as well. At the same time, we 21717c478bd9Sstevel@tonic-gate ** want to return control to the command line. So we do an 21727c478bd9Sstevel@tonic-gate ** extra fork(). 21737c478bd9Sstevel@tonic-gate */ 21747c478bd9Sstevel@tonic-gate 21757c478bd9Sstevel@tonic-gate if (Verbose || foregroundqueue || (pid = fork()) <= 0) 21767c478bd9Sstevel@tonic-gate { 21777c478bd9Sstevel@tonic-gate /* 21787c478bd9Sstevel@tonic-gate ** If the fork() failed we should still try to do 21797c478bd9Sstevel@tonic-gate ** the queue run. If it succeeded then the child 21807c478bd9Sstevel@tonic-gate ** is going to start the run and wait for all 21817c478bd9Sstevel@tonic-gate ** of the children to finish. 21827c478bd9Sstevel@tonic-gate */ 21837c478bd9Sstevel@tonic-gate 21847c478bd9Sstevel@tonic-gate if (pid == 0) 21857c478bd9Sstevel@tonic-gate { 21867c478bd9Sstevel@tonic-gate /* Reset global flags */ 21877c478bd9Sstevel@tonic-gate RestartRequest = NULL; 21887c478bd9Sstevel@tonic-gate ShutdownRequest = NULL; 21897c478bd9Sstevel@tonic-gate PendingSignal = 0; 21907c478bd9Sstevel@tonic-gate 21917c478bd9Sstevel@tonic-gate /* disconnect from terminal */ 21927c478bd9Sstevel@tonic-gate disconnect(2, CurEnv); 21937c478bd9Sstevel@tonic-gate } 21947c478bd9Sstevel@tonic-gate 21957c478bd9Sstevel@tonic-gate CurrentPid = getpid(); 21967c478bd9Sstevel@tonic-gate if (qgrp != NOQGRP) 21977c478bd9Sstevel@tonic-gate { 21987c478bd9Sstevel@tonic-gate int rwgflags = RWG_NONE; 21997c478bd9Sstevel@tonic-gate 22007c478bd9Sstevel@tonic-gate /* 22017c478bd9Sstevel@tonic-gate ** To run a specific queue group mark it to 22027c478bd9Sstevel@tonic-gate ** be run, select the work group it's in and 22037c478bd9Sstevel@tonic-gate ** increment the work counter. 22047c478bd9Sstevel@tonic-gate */ 22057c478bd9Sstevel@tonic-gate 22067c478bd9Sstevel@tonic-gate for (i = 0; i < NumQueue && Queue[i] != NULL; 22077c478bd9Sstevel@tonic-gate i++) 22087c478bd9Sstevel@tonic-gate Queue[i]->qg_nextrun = (time_t) -1; 22097c478bd9Sstevel@tonic-gate Queue[qgrp]->qg_nextrun = 0; 22107c478bd9Sstevel@tonic-gate if (Verbose) 22117c478bd9Sstevel@tonic-gate rwgflags |= RWG_VERBOSE; 22127c478bd9Sstevel@tonic-gate if (queuepersistent) 22137c478bd9Sstevel@tonic-gate rwgflags |= RWG_PERSISTENT; 22147c478bd9Sstevel@tonic-gate rwgflags |= RWG_FORCE; 22157c478bd9Sstevel@tonic-gate (void) run_work_group(Queue[qgrp]->qg_wgrp, 22167c478bd9Sstevel@tonic-gate rwgflags); 22177c478bd9Sstevel@tonic-gate } 22187c478bd9Sstevel@tonic-gate else 22197c478bd9Sstevel@tonic-gate (void) runqueue(false, Verbose, 22207c478bd9Sstevel@tonic-gate queuepersistent, true); 22217c478bd9Sstevel@tonic-gate 22227c478bd9Sstevel@tonic-gate /* set the title to make it easier to find */ 22237c478bd9Sstevel@tonic-gate sm_setproctitle(true, CurEnv, "Queue control"); 22247c478bd9Sstevel@tonic-gate (void) sm_signal(SIGCHLD, SIG_DFL); 22257c478bd9Sstevel@tonic-gate while (CurChildren > 0) 22267c478bd9Sstevel@tonic-gate { 22277c478bd9Sstevel@tonic-gate int status; 22287c478bd9Sstevel@tonic-gate pid_t ret; 22297c478bd9Sstevel@tonic-gate 22307c478bd9Sstevel@tonic-gate errno = 0; 22317c478bd9Sstevel@tonic-gate while ((ret = sm_wait(&status)) <= 0) 22327c478bd9Sstevel@tonic-gate { 22337c478bd9Sstevel@tonic-gate if (errno == ECHILD) 22347c478bd9Sstevel@tonic-gate { 22357c478bd9Sstevel@tonic-gate /* 22367c478bd9Sstevel@tonic-gate ** Oops... something got messed 22377c478bd9Sstevel@tonic-gate ** up really bad. Waiting for 22387c478bd9Sstevel@tonic-gate ** non-existent children 22397c478bd9Sstevel@tonic-gate ** shouldn't happen. Let's get 22407c478bd9Sstevel@tonic-gate ** out of here. 22417c478bd9Sstevel@tonic-gate */ 22427c478bd9Sstevel@tonic-gate 22437c478bd9Sstevel@tonic-gate CurChildren = 0; 22447c478bd9Sstevel@tonic-gate break; 22457c478bd9Sstevel@tonic-gate } 22467c478bd9Sstevel@tonic-gate continue; 22477c478bd9Sstevel@tonic-gate } 22487c478bd9Sstevel@tonic-gate 22497c478bd9Sstevel@tonic-gate /* something is really really wrong */ 22507c478bd9Sstevel@tonic-gate if (errno == ECHILD) 22517c478bd9Sstevel@tonic-gate { 22527c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, NOQID, 22537c478bd9Sstevel@tonic-gate "queue control process: lost all children: wait returned ECHILD"); 22547c478bd9Sstevel@tonic-gate break; 22557c478bd9Sstevel@tonic-gate } 22567c478bd9Sstevel@tonic-gate 22577c478bd9Sstevel@tonic-gate /* Only drop when a child gives status */ 22587c478bd9Sstevel@tonic-gate if (WIFSTOPPED(status)) 22597c478bd9Sstevel@tonic-gate continue; 22607c478bd9Sstevel@tonic-gate 22617c478bd9Sstevel@tonic-gate proc_list_drop(ret, status, NULL); 22627c478bd9Sstevel@tonic-gate } 22637c478bd9Sstevel@tonic-gate } 22647c478bd9Sstevel@tonic-gate finis(true, true, ExitStat); 22657c478bd9Sstevel@tonic-gate /* NOTREACHED */ 22667c478bd9Sstevel@tonic-gate } 22677c478bd9Sstevel@tonic-gate 22687c478bd9Sstevel@tonic-gate # if SASL 22697c478bd9Sstevel@tonic-gate if (OpMode == MD_SMTP || OpMode == MD_DAEMON) 22707c478bd9Sstevel@tonic-gate { 22717c478bd9Sstevel@tonic-gate /* check whether AUTH is turned off for the server */ 22727c478bd9Sstevel@tonic-gate if (!chkdaemonmodifiers(D_NOAUTH) && 22737c478bd9Sstevel@tonic-gate (i = sasl_server_init(srvcallbacks, "Sendmail")) != SASL_OK) 22747c478bd9Sstevel@tonic-gate syserr("!sasl_server_init failed! [%s]", 22757c478bd9Sstevel@tonic-gate sasl_errstring(i, NULL, NULL)); 22767c478bd9Sstevel@tonic-gate } 22777c478bd9Sstevel@tonic-gate # endif /* SASL */ 22787c478bd9Sstevel@tonic-gate 22797c478bd9Sstevel@tonic-gate if (OpMode == MD_SMTP) 22807c478bd9Sstevel@tonic-gate { 22817c478bd9Sstevel@tonic-gate proc_list_add(CurrentPid, "Sendmail SMTP Agent", 22827c478bd9Sstevel@tonic-gate PROC_DAEMON, 0, -1, NULL); 22837c478bd9Sstevel@tonic-gate 22847c478bd9Sstevel@tonic-gate /* clean up background delivery children */ 22857c478bd9Sstevel@tonic-gate (void) sm_signal(SIGCHLD, reapchild); 22867c478bd9Sstevel@tonic-gate } 22877c478bd9Sstevel@tonic-gate 22887c478bd9Sstevel@tonic-gate /* 22897c478bd9Sstevel@tonic-gate ** If a daemon, wait for a request. 22907c478bd9Sstevel@tonic-gate ** getrequests will always return in a child. 22917c478bd9Sstevel@tonic-gate ** If we should also be processing the queue, start 22927c478bd9Sstevel@tonic-gate ** doing it in background. 22937c478bd9Sstevel@tonic-gate ** We check for any errors that might have happened 22947c478bd9Sstevel@tonic-gate ** during startup. 22957c478bd9Sstevel@tonic-gate */ 22967c478bd9Sstevel@tonic-gate 22977c478bd9Sstevel@tonic-gate if (OpMode == MD_DAEMON || QueueIntvl > 0) 22987c478bd9Sstevel@tonic-gate { 22997c478bd9Sstevel@tonic-gate char dtype[200]; 23007c478bd9Sstevel@tonic-gate 23017c478bd9Sstevel@tonic-gate if (!run_in_foreground && !tTd(99, 100)) 23027c478bd9Sstevel@tonic-gate { 23037c478bd9Sstevel@tonic-gate /* put us in background */ 23047c478bd9Sstevel@tonic-gate i = fork(); 23057c478bd9Sstevel@tonic-gate if (i < 0) 23067c478bd9Sstevel@tonic-gate syserr("daemon: cannot fork"); 23077c478bd9Sstevel@tonic-gate if (i != 0) 23087c478bd9Sstevel@tonic-gate { 23097c478bd9Sstevel@tonic-gate finis(false, true, EX_OK); 23107c478bd9Sstevel@tonic-gate /* NOTREACHED */ 23117c478bd9Sstevel@tonic-gate } 23127c478bd9Sstevel@tonic-gate 23137c478bd9Sstevel@tonic-gate /* 23147c478bd9Sstevel@tonic-gate ** Initialize exception stack and default exception 23157c478bd9Sstevel@tonic-gate ** handler for child process. 23167c478bd9Sstevel@tonic-gate */ 23177c478bd9Sstevel@tonic-gate 23187c478bd9Sstevel@tonic-gate /* Reset global flags */ 23197c478bd9Sstevel@tonic-gate RestartRequest = NULL; 23207c478bd9Sstevel@tonic-gate RestartWorkGroup = false; 23217c478bd9Sstevel@tonic-gate ShutdownRequest = NULL; 23227c478bd9Sstevel@tonic-gate PendingSignal = 0; 23237c478bd9Sstevel@tonic-gate CurrentPid = getpid(); 23247c478bd9Sstevel@tonic-gate 23257c478bd9Sstevel@tonic-gate sm_exc_newthread(fatal_error); 23267c478bd9Sstevel@tonic-gate 23277c478bd9Sstevel@tonic-gate /* disconnect from our controlling tty */ 23287c478bd9Sstevel@tonic-gate disconnect(2, &MainEnvelope); 23297c478bd9Sstevel@tonic-gate } 23307c478bd9Sstevel@tonic-gate 23317c478bd9Sstevel@tonic-gate dtype[0] = '\0'; 23327c478bd9Sstevel@tonic-gate if (OpMode == MD_DAEMON) 23337c478bd9Sstevel@tonic-gate (void) sm_strlcat(dtype, "+SMTP", sizeof dtype); 23347c478bd9Sstevel@tonic-gate if (QueueIntvl > 0) 23357c478bd9Sstevel@tonic-gate { 23367c478bd9Sstevel@tonic-gate (void) sm_strlcat2(dtype, 23377c478bd9Sstevel@tonic-gate queuepersistent 23387c478bd9Sstevel@tonic-gate ? "+persistent-queueing@" 23397c478bd9Sstevel@tonic-gate : "+queueing@", 23407c478bd9Sstevel@tonic-gate pintvl(QueueIntvl, true), 23417c478bd9Sstevel@tonic-gate sizeof dtype); 23427c478bd9Sstevel@tonic-gate } 23437c478bd9Sstevel@tonic-gate if (tTd(0, 1)) 23447c478bd9Sstevel@tonic-gate (void) sm_strlcat(dtype, "+debugging", sizeof dtype); 23457c478bd9Sstevel@tonic-gate 23467c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NOQID, 23477c478bd9Sstevel@tonic-gate "starting daemon (%s): %s", Version, dtype + 1); 23487c478bd9Sstevel@tonic-gate #if XLA 23497c478bd9Sstevel@tonic-gate xla_create_file(); 23507c478bd9Sstevel@tonic-gate #endif /* XLA */ 23517c478bd9Sstevel@tonic-gate 23527c478bd9Sstevel@tonic-gate /* save daemon type in a macro for possible PidFile use */ 23537c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 23547c478bd9Sstevel@tonic-gate macid("{daemon_info}"), dtype + 1); 23557c478bd9Sstevel@tonic-gate 23567c478bd9Sstevel@tonic-gate /* save queue interval in a macro for possible PidFile use */ 23577c478bd9Sstevel@tonic-gate macdefine(&MainEnvelope.e_macro, A_TEMP, 23587c478bd9Sstevel@tonic-gate macid("{queue_interval}"), pintvl(QueueIntvl, true)); 23597c478bd9Sstevel@tonic-gate 23607c478bd9Sstevel@tonic-gate /* workaround: can't seem to release the signal in the parent */ 23617c478bd9Sstevel@tonic-gate (void) sm_signal(SIGHUP, sighup); 23627c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGHUP); 23637c478bd9Sstevel@tonic-gate (void) sm_signal(SIGTERM, sigterm); 23647c478bd9Sstevel@tonic-gate 23657c478bd9Sstevel@tonic-gate if (QueueIntvl > 0) 23667c478bd9Sstevel@tonic-gate { 23677c478bd9Sstevel@tonic-gate (void) runqueue(true, false, queuepersistent, true); 23687c478bd9Sstevel@tonic-gate 23697c478bd9Sstevel@tonic-gate /* 23707c478bd9Sstevel@tonic-gate ** If queuepersistent but not in daemon mode then 23717c478bd9Sstevel@tonic-gate ** we're going to do the queue runner monitoring here. 23727c478bd9Sstevel@tonic-gate ** If in daemon mode then the monitoring will happen 23737c478bd9Sstevel@tonic-gate ** elsewhere. 23747c478bd9Sstevel@tonic-gate */ 23757c478bd9Sstevel@tonic-gate 23767c478bd9Sstevel@tonic-gate if (OpMode != MD_DAEMON && queuepersistent) 23777c478bd9Sstevel@tonic-gate { 23787c478bd9Sstevel@tonic-gate /* 23797c478bd9Sstevel@tonic-gate ** Write the pid to file 23807c478bd9Sstevel@tonic-gate ** XXX Overwrites sendmail.pid 23817c478bd9Sstevel@tonic-gate */ 23827c478bd9Sstevel@tonic-gate 23837c478bd9Sstevel@tonic-gate log_sendmail_pid(&MainEnvelope); 23847c478bd9Sstevel@tonic-gate 23857c478bd9Sstevel@tonic-gate /* set the title to make it easier to find */ 23867c478bd9Sstevel@tonic-gate sm_setproctitle(true, CurEnv, "Queue control"); 23877c478bd9Sstevel@tonic-gate (void) sm_signal(SIGCHLD, SIG_DFL); 23887c478bd9Sstevel@tonic-gate while (CurChildren > 0) 23897c478bd9Sstevel@tonic-gate { 23907c478bd9Sstevel@tonic-gate int status; 23917c478bd9Sstevel@tonic-gate pid_t ret; 23927c478bd9Sstevel@tonic-gate int group; 23937c478bd9Sstevel@tonic-gate 23947c478bd9Sstevel@tonic-gate CHECK_RESTART; 23957c478bd9Sstevel@tonic-gate errno = 0; 23967c478bd9Sstevel@tonic-gate while ((ret = sm_wait(&status)) <= 0) 23977c478bd9Sstevel@tonic-gate { 23987c478bd9Sstevel@tonic-gate /* 23997c478bd9Sstevel@tonic-gate ** Waiting for non-existent 24007c478bd9Sstevel@tonic-gate ** children shouldn't happen. 24017c478bd9Sstevel@tonic-gate ** Let's get out of here if 24027c478bd9Sstevel@tonic-gate ** it occurs. 24037c478bd9Sstevel@tonic-gate */ 24047c478bd9Sstevel@tonic-gate 24057c478bd9Sstevel@tonic-gate if (errno == ECHILD) 24067c478bd9Sstevel@tonic-gate { 24077c478bd9Sstevel@tonic-gate CurChildren = 0; 24087c478bd9Sstevel@tonic-gate break; 24097c478bd9Sstevel@tonic-gate } 24107c478bd9Sstevel@tonic-gate continue; 24117c478bd9Sstevel@tonic-gate } 24127c478bd9Sstevel@tonic-gate 24137c478bd9Sstevel@tonic-gate /* something is really really wrong */ 24147c478bd9Sstevel@tonic-gate if (errno == ECHILD) 24157c478bd9Sstevel@tonic-gate { 24167c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, NOQID, 24177c478bd9Sstevel@tonic-gate "persistent queue runner control process: lost all children: wait returned ECHILD"); 24187c478bd9Sstevel@tonic-gate break; 24197c478bd9Sstevel@tonic-gate } 24207c478bd9Sstevel@tonic-gate 24217c478bd9Sstevel@tonic-gate if (WIFSTOPPED(status)) 24227c478bd9Sstevel@tonic-gate continue; 24237c478bd9Sstevel@tonic-gate 24247c478bd9Sstevel@tonic-gate /* Probe only on a child status */ 24257c478bd9Sstevel@tonic-gate proc_list_drop(ret, status, &group); 24267c478bd9Sstevel@tonic-gate 24277c478bd9Sstevel@tonic-gate if (WIFSIGNALED(status)) 24287c478bd9Sstevel@tonic-gate { 24297c478bd9Sstevel@tonic-gate if (WCOREDUMP(status)) 24307c478bd9Sstevel@tonic-gate { 24317c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, NOQID, 24327c478bd9Sstevel@tonic-gate "persistent queue runner=%d core dumped, signal=%d", 24337c478bd9Sstevel@tonic-gate group, WTERMSIG(status)); 24347c478bd9Sstevel@tonic-gate 24357c478bd9Sstevel@tonic-gate /* don't restart this */ 24367c478bd9Sstevel@tonic-gate mark_work_group_restart( 24377c478bd9Sstevel@tonic-gate group, -1); 24387c478bd9Sstevel@tonic-gate continue; 24397c478bd9Sstevel@tonic-gate } 24407c478bd9Sstevel@tonic-gate 24417c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, NOQID, 24427c478bd9Sstevel@tonic-gate "persistent queue runner=%d died, signal=%d", 24437c478bd9Sstevel@tonic-gate group, WTERMSIG(status)); 24447c478bd9Sstevel@tonic-gate } 24457c478bd9Sstevel@tonic-gate 24467c478bd9Sstevel@tonic-gate /* 24477c478bd9Sstevel@tonic-gate ** When debugging active, don't 24487c478bd9Sstevel@tonic-gate ** restart the persistent queues. 24497c478bd9Sstevel@tonic-gate ** But do log this as info. 24507c478bd9Sstevel@tonic-gate */ 24517c478bd9Sstevel@tonic-gate 24527c478bd9Sstevel@tonic-gate if (sm_debug_active(&DebugNoPRestart, 24537c478bd9Sstevel@tonic-gate 1)) 24547c478bd9Sstevel@tonic-gate { 24557c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, NOQID, 24567c478bd9Sstevel@tonic-gate "persistent queue runner=%d, exited", 24577c478bd9Sstevel@tonic-gate group); 24587c478bd9Sstevel@tonic-gate mark_work_group_restart(group, 24597c478bd9Sstevel@tonic-gate -1); 24607c478bd9Sstevel@tonic-gate } 24617c478bd9Sstevel@tonic-gate } 24627c478bd9Sstevel@tonic-gate finis(true, true, ExitStat); 24637c478bd9Sstevel@tonic-gate /* NOTREACHED */ 24647c478bd9Sstevel@tonic-gate } 24657c478bd9Sstevel@tonic-gate 24667c478bd9Sstevel@tonic-gate if (OpMode != MD_DAEMON) 24677c478bd9Sstevel@tonic-gate { 24687c478bd9Sstevel@tonic-gate char qtype[200]; 24697c478bd9Sstevel@tonic-gate 24707c478bd9Sstevel@tonic-gate /* 24717c478bd9Sstevel@tonic-gate ** Write the pid to file 24727c478bd9Sstevel@tonic-gate ** XXX Overwrites sendmail.pid 24737c478bd9Sstevel@tonic-gate */ 24747c478bd9Sstevel@tonic-gate 24757c478bd9Sstevel@tonic-gate log_sendmail_pid(&MainEnvelope); 24767c478bd9Sstevel@tonic-gate 24777c478bd9Sstevel@tonic-gate /* set the title to make it easier to find */ 24787c478bd9Sstevel@tonic-gate qtype[0] = '\0'; 24797c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(qtype, sizeof qtype, 4, 24807c478bd9Sstevel@tonic-gate "Queue runner@", 24817c478bd9Sstevel@tonic-gate pintvl(QueueIntvl, true), 24827c478bd9Sstevel@tonic-gate " for ", 24837c478bd9Sstevel@tonic-gate QueueDir); 24847c478bd9Sstevel@tonic-gate sm_setproctitle(true, CurEnv, qtype); 24857c478bd9Sstevel@tonic-gate for (;;) 24867c478bd9Sstevel@tonic-gate { 24877c478bd9Sstevel@tonic-gate (void) pause(); 24887c478bd9Sstevel@tonic-gate 24897c478bd9Sstevel@tonic-gate CHECK_RESTART; 24907c478bd9Sstevel@tonic-gate 24917c478bd9Sstevel@tonic-gate if (doqueuerun()) 24927c478bd9Sstevel@tonic-gate (void) runqueue(true, false, 24937c478bd9Sstevel@tonic-gate false, false); 24947c478bd9Sstevel@tonic-gate } 24957c478bd9Sstevel@tonic-gate } 24967c478bd9Sstevel@tonic-gate } 24977c478bd9Sstevel@tonic-gate dropenvelope(&MainEnvelope, true, false); 24987c478bd9Sstevel@tonic-gate 24997c478bd9Sstevel@tonic-gate #if STARTTLS 25007c478bd9Sstevel@tonic-gate /* init TLS for server, ignore result for now */ 25017c478bd9Sstevel@tonic-gate (void) initsrvtls(tls_ok); 25027c478bd9Sstevel@tonic-gate #endif /* STARTTLS */ 25037c478bd9Sstevel@tonic-gate 25047c478bd9Sstevel@tonic-gate nextreq: 25057c478bd9Sstevel@tonic-gate p_flags = getrequests(&MainEnvelope); 25067c478bd9Sstevel@tonic-gate 25077c478bd9Sstevel@tonic-gate /* drop privileges */ 25087c478bd9Sstevel@tonic-gate (void) drop_privileges(false); 25097c478bd9Sstevel@tonic-gate 25107c478bd9Sstevel@tonic-gate /* 25117c478bd9Sstevel@tonic-gate ** Get authentication data 25127c478bd9Sstevel@tonic-gate ** Set _ macro in BlankEnvelope before calling newenvelope(). 25137c478bd9Sstevel@tonic-gate */ 25147c478bd9Sstevel@tonic-gate 25157c478bd9Sstevel@tonic-gate authinfo = getauthinfo(sm_io_getinfo(InChannel, SM_IO_WHAT_FD, 25167c478bd9Sstevel@tonic-gate NULL), &forged); 25177c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, '_', authinfo); 25187c478bd9Sstevel@tonic-gate 25197c478bd9Sstevel@tonic-gate /* at this point we are in a child: reset state */ 25207c478bd9Sstevel@tonic-gate sm_rpool_free(MainEnvelope.e_rpool); 25217c478bd9Sstevel@tonic-gate (void) newenvelope(&MainEnvelope, &MainEnvelope, 25227c478bd9Sstevel@tonic-gate sm_rpool_new_x(NULL)); 25237c478bd9Sstevel@tonic-gate } 25247c478bd9Sstevel@tonic-gate 25257c478bd9Sstevel@tonic-gate if (LogLevel > 9) 25267c478bd9Sstevel@tonic-gate { 25277c478bd9Sstevel@tonic-gate /* log connection information */ 25287c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, NULL, "connect from %s", authinfo); 25297c478bd9Sstevel@tonic-gate } 25307c478bd9Sstevel@tonic-gate 25317c478bd9Sstevel@tonic-gate /* 25327c478bd9Sstevel@tonic-gate ** If running SMTP protocol, start collecting and executing 25337c478bd9Sstevel@tonic-gate ** commands. This will never return. 25347c478bd9Sstevel@tonic-gate */ 25357c478bd9Sstevel@tonic-gate 25367c478bd9Sstevel@tonic-gate if (OpMode == MD_SMTP || OpMode == MD_DAEMON) 25377c478bd9Sstevel@tonic-gate { 25387c478bd9Sstevel@tonic-gate char pbuf[20]; 25397c478bd9Sstevel@tonic-gate 25407c478bd9Sstevel@tonic-gate /* 25417c478bd9Sstevel@tonic-gate ** Save some macros for check_* rulesets. 25427c478bd9Sstevel@tonic-gate */ 25437c478bd9Sstevel@tonic-gate 25447c478bd9Sstevel@tonic-gate if (forged) 25457c478bd9Sstevel@tonic-gate { 25467c478bd9Sstevel@tonic-gate char ipbuf[103]; 25477c478bd9Sstevel@tonic-gate 25487c478bd9Sstevel@tonic-gate (void) sm_snprintf(ipbuf, sizeof ipbuf, "[%.100s]", 25497c478bd9Sstevel@tonic-gate anynet_ntoa(&RealHostAddr)); 25507c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 25517c478bd9Sstevel@tonic-gate macid("{client_name}"), ipbuf); 25527c478bd9Sstevel@tonic-gate } 25537c478bd9Sstevel@tonic-gate else 25547c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 25557c478bd9Sstevel@tonic-gate macid("{client_name}"), RealHostName); 25567c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_PERM, 25577c478bd9Sstevel@tonic-gate macid("{client_ptr}"), RealHostName); 25587c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 25597c478bd9Sstevel@tonic-gate macid("{client_addr}"), anynet_ntoa(&RealHostAddr)); 25607c478bd9Sstevel@tonic-gate sm_getla(); 25617c478bd9Sstevel@tonic-gate 25627c478bd9Sstevel@tonic-gate switch (RealHostAddr.sa.sa_family) 25637c478bd9Sstevel@tonic-gate { 25647c478bd9Sstevel@tonic-gate #if NETINET 25657c478bd9Sstevel@tonic-gate case AF_INET: 25667c478bd9Sstevel@tonic-gate (void) sm_snprintf(pbuf, sizeof pbuf, "%d", 25677c478bd9Sstevel@tonic-gate RealHostAddr.sin.sin_port); 25687c478bd9Sstevel@tonic-gate break; 25697c478bd9Sstevel@tonic-gate #endif /* NETINET */ 25707c478bd9Sstevel@tonic-gate #if NETINET6 25717c478bd9Sstevel@tonic-gate case AF_INET6: 25727c478bd9Sstevel@tonic-gate (void) sm_snprintf(pbuf, sizeof pbuf, "%d", 25737c478bd9Sstevel@tonic-gate RealHostAddr.sin6.sin6_port); 25747c478bd9Sstevel@tonic-gate break; 25757c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 25767c478bd9Sstevel@tonic-gate default: 25777c478bd9Sstevel@tonic-gate (void) sm_snprintf(pbuf, sizeof pbuf, "0"); 25787c478bd9Sstevel@tonic-gate break; 25797c478bd9Sstevel@tonic-gate } 25807c478bd9Sstevel@tonic-gate macdefine(&BlankEnvelope.e_macro, A_TEMP, 25817c478bd9Sstevel@tonic-gate macid("{client_port}"), pbuf); 25827c478bd9Sstevel@tonic-gate 25837c478bd9Sstevel@tonic-gate if (OpMode == MD_DAEMON) 25847c478bd9Sstevel@tonic-gate { 25857c478bd9Sstevel@tonic-gate /* validate the connection */ 25867c478bd9Sstevel@tonic-gate HoldErrs = true; 25877c478bd9Sstevel@tonic-gate nullserver = validate_connection(&RealHostAddr, 25887c478bd9Sstevel@tonic-gate macvalue(macid("{client_name}"), 25897c478bd9Sstevel@tonic-gate &MainEnvelope), 25907c478bd9Sstevel@tonic-gate &MainEnvelope); 25917c478bd9Sstevel@tonic-gate HoldErrs = false; 25927c478bd9Sstevel@tonic-gate } 25937c478bd9Sstevel@tonic-gate else if (p_flags == NULL) 25947c478bd9Sstevel@tonic-gate { 25957c478bd9Sstevel@tonic-gate p_flags = (BITMAP256 *) xalloc(sizeof *p_flags); 25967c478bd9Sstevel@tonic-gate clrbitmap(p_flags); 25977c478bd9Sstevel@tonic-gate } 25987c478bd9Sstevel@tonic-gate #if STARTTLS 25997c478bd9Sstevel@tonic-gate if (OpMode == MD_SMTP) 26007c478bd9Sstevel@tonic-gate (void) initsrvtls(tls_ok); 26017c478bd9Sstevel@tonic-gate #endif /* STARTTLS */ 26027c478bd9Sstevel@tonic-gate 26037c478bd9Sstevel@tonic-gate /* turn off profiling */ 26047c478bd9Sstevel@tonic-gate SM_PROF(1); 26057c478bd9Sstevel@tonic-gate smtp(nullserver, *p_flags, &MainEnvelope); 26067c478bd9Sstevel@tonic-gate 26077c478bd9Sstevel@tonic-gate if (tTd(93, 100)) 26087c478bd9Sstevel@tonic-gate { 26097c478bd9Sstevel@tonic-gate /* turn off profiling */ 26107c478bd9Sstevel@tonic-gate SM_PROF(0); 26117c478bd9Sstevel@tonic-gate if (OpMode == MD_DAEMON) 26127c478bd9Sstevel@tonic-gate goto nextreq; 26137c478bd9Sstevel@tonic-gate } 26147c478bd9Sstevel@tonic-gate } 26157c478bd9Sstevel@tonic-gate 26167c478bd9Sstevel@tonic-gate sm_rpool_free(MainEnvelope.e_rpool); 26177c478bd9Sstevel@tonic-gate clearenvelope(&MainEnvelope, false, sm_rpool_new_x(NULL)); 26187c478bd9Sstevel@tonic-gate if (OpMode == MD_VERIFY) 26197c478bd9Sstevel@tonic-gate { 26207c478bd9Sstevel@tonic-gate set_delivery_mode(SM_VERIFY, &MainEnvelope); 26217c478bd9Sstevel@tonic-gate PostMasterCopy = NULL; 26227c478bd9Sstevel@tonic-gate } 26237c478bd9Sstevel@tonic-gate else 26247c478bd9Sstevel@tonic-gate { 26257c478bd9Sstevel@tonic-gate /* interactive -- all errors are global */ 26267c478bd9Sstevel@tonic-gate MainEnvelope.e_flags |= EF_GLOBALERRS|EF_LOGSENDER; 26277c478bd9Sstevel@tonic-gate } 26287c478bd9Sstevel@tonic-gate 26297c478bd9Sstevel@tonic-gate /* 26307c478bd9Sstevel@tonic-gate ** Do basic system initialization and set the sender 26317c478bd9Sstevel@tonic-gate */ 26327c478bd9Sstevel@tonic-gate 26337c478bd9Sstevel@tonic-gate initsys(&MainEnvelope); 26347c478bd9Sstevel@tonic-gate macdefine(&MainEnvelope.e_macro, A_PERM, macid("{ntries}"), "0"); 26357c478bd9Sstevel@tonic-gate macdefine(&MainEnvelope.e_macro, A_PERM, macid("{nrcpts}"), "0"); 26367c478bd9Sstevel@tonic-gate setsender(from, &MainEnvelope, NULL, '\0', false); 26377c478bd9Sstevel@tonic-gate if (warn_f_flag != '\0' && !wordinclass(RealUserName, 't') && 26387c478bd9Sstevel@tonic-gate (!bitnset(M_LOCALMAILER, MainEnvelope.e_from.q_mailer->m_flags) || 26397c478bd9Sstevel@tonic-gate strcmp(MainEnvelope.e_from.q_user, RealUserName) != 0)) 26407c478bd9Sstevel@tonic-gate { 26417c478bd9Sstevel@tonic-gate auth_warning(&MainEnvelope, "%s set sender to %s using -%c", 26427c478bd9Sstevel@tonic-gate RealUserName, from, warn_f_flag); 26437c478bd9Sstevel@tonic-gate #if SASL 26447c478bd9Sstevel@tonic-gate auth = false; 26457c478bd9Sstevel@tonic-gate #endif /* SASL */ 26467c478bd9Sstevel@tonic-gate } 26477c478bd9Sstevel@tonic-gate if (auth) 26487c478bd9Sstevel@tonic-gate { 26497c478bd9Sstevel@tonic-gate char *fv; 26507c478bd9Sstevel@tonic-gate 26517c478bd9Sstevel@tonic-gate /* set the initial sender for AUTH= to $f@$j */ 26527c478bd9Sstevel@tonic-gate fv = macvalue('f', &MainEnvelope); 26537c478bd9Sstevel@tonic-gate if (fv == NULL || *fv == '\0') 26547c478bd9Sstevel@tonic-gate MainEnvelope.e_auth_param = NULL; 26557c478bd9Sstevel@tonic-gate else 26567c478bd9Sstevel@tonic-gate { 26577c478bd9Sstevel@tonic-gate if (strchr(fv, '@') == NULL) 26587c478bd9Sstevel@tonic-gate { 26597c478bd9Sstevel@tonic-gate i = strlen(fv) + strlen(macvalue('j', 26607c478bd9Sstevel@tonic-gate &MainEnvelope)) + 2; 26617c478bd9Sstevel@tonic-gate p = sm_malloc_x(i); 26627c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(p, i, 3, fv, "@", 26637c478bd9Sstevel@tonic-gate macvalue('j', 26647c478bd9Sstevel@tonic-gate &MainEnvelope)); 26657c478bd9Sstevel@tonic-gate } 26667c478bd9Sstevel@tonic-gate else 26677c478bd9Sstevel@tonic-gate p = sm_strdup_x(fv); 26687c478bd9Sstevel@tonic-gate MainEnvelope.e_auth_param = sm_rpool_strdup_x(MainEnvelope.e_rpool, 26697c478bd9Sstevel@tonic-gate xtextify(p, "=")); 26707c478bd9Sstevel@tonic-gate sm_free(p); /* XXX */ 26717c478bd9Sstevel@tonic-gate } 26727c478bd9Sstevel@tonic-gate } 26737c478bd9Sstevel@tonic-gate if (macvalue('s', &MainEnvelope) == NULL) 26747c478bd9Sstevel@tonic-gate macdefine(&MainEnvelope.e_macro, A_PERM, 's', RealHostName); 26757c478bd9Sstevel@tonic-gate 26767c478bd9Sstevel@tonic-gate av = argv + optind; 26777c478bd9Sstevel@tonic-gate if (*av == NULL && !GrabTo) 26787c478bd9Sstevel@tonic-gate { 26797c478bd9Sstevel@tonic-gate MainEnvelope.e_to = NULL; 26807c478bd9Sstevel@tonic-gate MainEnvelope.e_flags |= EF_GLOBALERRS; 26817c478bd9Sstevel@tonic-gate HoldErrs = false; 26827c478bd9Sstevel@tonic-gate SuperSafe = SAFE_NO; 26837c478bd9Sstevel@tonic-gate usrerr("Recipient names must be specified"); 26847c478bd9Sstevel@tonic-gate 26857c478bd9Sstevel@tonic-gate /* collect body for UUCP return */ 26867c478bd9Sstevel@tonic-gate if (OpMode != MD_VERIFY) 26877c478bd9Sstevel@tonic-gate collect(InChannel, false, NULL, &MainEnvelope, true); 26887c478bd9Sstevel@tonic-gate finis(true, true, EX_USAGE); 26897c478bd9Sstevel@tonic-gate /* NOTREACHED */ 26907c478bd9Sstevel@tonic-gate } 26917c478bd9Sstevel@tonic-gate 26927c478bd9Sstevel@tonic-gate /* 26937c478bd9Sstevel@tonic-gate ** Scan argv and deliver the message to everyone. 26947c478bd9Sstevel@tonic-gate */ 26957c478bd9Sstevel@tonic-gate 26967c478bd9Sstevel@tonic-gate save_val = LogUsrErrs; 26977c478bd9Sstevel@tonic-gate LogUsrErrs = true; 26987c478bd9Sstevel@tonic-gate sendtoargv(av, &MainEnvelope); 26997c478bd9Sstevel@tonic-gate LogUsrErrs = save_val; 27007c478bd9Sstevel@tonic-gate 27017c478bd9Sstevel@tonic-gate /* if we have had errors sofar, arrange a meaningful exit stat */ 27027c478bd9Sstevel@tonic-gate if (Errors > 0 && ExitStat == EX_OK) 27037c478bd9Sstevel@tonic-gate ExitStat = EX_USAGE; 27047c478bd9Sstevel@tonic-gate 27057c478bd9Sstevel@tonic-gate #if _FFR_FIX_DASHT 27067c478bd9Sstevel@tonic-gate /* 27077c478bd9Sstevel@tonic-gate ** If using -t, force not sending to argv recipients, even 27087c478bd9Sstevel@tonic-gate ** if they are mentioned in the headers. 27097c478bd9Sstevel@tonic-gate */ 27107c478bd9Sstevel@tonic-gate 27117c478bd9Sstevel@tonic-gate if (GrabTo) 27127c478bd9Sstevel@tonic-gate { 27137c478bd9Sstevel@tonic-gate ADDRESS *q; 27147c478bd9Sstevel@tonic-gate 27157c478bd9Sstevel@tonic-gate for (q = MainEnvelope.e_sendqueue; q != NULL; q = q->q_next) 27167c478bd9Sstevel@tonic-gate q->q_state = QS_REMOVED; 27177c478bd9Sstevel@tonic-gate } 27187c478bd9Sstevel@tonic-gate #endif /* _FFR_FIX_DASHT */ 27197c478bd9Sstevel@tonic-gate 27207c478bd9Sstevel@tonic-gate /* 27217c478bd9Sstevel@tonic-gate ** Read the input mail. 27227c478bd9Sstevel@tonic-gate */ 27237c478bd9Sstevel@tonic-gate 27247c478bd9Sstevel@tonic-gate MainEnvelope.e_to = NULL; 27257c478bd9Sstevel@tonic-gate if (OpMode != MD_VERIFY || GrabTo) 27267c478bd9Sstevel@tonic-gate { 27277c478bd9Sstevel@tonic-gate int savederrors; 27287c478bd9Sstevel@tonic-gate unsigned long savedflags; 27297c478bd9Sstevel@tonic-gate 27307c478bd9Sstevel@tonic-gate /* 27317c478bd9Sstevel@tonic-gate ** workaround for compiler warning on Irix: 27327c478bd9Sstevel@tonic-gate ** do not initialize variable in the definition, but 27337c478bd9Sstevel@tonic-gate ** later on: 27347c478bd9Sstevel@tonic-gate ** warning(1548): transfer of control bypasses 27357c478bd9Sstevel@tonic-gate ** initialization of: 27367c478bd9Sstevel@tonic-gate ** variable "savederrors" (declared at line 2570) 27377c478bd9Sstevel@tonic-gate ** variable "savedflags" (declared at line 2571) 27387c478bd9Sstevel@tonic-gate ** goto giveup; 27397c478bd9Sstevel@tonic-gate */ 27407c478bd9Sstevel@tonic-gate 27417c478bd9Sstevel@tonic-gate savederrors = Errors; 27427c478bd9Sstevel@tonic-gate savedflags = MainEnvelope.e_flags & EF_FATALERRS; 27437c478bd9Sstevel@tonic-gate MainEnvelope.e_flags |= EF_GLOBALERRS; 27447c478bd9Sstevel@tonic-gate MainEnvelope.e_flags &= ~EF_FATALERRS; 27457c478bd9Sstevel@tonic-gate Errors = 0; 27467c478bd9Sstevel@tonic-gate buffer_errors(); 27477c478bd9Sstevel@tonic-gate collect(InChannel, false, NULL, &MainEnvelope, true); 27487c478bd9Sstevel@tonic-gate 27497c478bd9Sstevel@tonic-gate /* header checks failed */ 27507c478bd9Sstevel@tonic-gate if (Errors > 0) 27517c478bd9Sstevel@tonic-gate { 27527c478bd9Sstevel@tonic-gate giveup: 27537c478bd9Sstevel@tonic-gate if (!GrabTo) 27547c478bd9Sstevel@tonic-gate { 27557c478bd9Sstevel@tonic-gate /* Log who the mail would have gone to */ 27567c478bd9Sstevel@tonic-gate logundelrcpts(&MainEnvelope, 27577c478bd9Sstevel@tonic-gate MainEnvelope.e_message, 27587c478bd9Sstevel@tonic-gate 8, false); 27597c478bd9Sstevel@tonic-gate } 27607c478bd9Sstevel@tonic-gate flush_errors(true); 27617c478bd9Sstevel@tonic-gate finis(true, true, ExitStat); 27627c478bd9Sstevel@tonic-gate /* NOTREACHED */ 27637c478bd9Sstevel@tonic-gate return -1; 27647c478bd9Sstevel@tonic-gate } 27657c478bd9Sstevel@tonic-gate 27667c478bd9Sstevel@tonic-gate /* bail out if message too large */ 27677c478bd9Sstevel@tonic-gate if (bitset(EF_CLRQUEUE, MainEnvelope.e_flags)) 27687c478bd9Sstevel@tonic-gate { 27697c478bd9Sstevel@tonic-gate finis(true, true, ExitStat != EX_OK ? ExitStat 27707c478bd9Sstevel@tonic-gate : EX_DATAERR); 27717c478bd9Sstevel@tonic-gate /* NOTREACHED */ 27727c478bd9Sstevel@tonic-gate return -1; 27737c478bd9Sstevel@tonic-gate } 27747c478bd9Sstevel@tonic-gate 27757c478bd9Sstevel@tonic-gate /* set message size */ 27767c478bd9Sstevel@tonic-gate (void) sm_snprintf(buf, sizeof buf, "%ld", 27777c478bd9Sstevel@tonic-gate MainEnvelope.e_msgsize); 27787c478bd9Sstevel@tonic-gate macdefine(&MainEnvelope.e_macro, A_TEMP, 27797c478bd9Sstevel@tonic-gate macid("{msg_size}"), buf); 27807c478bd9Sstevel@tonic-gate 27817c478bd9Sstevel@tonic-gate Errors = savederrors; 27827c478bd9Sstevel@tonic-gate MainEnvelope.e_flags |= savedflags; 27837c478bd9Sstevel@tonic-gate } 27847c478bd9Sstevel@tonic-gate errno = 0; 27857c478bd9Sstevel@tonic-gate 27867c478bd9Sstevel@tonic-gate if (tTd(1, 1)) 27877c478bd9Sstevel@tonic-gate sm_dprintf("From person = \"%s\"\n", 27887c478bd9Sstevel@tonic-gate MainEnvelope.e_from.q_paddr); 27897c478bd9Sstevel@tonic-gate 27907c478bd9Sstevel@tonic-gate /* Check if quarantining stats should be updated */ 27917c478bd9Sstevel@tonic-gate if (MainEnvelope.e_quarmsg != NULL) 27927c478bd9Sstevel@tonic-gate markstats(&MainEnvelope, NULL, STATS_QUARANTINE); 27937c478bd9Sstevel@tonic-gate 27947c478bd9Sstevel@tonic-gate /* 27957c478bd9Sstevel@tonic-gate ** Actually send everything. 27967c478bd9Sstevel@tonic-gate ** If verifying, just ack. 27977c478bd9Sstevel@tonic-gate */ 27987c478bd9Sstevel@tonic-gate 27997c478bd9Sstevel@tonic-gate if (Errors == 0) 28007c478bd9Sstevel@tonic-gate { 28017c478bd9Sstevel@tonic-gate if (!split_by_recipient(&MainEnvelope) && 28027c478bd9Sstevel@tonic-gate bitset(EF_FATALERRS, MainEnvelope.e_flags)) 28037c478bd9Sstevel@tonic-gate goto giveup; 28047c478bd9Sstevel@tonic-gate } 28057c478bd9Sstevel@tonic-gate 28067c478bd9Sstevel@tonic-gate /* make sure we deliver at least the first envelope */ 28077c478bd9Sstevel@tonic-gate i = FastSplit > 0 ? 0 : -1; 28087c478bd9Sstevel@tonic-gate for (e = &MainEnvelope; e != NULL; e = e->e_sibling, i++) 28097c478bd9Sstevel@tonic-gate { 28107c478bd9Sstevel@tonic-gate ENVELOPE *next; 28117c478bd9Sstevel@tonic-gate 28127c478bd9Sstevel@tonic-gate e->e_from.q_state = QS_SENDER; 28137c478bd9Sstevel@tonic-gate if (tTd(1, 5)) 28147c478bd9Sstevel@tonic-gate { 28157c478bd9Sstevel@tonic-gate sm_dprintf("main[%d]: QS_SENDER ", i); 28167c478bd9Sstevel@tonic-gate printaddr(sm_debug_file(), &e->e_from, false); 28177c478bd9Sstevel@tonic-gate } 28187c478bd9Sstevel@tonic-gate e->e_to = NULL; 28197c478bd9Sstevel@tonic-gate sm_getla(); 28207c478bd9Sstevel@tonic-gate GrabTo = false; 28217c478bd9Sstevel@tonic-gate #if NAMED_BIND 28227c478bd9Sstevel@tonic-gate _res.retry = TimeOuts.res_retry[RES_TO_FIRST]; 28237c478bd9Sstevel@tonic-gate _res.retrans = TimeOuts.res_retrans[RES_TO_FIRST]; 28247c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 28257c478bd9Sstevel@tonic-gate next = e->e_sibling; 28267c478bd9Sstevel@tonic-gate e->e_sibling = NULL; 28277c478bd9Sstevel@tonic-gate 28287c478bd9Sstevel@tonic-gate /* after FastSplit envelopes: queue up */ 28297c478bd9Sstevel@tonic-gate sendall(e, i >= FastSplit ? SM_QUEUE : SM_DEFAULT); 28307c478bd9Sstevel@tonic-gate e->e_sibling = next; 28317c478bd9Sstevel@tonic-gate } 28327c478bd9Sstevel@tonic-gate 28337c478bd9Sstevel@tonic-gate /* 28347c478bd9Sstevel@tonic-gate ** All done. 28357c478bd9Sstevel@tonic-gate ** Don't send return error message if in VERIFY mode. 28367c478bd9Sstevel@tonic-gate */ 28377c478bd9Sstevel@tonic-gate 28387c478bd9Sstevel@tonic-gate finis(true, true, ExitStat); 28397c478bd9Sstevel@tonic-gate /* NOTREACHED */ 28407c478bd9Sstevel@tonic-gate return ExitStat; 28417c478bd9Sstevel@tonic-gate } 28427c478bd9Sstevel@tonic-gate /* 28437c478bd9Sstevel@tonic-gate ** STOP_SENDMAIL -- Stop the running program 28447c478bd9Sstevel@tonic-gate ** 28457c478bd9Sstevel@tonic-gate ** Parameters: 28467c478bd9Sstevel@tonic-gate ** none. 28477c478bd9Sstevel@tonic-gate ** 28487c478bd9Sstevel@tonic-gate ** Returns: 28497c478bd9Sstevel@tonic-gate ** none. 28507c478bd9Sstevel@tonic-gate ** 28517c478bd9Sstevel@tonic-gate ** Side Effects: 28527c478bd9Sstevel@tonic-gate ** exits. 28537c478bd9Sstevel@tonic-gate */ 28547c478bd9Sstevel@tonic-gate 28557c478bd9Sstevel@tonic-gate void 28567c478bd9Sstevel@tonic-gate stop_sendmail() 28577c478bd9Sstevel@tonic-gate { 28587c478bd9Sstevel@tonic-gate /* reset uid for process accounting */ 28597c478bd9Sstevel@tonic-gate endpwent(); 28607c478bd9Sstevel@tonic-gate (void) setuid(RealUid); 28617c478bd9Sstevel@tonic-gate exit(EX_OK); 28627c478bd9Sstevel@tonic-gate } 28637c478bd9Sstevel@tonic-gate /* 28647c478bd9Sstevel@tonic-gate ** FINIS -- Clean up and exit. 28657c478bd9Sstevel@tonic-gate ** 28667c478bd9Sstevel@tonic-gate ** Parameters: 28677c478bd9Sstevel@tonic-gate ** drop -- whether or not to drop CurEnv envelope 28687c478bd9Sstevel@tonic-gate ** cleanup -- call exit() or _exit()? 28697c478bd9Sstevel@tonic-gate ** exitstat -- exit status to use for exit() call 28707c478bd9Sstevel@tonic-gate ** 28717c478bd9Sstevel@tonic-gate ** Returns: 28727c478bd9Sstevel@tonic-gate ** never 28737c478bd9Sstevel@tonic-gate ** 28747c478bd9Sstevel@tonic-gate ** Side Effects: 28757c478bd9Sstevel@tonic-gate ** exits sendmail 28767c478bd9Sstevel@tonic-gate */ 28777c478bd9Sstevel@tonic-gate 28787c478bd9Sstevel@tonic-gate void 28797c478bd9Sstevel@tonic-gate finis(drop, cleanup, exitstat) 28807c478bd9Sstevel@tonic-gate bool drop; 28817c478bd9Sstevel@tonic-gate bool cleanup; 28827c478bd9Sstevel@tonic-gate volatile int exitstat; 28837c478bd9Sstevel@tonic-gate { 28847c478bd9Sstevel@tonic-gate char pidpath[MAXPATHLEN]; 2885*3ee0e492Sjbeck pid_t pid; 28867c478bd9Sstevel@tonic-gate 28877c478bd9Sstevel@tonic-gate /* Still want to process new timeouts added below */ 28887c478bd9Sstevel@tonic-gate sm_clear_events(); 28897c478bd9Sstevel@tonic-gate (void) sm_releasesignal(SIGALRM); 28907c478bd9Sstevel@tonic-gate 28917c478bd9Sstevel@tonic-gate if (tTd(2, 1)) 28927c478bd9Sstevel@tonic-gate { 28937c478bd9Sstevel@tonic-gate sm_dprintf("\n====finis: stat %d e_id=%s e_flags=", 28947c478bd9Sstevel@tonic-gate exitstat, 28957c478bd9Sstevel@tonic-gate CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id); 28967c478bd9Sstevel@tonic-gate printenvflags(CurEnv); 28977c478bd9Sstevel@tonic-gate } 28987c478bd9Sstevel@tonic-gate if (tTd(2, 9)) 28997c478bd9Sstevel@tonic-gate printopenfds(false); 29007c478bd9Sstevel@tonic-gate 29017c478bd9Sstevel@tonic-gate SM_TRY 29027c478bd9Sstevel@tonic-gate /* 29037c478bd9Sstevel@tonic-gate ** Clean up. This might raise E:mta.quickabort 29047c478bd9Sstevel@tonic-gate */ 29057c478bd9Sstevel@tonic-gate 29067c478bd9Sstevel@tonic-gate /* clean up temp files */ 29077c478bd9Sstevel@tonic-gate CurEnv->e_to = NULL; 29087c478bd9Sstevel@tonic-gate if (drop) 29097c478bd9Sstevel@tonic-gate { 29107c478bd9Sstevel@tonic-gate if (CurEnv->e_id != NULL) 29117c478bd9Sstevel@tonic-gate { 29127c478bd9Sstevel@tonic-gate dropenvelope(CurEnv, true, false); 29137c478bd9Sstevel@tonic-gate sm_rpool_free(CurEnv->e_rpool); 29147c478bd9Sstevel@tonic-gate CurEnv->e_rpool = NULL; 29157c478bd9Sstevel@tonic-gate } 29167c478bd9Sstevel@tonic-gate else 29177c478bd9Sstevel@tonic-gate poststats(StatFile); 29187c478bd9Sstevel@tonic-gate } 29197c478bd9Sstevel@tonic-gate 29207c478bd9Sstevel@tonic-gate /* flush any cached connections */ 29217c478bd9Sstevel@tonic-gate mci_flush(true, NULL); 29227c478bd9Sstevel@tonic-gate 29237c478bd9Sstevel@tonic-gate /* close maps belonging to this pid */ 29247c478bd9Sstevel@tonic-gate closemaps(false); 29257c478bd9Sstevel@tonic-gate 29267c478bd9Sstevel@tonic-gate #if USERDB 29277c478bd9Sstevel@tonic-gate /* close UserDatabase */ 29287c478bd9Sstevel@tonic-gate _udbx_close(); 29297c478bd9Sstevel@tonic-gate #endif /* USERDB */ 29307c478bd9Sstevel@tonic-gate 29317c478bd9Sstevel@tonic-gate #if SASL 29327c478bd9Sstevel@tonic-gate stop_sasl_client(); 29337c478bd9Sstevel@tonic-gate #endif /* SASL */ 29347c478bd9Sstevel@tonic-gate 29357c478bd9Sstevel@tonic-gate #if XLA 29367c478bd9Sstevel@tonic-gate /* clean up extended load average stuff */ 29377c478bd9Sstevel@tonic-gate xla_all_end(); 29387c478bd9Sstevel@tonic-gate #endif /* XLA */ 29397c478bd9Sstevel@tonic-gate 29407c478bd9Sstevel@tonic-gate SM_FINALLY 29417c478bd9Sstevel@tonic-gate /* 29427c478bd9Sstevel@tonic-gate ** And exit. 29437c478bd9Sstevel@tonic-gate */ 29447c478bd9Sstevel@tonic-gate 29457c478bd9Sstevel@tonic-gate if (LogLevel > 78) 29467c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, "finis, pid=%d", 29477c478bd9Sstevel@tonic-gate (int) CurrentPid); 29487c478bd9Sstevel@tonic-gate if (exitstat == EX_TEMPFAIL || 29497c478bd9Sstevel@tonic-gate CurEnv->e_errormode == EM_BERKNET) 29507c478bd9Sstevel@tonic-gate exitstat = EX_OK; 29517c478bd9Sstevel@tonic-gate 29527c478bd9Sstevel@tonic-gate /* XXX clean up queues and related data structures */ 29537c478bd9Sstevel@tonic-gate cleanup_queues(); 2954*3ee0e492Sjbeck pid = getpid(); 29557c478bd9Sstevel@tonic-gate #if SM_CONF_SHM 2956*3ee0e492Sjbeck cleanup_shm(DaemonPid == pid); 29577c478bd9Sstevel@tonic-gate #endif /* SM_CONF_SHM */ 29587c478bd9Sstevel@tonic-gate 29597c478bd9Sstevel@tonic-gate /* close locked pid file */ 29607c478bd9Sstevel@tonic-gate close_sendmail_pid(); 29617c478bd9Sstevel@tonic-gate 2962*3ee0e492Sjbeck if (DaemonPid == pid || PidFilePid == pid) 29637c478bd9Sstevel@tonic-gate { 29647c478bd9Sstevel@tonic-gate /* blow away the pid file */ 29657c478bd9Sstevel@tonic-gate expand(PidFile, pidpath, sizeof pidpath, CurEnv); 29667c478bd9Sstevel@tonic-gate (void) unlink(pidpath); 29677c478bd9Sstevel@tonic-gate } 29687c478bd9Sstevel@tonic-gate 29697c478bd9Sstevel@tonic-gate /* reset uid for process accounting */ 29707c478bd9Sstevel@tonic-gate endpwent(); 29717c478bd9Sstevel@tonic-gate sm_mbdb_terminate(); 2972445f2479Sjbeck #if _FFR_MEMSTAT 2973445f2479Sjbeck (void) sm_memstat_close(); 2974445f2479Sjbeck #endif /* _FFR_MEMSTAT */ 29757c478bd9Sstevel@tonic-gate (void) setuid(RealUid); 29767c478bd9Sstevel@tonic-gate #if SM_HEAP_CHECK 29777c478bd9Sstevel@tonic-gate /* dump the heap, if we are checking for memory leaks */ 29787c478bd9Sstevel@tonic-gate if (sm_debug_active(&SmHeapCheck, 2)) 29797c478bd9Sstevel@tonic-gate sm_heap_report(smioout, 29807c478bd9Sstevel@tonic-gate sm_debug_level(&SmHeapCheck) - 1); 29817c478bd9Sstevel@tonic-gate #endif /* SM_HEAP_CHECK */ 29827c478bd9Sstevel@tonic-gate if (sm_debug_active(&SmXtrapReport, 1)) 29837c478bd9Sstevel@tonic-gate sm_dprintf("xtrap count = %d\n", SmXtrapCount); 29847c478bd9Sstevel@tonic-gate if (cleanup) 29857c478bd9Sstevel@tonic-gate exit(exitstat); 29867c478bd9Sstevel@tonic-gate else 29877c478bd9Sstevel@tonic-gate _exit(exitstat); 29887c478bd9Sstevel@tonic-gate SM_END_TRY 29897c478bd9Sstevel@tonic-gate } 29907c478bd9Sstevel@tonic-gate /* 29917c478bd9Sstevel@tonic-gate ** INTINDEBUG -- signal handler for SIGINT in -bt mode 29927c478bd9Sstevel@tonic-gate ** 29937c478bd9Sstevel@tonic-gate ** Parameters: 29947c478bd9Sstevel@tonic-gate ** sig -- incoming signal. 29957c478bd9Sstevel@tonic-gate ** 29967c478bd9Sstevel@tonic-gate ** Returns: 29977c478bd9Sstevel@tonic-gate ** none. 29987c478bd9Sstevel@tonic-gate ** 29997c478bd9Sstevel@tonic-gate ** Side Effects: 30007c478bd9Sstevel@tonic-gate ** longjmps back to test mode loop. 30017c478bd9Sstevel@tonic-gate ** 30027c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 30037c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 30047c478bd9Sstevel@tonic-gate ** DOING. 30057c478bd9Sstevel@tonic-gate */ 30067c478bd9Sstevel@tonic-gate 30077c478bd9Sstevel@tonic-gate /* Type of an exception generated on SIGINT during address test mode. */ 30087c478bd9Sstevel@tonic-gate static const SM_EXC_TYPE_T EtypeInterrupt = 30097c478bd9Sstevel@tonic-gate { 30107c478bd9Sstevel@tonic-gate SmExcTypeMagic, 30117c478bd9Sstevel@tonic-gate "S:mta.interrupt", 30127c478bd9Sstevel@tonic-gate "", 30137c478bd9Sstevel@tonic-gate sm_etype_printf, 30147c478bd9Sstevel@tonic-gate "interrupt", 30157c478bd9Sstevel@tonic-gate }; 30167c478bd9Sstevel@tonic-gate 30177c478bd9Sstevel@tonic-gate /* ARGSUSED */ 30187c478bd9Sstevel@tonic-gate static SIGFUNC_DECL 30197c478bd9Sstevel@tonic-gate intindebug(sig) 30207c478bd9Sstevel@tonic-gate int sig; 30217c478bd9Sstevel@tonic-gate { 30227c478bd9Sstevel@tonic-gate int save_errno = errno; 30237c478bd9Sstevel@tonic-gate 30247c478bd9Sstevel@tonic-gate FIX_SYSV_SIGNAL(sig, intindebug); 30257c478bd9Sstevel@tonic-gate errno = save_errno; 30267c478bd9Sstevel@tonic-gate CHECK_CRITICAL(sig); 30277c478bd9Sstevel@tonic-gate errno = save_errno; 30287c478bd9Sstevel@tonic-gate sm_exc_raisenew_x(&EtypeInterrupt); 30297c478bd9Sstevel@tonic-gate errno = save_errno; 30307c478bd9Sstevel@tonic-gate return SIGFUNC_RETURN; 30317c478bd9Sstevel@tonic-gate } 30327c478bd9Sstevel@tonic-gate /* 30337c478bd9Sstevel@tonic-gate ** SIGTERM -- SIGTERM handler for the daemon 30347c478bd9Sstevel@tonic-gate ** 30357c478bd9Sstevel@tonic-gate ** Parameters: 30367c478bd9Sstevel@tonic-gate ** sig -- signal number. 30377c478bd9Sstevel@tonic-gate ** 30387c478bd9Sstevel@tonic-gate ** Returns: 30397c478bd9Sstevel@tonic-gate ** none. 30407c478bd9Sstevel@tonic-gate ** 30417c478bd9Sstevel@tonic-gate ** Side Effects: 30427c478bd9Sstevel@tonic-gate ** Sets ShutdownRequest which will hopefully trigger 30437c478bd9Sstevel@tonic-gate ** the daemon to exit. 30447c478bd9Sstevel@tonic-gate ** 30457c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 30467c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 30477c478bd9Sstevel@tonic-gate ** DOING. 30487c478bd9Sstevel@tonic-gate */ 30497c478bd9Sstevel@tonic-gate 30507c478bd9Sstevel@tonic-gate /* ARGSUSED */ 30517c478bd9Sstevel@tonic-gate static SIGFUNC_DECL 30527c478bd9Sstevel@tonic-gate sigterm(sig) 30537c478bd9Sstevel@tonic-gate int sig; 30547c478bd9Sstevel@tonic-gate { 30557c478bd9Sstevel@tonic-gate int save_errno = errno; 30567c478bd9Sstevel@tonic-gate 30577c478bd9Sstevel@tonic-gate FIX_SYSV_SIGNAL(sig, sigterm); 30587c478bd9Sstevel@tonic-gate ShutdownRequest = "signal"; 30597c478bd9Sstevel@tonic-gate errno = save_errno; 30607c478bd9Sstevel@tonic-gate return SIGFUNC_RETURN; 30617c478bd9Sstevel@tonic-gate } 30627c478bd9Sstevel@tonic-gate /* 30637c478bd9Sstevel@tonic-gate ** SIGHUP -- handle a SIGHUP signal 30647c478bd9Sstevel@tonic-gate ** 30657c478bd9Sstevel@tonic-gate ** Parameters: 30667c478bd9Sstevel@tonic-gate ** sig -- incoming signal. 30677c478bd9Sstevel@tonic-gate ** 30687c478bd9Sstevel@tonic-gate ** Returns: 30697c478bd9Sstevel@tonic-gate ** none. 30707c478bd9Sstevel@tonic-gate ** 30717c478bd9Sstevel@tonic-gate ** Side Effects: 30727c478bd9Sstevel@tonic-gate ** Sets RestartRequest which should cause the daemon 30737c478bd9Sstevel@tonic-gate ** to restart. 30747c478bd9Sstevel@tonic-gate ** 30757c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 30767c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 30777c478bd9Sstevel@tonic-gate ** DOING. 30787c478bd9Sstevel@tonic-gate */ 30797c478bd9Sstevel@tonic-gate 30807c478bd9Sstevel@tonic-gate /* ARGSUSED */ 30817c478bd9Sstevel@tonic-gate static SIGFUNC_DECL 30827c478bd9Sstevel@tonic-gate sighup(sig) 30837c478bd9Sstevel@tonic-gate int sig; 30847c478bd9Sstevel@tonic-gate { 30857c478bd9Sstevel@tonic-gate int save_errno = errno; 30867c478bd9Sstevel@tonic-gate 30877c478bd9Sstevel@tonic-gate FIX_SYSV_SIGNAL(sig, sighup); 30887c478bd9Sstevel@tonic-gate RestartRequest = "signal"; 30897c478bd9Sstevel@tonic-gate errno = save_errno; 30907c478bd9Sstevel@tonic-gate return SIGFUNC_RETURN; 30917c478bd9Sstevel@tonic-gate } 30927c478bd9Sstevel@tonic-gate /* 30937c478bd9Sstevel@tonic-gate ** SIGPIPE -- signal handler for SIGPIPE 30947c478bd9Sstevel@tonic-gate ** 30957c478bd9Sstevel@tonic-gate ** Parameters: 30967c478bd9Sstevel@tonic-gate ** sig -- incoming signal. 30977c478bd9Sstevel@tonic-gate ** 30987c478bd9Sstevel@tonic-gate ** Returns: 30997c478bd9Sstevel@tonic-gate ** none. 31007c478bd9Sstevel@tonic-gate ** 31017c478bd9Sstevel@tonic-gate ** Side Effects: 31027c478bd9Sstevel@tonic-gate ** Sets StopRequest which should cause the mailq/hoststatus 31037c478bd9Sstevel@tonic-gate ** display to stop. 31047c478bd9Sstevel@tonic-gate ** 31057c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 31067c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 31077c478bd9Sstevel@tonic-gate ** DOING. 31087c478bd9Sstevel@tonic-gate */ 31097c478bd9Sstevel@tonic-gate 31107c478bd9Sstevel@tonic-gate /* ARGSUSED */ 31117c478bd9Sstevel@tonic-gate static SIGFUNC_DECL 31127c478bd9Sstevel@tonic-gate sigpipe(sig) 31137c478bd9Sstevel@tonic-gate int sig; 31147c478bd9Sstevel@tonic-gate { 31157c478bd9Sstevel@tonic-gate int save_errno = errno; 31167c478bd9Sstevel@tonic-gate 31177c478bd9Sstevel@tonic-gate FIX_SYSV_SIGNAL(sig, sigpipe); 31187c478bd9Sstevel@tonic-gate StopRequest = true; 31197c478bd9Sstevel@tonic-gate errno = save_errno; 31207c478bd9Sstevel@tonic-gate return SIGFUNC_RETURN; 31217c478bd9Sstevel@tonic-gate } 31227c478bd9Sstevel@tonic-gate /* 31237c478bd9Sstevel@tonic-gate ** INTSIG -- clean up on interrupt 31247c478bd9Sstevel@tonic-gate ** 31257c478bd9Sstevel@tonic-gate ** This just arranges to exit. It pessimizes in that it 31267c478bd9Sstevel@tonic-gate ** may resend a message. 31277c478bd9Sstevel@tonic-gate ** 31287c478bd9Sstevel@tonic-gate ** Parameters: 31297c478bd9Sstevel@tonic-gate ** none. 31307c478bd9Sstevel@tonic-gate ** 31317c478bd9Sstevel@tonic-gate ** Returns: 31327c478bd9Sstevel@tonic-gate ** none. 31337c478bd9Sstevel@tonic-gate ** 31347c478bd9Sstevel@tonic-gate ** Side Effects: 31357c478bd9Sstevel@tonic-gate ** Unlocks the current job. 31367c478bd9Sstevel@tonic-gate ** 31377c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 31387c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 31397c478bd9Sstevel@tonic-gate ** DOING. 31407c478bd9Sstevel@tonic-gate ** 31417c478bd9Sstevel@tonic-gate ** XXX: More work is needed for this signal handler. 31427c478bd9Sstevel@tonic-gate */ 31437c478bd9Sstevel@tonic-gate 31447c478bd9Sstevel@tonic-gate /* ARGSUSED */ 31457c478bd9Sstevel@tonic-gate SIGFUNC_DECL 31467c478bd9Sstevel@tonic-gate intsig(sig) 31477c478bd9Sstevel@tonic-gate int sig; 31487c478bd9Sstevel@tonic-gate { 31497c478bd9Sstevel@tonic-gate bool drop = false; 31507c478bd9Sstevel@tonic-gate int save_errno = errno; 31517c478bd9Sstevel@tonic-gate 31527c478bd9Sstevel@tonic-gate FIX_SYSV_SIGNAL(sig, intsig); 31537c478bd9Sstevel@tonic-gate errno = save_errno; 31547c478bd9Sstevel@tonic-gate CHECK_CRITICAL(sig); 31557c478bd9Sstevel@tonic-gate sm_allsignals(true); 31567c478bd9Sstevel@tonic-gate 31577c478bd9Sstevel@tonic-gate if (sig != 0 && LogLevel > 79) 31587c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, "interrupt"); 31597c478bd9Sstevel@tonic-gate FileName = NULL; 31607c478bd9Sstevel@tonic-gate 31617c478bd9Sstevel@tonic-gate /* Clean-up on aborted stdin message submission */ 31627c478bd9Sstevel@tonic-gate if (CurEnv->e_id != NULL && 31637c478bd9Sstevel@tonic-gate (OpMode == MD_SMTP || 31647c478bd9Sstevel@tonic-gate OpMode == MD_DELIVER || 31657c478bd9Sstevel@tonic-gate OpMode == MD_ARPAFTP)) 31667c478bd9Sstevel@tonic-gate { 31677c478bd9Sstevel@tonic-gate register ADDRESS *q; 31687c478bd9Sstevel@tonic-gate 31697c478bd9Sstevel@tonic-gate /* don't return an error indication */ 31707c478bd9Sstevel@tonic-gate CurEnv->e_to = NULL; 31717c478bd9Sstevel@tonic-gate CurEnv->e_flags &= ~EF_FATALERRS; 31727c478bd9Sstevel@tonic-gate CurEnv->e_flags |= EF_CLRQUEUE; 31737c478bd9Sstevel@tonic-gate 31747c478bd9Sstevel@tonic-gate /* 31757c478bd9Sstevel@tonic-gate ** Spin through the addresses and 31767c478bd9Sstevel@tonic-gate ** mark them dead to prevent bounces 31777c478bd9Sstevel@tonic-gate */ 31787c478bd9Sstevel@tonic-gate 31797c478bd9Sstevel@tonic-gate for (q = CurEnv->e_sendqueue; q != NULL; q = q->q_next) 31807c478bd9Sstevel@tonic-gate q->q_state = QS_DONTSEND; 31817c478bd9Sstevel@tonic-gate 31827c478bd9Sstevel@tonic-gate drop = true; 31837c478bd9Sstevel@tonic-gate } 31847c478bd9Sstevel@tonic-gate else if (OpMode != MD_TEST) 31857c478bd9Sstevel@tonic-gate { 31867c478bd9Sstevel@tonic-gate unlockqueue(CurEnv); 31877c478bd9Sstevel@tonic-gate } 31887c478bd9Sstevel@tonic-gate 31897c478bd9Sstevel@tonic-gate finis(drop, false, EX_OK); 31907c478bd9Sstevel@tonic-gate /* NOTREACHED */ 31917c478bd9Sstevel@tonic-gate } 31927c478bd9Sstevel@tonic-gate /* 31937c478bd9Sstevel@tonic-gate ** DISCONNECT -- remove our connection with any foreground process 31947c478bd9Sstevel@tonic-gate ** 31957c478bd9Sstevel@tonic-gate ** Parameters: 31967c478bd9Sstevel@tonic-gate ** droplev -- how "deeply" we should drop the line. 31977c478bd9Sstevel@tonic-gate ** 0 -- ignore signals, mail back errors, make sure 31987c478bd9Sstevel@tonic-gate ** output goes to stdout. 31997c478bd9Sstevel@tonic-gate ** 1 -- also, make stdout go to /dev/null. 32007c478bd9Sstevel@tonic-gate ** 2 -- also, disconnect from controlling terminal 32017c478bd9Sstevel@tonic-gate ** (only for daemon mode). 32027c478bd9Sstevel@tonic-gate ** e -- the current envelope. 32037c478bd9Sstevel@tonic-gate ** 32047c478bd9Sstevel@tonic-gate ** Returns: 32057c478bd9Sstevel@tonic-gate ** none 32067c478bd9Sstevel@tonic-gate ** 32077c478bd9Sstevel@tonic-gate ** Side Effects: 32087c478bd9Sstevel@tonic-gate ** Trys to insure that we are immune to vagaries of 32097c478bd9Sstevel@tonic-gate ** the controlling tty. 32107c478bd9Sstevel@tonic-gate */ 32117c478bd9Sstevel@tonic-gate 32127c478bd9Sstevel@tonic-gate void 32137c478bd9Sstevel@tonic-gate disconnect(droplev, e) 32147c478bd9Sstevel@tonic-gate int droplev; 32157c478bd9Sstevel@tonic-gate register ENVELOPE *e; 32167c478bd9Sstevel@tonic-gate { 32177c478bd9Sstevel@tonic-gate int fd; 32187c478bd9Sstevel@tonic-gate 32197c478bd9Sstevel@tonic-gate if (tTd(52, 1)) 32207c478bd9Sstevel@tonic-gate sm_dprintf("disconnect: In %d Out %d, e=%p\n", 32217c478bd9Sstevel@tonic-gate sm_io_getinfo(InChannel, SM_IO_WHAT_FD, NULL), 32227c478bd9Sstevel@tonic-gate sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL), e); 32237c478bd9Sstevel@tonic-gate if (tTd(52, 100)) 32247c478bd9Sstevel@tonic-gate { 32257c478bd9Sstevel@tonic-gate sm_dprintf("don't\n"); 32267c478bd9Sstevel@tonic-gate return; 32277c478bd9Sstevel@tonic-gate } 32287c478bd9Sstevel@tonic-gate if (LogLevel > 93) 32297c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, e->e_id, 32307c478bd9Sstevel@tonic-gate "disconnect level %d", 32317c478bd9Sstevel@tonic-gate droplev); 32327c478bd9Sstevel@tonic-gate 32337c478bd9Sstevel@tonic-gate /* be sure we don't get nasty signals */ 32347c478bd9Sstevel@tonic-gate (void) sm_signal(SIGINT, SIG_IGN); 32357c478bd9Sstevel@tonic-gate (void) sm_signal(SIGQUIT, SIG_IGN); 32367c478bd9Sstevel@tonic-gate 32377c478bd9Sstevel@tonic-gate /* we can't communicate with our caller, so.... */ 32387c478bd9Sstevel@tonic-gate HoldErrs = true; 32397c478bd9Sstevel@tonic-gate CurEnv->e_errormode = EM_MAIL; 32407c478bd9Sstevel@tonic-gate Verbose = 0; 32417c478bd9Sstevel@tonic-gate DisConnected = true; 32427c478bd9Sstevel@tonic-gate 32437c478bd9Sstevel@tonic-gate /* all input from /dev/null */ 32447c478bd9Sstevel@tonic-gate if (InChannel != smioin) 32457c478bd9Sstevel@tonic-gate { 32467c478bd9Sstevel@tonic-gate (void) sm_io_close(InChannel, SM_TIME_DEFAULT); 32477c478bd9Sstevel@tonic-gate InChannel = smioin; 32487c478bd9Sstevel@tonic-gate } 32497c478bd9Sstevel@tonic-gate if (sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, SM_PATH_DEVNULL, 32507c478bd9Sstevel@tonic-gate SM_IO_RDONLY, NULL, smioin) == NULL) 32517c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, e->e_id, 32527c478bd9Sstevel@tonic-gate "disconnect: sm_io_reopen(\"%s\") failed: %s", 32537c478bd9Sstevel@tonic-gate SM_PATH_DEVNULL, sm_errstring(errno)); 32547c478bd9Sstevel@tonic-gate 32557c478bd9Sstevel@tonic-gate /* 32567c478bd9Sstevel@tonic-gate ** output to the transcript 32577c478bd9Sstevel@tonic-gate ** We also compare the fd numbers here since OutChannel 32587c478bd9Sstevel@tonic-gate ** might be a layer on top of smioout due to encryption 32597c478bd9Sstevel@tonic-gate ** (see sfsasl.c). 32607c478bd9Sstevel@tonic-gate */ 32617c478bd9Sstevel@tonic-gate 32627c478bd9Sstevel@tonic-gate if (OutChannel != smioout && 32637c478bd9Sstevel@tonic-gate sm_io_getinfo(OutChannel, SM_IO_WHAT_FD, NULL) != 32647c478bd9Sstevel@tonic-gate sm_io_getinfo(smioout, SM_IO_WHAT_FD, NULL)) 32657c478bd9Sstevel@tonic-gate { 32667c478bd9Sstevel@tonic-gate (void) sm_io_close(OutChannel, SM_TIME_DEFAULT); 32677c478bd9Sstevel@tonic-gate OutChannel = smioout; 32687c478bd9Sstevel@tonic-gate 32697c478bd9Sstevel@tonic-gate #if 0 32707c478bd9Sstevel@tonic-gate /* 32717c478bd9Sstevel@tonic-gate ** Has smioout been closed? Reopen it. 32727c478bd9Sstevel@tonic-gate ** This shouldn't happen anymore, the code is here 32737c478bd9Sstevel@tonic-gate ** just as a reminder. 32747c478bd9Sstevel@tonic-gate */ 32757c478bd9Sstevel@tonic-gate 32767c478bd9Sstevel@tonic-gate if (smioout->sm_magic == NULL && 32777c478bd9Sstevel@tonic-gate sm_io_reopen(SmFtStdio, SM_TIME_DEFAULT, SM_PATH_DEVNULL, 32787c478bd9Sstevel@tonic-gate SM_IO_WRONLY, NULL, smioout) == NULL) 32797c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, e->e_id, 32807c478bd9Sstevel@tonic-gate "disconnect: sm_io_reopen(\"%s\") failed: %s", 32817c478bd9Sstevel@tonic-gate SM_PATH_DEVNULL, sm_errstring(errno)); 32827c478bd9Sstevel@tonic-gate #endif /* 0 */ 32837c478bd9Sstevel@tonic-gate } 32847c478bd9Sstevel@tonic-gate if (droplev > 0) 32857c478bd9Sstevel@tonic-gate { 32867c478bd9Sstevel@tonic-gate fd = open(SM_PATH_DEVNULL, O_WRONLY, 0666); 32877c478bd9Sstevel@tonic-gate if (fd == -1) 3288*3ee0e492Sjbeck { 32897c478bd9Sstevel@tonic-gate sm_syslog(LOG_ERR, e->e_id, 32907c478bd9Sstevel@tonic-gate "disconnect: open(\"%s\") failed: %s", 32917c478bd9Sstevel@tonic-gate SM_PATH_DEVNULL, sm_errstring(errno)); 3292*3ee0e492Sjbeck } 32937c478bd9Sstevel@tonic-gate (void) sm_io_flush(smioout, SM_TIME_DEFAULT); 3294*3ee0e492Sjbeck if (fd >= 0) 3295*3ee0e492Sjbeck { 3296*3ee0e492Sjbeck (void) dup2(fd, STDOUT_FILENO); 3297*3ee0e492Sjbeck (void) dup2(fd, STDERR_FILENO); 3298*3ee0e492Sjbeck (void) close(fd); 3299*3ee0e492Sjbeck } 33007c478bd9Sstevel@tonic-gate } 33017c478bd9Sstevel@tonic-gate 33027c478bd9Sstevel@tonic-gate /* drop our controlling TTY completely if possible */ 33037c478bd9Sstevel@tonic-gate if (droplev > 1) 33047c478bd9Sstevel@tonic-gate { 33057c478bd9Sstevel@tonic-gate (void) setsid(); 33067c478bd9Sstevel@tonic-gate errno = 0; 33077c478bd9Sstevel@tonic-gate } 33087c478bd9Sstevel@tonic-gate 33097c478bd9Sstevel@tonic-gate #if XDEBUG 33107c478bd9Sstevel@tonic-gate checkfd012("disconnect"); 33117c478bd9Sstevel@tonic-gate #endif /* XDEBUG */ 33127c478bd9Sstevel@tonic-gate 33137c478bd9Sstevel@tonic-gate if (LogLevel > 71) 33147c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, e->e_id, "in background, pid=%d", 33157c478bd9Sstevel@tonic-gate (int) CurrentPid); 33167c478bd9Sstevel@tonic-gate 33177c478bd9Sstevel@tonic-gate errno = 0; 33187c478bd9Sstevel@tonic-gate } 33197c478bd9Sstevel@tonic-gate 33207c478bd9Sstevel@tonic-gate static void 33217c478bd9Sstevel@tonic-gate obsolete(argv) 33227c478bd9Sstevel@tonic-gate char *argv[]; 33237c478bd9Sstevel@tonic-gate { 33247c478bd9Sstevel@tonic-gate register char *ap; 33257c478bd9Sstevel@tonic-gate register char *op; 33267c478bd9Sstevel@tonic-gate 33277c478bd9Sstevel@tonic-gate while ((ap = *++argv) != NULL) 33287c478bd9Sstevel@tonic-gate { 33297c478bd9Sstevel@tonic-gate /* Return if "--" or not an option of any form. */ 33307c478bd9Sstevel@tonic-gate if (ap[0] != '-' || ap[1] == '-') 33317c478bd9Sstevel@tonic-gate return; 33327c478bd9Sstevel@tonic-gate 33337c478bd9Sstevel@tonic-gate /* Don't allow users to use "-Q." or "-Q ." */ 33347c478bd9Sstevel@tonic-gate if ((ap[1] == 'Q' && ap[2] == '.') || 33357c478bd9Sstevel@tonic-gate (ap[1] == 'Q' && argv[1] != NULL && 33367c478bd9Sstevel@tonic-gate argv[1][0] == '.' && argv[1][1] == '\0')) 33377c478bd9Sstevel@tonic-gate { 33387c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 33397c478bd9Sstevel@tonic-gate "Can not use -Q.\n"); 33407c478bd9Sstevel@tonic-gate exit(EX_USAGE); 33417c478bd9Sstevel@tonic-gate } 33427c478bd9Sstevel@tonic-gate 33437c478bd9Sstevel@tonic-gate /* skip over options that do have a value */ 33447c478bd9Sstevel@tonic-gate op = strchr(OPTIONS, ap[1]); 33457c478bd9Sstevel@tonic-gate if (op != NULL && *++op == ':' && ap[2] == '\0' && 33467c478bd9Sstevel@tonic-gate ap[1] != 'd' && 33477c478bd9Sstevel@tonic-gate #if defined(sony_news) 33487c478bd9Sstevel@tonic-gate ap[1] != 'E' && ap[1] != 'J' && 33497c478bd9Sstevel@tonic-gate #endif /* defined(sony_news) */ 33507c478bd9Sstevel@tonic-gate argv[1] != NULL && argv[1][0] != '-') 33517c478bd9Sstevel@tonic-gate { 33527c478bd9Sstevel@tonic-gate argv++; 33537c478bd9Sstevel@tonic-gate continue; 33547c478bd9Sstevel@tonic-gate } 33557c478bd9Sstevel@tonic-gate 33567c478bd9Sstevel@tonic-gate /* If -C doesn't have an argument, use sendmail.cf. */ 33577c478bd9Sstevel@tonic-gate #define __DEFPATH "sendmail.cf" 33587c478bd9Sstevel@tonic-gate if (ap[1] == 'C' && ap[2] == '\0') 33597c478bd9Sstevel@tonic-gate { 33607c478bd9Sstevel@tonic-gate *argv = xalloc(sizeof(__DEFPATH) + 2); 33617c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(argv[0], sizeof(__DEFPATH) + 2, 2, 33627c478bd9Sstevel@tonic-gate "-C", __DEFPATH); 33637c478bd9Sstevel@tonic-gate } 33647c478bd9Sstevel@tonic-gate 33657c478bd9Sstevel@tonic-gate /* If -q doesn't have an argument, run it once. */ 33667c478bd9Sstevel@tonic-gate if (ap[1] == 'q' && ap[2] == '\0') 33677c478bd9Sstevel@tonic-gate *argv = "-q0"; 33687c478bd9Sstevel@tonic-gate 33697c478bd9Sstevel@tonic-gate /* If -Q doesn't have an argument, disable quarantining */ 33707c478bd9Sstevel@tonic-gate if (ap[1] == 'Q' && ap[2] == '\0') 33717c478bd9Sstevel@tonic-gate *argv = "-Q."; 33727c478bd9Sstevel@tonic-gate 33737c478bd9Sstevel@tonic-gate /* if -d doesn't have an argument, use 0-99.1 */ 33747c478bd9Sstevel@tonic-gate if (ap[1] == 'd' && ap[2] == '\0') 33757c478bd9Sstevel@tonic-gate *argv = "-d0-99.1"; 33767c478bd9Sstevel@tonic-gate 33777c478bd9Sstevel@tonic-gate #if defined(sony_news) 33787c478bd9Sstevel@tonic-gate /* if -E doesn't have an argument, use -EC */ 33797c478bd9Sstevel@tonic-gate if (ap[1] == 'E' && ap[2] == '\0') 33807c478bd9Sstevel@tonic-gate *argv = "-EC"; 33817c478bd9Sstevel@tonic-gate 33827c478bd9Sstevel@tonic-gate /* if -J doesn't have an argument, use -JJ */ 33837c478bd9Sstevel@tonic-gate if (ap[1] == 'J' && ap[2] == '\0') 33847c478bd9Sstevel@tonic-gate *argv = "-JJ"; 33857c478bd9Sstevel@tonic-gate #endif /* defined(sony_news) */ 33867c478bd9Sstevel@tonic-gate } 33877c478bd9Sstevel@tonic-gate } 33887c478bd9Sstevel@tonic-gate /* 33897c478bd9Sstevel@tonic-gate ** AUTH_WARNING -- specify authorization warning 33907c478bd9Sstevel@tonic-gate ** 33917c478bd9Sstevel@tonic-gate ** Parameters: 33927c478bd9Sstevel@tonic-gate ** e -- the current envelope. 33937c478bd9Sstevel@tonic-gate ** msg -- the text of the message. 33947c478bd9Sstevel@tonic-gate ** args -- arguments to the message. 33957c478bd9Sstevel@tonic-gate ** 33967c478bd9Sstevel@tonic-gate ** Returns: 33977c478bd9Sstevel@tonic-gate ** none. 33987c478bd9Sstevel@tonic-gate */ 33997c478bd9Sstevel@tonic-gate 34007c478bd9Sstevel@tonic-gate void 34017c478bd9Sstevel@tonic-gate #ifdef __STDC__ 34027c478bd9Sstevel@tonic-gate auth_warning(register ENVELOPE *e, const char *msg, ...) 34037c478bd9Sstevel@tonic-gate #else /* __STDC__ */ 34047c478bd9Sstevel@tonic-gate auth_warning(e, msg, va_alist) 34057c478bd9Sstevel@tonic-gate register ENVELOPE *e; 34067c478bd9Sstevel@tonic-gate const char *msg; 34077c478bd9Sstevel@tonic-gate va_dcl 34087c478bd9Sstevel@tonic-gate #endif /* __STDC__ */ 34097c478bd9Sstevel@tonic-gate { 34107c478bd9Sstevel@tonic-gate char buf[MAXLINE]; 34117c478bd9Sstevel@tonic-gate SM_VA_LOCAL_DECL 34127c478bd9Sstevel@tonic-gate 34137c478bd9Sstevel@tonic-gate if (bitset(PRIV_AUTHWARNINGS, PrivacyFlags)) 34147c478bd9Sstevel@tonic-gate { 34157c478bd9Sstevel@tonic-gate register char *p; 34167c478bd9Sstevel@tonic-gate static char hostbuf[48]; 34177c478bd9Sstevel@tonic-gate 34187c478bd9Sstevel@tonic-gate if (hostbuf[0] == '\0') 34197c478bd9Sstevel@tonic-gate { 34207c478bd9Sstevel@tonic-gate struct hostent *hp; 34217c478bd9Sstevel@tonic-gate 34227c478bd9Sstevel@tonic-gate hp = myhostname(hostbuf, sizeof hostbuf); 34237c478bd9Sstevel@tonic-gate #if NETINET6 34247c478bd9Sstevel@tonic-gate if (hp != NULL) 34257c478bd9Sstevel@tonic-gate { 34267c478bd9Sstevel@tonic-gate freehostent(hp); 34277c478bd9Sstevel@tonic-gate hp = NULL; 34287c478bd9Sstevel@tonic-gate } 34297c478bd9Sstevel@tonic-gate #endif /* NETINET6 */ 34307c478bd9Sstevel@tonic-gate } 34317c478bd9Sstevel@tonic-gate 34327c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(buf, sizeof buf, 2, hostbuf, ": "); 34337c478bd9Sstevel@tonic-gate p = &buf[strlen(buf)]; 34347c478bd9Sstevel@tonic-gate SM_VA_START(ap, msg); 34357c478bd9Sstevel@tonic-gate (void) sm_vsnprintf(p, SPACELEFT(buf, p), msg, ap); 34367c478bd9Sstevel@tonic-gate SM_VA_END(ap); 34377c478bd9Sstevel@tonic-gate addheader("X-Authentication-Warning", buf, 0, e); 34387c478bd9Sstevel@tonic-gate if (LogLevel > 3) 34397c478bd9Sstevel@tonic-gate sm_syslog(LOG_INFO, e->e_id, 34407c478bd9Sstevel@tonic-gate "Authentication-Warning: %.400s", 34417c478bd9Sstevel@tonic-gate buf); 34427c478bd9Sstevel@tonic-gate } 34437c478bd9Sstevel@tonic-gate } 34447c478bd9Sstevel@tonic-gate /* 34457c478bd9Sstevel@tonic-gate ** GETEXTENV -- get from external environment 34467c478bd9Sstevel@tonic-gate ** 34477c478bd9Sstevel@tonic-gate ** Parameters: 34487c478bd9Sstevel@tonic-gate ** envar -- the name of the variable to retrieve 34497c478bd9Sstevel@tonic-gate ** 34507c478bd9Sstevel@tonic-gate ** Returns: 34517c478bd9Sstevel@tonic-gate ** The value, if any. 34527c478bd9Sstevel@tonic-gate */ 34537c478bd9Sstevel@tonic-gate 34547c478bd9Sstevel@tonic-gate static char * 34557c478bd9Sstevel@tonic-gate getextenv(envar) 34567c478bd9Sstevel@tonic-gate const char *envar; 34577c478bd9Sstevel@tonic-gate { 34587c478bd9Sstevel@tonic-gate char **envp; 34597c478bd9Sstevel@tonic-gate int l; 34607c478bd9Sstevel@tonic-gate 34617c478bd9Sstevel@tonic-gate l = strlen(envar); 34627c478bd9Sstevel@tonic-gate for (envp = ExternalEnviron; envp != NULL && *envp != NULL; envp++) 34637c478bd9Sstevel@tonic-gate { 34647c478bd9Sstevel@tonic-gate if (strncmp(*envp, envar, l) == 0 && (*envp)[l] == '=') 34657c478bd9Sstevel@tonic-gate return &(*envp)[l + 1]; 34667c478bd9Sstevel@tonic-gate } 34677c478bd9Sstevel@tonic-gate return NULL; 34687c478bd9Sstevel@tonic-gate } 34697c478bd9Sstevel@tonic-gate /* 3470445f2479Sjbeck ** SM_SETUSERENV -- set an environment variable in the propagated environment 34717c478bd9Sstevel@tonic-gate ** 34727c478bd9Sstevel@tonic-gate ** Parameters: 34737c478bd9Sstevel@tonic-gate ** envar -- the name of the environment variable. 34747c478bd9Sstevel@tonic-gate ** value -- the value to which it should be set. If 34757c478bd9Sstevel@tonic-gate ** null, this is extracted from the incoming 34767c478bd9Sstevel@tonic-gate ** environment. If that is not set, the call 3477445f2479Sjbeck ** to sm_setuserenv is ignored. 34787c478bd9Sstevel@tonic-gate ** 34797c478bd9Sstevel@tonic-gate ** Returns: 34807c478bd9Sstevel@tonic-gate ** none. 34817c478bd9Sstevel@tonic-gate */ 34827c478bd9Sstevel@tonic-gate 34837c478bd9Sstevel@tonic-gate void 3484445f2479Sjbeck sm_setuserenv(envar, value) 34857c478bd9Sstevel@tonic-gate const char *envar; 34867c478bd9Sstevel@tonic-gate const char *value; 34877c478bd9Sstevel@tonic-gate { 34887c478bd9Sstevel@tonic-gate int i, l; 34897c478bd9Sstevel@tonic-gate char **evp = UserEnviron; 34907c478bd9Sstevel@tonic-gate char *p; 34917c478bd9Sstevel@tonic-gate 34927c478bd9Sstevel@tonic-gate if (value == NULL) 34937c478bd9Sstevel@tonic-gate { 34947c478bd9Sstevel@tonic-gate value = getextenv(envar); 34957c478bd9Sstevel@tonic-gate if (value == NULL) 34967c478bd9Sstevel@tonic-gate return; 34977c478bd9Sstevel@tonic-gate } 34987c478bd9Sstevel@tonic-gate 34997c478bd9Sstevel@tonic-gate /* XXX enforce reasonable size? */ 35007c478bd9Sstevel@tonic-gate i = strlen(envar) + 1; 35017c478bd9Sstevel@tonic-gate l = strlen(value) + i + 1; 35027c478bd9Sstevel@tonic-gate p = (char *) xalloc(l); 35037c478bd9Sstevel@tonic-gate (void) sm_strlcpyn(p, l, 3, envar, "=", value); 35047c478bd9Sstevel@tonic-gate 35057c478bd9Sstevel@tonic-gate while (*evp != NULL && strncmp(*evp, p, i) != 0) 35067c478bd9Sstevel@tonic-gate evp++; 35077c478bd9Sstevel@tonic-gate if (*evp != NULL) 35087c478bd9Sstevel@tonic-gate { 35097c478bd9Sstevel@tonic-gate *evp++ = p; 35107c478bd9Sstevel@tonic-gate } 35117c478bd9Sstevel@tonic-gate else if (evp < &UserEnviron[MAXUSERENVIRON]) 35127c478bd9Sstevel@tonic-gate { 35137c478bd9Sstevel@tonic-gate *evp++ = p; 35147c478bd9Sstevel@tonic-gate *evp = NULL; 35157c478bd9Sstevel@tonic-gate } 35167c478bd9Sstevel@tonic-gate 35177c478bd9Sstevel@tonic-gate /* make sure it is in our environment as well */ 35187c478bd9Sstevel@tonic-gate if (putenv(p) < 0) 3519445f2479Sjbeck syserr("sm_setuserenv: putenv(%s) failed", p); 35207c478bd9Sstevel@tonic-gate } 35217c478bd9Sstevel@tonic-gate /* 35227c478bd9Sstevel@tonic-gate ** DUMPSTATE -- dump state 35237c478bd9Sstevel@tonic-gate ** 35247c478bd9Sstevel@tonic-gate ** For debugging. 35257c478bd9Sstevel@tonic-gate */ 35267c478bd9Sstevel@tonic-gate 35277c478bd9Sstevel@tonic-gate void 35287c478bd9Sstevel@tonic-gate dumpstate(when) 35297c478bd9Sstevel@tonic-gate char *when; 35307c478bd9Sstevel@tonic-gate { 35317c478bd9Sstevel@tonic-gate register char *j = macvalue('j', CurEnv); 35327c478bd9Sstevel@tonic-gate int rs; 35337c478bd9Sstevel@tonic-gate extern int NextMacroId; 35347c478bd9Sstevel@tonic-gate 35357c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, 35367c478bd9Sstevel@tonic-gate "--- dumping state on %s: $j = %s ---", 35377c478bd9Sstevel@tonic-gate when, 35387c478bd9Sstevel@tonic-gate j == NULL ? "<NULL>" : j); 35397c478bd9Sstevel@tonic-gate if (j != NULL) 35407c478bd9Sstevel@tonic-gate { 35417c478bd9Sstevel@tonic-gate if (!wordinclass(j, 'w')) 35427c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, 35437c478bd9Sstevel@tonic-gate "*** $j not in $=w ***"); 35447c478bd9Sstevel@tonic-gate } 35457c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, "CurChildren = %d", CurChildren); 35467c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, "NextMacroId = %d (Max %d)", 35477c478bd9Sstevel@tonic-gate NextMacroId, MAXMACROID); 35487c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- open file descriptors: ---"); 35497c478bd9Sstevel@tonic-gate printopenfds(true); 35507c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- connection cache: ---"); 35517c478bd9Sstevel@tonic-gate mci_dump_all(smioout, true); 35527c478bd9Sstevel@tonic-gate rs = strtorwset("debug_dumpstate", NULL, ST_FIND); 35537c478bd9Sstevel@tonic-gate if (rs > 0) 35547c478bd9Sstevel@tonic-gate { 35557c478bd9Sstevel@tonic-gate int status; 35567c478bd9Sstevel@tonic-gate register char **pvp; 35577c478bd9Sstevel@tonic-gate char *pv[MAXATOM + 1]; 35587c478bd9Sstevel@tonic-gate 35597c478bd9Sstevel@tonic-gate pv[0] = NULL; 35607c478bd9Sstevel@tonic-gate status = REWRITE(pv, rs, CurEnv); 35617c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, 35627c478bd9Sstevel@tonic-gate "--- ruleset debug_dumpstate returns stat %d, pv: ---", 35637c478bd9Sstevel@tonic-gate status); 35647c478bd9Sstevel@tonic-gate for (pvp = pv; *pvp != NULL; pvp++) 35657c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, "%s", *pvp); 35667c478bd9Sstevel@tonic-gate } 35677c478bd9Sstevel@tonic-gate sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- end of state dump ---"); 35687c478bd9Sstevel@tonic-gate } 35697c478bd9Sstevel@tonic-gate 35707c478bd9Sstevel@tonic-gate #ifdef SIGUSR1 35717c478bd9Sstevel@tonic-gate /* 35727c478bd9Sstevel@tonic-gate ** SIGUSR1 -- Signal a request to dump state. 35737c478bd9Sstevel@tonic-gate ** 35747c478bd9Sstevel@tonic-gate ** Parameters: 35757c478bd9Sstevel@tonic-gate ** sig -- calling signal. 35767c478bd9Sstevel@tonic-gate ** 35777c478bd9Sstevel@tonic-gate ** Returns: 35787c478bd9Sstevel@tonic-gate ** none. 35797c478bd9Sstevel@tonic-gate ** 35807c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 35817c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 35827c478bd9Sstevel@tonic-gate ** DOING. 35837c478bd9Sstevel@tonic-gate ** 35847c478bd9Sstevel@tonic-gate ** XXX: More work is needed for this signal handler. 35857c478bd9Sstevel@tonic-gate */ 35867c478bd9Sstevel@tonic-gate 35877c478bd9Sstevel@tonic-gate /* ARGSUSED */ 35887c478bd9Sstevel@tonic-gate static SIGFUNC_DECL 35897c478bd9Sstevel@tonic-gate sigusr1(sig) 35907c478bd9Sstevel@tonic-gate int sig; 35917c478bd9Sstevel@tonic-gate { 35927c478bd9Sstevel@tonic-gate int save_errno = errno; 35937c478bd9Sstevel@tonic-gate # if SM_HEAP_CHECK 35947c478bd9Sstevel@tonic-gate extern void dumpstab __P((void)); 35957c478bd9Sstevel@tonic-gate # endif /* SM_HEAP_CHECK */ 35967c478bd9Sstevel@tonic-gate 35977c478bd9Sstevel@tonic-gate FIX_SYSV_SIGNAL(sig, sigusr1); 35987c478bd9Sstevel@tonic-gate errno = save_errno; 35997c478bd9Sstevel@tonic-gate CHECK_CRITICAL(sig); 36007c478bd9Sstevel@tonic-gate dumpstate("user signal"); 36017c478bd9Sstevel@tonic-gate # if SM_HEAP_CHECK 36027c478bd9Sstevel@tonic-gate dumpstab(); 36037c478bd9Sstevel@tonic-gate # endif /* SM_HEAP_CHECK */ 36047c478bd9Sstevel@tonic-gate errno = save_errno; 36057c478bd9Sstevel@tonic-gate return SIGFUNC_RETURN; 36067c478bd9Sstevel@tonic-gate } 36077c478bd9Sstevel@tonic-gate #endif /* SIGUSR1 */ 36087c478bd9Sstevel@tonic-gate 36097c478bd9Sstevel@tonic-gate /* 36107c478bd9Sstevel@tonic-gate ** DROP_PRIVILEGES -- reduce privileges to those of the RunAsUser option 36117c478bd9Sstevel@tonic-gate ** 36127c478bd9Sstevel@tonic-gate ** Parameters: 36137c478bd9Sstevel@tonic-gate ** to_real_uid -- if set, drop to the real uid instead 36147c478bd9Sstevel@tonic-gate ** of the RunAsUser. 36157c478bd9Sstevel@tonic-gate ** 36167c478bd9Sstevel@tonic-gate ** Returns: 36177c478bd9Sstevel@tonic-gate ** EX_OSERR if the setuid failed. 36187c478bd9Sstevel@tonic-gate ** EX_OK otherwise. 36197c478bd9Sstevel@tonic-gate */ 36207c478bd9Sstevel@tonic-gate 36217c478bd9Sstevel@tonic-gate int 36227c478bd9Sstevel@tonic-gate drop_privileges(to_real_uid) 36237c478bd9Sstevel@tonic-gate bool to_real_uid; 36247c478bd9Sstevel@tonic-gate { 36257c478bd9Sstevel@tonic-gate int rval = EX_OK; 36267c478bd9Sstevel@tonic-gate GIDSET_T emptygidset[1]; 36277c478bd9Sstevel@tonic-gate 36287c478bd9Sstevel@tonic-gate if (tTd(47, 1)) 36297c478bd9Sstevel@tonic-gate 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", 36307c478bd9Sstevel@tonic-gate (int) to_real_uid, 36317c478bd9Sstevel@tonic-gate (int) RealUid, (int) RealGid, 36327c478bd9Sstevel@tonic-gate (int) getuid(), (int) getgid(), 36337c478bd9Sstevel@tonic-gate (int) geteuid(), (int) getegid(), 36347c478bd9Sstevel@tonic-gate (int) RunAsUid, (int) RunAsGid); 36357c478bd9Sstevel@tonic-gate 36367c478bd9Sstevel@tonic-gate if (to_real_uid) 36377c478bd9Sstevel@tonic-gate { 36387c478bd9Sstevel@tonic-gate RunAsUserName = RealUserName; 36397c478bd9Sstevel@tonic-gate RunAsUid = RealUid; 36407c478bd9Sstevel@tonic-gate RunAsGid = RealGid; 36417c478bd9Sstevel@tonic-gate EffGid = RunAsGid; 36427c478bd9Sstevel@tonic-gate } 36437c478bd9Sstevel@tonic-gate 36447c478bd9Sstevel@tonic-gate /* make sure no one can grab open descriptors for secret files */ 36457c478bd9Sstevel@tonic-gate endpwent(); 36467c478bd9Sstevel@tonic-gate sm_mbdb_terminate(); 36477c478bd9Sstevel@tonic-gate 36487c478bd9Sstevel@tonic-gate /* reset group permissions; these can be set later */ 36497c478bd9Sstevel@tonic-gate emptygidset[0] = (to_real_uid || RunAsGid != 0) ? RunAsGid : getegid(); 36507c478bd9Sstevel@tonic-gate 36517c478bd9Sstevel@tonic-gate /* 36527c478bd9Sstevel@tonic-gate ** Notice: on some OS (Linux...) the setgroups() call causes 36537c478bd9Sstevel@tonic-gate ** a logfile entry if sendmail is not run by root. 36547c478bd9Sstevel@tonic-gate ** However, it is unclear (no POSIX standard) whether 36557c478bd9Sstevel@tonic-gate ** setgroups() can only succeed if executed by root. 36567c478bd9Sstevel@tonic-gate ** So for now we keep it as it is; if you want to change it, use 36577c478bd9Sstevel@tonic-gate ** if (geteuid() == 0 && setgroups(1, emptygidset) == -1) 36587c478bd9Sstevel@tonic-gate */ 36597c478bd9Sstevel@tonic-gate 36607c478bd9Sstevel@tonic-gate if (setgroups(1, emptygidset) == -1 && geteuid() == 0) 36617c478bd9Sstevel@tonic-gate { 36627c478bd9Sstevel@tonic-gate syserr("drop_privileges: setgroups(1, %d) failed", 36637c478bd9Sstevel@tonic-gate (int) emptygidset[0]); 36647c478bd9Sstevel@tonic-gate rval = EX_OSERR; 36657c478bd9Sstevel@tonic-gate } 36667c478bd9Sstevel@tonic-gate 36677c478bd9Sstevel@tonic-gate /* reset primary group id */ 36687c478bd9Sstevel@tonic-gate if (to_real_uid) 36697c478bd9Sstevel@tonic-gate { 36707c478bd9Sstevel@tonic-gate /* 36717c478bd9Sstevel@tonic-gate ** Drop gid to real gid. 36727c478bd9Sstevel@tonic-gate ** On some OS we must reset the effective[/real[/saved]] gid, 36737c478bd9Sstevel@tonic-gate ** and then use setgid() to finally drop all group privileges. 36747c478bd9Sstevel@tonic-gate ** Later on we check whether we can get back the 36757c478bd9Sstevel@tonic-gate ** effective gid. 36767c478bd9Sstevel@tonic-gate */ 36777c478bd9Sstevel@tonic-gate 36787c478bd9Sstevel@tonic-gate #if HASSETEGID 36797c478bd9Sstevel@tonic-gate if (setegid(RunAsGid) < 0) 36807c478bd9Sstevel@tonic-gate { 36817c478bd9Sstevel@tonic-gate syserr("drop_privileges: setegid(%d) failed", 36827c478bd9Sstevel@tonic-gate (int) RunAsGid); 36837c478bd9Sstevel@tonic-gate rval = EX_OSERR; 36847c478bd9Sstevel@tonic-gate } 36857c478bd9Sstevel@tonic-gate #else /* HASSETEGID */ 36867c478bd9Sstevel@tonic-gate # if HASSETREGID 36877c478bd9Sstevel@tonic-gate if (setregid(RunAsGid, RunAsGid) < 0) 36887c478bd9Sstevel@tonic-gate { 36897c478bd9Sstevel@tonic-gate syserr("drop_privileges: setregid(%d, %d) failed", 36907c478bd9Sstevel@tonic-gate (int) RunAsGid, (int) RunAsGid); 36917c478bd9Sstevel@tonic-gate rval = EX_OSERR; 36927c478bd9Sstevel@tonic-gate } 36937c478bd9Sstevel@tonic-gate # else /* HASSETREGID */ 36947c478bd9Sstevel@tonic-gate # if HASSETRESGID 36957c478bd9Sstevel@tonic-gate if (setresgid(RunAsGid, RunAsGid, RunAsGid) < 0) 36967c478bd9Sstevel@tonic-gate { 36977c478bd9Sstevel@tonic-gate syserr("drop_privileges: setresgid(%d, %d, %d) failed", 36987c478bd9Sstevel@tonic-gate (int) RunAsGid, (int) RunAsGid, (int) RunAsGid); 36997c478bd9Sstevel@tonic-gate rval = EX_OSERR; 37007c478bd9Sstevel@tonic-gate } 37017c478bd9Sstevel@tonic-gate # endif /* HASSETRESGID */ 37027c478bd9Sstevel@tonic-gate # endif /* HASSETREGID */ 37037c478bd9Sstevel@tonic-gate #endif /* HASSETEGID */ 37047c478bd9Sstevel@tonic-gate } 37057c478bd9Sstevel@tonic-gate if (rval == EX_OK && (to_real_uid || RunAsGid != 0)) 37067c478bd9Sstevel@tonic-gate { 37077c478bd9Sstevel@tonic-gate if (setgid(RunAsGid) < 0 && (!UseMSP || getegid() != RunAsGid)) 37087c478bd9Sstevel@tonic-gate { 37097c478bd9Sstevel@tonic-gate syserr("drop_privileges: setgid(%d) failed", 37107c478bd9Sstevel@tonic-gate (int) RunAsGid); 37117c478bd9Sstevel@tonic-gate rval = EX_OSERR; 37127c478bd9Sstevel@tonic-gate } 37137c478bd9Sstevel@tonic-gate errno = 0; 37147c478bd9Sstevel@tonic-gate if (rval == EX_OK && getegid() != RunAsGid) 37157c478bd9Sstevel@tonic-gate { 37167c478bd9Sstevel@tonic-gate syserr("drop_privileges: Unable to set effective gid=%d to RunAsGid=%d", 37177c478bd9Sstevel@tonic-gate (int) getegid(), (int) RunAsGid); 37187c478bd9Sstevel@tonic-gate rval = EX_OSERR; 37197c478bd9Sstevel@tonic-gate } 37207c478bd9Sstevel@tonic-gate } 37217c478bd9Sstevel@tonic-gate 37227c478bd9Sstevel@tonic-gate /* fiddle with uid */ 37237c478bd9Sstevel@tonic-gate if (to_real_uid || RunAsUid != 0) 37247c478bd9Sstevel@tonic-gate { 37257c478bd9Sstevel@tonic-gate uid_t euid; 37267c478bd9Sstevel@tonic-gate 37277c478bd9Sstevel@tonic-gate /* 37287c478bd9Sstevel@tonic-gate ** Try to setuid(RunAsUid). 37297c478bd9Sstevel@tonic-gate ** euid must be RunAsUid, 37307c478bd9Sstevel@tonic-gate ** ruid must be RunAsUid unless (e|r)uid wasn't 0 37317c478bd9Sstevel@tonic-gate ** and we didn't have to drop privileges to the real uid. 37327c478bd9Sstevel@tonic-gate */ 37337c478bd9Sstevel@tonic-gate 37347c478bd9Sstevel@tonic-gate if (setuid(RunAsUid) < 0 || 37357c478bd9Sstevel@tonic-gate geteuid() != RunAsUid || 37367c478bd9Sstevel@tonic-gate (getuid() != RunAsUid && 37377c478bd9Sstevel@tonic-gate (to_real_uid || geteuid() == 0 || getuid() == 0))) 37387c478bd9Sstevel@tonic-gate { 37397c478bd9Sstevel@tonic-gate #if HASSETREUID 37407c478bd9Sstevel@tonic-gate /* 37417c478bd9Sstevel@tonic-gate ** if ruid != RunAsUid, euid == RunAsUid, then 37427c478bd9Sstevel@tonic-gate ** try resetting just the real uid, then using 37437c478bd9Sstevel@tonic-gate ** setuid() to drop the saved-uid as well. 37447c478bd9Sstevel@tonic-gate */ 37457c478bd9Sstevel@tonic-gate 37467c478bd9Sstevel@tonic-gate if (geteuid() == RunAsUid) 37477c478bd9Sstevel@tonic-gate { 37487c478bd9Sstevel@tonic-gate if (setreuid(RunAsUid, -1) < 0) 37497c478bd9Sstevel@tonic-gate { 37507c478bd9Sstevel@tonic-gate syserr("drop_privileges: setreuid(%d, -1) failed", 37517c478bd9Sstevel@tonic-gate (int) RunAsUid); 37527c478bd9Sstevel@tonic-gate rval = EX_OSERR; 37537c478bd9Sstevel@tonic-gate } 37547c478bd9Sstevel@tonic-gate if (setuid(RunAsUid) < 0) 37557c478bd9Sstevel@tonic-gate { 37567c478bd9Sstevel@tonic-gate syserr("drop_privileges: second setuid(%d) attempt failed", 37577c478bd9Sstevel@tonic-gate (int) RunAsUid); 37587c478bd9Sstevel@tonic-gate rval = EX_OSERR; 37597c478bd9Sstevel@tonic-gate } 37607c478bd9Sstevel@tonic-gate } 37617c478bd9Sstevel@tonic-gate else 37627c478bd9Sstevel@tonic-gate #endif /* HASSETREUID */ 37637c478bd9Sstevel@tonic-gate { 37647c478bd9Sstevel@tonic-gate syserr("drop_privileges: setuid(%d) failed", 37657c478bd9Sstevel@tonic-gate (int) RunAsUid); 37667c478bd9Sstevel@tonic-gate rval = EX_OSERR; 37677c478bd9Sstevel@tonic-gate } 37687c478bd9Sstevel@tonic-gate } 37697c478bd9Sstevel@tonic-gate euid = geteuid(); 37707c478bd9Sstevel@tonic-gate if (RunAsUid != 0 && setuid(0) == 0) 37717c478bd9Sstevel@tonic-gate { 37727c478bd9Sstevel@tonic-gate /* 37737c478bd9Sstevel@tonic-gate ** Believe it or not, the Linux capability model 37747c478bd9Sstevel@tonic-gate ** allows a non-root process to override setuid() 37757c478bd9Sstevel@tonic-gate ** on a process running as root and prevent that 37767c478bd9Sstevel@tonic-gate ** process from dropping privileges. 37777c478bd9Sstevel@tonic-gate */ 37787c478bd9Sstevel@tonic-gate 37797c478bd9Sstevel@tonic-gate syserr("drop_privileges: setuid(0) succeeded (when it should not)"); 37807c478bd9Sstevel@tonic-gate rval = EX_OSERR; 37817c478bd9Sstevel@tonic-gate } 37827c478bd9Sstevel@tonic-gate else if (RunAsUid != euid && setuid(euid) == 0) 37837c478bd9Sstevel@tonic-gate { 37847c478bd9Sstevel@tonic-gate /* 37857c478bd9Sstevel@tonic-gate ** Some operating systems will keep the saved-uid 37867c478bd9Sstevel@tonic-gate ** if a non-root effective-uid calls setuid(real-uid) 37877c478bd9Sstevel@tonic-gate ** making it possible to set it back again later. 37887c478bd9Sstevel@tonic-gate */ 37897c478bd9Sstevel@tonic-gate 37907c478bd9Sstevel@tonic-gate syserr("drop_privileges: Unable to drop non-root set-user-ID privileges"); 37917c478bd9Sstevel@tonic-gate rval = EX_OSERR; 37927c478bd9Sstevel@tonic-gate } 37937c478bd9Sstevel@tonic-gate } 37947c478bd9Sstevel@tonic-gate 37957c478bd9Sstevel@tonic-gate if ((to_real_uid || RunAsGid != 0) && 37967c478bd9Sstevel@tonic-gate rval == EX_OK && RunAsGid != EffGid && 37977c478bd9Sstevel@tonic-gate getuid() != 0 && geteuid() != 0) 37987c478bd9Sstevel@tonic-gate { 37997c478bd9Sstevel@tonic-gate errno = 0; 38007c478bd9Sstevel@tonic-gate if (setgid(EffGid) == 0) 38017c478bd9Sstevel@tonic-gate { 38027c478bd9Sstevel@tonic-gate syserr("drop_privileges: setgid(%d) succeeded (when it should not)", 38037c478bd9Sstevel@tonic-gate (int) EffGid); 38047c478bd9Sstevel@tonic-gate rval = EX_OSERR; 38057c478bd9Sstevel@tonic-gate } 38067c478bd9Sstevel@tonic-gate } 38077c478bd9Sstevel@tonic-gate 38087c478bd9Sstevel@tonic-gate if (tTd(47, 5)) 38097c478bd9Sstevel@tonic-gate { 38107c478bd9Sstevel@tonic-gate sm_dprintf("drop_privileges: e/ruid = %d/%d e/rgid = %d/%d\n", 38117c478bd9Sstevel@tonic-gate (int) geteuid(), (int) getuid(), 38127c478bd9Sstevel@tonic-gate (int) getegid(), (int) getgid()); 38137c478bd9Sstevel@tonic-gate sm_dprintf("drop_privileges: RunAsUser = %d:%d\n", 38147c478bd9Sstevel@tonic-gate (int) RunAsUid, (int) RunAsGid); 38157c478bd9Sstevel@tonic-gate if (tTd(47, 10)) 38167c478bd9Sstevel@tonic-gate sm_dprintf("drop_privileges: rval = %d\n", rval); 38177c478bd9Sstevel@tonic-gate } 38187c478bd9Sstevel@tonic-gate return rval; 38197c478bd9Sstevel@tonic-gate } 38207c478bd9Sstevel@tonic-gate /* 38217c478bd9Sstevel@tonic-gate ** FILL_FD -- make sure a file descriptor has been properly allocated 38227c478bd9Sstevel@tonic-gate ** 38237c478bd9Sstevel@tonic-gate ** Used to make sure that stdin/out/err are allocated on startup 38247c478bd9Sstevel@tonic-gate ** 38257c478bd9Sstevel@tonic-gate ** Parameters: 38267c478bd9Sstevel@tonic-gate ** fd -- the file descriptor to be filled. 38277c478bd9Sstevel@tonic-gate ** where -- a string used for logging. If NULL, this is 38287c478bd9Sstevel@tonic-gate ** being called on startup, and logging should 38297c478bd9Sstevel@tonic-gate ** not be done. 38307c478bd9Sstevel@tonic-gate ** 38317c478bd9Sstevel@tonic-gate ** Returns: 38327c478bd9Sstevel@tonic-gate ** none 38337c478bd9Sstevel@tonic-gate ** 38347c478bd9Sstevel@tonic-gate ** Side Effects: 38357c478bd9Sstevel@tonic-gate ** possibly changes MissingFds 38367c478bd9Sstevel@tonic-gate */ 38377c478bd9Sstevel@tonic-gate 38387c478bd9Sstevel@tonic-gate void 38397c478bd9Sstevel@tonic-gate fill_fd(fd, where) 38407c478bd9Sstevel@tonic-gate int fd; 38417c478bd9Sstevel@tonic-gate char *where; 38427c478bd9Sstevel@tonic-gate { 38437c478bd9Sstevel@tonic-gate int i; 38447c478bd9Sstevel@tonic-gate struct stat stbuf; 38457c478bd9Sstevel@tonic-gate 38467c478bd9Sstevel@tonic-gate if (fstat(fd, &stbuf) >= 0 || errno != EBADF) 38477c478bd9Sstevel@tonic-gate return; 38487c478bd9Sstevel@tonic-gate 38497c478bd9Sstevel@tonic-gate if (where != NULL) 38507c478bd9Sstevel@tonic-gate syserr("fill_fd: %s: fd %d not open", where, fd); 38517c478bd9Sstevel@tonic-gate else 38527c478bd9Sstevel@tonic-gate MissingFds |= 1 << fd; 38537c478bd9Sstevel@tonic-gate i = open(SM_PATH_DEVNULL, fd == 0 ? O_RDONLY : O_WRONLY, 0666); 38547c478bd9Sstevel@tonic-gate if (i < 0) 38557c478bd9Sstevel@tonic-gate { 38567c478bd9Sstevel@tonic-gate syserr("!fill_fd: %s: cannot open %s", 38577c478bd9Sstevel@tonic-gate where == NULL ? "startup" : where, SM_PATH_DEVNULL); 38587c478bd9Sstevel@tonic-gate } 38597c478bd9Sstevel@tonic-gate if (fd != i) 38607c478bd9Sstevel@tonic-gate { 38617c478bd9Sstevel@tonic-gate (void) dup2(i, fd); 38627c478bd9Sstevel@tonic-gate (void) close(i); 38637c478bd9Sstevel@tonic-gate } 38647c478bd9Sstevel@tonic-gate } 38657c478bd9Sstevel@tonic-gate /* 38667c478bd9Sstevel@tonic-gate ** SM_PRINTOPTIONS -- print options 38677c478bd9Sstevel@tonic-gate ** 38687c478bd9Sstevel@tonic-gate ** Parameters: 38697c478bd9Sstevel@tonic-gate ** options -- array of options. 38707c478bd9Sstevel@tonic-gate ** 38717c478bd9Sstevel@tonic-gate ** Returns: 38727c478bd9Sstevel@tonic-gate ** none. 38737c478bd9Sstevel@tonic-gate */ 38747c478bd9Sstevel@tonic-gate 38757c478bd9Sstevel@tonic-gate static void 38767c478bd9Sstevel@tonic-gate sm_printoptions(options) 38777c478bd9Sstevel@tonic-gate char **options; 38787c478bd9Sstevel@tonic-gate { 38797c478bd9Sstevel@tonic-gate int ll; 38807c478bd9Sstevel@tonic-gate char **av; 38817c478bd9Sstevel@tonic-gate 38827c478bd9Sstevel@tonic-gate av = options; 38837c478bd9Sstevel@tonic-gate ll = 7; 38847c478bd9Sstevel@tonic-gate while (*av != NULL) 38857c478bd9Sstevel@tonic-gate { 38867c478bd9Sstevel@tonic-gate if (ll + strlen(*av) > 63) 38877c478bd9Sstevel@tonic-gate { 38887c478bd9Sstevel@tonic-gate sm_dprintf("\n"); 38897c478bd9Sstevel@tonic-gate ll = 0; 38907c478bd9Sstevel@tonic-gate } 38917c478bd9Sstevel@tonic-gate if (ll == 0) 38927c478bd9Sstevel@tonic-gate sm_dprintf("\t\t"); 38937c478bd9Sstevel@tonic-gate else 38947c478bd9Sstevel@tonic-gate sm_dprintf(" "); 38957c478bd9Sstevel@tonic-gate sm_dprintf("%s", *av); 38967c478bd9Sstevel@tonic-gate ll += strlen(*av++) + 1; 38977c478bd9Sstevel@tonic-gate } 38987c478bd9Sstevel@tonic-gate sm_dprintf("\n"); 38997c478bd9Sstevel@tonic-gate } 39007c478bd9Sstevel@tonic-gate /* 39017c478bd9Sstevel@tonic-gate ** TESTMODELINE -- process a test mode input line 39027c478bd9Sstevel@tonic-gate ** 39037c478bd9Sstevel@tonic-gate ** Parameters: 39047c478bd9Sstevel@tonic-gate ** line -- the input line. 39057c478bd9Sstevel@tonic-gate ** e -- the current environment. 39067c478bd9Sstevel@tonic-gate ** Syntax: 39077c478bd9Sstevel@tonic-gate ** # a comment 39087c478bd9Sstevel@tonic-gate ** .X process X as a configuration line 39097c478bd9Sstevel@tonic-gate ** =X dump a configuration item (such as mailers) 39107c478bd9Sstevel@tonic-gate ** $X dump a macro or class 39117c478bd9Sstevel@tonic-gate ** /X try an activity 39127c478bd9Sstevel@tonic-gate ** X normal process through rule set X 39137c478bd9Sstevel@tonic-gate */ 39147c478bd9Sstevel@tonic-gate 39157c478bd9Sstevel@tonic-gate static void 39167c478bd9Sstevel@tonic-gate testmodeline(line, e) 39177c478bd9Sstevel@tonic-gate char *line; 39187c478bd9Sstevel@tonic-gate ENVELOPE *e; 39197c478bd9Sstevel@tonic-gate { 39207c478bd9Sstevel@tonic-gate register char *p; 39217c478bd9Sstevel@tonic-gate char *q; 39227c478bd9Sstevel@tonic-gate auto char *delimptr; 39237c478bd9Sstevel@tonic-gate int mid; 39247c478bd9Sstevel@tonic-gate int i, rs; 39257c478bd9Sstevel@tonic-gate STAB *map; 39267c478bd9Sstevel@tonic-gate char **s; 39277c478bd9Sstevel@tonic-gate struct rewrite *rw; 39287c478bd9Sstevel@tonic-gate ADDRESS a; 39297c478bd9Sstevel@tonic-gate static int tryflags = RF_COPYNONE; 39307c478bd9Sstevel@tonic-gate char exbuf[MAXLINE]; 39317c478bd9Sstevel@tonic-gate extern unsigned char TokTypeNoC[]; 39327c478bd9Sstevel@tonic-gate 39337c478bd9Sstevel@tonic-gate /* skip leading spaces */ 39347c478bd9Sstevel@tonic-gate while (*line == ' ') 39357c478bd9Sstevel@tonic-gate line++; 39367c478bd9Sstevel@tonic-gate 39377c478bd9Sstevel@tonic-gate switch (line[0]) 39387c478bd9Sstevel@tonic-gate { 39397c478bd9Sstevel@tonic-gate case '#': 39407c478bd9Sstevel@tonic-gate case '\0': 39417c478bd9Sstevel@tonic-gate return; 39427c478bd9Sstevel@tonic-gate 39437c478bd9Sstevel@tonic-gate case '?': 39447c478bd9Sstevel@tonic-gate help("-bt", e); 39457c478bd9Sstevel@tonic-gate return; 39467c478bd9Sstevel@tonic-gate 39477c478bd9Sstevel@tonic-gate case '.': /* config-style settings */ 39487c478bd9Sstevel@tonic-gate switch (line[1]) 39497c478bd9Sstevel@tonic-gate { 39507c478bd9Sstevel@tonic-gate case 'D': 39517c478bd9Sstevel@tonic-gate mid = macid_parse(&line[2], &delimptr); 39527c478bd9Sstevel@tonic-gate if (mid == 0) 39537c478bd9Sstevel@tonic-gate return; 39547c478bd9Sstevel@tonic-gate translate_dollars(delimptr); 39557c478bd9Sstevel@tonic-gate macdefine(&e->e_macro, A_TEMP, mid, delimptr); 39567c478bd9Sstevel@tonic-gate break; 39577c478bd9Sstevel@tonic-gate 39587c478bd9Sstevel@tonic-gate case 'C': 39597c478bd9Sstevel@tonic-gate if (line[2] == '\0') /* not to call syserr() */ 39607c478bd9Sstevel@tonic-gate return; 39617c478bd9Sstevel@tonic-gate 39627c478bd9Sstevel@tonic-gate mid = macid_parse(&line[2], &delimptr); 39637c478bd9Sstevel@tonic-gate if (mid == 0) 39647c478bd9Sstevel@tonic-gate return; 39657c478bd9Sstevel@tonic-gate translate_dollars(delimptr); 39667c478bd9Sstevel@tonic-gate expand(delimptr, exbuf, sizeof exbuf, e); 39677c478bd9Sstevel@tonic-gate p = exbuf; 39687c478bd9Sstevel@tonic-gate while (*p != '\0') 39697c478bd9Sstevel@tonic-gate { 39707c478bd9Sstevel@tonic-gate register char *wd; 39717c478bd9Sstevel@tonic-gate char delim; 39727c478bd9Sstevel@tonic-gate 39737c478bd9Sstevel@tonic-gate while (*p != '\0' && isascii(*p) && isspace(*p)) 39747c478bd9Sstevel@tonic-gate p++; 39757c478bd9Sstevel@tonic-gate wd = p; 39767c478bd9Sstevel@tonic-gate while (*p != '\0' && !(isascii(*p) && isspace(*p))) 39777c478bd9Sstevel@tonic-gate p++; 39787c478bd9Sstevel@tonic-gate delim = *p; 39797c478bd9Sstevel@tonic-gate *p = '\0'; 39807c478bd9Sstevel@tonic-gate if (wd[0] != '\0') 39817c478bd9Sstevel@tonic-gate setclass(mid, wd); 39827c478bd9Sstevel@tonic-gate *p = delim; 39837c478bd9Sstevel@tonic-gate } 39847c478bd9Sstevel@tonic-gate break; 39857c478bd9Sstevel@tonic-gate 39867c478bd9Sstevel@tonic-gate case '\0': 39877c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 39887c478bd9Sstevel@tonic-gate "Usage: .[DC]macro value(s)\n"); 39897c478bd9Sstevel@tonic-gate break; 39907c478bd9Sstevel@tonic-gate 39917c478bd9Sstevel@tonic-gate default: 39927c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 39937c478bd9Sstevel@tonic-gate "Unknown \".\" command %s\n", line); 39947c478bd9Sstevel@tonic-gate break; 39957c478bd9Sstevel@tonic-gate } 39967c478bd9Sstevel@tonic-gate return; 39977c478bd9Sstevel@tonic-gate 39987c478bd9Sstevel@tonic-gate case '=': /* config-style settings */ 39997c478bd9Sstevel@tonic-gate switch (line[1]) 40007c478bd9Sstevel@tonic-gate { 40017c478bd9Sstevel@tonic-gate case 'S': /* dump rule set */ 40027c478bd9Sstevel@tonic-gate rs = strtorwset(&line[2], NULL, ST_FIND); 40037c478bd9Sstevel@tonic-gate if (rs < 0) 40047c478bd9Sstevel@tonic-gate { 40057c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 40067c478bd9Sstevel@tonic-gate "Undefined ruleset %s\n", &line[2]); 40077c478bd9Sstevel@tonic-gate return; 40087c478bd9Sstevel@tonic-gate } 40097c478bd9Sstevel@tonic-gate rw = RewriteRules[rs]; 40107c478bd9Sstevel@tonic-gate if (rw == NULL) 40117c478bd9Sstevel@tonic-gate return; 40127c478bd9Sstevel@tonic-gate do 40137c478bd9Sstevel@tonic-gate { 40147c478bd9Sstevel@tonic-gate (void) sm_io_putc(smioout, SM_TIME_DEFAULT, 40157c478bd9Sstevel@tonic-gate 'R'); 40167c478bd9Sstevel@tonic-gate s = rw->r_lhs; 40177c478bd9Sstevel@tonic-gate while (*s != NULL) 40187c478bd9Sstevel@tonic-gate { 40197c478bd9Sstevel@tonic-gate xputs(smioout, *s++); 40207c478bd9Sstevel@tonic-gate (void) sm_io_putc(smioout, 40217c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, ' '); 40227c478bd9Sstevel@tonic-gate } 40237c478bd9Sstevel@tonic-gate (void) sm_io_putc(smioout, SM_TIME_DEFAULT, 40247c478bd9Sstevel@tonic-gate '\t'); 40257c478bd9Sstevel@tonic-gate (void) sm_io_putc(smioout, SM_TIME_DEFAULT, 40267c478bd9Sstevel@tonic-gate '\t'); 40277c478bd9Sstevel@tonic-gate s = rw->r_rhs; 40287c478bd9Sstevel@tonic-gate while (*s != NULL) 40297c478bd9Sstevel@tonic-gate { 40307c478bd9Sstevel@tonic-gate xputs(smioout, *s++); 40317c478bd9Sstevel@tonic-gate (void) sm_io_putc(smioout, 40327c478bd9Sstevel@tonic-gate SM_TIME_DEFAULT, ' '); 40337c478bd9Sstevel@tonic-gate } 40347c478bd9Sstevel@tonic-gate (void) sm_io_putc(smioout, SM_TIME_DEFAULT, 40357c478bd9Sstevel@tonic-gate '\n'); 40367c478bd9Sstevel@tonic-gate } while ((rw = rw->r_next) != NULL); 40377c478bd9Sstevel@tonic-gate break; 40387c478bd9Sstevel@tonic-gate 40397c478bd9Sstevel@tonic-gate case 'M': 40407c478bd9Sstevel@tonic-gate for (i = 0; i < MAXMAILERS; i++) 40417c478bd9Sstevel@tonic-gate { 40427c478bd9Sstevel@tonic-gate if (Mailer[i] != NULL) 40437c478bd9Sstevel@tonic-gate printmailer(smioout, Mailer[i]); 40447c478bd9Sstevel@tonic-gate } 40457c478bd9Sstevel@tonic-gate break; 40467c478bd9Sstevel@tonic-gate 40477c478bd9Sstevel@tonic-gate case '\0': 40487c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 40497c478bd9Sstevel@tonic-gate "Usage: =Sruleset or =M\n"); 40507c478bd9Sstevel@tonic-gate break; 40517c478bd9Sstevel@tonic-gate 40527c478bd9Sstevel@tonic-gate default: 40537c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 40547c478bd9Sstevel@tonic-gate "Unknown \"=\" command %s\n", line); 40557c478bd9Sstevel@tonic-gate break; 40567c478bd9Sstevel@tonic-gate } 40577c478bd9Sstevel@tonic-gate return; 40587c478bd9Sstevel@tonic-gate 40597c478bd9Sstevel@tonic-gate case '-': /* set command-line-like opts */ 40607c478bd9Sstevel@tonic-gate switch (line[1]) 40617c478bd9Sstevel@tonic-gate { 40627c478bd9Sstevel@tonic-gate case 'd': 40637c478bd9Sstevel@tonic-gate tTflag(&line[2]); 40647c478bd9Sstevel@tonic-gate break; 40657c478bd9Sstevel@tonic-gate 40667c478bd9Sstevel@tonic-gate case '\0': 40677c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 40687c478bd9Sstevel@tonic-gate "Usage: -d{debug arguments}\n"); 40697c478bd9Sstevel@tonic-gate break; 40707c478bd9Sstevel@tonic-gate 40717c478bd9Sstevel@tonic-gate default: 40727c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 40737c478bd9Sstevel@tonic-gate "Unknown \"-\" command %s\n", line); 40747c478bd9Sstevel@tonic-gate break; 40757c478bd9Sstevel@tonic-gate } 40767c478bd9Sstevel@tonic-gate return; 40777c478bd9Sstevel@tonic-gate 40787c478bd9Sstevel@tonic-gate case '$': 40797c478bd9Sstevel@tonic-gate if (line[1] == '=') 40807c478bd9Sstevel@tonic-gate { 40817c478bd9Sstevel@tonic-gate mid = macid(&line[2]); 40827c478bd9Sstevel@tonic-gate if (mid != 0) 40837c478bd9Sstevel@tonic-gate stabapply(dump_class, mid); 40847c478bd9Sstevel@tonic-gate return; 40857c478bd9Sstevel@tonic-gate } 40867c478bd9Sstevel@tonic-gate mid = macid(&line[1]); 40877c478bd9Sstevel@tonic-gate if (mid == 0) 40887c478bd9Sstevel@tonic-gate return; 40897c478bd9Sstevel@tonic-gate p = macvalue(mid, e); 40907c478bd9Sstevel@tonic-gate if (p == NULL) 40917c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 40927c478bd9Sstevel@tonic-gate "Undefined\n"); 40937c478bd9Sstevel@tonic-gate else 40947c478bd9Sstevel@tonic-gate { 40957c478bd9Sstevel@tonic-gate xputs(smioout, p); 40967c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 40977c478bd9Sstevel@tonic-gate "\n"); 40987c478bd9Sstevel@tonic-gate } 40997c478bd9Sstevel@tonic-gate return; 41007c478bd9Sstevel@tonic-gate 41017c478bd9Sstevel@tonic-gate case '/': /* miscellaneous commands */ 41027c478bd9Sstevel@tonic-gate p = &line[strlen(line)]; 41037c478bd9Sstevel@tonic-gate while (--p >= line && isascii(*p) && isspace(*p)) 41047c478bd9Sstevel@tonic-gate *p = '\0'; 41057c478bd9Sstevel@tonic-gate p = strpbrk(line, " \t"); 41067c478bd9Sstevel@tonic-gate if (p != NULL) 41077c478bd9Sstevel@tonic-gate { 41087c478bd9Sstevel@tonic-gate while (isascii(*p) && isspace(*p)) 41097c478bd9Sstevel@tonic-gate *p++ = '\0'; 41107c478bd9Sstevel@tonic-gate } 41117c478bd9Sstevel@tonic-gate else 41127c478bd9Sstevel@tonic-gate p = ""; 41137c478bd9Sstevel@tonic-gate if (line[1] == '\0') 41147c478bd9Sstevel@tonic-gate { 41157c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 41167c478bd9Sstevel@tonic-gate "Usage: /[canon|map|mx|parse|try|tryflags]\n"); 41177c478bd9Sstevel@tonic-gate return; 41187c478bd9Sstevel@tonic-gate } 41197c478bd9Sstevel@tonic-gate if (sm_strcasecmp(&line[1], "quit") == 0) 41207c478bd9Sstevel@tonic-gate { 41217c478bd9Sstevel@tonic-gate CurEnv->e_id = NULL; 41227c478bd9Sstevel@tonic-gate finis(true, true, ExitStat); 41237c478bd9Sstevel@tonic-gate /* NOTREACHED */ 41247c478bd9Sstevel@tonic-gate } 41257c478bd9Sstevel@tonic-gate if (sm_strcasecmp(&line[1], "mx") == 0) 41267c478bd9Sstevel@tonic-gate { 41277c478bd9Sstevel@tonic-gate #if NAMED_BIND 41287c478bd9Sstevel@tonic-gate /* look up MX records */ 41297c478bd9Sstevel@tonic-gate int nmx; 41307c478bd9Sstevel@tonic-gate auto int rcode; 41317c478bd9Sstevel@tonic-gate char *mxhosts[MAXMXHOSTS + 1]; 41327c478bd9Sstevel@tonic-gate 41337c478bd9Sstevel@tonic-gate if (*p == '\0') 41347c478bd9Sstevel@tonic-gate { 41357c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 41367c478bd9Sstevel@tonic-gate "Usage: /mx address\n"); 41377c478bd9Sstevel@tonic-gate return; 41387c478bd9Sstevel@tonic-gate } 41397c478bd9Sstevel@tonic-gate nmx = getmxrr(p, mxhosts, NULL, false, &rcode, true, 41407c478bd9Sstevel@tonic-gate NULL); 41417c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 41427c478bd9Sstevel@tonic-gate "getmxrr(%s) returns %d value(s):\n", 41437c478bd9Sstevel@tonic-gate p, nmx); 41447c478bd9Sstevel@tonic-gate for (i = 0; i < nmx; i++) 41457c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 41467c478bd9Sstevel@tonic-gate "\t%s\n", mxhosts[i]); 41477c478bd9Sstevel@tonic-gate #else /* NAMED_BIND */ 41487c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 41497c478bd9Sstevel@tonic-gate "No MX code compiled in\n"); 41507c478bd9Sstevel@tonic-gate #endif /* NAMED_BIND */ 41517c478bd9Sstevel@tonic-gate } 41527c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(&line[1], "canon") == 0) 41537c478bd9Sstevel@tonic-gate { 41547c478bd9Sstevel@tonic-gate char host[MAXHOSTNAMELEN]; 41557c478bd9Sstevel@tonic-gate 41567c478bd9Sstevel@tonic-gate if (*p == '\0') 41577c478bd9Sstevel@tonic-gate { 41587c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 41597c478bd9Sstevel@tonic-gate "Usage: /canon address\n"); 41607c478bd9Sstevel@tonic-gate return; 41617c478bd9Sstevel@tonic-gate } 41627c478bd9Sstevel@tonic-gate else if (sm_strlcpy(host, p, sizeof host) >= sizeof host) 41637c478bd9Sstevel@tonic-gate { 41647c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 41657c478bd9Sstevel@tonic-gate "Name too long\n"); 41667c478bd9Sstevel@tonic-gate return; 41677c478bd9Sstevel@tonic-gate } 41687c478bd9Sstevel@tonic-gate (void) getcanonname(host, sizeof host, !HasWildcardMX, 41697c478bd9Sstevel@tonic-gate NULL); 41707c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 41717c478bd9Sstevel@tonic-gate "getcanonname(%s) returns %s\n", 41727c478bd9Sstevel@tonic-gate p, host); 41737c478bd9Sstevel@tonic-gate } 41747c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(&line[1], "map") == 0) 41757c478bd9Sstevel@tonic-gate { 41767c478bd9Sstevel@tonic-gate auto int rcode = EX_OK; 41777c478bd9Sstevel@tonic-gate char *av[2]; 41787c478bd9Sstevel@tonic-gate 41797c478bd9Sstevel@tonic-gate if (*p == '\0') 41807c478bd9Sstevel@tonic-gate { 41817c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 41827c478bd9Sstevel@tonic-gate "Usage: /map mapname key\n"); 41837c478bd9Sstevel@tonic-gate return; 41847c478bd9Sstevel@tonic-gate } 41857c478bd9Sstevel@tonic-gate for (q = p; *q != '\0' && !(isascii(*q) && isspace(*q)); q++) 41867c478bd9Sstevel@tonic-gate continue; 41877c478bd9Sstevel@tonic-gate if (*q == '\0') 41887c478bd9Sstevel@tonic-gate { 41897c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 41907c478bd9Sstevel@tonic-gate "No key specified\n"); 41917c478bd9Sstevel@tonic-gate return; 41927c478bd9Sstevel@tonic-gate } 41937c478bd9Sstevel@tonic-gate *q++ = '\0'; 41947c478bd9Sstevel@tonic-gate map = stab(p, ST_MAP, ST_FIND); 41957c478bd9Sstevel@tonic-gate if (map == NULL) 41967c478bd9Sstevel@tonic-gate { 41977c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 41987c478bd9Sstevel@tonic-gate "Map named \"%s\" not found\n", p); 41997c478bd9Sstevel@tonic-gate return; 42007c478bd9Sstevel@tonic-gate } 42017c478bd9Sstevel@tonic-gate if (!bitset(MF_OPEN, map->s_map.map_mflags) && 42027c478bd9Sstevel@tonic-gate !openmap(&(map->s_map))) 42037c478bd9Sstevel@tonic-gate { 42047c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 42057c478bd9Sstevel@tonic-gate "Map named \"%s\" not open\n", p); 42067c478bd9Sstevel@tonic-gate return; 42077c478bd9Sstevel@tonic-gate } 42087c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 42097c478bd9Sstevel@tonic-gate "map_lookup: %s (%s) ", p, q); 42107c478bd9Sstevel@tonic-gate av[0] = q; 42117c478bd9Sstevel@tonic-gate av[1] = NULL; 42127c478bd9Sstevel@tonic-gate p = (*map->s_map.map_class->map_lookup) 42137c478bd9Sstevel@tonic-gate (&map->s_map, q, av, &rcode); 42147c478bd9Sstevel@tonic-gate if (p == NULL) 42157c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 42167c478bd9Sstevel@tonic-gate "no match (%d)\n", 42177c478bd9Sstevel@tonic-gate rcode); 42187c478bd9Sstevel@tonic-gate else 42197c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 42207c478bd9Sstevel@tonic-gate "returns %s (%d)\n", p, 42217c478bd9Sstevel@tonic-gate rcode); 42227c478bd9Sstevel@tonic-gate } 42237c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(&line[1], "try") == 0) 42247c478bd9Sstevel@tonic-gate { 42257c478bd9Sstevel@tonic-gate MAILER *m; 42267c478bd9Sstevel@tonic-gate STAB *st; 42277c478bd9Sstevel@tonic-gate auto int rcode = EX_OK; 42287c478bd9Sstevel@tonic-gate 42297c478bd9Sstevel@tonic-gate q = strpbrk(p, " \t"); 42307c478bd9Sstevel@tonic-gate if (q != NULL) 42317c478bd9Sstevel@tonic-gate { 42327c478bd9Sstevel@tonic-gate while (isascii(*q) && isspace(*q)) 42337c478bd9Sstevel@tonic-gate *q++ = '\0'; 42347c478bd9Sstevel@tonic-gate } 42357c478bd9Sstevel@tonic-gate if (q == NULL || *q == '\0') 42367c478bd9Sstevel@tonic-gate { 42377c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 42387c478bd9Sstevel@tonic-gate "Usage: /try mailer address\n"); 42397c478bd9Sstevel@tonic-gate return; 42407c478bd9Sstevel@tonic-gate } 42417c478bd9Sstevel@tonic-gate st = stab(p, ST_MAILER, ST_FIND); 42427c478bd9Sstevel@tonic-gate if (st == NULL) 42437c478bd9Sstevel@tonic-gate { 42447c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 42457c478bd9Sstevel@tonic-gate "Unknown mailer %s\n", p); 42467c478bd9Sstevel@tonic-gate return; 42477c478bd9Sstevel@tonic-gate } 42487c478bd9Sstevel@tonic-gate m = st->s_mailer; 42497c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 42507c478bd9Sstevel@tonic-gate "Trying %s %s address %s for mailer %s\n", 42517c478bd9Sstevel@tonic-gate bitset(RF_HEADERADDR, tryflags) ? "header" 42527c478bd9Sstevel@tonic-gate : "envelope", 42537c478bd9Sstevel@tonic-gate bitset(RF_SENDERADDR, tryflags) ? "sender" 42547c478bd9Sstevel@tonic-gate : "recipient", q, p); 42557c478bd9Sstevel@tonic-gate p = remotename(q, m, tryflags, &rcode, CurEnv); 42567c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 42577c478bd9Sstevel@tonic-gate "Rcode = %d, addr = %s\n", 42587c478bd9Sstevel@tonic-gate rcode, p == NULL ? "<NULL>" : p); 42597c478bd9Sstevel@tonic-gate e->e_to = NULL; 42607c478bd9Sstevel@tonic-gate } 42617c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(&line[1], "tryflags") == 0) 42627c478bd9Sstevel@tonic-gate { 42637c478bd9Sstevel@tonic-gate if (*p == '\0') 42647c478bd9Sstevel@tonic-gate { 42657c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 42667c478bd9Sstevel@tonic-gate "Usage: /tryflags [Hh|Ee][Ss|Rr]\n"); 42677c478bd9Sstevel@tonic-gate return; 42687c478bd9Sstevel@tonic-gate } 42697c478bd9Sstevel@tonic-gate for (; *p != '\0'; p++) 42707c478bd9Sstevel@tonic-gate { 42717c478bd9Sstevel@tonic-gate switch (*p) 42727c478bd9Sstevel@tonic-gate { 42737c478bd9Sstevel@tonic-gate case 'H': 42747c478bd9Sstevel@tonic-gate case 'h': 42757c478bd9Sstevel@tonic-gate tryflags |= RF_HEADERADDR; 42767c478bd9Sstevel@tonic-gate break; 42777c478bd9Sstevel@tonic-gate 42787c478bd9Sstevel@tonic-gate case 'E': 42797c478bd9Sstevel@tonic-gate case 'e': 42807c478bd9Sstevel@tonic-gate tryflags &= ~RF_HEADERADDR; 42817c478bd9Sstevel@tonic-gate break; 42827c478bd9Sstevel@tonic-gate 42837c478bd9Sstevel@tonic-gate case 'S': 42847c478bd9Sstevel@tonic-gate case 's': 42857c478bd9Sstevel@tonic-gate tryflags |= RF_SENDERADDR; 42867c478bd9Sstevel@tonic-gate break; 42877c478bd9Sstevel@tonic-gate 42887c478bd9Sstevel@tonic-gate case 'R': 42897c478bd9Sstevel@tonic-gate case 'r': 42907c478bd9Sstevel@tonic-gate tryflags &= ~RF_SENDERADDR; 42917c478bd9Sstevel@tonic-gate break; 42927c478bd9Sstevel@tonic-gate } 42937c478bd9Sstevel@tonic-gate } 42947c478bd9Sstevel@tonic-gate exbuf[0] = bitset(RF_HEADERADDR, tryflags) ? 'h' : 'e'; 42957c478bd9Sstevel@tonic-gate exbuf[1] = ' '; 42967c478bd9Sstevel@tonic-gate exbuf[2] = bitset(RF_SENDERADDR, tryflags) ? 's' : 'r'; 42977c478bd9Sstevel@tonic-gate exbuf[3] = '\0'; 42987c478bd9Sstevel@tonic-gate macdefine(&e->e_macro, A_TEMP, 42997c478bd9Sstevel@tonic-gate macid("{addr_type}"), exbuf); 43007c478bd9Sstevel@tonic-gate } 43017c478bd9Sstevel@tonic-gate else if (sm_strcasecmp(&line[1], "parse") == 0) 43027c478bd9Sstevel@tonic-gate { 43037c478bd9Sstevel@tonic-gate if (*p == '\0') 43047c478bd9Sstevel@tonic-gate { 43057c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 43067c478bd9Sstevel@tonic-gate "Usage: /parse address\n"); 43077c478bd9Sstevel@tonic-gate return; 43087c478bd9Sstevel@tonic-gate } 43097c478bd9Sstevel@tonic-gate q = crackaddr(p, e); 43107c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 43117c478bd9Sstevel@tonic-gate "Cracked address = "); 43127c478bd9Sstevel@tonic-gate xputs(smioout, q); 43137c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 43147c478bd9Sstevel@tonic-gate "\nParsing %s %s address\n", 43157c478bd9Sstevel@tonic-gate bitset(RF_HEADERADDR, tryflags) ? 43167c478bd9Sstevel@tonic-gate "header" : "envelope", 43177c478bd9Sstevel@tonic-gate bitset(RF_SENDERADDR, tryflags) ? 43187c478bd9Sstevel@tonic-gate "sender" : "recipient"); 43197c478bd9Sstevel@tonic-gate if (parseaddr(p, &a, tryflags, '\0', NULL, e, true) 43207c478bd9Sstevel@tonic-gate == NULL) 43217c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 43227c478bd9Sstevel@tonic-gate "Cannot parse\n"); 43237c478bd9Sstevel@tonic-gate else if (a.q_host != NULL && a.q_host[0] != '\0') 43247c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 43257c478bd9Sstevel@tonic-gate "mailer %s, host %s, user %s\n", 43267c478bd9Sstevel@tonic-gate a.q_mailer->m_name, 43277c478bd9Sstevel@tonic-gate a.q_host, 43287c478bd9Sstevel@tonic-gate a.q_user); 43297c478bd9Sstevel@tonic-gate else 43307c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 43317c478bd9Sstevel@tonic-gate "mailer %s, user %s\n", 43327c478bd9Sstevel@tonic-gate a.q_mailer->m_name, 43337c478bd9Sstevel@tonic-gate a.q_user); 43347c478bd9Sstevel@tonic-gate e->e_to = NULL; 43357c478bd9Sstevel@tonic-gate } 43367c478bd9Sstevel@tonic-gate else 43377c478bd9Sstevel@tonic-gate { 43387c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 43397c478bd9Sstevel@tonic-gate "Unknown \"/\" command %s\n", 43407c478bd9Sstevel@tonic-gate line); 43417c478bd9Sstevel@tonic-gate } 43427c478bd9Sstevel@tonic-gate return; 43437c478bd9Sstevel@tonic-gate } 43447c478bd9Sstevel@tonic-gate 43457c478bd9Sstevel@tonic-gate for (p = line; isascii(*p) && isspace(*p); p++) 43467c478bd9Sstevel@tonic-gate continue; 43477c478bd9Sstevel@tonic-gate q = p; 43487c478bd9Sstevel@tonic-gate while (*p != '\0' && !(isascii(*p) && isspace(*p))) 43497c478bd9Sstevel@tonic-gate p++; 43507c478bd9Sstevel@tonic-gate if (*p == '\0') 43517c478bd9Sstevel@tonic-gate { 43527c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 43537c478bd9Sstevel@tonic-gate "No address!\n"); 43547c478bd9Sstevel@tonic-gate return; 43557c478bd9Sstevel@tonic-gate } 43567c478bd9Sstevel@tonic-gate *p = '\0'; 43577c478bd9Sstevel@tonic-gate if (invalidaddr(p + 1, NULL, true)) 43587c478bd9Sstevel@tonic-gate return; 43597c478bd9Sstevel@tonic-gate do 43607c478bd9Sstevel@tonic-gate { 43617c478bd9Sstevel@tonic-gate register char **pvp; 43627c478bd9Sstevel@tonic-gate char pvpbuf[PSBUFSIZE]; 43637c478bd9Sstevel@tonic-gate 43647c478bd9Sstevel@tonic-gate pvp = prescan(++p, ',', pvpbuf, sizeof pvpbuf, &delimptr, 43657c478bd9Sstevel@tonic-gate ConfigLevel >= 9 ? TokTypeNoC : NULL, false); 43667c478bd9Sstevel@tonic-gate if (pvp == NULL) 43677c478bd9Sstevel@tonic-gate continue; 43687c478bd9Sstevel@tonic-gate p = q; 43697c478bd9Sstevel@tonic-gate while (*p != '\0') 43707c478bd9Sstevel@tonic-gate { 43717c478bd9Sstevel@tonic-gate int status; 43727c478bd9Sstevel@tonic-gate 43737c478bd9Sstevel@tonic-gate rs = strtorwset(p, NULL, ST_FIND); 43747c478bd9Sstevel@tonic-gate if (rs < 0) 43757c478bd9Sstevel@tonic-gate { 43767c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 43777c478bd9Sstevel@tonic-gate "Undefined ruleset %s\n", 43787c478bd9Sstevel@tonic-gate p); 43797c478bd9Sstevel@tonic-gate break; 43807c478bd9Sstevel@tonic-gate } 43817c478bd9Sstevel@tonic-gate status = REWRITE(pvp, rs, e); 43827c478bd9Sstevel@tonic-gate if (status != EX_OK) 43837c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 43847c478bd9Sstevel@tonic-gate "== Ruleset %s (%d) status %d\n", 43857c478bd9Sstevel@tonic-gate p, rs, status); 43867c478bd9Sstevel@tonic-gate while (*p != '\0' && *p++ != ',') 43877c478bd9Sstevel@tonic-gate continue; 43887c478bd9Sstevel@tonic-gate } 43897c478bd9Sstevel@tonic-gate } while (*(p = delimptr) != '\0'); 43907c478bd9Sstevel@tonic-gate } 43917c478bd9Sstevel@tonic-gate 43927c478bd9Sstevel@tonic-gate static void 43937c478bd9Sstevel@tonic-gate dump_class(s, id) 43947c478bd9Sstevel@tonic-gate register STAB *s; 43957c478bd9Sstevel@tonic-gate int id; 43967c478bd9Sstevel@tonic-gate { 43977c478bd9Sstevel@tonic-gate if (s->s_symtype != ST_CLASS) 43987c478bd9Sstevel@tonic-gate return; 43997c478bd9Sstevel@tonic-gate if (bitnset(bitidx(id), s->s_class)) 44007c478bd9Sstevel@tonic-gate (void) sm_io_fprintf(smioout, SM_TIME_DEFAULT, 44017c478bd9Sstevel@tonic-gate "%s\n", s->s_name); 44027c478bd9Sstevel@tonic-gate } 44037c478bd9Sstevel@tonic-gate 44047c478bd9Sstevel@tonic-gate /* 44057c478bd9Sstevel@tonic-gate ** An exception type used to create QuickAbort exceptions. 44067c478bd9Sstevel@tonic-gate ** This is my first cut at converting QuickAbort from longjmp to exceptions. 44077c478bd9Sstevel@tonic-gate ** These exceptions have a single integer argument, which is the argument 44087c478bd9Sstevel@tonic-gate ** to longjmp in the original code (either 1 or 2). I don't know the 44097c478bd9Sstevel@tonic-gate ** significance of 1 vs 2: the calls to setjmp don't care. 44107c478bd9Sstevel@tonic-gate */ 44117c478bd9Sstevel@tonic-gate 44127c478bd9Sstevel@tonic-gate const SM_EXC_TYPE_T EtypeQuickAbort = 44137c478bd9Sstevel@tonic-gate { 44147c478bd9Sstevel@tonic-gate SmExcTypeMagic, 44157c478bd9Sstevel@tonic-gate "E:mta.quickabort", 44167c478bd9Sstevel@tonic-gate "i", 44177c478bd9Sstevel@tonic-gate sm_etype_printf, 44187c478bd9Sstevel@tonic-gate "quick abort %0", 44197c478bd9Sstevel@tonic-gate }; 4420