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 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * from: @(#)amd.c 8.1 (Berkeley) 6/6/93
35 * $Id: amd.c,v 1.25 2023/07/05 18:45:14 guenther Exp $
36 */
37
38 /*
39 * Automounter
40 */
41
42 #include "am.h"
43 #include <signal.h>
44 #include <sys/ioctl.h>
45 #include <sys/stat.h>
46 #include <fcntl.h>
47 #include <unistd.h>
48 #include <setjmp.h>
49 #include <endian.h>
50
51 #include <rpc/rpc.h>
52 #include <rpcsvc/ypclnt.h>
53 #include <rpcsvc/yp_prot.h>
54
55 #if BYTE_ORDER == LITTLE_ENDIAN
56 #define ARCH_ENDIAN "little"
57 #elif BYTE_ORDER == BIG_ENDIAN
58 #define ARCH_ENDIAN "big"
59 #else
60 #error "unknown endian"
61 #endif
62
63 char pid_fsname[16 + HOST_NAME_MAX+1]; /* "kiska.southseas.nz:(pid%d)" */
64 #ifdef HAS_HOST
65 #ifdef HOST_EXEC
66 char *host_helper;
67 #endif /* HOST_EXEC */
68 #endif /* HAS_HOST */
69 char *auto_dir = "/tmp_mnt";
70 char *hostdomain = "unknown.domain";
71 char hostname[HOST_NAME_MAX+1] = "localhost"; /* Hostname */
72 char hostd[2*(HOST_NAME_MAX+1)]; /* Host+domain */
73 char *op_sys = "bsd44"; /* Name of current op_sys */
74 char *arch = ARCH_REP; /* Name of current architecture */
75 char *endian = ARCH_ENDIAN; /* Big or Little endian */
76 char *wire;
77 int foreground = 1; /* This is the top-level server */
78 pid_t mypid; /* Current process id */
79 volatile sig_atomic_t immediate_abort; /* Should close-down unmounts be retried */
80 struct in_addr myipaddr; /* (An) IP address of this host */
81 serv_state amd_state;
82 struct amd_stats amd_stats; /* Server statistics */
83 time_t do_mapc_reload = 0; /* mapc_reload() call required? */
84 jmp_buf select_intr;
85 int select_intr_valid;
86 int orig_umask;
87
88 /*
89 * Signal handler:
90 * SIGINT - tells amd to do a full shutdown, including unmounting all filesystem.
91 * SIGTERM - tells amd to shutdown now. Just unmounts the automount nodes.
92 */
93 static void
sigterm(int sig)94 sigterm(int sig)
95 {
96
97 switch (sig) {
98 case SIGINT:
99 immediate_abort = 15;
100 break;
101
102 case SIGTERM:
103 immediate_abort = -1;
104 /* fall through... */
105
106 default:
107 plog(XLOG_WARNING, "WARNING: automounter going down on signal %d", sig);
108 break;
109 }
110 if (select_intr_valid)
111 longjmp(select_intr, sig);
112 }
113
114 /*
115 * Hook for cache reload.
116 * When a SIGHUP arrives it schedules a call to mapc_reload
117 */
118 static void
sighup(int sig)119 sighup(int sig)
120 {
121
122 #ifdef DEBUG
123 if (sig != SIGHUP)
124 dlog("spurious call to sighup");
125 #endif /* DEBUG */
126 /*
127 * Force a reload by zero'ing the timer
128 */
129 if (amd_state == Run)
130 do_mapc_reload = 0;
131 }
132
133 static void
parent_exit(int sig)134 parent_exit(int sig)
135 {
136 _exit(0);
137 }
138
139 static pid_t
daemon_mode(void)140 daemon_mode(void)
141 {
142 pid_t bgpid;
143
144 signal(SIGQUIT, parent_exit);
145 bgpid = background();
146
147 if (bgpid != 0) {
148 if (print_pid) {
149 printf("%ld\n", (long)bgpid);
150 fflush(stdout);
151 }
152 /*
153 * Now wait for the automount points to
154 * complete.
155 */
156 for (;;)
157 pause();
158 }
159
160 signal(SIGQUIT, SIG_DFL);
161
162 /*
163 * Pretend we are in the foreground again
164 */
165 foreground = 1;
166
167 #ifdef TIOCNOTTY
168 {
169 int t = open("/dev/tty", O_RDWR);
170 if (t == -1) {
171 if (errno != ENXIO) /* not an error if already no controlling tty */
172 plog(XLOG_WARNING, "Could not open controlling tty: %m");
173 } else {
174 if (ioctl(t, TIOCNOTTY, 0) == -1 && errno != ENOTTY)
175 plog(XLOG_WARNING, "Could not disassociate tty (TIOCNOTTY): %m");
176 (void) close(t);
177 }
178 }
179 #else
180 (void) setpgrp();
181 #endif /* TIOCNOTTY */
182
183 return getppid();
184 }
185
186 int
main(int argc,char * argv[])187 main(int argc, char *argv[])
188 {
189 char *domdot;
190 pid_t ppid = 0;
191 int error;
192
193 logfp = stderr; /* Log errors to stderr initially */
194
195 /*
196 * Make sure some built-in assumptions are true before we start
197 */
198 assert(sizeof(nfscookie) >= sizeof (unsigned int));
199 assert(sizeof(int) >= 4);
200
201 /*
202 * Set processing status.
203 */
204 amd_state = Start;
205
206 /*
207 * Initialise process id. This is kept
208 * cached since it is used for generating
209 * and using file handles.
210 */
211 mypid = getpid();
212
213 /*
214 * Get local machine name
215 */
216 if (gethostname(hostname, sizeof(hostname)) == -1) {
217 plog(XLOG_FATAL, "gethostname: %m");
218 going_down(1);
219 }
220 /*
221 * Check it makes sense
222 */
223 if (!*hostname) {
224 plog(XLOG_FATAL, "host name is not set");
225 going_down(1);
226 }
227 /*
228 * Partially initialise hostd[]. This
229 * is completed in get_args().
230 */
231 if ((domdot = strchr(hostname, '.'))) {
232 /*
233 * Hostname already contains domainname.
234 * Split out hostname and domainname
235 * components
236 */
237 *domdot++ = '\0';
238 hostdomain = domdot;
239 }
240 strlcpy(hostd, hostname, sizeof hostd);
241
242 /*
243 * Trap interrupts for shutdowns.
244 */
245 (void) signal(SIGINT, sigterm);
246
247 /*
248 * Hangups tell us to reload the cache
249 */
250 (void) signal(SIGHUP, sighup);
251
252 /*
253 * Trap Terminate so that we can shutdown gracefully (some chance)
254 */
255 (void) signal(SIGTERM, sigterm);
256 /*
257 * Trap Death-of-a-child. These allow us to
258 * pick up the exit status of backgrounded mounts.
259 * See "sched.c".
260 */
261 (void) signal(SIGCHLD, sigchld);
262
263 /*
264 * Fix-up any umask problems. Most systems default
265 * to 002 which is not too convenient for our purposes
266 */
267 orig_umask = umask(0);
268
269 /*
270 * Figure out primary network name
271 */
272 wire = getwire();
273
274 /*
275 * Determine command-line arguments
276 */
277 get_args(argc, argv);
278
279 if (mkdir(auto_dir, 0755) == -1) {
280 if (errno != EEXIST)
281 plog(XLOG_FATAL, "mkdir(autodir = %s: %m", auto_dir);
282 }
283
284 /*
285 * Get our own IP address so that we
286 * can mount the automounter.
287 */
288 { struct sockaddr_in sin;
289 get_myaddress(&sin);
290 myipaddr.s_addr = sin.sin_addr.s_addr;
291 }
292
293 /*
294 * Now check we are root.
295 */
296 if (geteuid() != 0) {
297 plog(XLOG_FATAL, "Must be root to mount filesystems (euid = %u)", geteuid());
298 going_down(1);
299 }
300
301 /*
302 * If the domain was specified then bind it here
303 * to circumvent any default bindings that may
304 * be done in the C library.
305 */
306 if (domain && yp_bind(domain)) {
307 plog(XLOG_FATAL, "Can't bind to domain \"%s\"", domain);
308 going_down(1);
309 }
310
311 #ifdef DEBUG
312 Debug(D_DAEMON)
313 #endif /* DEBUG */
314 ppid = daemon_mode();
315
316 snprintf(pid_fsname, sizeof(pid_fsname), "%s:(pid%ld)", hostname, (long)mypid);
317
318 do_mapc_reload = clocktime() + ONE_HOUR;
319
320 /*
321 * Register automounter with system
322 */
323 error = mount_automounter(ppid);
324 if (error && ppid)
325 kill(ppid, SIGALRM);
326 going_down(error);
327
328 abort();
329 }
330