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