xref: /original-bsd/usr.sbin/amd/amd/amd.c (revision a4dfca06)
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