1398a5aebSmckusick /*
2398a5aebSmckusick * Copyright (c) 1989 Jan-Simon Pendry
3398a5aebSmckusick * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
4*a4dfca06Sbostic * Copyright (c) 1989, 1993
5*a4dfca06Sbostic * The Regents of the University of California. All rights reserved.
6398a5aebSmckusick *
7398a5aebSmckusick * This code is derived from software contributed to Berkeley by
8398a5aebSmckusick * Jan-Simon Pendry at Imperial College, London.
9398a5aebSmckusick *
10398a5aebSmckusick * %sccs.include.redist.c%
11398a5aebSmckusick *
12*a4dfca06Sbostic * @(#)amd.c 8.1 (Berkeley) 06/06/93
13c626267eSpendry *
14cc0207dcSpendry * $Id: amd.c,v 5.2.2.1 1992/02/09 15:08:15 jsp beta $
15c626267eSpendry *
16398a5aebSmckusick */
17398a5aebSmckusick
183d8714deSbostic #ifndef lint
19*a4dfca06Sbostic static char copyright[] =
20*a4dfca06Sbostic "@(#) Copyright (c) 1989, 1993\n\
21*a4dfca06Sbostic The Regents of the University of California. All rights reserved.\n";
223d8714deSbostic #endif /* not lint */
233d8714deSbostic
24398a5aebSmckusick /*
25398a5aebSmckusick * Automounter
26398a5aebSmckusick */
27398a5aebSmckusick
28398a5aebSmckusick #include "am.h"
29398a5aebSmckusick #include <sys/signal.h>
30398a5aebSmckusick #include <sys/ioctl.h>
31398a5aebSmckusick #include <fcntl.h>
32398a5aebSmckusick #include <setjmp.h>
33398a5aebSmckusick
34398a5aebSmckusick char pid_fsname[16 + MAXHOSTNAMELEN]; /* "kiska.southseas.nz:(pid%d)" */
35398a5aebSmckusick char *progname; /* "amd" */
36398a5aebSmckusick #ifdef HAS_HOST
378a89c22cSpendry #ifdef HOST_EXEC
38398a5aebSmckusick char *host_helper;
398a89c22cSpendry #endif /* HOST_EXEC */
40398a5aebSmckusick #endif /* HAS_HOST */
41398a5aebSmckusick char *auto_dir = "/a";
42398a5aebSmckusick char *hostdomain = "unknown.domain";
438a89c22cSpendry char hostname[MAXHOSTNAMELEN] = "localhost"; /* Hostname */
44398a5aebSmckusick char hostd[2*MAXHOSTNAMELEN]; /* Host+domain */
45398a5aebSmckusick char *op_sys = OS_REP; /* Name of current op_sys */
46398a5aebSmckusick char *arch = ARCH_REP; /* Name of current architecture */
47398a5aebSmckusick char *endian = ARCH_ENDIAN; /* Big or Little endian */
488a89c22cSpendry char *wire;
49398a5aebSmckusick int foreground = 1; /* This is the top-level server */
50398a5aebSmckusick int mypid; /* Current process id */
51398a5aebSmckusick int immediate_abort; /* Should close-down unmounts be retried */
52398a5aebSmckusick struct in_addr myipaddr; /* (An) IP address of this host */
538a89c22cSpendry serv_state amd_state;
54398a5aebSmckusick struct amd_stats amd_stats; /* Server statistics */
55398a5aebSmckusick time_t do_mapc_reload = 0; /* mapc_reload() call required? */
56398a5aebSmckusick jmp_buf select_intr;
57398a5aebSmckusick int select_intr_valid;
58398a5aebSmckusick int orig_umask;
59398a5aebSmckusick
60398a5aebSmckusick /*
61398a5aebSmckusick * Signal handler:
62398a5aebSmckusick * SIGINT - tells amd to do a full shutdown, including unmounting all filesystem.
63398a5aebSmckusick * SIGTERM - tells amd to shutdown now. Just unmounts the automount nodes.
64398a5aebSmckusick */
sigterm(sig)65398a5aebSmckusick static void sigterm(sig)
66398a5aebSmckusick int sig;
67398a5aebSmckusick {
68398a5aebSmckusick #ifdef SYS5_SIGNALS
69398a5aebSmckusick signal(sig, sigterm);
708a89c22cSpendry #endif /* SYS5_SIGNALS */
71398a5aebSmckusick
72398a5aebSmckusick switch (sig) {
73398a5aebSmckusick case SIGINT:
74398a5aebSmckusick immediate_abort = 15;
75398a5aebSmckusick break;
76398a5aebSmckusick
77398a5aebSmckusick case SIGTERM:
78398a5aebSmckusick immediate_abort = -1;
79398a5aebSmckusick /* fall through... */
80398a5aebSmckusick
81398a5aebSmckusick default:
82398a5aebSmckusick plog(XLOG_WARNING, "WARNING: automounter going down on signal %d", sig);
83398a5aebSmckusick break;
84398a5aebSmckusick }
85398a5aebSmckusick if (select_intr_valid)
86398a5aebSmckusick longjmp(select_intr, sig);
87398a5aebSmckusick }
88398a5aebSmckusick
89398a5aebSmckusick /*
90398a5aebSmckusick * Hook for cache reload.
91398a5aebSmckusick * When a SIGHUP arrives it schedules a call to mapc_reload
92398a5aebSmckusick */
938a89c22cSpendry /*ARGSUSED*/
sighup(sig)94398a5aebSmckusick static void sighup(sig)
95398a5aebSmckusick int sig;
96398a5aebSmckusick {
97398a5aebSmckusick #ifdef SYS5_SIGNALS
98398a5aebSmckusick signal(sig, sighup);
998a89c22cSpendry #endif /* SYS5_SIGNALS */
100398a5aebSmckusick
101398a5aebSmckusick #ifdef DEBUG
102398a5aebSmckusick if (sig != SIGHUP)
103398a5aebSmckusick dlog("spurious call to sighup");
104398a5aebSmckusick #endif /* DEBUG */
105398a5aebSmckusick /*
106398a5aebSmckusick * Force a reload by zero'ing the timer
107398a5aebSmckusick */
108398a5aebSmckusick if (amd_state == Run)
109398a5aebSmckusick do_mapc_reload = 0;
110398a5aebSmckusick }
111398a5aebSmckusick
1128a89c22cSpendry /*ARGSUSED*/
parent_exit(sig)113398a5aebSmckusick static void parent_exit(sig)
114398a5aebSmckusick int sig;
115398a5aebSmckusick {
116398a5aebSmckusick exit(0);
117398a5aebSmckusick }
118398a5aebSmckusick
daemon_mode(P_void)119398a5aebSmckusick static int daemon_mode(P_void)
120398a5aebSmckusick {
1218a89c22cSpendry int bgpid;
1228a89c22cSpendry
1238a89c22cSpendry signal(SIGQUIT, parent_exit);
1248a89c22cSpendry bgpid = background();
125398a5aebSmckusick
126398a5aebSmckusick if (bgpid != 0) {
127398a5aebSmckusick if (print_pid) {
128398a5aebSmckusick printf("%d\n", bgpid);
129398a5aebSmckusick fflush(stdout);
130398a5aebSmckusick }
131398a5aebSmckusick /*
132398a5aebSmckusick * Now wait for the automount points to
133398a5aebSmckusick * complete.
134398a5aebSmckusick */
135398a5aebSmckusick for (;;)
136398a5aebSmckusick pause();
137398a5aebSmckusick }
138398a5aebSmckusick
1398a89c22cSpendry signal(SIGQUIT, SIG_DFL);
1408a89c22cSpendry
141398a5aebSmckusick /*
142398a5aebSmckusick * Pretend we are in the foreground again
143398a5aebSmckusick */
144398a5aebSmckusick foreground = 1;
1458a89c22cSpendry
146398a5aebSmckusick #ifdef TIOCNOTTY
147398a5aebSmckusick {
148398a5aebSmckusick int t = open("/dev/tty", O_RDWR);
149398a5aebSmckusick if (t < 0) {
150398a5aebSmckusick if (errno != ENXIO) /* not an error if already no controlling tty */
151398a5aebSmckusick plog(XLOG_WARNING, "Could not open controlling tty: %m");
1528a89c22cSpendry } else {
1538a89c22cSpendry if (ioctl(t, TIOCNOTTY, 0) < 0 && errno != ENOTTY)
154398a5aebSmckusick plog(XLOG_WARNING, "Could not disassociate tty (TIOCNOTTY): %m");
1558a89c22cSpendry (void) close(t);
156398a5aebSmckusick }
157398a5aebSmckusick }
158398a5aebSmckusick #else
159398a5aebSmckusick (void) setpgrp();
160398a5aebSmckusick #endif /* TIOCNOTTY */
161398a5aebSmckusick
162398a5aebSmckusick return getppid();
163398a5aebSmckusick }
164398a5aebSmckusick
main(argc,argv)165398a5aebSmckusick main(argc, argv)
166398a5aebSmckusick int argc;
167398a5aebSmckusick char *argv[];
168398a5aebSmckusick {
169398a5aebSmckusick char *domdot;
170398a5aebSmckusick int ppid = 0;
171398a5aebSmckusick int error;
172398a5aebSmckusick
173398a5aebSmckusick /*
174398a5aebSmckusick * Make sure some built-in assumptions are true before we start
175398a5aebSmckusick */
176398a5aebSmckusick assert(sizeof(nfscookie) >= sizeof (unsigned int));
177398a5aebSmckusick assert(sizeof(int) >= 4);
178398a5aebSmckusick
179398a5aebSmckusick /*
180398a5aebSmckusick * Set processing status.
181398a5aebSmckusick */
182398a5aebSmckusick amd_state = Start;
183398a5aebSmckusick
184398a5aebSmckusick /*
1858a89c22cSpendry * Determine program name
1868a89c22cSpendry */
1878a89c22cSpendry if (argv[0]) {
1888a89c22cSpendry progname = strrchr(argv[0], '/');
1898a89c22cSpendry if (progname && progname[1])
1908a89c22cSpendry progname++;
1918a89c22cSpendry else
1928a89c22cSpendry progname = argv[0];
1938a89c22cSpendry }
1948a89c22cSpendry
1958a89c22cSpendry if (!progname)
1968a89c22cSpendry progname = "amd";
1978a89c22cSpendry
1988a89c22cSpendry /*
1998a89c22cSpendry * Initialise process id. This is kept
2008a89c22cSpendry * cached since it is used for generating
2018a89c22cSpendry * and using file handles.
2028a89c22cSpendry */
2038a89c22cSpendry mypid = getpid();
2048a89c22cSpendry
2058a89c22cSpendry /*
206398a5aebSmckusick * Get local machine name
207398a5aebSmckusick */
208398a5aebSmckusick if (gethostname(hostname, sizeof(hostname)) < 0) {
209398a5aebSmckusick plog(XLOG_FATAL, "gethostname: %m");
210398a5aebSmckusick going_down(1);
211398a5aebSmckusick }
212398a5aebSmckusick /*
213398a5aebSmckusick * Check it makes sense
214398a5aebSmckusick */
215398a5aebSmckusick if (!*hostname) {
216398a5aebSmckusick plog(XLOG_FATAL, "host name is not set");
217398a5aebSmckusick going_down(1);
218398a5aebSmckusick }
219398a5aebSmckusick /*
220398a5aebSmckusick * Partially initialise hostd[]. This
221398a5aebSmckusick * is completed in get_args().
222398a5aebSmckusick */
223398a5aebSmckusick if (domdot = strchr(hostname, '.')) {
224398a5aebSmckusick /*
225398a5aebSmckusick * Hostname already contains domainname.
226398a5aebSmckusick * Split out hostname and domainname
227398a5aebSmckusick * components
228398a5aebSmckusick */
229398a5aebSmckusick *domdot++ = '\0';
230398a5aebSmckusick hostdomain = domdot;
231398a5aebSmckusick }
232398a5aebSmckusick strcpy(hostd, hostname);
233398a5aebSmckusick
234398a5aebSmckusick /*
235398a5aebSmckusick * Trap interrupts for shutdowns.
236398a5aebSmckusick */
237398a5aebSmckusick (void) signal(SIGINT, sigterm);
238398a5aebSmckusick
239398a5aebSmckusick /*
240398a5aebSmckusick * Hangups tell us to reload the cache
241398a5aebSmckusick */
242398a5aebSmckusick (void) signal(SIGHUP, sighup);
243398a5aebSmckusick
244398a5aebSmckusick /*
245398a5aebSmckusick * Trap Terminate so that we can shutdown gracefully (some chance)
246398a5aebSmckusick */
247398a5aebSmckusick (void) signal(SIGTERM, sigterm);
248398a5aebSmckusick /*
249398a5aebSmckusick * Trap Death-of-a-child. These allow us to
250398a5aebSmckusick * pick up the exit status of backgrounded mounts.
251398a5aebSmckusick * See "sched.c".
252398a5aebSmckusick */
253398a5aebSmckusick (void) signal(SIGCHLD, sigchld);
254398a5aebSmckusick
255398a5aebSmckusick /*
256398a5aebSmckusick * Fix-up any umask problems. Most systems default
257398a5aebSmckusick * to 002 which is not too convenient for our purposes
258398a5aebSmckusick */
259398a5aebSmckusick orig_umask = umask(0);
260398a5aebSmckusick
261398a5aebSmckusick /*
2628a89c22cSpendry * Figure out primary network name
2638a89c22cSpendry */
2648a89c22cSpendry wire = getwire();
2658a89c22cSpendry
2668a89c22cSpendry /*
267398a5aebSmckusick * Determine command-line arguments
268398a5aebSmckusick */
269398a5aebSmckusick get_args(argc, argv);
270398a5aebSmckusick
271398a5aebSmckusick /*
272398a5aebSmckusick * Get our own IP address so that we
2738a89c22cSpendry * can mount the automounter.
274398a5aebSmckusick */
2758a89c22cSpendry { struct sockaddr_in sin;
2768a89c22cSpendry get_myaddress(&sin);
2778a89c22cSpendry myipaddr.s_addr = sin.sin_addr.s_addr;
278398a5aebSmckusick }
279398a5aebSmckusick
280398a5aebSmckusick /*
281398a5aebSmckusick * Now check we are root.
282398a5aebSmckusick */
283398a5aebSmckusick if (geteuid() != 0) {
284398a5aebSmckusick plog(XLOG_FATAL, "Must be root to mount filesystems (euid = %d)", geteuid());
285398a5aebSmckusick going_down(1);
286398a5aebSmckusick }
287398a5aebSmckusick
288398a5aebSmckusick #ifdef HAS_NIS_MAPS
289398a5aebSmckusick /*
290398a5aebSmckusick * If the domain was specified then bind it here
291398a5aebSmckusick * to circumvent any default bindings that may
292398a5aebSmckusick * be done in the C library.
293398a5aebSmckusick */
294398a5aebSmckusick if (domain && yp_bind(domain)) {
295398a5aebSmckusick plog(XLOG_FATAL, "Can't bind to domain \"%s\"", domain);
296398a5aebSmckusick going_down(1);
297398a5aebSmckusick }
298398a5aebSmckusick #endif /* HAS_NIS_MAPS */
299398a5aebSmckusick
300398a5aebSmckusick #ifdef DEBUG
301398a5aebSmckusick Debug(D_DAEMON)
302398a5aebSmckusick #endif /* DEBUG */
303398a5aebSmckusick ppid = daemon_mode();
304398a5aebSmckusick
305398a5aebSmckusick sprintf(pid_fsname, "%s:(pid%d)", hostname, mypid);
306398a5aebSmckusick
307398a5aebSmckusick do_mapc_reload = clocktime() + ONE_HOUR;
308398a5aebSmckusick
309398a5aebSmckusick /*
310398a5aebSmckusick * Register automounter with system
311398a5aebSmckusick */
312398a5aebSmckusick error = mount_automounter(ppid);
313398a5aebSmckusick if (error && ppid)
314398a5aebSmckusick kill(SIGALRM, ppid);
315398a5aebSmckusick going_down(error);
316398a5aebSmckusick
317398a5aebSmckusick abort();
318398a5aebSmckusick }
319