2 * Copyright (c) 1997-1999 Erez Zadok
3 * Copyright (c) 1989 Jan-Simon Pendry
4 * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1989 The Regents of the University of California.
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgment:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 * $Id: hlfsd.c,v 1.5 1999/09/08 23:36:51 ezk Exp $
42 * $FreeBSD: src/contrib/amd/hlfsd/hlfsd.c,v 1.5 1999/09/15 05:45:15 obrien Exp $
44 * HLFSD was written at Columbia University Computer Science Department, by
45 * Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
46 * It is being distributed under the same terms and conditions as amd does.
51 #endif /* HAVE_CONFIG_H */
58 static RETSIGTYPE proceed(int);
59 static RETSIGTYPE reaper(int);
60 static RETSIGTYPE reload(int);
61 static char *hlfs_group = DEFAULT_HLFS_GROUP;
62 static char default_dir_name[] = DEFAULT_DIRNAME;
63 static char *dir_name = default_dir_name;
64 static int printpid = 0;
65 static int stoplight = 0;
66 static void hlfsd_init(void);
67 static void usage(void);
69 static struct itimerval reloadinterval = {
70 {DEFAULT_INTERVAL, 0},
75 * default mount options.
77 static char default_mntopts[] = "ro,noac";
83 char *alt_spooldir = ALT_SPOOLDIR;
84 char *home_subdir = HOME_SUBDIR;
85 char *logfile = DEFAULT_LOGFILE;
86 char *passwdfile = NULL; /* alternate passwd file to use */
88 char hostname[MAXHOSTNAMELEN + 1] = "localhost";
89 int cache_interval = DEFAULT_CACHE_INTERVAL;
90 gid_t hlfs_gid = (gid_t) INVALIDID;
98 /* symbol must be available always */
99 #ifdef MOUNT_TABLE_ON_FILE
100 char *mnttab_file_name = MNTTAB_FILE_NAME;
101 #else /* not MOUNT_TABLE_ON_FILE */
102 char *mnttab_file_name = NULL;
103 #endif /* not MOUNT_TABLE_ON_FILE */
105 /* forward declarations */
106 void hlfsd_going_down(int rc);
113 "Usage: %s [-Cfhnpv] [-a altdir] [-c cache-interval] [-g group]\n",
115 fprintf(stderr, "\t[-i interval] [-l logfile] [-o mntopts] [-P passwdfile]\n");
116 show_opts('x', xlog_opt);
118 show_opts('D', dbg_opt);
120 fprintf(stderr, "\t[dir_name [subdir]]\n");
126 main(int argc, char *argv[])
129 char *mntopts = (char *) NULL;
130 char hostpid_fs[MAXHOSTNAMELEN + 1 + 16]; /* room for ":(pid###)" */
131 char progpid_fs[PROGNAMESZ + 1 + 11]; /* room for ":pid" */
140 int soNFS; /* NFS socket */
145 struct dirent *direntry;
149 MTYPE_TYPE type = MOUNT_TYPE_NFS;
151 #ifdef HAVE_SIGACTION
153 #endif /* not HAVE_SIGACTION */
155 #ifndef HAVE_TRANSPORT_TYPE_TLI
156 struct sockaddr_in localsocket;
157 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
160 /* get program name and truncate so we don't overflow progpid_fs */
162 if ((progname = strrchr(argv[0], '/')) != NULL)
166 if ((int) strlen(progname) > PROGNAMESZ) /* truncate to reasonable size */
167 progname[PROGNAMESZ] = '\0';
168 am_set_progname(progname);
170 while ((opt = getopt(argc, argv, "a:c:CD:fg:hi:l:no:pP:x:v")) != -1)
174 if (!optarg || optarg[0] != '/') {
175 printf("%s: invalid directory for -a: %s\n",
176 am_get_progname(), optarg);
179 alt_spooldir = optarg;
184 printf("%s: invalid interval for -c: %s\n",
185 am_get_progname(), optarg);
188 cache_interval = atoi(optarg);
205 printf("%s: invalid interval for -i: %s\n",
206 am_get_progname(), optarg);
209 reloadinterval.it_interval.tv_sec = atoi(optarg);
210 reloadinterval.it_value.tv_sec = atoi(optarg);
234 fprintf(stderr, "%s\n", HLFSD_VERSION);
238 opterrs += switch_option(optarg);
243 opterrs += debug_option(optarg);
244 #else /* not DEBUG */
245 fprintf(stderr, "%s: not compiled with DEBUG -- sorry.\n", am_get_progname());
246 #endif /* not DEBUG */
254 /* set some default debugging options */
255 if (xlog_level_init == ~0)
257 /* need my pid before any dlog/plog */
260 switch_option("debug");
264 * Terminate if did not ask to forcecache (-C) and hlfsd would not be able
265 * to set the minimum cache intervals.
267 #if !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_FIELD_NFS_ARGS_T_ACREGMIN)
269 fprintf(stderr, "%s: will not be able to turn off attribute caches.\n", am_get_progname());
272 #endif /* !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_FIELD_NFS_ARGS_T_ACREGMIN) */
275 switch (argc - optind) {
277 home_subdir = argv[optind + 1];
279 dir_name = argv[optind];
289 /* ensure that only root can run hlfsd */
291 fprintf(stderr, "hlfsd can only be run as root\n");
294 setbuf(stdout, (char *) NULL);
297 /* find gid for hlfs_group */
298 if ((grp = getgrnam(hlfs_group)) == (struct group *) NULL) {
299 fprintf(stderr, "%s: cannot get gid for group \"%s\".\n",
300 am_get_progname(), hlfs_group);
302 hlfs_gid = grp->gr_gid;
305 /* get hostname for logging and open log before we reset umask */
306 gethostname(hostname, sizeof(hostname));
307 hostname[sizeof(hostname) - 1] = '\0';
308 if ((dot = strchr(hostname, '.')) != NULL)
310 orig_umask = umask(0);
312 switch_to_logfile(logfile, orig_umask);
314 #if defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE)
315 if (debug_flags & D_MTAB)
316 dlog("-D mtab option ignored");
317 #endif /* defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE) */
319 /* avoid hanging on other NFS servers if started elsewhere */
321 fatal("cannot chdir to /: %m");
324 fatal("must be root to mount filesystems");
327 * dir_name must match "^(/.*)/([^/]+)$", and is split at last '/' with
328 * slinkname = `basename $dir_name` - requires dir_name be writable
331 if (dir_name[0] != '/'
332 || ((slinkname = strrchr(dir_name, '/')), *slinkname++ = '\0',
333 (dir_name[0] == '\0' || slinkname[0] == '\0'))) {
336 printf("%s: invalid mount directory/link %s\n",
337 am_get_progname(), dir_name);
341 clock_valid = 0; /* invalidate logging clock */
344 /* make sure mount point exists and is at least mode 555 */
345 if (stat(dir_name, &stmodes) < 0)
346 if (errno != ENOENT || mkdirs(dir_name, 0555) < 0
347 || stat(dir_name, &stmodes) < 0)
348 fatalerror(dir_name);
350 if ((stmodes.st_mode & 0555) != 0555) {
351 fprintf(stderr, "%s: directory %s not read/executable\n",
352 am_get_progname(), dir_name);
353 plog(XLOG_WARNING, "directory %s not read/executable",
357 /* warn if extraneous stuff will be hidden by mount */
358 if ((mountdir = opendir(dir_name)) == NULL)
359 fatalerror(dir_name);
361 while ((direntry = readdir(mountdir)) != NULL) {
362 if (!NSTREQ(".", direntry->d_name, NAMLEN(direntry)) &&
363 !NSTREQ("..", direntry->d_name, NAMLEN(direntry)) &&
364 !NSTREQ(slinkname, direntry->d_name, NAMLEN(direntry)))
368 if (direntry != NULL) {
369 fprintf(stderr, "%s: %s/%s will be hidden by mount\n",
370 am_get_progname(), dir_name, direntry->d_name);
371 plog(XLOG_WARNING, "%s/%s will be hidden by mount\n",
372 dir_name, direntry->d_name);
376 /* make sure alternate spool dir exists */
377 if ((errno = mkdirs(alt_spooldir, OPEN_SPOOLMODE))) {
378 fprintf(stderr, "%s: cannot create alternate dir ",
380 perror(alt_spooldir);
381 plog(XLOG_ERROR, "cannot create alternate dir %s: %m",
384 chmod(alt_spooldir, OPEN_SPOOLMODE);
386 /* create failsafe link to alternate spool directory */
387 slinkname[-1] = '/'; /* unsplit dir_name to include link */
388 if (lstat(dir_name, &stmodes) == 0 &&
389 (stmodes.st_mode & S_IFMT) != S_IFLNK) {
390 fprintf(stderr, "%s: failsafe %s not a symlink\n",
391 am_get_progname(), dir_name);
392 plog(XLOG_WARNING, "failsafe %s not a symlink\n",
397 if (symlink(alt_spooldir, dir_name) < 0) {
399 "%s: cannot create failsafe symlink %s -> ",
400 am_get_progname(), dir_name);
401 perror(alt_spooldir);
403 "cannot create failsafe symlink %s -> %s: %m",
404 dir_name, alt_spooldir);
408 slinkname[-1] = '\0'; /* resplit dir_name */
409 } /* end of "if (!forcefast) {" */
412 * Register hlfsd as an nfs service with the portmapper.
414 #ifdef HAVE_TRANSPORT_TYPE_TLI
415 ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
416 #else /* not HAVE_TRANSPORT_TYPE_TLI */
417 ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
418 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
420 fatal("cannot create NFS service");
422 #ifdef HAVE_SIGACTION
423 sa.sa_handler = proceed;
425 sigemptyset(&(sa.sa_mask));
426 sigaddset(&(sa.sa_mask), SIGUSR2);
427 sigaction(SIGUSR2, &sa, NULL);
428 #else /* not HAVE_SIGACTION */
429 signal(SIGUSR2, proceed);
430 #endif /* not HAVE_SIGACTION */
432 plog(XLOG_INFO, "Initializing hlfsd...");
433 hlfsd_init(); /* start up child (forking) to run svc_run */
435 #ifdef HAVE_SIGACTION
436 sa.sa_handler = reaper;
438 sigemptyset(&(sa.sa_mask));
439 sigaddset(&(sa.sa_mask), SIGCHLD);
440 sigaction(SIGCHLD, &sa, NULL);
441 #else /* not HAVE_SIGACTION */
442 signal(SIGCHLD, reaper);
443 #endif /* not HAVE_SIGACTION */
447 * In the parent, if -D nodaemon (or -D daemon) , we don't need to
448 * set this signal handler.
452 /* XXX: port to use pure svr4 signals */
454 while (stoplight != SIGUSR2) {
455 plog(XLOG_INFO, "parent waits for child to setup (stoplight=%d)", stoplight);
456 s = sigpause(0); /* wait for child to set up */
464 * setup options to mount table (/etc/{mtab,mnttab}) entry
466 sprintf(hostpid_fs, "%s:(pid%d)", hostname, masterpid);
467 memset((char *) &mnt, 0, sizeof(mnt));
468 mnt.mnt_dir = dir_name; /* i.e., "/mail" */
469 mnt.mnt_fsname = hostpid_fs;
471 mnt.mnt_opts = mntopts;
473 strcpy(preopts, default_mntopts);
475 * Turn off all kinds of attribute and symlink caches as
476 * much as possible. Also make sure that mount does not
479 #ifdef MNTTAB_OPT_INTR
480 strcat(preopts, ",");
481 strcat(preopts, MNTTAB_OPT_INTR);
482 #endif /* MNTTAB_OPT_INTR */
483 #ifdef MNTTAB_OPT_IGNORE
484 strcat(preopts, ",");
485 strcat(preopts, MNTTAB_OPT_IGNORE);
486 #endif /* MNTTAB_OPT_IGNORE */
487 #ifdef MNT2_GEN_OPT_CACHE
488 strcat(preopts, ",nocache");
489 #endif /* MNT2_GEN_OPT_CACHE */
490 #ifdef MNT2_NFS_OPT_SYMTTL
491 strcat(preopts, ",symttl=0");
492 #endif /* MNT2_NFS_OPT_SYMTTL */
493 mnt.mnt_opts = preopts;
497 * Make sure that amd's top-level NFS mounts are hidden by default
499 * If they don't appear to support the either the "ignore" mnttab
500 * option entry, or the "auto" one, set the mount type to "nfs".
502 mnt.mnt_type = HIDE_MOUNT_TYPE;
503 /* some systems don't have a mount type, but a mount flag */
505 #ifndef HAVE_TRANSPORT_TYPE_TLI
506 amu_get_myaddress(&localsocket.sin_addr);
507 localsocket.sin_family = AF_INET;
508 localsocket.sin_port = htons(nfsxprt->xp_port);
509 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
512 * Update hostname field.
513 * Make some name prog:pid (i.e., hlfsd:174) for hostname
515 sprintf(progpid_fs, "%s:%d", am_get_progname(), masterpid);
517 /* Most kernels have a name length restriction. */
518 if ((int) strlen(progpid_fs) >= (int) MAXHOSTNAMELEN)
519 strcpy(progpid_fs + MAXHOSTNAMELEN - 3, "..");
521 genflags = compute_mount_flags(&mnt);
523 retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);
527 memmove(&anh.v2.fhs_fh, root_fhp, sizeof(*root_fhp));
528 #ifdef HAVE_TRANSPORT_TYPE_TLI
529 compute_nfs_args(&nfs_args,
533 NULL, /* remote host IP addr is set below */
534 NFS_VERSION, /* version 2 */
535 "udp", /* XXX: shouldn't this be "udp"? */
537 progpid_fs, /* host name for kernel */
538 hostpid_fs); /* filesystem name for kernel */
540 * IMPORTANT: set the correct IP address AFTERWARDS. It cannot
541 * be done using the normal mechanism of compute_nfs_args(), because
542 * that one will allocate a new address and use NFS_SA_DREF() to copy
543 * parts to it, while assuming that the ip_addr passed is always
544 * a "struct sockaddr_in". That assumption is incorrect on TLI systems,
545 * because they define a special macro HOST_SELF which is DIFFERENT
546 * than localhost (127.0.0.1)!
548 nfs_args.addr = &nfsxprt->xp_ltaddr;
549 #else /* not HAVE_TRANSPORT_TYPE_TLI */
550 compute_nfs_args(&nfs_args,
554 NFS_VERSION, /* version 2 */
555 "udp", /* XXX: shouldn't this be "udp"? */
557 progpid_fs, /* host name for kernel */
558 hostpid_fs); /* filesystem name for kernel */
559 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
561 /*************************************************************************
562 * NOTE: while compute_nfs_args() works ok for regular NFS mounts *
563 * the toplvl one is not, and so some options must be corrected by hand *
564 * more carefully, *after* compute_nfs_args() runs. *
565 *************************************************************************/
566 compute_automounter_nfs_args(&nfs_args, &mnt);
568 clock_valid = 0; /* invalidate logging clock */
571 * The following code could be cleverly ifdef-ed, but I duplicated the
572 * mount_fs call three times for simplicity and readability.
576 * For some reason, this mount may have to be done in the background, if I am
577 * using -D nodebug. I suspect that the actual act of mounting requires
578 * calling to hlfsd itself to invoke one or more of its nfs calls, to stat
579 * /mail. That means that even if you say -D nodaemon, at least the mount
580 * of hlfsd itself on top of /mail will be done in the background.
581 * The other alternative I have is to run svc_run, but set a special
582 * signal handler to perform the mount in N seconds via some alarm.
585 if (debug_flags & D_DAEMON) { /* asked for -D daemon */
586 plog(XLOG_INFO, "parent NFS mounting hlfsd service points");
587 if (mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name) < 0)
588 fatal("nfsmount: %m");
589 } else { /* asked for -D nodaemon */
590 if (fork() == 0) { /* child runs mount */
593 plog(XLOG_INFO, "child NFS mounting hlfsd service points");
594 if (mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name) < 0) {
595 fatal("nfsmount: %m");
597 exit(0); /* all went well */
598 } else { /* fork failed or parent running */
599 plog(XLOG_INFO, "parent waiting 1sec for mount...");
602 #else /* not DEBUG */
603 plog(XLOG_INFO, "normal NFS mounting hlfsd service points");
604 if (mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, 2, "udp", mnttab_file_name) < 0)
605 fatal("nfsmount: %m");
606 #endif /* not DEBUG */
608 #ifdef HAVE_TRANSPORT_TYPE_TLI
610 * XXX: this free_knetconfig() was not done for hlfsd before,
611 * and apparently there was a reason for it, but why? -Erez
613 free_knetconfig(nfs_args.knconf);
615 * local automounter mounts do not allocate a special address, so
616 * no need to XFREE(nfs_args.addr) under TLI.
618 #endif /* HAVE_TRANSPORT_TYPE_TLI */
621 printf("%d\n", masterpid);
623 plog(XLOG_INFO, "hlfsd ready to serve");
626 * If asked not to fork a daemon (-D nodaemon), then hlfsd_init()
627 * will not run svc_run. We must start svc_run here.
629 dlog("starting no-daemon debugging svc_run");
634 cleanup(0); /* should never happen here */
635 return (0); /* everything went fine? */
643 #ifdef HAVE_SIGACTION
645 #endif /* HAVE_SIGACTION */
647 clock_valid = 0; /* invalidate logging clock */
650 * Initialize file handles.
652 plog(XLOG_INFO, "initializing hlfsd file handles");
653 hlfsd_init_filehandles();
657 * If -D daemon then we must fork.
666 if (child != 0) { /* parent process - save child pid */
668 am_set_mypid(); /* for logging routines */
677 plog(XLOG_INFO, "initializing home directory database");
678 plt_init(); /* initialize database */
679 plog(XLOG_INFO, "home directory database initialized");
681 masterpid = serverpid = am_set_mypid(); /* for logging routines */
684 * SIGALRM/SIGHUP: reload password database if timer expired
685 * or user sent HUP signal.
687 #ifdef HAVE_SIGACTION
688 sa.sa_handler = reload;
690 sigemptyset(&(sa.sa_mask));
691 sigaddset(&(sa.sa_mask), SIGALRM);
692 sigaddset(&(sa.sa_mask), SIGHUP);
693 sigaction(SIGALRM, &sa, NULL);
694 sigaction(SIGHUP, &sa, NULL);
695 #else /* not HAVE_SIGACTION */
696 signal(SIGALRM, reload);
697 signal(SIGHUP, reload);
698 #endif /* not HAVE_SIGACTION */
701 * SIGTERM: cleanup and exit.
703 #ifdef HAVE_SIGACTION
704 sa.sa_handler = cleanup;
706 sigemptyset(&(sa.sa_mask));
707 sigaddset(&(sa.sa_mask), SIGTERM);
708 sigaction(SIGTERM, &sa, NULL);
709 #else /* not HAVE_SIGACTION */
710 signal(SIGTERM, cleanup);
711 #endif /* not HAVE_SIGACTION */
714 * SIGCHLD: interlock synchronization and testing
716 #ifdef HAVE_SIGACTION
717 sa.sa_handler = interlock;
719 sigemptyset(&(sa.sa_mask));
720 sigaddset(&(sa.sa_mask), SIGCHLD);
721 sigaction(SIGCHLD, &sa, NULL);
722 #else /* not HAVE_SIGACTION */
723 signal(SIGCHLD, interlock);
724 #endif /* not HAVE_SIGACTION */
727 * SIGUSR1: dump internal hlfsd maps/cache to file
729 #ifdef HAVE_SIGACTION
730 # if defined(DEBUG) || defined(DEBUG_PRINT)
731 sa.sa_handler = plt_print;
732 # else /* not defined(DEBUG) || defined(DEBUG_PRINT) */
733 sa.sa_handler = SIG_IGN;
734 # endif /* not defined(DEBUG) || defined(DEBUG_PRINT) */
736 sigemptyset(&(sa.sa_mask));
737 sigaddset(&(sa.sa_mask), SIGUSR1);
738 sigaction(SIGUSR1, &sa, NULL);
739 #else /* not HAVE_SIGACTION */
740 # if defined(DEBUG) || defined(DEBUG_PRINT)
741 signal(SIGUSR1, plt_print);
742 # else /* not defined(DEBUG) || defined(DEBUG_PRINT) */
743 signal(SIGUSR1, SIG_IGN);
744 # endif /* not defined(DEBUG) || defined(DEBUG_PRINT) */
745 #endif /* not HAVE_SIGACTION */
747 if (setitimer(ITIMER_REAL, &reloadinterval, (struct itimerval *) 0) < 0)
748 fatal("setitimer: %m");
750 gettimeofday((struct timeval *) &startup, (struct timezone *) 0);
754 * If -D daemon, then start serving here in the child,
755 * and the parent will exit. But if -D nodaemon, then
756 * skip this code and make sure svc_run is entered elsewhere.
762 * Dissociate from the controlling terminal
764 amu_release_controlling_tty();
767 * signal parent we are ready. parent should
770 if (kill(getppid(), SIGUSR2) < 0)
772 plog(XLOG_INFO, "starting svc_run");
774 cleanup(0); /* should never happen, just in case */
776 } /* end of code that runs iff hlfsd daemonizes */
795 clock_valid = 0; /* invalidate logging clock */
797 if (getpid() != masterpid)
801 * If received a SIGHUP, close and reopen the log file (so that it
804 if (signum == SIGHUP && logfile)
805 switch_to_logfile(logfile, orig_umask);
808 * parent performs the reload, while the child continues to serve
809 * clients accessing the home dir link.
811 if ((child = fork()) > 0) {
812 serverpid = child; /* parent runs here */
817 if (kill(child, SIGKILL) < 0) {
818 plog(XLOG_ERROR, "kill child: %m");
819 } else { /* wait for child to die before continue */
820 if (wait(&status) != child) {
822 * I took out this line because it generates annoying output. It
823 * indicates a very small bug in hlfsd which is totally harmless.
824 * It causes hlfsd to work a bit harder than it should.
825 * Nevertheless, I intend on fixing it in a future release.
826 * -Erez Zadok <ezk@cs.columbia.edu>
828 /* plog(XLOG_ERROR, "unknown child"); */
831 serverpid = masterpid;
832 } else if (child < 0) {
833 plog(XLOG_ERROR, "unable to fork: %m");
835 /* let child handle requests while we reload */
836 serverpid = getpid();
848 clock_valid = 0; /* invalidate logging clock */
853 if (getpid() != masterpid)
867 while ((umount_result = UMOUNT_FS(dir_name, mnttab_file_name)) == EBUSY) {
869 dlog("cleanup(): umount delaying for 10 seconds");
873 if (stat(dir_name, &stbuf) == 0 && stbuf.st_ino == ROOTID) {
874 plog(XLOG_ERROR, "unable to unmount %s", dir_name);
875 plog(XLOG_ERROR, "suspending, unmount before terminating");
876 kill(am_mypid, SIGSTOP);
877 continue; /* retry unmount */
883 dlog("cleanup(): killing processes and terminating");
886 kill(masterpid, SIGKILL);
891 kill(serverpid, SIGKILL);
893 plog(XLOG_INFO, "hlfsd terminating with status 0\n");
903 if (wait(&result) == masterpid) {
910 hlfsd_going_down(int rc)
912 int mypid = getpid(); /* XXX: should this be the global am_mypid */
914 if (mypid == masterpid)
916 else if (mypid == serverpid)
917 kill(masterpid, SIGTERM);
926 if (logfile && !STREQ(logfile, "stderr")) {
930 messlen = strlen(mess);
932 if (!STREQ(&mess[messlen + 1 - sizeof(ERRM)], ERRM))
933 fprintf(stderr, "%s: %s\n", am_get_progname(), mess);
935 strcpy(lessmess, mess);
936 lessmess[messlen - 4] = '\0';
938 if (errno < sys_nerr)
939 fprintf(stderr, "%s: %s: %s\n", am_get_progname(), lessmess,
942 #else /* not HAVE_STRERROR */
944 #endif /* not HAVE_STRERROR */
947 fprintf(stderr, "%s: %s: Error %d\n",
948 am_get_progname(), lessmess, errno);
951 plog(XLOG_FATAL, mess);