138494Sobrien/*
2174298Sobrien * Copyright (c) 1997-2006 Erez Zadok
338494Sobrien * Copyright (c) 1989 Jan-Simon Pendry
438494Sobrien * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
538494Sobrien * Copyright (c) 1989 The Regents of the University of California.
638494Sobrien * All rights reserved.
738494Sobrien *
838494Sobrien * This code is derived from software contributed to Berkeley by
938494Sobrien * Jan-Simon Pendry at Imperial College, London.
1038494Sobrien *
1138494Sobrien * Redistribution and use in source and binary forms, with or without
1238494Sobrien * modification, are permitted provided that the following conditions
1338494Sobrien * are met:
1438494Sobrien * 1. Redistributions of source code must retain the above copyright
1538494Sobrien *    notice, this list of conditions and the following disclaimer.
1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1738494Sobrien *    notice, this list of conditions and the following disclaimer in the
1838494Sobrien *    documentation and/or other materials provided with the distribution.
1938494Sobrien * 3. All advertising materials mentioning features or use of this software
2042633Sobrien *    must display the following acknowledgment:
2138494Sobrien *      This product includes software developed by the University of
2238494Sobrien *      California, Berkeley and its contributors.
2338494Sobrien * 4. Neither the name of the University nor the names of its contributors
2438494Sobrien *    may be used to endorse or promote products derived from this software
2538494Sobrien *    without specific prior written permission.
2638494Sobrien *
2738494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2838494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2938494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3038494Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3138494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3238494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3338494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3438494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3538494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3638494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3738494Sobrien * SUCH DAMAGE.
3838494Sobrien *
3938494Sobrien *
40131706Smbr * $Id: amd.c,v 1.8.2.6 2004/01/06 03:15:16 ezk Exp $
41174298Sobrien * File: am-utils/amd/amd.c
4238494Sobrien *
4338494Sobrien */
4438494Sobrien
45174298Sobrien#include <sys/cdefs.h>
46174298Sobrien__FBSDID("$FreeBSD$");
47174298Sobrien
4838494Sobrien/*
4938494Sobrien * Automounter
5038494Sobrien */
5138494Sobrien
5238494Sobrien#ifdef HAVE_CONFIG_H
5338494Sobrien# include <config.h>
5438494Sobrien#endif /* HAVE_CONFIG_H */
5538494Sobrien#include <am_defs.h>
5638494Sobrien#include <amd.h>
5738494Sobrien
5838494Sobrienstruct amu_global_options gopt;	/* where global options are stored */
5938494Sobrien
60174298Sobrienchar pid_fsname[SIZEOF_PID_FSNAME]; /* "kiska.southseas.nz:(pid%d)" */
6138494Sobrienchar *hostdomain = "unknown.domain";
62174298Sobrien#define SIZEOF_HOSTD (2 * MAXHOSTNAMELEN + 1)	/* Host+domain */
63174298Sobrienchar hostd[SIZEOF_HOSTD];	/* Host+domain */
6438494Sobrienchar *endian = ARCH_ENDIAN;	/* Big or Little endian */
6538494Sobrienchar *cpu = HOST_CPU;		/* CPU type */
6638494Sobrienchar *PrimNetName;		/* name of primary network */
6738494Sobrienchar *PrimNetNum;		/* number of primary network */
6838494Sobrien
6938494Sobrienint immediate_abort;		/* Should close-down unmounts be retried */
7042633Sobrienint orig_umask = 022;
7138494Sobrienint select_intr_valid;
7238494Sobrien
7338494Sobrienjmp_buf select_intr;
7438494Sobrienstruct amd_stats amd_stats;	/* Server statistics */
7538494Sobrienstruct in_addr myipaddr;	/* (An) IP address of this host */
7638494Sobrientime_t do_mapc_reload = 0;	/* mapc_reload() call required? */
7738494Sobrien
78174298Sobrien#ifdef HAVE_FS_AUTOFS
79174298Sobrienint amd_use_autofs = 0;
80174298Sobrien#endif /* HAVE_FS_AUTOFS */
81174298Sobrien
8238494Sobrien#ifdef HAVE_SIGACTION
8338494Sobriensigset_t masked_sigs;
8438494Sobrien#endif /* HAVE_SIGACTION */
8538494Sobrien
8638494Sobrien
8738494Sobrien/*
8838494Sobrien * Signal handler:
8938494Sobrien * SIGINT - tells amd to do a full shutdown, including unmounting all
9038494Sobrien *       filesystem.
9138494Sobrien * SIGTERM - tells amd to shutdown now.  Just unmounts the automount nodes.
9238494Sobrien */
9338494Sobrienstatic RETSIGTYPE
9438494Sobriensigterm(int sig)
9538494Sobrien{
9638494Sobrien#ifdef REINSTALL_SIGNAL_HANDLER
9738494Sobrien  signal(sig, sigterm);
9838494Sobrien#endif /* REINSTALL_SIGNAL_HANDLER */
9938494Sobrien
10038494Sobrien  switch (sig) {
10138494Sobrien  case SIGINT:
10238494Sobrien    immediate_abort = 15;
10338494Sobrien    break;
10438494Sobrien
10538494Sobrien  case SIGTERM:
10638494Sobrien    immediate_abort = -1;
10738494Sobrien    /* fall through... */
10838494Sobrien
10938494Sobrien  default:
11038494Sobrien    plog(XLOG_WARNING, "WARNING: automounter going down on signal %d", sig);
11138494Sobrien    break;
11238494Sobrien  }
11338494Sobrien  if (select_intr_valid)
11438494Sobrien    longjmp(select_intr, sig);
11538494Sobrien}
11638494Sobrien
11738494Sobrien
11838494Sobrien/*
11938494Sobrien * Hook for cache reload.
12038494Sobrien * When a SIGHUP arrives it schedules a call to mapc_reload
12138494Sobrien */
12238494Sobrienstatic RETSIGTYPE
12338494Sobriensighup(int sig)
12438494Sobrien{
12538494Sobrien#ifdef REINSTALL_SIGNAL_HANDLER
12638494Sobrien  signal(sig, sighup);
12738494Sobrien#endif /* REINSTALL_SIGNAL_HANDLER */
12838494Sobrien
12938494Sobrien  if (sig != SIGHUP)
13038494Sobrien    dlog("spurious call to sighup");
13138494Sobrien  /*
13238494Sobrien   * Force a reload by zero'ing the timer
13338494Sobrien   */
13438494Sobrien  if (amd_state == Run)
13538494Sobrien    do_mapc_reload = 0;
13638494Sobrien}
13738494Sobrien
13838494Sobrien
13938494Sobrienstatic RETSIGTYPE
14038494Sobrienparent_exit(int sig)
14138494Sobrien{
142174298Sobrien  /*
143174298Sobrien   * This signal handler is called during Amd initialization.  The parent
144174298Sobrien   * forks a child to do all the hard automounting work, and waits for a
145174298Sobrien   * SIGQUIT signal from the child.  When the parent gets the signal it's
146174298Sobrien   * supposed to call this handler and exit(3), thus completing the
147174298Sobrien   * daemonizing process.  Alas, on some systems, especially Linux 2.4/2.6
148174298Sobrien   * with Glibc, exit(3) doesn't always terminate the parent process.
149174298Sobrien   * Worse, the parent process now refuses to accept any more SIGQUIT
150174298Sobrien   * signals -- they are blocked.  What's really annoying is that this
151174298Sobrien   * doesn't happen all the time, suggesting a race condition somewhere.
152174298Sobrien   * (This happens even if I change the logic to use another signal.)  I
153174298Sobrien   * traced this to something which exit(3) does in addition to exiting the
154174298Sobrien   * process, probably some atexit() stuff or other side-effects related to
155174298Sobrien   * signal handling.  Either way, since at this stage the parent process
156174298Sobrien   * just needs to terminate, I'm simply calling _exit(2).  Note also that
157174298Sobrien   * the OpenGroup doesn't list exit(3) as a recommended "Base Interface"
158174298Sobrien   * but they do list _exit(2) as one.  This fix seems to work reliably all
159174298Sobrien   * the time. -Erez (2/27/2005)
160174298Sobrien   */
161174298Sobrien  _exit(0);
16238494Sobrien}
16338494Sobrien
16438494Sobrien
16538494Sobrienstatic int
16638494Sobriendaemon_mode(void)
16738494Sobrien{
16838494Sobrien  int bgpid;
16938494Sobrien
17038494Sobrien#ifdef HAVE_SIGACTION
17138494Sobrien  struct sigaction sa, osa;
17238494Sobrien
173174298Sobrien  memset(&sa, 0, sizeof(sa));
17438494Sobrien  sa.sa_handler = parent_exit;
17538494Sobrien  sa.sa_flags = 0;
17638494Sobrien  sigemptyset(&(sa.sa_mask));
17738494Sobrien  sigaddset(&(sa.sa_mask), SIGQUIT);
17838494Sobrien  sigaction(SIGQUIT, &sa, &osa);
17938494Sobrien#else /* not HAVE_SIGACTION */
18038494Sobrien  signal(SIGQUIT, parent_exit);
18138494Sobrien#endif /* not HAVE_SIGACTION */
18238494Sobrien
18338494Sobrien  bgpid = background();
18438494Sobrien
18538494Sobrien  if (bgpid != 0) {
18638494Sobrien    /*
18738494Sobrien     * Now wait for the automount points to
18838494Sobrien     * complete.
18938494Sobrien     */
19038494Sobrien    for (;;)
19138494Sobrien      pause();
19242633Sobrien    /* should never reach here */
19338494Sobrien  }
19438494Sobrien#ifdef HAVE_SIGACTION
19538494Sobrien  sigaction(SIGQUIT, &osa, NULL);
19638494Sobrien#else /* not HAVE_SIGACTION */
19738494Sobrien  signal(SIGQUIT, SIG_DFL);
19838494Sobrien#endif /* not HAVE_SIGACTION */
19938494Sobrien
20038494Sobrien  /*
20138494Sobrien   * Record our pid to make it easier to kill the correct amd.
20238494Sobrien   */
20338494Sobrien  if (gopt.flags & CFM_PRINT_PID) {
20438494Sobrien    if (STREQ(gopt.pid_file, "/dev/stdout")) {
20542633Sobrien      printf("%ld\n", (long) am_mypid);
20682797Sobrien      /* flush stdout, just in case */
20738494Sobrien      fflush(stdout);
20838494Sobrien    } else {
20938494Sobrien      FILE *f;
21038494Sobrien      mode_t prev_umask = umask(0022); /* set secure temporary umask */
21138494Sobrien
21238494Sobrien      f = fopen(gopt.pid_file, "w");
21338494Sobrien      if (f) {
21442633Sobrien	fprintf(f, "%ld\n", (long) am_mypid);
21538494Sobrien	(void) fclose(f);
21638494Sobrien      } else {
21738494Sobrien	fprintf(stderr, "cannot open %s (errno=%d)\n", gopt.pid_file, errno);
21838494Sobrien      }
21938494Sobrien      umask(prev_umask);	/* restore umask */
22038494Sobrien    }
22138494Sobrien  }
22238494Sobrien
22338494Sobrien  /*
22438494Sobrien   * Pretend we are in the foreground again
22538494Sobrien   */
22638494Sobrien  foreground = 1;
22738494Sobrien
22838494Sobrien  /*
22938494Sobrien   * Dissociate from the controlling terminal
23038494Sobrien   */
23138494Sobrien  amu_release_controlling_tty();
23238494Sobrien
23338494Sobrien  return getppid();
23438494Sobrien}
23538494Sobrien
23638494Sobrien
23738494Sobrien/*
23838494Sobrien * Initialize global options structure.
23938494Sobrien */
24038494Sobrienstatic void
24138494Sobrieninit_global_options(void)
24238494Sobrien{
24338494Sobrien#if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
24438494Sobrien  static struct utsname un;
24538494Sobrien#endif /* defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) */
246174298Sobrien  int i;
24738494Sobrien
24838494Sobrien  memset(&gopt, 0, sizeof(struct amu_global_options));
24938494Sobrien
25038494Sobrien  /* name of current architecture */
25138494Sobrien  gopt.arch = HOST_ARCH;
25238494Sobrien
25338494Sobrien  /* automounter temp dir */
25465308Sobrien  gopt.auto_dir = "/.amd_mnt";
25538494Sobrien
256174298Sobrien  /* toplevel attribute cache timeout */
257174298Sobrien  gopt.auto_attrcache = 0;
258174298Sobrien
25938494Sobrien  /* cluster name */
26038494Sobrien  gopt.cluster = NULL;
26138494Sobrien
262174298Sobrien  /* executable map timeout */
263174298Sobrien  gopt.exec_map_timeout = AMFS_EXEC_MAP_TIMEOUT;
264174298Sobrien
26538494Sobrien  /*
26638494Sobrien   * kernel architecture: this you must get from uname() if possible.
26738494Sobrien   */
26838494Sobrien#if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
26938494Sobrien  if (uname(&un) >= 0)
27038494Sobrien    gopt.karch = un.machine;
27138494Sobrien  else
27238494Sobrien#endif /* defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) */
27338494Sobrien    gopt.karch = HOST_ARCH;
27438494Sobrien
27538494Sobrien  /* amd log file */
27638494Sobrien  gopt.logfile = NULL;
27738494Sobrien
27838494Sobrien  /* operating system name */
27938494Sobrien  gopt.op_sys = HOST_OS_NAME;
28038494Sobrien
28138494Sobrien  /* OS version */
28238494Sobrien  gopt.op_sys_ver = HOST_OS_VERSION;
28338494Sobrien
28452897Sobrien  /* full OS name and version */
28552897Sobrien  gopt.op_sys_full = HOST_OS;
28652897Sobrien
28752897Sobrien  /* OS version */
28852897Sobrien  gopt.op_sys_vendor = HOST_VENDOR;
28952897Sobrien
29038494Sobrien  /* pid file */
29138494Sobrien  gopt.pid_file = "/dev/stdout";
29238494Sobrien
29338494Sobrien  /* local domain */
29438494Sobrien  gopt.sub_domain = NULL;
29538494Sobrien
296174298Sobrien  /* reset NFS (and toplvl) retransmit counter and retry interval */
297174298Sobrien  for (i=0; i<AMU_TYPE_MAX; ++i) {
298174298Sobrien    gopt.amfs_auto_retrans[i] = -1; /* -1 means "never set before" */
299174298Sobrien    gopt.amfs_auto_timeo[i] = -1; /* -1 means "never set before" */
300174298Sobrien  }
30138494Sobrien
30238494Sobrien  /* cache duration */
30338494Sobrien  gopt.am_timeo = AM_TTL;
30438494Sobrien
30538494Sobrien  /* dismount interval */
30638494Sobrien  gopt.am_timeo_w = AM_TTL_W;
30738494Sobrien
308174298Sobrien  /* map reload intervl */
309174298Sobrien  gopt.map_reload_interval = ONE_HOUR;
310174298Sobrien
31138494Sobrien  /*
312174298Sobrien   * various CFM_* flags that are on by default.
31338494Sobrien   */
314174298Sobrien  gopt.flags = CFM_DEFAULT_FLAGS;
31538494Sobrien
31638494Sobrien#ifdef HAVE_MAP_HESIOD
31738494Sobrien  /* Hesiod rhs zone */
31838494Sobrien  gopt.hesiod_base = "automount";
31938494Sobrien#endif /* HAVE_MAP_HESIOD */
32038494Sobrien
32138494Sobrien#ifdef HAVE_MAP_LDAP
32238494Sobrien  /* LDAP base */
32338494Sobrien  gopt.ldap_base = NULL;
32438494Sobrien
32538494Sobrien  /* LDAP host ports */
32638494Sobrien  gopt.ldap_hostports = NULL;
32738494Sobrien
32838494Sobrien  /* LDAP cache */
32938494Sobrien  gopt.ldap_cache_seconds = 0;
33038494Sobrien  gopt.ldap_cache_maxmem = 131072;
331174298Sobrien
332174298Sobrien  /* LDAP protocol version */
333174298Sobrien  gopt.ldap_proto_version = 2;
33438494Sobrien#endif /* HAVE_MAP_LDAP */
33538494Sobrien
33638494Sobrien#ifdef HAVE_MAP_NIS
33738494Sobrien  /* YP domain name */
33838494Sobrien  gopt.nis_domain = NULL;
33938494Sobrien#endif /* HAVE_MAP_NIS */
34038494Sobrien}
34138494Sobrien
34238494Sobrien
343174298Sobrien/*
344174298Sobrien * Lock process text and data segment in memory (after forking the daemon)
345174298Sobrien */
346174298Sobrienstatic void
347174298Sobriendo_memory_locking(void)
348174298Sobrien{
349174298Sobrien#if defined(HAVE_PLOCK) || defined(HAVE_MLOCKALL)
350174298Sobrien  int locked_ok = 0;
351174298Sobrien#else /* not HAVE_PLOCK and not HAVE_MLOCKALL */
352174298Sobrien  plog(XLOG_WARNING, "Process memory locking not supported by the OS");
353174298Sobrien#endif /* not HAVE_PLOCK and not HAVE_MLOCKALL */
354174298Sobrien#ifdef HAVE_PLOCK
355174298Sobrien# ifdef _AIX
356174298Sobrien  /*
357174298Sobrien   * On AIX you must lower the stack size using ulimit() before calling
358174298Sobrien   * plock.  Otherwise plock will reserve a lot of memory space based on
359174298Sobrien   * your maximum stack size limit.  Since it is not easily possible to
360174298Sobrien   * tell what should the limit be, I print a warning before calling
361174298Sobrien   * plock().  See the manual pages for ulimit(1,3,4) on your AIX system.
362174298Sobrien   */
363174298Sobrien  plog(XLOG_WARNING, "AIX: may need to lower stack size using ulimit(3) before calling plock");
364174298Sobrien# endif /* _AIX */
365174298Sobrien  if (!locked_ok && plock(PROCLOCK) != 0)
366174298Sobrien    plog(XLOG_WARNING, "Couldn't lock process pages in memory using plock(): %m");
367174298Sobrien  else
368174298Sobrien    locked_ok = 1;
369174298Sobrien#endif /* HAVE_PLOCK */
370174298Sobrien#ifdef HAVE_MLOCKALL
371174298Sobrien  if (!locked_ok && mlockall(MCL_CURRENT|MCL_FUTURE) != 0)
372174298Sobrien    plog(XLOG_WARNING, "Couldn't lock process pages in memory using mlockall(): %m");
373174298Sobrien  else
374174298Sobrien    locked_ok = 1;
375174298Sobrien#endif /* HAVE_MLOCKALL */
376174298Sobrien#if defined(HAVE_PLOCK) || defined(HAVE_MLOCKALL)
377174298Sobrien  if (locked_ok)
378174298Sobrien    plog(XLOG_INFO, "Locked process pages in memory");
379174298Sobrien#endif /* HAVE_PLOCK || HAVE_MLOCKALL */
380174298Sobrien
381174298Sobrien#if defined(HAVE_MADVISE) && defined(MADV_PROTECT)
382174298Sobrien    madvise(0, 0, MADV_PROTECT); /* may be redundant of the above worked out */
383174298Sobrien#endif /* defined(HAVE_MADVISE) && defined(MADV_PROTECT) */
384174298Sobrien}
385174298Sobrien
386174298Sobrien
38738494Sobrienint
38838494Sobrienmain(int argc, char *argv[])
38938494Sobrien{
390174298Sobrien  char *domdot, *verstr, *vertmp;
39138494Sobrien  int ppid = 0;
39238494Sobrien  int error;
39342633Sobrien  char *progname = NULL;		/* "amd" */
39442633Sobrien  char hostname[MAXHOSTNAMELEN + 1] = "localhost"; /* Hostname */
39538494Sobrien
39638494Sobrien  /*
39738494Sobrien   * Make sure some built-in assumptions are true before we start
39838494Sobrien   */
39938494Sobrien  assert(sizeof(nfscookie) >= sizeof(u_int));
40038494Sobrien  assert(sizeof(int) >= 4);
40138494Sobrien
40238494Sobrien  /*
40338494Sobrien   * Set processing status.
40438494Sobrien   */
40538494Sobrien  amd_state = Start;
40638494Sobrien
40738494Sobrien  /*
40838494Sobrien   * Determine program name
40938494Sobrien   */
41038494Sobrien  if (argv[0]) {
41138494Sobrien    progname = strrchr(argv[0], '/');
41238494Sobrien    if (progname && progname[1])
41338494Sobrien      progname++;
41438494Sobrien    else
41538494Sobrien      progname = argv[0];
41638494Sobrien  }
41738494Sobrien  if (!progname)
41838494Sobrien    progname = "amd";
41942633Sobrien  am_set_progname(progname);
42038494Sobrien
42138494Sobrien  /*
42242633Sobrien   * Initialize process id.  This is kept
42338494Sobrien   * cached since it is used for generating
42438494Sobrien   * and using file handles.
42538494Sobrien   */
42642633Sobrien  am_set_mypid();
42738494Sobrien
42838494Sobrien  /*
42938494Sobrien   * Get local machine name
43038494Sobrien   */
43138494Sobrien  if (gethostname(hostname, sizeof(hostname)) < 0) {
43238494Sobrien    plog(XLOG_FATAL, "gethostname: %m");
43338494Sobrien    going_down(1);
43438494Sobrien  }
43538500Sobrien  hostname[sizeof(hostname) - 1] = '\0';
43638494Sobrien
43738494Sobrien  /*
43838494Sobrien   * Check it makes sense
43938494Sobrien   */
44038494Sobrien  if (!*hostname) {
44138494Sobrien    plog(XLOG_FATAL, "host name is not set");
44238494Sobrien    going_down(1);
44338494Sobrien  }
44438494Sobrien
44538494Sobrien  /*
44638494Sobrien   * Initialize global options structure.
44738494Sobrien   */
44838494Sobrien  init_global_options();
44938494Sobrien
45038494Sobrien  /*
45142633Sobrien   * Partially initialize hostd[].  This
45238494Sobrien   * is completed in get_args().
45338494Sobrien   */
45438494Sobrien  if ((domdot = strchr(hostname, '.'))) {
45538494Sobrien    /*
45638494Sobrien     * Hostname already contains domainname.
45738494Sobrien     * Split out hostname and domainname
45838494Sobrien     * components
45938494Sobrien     */
46038494Sobrien    *domdot++ = '\0';
46138494Sobrien    hostdomain = domdot;
46238494Sobrien  }
463174298Sobrien  xstrlcpy(hostd, hostname, sizeof(hostd));
46442633Sobrien  am_set_hostname(hostname);
46538494Sobrien
46638494Sobrien  /*
467174298Sobrien   * Setup signal handlers
46838494Sobrien   */
469174298Sobrien  /* SIGINT: trap interrupts for shutdowns */
470174298Sobrien  setup_sighandler(SIGINT, sigterm);
471174298Sobrien  /* SIGTERM: trap terminate so we can shutdown cleanly (some chance) */
472174298Sobrien  setup_sighandler(SIGTERM, sigterm);
473174298Sobrien  /* SIGHUP: hangups tell us to reload the cache */
474174298Sobrien  setup_sighandler(SIGHUP, sighup);
47538494Sobrien  /*
476174298Sobrien   * SIGCHLD: trap Death-of-a-child.  These allow us to pick up the exit
477174298Sobrien   * status of backgrounded mounts.  See "sched.c".
47838494Sobrien   */
479174298Sobrien  setup_sighandler(SIGCHLD, sigchld);
48038494Sobrien#ifdef HAVE_SIGACTION
481174298Sobrien  /* construct global "masked_sigs" used in nfs_start.c */
48238494Sobrien  sigemptyset(&masked_sigs);
483174298Sobrien  sigaddset(&masked_sigs, SIGINT);
484174298Sobrien  sigaddset(&masked_sigs, SIGTERM);
48538494Sobrien  sigaddset(&masked_sigs, SIGHUP);
48638494Sobrien  sigaddset(&masked_sigs, SIGCHLD);
487174298Sobrien#endif /* HAVE_SIGACTION */
48838494Sobrien
48938494Sobrien  /*
49038494Sobrien   * Fix-up any umask problems.  Most systems default
49138494Sobrien   * to 002 which is not too convenient for our purposes
49238494Sobrien   */
49338494Sobrien  orig_umask = umask(0);
49438494Sobrien
49538494Sobrien  /*
49638494Sobrien   * Figure out primary network name
49738494Sobrien   */
49838494Sobrien  getwire(&PrimNetName, &PrimNetNum);
49938494Sobrien
50038494Sobrien  /*
50138494Sobrien   * Determine command-line arguments
50238494Sobrien   */
50338494Sobrien  get_args(argc, argv);
50438494Sobrien
50538494Sobrien  /*
50638494Sobrien   * Log version information.
50738494Sobrien   */
508174298Sobrien  vertmp = get_version_string();
509174298Sobrien  verstr = strtok(vertmp, "\n");
51038494Sobrien  plog(XLOG_INFO, "AM-UTILS VERSION INFORMATION:");
51138494Sobrien  while (verstr) {
51282797Sobrien    plog(XLOG_INFO, "%s", verstr);
51338494Sobrien    verstr = strtok(NULL, "\n");
51438494Sobrien  }
515174298Sobrien  XFREE(vertmp);
51638494Sobrien
51738494Sobrien  /*
518174298Sobrien   * Get our own IP address so that we can mount the automounter.  We pass
519174298Sobrien   * localhost_address which could be used as the default localhost
520174298Sobrien   * name/address in amu_get_myaddress().
52138494Sobrien   */
522174298Sobrien  amu_get_myaddress(&myipaddr, gopt.localhost_address);
52351300Sobrien  plog(XLOG_INFO, "My ip addr is %s", inet_ntoa(myipaddr));
52438494Sobrien
52538494Sobrien  /* avoid hanging on other NFS servers if started elsewhere */
52638494Sobrien  if (chdir("/") < 0)
52738494Sobrien    plog(XLOG_INFO, "cannot chdir to /: %m");
52838494Sobrien
52938494Sobrien  /*
53038494Sobrien   * Now check we are root.
53138494Sobrien   */
53238494Sobrien  if (geteuid() != 0) {
53351300Sobrien    plog(XLOG_FATAL, "Must be root to mount filesystems (euid = %ld)", (long) geteuid());
53438494Sobrien    going_down(1);
53538494Sobrien  }
53638494Sobrien
53738494Sobrien#ifdef HAVE_MAP_NIS
53838494Sobrien  /*
53938494Sobrien   * If the domain was specified then bind it here
54038494Sobrien   * to circumvent any default bindings that may
54138494Sobrien   * be done in the C library.
54238494Sobrien   */
54338494Sobrien  if (gopt.nis_domain && yp_bind(gopt.nis_domain)) {
54438494Sobrien    plog(XLOG_FATAL, "Can't bind to NIS domain \"%s\"", gopt.nis_domain);
54538494Sobrien    going_down(1);
54638494Sobrien  }
54738494Sobrien#endif /* HAVE_MAP_NIS */
54838494Sobrien
549174298Sobrien  if (!amuDebug(D_DAEMON))
55038494Sobrien    ppid = daemon_mode();
55138494Sobrien
552174298Sobrien  /*
553174298Sobrien   * Lock process text and data segment in memory.
554174298Sobrien   */
555174298Sobrien  if (gopt.flags & CFM_PROCESS_LOCK) {
556174298Sobrien    do_memory_locking();
557174298Sobrien  }
55838494Sobrien
559174298Sobrien  do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval;
56038494Sobrien
56138494Sobrien  /*
56238494Sobrien   * Register automounter with system.
56338494Sobrien   */
56438494Sobrien  error = mount_automounter(ppid);
56538494Sobrien  if (error && ppid)
56642633Sobrien    kill(ppid, SIGALRM);
567174298Sobrien
568174298Sobrien#ifdef HAVE_FS_AUTOFS
569174298Sobrien  /*
570174298Sobrien   * XXX this should be part of going_down(), but I can't move it there
571174298Sobrien   * because it would be calling non-library code from the library... ugh
572174298Sobrien   */
573174298Sobrien  if (amd_use_autofs)
574174298Sobrien    destroy_autofs_service();
575174298Sobrien#endif /* HAVE_FS_AUTOFS */
576174298Sobrien
57738494Sobrien  going_down(error);
57838494Sobrien
57938494Sobrien  abort();
58038494Sobrien  return 1; /* should never get here */
58138494Sobrien}
582