xref: /netbsd-src/external/bsd/am-utils/dist/amd/amd.c (revision 8bae5d409deb915cf7c8f0539fae22ff2cb8a313)
1*8bae5d40Schristos /*	$NetBSD: amd.c,v 1.1.1.3 2015/01/17 16:34:15 christos Exp $	*/
2a53f50b9Schristos 
3a53f50b9Schristos /*
4*8bae5d40Schristos  * Copyright (c) 1997-2014 Erez Zadok
5a53f50b9Schristos  * Copyright (c) 1989 Jan-Simon Pendry
6a53f50b9Schristos  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
7a53f50b9Schristos  * Copyright (c) 1989 The Regents of the University of California.
8a53f50b9Schristos  * All rights reserved.
9a53f50b9Schristos  *
10a53f50b9Schristos  * This code is derived from software contributed to Berkeley by
11a53f50b9Schristos  * Jan-Simon Pendry at Imperial College, London.
12a53f50b9Schristos  *
13a53f50b9Schristos  * Redistribution and use in source and binary forms, with or without
14a53f50b9Schristos  * modification, are permitted provided that the following conditions
15a53f50b9Schristos  * are met:
16a53f50b9Schristos  * 1. Redistributions of source code must retain the above copyright
17a53f50b9Schristos  *    notice, this list of conditions and the following disclaimer.
18a53f50b9Schristos  * 2. Redistributions in binary form must reproduce the above copyright
19a53f50b9Schristos  *    notice, this list of conditions and the following disclaimer in the
20a53f50b9Schristos  *    documentation and/or other materials provided with the distribution.
21*8bae5d40Schristos  * 3. Neither the name of the University nor the names of its contributors
22a53f50b9Schristos  *    may be used to endorse or promote products derived from this software
23a53f50b9Schristos  *    without specific prior written permission.
24a53f50b9Schristos  *
25a53f50b9Schristos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26a53f50b9Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27a53f50b9Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28a53f50b9Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29a53f50b9Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30a53f50b9Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31a53f50b9Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32a53f50b9Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33a53f50b9Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34a53f50b9Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35a53f50b9Schristos  * SUCH DAMAGE.
36a53f50b9Schristos  *
37a53f50b9Schristos  *
38a53f50b9Schristos  * File: am-utils/amd/amd.c
39a53f50b9Schristos  *
40a53f50b9Schristos  */
41a53f50b9Schristos 
42a53f50b9Schristos /*
43a53f50b9Schristos  * Automounter
44a53f50b9Schristos  */
45a53f50b9Schristos 
46a53f50b9Schristos #ifdef HAVE_CONFIG_H
47a53f50b9Schristos # include <config.h>
48a53f50b9Schristos #endif /* HAVE_CONFIG_H */
49a53f50b9Schristos #include <am_defs.h>
50a53f50b9Schristos #include <amd.h>
51a53f50b9Schristos 
52a53f50b9Schristos struct amu_global_options gopt;	/* where global options are stored */
53a53f50b9Schristos 
54a53f50b9Schristos char pid_fsname[SIZEOF_PID_FSNAME]; /* "kiska.southseas.nz:(pid%d)" */
55a53f50b9Schristos char *hostdomain = "unknown.domain";
56a53f50b9Schristos #define SIZEOF_HOSTD (2 * MAXHOSTNAMELEN + 1)	/* Host+domain */
57a53f50b9Schristos char hostd[SIZEOF_HOSTD];	/* Host+domain */
58a53f50b9Schristos char *endian = ARCH_ENDIAN;	/* Big or Little endian */
59a53f50b9Schristos char *cpu = HOST_CPU;		/* CPU type */
60a53f50b9Schristos char *PrimNetName;		/* name of primary network */
61a53f50b9Schristos char *PrimNetNum;		/* number of primary network */
62a53f50b9Schristos 
63a53f50b9Schristos int immediate_abort;		/* Should close-down unmounts be retried */
64a53f50b9Schristos int orig_umask = 022;
65a53f50b9Schristos int select_intr_valid;
66a53f50b9Schristos 
67a53f50b9Schristos jmp_buf select_intr;
68a53f50b9Schristos struct amd_stats amd_stats;	/* Server statistics */
69a53f50b9Schristos struct in_addr myipaddr;	/* (An) IP address of this host */
70a53f50b9Schristos time_t do_mapc_reload = 0;	/* mapc_reload() call required? */
71a53f50b9Schristos 
72a53f50b9Schristos #ifdef HAVE_FS_AUTOFS
73a53f50b9Schristos int amd_use_autofs = 0;
74a53f50b9Schristos #endif /* HAVE_FS_AUTOFS */
75a53f50b9Schristos 
76a53f50b9Schristos #ifdef HAVE_SIGACTION
77a53f50b9Schristos sigset_t masked_sigs;
78a53f50b9Schristos #endif /* HAVE_SIGACTION */
79a53f50b9Schristos 
80a53f50b9Schristos 
81a53f50b9Schristos /*
82a53f50b9Schristos  * Signal handler:
83a53f50b9Schristos  * SIGINT - tells amd to do a full shutdown, including unmounting all
84a53f50b9Schristos  *       filesystem.
85a53f50b9Schristos  * SIGTERM - tells amd to shutdown now.  Just unmounts the automount nodes.
86a53f50b9Schristos  */
87a53f50b9Schristos static RETSIGTYPE
sigterm(int sig)88a53f50b9Schristos sigterm(int sig)
89a53f50b9Schristos {
90a53f50b9Schristos #ifdef REINSTALL_SIGNAL_HANDLER
91a53f50b9Schristos   signal(sig, sigterm);
92a53f50b9Schristos #endif /* REINSTALL_SIGNAL_HANDLER */
93a53f50b9Schristos 
94a53f50b9Schristos   switch (sig) {
95a53f50b9Schristos   case SIGINT:
96a53f50b9Schristos     immediate_abort = 15;
97a53f50b9Schristos     break;
98a53f50b9Schristos 
99a53f50b9Schristos   case SIGTERM:
100a53f50b9Schristos     immediate_abort = -1;
101a53f50b9Schristos     /* fall through... */
102a53f50b9Schristos 
103a53f50b9Schristos   default:
104a53f50b9Schristos     plog(XLOG_WARNING, "WARNING: automounter going down on signal %d", sig);
105a53f50b9Schristos     break;
106a53f50b9Schristos   }
107a53f50b9Schristos   if (select_intr_valid)
108a53f50b9Schristos     longjmp(select_intr, sig);
109a53f50b9Schristos }
110a53f50b9Schristos 
111a53f50b9Schristos 
112a53f50b9Schristos /*
113a53f50b9Schristos  * Hook for cache reload.
114a53f50b9Schristos  * When a SIGHUP arrives it schedules a call to mapc_reload
115a53f50b9Schristos  */
116a53f50b9Schristos static RETSIGTYPE
sighup(int sig)117a53f50b9Schristos sighup(int sig)
118a53f50b9Schristos {
119a53f50b9Schristos #ifdef REINSTALL_SIGNAL_HANDLER
120a53f50b9Schristos   signal(sig, sighup);
121a53f50b9Schristos #endif /* REINSTALL_SIGNAL_HANDLER */
122a53f50b9Schristos 
123a53f50b9Schristos   if (sig != SIGHUP)
124a53f50b9Schristos     dlog("spurious call to sighup");
125a53f50b9Schristos   /*
126a53f50b9Schristos    * Force a reload by zero'ing the timer
127a53f50b9Schristos    */
128a53f50b9Schristos   if (amd_state == Run)
129a53f50b9Schristos     do_mapc_reload = 0;
130a53f50b9Schristos }
131a53f50b9Schristos 
132a53f50b9Schristos 
133a53f50b9Schristos static RETSIGTYPE
parent_exit(int sig)134a53f50b9Schristos parent_exit(int sig)
135a53f50b9Schristos {
136a53f50b9Schristos   /*
137a53f50b9Schristos    * This signal handler is called during Amd initialization.  The parent
138a53f50b9Schristos    * forks a child to do all the hard automounting work, and waits for a
139a53f50b9Schristos    * SIGQUIT signal from the child.  When the parent gets the signal it's
140a53f50b9Schristos    * supposed to call this handler and exit(3), thus completing the
141a53f50b9Schristos    * daemonizing process.  Alas, on some systems, especially Linux 2.4/2.6
142a53f50b9Schristos    * with Glibc, exit(3) doesn't always terminate the parent process.
143a53f50b9Schristos    * Worse, the parent process now refuses to accept any more SIGQUIT
144a53f50b9Schristos    * signals -- they are blocked.  What's really annoying is that this
145a53f50b9Schristos    * doesn't happen all the time, suggesting a race condition somewhere.
146a53f50b9Schristos    * (This happens even if I change the logic to use another signal.)  I
147a53f50b9Schristos    * traced this to something which exit(3) does in addition to exiting the
148a53f50b9Schristos    * process, probably some atexit() stuff or other side-effects related to
149a53f50b9Schristos    * signal handling.  Either way, since at this stage the parent process
150a53f50b9Schristos    * just needs to terminate, I'm simply calling _exit(2).  Note also that
151a53f50b9Schristos    * the OpenGroup doesn't list exit(3) as a recommended "Base Interface"
152a53f50b9Schristos    * but they do list _exit(2) as one.  This fix seems to work reliably all
153a53f50b9Schristos    * the time. -Erez (2/27/2005)
154a53f50b9Schristos    */
155a53f50b9Schristos   _exit(0);
156a53f50b9Schristos }
157a53f50b9Schristos 
158a53f50b9Schristos 
159a53f50b9Schristos static int
daemon_mode(void)160a53f50b9Schristos daemon_mode(void)
161a53f50b9Schristos {
162a53f50b9Schristos   int bgpid;
163a53f50b9Schristos 
164a53f50b9Schristos #ifdef HAVE_SIGACTION
165a53f50b9Schristos   struct sigaction sa, osa;
166a53f50b9Schristos 
167a53f50b9Schristos   memset(&sa, 0, sizeof(sa));
168a53f50b9Schristos   sa.sa_handler = parent_exit;
169a53f50b9Schristos   sa.sa_flags = 0;
170a53f50b9Schristos   sigemptyset(&(sa.sa_mask));
171a53f50b9Schristos   sigaddset(&(sa.sa_mask), SIGQUIT);
172a53f50b9Schristos   sigaction(SIGQUIT, &sa, &osa);
173a53f50b9Schristos #else /* not HAVE_SIGACTION */
174a53f50b9Schristos   signal(SIGQUIT, parent_exit);
175a53f50b9Schristos #endif /* not HAVE_SIGACTION */
176a53f50b9Schristos 
177a53f50b9Schristos   bgpid = background();
178a53f50b9Schristos 
179a53f50b9Schristos   if (bgpid != 0) {
180a53f50b9Schristos     /*
181a53f50b9Schristos      * Now wait for the automount points to
182a53f50b9Schristos      * complete.
183a53f50b9Schristos      */
184a53f50b9Schristos     for (;;)
185a53f50b9Schristos       pause();
186a53f50b9Schristos     /* should never reach here */
187a53f50b9Schristos   }
188a53f50b9Schristos #ifdef HAVE_SIGACTION
189a53f50b9Schristos   sigaction(SIGQUIT, &osa, NULL);
190a53f50b9Schristos #else /* not HAVE_SIGACTION */
191a53f50b9Schristos   signal(SIGQUIT, SIG_DFL);
192a53f50b9Schristos #endif /* not HAVE_SIGACTION */
193a53f50b9Schristos 
194a53f50b9Schristos   /*
195a53f50b9Schristos    * Record our pid to make it easier to kill the correct amd.
196a53f50b9Schristos    */
197a53f50b9Schristos   if (gopt.flags & CFM_PRINT_PID) {
198a53f50b9Schristos     if (STREQ(gopt.pid_file, "/dev/stdout")) {
199a53f50b9Schristos       printf("%ld\n", (long) am_mypid);
200a53f50b9Schristos       /* flush stdout, just in case */
201a53f50b9Schristos       fflush(stdout);
202a53f50b9Schristos     } else {
203a53f50b9Schristos       FILE *f;
204a53f50b9Schristos       mode_t prev_umask = umask(0022); /* set secure temporary umask */
205a53f50b9Schristos 
206a53f50b9Schristos       f = fopen(gopt.pid_file, "w");
207a53f50b9Schristos       if (f) {
208a53f50b9Schristos 	fprintf(f, "%ld\n", (long) am_mypid);
209a53f50b9Schristos 	(void) fclose(f);
210a53f50b9Schristos       } else {
211a53f50b9Schristos 	fprintf(stderr, "cannot open %s (errno=%d)\n", gopt.pid_file, errno);
212a53f50b9Schristos       }
213a53f50b9Schristos       umask(prev_umask);	/* restore umask */
214a53f50b9Schristos     }
215a53f50b9Schristos   }
216a53f50b9Schristos 
217a53f50b9Schristos   /*
218a53f50b9Schristos    * Pretend we are in the foreground again
219a53f50b9Schristos    */
220a53f50b9Schristos   foreground = 1;
221a53f50b9Schristos 
222a53f50b9Schristos   /*
223a53f50b9Schristos    * Dissociate from the controlling terminal
224a53f50b9Schristos    */
225a53f50b9Schristos   amu_release_controlling_tty();
226a53f50b9Schristos 
227a53f50b9Schristos   return getppid();
228a53f50b9Schristos }
229a53f50b9Schristos 
230a53f50b9Schristos 
231a53f50b9Schristos /*
232a53f50b9Schristos  * Initialize global options structure.
233a53f50b9Schristos  */
234a53f50b9Schristos static void
init_global_options(void)235a53f50b9Schristos init_global_options(void)
236a53f50b9Schristos {
237a53f50b9Schristos #if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
238a53f50b9Schristos   static struct utsname un;
239a53f50b9Schristos #endif /* defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) */
240a53f50b9Schristos   int i;
241a53f50b9Schristos 
242a53f50b9Schristos   memset(&gopt, 0, sizeof(struct amu_global_options));
243a53f50b9Schristos 
244a53f50b9Schristos   /* name of current architecture */
245a53f50b9Schristos   gopt.arch = HOST_ARCH;
246a53f50b9Schristos 
247a53f50b9Schristos   /* automounter temp dir */
248a53f50b9Schristos   gopt.auto_dir = "/a";
249a53f50b9Schristos 
250a53f50b9Schristos   /* toplevel attribute cache timeout */
251a53f50b9Schristos   gopt.auto_attrcache = 0;
252a53f50b9Schristos 
253a53f50b9Schristos   /* cluster name */
254a53f50b9Schristos   gopt.cluster = NULL;
255a53f50b9Schristos 
256a53f50b9Schristos   /* executable map timeout */
257a53f50b9Schristos   gopt.exec_map_timeout = AMFS_EXEC_MAP_TIMEOUT;
258a53f50b9Schristos 
259a53f50b9Schristos   /*
260a53f50b9Schristos    * kernel architecture: this you must get from uname() if possible.
261a53f50b9Schristos    */
262a53f50b9Schristos #if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
263a53f50b9Schristos   if (uname(&un) >= 0)
264a53f50b9Schristos     gopt.karch = un.machine;
265a53f50b9Schristos   else
266a53f50b9Schristos #endif /* defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) */
267a53f50b9Schristos     gopt.karch = HOST_ARCH;
268a53f50b9Schristos 
269a53f50b9Schristos   /* amd log file */
270a53f50b9Schristos   gopt.logfile = NULL;
271a53f50b9Schristos 
272a53f50b9Schristos   /* operating system name */
273a53f50b9Schristos   gopt.op_sys = HOST_OS_NAME;
274a53f50b9Schristos 
275a53f50b9Schristos   /* OS version */
276a53f50b9Schristos   gopt.op_sys_ver = HOST_OS_VERSION;
277a53f50b9Schristos 
278a53f50b9Schristos   /* full OS name and version */
279a53f50b9Schristos   gopt.op_sys_full = HOST_OS;
280a53f50b9Schristos 
281a53f50b9Schristos   /* OS version */
282a53f50b9Schristos   gopt.op_sys_vendor = HOST_VENDOR;
283a53f50b9Schristos 
284a53f50b9Schristos   /* pid file */
285a53f50b9Schristos   gopt.pid_file = "/dev/stdout";
286a53f50b9Schristos 
287a53f50b9Schristos   /* local domain */
288a53f50b9Schristos   gopt.sub_domain = NULL;
289a53f50b9Schristos 
290a53f50b9Schristos   /* reset NFS (and toplvl) retransmit counter and retry interval */
291a53f50b9Schristos   for (i=0; i<AMU_TYPE_MAX; ++i) {
292a53f50b9Schristos     gopt.amfs_auto_retrans[i] = -1; /* -1 means "never set before" */
293a53f50b9Schristos     gopt.amfs_auto_timeo[i] = -1; /* -1 means "never set before" */
294a53f50b9Schristos   }
295a53f50b9Schristos 
296a53f50b9Schristos   /* cache duration */
297a53f50b9Schristos   gopt.am_timeo = AM_TTL;
298a53f50b9Schristos 
299a53f50b9Schristos   /* dismount interval */
300a53f50b9Schristos   gopt.am_timeo_w = AM_TTL_W;
301a53f50b9Schristos 
302a53f50b9Schristos   /* map reload intervl */
303a53f50b9Schristos   gopt.map_reload_interval = ONE_HOUR;
304a53f50b9Schristos 
305a53f50b9Schristos   /*
306a53f50b9Schristos    * various CFM_* flags that are on by default.
307a53f50b9Schristos    */
308a53f50b9Schristos   gopt.flags = CFM_DEFAULT_FLAGS;
309a53f50b9Schristos 
310a53f50b9Schristos #ifdef HAVE_MAP_HESIOD
311a53f50b9Schristos   /* Hesiod rhs zone */
312a53f50b9Schristos   gopt.hesiod_base = "automount";
313a53f50b9Schristos #endif /* HAVE_MAP_HESIOD */
314a53f50b9Schristos 
315a53f50b9Schristos #ifdef HAVE_MAP_LDAP
316a53f50b9Schristos   /* LDAP base */
317a53f50b9Schristos   gopt.ldap_base = NULL;
318a53f50b9Schristos 
319a53f50b9Schristos   /* LDAP host ports */
320a53f50b9Schristos   gopt.ldap_hostports = NULL;
321a53f50b9Schristos 
322a53f50b9Schristos   /* LDAP cache */
323a53f50b9Schristos   gopt.ldap_cache_seconds = 0;
324a53f50b9Schristos   gopt.ldap_cache_maxmem = 131072;
325a53f50b9Schristos 
326a53f50b9Schristos   /* LDAP protocol version */
327a53f50b9Schristos   gopt.ldap_proto_version = 2;
328a53f50b9Schristos #endif /* HAVE_MAP_LDAP */
329a53f50b9Schristos 
330a53f50b9Schristos #ifdef HAVE_MAP_NIS
331a53f50b9Schristos   /* YP domain name */
332a53f50b9Schristos   gopt.nis_domain = NULL;
333a53f50b9Schristos #endif /* HAVE_MAP_NIS */
334a53f50b9Schristos }
335a53f50b9Schristos 
336a53f50b9Schristos 
337a53f50b9Schristos /*
338a53f50b9Schristos  * Lock process text and data segment in memory (after forking the daemon)
339a53f50b9Schristos  */
340a53f50b9Schristos static void
do_memory_locking(void)341a53f50b9Schristos do_memory_locking(void)
342a53f50b9Schristos {
343a53f50b9Schristos #if defined(HAVE_PLOCK) || defined(HAVE_MLOCKALL)
344a53f50b9Schristos   int locked_ok = 0;
345a53f50b9Schristos #else /* not HAVE_PLOCK and not HAVE_MLOCKALL */
346a53f50b9Schristos   plog(XLOG_WARNING, "Process memory locking not supported by the OS");
347a53f50b9Schristos #endif /* not HAVE_PLOCK and not HAVE_MLOCKALL */
348a53f50b9Schristos #ifdef HAVE_PLOCK
349a53f50b9Schristos # ifdef _AIX
350a53f50b9Schristos   /*
351a53f50b9Schristos    * On AIX you must lower the stack size using ulimit() before calling
352a53f50b9Schristos    * plock.  Otherwise plock will reserve a lot of memory space based on
353a53f50b9Schristos    * your maximum stack size limit.  Since it is not easily possible to
354a53f50b9Schristos    * tell what should the limit be, I print a warning before calling
355a53f50b9Schristos    * plock().  See the manual pages for ulimit(1,3,4) on your AIX system.
356a53f50b9Schristos    */
357a53f50b9Schristos   plog(XLOG_WARNING, "AIX: may need to lower stack size using ulimit(3) before calling plock");
358a53f50b9Schristos # endif /* _AIX */
359a53f50b9Schristos   if (!locked_ok && plock(PROCLOCK) != 0)
360a53f50b9Schristos     plog(XLOG_WARNING, "Couldn't lock process pages in memory using plock(): %m");
361a53f50b9Schristos   else
362a53f50b9Schristos     locked_ok = 1;
363a53f50b9Schristos #endif /* HAVE_PLOCK */
364a53f50b9Schristos #ifdef HAVE_MLOCKALL
365a53f50b9Schristos   if (!locked_ok && mlockall(MCL_CURRENT|MCL_FUTURE) != 0)
366a53f50b9Schristos     plog(XLOG_WARNING, "Couldn't lock process pages in memory using mlockall(): %m");
367a53f50b9Schristos   else
368a53f50b9Schristos     locked_ok = 1;
369a53f50b9Schristos #endif /* HAVE_MLOCKALL */
370a53f50b9Schristos #if defined(HAVE_PLOCK) || defined(HAVE_MLOCKALL)
371a53f50b9Schristos   if (locked_ok)
372a53f50b9Schristos     plog(XLOG_INFO, "Locked process pages in memory");
373a53f50b9Schristos #endif /* HAVE_PLOCK || HAVE_MLOCKALL */
374a53f50b9Schristos 
375a53f50b9Schristos #if defined(HAVE_MADVISE) && defined(MADV_PROTECT)
376a53f50b9Schristos     madvise(NULL, 0, MADV_PROTECT); /* may be redundant of the above worked out */
377a53f50b9Schristos #endif /* defined(HAVE_MADVISE) && defined(MADV_PROTECT) */
378a53f50b9Schristos }
379a53f50b9Schristos 
380a53f50b9Schristos 
381a53f50b9Schristos int
main(int argc,char * argv[])382a53f50b9Schristos main(int argc, char *argv[])
383a53f50b9Schristos {
384a53f50b9Schristos   char *domdot, *verstr, *vertmp;
385a53f50b9Schristos   int ppid = 0;
386a53f50b9Schristos   int error;
387a53f50b9Schristos   char *progname = NULL;		/* "amd" */
388a53f50b9Schristos   char hostname[MAXHOSTNAMELEN + 1] = "localhost"; /* Hostname */
389a53f50b9Schristos 
390a53f50b9Schristos   /*
391a53f50b9Schristos    * Make sure some built-in assumptions are true before we start
392a53f50b9Schristos    */
393a53f50b9Schristos   assert(sizeof(nfscookie) >= sizeof(u_int));
394a53f50b9Schristos   assert(sizeof(int) >= 4);
395a53f50b9Schristos 
396a53f50b9Schristos   /*
397a53f50b9Schristos    * Set processing status.
398a53f50b9Schristos    */
399a53f50b9Schristos   amd_state = Start;
400a53f50b9Schristos 
401a53f50b9Schristos   /*
402a53f50b9Schristos    * Determine program name
403a53f50b9Schristos    */
404a53f50b9Schristos   if (argv[0]) {
405a53f50b9Schristos     progname = strrchr(argv[0], '/');
406a53f50b9Schristos     if (progname && progname[1])
407a53f50b9Schristos       progname++;
408a53f50b9Schristos     else
409a53f50b9Schristos       progname = argv[0];
410a53f50b9Schristos   }
411a53f50b9Schristos   if (!progname)
412a53f50b9Schristos     progname = "amd";
413a53f50b9Schristos   am_set_progname(progname);
414a53f50b9Schristos 
415a53f50b9Schristos   /*
416a53f50b9Schristos    * Initialize process id.  This is kept
417a53f50b9Schristos    * cached since it is used for generating
418a53f50b9Schristos    * and using file handles.
419a53f50b9Schristos    */
420a53f50b9Schristos   am_set_mypid();
421a53f50b9Schristos 
422a53f50b9Schristos   /*
423a53f50b9Schristos    * Get local machine name
424a53f50b9Schristos    */
425a53f50b9Schristos   if (gethostname(hostname, sizeof(hostname)) < 0) {
426a53f50b9Schristos     plog(XLOG_FATAL, "gethostname: %m");
427a53f50b9Schristos     going_down(1);
428*8bae5d40Schristos     return 1;
429a53f50b9Schristos   }
430a53f50b9Schristos   hostname[sizeof(hostname) - 1] = '\0';
431a53f50b9Schristos 
432a53f50b9Schristos   /*
433a53f50b9Schristos    * Check it makes sense
434a53f50b9Schristos    */
435a53f50b9Schristos   if (!*hostname) {
436a53f50b9Schristos     plog(XLOG_FATAL, "host name is not set");
437a53f50b9Schristos     going_down(1);
438*8bae5d40Schristos     return 1;
439a53f50b9Schristos   }
440a53f50b9Schristos 
441a53f50b9Schristos   /*
442a53f50b9Schristos    * Initialize global options structure.
443a53f50b9Schristos    */
444a53f50b9Schristos   init_global_options();
445a53f50b9Schristos 
446a53f50b9Schristos   /*
447a53f50b9Schristos    * Partially initialize hostd[].  This
448a53f50b9Schristos    * is completed in get_args().
449a53f50b9Schristos    */
450a53f50b9Schristos   if ((domdot = strchr(hostname, '.'))) {
451a53f50b9Schristos     /*
452a53f50b9Schristos      * Hostname already contains domainname.
453a53f50b9Schristos      * Split out hostname and domainname
454a53f50b9Schristos      * components
455a53f50b9Schristos      */
456a53f50b9Schristos     *domdot++ = '\0';
457a53f50b9Schristos     hostdomain = domdot;
458a53f50b9Schristos   }
459a53f50b9Schristos   xstrlcpy(hostd, hostname, sizeof(hostd));
460a53f50b9Schristos   am_set_hostname(hostname);
461a53f50b9Schristos 
462a53f50b9Schristos   /*
463a53f50b9Schristos    * Setup signal handlers
464a53f50b9Schristos    */
465a53f50b9Schristos   /* SIGINT: trap interrupts for shutdowns */
466a53f50b9Schristos   setup_sighandler(SIGINT, sigterm);
467a53f50b9Schristos   /* SIGTERM: trap terminate so we can shutdown cleanly (some chance) */
468a53f50b9Schristos   setup_sighandler(SIGTERM, sigterm);
469a53f50b9Schristos   /* SIGHUP: hangups tell us to reload the cache */
470a53f50b9Schristos   setup_sighandler(SIGHUP, sighup);
471a53f50b9Schristos   /*
472a53f50b9Schristos    * SIGCHLD: trap Death-of-a-child.  These allow us to pick up the exit
473a53f50b9Schristos    * status of backgrounded mounts.  See "sched.c".
474a53f50b9Schristos    */
475a53f50b9Schristos   setup_sighandler(SIGCHLD, sigchld);
476a53f50b9Schristos #ifdef HAVE_SIGACTION
477a53f50b9Schristos   /* construct global "masked_sigs" used in nfs_start.c */
478a53f50b9Schristos   sigemptyset(&masked_sigs);
479a53f50b9Schristos   sigaddset(&masked_sigs, SIGINT);
480a53f50b9Schristos   sigaddset(&masked_sigs, SIGTERM);
481a53f50b9Schristos   sigaddset(&masked_sigs, SIGHUP);
482a53f50b9Schristos   sigaddset(&masked_sigs, SIGCHLD);
483a53f50b9Schristos #endif /* HAVE_SIGACTION */
484a53f50b9Schristos 
485a53f50b9Schristos   /*
486a53f50b9Schristos    * Fix-up any umask problems.  Most systems default
487a53f50b9Schristos    * to 002 which is not too convenient for our purposes
488a53f50b9Schristos    */
489a53f50b9Schristos   orig_umask = umask(0);
490a53f50b9Schristos 
491a53f50b9Schristos   /*
492a53f50b9Schristos    * Figure out primary network name
493a53f50b9Schristos    */
494a53f50b9Schristos   getwire(&PrimNetName, &PrimNetNum);
495a53f50b9Schristos 
496a53f50b9Schristos   /*
497a53f50b9Schristos    * Determine command-line arguments.
498a53f50b9Schristos    * (Also initialize amd.conf parameters, maps, and more.)
499a53f50b9Schristos    */
500a53f50b9Schristos   get_args(argc, argv);
501a53f50b9Schristos 
502a53f50b9Schristos   /*
503a53f50b9Schristos    * Log version information.
504a53f50b9Schristos    */
505a53f50b9Schristos   vertmp = get_version_string();
506a53f50b9Schristos   verstr = strtok(vertmp, "\n");
507a53f50b9Schristos   plog(XLOG_INFO, "AM-UTILS VERSION INFORMATION:");
508a53f50b9Schristos   while (verstr) {
509a53f50b9Schristos     plog(XLOG_INFO, "%s", verstr);
510a53f50b9Schristos     verstr = strtok(NULL, "\n");
511a53f50b9Schristos   }
512a53f50b9Schristos   XFREE(vertmp);
513a53f50b9Schristos 
514a53f50b9Schristos   /*
515a53f50b9Schristos    * Get our own IP address so that we can mount the automounter.  We pass
516a53f50b9Schristos    * localhost_address which could be used as the default localhost
517a53f50b9Schristos    * name/address in amu_get_myaddress().
518a53f50b9Schristos    */
519a53f50b9Schristos   amu_get_myaddress(&myipaddr, gopt.localhost_address);
520a53f50b9Schristos   plog(XLOG_INFO, "My ip addr is %s", inet_ntoa(myipaddr));
521a53f50b9Schristos 
522a53f50b9Schristos   /* avoid hanging on other NFS servers if started elsewhere */
523a53f50b9Schristos   if (chdir("/") < 0)
524a53f50b9Schristos     plog(XLOG_INFO, "cannot chdir to /: %m");
525a53f50b9Schristos 
526a53f50b9Schristos   /*
527a53f50b9Schristos    * Now check we are root.
528a53f50b9Schristos    */
529a53f50b9Schristos   if (geteuid() != 0) {
530a53f50b9Schristos     plog(XLOG_FATAL, "Must be root to mount filesystems (euid = %ld)", (long) geteuid());
531a53f50b9Schristos     going_down(1);
532*8bae5d40Schristos     return 1;
533a53f50b9Schristos   }
534a53f50b9Schristos 
535a53f50b9Schristos #ifdef HAVE_MAP_NIS
536a53f50b9Schristos   /*
537a53f50b9Schristos    * If the domain was specified then bind it here
538a53f50b9Schristos    * to circumvent any default bindings that may
539a53f50b9Schristos    * be done in the C library.
540a53f50b9Schristos    */
541a53f50b9Schristos   if (gopt.nis_domain && yp_bind(gopt.nis_domain)) {
542a53f50b9Schristos     plog(XLOG_FATAL, "Can't bind to NIS domain \"%s\"", gopt.nis_domain);
543a53f50b9Schristos     going_down(1);
544*8bae5d40Schristos     return 1;
545a53f50b9Schristos   }
546a53f50b9Schristos #endif /* HAVE_MAP_NIS */
547a53f50b9Schristos 
548a53f50b9Schristos   if (amuDebug(D_DAEMON))
549a53f50b9Schristos     ppid = daemon_mode();
550a53f50b9Schristos 
551a53f50b9Schristos   /*
552a53f50b9Schristos    * Lock process text and data segment in memory.
553a53f50b9Schristos    */
554a53f50b9Schristos   if (gopt.flags & CFM_PROCESS_LOCK) {
555a53f50b9Schristos     do_memory_locking();
556a53f50b9Schristos   }
557a53f50b9Schristos 
558a53f50b9Schristos   do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval;
559a53f50b9Schristos 
560a53f50b9Schristos   /*
561a53f50b9Schristos    * Register automounter with system.
562a53f50b9Schristos    */
563a53f50b9Schristos   error = mount_automounter(ppid);
564a53f50b9Schristos   if (error && ppid)
565a53f50b9Schristos     kill(ppid, SIGALRM);
566a53f50b9Schristos 
567a53f50b9Schristos #ifdef HAVE_FS_AUTOFS
568a53f50b9Schristos   /*
569a53f50b9Schristos    * XXX this should be part of going_down(), but I can't move it there
570a53f50b9Schristos    * because it would be calling non-library code from the library... ugh
571a53f50b9Schristos    */
572a53f50b9Schristos   if (amd_use_autofs)
573a53f50b9Schristos     destroy_autofs_service();
574a53f50b9Schristos #endif /* HAVE_FS_AUTOFS */
575a53f50b9Schristos 
576a53f50b9Schristos   going_down(error);
577a53f50b9Schristos 
578a53f50b9Schristos   abort();
579a53f50b9Schristos   return 1; /* should never get here */
580a53f50b9Schristos }
581