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