2 * Copyright (c) 1997-1999 Erez Zadok
3 * Copyright (c) 1989 Jan-Simon Pendry
4 * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1989 The Regents of the University of California.
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgment:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 * $Id: amd.c,v 1.6 1999/09/30 21:01:29 ezk Exp $
42 * $FreeBSD: src/contrib/amd/amd/amd.c,v 1.6.2.1 2000/09/20 02:17:04 jkh Exp $
43 * $DragonFly: src/contrib/amd/amd/amd.c,v 1.2 2003/06/17 04:23:56 dillon Exp $
53 #endif /* HAVE_CONFIG_H */
57 struct amu_global_options gopt
; /* where global options are stored */
59 char pid_fsname
[16 + MAXHOSTNAMELEN
]; /* "kiska.southseas.nz:(pid%d)" */
60 char *hostdomain
= "unknown.domain";
61 char hostd
[2 * MAXHOSTNAMELEN
+ 1]; /* Host+domain */
62 char *endian
= ARCH_ENDIAN
; /* Big or Little endian */
63 char *cpu
= HOST_CPU
; /* CPU type */
64 char *PrimNetName
; /* name of primary network */
65 char *PrimNetNum
; /* number of primary network */
67 int immediate_abort
; /* Should close-down unmounts be retried */
69 int select_intr_valid
;
72 struct amd_stats amd_stats
; /* Server statistics */
73 struct in_addr myipaddr
; /* (An) IP address of this host */
74 time_t do_mapc_reload
= 0; /* mapc_reload() call required? */
78 #endif /* HAVE_SIGACTION */
83 * SIGINT - tells amd to do a full shutdown, including unmounting all
85 * SIGTERM - tells amd to shutdown now. Just unmounts the automount nodes.
90 #ifdef REINSTALL_SIGNAL_HANDLER
92 #endif /* REINSTALL_SIGNAL_HANDLER */
100 immediate_abort
= -1;
101 /* fall through... */
104 plog(XLOG_WARNING
, "WARNING: automounter going down on signal %d", sig
);
107 if (select_intr_valid
)
108 longjmp(select_intr
, sig
);
113 * Hook for cache reload.
114 * When a SIGHUP arrives it schedules a call to mapc_reload
119 #ifdef REINSTALL_SIGNAL_HANDLER
121 #endif /* REINSTALL_SIGNAL_HANDLER */
125 dlog("spurious call to sighup");
128 * Force a reload by zero'ing the timer
130 if (amd_state
== Run
)
147 #ifdef HAVE_SIGACTION
148 struct sigaction sa
, osa
;
150 sa
.sa_handler
= parent_exit
;
152 sigemptyset(&(sa
.sa_mask
));
153 sigaddset(&(sa
.sa_mask
), SIGQUIT
);
154 sigaction(SIGQUIT
, &sa
, &osa
);
155 #else /* not HAVE_SIGACTION */
156 signal(SIGQUIT
, parent_exit
);
157 #endif /* not HAVE_SIGACTION */
159 bgpid
= background();
163 * Now wait for the automount points to
168 /* should never reach here */
170 #ifdef HAVE_SIGACTION
171 sigaction(SIGQUIT
, &osa
, NULL
);
172 #else /* not HAVE_SIGACTION */
173 signal(SIGQUIT
, SIG_DFL
);
174 #endif /* not HAVE_SIGACTION */
177 * Record our pid to make it easier to kill the correct amd.
179 if (gopt
.flags
& CFM_PRINT_PID
) {
180 if (STREQ(gopt
.pid_file
, "/dev/stdout")) {
181 printf("%ld\n", (long) am_mypid
);
183 /* do not fclose stdout */
186 mode_t prev_umask
= umask(0022); /* set secure temporary umask */
188 f
= fopen(gopt
.pid_file
, "w");
190 fprintf(f
, "%ld\n", (long) am_mypid
);
193 fprintf(stderr
, "cannot open %s (errno=%d)\n", gopt
.pid_file
, errno
);
195 umask(prev_umask
); /* restore umask */
200 * Pretend we are in the foreground again
205 * Dissociate from the controlling terminal
207 amu_release_controlling_tty();
214 * Initialize global options structure.
217 init_global_options(void)
219 #if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
220 static struct utsname un
;
221 #endif /* defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) */
223 memset(&gopt
, 0, sizeof(struct amu_global_options
));
225 /* name of current architecture */
226 gopt
.arch
= HOST_ARCH
;
228 /* automounter temp dir */
229 gopt
.auto_dir
= "/.amd_mnt";
235 * kernel architecture: this you must get from uname() if possible.
237 #if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
239 gopt
.karch
= un
.machine
;
241 #endif /* defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME) */
242 gopt
.karch
= HOST_ARCH
;
247 /* operating system name */
248 gopt
.op_sys
= HOST_OS_NAME
;
251 gopt
.op_sys_ver
= HOST_OS_VERSION
;
253 /* full OS name and version */
254 gopt
.op_sys_full
= HOST_OS
;
257 gopt
.op_sys_vendor
= HOST_VENDOR
;
260 gopt
.pid_file
= "/dev/stdout";
263 gopt
.sub_domain
= NULL
;
265 /* NFS retransmit counter */
266 gopt
.amfs_auto_retrans
= -1;
268 /* NFS retry interval */
269 gopt
.amfs_auto_timeo
= -1;
272 gopt
.am_timeo
= AM_TTL
;
274 /* dismount interval */
275 gopt
.am_timeo_w
= AM_TTL_W
;
278 * various CFM_* flags.
279 * by default, only the "plock" option is on (if available).
281 gopt
.flags
= CFM_PROCESS_LOCK
;
283 #ifdef HAVE_MAP_HESIOD
284 /* Hesiod rhs zone */
285 gopt
.hesiod_base
= "automount";
286 #endif /* HAVE_MAP_HESIOD */
290 gopt
.ldap_base
= NULL
;
292 /* LDAP host ports */
293 gopt
.ldap_hostports
= NULL
;
296 gopt
.ldap_cache_seconds
= 0;
297 gopt
.ldap_cache_maxmem
= 131072;
298 #endif /* HAVE_MAP_LDAP */
302 gopt
.nis_domain
= NULL
;
303 #endif /* HAVE_MAP_NIS */
308 main(int argc
, char *argv
[])
310 char *domdot
, *verstr
;
313 char *progname
= NULL
; /* "amd" */
314 char hostname
[MAXHOSTNAMELEN
+ 1] = "localhost"; /* Hostname */
315 #ifdef HAVE_SIGACTION
317 #endif /* HAVE_SIGACTION */
320 * Make sure some built-in assumptions are true before we start
322 assert(sizeof(nfscookie
) >= sizeof(u_int
));
323 assert(sizeof(int) >= 4);
326 * Set processing status.
331 * Determine program name
334 progname
= strrchr(argv
[0], '/');
335 if (progname
&& progname
[1])
342 am_set_progname(progname
);
345 * Initialize process id. This is kept
346 * cached since it is used for generating
347 * and using file handles.
352 * Get local machine name
354 if (gethostname(hostname
, sizeof(hostname
)) < 0) {
355 plog(XLOG_FATAL
, "gethostname: %m");
358 hostname
[sizeof(hostname
) - 1] = '\0';
361 * Check it makes sense
364 plog(XLOG_FATAL
, "host name is not set");
369 /* initialize debugging flags (Register AMQ, Enter daemon mode) */
370 debug_flags
= D_AMQ
| D_DAEMON
;
374 * Initialize global options structure.
376 init_global_options();
379 * Partially initialize hostd[]. This
380 * is completed in get_args().
382 if ((domdot
= strchr(hostname
, '.'))) {
384 * Hostname already contains domainname.
385 * Split out hostname and domainname
391 strcpy(hostd
, hostname
);
392 am_set_hostname(hostname
);
395 * Trap interrupts for shutdowns.
397 #ifdef HAVE_SIGACTION
398 sa
.sa_handler
= sigterm
;
400 sigemptyset(&(sa
.sa_mask
));
401 sigaddset(&(sa
.sa_mask
), SIGINT
);
402 sigaddset(&(sa
.sa_mask
), SIGTERM
);
403 sigaction(SIGINT
, &sa
, NULL
);
404 sigaction(SIGTERM
, &sa
, NULL
);
405 #else /* not HAVE_SIGACTION */
406 (void) signal(SIGINT
, sigterm
);
407 #endif /* not HAVE_SIGACTION */
410 * Trap Terminate so that we can shutdown gracefully (some chance)
412 #ifdef HAVE_SIGACTION
413 sa
.sa_handler
= sigterm
;
415 sigemptyset(&(sa
.sa_mask
));
416 sigaddset(&(sa
.sa_mask
), SIGTERM
);
417 sigaction(SIGTERM
, &sa
, NULL
);
418 #else /* not HAVE_SIGACTION */
419 (void) signal(SIGTERM
, sigterm
);
420 #endif /* not HAVE_SIGACTION */
423 * Hangups tell us to reload the cache
425 #ifdef HAVE_SIGACTION
426 sa
.sa_handler
= sighup
;
428 sigemptyset(&(sa
.sa_mask
));
429 sigaddset(&(sa
.sa_mask
), SIGHUP
);
430 sigaction(SIGHUP
, &sa
, NULL
);
431 #else /* not HAVE_SIGACTION */
432 (void) signal(SIGHUP
, sighup
);
433 #endif /* not HAVE_SIGACTION */
436 * Trap Death-of-a-child. These allow us to
437 * pick up the exit status of backgrounded mounts.
440 #ifdef HAVE_SIGACTION
441 sa
.sa_handler
= sigchld
;
443 sigemptyset(&(sa
.sa_mask
));
444 sigaddset(&(sa
.sa_mask
), SIGCHLD
);
445 sigaction(SIGCHLD
, &sa
, NULL
);
448 * construct global "masked_sigs" used in nfs_start.c
450 sigemptyset(&masked_sigs
);
451 sigaddset(&masked_sigs
, SIGHUP
);
452 sigaddset(&masked_sigs
, SIGCHLD
);
453 sigaddset(&masked_sigs
, SIGTERM
);
454 sigaddset(&masked_sigs
, SIGINT
);
455 #else /* not HAVE_SIGACTION */
456 (void) signal(SIGCHLD
, sigchld
);
457 #endif /* not HAVE_SIGACTION */
460 * Fix-up any umask problems. Most systems default
461 * to 002 which is not too convenient for our purposes
463 orig_umask
= umask(0);
466 * Figure out primary network name
468 getwire(&PrimNetName
, &PrimNetNum
);
471 * Determine command-line arguments
473 get_args(argc
, argv
);
476 * Log version information.
478 verstr
= strtok(get_version_string(), "\n");
479 plog(XLOG_INFO
, "AM-UTILS VERSION INFORMATION:");
481 plog(XLOG_INFO
, verstr
);
482 verstr
= strtok(NULL
, "\n");
486 * Get our own IP address so that we
487 * can mount the automounter.
489 amu_get_myaddress(&myipaddr
);
490 plog(XLOG_INFO
, "My ip addr is %s", inet_ntoa(myipaddr
));
492 /* avoid hanging on other NFS servers if started elsewhere */
494 plog(XLOG_INFO
, "cannot chdir to /: %m");
497 * Now check we are root.
499 if (geteuid() != 0) {
500 plog(XLOG_FATAL
, "Must be root to mount filesystems (euid = %ld)", (long) geteuid());
505 * Lock process text and data segment in memory.
508 if (gopt
.flags
& CFM_PROCESS_LOCK
) {
511 * On AIX you must lower the stack size using ulimit() before calling
512 * plock. Otherwise plock will reserve a lot of memory space based on
513 * your maximum stack size limit. Since it is not easily possible to
514 * tell what should the limit be, I print a warning before calling
515 * plock(). See the manual pages for ulimit(1,3,4) on your AIX system.
517 plog(XLOG_WARNING
, "AIX: may need to lower stack size using ulimit(3) before calling plock");
519 if (plock(PROCLOCK
) != 0) {
520 plog(XLOG_WARNING
, "Couldn't lock process text and data segment in memory: %m");
522 plog(XLOG_INFO
, "Locked process text and data segment in memory");
525 #endif /* HAVE_PLOCK */
529 * If the domain was specified then bind it here
530 * to circumvent any default bindings that may
531 * be done in the C library.
533 if (gopt
.nis_domain
&& yp_bind(gopt
.nis_domain
)) {
534 plog(XLOG_FATAL
, "Can't bind to NIS domain \"%s\"", gopt
.nis_domain
);
537 #endif /* HAVE_MAP_NIS */
542 ppid
= daemon_mode();
544 sprintf(pid_fsname
, "%s:(pid%ld)", am_get_hostname(), (long) am_mypid
);
546 do_mapc_reload
= clocktime() + ONE_HOUR
;
549 * Register automounter with system.
551 error
= mount_automounter(ppid
);
557 return 1; /* should never get here */