Deleted Added
sdiff udiff text old ( 41145 ) new ( 42633 )
full compact
1/*
2 * Copyright (c) 1997-1998 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.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
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 acknowledgement:
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.
26 *
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

--- 4 unchanged lines hidden (view full) ---

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
37 * SUCH DAMAGE.
38 *
39 * %W% (Berkeley) %G%
40 *
41 * $Id: hlfsd.c,v 1.2 1998/08/23 22:52:08 obrien Exp $
42 *
43 * HLFSD was written at Columbia University Computer Science Department, by
44 * Erez Zadok <ezk@cs.columbia.edu> and Alexander Dupuy <dupuy@cs.columbia.edu>
45 * It is being distributed under the same terms and conditions as amd does.
46 */
47
48#ifdef HAVE_CONFIG_H
49# include <config.h>

--- 28 unchanged lines hidden (view full) ---

78/*
79 * GLOBALS:
80 */
81SVCXPRT *nfsxprt;
82char *alt_spooldir = ALT_SPOOLDIR;
83char *home_subdir = HOME_SUBDIR;
84char *logfile = DEFAULT_LOGFILE;
85char *passwdfile = NULL; /* alternate passwd file to use */
86char *progname;
87char *slinkname = 0;
88char hostname[MAXHOSTNAMELEN + 1] = "localhost";
89int cache_interval = DEFAULT_CACHE_INTERVAL;
90int foreground = 1; /* This is the top-level server */
91gid_t hlfs_gid = (gid_t) INVALIDID;
92int masterpid = 0;
93int noverify = 0;
94int orig_umask;
95int serverpid = 0;
96nfstime startup;
97pid_t mypid; /* Current process id */
98serv_state amd_state;
99u_short nfs_port;
100
101/* symbol must be available always */
102#ifdef MOUNT_TABLE_ON_FILE
103char *mnttab_file_name = MNTTAB_FILE_NAME;
104#else /* not MOUNT_TABLE_ON_FILE */
105char *mnttab_file_name = NULL;
106#endif /* not MOUNT_TABLE_ON_FILE */
107
108#ifdef DEBUG
109int debug_flags = 0;
110#endif /* DEBUG */
111
112/* forward declarations */
113void hlfsd_going_down(int rc);
114
115
116static void
117usage(void)
118{
119 fprintf(stderr,
120 "Usage: %s [-Cfhnpv] [-a altdir] [-c cache-interval] [-g group]\n",
121 progname);
122 fprintf(stderr, "\t[-i interval] [-l logfile] [-o mntopts] [-P passwdfile]\n");
123 show_opts('x', xlog_opt);
124#ifdef DEBUG
125 show_opts('D', dbg_opt);
126#endif /* DEBUG */
127 fprintf(stderr, "\t[dir_name [subdir]]\n");
128 exit(2);
129}
130
131
132int
133main(int argc, char *argv[])
134{
135 char *dot;
136 char *mntopts = (char *) NULL;
137 char hostpid_fs[MAXHOSTNAMELEN + 1 + 16]; /* room for ":(pid###)" */
138 char progpid_fs[PROGNAMESZ + 1 + 11]; /* room for ":pid" */
139 char preopts[128];
140 int forcecache = 0;
141 int forcefast = 0;
142 int genflags = 0;
143 int opt, ret;
144 int opterrs = 0;
145 int retry;
146 int soNFS; /* NFS socket */
147 int s = -99;

--- 18 unchanged lines hidden (view full) ---

166 /* get program name and truncate so we don't overflow progpid_fs */
167
168 if ((progname = strrchr(argv[0], '/')) != NULL)
169 progname++;
170 else
171 progname = argv[0];
172 if ((int) strlen(progname) > PROGNAMESZ) /* truncate to reasonable size */
173 progname[PROGNAMESZ] = '\0';
174
175 while ((opt = getopt(argc, argv, "a:c:CD:fg:hi:l:no:pP:x:v")) != EOF)
176 switch (opt) {
177
178 case 'a':
179 if (!optarg || optarg[0] != '/') {
180 printf("%s: invalid directory for -a: %s\n",
181 progname, optarg);
182 exit(3);
183 }
184 alt_spooldir = optarg;
185 break;
186
187 case 'c':
188 if (!atoi(optarg)) {
189 printf("%s: invalid interval for -c: %s\n",
190 progname, optarg);
191 exit(3);
192 }
193 cache_interval = atoi(optarg);
194 break;
195
196 case 'C':
197 forcecache++;
198 break;

--- 4 unchanged lines hidden (view full) ---

203
204 case 'g':
205 hlfs_group = optarg;
206 break;
207
208 case 'i':
209 if (!atoi(optarg)) {
210 printf("%s: invalid interval for -i: %s\n",
211 progname, optarg);
212 exit(3);
213 }
214 reloadinterval.it_interval.tv_sec = atoi(optarg);
215 reloadinterval.it_value.tv_sec = atoi(optarg);
216 break;
217
218 case 'l':
219 logfile = optarg;

--- 22 unchanged lines hidden (view full) ---

242 case 'x':
243 opterrs += switch_option(optarg);
244 break;
245
246 case 'D':
247#ifdef DEBUG
248 opterrs += debug_option(optarg);
249#else /* not DEBUG */
250 fprintf(stderr, "%s: not compiled with DEBUG -- sorry.\n", progname);
251#endif /* not DEBUG */
252 break;
253
254 case 'h':
255 case '?':
256 opterrs++;
257 }
258
259 /* set some default debugging options */
260 if (xlog_level_init == ~0)
261 switch_option("");
262 /* need my pid before any dlog/plog */
263 mypid = getpid();
264#ifdef DEBUG
265 switch_option("debug");
266#endif /* DEBUG */
267
268/*
269 * Terminate if did not ask to forcecache (-C) and hlfsd would not be able
270 * to set the minimum cache intervals.
271 */
272#if !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_FIELD_NFS_ARGS_T_ACREGMIN)
273 if (!forcecache) {
274 fprintf(stderr, "%s: will not be able to turn off attribute caches.\n", progname);
275 exit(1);
276 }
277#endif /* !defined(MNT2_NFS_OPT_ACREGMIN) && !defined(MNT2_NFS_OPT_NOAC) && !defined(HAVE_FIELD_NFS_ARGS_T_ACREGMIN) */
278
279
280 switch (argc - optind) {
281 case 2:
282 home_subdir = argv[optind + 1];

--- 14 unchanged lines hidden (view full) ---

297 exit(1);
298 }
299 setbuf(stdout, (char *) NULL);
300 umask(0);
301
302 /* find gid for hlfs_group */
303 if ((grp = getgrnam(hlfs_group)) == (struct group *) NULL) {
304 fprintf(stderr, "%s: cannot get gid for group \"%s\".\n",
305 progname, hlfs_group);
306 } else {
307 hlfs_gid = grp->gr_gid;
308 }
309
310 /* get hostname for logging and open log before we reset umask */
311 gethostname(hostname, sizeof(hostname));
312 hostname[sizeof(hostname) - 1] = '\0';
313 if ((dot = strchr(hostname, '.')) != NULL)
314 *dot = '\0';
315 if (logfile)
316 switch_to_logfile(logfile);
317 orig_umask = umask(0);
318
319#if defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE)
320 if (debug_flags & D_MTAB)
321 dlog("-D mtab option ignored");
322#endif /* defined(DEBUG) && !defined(MOUNT_TABLE_ON_FILE) */
323
324 /* avoid hanging on other NFS servers if started elsewhere */
325 if (chdir("/") < 0)

--- 8 unchanged lines hidden (view full) ---

334 */
335
336 if (dir_name[0] != '/'
337 || ((slinkname = strrchr(dir_name, '/')), *slinkname++ = '\0',
338 (dir_name[0] == '\0' || slinkname[0] == '\0'))) {
339 if (slinkname)
340 *--slinkname = '/';
341 printf("%s: invalid mount directory/link %s\n",
342 progname, dir_name);
343 exit(3);
344 }
345
346 clock_valid = 0; /* invalidate logging clock */
347
348 if (!forcefast) {
349 /* make sure mount point exists and is at least mode 555 */
350 if (stat(dir_name, &stmodes) < 0)
351 if (errno != ENOENT || mkdirs(dir_name, 0555) < 0
352 || stat(dir_name, &stmodes) < 0)
353 fatalerror(dir_name);
354
355 if ((stmodes.st_mode & 0555) != 0555) {
356 fprintf(stderr, "%s: directory %s not read/executable\n",
357 progname, dir_name);
358 plog(XLOG_WARNING, "directory %s not read/executable",
359 dir_name);
360 }
361
362 /* warn if extraneous stuff will be hidden by mount */
363 if ((mountdir = opendir(dir_name)) == NULL)
364 fatalerror(dir_name);
365
366 while ((direntry = readdir(mountdir)) != NULL) {
367 if (!NSTREQ(".", direntry->d_name, NAMLEN(direntry)) &&
368 !NSTREQ("..", direntry->d_name, NAMLEN(direntry)) &&
369 !NSTREQ(slinkname, direntry->d_name, NAMLEN(direntry)))
370 break;
371 }
372
373 if (direntry != NULL) {
374 fprintf(stderr, "%s: %s/%s will be hidden by mount\n",
375 progname, dir_name, direntry->d_name);
376 plog(XLOG_WARNING, "%s/%s will be hidden by mount\n",
377 dir_name, direntry->d_name);
378 }
379 closedir(mountdir);
380
381 /* make sure alternate spool dir exists */
382 if ((errno = mkdirs(alt_spooldir, OPEN_SPOOLMODE))) {
383 fprintf(stderr, "%s: cannot create alternate dir ",
384 progname);
385 perror(alt_spooldir);
386 plog(XLOG_ERROR, "cannot create alternate dir %s: %m",
387 alt_spooldir);
388 }
389 chmod(alt_spooldir, OPEN_SPOOLMODE);
390
391 /* create failsafe link to alternate spool directory */
392 slinkname[-1] = '/'; /* unsplit dir_name to include link */
393 if (lstat(dir_name, &stmodes) == 0 &&
394 (stmodes.st_mode & S_IFMT) != S_IFLNK) {
395 fprintf(stderr, "%s: failsafe %s not a symlink\n",
396 progname, dir_name);
397 plog(XLOG_WARNING, "failsafe %s not a symlink\n",
398 dir_name);
399 } else {
400 unlink(dir_name);
401
402 if (symlink(alt_spooldir, dir_name) < 0) {
403 fprintf(stderr,
404 "%s: cannot create failsafe symlink %s -> ",
405 progname, dir_name);
406 perror(alt_spooldir);
407 plog(XLOG_WARNING,
408 "cannot create failsafe symlink %s -> %s: %m",
409 dir_name, alt_spooldir);
410 }
411 }
412
413 slinkname[-1] = '\0'; /* resplit dir_name */

--- 98 unchanged lines hidden (view full) ---

512 localsocket.sin_family = AF_INET;
513 localsocket.sin_port = htons(nfsxprt->xp_port);
514#endif /* not HAVE_TRANSPORT_TYPE_TLI */
515
516 /*
517 * Update hostname field.
518 * Make some name prog:pid (i.e., hlfsd:174) for hostname
519 */
520 sprintf(progpid_fs, "%s:%d", progname, masterpid);
521
522 /* Most kernels have a name length restriction. */
523 if ((int) strlen(progpid_fs) >= (int) MAXHOSTNAMELEN)
524 strcpy(progpid_fs + MAXHOSTNAMELEN - 3, "..");
525
526 genflags = compute_mount_flags(&mnt);
527
528 retry = hasmntval(&mnt, MNTTAB_OPT_RETRY);

--- 59 unchanged lines hidden (view full) ---

588 * -Erez Zadok.
589 */
590 if (debug_flags & D_DAEMON) { /* asked for -D daemon */
591 plog(XLOG_INFO, "parent NFS mounting hlfsd service points");
592 if (mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name) < 0)
593 fatal("nfsmount: %m");
594 } else { /* asked for -D nodaemon */
595 if (fork() == 0) { /* child runs mount */
596 mypid = getpid();
597 foreground = 0;
598 plog(XLOG_INFO, "child NFS mounting hlfsd service points");
599 if (mount_fs(&mnt, genflags, (caddr_t) &nfs_args, retry, type, 0, NULL, mnttab_file_name) < 0) {
600 fatal("nfsmount: %m");
601 }
602 exit(0); /* all went well */
603 } else { /* fork failed or parent running */
604 plog(XLOG_INFO, "parent waiting 1sec for mount...");

--- 60 unchanged lines hidden (view full) ---

665#endif /* DEBUG */
666 child = fork();
667
668 if (child < 0)
669 fatal("fork: %m");
670
671 if (child != 0) { /* parent process - save child pid */
672 masterpid = child;
673 mypid = getpid(); /* for logging routines */
674 return;
675 }
676
677 /*
678 * CHILD CODE:
679 * initialize server
680 */
681
682 plog(XLOG_INFO, "initializing home directory database");
683 plt_init(); /* initialize database */
684 plog(XLOG_INFO, "home directory database initialized");
685
686 masterpid = serverpid = mypid = getpid(); /* for logging routines */
687
688 /*
689 * SIGALRM/SIGHUP: reload password database if timer expired
690 * or user sent HUP signal.
691 */
692#ifdef HAVE_SIGACTION
693 sa.sa_handler = reload;
694 sa.sa_flags = 0;

--- 16 unchanged lines hidden (view full) ---

711 sigemptyset(&(sa.sa_mask));
712 sigaddset(&(sa.sa_mask), SIGTERM);
713 sigaction(SIGTERM, &sa, NULL);
714#else /* not HAVE_SIGACTION */
715 signal(SIGTERM, cleanup);
716#endif /* not HAVE_SIGACTION */
717
718 /*
719 * SIGCHLD: interlock sycronization and testing
720 */
721#ifdef HAVE_SIGACTION
722 sa.sa_handler = interlock;
723 sa.sa_flags = 0;
724 sigemptyset(&(sa.sa_mask));
725 sigaddset(&(sa.sa_mask), SIGCHLD);
726 sigaction(SIGCHLD, &sa, NULL);
727#else /* not HAVE_SIGACTION */

--- 74 unchanged lines hidden (view full) ---

802 if (getpid() != masterpid)
803 return;
804
805 /*
806 * If received a SIGHUP, close and reopen the log file (so that it
807 * can be rotated)
808 */
809 if (signum == SIGHUP && logfile)
810 switch_to_logfile(logfile);
811
812 /*
813 * parent performs the reload, while the child continues to serve
814 * clients accessing the home dir link.
815 */
816 if ((child = fork()) > 0) {
817 serverpid = child; /* parent runs here */
818 mypid = getpid();
819
820 plt_init();
821
822 if (kill(child, SIGKILL) < 0) {
823 plog(XLOG_ERROR, "kill child: %m");
824 } else { /* wait for child to die before continue */
825 if (wait(&status) != child) {
826 /*

--- 7 unchanged lines hidden (view full) ---

834 }
835 }
836 serverpid = masterpid;
837 } else if (child < 0) {
838 plog(XLOG_ERROR, "unable to fork: %m");
839 } else {
840 /* let child handle requests while we reload */
841 serverpid = getpid();
842 mypid = getpid();
843 }
844}
845
846
847RETSIGTYPE
848cleanup(int signum)
849{
850 struct stat stbuf;

--- 7 unchanged lines hidden (view full) ---

858 if (getpid() != masterpid)
859 return;
860
861#ifdef DEBUG
862 amuDebug(D_DAEMON)
863#endif /* DEBUG */
864 if (fork() != 0) {
865 masterpid = 0;
866 mypid = getpid();
867 return;
868 }
869 mypid = getpid();
870
871 for (;;) {
872 while ((umount_result = UMOUNT_FS(dir_name, mnttab_file_name)) == EBUSY) {
873#ifdef DEBUG
874 dlog("cleanup(): umount delaying for 10 seconds");
875#endif /* DEBUG */
876 sleep(10);
877 }
878 if (stat(dir_name, &stbuf) == 0 && stbuf.st_ino == ROOTID) {
879 plog(XLOG_ERROR, "unable to unmount %s", dir_name);
880 plog(XLOG_ERROR, "suspending, unmount before terminating");
881 kill(mypid, SIGSTOP);
882 continue; /* retry unmount */
883 }
884 break;
885 }
886
887#ifdef DEBUG
888 dlog("cleanup(): killing processes and terminating");
889 amuDebug(D_DAEMON)

--- 19 unchanged lines hidden (view full) ---

909 exit(4);
910 }
911}
912
913
914void
915hlfsd_going_down(int rc)
916{
917 int mypid = getpid();
918
919 if (mypid == masterpid)
920 cleanup(0);
921 else if (mypid == serverpid)
922 kill(masterpid, SIGTERM);
923
924 exit(rc);
925}

--- 4 unchanged lines hidden (view full) ---

930{
931 if (logfile && !STREQ(logfile, "stderr")) {
932 char lessmess[128];
933 int messlen;
934
935 messlen = strlen(mess);
936
937 if (!STREQ(&mess[messlen + 1 - sizeof(ERRM)], ERRM))
938 fprintf(stderr, "%s: %s\n", progname, mess);
939 else {
940 strcpy(lessmess, mess);
941 lessmess[messlen - 4] = '\0';
942
943 if (errno < sys_nerr)
944 fprintf(stderr, "%s: %s: %s\n", progname,
945 lessmess, sys_errlist[errno]);
946 else
947 fprintf(stderr, "%s: %s: Error %d\n",
948 progname, lessmess, errno);
949 }
950 }
951 plog(XLOG_FATAL, mess);
952
953 hlfsd_going_down(1);
954}