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