source: trunk/athena/bin/attach/attach.c @ 17985

Revision 17985, 10.0 KB checked in by ghudson, 22 years ago (diff)
Add support for local copies of lockers, and new -M option to turn it off.
Line 
1/* Copyright 1998 by the Massachusetts Institute of Technology.
2 *
3 * Permission to use, copy, modify, and distribute this
4 * software and its documentation for any purpose and without
5 * fee is hereby granted, provided that the above copyright
6 * notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting
8 * documentation, and that the name of M.I.T. not be used in
9 * advertising or publicity pertaining to distribution of the
10 * software without specific, written prior permission.
11 * M.I.T. makes no representations about the suitability of
12 * this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 */
15
16/* This is attach, which is used to attach lockers to workstations. */
17
18static const char rcsid[] = "$Id: attach.c,v 1.34 2002-10-17 05:19:50 ghudson Exp $";
19
20#include <netdb.h>
21#include <pwd.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26
27#include <locker.h>
28#include "attach.h"
29#include "agetopt.h"
30
31static void usage(void);
32static void attach_list(locker_context context, char *host);
33static int print_callback(locker_context context, locker_attachent *at,
34                          void *val);
35static void attach_print_entry(char *fs, char *mp, char *user, char *mode);
36static int attach_print(locker_context context, locker_attachent *at,
37                        void *data);
38static void attach_lookup(locker_context context, char *filesystem);
39
40static struct agetopt_option attach_options[] = {
41  { "noremap", 'a', 0 },
42  { "debug", 'd', 0 },
43  { "explicit", 'e', 0 },
44  { "force", 'f', 0 },
45  { "skipfsck", 'F', 0 },
46  { "remap", 'g', 0 },
47  { "nozephyr", 'h', 0 },
48  { "host", 'H', 0 },
49  { "lookup", 'l', 0 },
50  { "lock", 'L', 0 },
51  { "mountpoint", 'm', 1 },
52  { "nomap", 'n', 0 },
53  { "nosetuid", 'N', 0 },
54  { "nosuid", 'N', 0 },
55  { "master", 'M', 0 },
56  { "mountoptions", 'o', 1 },
57  { "override", 'O', 0 },
58  { "printpath", 'p', 0 },
59  { "quiet", 'q', 0 },
60  { "readonly", 'r', 0 },
61  { "spoofhost", 's', 1 },
62  { "setuid", 'S', 0 },
63  { "suid", 'S', 0 },
64  { "type", 't', 1 },
65  { "user", 'U', 1 },
66  { "verbose", 'v', 0 },
67  { "write", 'w', 0 },
68  { "noexplicit", 'x', 0 },
69  { "map", 'y', 0 },
70  { "zephyr", 'z', 0 },
71  { 0, 0, 0 }
72};
73
74locker_callback attach_callback = print_callback;
75
76enum { ATTACH_FILESYSTEM, ATTACH_EXPLICIT, ATTACH_LOOKUP, ATTACH_LIST_HOST };
77enum { ATTACH_QUIET, ATTACH_VERBOSE, ATTACH_PRINTPATH };
78
79int attach_main(int argc, char **argv)
80{
81  locker_context context;
82  locker_attachent *at;
83  int options = LOCKER_ATTACH_DEFAULT_OPTIONS;
84  char *type = "nfs", *mountpoint = NULL, *mountoptions = NULL;
85  int mode = ATTACH_FILESYSTEM, auth = LOCKER_AUTH_DEFAULT;
86  int output = ATTACH_VERBOSE, opt, gotname = 0;
87  int status, estatus = 0;
88
89  if (locker_init(&context, getuid(), NULL, NULL))
90    exit(1);
91
92  /* Wrap another while around the getopt so we can go through
93   * multiple cycles of "[options] lockers...".
94   */
95  while (optind < argc)
96    {
97      while ((opt = attach_getopt(argc, argv, attach_options)) != -1)
98        {
99          switch (opt)
100            {
101            case 'a':
102              options &= ~LOCKER_ATTACH_OPT_REAUTH;
103              break;
104
105            case 'e':
106              mode = ATTACH_EXPLICIT;
107              break;
108
109            case 'g':
110              options |= LOCKER_ATTACH_OPT_REAUTH;
111              break;
112
113            case 'h':
114              options &= ~LOCKER_ATTACH_OPT_ZEPHYR;
115              break;
116
117            case 'H':
118              mode = ATTACH_LIST_HOST;
119              break;
120
121            case 'l':
122              mode = ATTACH_LOOKUP;
123              break;
124
125            case 'L':
126              options |= LOCKER_ATTACH_OPT_LOCK;
127              break;
128
129            case 'm':
130              mountpoint = optarg;
131              break;
132
133            case 'M':
134              options |= LOCKER_ATTACH_OPT_MASTER;
135              break;
136
137            case 'n':
138              auth = LOCKER_AUTH_NONE;
139              break;
140
141            case 'N':
142              options &= ~LOCKER_ATTACH_OPT_ALLOW_SETUID;
143              break;
144
145            case 'o':
146              mountoptions = optarg;
147              break;
148
149            case 'O':
150              options |= LOCKER_ATTACH_OPT_OVERRIDE;
151              break;
152
153            case 'p':
154              output = ATTACH_PRINTPATH;
155              break;
156
157            case 'q':
158              output = ATTACH_QUIET;
159              break;
160
161            case 'r':
162              auth = LOCKER_AUTH_READONLY;
163              break;
164
165            case 'S':
166              options |= LOCKER_ATTACH_OPT_ALLOW_SETUID;
167              break;
168
169            case 't':
170              type = optarg;
171              break;
172
173            case 'U':
174              if (getuid() != 0)
175                {
176                  fprintf(stderr, "%s: You are not allowed to use the "
177                          "--user option.\n", whoami);
178                  exit(1);
179                }
180              else
181                {
182                  struct passwd *pw;
183
184                  pw = getpwnam(optarg);
185                  if (!pw)
186                    {
187                      fprintf(stderr, "%s: No such user %s.\n",
188                              whoami, optarg);
189                      exit(1);
190                    }
191                  locker_end(context);
192                  if (locker_init(&context, pw->pw_uid, NULL, NULL))
193                    exit(1);
194                }
195              break;
196
197            case 'v':
198              output = ATTACH_VERBOSE;
199              break;
200
201            case 'w':
202              auth = LOCKER_AUTH_READWRITE;
203              break;
204
205            case 'x':
206              mode = ATTACH_FILESYSTEM;
207              break;
208
209            case 'y':
210              auth = LOCKER_AUTH_DEFAULT;
211              break;
212
213            case 'z':
214              options |= LOCKER_ATTACH_OPT_ZEPHYR;
215              break;
216
217            case 'd':
218            case 'f':
219            case 's':
220              fprintf(stderr, "%s: The '%c' flag is no longer supported.\n",
221                      whoami, opt);
222              break;
223
224            default:
225              usage();
226            }
227        }
228
229      while (optind < argc && argv[optind][0] != '-')
230        {
231          gotname++;
232          switch (mode)
233            {
234            case ATTACH_FILESYSTEM:
235              status = locker_attach(context, argv[optind], mountpoint,
236                                     auth, options, mountoptions, &at);
237              if (LOCKER_ATTACH_SUCCESS(status))
238                {
239                  locker_attachent *ai;
240
241                  for (ai = at->next; ai; ai = ai->next)
242                    attach_callback(context, ai, &output);
243                  attach_callback(context, at, &output);
244                  locker_free_attachent(context, at);
245                }
246              else
247                estatus = 2;
248              break;
249
250            case ATTACH_EXPLICIT:
251              status = locker_attach_explicit(context, type, argv[optind],
252                                              mountpoint, auth, options,
253                                              mountoptions, &at);
254              if (LOCKER_ATTACH_SUCCESS(status))
255                {
256                  attach_callback(context, at, &output);
257                  locker_free_attachent(context, at);
258                }
259              else
260                estatus = 2;
261              break;
262
263            case ATTACH_LOOKUP:
264              attach_lookup(context, argv[optind]);
265              break;
266
267            case ATTACH_LIST_HOST:
268              attach_list(context, argv[optind]);
269              break;
270            }
271
272          /* -m only applies to the first locker after it is specified. */
273          mountpoint = NULL;
274
275          optind++;
276        }
277    }
278
279  /* If no locker names, and no mode options given, list attached
280   * lockers. Otherwise, if we didn't attach anything, give an error.
281   */
282  if (!gotname)
283    {
284      if (argc == optind && mode == ATTACH_FILESYSTEM)
285        attach_list(context, NULL);
286      else
287        usage();
288    }
289
290  locker_do_zsubs(context, LOCKER_ZEPHYR_SUBSCRIBE);
291  locker_end(context);
292
293  /* Must be return, not exit, since it might be returning to add_main. */
294  return estatus;
295}
296
297
298static void attach_list(locker_context context, char *host)
299{
300  struct hostent *h;
301
302  if (host)
303    {
304      h = gethostbyname(host);
305      if (!h)
306        {
307          fprintf(stderr, "%s: Could not resolve hostname \"%s\".\n",
308                  whoami, host);
309          exit(1);
310        }
311    }
312
313  attach_print_entry("filesystem", "mountpoint", "user", "mode");
314  attach_print_entry("----------", "----------", "----", "----");
315
316  if (host)
317    {
318      locker_iterate_attachtab(context, locker_check_host, h->h_addr,
319                               attach_print, NULL);
320    }
321  else
322    locker_iterate_attachtab(context, NULL, NULL, attach_print, NULL);
323}
324
325static int print_callback(locker_context context, locker_attachent *at,
326                          void *val)
327{
328  int *output = val;
329
330  if (*output == ATTACH_VERBOSE)
331    {
332      if (*at->hostdir)
333        {
334          fprintf(stderr, "%s: %s attached to %s for filesystem %s\n",
335                 whoami, at->hostdir, at->mountpoint, at->name);
336        }
337      else
338        {
339          fprintf(stderr, "%s: %s (%s) attached\n", whoami, at->name,
340                 at->mountpoint);
341        }
342    }
343  else if (*output == ATTACH_PRINTPATH)
344    printf("%s\n", at->mountpoint);
345
346  return LOCKER_SUCCESS;
347}
348
349static void attach_print_entry(char *fs, char *mp, char *user, char *mode)
350{
351  printf("%-22s %-22s %-18s %s\n", fs, mp, user, mode);
352}
353
354static int attach_print(locker_context context, locker_attachent *at,
355                        void *data)
356{
357  char *ownerlist, *p, optstr[32], *name;
358  struct passwd *pw;
359  int i;
360
361  /* Build name. */
362  if (at->flags & LOCKER_FLAG_NAMEFILE)
363    name = at->name;
364  else
365    {
366      name = malloc(strlen(at->name) + 3);
367      if (!name)
368        {
369          fprintf(stderr, "%s: Out of memory.\n", whoami);
370          exit(1);
371        }
372      sprintf(name, "(%s)", at->name);
373    }
374
375  /* Build ownerlist. */
376  p = ownerlist = malloc(9 * at->nowners + 2);
377  if (!ownerlist)
378    {
379      fprintf(stderr, "%s: Out of memory.\n", whoami);
380      exit(1);
381    }
382  if (at->nowners > 1)
383    *p++ = '{';
384  for (i = 0; i < at->nowners; i++)
385    {
386      if (i)
387        *p++ = ',';
388      pw = getpwuid(at->owners[i]);
389      if (pw)
390        p += sprintf(p, "%s", pw->pw_name);
391      else
392        p += sprintf(p, "#%lu", (unsigned long) at->owners[i]);
393    }
394  if (at->nowners > 1)
395    strcat(p, "}");
396
397  /* Build optstr. (32 characters is "long enough".) */
398  optstr[0] = at->mode;
399  optstr[1] = '\0';
400  if (at->flags & LOCKER_FLAG_NOSUID)
401    strcat(optstr, ",nosuid");
402  if (at->flags & LOCKER_FLAG_LOCKED)
403    strcat(optstr, ",locked");
404  if (at->flags & LOCKER_FLAG_KEEP)
405    strcat(optstr, ",perm");
406
407  attach_print_entry(name, at->mountpoint[0] == '/' ? at->mountpoint : "-",
408                     ownerlist, optstr);
409  free(ownerlist);
410  if (!(at->flags & LOCKER_FLAG_NAMEFILE))
411    free(name);
412
413  return LOCKER_SUCCESS;
414}
415
416static void attach_lookup(locker_context context, char *filesystem)
417{
418  int status, i;
419  char **fs;
420  void *cleanup;
421
422  status = locker_lookup_filsys(context, filesystem, &fs, &cleanup);
423  if (status == LOCKER_SUCCESS)
424    {
425      printf("%s resolves to:\n", filesystem);
426      for (i = 0; fs[i]; i++)
427        printf("%s\n", fs[i]);
428      locker_free_filesys(context, fs, cleanup);
429    }
430}
431
432static void usage(void)
433{
434  fprintf(stderr, "Usage: attach [options] filesystem ... [options] filesystem ...\n");
435  fprintf(stderr, "       attach -l filesystem\n");
436  fprintf(stderr, "       attach -H host\n");
437  fprintf(stderr, "       attach\n");
438  exit(1);
439}
Note: See TracBrowser for help on using the repository browser.