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