/* Copyright 1998 by the Massachusetts Institute of Technology. * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright * notice and this permission notice appear in supporting * documentation, and that the name of M.I.T. not be used in * advertising or publicity pertaining to distribution of the * software without specific, written prior permission. * M.I.T. makes no representations about the suitability of * this software for any purpose. It is provided "as is" * without express or implied warranty. */ /* This is detach, which is used to detach lockers from workstations. */ static const char rcsid[] = "$Id: detach.c,v 1.24 1999-09-27 16:14:13 danw Exp $"; #include #include #include #include #include #include #include "attach.h" #include "agetopt.h" static void usage(void); static void detach_all(locker_context context, int options); static void detach_by_host(locker_context context, char *host, int options); static int detach_attachent(locker_context context, locker_attachent *at, void *optionsp); static struct agetopt_option detach_options[] = { { "all", 'a', 0 }, { "clean", 'C', 0 }, { "debug", 'd', 0 }, { "explicit", 'e', 0 }, { "force", 'f', 0 }, { "nozephyr", 'h', 0 }, { "host", 'H', 0 }, { "lint", 'L', 0 }, { "nomap", 'n', 0 }, { "override", 'O', 0 }, { "quiet", 'q', 0 }, { "spoofhost", 's', 1 }, { "type", 't', 1 }, { "user", 'U', 1 }, { "verbose", 'v', 0 }, { "noexplicit", 'x', 0 }, { "unmap", 'y', 0 }, { "zephyr", 'z', 0 }, { 0, 0, 0 } }; static int verbose = 1; enum { DETACH_FILESYSTEM, DETACH_EXPLICIT, DETACH_BY_HOST }; int detach_main(int argc, char **argv) { locker_context context; locker_attachent *at; int options = LOCKER_DETACH_DEFAULT_OPTIONS; char *type = "nfs"; int mode = DETACH_FILESYSTEM, opt, gotname = 0; int status, estatus = 0; if (locker_init(&context, getuid(), NULL, NULL)) exit(1); /* Wrap another while around the getopt so we can go through * multiple cycles of "[options] lockers...". */ while (optind < argc) { while ((opt = attach_getopt(argc, argv, detach_options)) != -1) { switch (opt) { case 'a': /* backward compatibility: "detach -O -a" implies * override, but not unlock. */ detach_all(context, options & ~LOCKER_DETACH_OPT_UNLOCK); gotname++; break; case 'C': options |= LOCKER_DETACH_OPT_CLEAN; break; case 'e': mode = DETACH_EXPLICIT; break; case 'h': options &= ~LOCKER_DETACH_OPT_UNZEPHYR; break; case 'H': mode = DETACH_BY_HOST; break; case 'n': options &= ~LOCKER_DETACH_OPT_UNAUTH; break; case 'O': options |= LOCKER_DETACH_OPT_OVERRIDE | LOCKER_DETACH_OPT_UNLOCK; break; case 'q': verbose = 0; break; case 't': type = optarg; break; case 'U': if (getuid() != 0) { fprintf(stderr, "%s: You are not allowed to use the " "--user option.\n", whoami); exit(1); } else { struct passwd *pw; pw = getpwnam(optarg); if (!pw) { fprintf(stderr, "%s: No such user %s.\n", whoami, optarg); exit(1); } locker_end(context); if (locker_init(&context, pw->pw_uid, NULL, NULL)) exit(1); } break; case 'v': verbose = 1; break; case 'x': mode = DETACH_FILESYSTEM; break; case 'y': options |= LOCKER_DETACH_OPT_UNAUTH; break; case 'z': options |= LOCKER_DETACH_OPT_UNZEPHYR; break; case 'd': case 'f': case 'L': case 's': fprintf(stderr, "%s: The '%c' flag is no longer supported.\n", whoami, opt); break; default: usage(); } } while (optind < argc && argv[optind][0] != '-') { gotname++; switch (mode) { case DETACH_FILESYSTEM: if (*argv[optind] == '/') { status = locker_detach(context, NULL, argv[optind], options, &at); } else { status = locker_detach(context, argv[optind], NULL, options, &at); } if (status == LOCKER_SUCCESS) { if (verbose) printf("%s: %s detached\n", whoami, at->name); locker_free_attachent(context, at); } else if (!LOCKER_DETACH_SUCCESS(status)) estatus = 2; break; case DETACH_EXPLICIT: status = locker_detach_explicit(context, type, argv[optind], NULL, options, &at); if (status == LOCKER_SUCCESS) { if (verbose) printf("%s: %s detached\n", whoami, at->name); locker_free_attachent(context, at); } else if (!LOCKER_DETACH_SUCCESS(status)) estatus = 2; break; case DETACH_BY_HOST: detach_by_host(context, argv[optind], options); break; } optind++; } } if (!gotname) usage(); locker_do_zsubs(context, LOCKER_ZEPHYR_UNSUBSCRIBE); locker_end(context); exit(estatus); } static void detach_by_host(locker_context context, char *host, int options) { struct hostent *h; h = gethostbyname(host); if (!h) { fprintf(stderr, "%s: Could not resolve hostname \"%s\".\n", whoami, host); exit(1); } locker_iterate_attachtab(context, locker_check_host, h->h_addr, detach_attachent, &options); } static int detach_attachent(locker_context context, locker_attachent *at, void *optionsp) { int status, options = *(int *)optionsp; status = locker_detach_attachent(context, at, options); if (status == LOCKER_SUCCESS && verbose) printf("%s: %s detached\n", whoami, at->name); return 0; } static void detach_all(locker_context context, int options) { locker_iterate_attachtab(context, NULL, NULL, detach_attachent, &options); } static void usage(void) { fprintf(stderr, "Usage: detach [options] filesystem ... [options] filesystem ...\n"); fprintf(stderr, " detach [options] mountpoint ...\n"); fprintf(stderr, " detach [options] -H host ...\n"); fprintf(stderr, " detach [options] -a\n"); exit(1); }