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

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