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