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 */
sigterm(sig)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*/
sighup(sig)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*/
parent_exit(sig)113 static void parent_exit(sig)
114 int sig;
115 {
116 exit(0);
117 }
118
daemon_mode(P_void)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
main(argc,argv)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