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