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