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 $
43 * $DragonFly: src/contrib/amd/hlfsd/hlfsd.c,v 1.2 2003/06/17 04:23:57 dillon Exp $
45 * HLFSD was written at Columbia University Computer Science Department, by
46 * Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
47 * It is being distributed under the same terms and conditions as amd does.
52 #endif /* HAVE_CONFIG_H */
59 static RETSIGTYPE
proceed(int);
60 static RETSIGTYPE
reaper(int);
61 static RETSIGTYPE
reload(int);
62 static char *hlfs_group
= DEFAULT_HLFS_GROUP
;
63 static char default_dir_name
[] = DEFAULT_DIRNAME
;
64 static char *dir_name
= default_dir_name
;
65 static int printpid
= 0;
66 static int stoplight
= 0;
67 static void hlfsd_init(void);
68 static void usage(void);
70 static struct itimerval reloadinterval
= {
71 {DEFAULT_INTERVAL
, 0},
76 * default mount options.
78 static char default_mntopts
[] = "ro,noac";
84 char *alt_spooldir
= ALT_SPOOLDIR
;
85 char *home_subdir
= HOME_SUBDIR
;
86 char *logfile
= DEFAULT_LOGFILE
;
87 char *passwdfile
= NULL
; /* alternate passwd file to use */
89 char hostname
[MAXHOSTNAMELEN
+ 1] = "localhost";
90 int cache_interval
= DEFAULT_CACHE_INTERVAL
;
91 gid_t hlfs_gid
= (gid_t
) INVALIDID
;
99 /* symbol must be available always */
100 #ifdef MOUNT_TABLE_ON_FILE
101 char *mnttab_file_name
= MNTTAB_FILE_NAME
;
102 #else /* not MOUNT_TABLE_ON_FILE */
103 char *mnttab_file_name
= NULL
;
104 #endif /* not MOUNT_TABLE_ON_FILE */
106 /* forward declarations */
107 void hlfsd_going_down(int rc
);
114 "Usage: %s [-Cfhnpv] [-a altdir] [-c cache-interval] [-g group]\n",
116 fprintf(stderr
, "\t[-i interval] [-l logfile] [-o mntopts] [-P passwdfile]\n");
117 show_opts('x', xlog_opt
);
119 show_opts('D', dbg_opt
);
121 fprintf(stderr
, "\t[dir_name [subdir]]\n");
127 main(int argc
, char *argv
[])
130 char *mntopts
= (char *) NULL
;
131 char hostpid_fs
[MAXHOSTNAMELEN
+ 1 + 16]; /* room for ":(pid###)" */
132 char progpid_fs
[PROGNAMESZ
+ 1 + 11]; /* room for ":pid" */
141 int soNFS
; /* NFS socket */
146 struct dirent
*direntry
;
150 MTYPE_TYPE type
= MOUNT_TYPE_NFS
;
152 #ifdef HAVE_SIGACTION
154 #endif /* not HAVE_SIGACTION */
156 #ifndef HAVE_TRANSPORT_TYPE_TLI
157 struct sockaddr_in localsocket
;
158 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
161 /* get program name and truncate so we don't overflow progpid_fs */
163 if ((progname
= strrchr(argv
[0], '/')) != NULL
)
167 if ((int) strlen(progname
) > PROGNAMESZ
) /* truncate to reasonable size */
168 progname
[PROGNAMESZ
] = '\0';
169 am_set_progname(progname
);
171 while ((opt
= getopt(argc
, argv
, "a:c:CD:fg:hi:l:no:pP:x:v")) != -1)
175 if (!optarg
|| optarg
[0] != '/') {
176 printf("%s: invalid directory for -a: %s\n",
177 am_get_progname(), optarg
);
180 alt_spooldir
= optarg
;
185 printf("%s: invalid interval for -c: %s\n",
186 am_get_progname(), optarg
);
189 cache_interval
= atoi(optarg
);
206 printf("%s: invalid interval for -i: %s\n",
207 am_get_progname(), optarg
);
210 reloadinterval
.it_interval
.tv_sec
= atoi(optarg
);
211 reloadinterval
.it_value
.tv_sec
= atoi(optarg
);
235 fprintf(stderr
, "%s\n", HLFSD_VERSION
);
239 opterrs
+= switch_option(optarg
);
244 opterrs
+= debug_option(optarg
);
245 #else /* not DEBUG */
246 fprintf(stderr
, "%s: not compiled with DEBUG -- sorry.\n", am_get_progname());
247 #endif /* not DEBUG */
255 /* set some default debugging options */
256 if (xlog_level_init
== ~0)
258 /* need my pid before any dlog/plog */
261 switch_option("debug");
265 * Terminate if did not ask to forcecache (-C) and hlfsd would not be able
266 * to set the minimum cache intervals.
268 #if !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_FIELD_NFS_ARGS_T_ACREGMIN)
270 fprintf(stderr
, "%s: will not be able to turn off attribute caches.\n", am_get_progname());
273 #endif /* !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_FIELD_NFS_ARGS_T_ACREGMIN) */
276 switch (argc
- optind
) {
278 home_subdir
= argv
[optind
+ 1];
280 dir_name
= argv
[optind
];
290 /* ensure that only root can run hlfsd */
292 fprintf(stderr
, "hlfsd can only be run as root\n");
295 setbuf(stdout
, (char *) NULL
);
298 /* find gid for hlfs_group */
299 if ((grp
= getgrnam(hlfs_group
)) == (struct group
*) NULL
) {
300 fprintf(stderr
, "%s: cannot get gid for group \"%s\".\n",
301 am_get_progname(), hlfs_group
);
303 hlfs_gid
= grp
->gr_gid
;
306 /* get hostname for logging and open log before we reset umask */
307 gethostname(hostname
, sizeof(hostname
));
308 hostname
[sizeof(hostname
) - 1] = '\0';
309 if ((dot
= strchr(hostname
, '.')) != NULL
)
311 orig_umask
= umask(0);
313 switch_to_logfile(logfile
, orig_umask
);
315 #if defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE)
316 if (debug_flags
& D_MTAB
)
317 dlog("-D mtab option ignored");
318 #endif /* defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE) */
320 /* avoid hanging on other NFS servers if started elsewhere */
322 fatal("cannot chdir to /: %m");
325 fatal("must be root to mount filesystems");
328 * dir_name must match "^(/.*)/([^/]+)$", and is split at last '/' with
329 * slinkname = `basename $dir_name` - requires dir_name be writable
332 if (dir_name
[0] != '/'
333 || ((slinkname
= strrchr(dir_name
, '/')), *slinkname
++ = '\0',
334 (dir_name
[0] == '\0' || slinkname
[0] == '\0'))) {
337 printf("%s: invalid mount directory/link %s\n",
338 am_get_progname(), dir_name
);
342 clock_valid
= 0; /* invalidate logging clock */
345 /* make sure mount point exists and is at least mode 555 */
346 if (stat(dir_name
, &stmodes
) < 0)
347 if (errno
!= ENOENT
|| mkdirs(dir_name
, 0555) < 0
348 || stat(dir_name
, &stmodes
) < 0)
349 fatalerror(dir_name
);
351 if ((stmodes
.st_mode
& 0555) != 0555) {
352 fprintf(stderr
, "%s: directory %s not read/executable\n",
353 am_get_progname(), dir_name
);
354 plog(XLOG_WARNING
, "directory %s not read/executable",
358 /* warn if extraneous stuff will be hidden by mount */
359 if ((mountdir
= opendir(dir_name
)) == NULL
)
360 fatalerror(dir_name
);
362 while ((direntry
= readdir(mountdir
)) != NULL
) {
363 if (!NSTREQ(".", direntry
->d_name
, NAMLEN(direntry
)) &&
364 !NSTREQ("..", direntry
->d_name
, NAMLEN(direntry
)) &&
365 !NSTREQ(slinkname
, direntry
->d_name
, NAMLEN(direntry
)))
369 if (direntry
!= NULL
) {
370 fprintf(stderr
, "%s: %s/%s will be hidden by mount\n",
371 am_get_progname(), dir_name
, direntry
->d_name
);
372 plog(XLOG_WARNING
, "%s/%s will be hidden by mount\n",
373 dir_name
, direntry
->d_name
);
377 /* make sure alternate spool dir exists */
378 if ((errno
= mkdirs(alt_spooldir
, OPEN_SPOOLMODE
))) {
379 fprintf(stderr
, "%s: cannot create alternate dir ",
381 perror(alt_spooldir
);
382 plog(XLOG_ERROR
, "cannot create alternate dir %s: %m",
385 chmod(alt_spooldir
, OPEN_SPOOLMODE
);
387 /* create failsafe link to alternate spool directory */
388 slinkname
[-1] = '/'; /* unsplit dir_name to include link */
389 if (lstat(dir_name
, &stmodes
) == 0 &&
390 (stmodes
.st_mode
& S_IFMT
) != S_IFLNK
) {
391 fprintf(stderr
, "%s: failsafe %s not a symlink\n",
392 am_get_progname(), dir_name
);
393 plog(XLOG_WARNING
, "failsafe %s not a symlink\n",
398 if (symlink(alt_spooldir
, dir_name
) < 0) {
400 "%s: cannot create failsafe symlink %s -> ",
401 am_get_progname(), dir_name
);
402 perror(alt_spooldir
);
404 "cannot create failsafe symlink %s -> %s: %m",
405 dir_name
, alt_spooldir
);
409 slinkname
[-1] = '\0'; /* resplit dir_name */
410 } /* end of "if (!forcefast) {" */
413 * Register hlfsd as an nfs service with the portmapper.
415 #ifdef HAVE_TRANSPORT_TYPE_TLI
416 ret
= create_nfs_service(&soNFS
, &nfs_port
, &nfsxprt
, nfs_program_2
);
417 #else /* not HAVE_TRANSPORT_TYPE_TLI */
418 ret
= create_nfs_service(&soNFS
, &nfs_port
, &nfsxprt
, nfs_program_2
);
419 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
421 fatal("cannot create NFS service");
423 #ifdef HAVE_SIGACTION
424 sa
.sa_handler
= proceed
;
426 sigemptyset(&(sa
.sa_mask
));
427 sigaddset(&(sa
.sa_mask
), SIGUSR2
);
428 sigaction(SIGUSR2
, &sa
, NULL
);
429 #else /* not HAVE_SIGACTION */
430 signal(SIGUSR2
, proceed
);
431 #endif /* not HAVE_SIGACTION */
433 plog(XLOG_INFO
, "Initializing hlfsd...");
434 hlfsd_init(); /* start up child (forking) to run svc_run */
436 #ifdef HAVE_SIGACTION
437 sa
.sa_handler
= reaper
;
439 sigemptyset(&(sa
.sa_mask
));
440 sigaddset(&(sa
.sa_mask
), SIGCHLD
);
441 sigaction(SIGCHLD
, &sa
, NULL
);
442 #else /* not HAVE_SIGACTION */
443 signal(SIGCHLD
, reaper
);
444 #endif /* not HAVE_SIGACTION */
448 * In the parent, if -D nodaemon (or -D daemon) , we don't need to
449 * set this signal handler.
453 /* XXX: port to use pure svr4 signals */
455 while (stoplight
!= SIGUSR2
) {
456 plog(XLOG_INFO
, "parent waits for child to setup (stoplight=%d)", stoplight
);
457 s
= sigpause(0); /* wait for child to set up */
465 * setup options to mount table (/etc/{mtab,mnttab}) entry
467 sprintf(hostpid_fs
, "%s:(pid%d)", hostname
, masterpid
);
468 memset((char *) &mnt
, 0, sizeof(mnt
));
469 mnt
.mnt_dir
= dir_name
; /* i.e., "/mail" */
470 mnt
.mnt_fsname
= hostpid_fs
;
472 mnt
.mnt_opts
= mntopts
;
474 strcpy(preopts
, default_mntopts
);
476 * Turn off all kinds of attribute and symlink caches as
477 * much as possible. Also make sure that mount does not
480 #ifdef MNTTAB_OPT_INTR
481 strcat(preopts
, ",");
482 strcat(preopts
, MNTTAB_OPT_INTR
);
483 #endif /* MNTTAB_OPT_INTR */
484 #ifdef MNTTAB_OPT_IGNORE
485 strcat(preopts
, ",");
486 strcat(preopts
, MNTTAB_OPT_IGNORE
);
487 #endif /* MNTTAB_OPT_IGNORE */
488 #ifdef MNT2_GEN_OPT_CACHE
489 strcat(preopts
, ",nocache");
490 #endif /* MNT2_GEN_OPT_CACHE */
491 #ifdef MNT2_NFS_OPT_SYMTTL
492 strcat(preopts
, ",symttl=0");
493 #endif /* MNT2_NFS_OPT_SYMTTL */
494 mnt
.mnt_opts
= preopts
;
498 * Make sure that amd's top-level NFS mounts are hidden by default
500 * If they don't appear to support the either the "ignore" mnttab
501 * option entry, or the "auto" one, set the mount type to "nfs".
503 mnt
.mnt_type
= HIDE_MOUNT_TYPE
;
504 /* some systems don't have a mount type, but a mount flag */
506 #ifndef HAVE_TRANSPORT_TYPE_TLI
507 amu_get_myaddress(&localsocket
.sin_addr
);
508 localsocket
.sin_family
= AF_INET
;
509 localsocket
.sin_port
= htons(nfsxprt
->xp_port
);
510 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
513 * Update hostname field.
514 * Make some name prog:pid (i.e., hlfsd:174) for hostname
516 sprintf(progpid_fs
, "%s:%d", am_get_progname(), masterpid
);
518 /* Most kernels have a name length restriction. */
519 if ((int) strlen(progpid_fs
) >= (int) MAXHOSTNAMELEN
)
520 strcpy(progpid_fs
+ MAXHOSTNAMELEN
- 3, "..");
522 genflags
= compute_mount_flags(&mnt
);
524 retry
= hasmntval(&mnt
, MNTTAB_OPT_RETRY
);
528 memmove(&anh
.v2
.fhs_fh
, root_fhp
, sizeof(*root_fhp
));
529 #ifdef HAVE_TRANSPORT_TYPE_TLI
530 compute_nfs_args(&nfs_args
,
534 NULL
, /* remote host IP addr is set below */
535 NFS_VERSION
, /* version 2 */
536 "udp", /* XXX: shouldn't this be "udp"? */
538 progpid_fs
, /* host name for kernel */
539 hostpid_fs
); /* filesystem name for kernel */
541 * IMPORTANT: set the correct IP address AFTERWARDS. It cannot
542 * be done using the normal mechanism of compute_nfs_args(), because
543 * that one will allocate a new address and use NFS_SA_DREF() to copy
544 * parts to it, while assuming that the ip_addr passed is always
545 * a "struct sockaddr_in". That assumption is incorrect on TLI systems,
546 * because they define a special macro HOST_SELF which is DIFFERENT
547 * than localhost (127.0.0.1)!
549 nfs_args
.addr
= &nfsxprt
->xp_ltaddr
;
550 #else /* not HAVE_TRANSPORT_TYPE_TLI */
551 compute_nfs_args(&nfs_args
,
555 NFS_VERSION
, /* version 2 */
556 "udp", /* XXX: shouldn't this be "udp"? */
558 progpid_fs
, /* host name for kernel */
559 hostpid_fs
); /* filesystem name for kernel */
560 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
562 /*************************************************************************
563 * NOTE: while compute_nfs_args() works ok for regular NFS mounts *
564 * the toplvl one is not, and so some options must be corrected by hand *
565 * more carefully, *after* compute_nfs_args() runs. *
566 *************************************************************************/
567 compute_automounter_nfs_args(&nfs_args
, &mnt
);
569 clock_valid
= 0; /* invalidate logging clock */
572 * The following code could be cleverly ifdef-ed, but I duplicated the
573 * mount_fs call three times for simplicity and readability.
577 * For some reason, this mount may have to be done in the background, if I am
578 * using -D nodebug. I suspect that the actual act of mounting requires
579 * calling to hlfsd itself to invoke one or more of its nfs calls, to stat
580 * /mail. That means that even if you say -D nodaemon, at least the mount
581 * of hlfsd itself on top of /mail will be done in the background.
582 * The other alternative I have is to run svc_run, but set a special
583 * signal handler to perform the mount in N seconds via some alarm.
586 if (debug_flags
& D_DAEMON
) { /* asked for -D daemon */
587 plog(XLOG_INFO
, "parent NFS mounting hlfsd service points");
588 if (mount_fs(&mnt
, genflags
, (caddr_t
) &nfs_args
, retry
, type
, 0, NULL
, mnttab_file_name
) < 0)
589 fatal("nfsmount: %m");
590 } else { /* asked for -D nodaemon */
591 if (fork() == 0) { /* child runs mount */
594 plog(XLOG_INFO
, "child NFS mounting hlfsd service points");
595 if (mount_fs(&mnt
, genflags
, (caddr_t
) &nfs_args
, retry
, type
, 0, NULL
, mnttab_file_name
) < 0) {
596 fatal("nfsmount: %m");
598 exit(0); /* all went well */
599 } else { /* fork failed or parent running */
600 plog(XLOG_INFO
, "parent waiting 1sec for mount...");
603 #else /* not DEBUG */
604 plog(XLOG_INFO
, "normal NFS mounting hlfsd service points");
605 if (mount_fs(&mnt
, genflags
, (caddr_t
) &nfs_args
, retry
, type
, 2, "udp", mnttab_file_name
) < 0)
606 fatal("nfsmount: %m");
607 #endif /* not DEBUG */
609 #ifdef HAVE_TRANSPORT_TYPE_TLI
611 * XXX: this free_knetconfig() was not done for hlfsd before,
612 * and apparently there was a reason for it, but why? -Erez
614 free_knetconfig(nfs_args
.knconf
);
616 * local automounter mounts do not allocate a special address, so
617 * no need to XFREE(nfs_args.addr) under TLI.
619 #endif /* HAVE_TRANSPORT_TYPE_TLI */
622 printf("%d\n", masterpid
);
624 plog(XLOG_INFO
, "hlfsd ready to serve");
627 * If asked not to fork a daemon (-D nodaemon), then hlfsd_init()
628 * will not run svc_run. We must start svc_run here.
630 dlog("starting no-daemon debugging svc_run");
635 cleanup(0); /* should never happen here */
636 return (0); /* everything went fine? */
644 #ifdef HAVE_SIGACTION
646 #endif /* HAVE_SIGACTION */
648 clock_valid
= 0; /* invalidate logging clock */
651 * Initialize file handles.
653 plog(XLOG_INFO
, "initializing hlfsd file handles");
654 hlfsd_init_filehandles();
658 * If -D daemon then we must fork.
667 if (child
!= 0) { /* parent process - save child pid */
669 am_set_mypid(); /* for logging routines */
678 plog(XLOG_INFO
, "initializing home directory database");
679 plt_init(); /* initialize database */
680 plog(XLOG_INFO
, "home directory database initialized");
682 masterpid
= serverpid
= am_set_mypid(); /* for logging routines */
685 * SIGALRM/SIGHUP: reload password database if timer expired
686 * or user sent HUP signal.
688 #ifdef HAVE_SIGACTION
689 sa
.sa_handler
= reload
;
691 sigemptyset(&(sa
.sa_mask
));
692 sigaddset(&(sa
.sa_mask
), SIGALRM
);
693 sigaddset(&(sa
.sa_mask
), SIGHUP
);
694 sigaction(SIGALRM
, &sa
, NULL
);
695 sigaction(SIGHUP
, &sa
, NULL
);
696 #else /* not HAVE_SIGACTION */
697 signal(SIGALRM
, reload
);
698 signal(SIGHUP
, reload
);
699 #endif /* not HAVE_SIGACTION */
702 * SIGTERM: cleanup and exit.
704 #ifdef HAVE_SIGACTION
705 sa
.sa_handler
= cleanup
;
707 sigemptyset(&(sa
.sa_mask
));
708 sigaddset(&(sa
.sa_mask
), SIGTERM
);
709 sigaction(SIGTERM
, &sa
, NULL
);
710 #else /* not HAVE_SIGACTION */
711 signal(SIGTERM
, cleanup
);
712 #endif /* not HAVE_SIGACTION */
715 * SIGCHLD: interlock synchronization and testing
717 #ifdef HAVE_SIGACTION
718 sa
.sa_handler
= interlock
;
720 sigemptyset(&(sa
.sa_mask
));
721 sigaddset(&(sa
.sa_mask
), SIGCHLD
);
722 sigaction(SIGCHLD
, &sa
, NULL
);
723 #else /* not HAVE_SIGACTION */
724 signal(SIGCHLD
, interlock
);
725 #endif /* not HAVE_SIGACTION */
728 * SIGUSR1: dump internal hlfsd maps/cache to file
730 #ifdef HAVE_SIGACTION
731 # if defined(DEBUG) || defined(DEBUG_PRINT)
732 sa
.sa_handler
= plt_print
;
733 # else /* not defined(DEBUG) || defined(DEBUG_PRINT) */
734 sa
.sa_handler
= SIG_IGN
;
735 # endif /* not defined(DEBUG) || defined(DEBUG_PRINT) */
737 sigemptyset(&(sa
.sa_mask
));
738 sigaddset(&(sa
.sa_mask
), SIGUSR1
);
739 sigaction(SIGUSR1
, &sa
, NULL
);
740 #else /* not HAVE_SIGACTION */
741 # if defined(DEBUG) || defined(DEBUG_PRINT)
742 signal(SIGUSR1
, plt_print
);
743 # else /* not defined(DEBUG) || defined(DEBUG_PRINT) */
744 signal(SIGUSR1
, SIG_IGN
);
745 # endif /* not defined(DEBUG) || defined(DEBUG_PRINT) */
746 #endif /* not HAVE_SIGACTION */
748 if (setitimer(ITIMER_REAL
, &reloadinterval
, (struct itimerval
*) 0) < 0)
749 fatal("setitimer: %m");
751 gettimeofday((struct timeval
*) &startup
, (struct timezone
*) 0);
755 * If -D daemon, then start serving here in the child,
756 * and the parent will exit. But if -D nodaemon, then
757 * skip this code and make sure svc_run is entered elsewhere.
763 * Dissociate from the controlling terminal
765 amu_release_controlling_tty();
768 * signal parent we are ready. parent should
771 if (kill(getppid(), SIGUSR2
) < 0)
773 plog(XLOG_INFO
, "starting svc_run");
775 cleanup(0); /* should never happen, just in case */
777 } /* end of code that runs iff hlfsd daemonizes */
796 clock_valid
= 0; /* invalidate logging clock */
798 if (getpid() != masterpid
)
802 * If received a SIGHUP, close and reopen the log file (so that it
805 if (signum
== SIGHUP
&& logfile
)
806 switch_to_logfile(logfile
, orig_umask
);
809 * parent performs the reload, while the child continues to serve
810 * clients accessing the home dir link.
812 if ((child
= fork()) > 0) {
813 serverpid
= child
; /* parent runs here */
818 if (kill(child
, SIGKILL
) < 0) {
819 plog(XLOG_ERROR
, "kill child: %m");
820 } else { /* wait for child to die before continue */
821 if (wait(&status
) != child
) {
823 * I took out this line because it generates annoying output. It
824 * indicates a very small bug in hlfsd which is totally harmless.
825 * It causes hlfsd to work a bit harder than it should.
826 * Nevertheless, I intend on fixing it in a future release.
827 * -Erez Zadok <ezk@cs.columbia.edu>
829 /* plog(XLOG_ERROR, "unknown child"); */
832 serverpid
= masterpid
;
833 } else if (child
< 0) {
834 plog(XLOG_ERROR
, "unable to fork: %m");
836 /* let child handle requests while we reload */
837 serverpid
= getpid();
849 clock_valid
= 0; /* invalidate logging clock */
854 if (getpid() != masterpid
)
868 while ((umount_result
= UMOUNT_FS(dir_name
, mnttab_file_name
)) == EBUSY
) {
870 dlog("cleanup(): umount delaying for 10 seconds");
874 if (stat(dir_name
, &stbuf
) == 0 && stbuf
.st_ino
== ROOTID
) {
875 plog(XLOG_ERROR
, "unable to unmount %s", dir_name
);
876 plog(XLOG_ERROR
, "suspending, unmount before terminating");
877 kill(am_mypid
, SIGSTOP
);
878 continue; /* retry unmount */
884 dlog("cleanup(): killing processes and terminating");
887 kill(masterpid
, SIGKILL
);
892 kill(serverpid
, SIGKILL
);
894 plog(XLOG_INFO
, "hlfsd terminating with status 0\n");
904 if (wait(&result
) == masterpid
) {
911 hlfsd_going_down(int rc
)
913 int mypid
= getpid(); /* XXX: should this be the global am_mypid */
915 if (mypid
== masterpid
)
917 else if (mypid
== serverpid
)
918 kill(masterpid
, SIGTERM
);
927 if (logfile
&& !STREQ(logfile
, "stderr")) {
931 messlen
= strlen(mess
);
933 if (!STREQ(&mess
[messlen
+ 1 - sizeof(ERRM
)], ERRM
))
934 fprintf(stderr
, "%s: %s\n", am_get_progname(), mess
);
936 strcpy(lessmess
, mess
);
937 lessmess
[messlen
- 4] = '\0';
939 if (errno
< sys_nerr
)
940 fprintf(stderr
, "%s: %s: %s\n", am_get_progname(), lessmess
,
943 #else /* not HAVE_STRERROR */
945 #endif /* not HAVE_STRERROR */
948 fprintf(stderr
, "%s: %s: Error %d\n",
949 am_get_progname(), lessmess
, errno
);
952 plog(XLOG_FATAL
, mess
);