xref: /original-bsd/usr.sbin/amd/amd/amd.c (revision c3e32dec)
1 /*
2  * Copyright (c) 1989 Jan-Simon Pendry
3  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
4  * Copyright (c) 1989, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * This code is derived from software contributed to Berkeley by
8  * Jan-Simon Pendry at Imperial College, London.
9  *
10  * %sccs.include.redist.c%
11  *
12  *	@(#)amd.c	8.1 (Berkeley) 06/06/93
13  *
14  * $Id: amd.c,v 5.2.2.1 1992/02/09 15:08:15 jsp beta $
15  *
16  */
17 
18 #ifndef lint
19 static char copyright[] =
20 "@(#) Copyright (c) 1989, 1993\n\
21 	The Regents of the University of California.  All rights reserved.\n";
22 #endif /* not lint */
23 
24 /*
25  * Automounter
26  */
27 
28 #include "am.h"
29 #include <sys/signal.h>
30 #include <sys/ioctl.h>
31 #include <fcntl.h>
32 #include <setjmp.h>
33 
34 char pid_fsname[16 + MAXHOSTNAMELEN];	/* "kiska.southseas.nz:(pid%d)" */
35 char *progname;				/* "amd" */
36 #ifdef HAS_HOST
37 #ifdef HOST_EXEC
38 char *host_helper;
39 #endif /* HOST_EXEC */
40 #endif /* HAS_HOST */
41 char *auto_dir = "/a";
42 char *hostdomain = "unknown.domain";
43 char hostname[MAXHOSTNAMELEN] = "localhost"; /* Hostname */
44 char hostd[2*MAXHOSTNAMELEN];		/* Host+domain */
45 char *op_sys = OS_REP;			/* Name of current op_sys */
46 char *arch = ARCH_REP;			/* Name of current architecture */
47 char *endian = ARCH_ENDIAN;		/* Big or Little endian */
48 char *wire;
49 int foreground = 1;			/* This is the top-level server */
50 int mypid;				/* Current process id */
51 int immediate_abort;			/* Should close-down unmounts be retried */
52 struct in_addr myipaddr;		/* (An) IP address of this host */
53 serv_state amd_state;
54 struct amd_stats amd_stats;		/* Server statistics */
55 time_t do_mapc_reload = 0;		/* mapc_reload() call required? */
56 jmp_buf select_intr;
57 int select_intr_valid;
58 int orig_umask;
59 
60 /*
61  * Signal handler:
62  * SIGINT - tells amd to do a full shutdown, including unmounting all filesystem.
63  * SIGTERM - tells amd to shutdown now.  Just unmounts the automount nodes.
64  */
65 static void sigterm(sig)
66 int sig;
67 {
68 #ifdef SYS5_SIGNALS
69 	signal(sig, sigterm);
70 #endif /* SYS5_SIGNALS */
71 
72 	switch (sig) {
73 	case SIGINT:
74 		immediate_abort = 15;
75 		break;
76 
77 	case SIGTERM:
78 		immediate_abort = -1;
79 		/* fall through... */
80 
81 	default:
82 		plog(XLOG_WARNING, "WARNING: automounter going down on signal %d", sig);
83 		break;
84 	}
85 	if (select_intr_valid)
86 		longjmp(select_intr, sig);
87 }
88 
89 /*
90  * Hook for cache reload.
91  * When a SIGHUP arrives it schedules a call to mapc_reload
92  */
93 /*ARGSUSED*/
94 static void sighup(sig)
95 int sig;
96 {
97 #ifdef SYS5_SIGNALS
98 	signal(sig, sighup);
99 #endif /* SYS5_SIGNALS */
100 
101 #ifdef DEBUG
102 	if (sig != SIGHUP)
103 		dlog("spurious call to sighup");
104 #endif /* DEBUG */
105 	/*
106 	 * Force a reload by zero'ing the timer
107 	 */
108 	if (amd_state == Run)
109 		do_mapc_reload = 0;
110 }
111 
112 /*ARGSUSED*/
113 static void parent_exit(sig)
114 int sig;
115 {
116 	exit(0);
117 }
118 
119 static int daemon_mode(P_void)
120 {
121 	int bgpid;
122 
123 	signal(SIGQUIT, parent_exit);
124 	bgpid = background();
125 
126 	if (bgpid != 0) {
127 		if (print_pid) {
128 			printf("%d\n", bgpid);
129 			fflush(stdout);
130 		}
131 		/*
132 		 * Now wait for the automount points to
133 		 * complete.
134 		 */
135 		for (;;)
136 			pause();
137 	}
138 
139 	signal(SIGQUIT, SIG_DFL);
140 
141 	/*
142 	 * Pretend we are in the foreground again
143 	 */
144 	foreground = 1;
145 
146 #ifdef TIOCNOTTY
147 	{
148 		int t = open("/dev/tty", O_RDWR);
149 		if (t < 0) {
150 			if (errno != ENXIO)	/* not an error if already no controlling tty */
151 				plog(XLOG_WARNING, "Could not open controlling tty: %m");
152 		} else {
153 			if (ioctl(t, TIOCNOTTY, 0) < 0 && errno != ENOTTY)
154 				plog(XLOG_WARNING, "Could not disassociate tty (TIOCNOTTY): %m");
155 			(void) close(t);
156 		}
157 	}
158 #else
159 	(void) setpgrp();
160 #endif /* TIOCNOTTY */
161 
162 	return getppid();
163 }
164 
165 main(argc, argv)
166 int argc;
167 char *argv[];
168 {
169 	char *domdot;
170 	int ppid = 0;
171 	int error;
172 
173 	/*
174 	 * Make sure some built-in assumptions are true before we start
175 	 */
176 	assert(sizeof(nfscookie) >= sizeof (unsigned int));
177 	assert(sizeof(int) >= 4);
178 
179 	/*
180 	 * Set processing status.
181 	 */
182 	amd_state = Start;
183 
184 	/*
185 	 * Determine program name
186 	 */
187 	if (argv[0]) {
188 		progname = strrchr(argv[0], '/');
189 		if (progname && progname[1])
190 			progname++;
191 		else
192 			progname = argv[0];
193 	}
194 
195 	if (!progname)
196 		progname = "amd";
197 
198 	/*
199 	 * Initialise process id.  This is kept
200 	 * cached since it is used for generating
201 	 * and using file handles.
202 	 */
203 	mypid = getpid();
204 
205 	/*
206 	 * Get local machine name
207 	 */
208 	if (gethostname(hostname, sizeof(hostname)) < 0) {
209 		plog(XLOG_FATAL, "gethostname: %m");
210 		going_down(1);
211 	}
212 	/*
213 	 * Check it makes sense
214 	 */
215 	if (!*hostname) {
216 		plog(XLOG_FATAL, "host name is not set");
217 		going_down(1);
218 	}
219 	/*
220 	 * Partially initialise hostd[].  This
221 	 * is completed in get_args().
222 	 */
223 	if (domdot = strchr(hostname, '.')) {
224 		/*
225 		 * Hostname already contains domainname.
226 		 * Split out hostname and domainname
227 		 * components
228 		 */
229 		*domdot++ = '\0';
230 		hostdomain = domdot;
231 	}
232 	strcpy(hostd, hostname);
233 
234 	/*
235 	 * Trap interrupts for shutdowns.
236 	 */
237 	(void) signal(SIGINT, sigterm);
238 
239 	/*
240 	 * Hangups tell us to reload the cache
241 	 */
242 	(void) signal(SIGHUP, sighup);
243 
244 	/*
245 	 * Trap Terminate so that we can shutdown gracefully (some chance)
246 	 */
247 	(void) signal(SIGTERM, sigterm);
248 	/*
249 	 * Trap Death-of-a-child.  These allow us to
250 	 * pick up the exit status of backgrounded mounts.
251 	 * See "sched.c".
252 	 */
253 	(void) signal(SIGCHLD, sigchld);
254 
255 	/*
256 	 * Fix-up any umask problems.  Most systems default
257 	 * to 002 which is not too convenient for our purposes
258 	 */
259 	orig_umask = umask(0);
260 
261 	/*
262 	 * Figure out primary network name
263 	 */
264 	wire = getwire();
265 
266 	/*
267 	 * Determine command-line arguments
268 	 */
269 	get_args(argc, argv);
270 
271 	/*
272 	 * Get our own IP address so that we
273 	 * can mount the automounter.
274 	 */
275 	{ struct sockaddr_in sin;
276 	  get_myaddress(&sin);
277 	  myipaddr.s_addr = sin.sin_addr.s_addr;
278 	}
279 
280 	/*
281 	 * Now check we are root.
282 	 */
283 	if (geteuid() != 0) {
284 		plog(XLOG_FATAL, "Must be root to mount filesystems (euid = %d)", geteuid());
285 		going_down(1);
286 	}
287 
288 #ifdef HAS_NIS_MAPS
289 	/*
290 	 * If the domain was specified then bind it here
291 	 * to circumvent any default bindings that may
292 	 * be done in the C library.
293 	 */
294 	if (domain && yp_bind(domain)) {
295 		plog(XLOG_FATAL, "Can't bind to domain \"%s\"", domain);
296 		going_down(1);
297 	}
298 #endif /* HAS_NIS_MAPS */
299 
300 #ifdef DEBUG
301 	Debug(D_DAEMON)
302 #endif /* DEBUG */
303 	ppid = daemon_mode();
304 
305 	sprintf(pid_fsname, "%s:(pid%d)", hostname, mypid);
306 
307 	do_mapc_reload = clocktime() + ONE_HOUR;
308 
309 	/*
310 	 * Register automounter with system
311 	 */
312 	error = mount_automounter(ppid);
313 	if (error && ppid)
314 		kill(SIGALRM, ppid);
315 	going_down(error);
316 
317 	abort();
318 }
319