1 | /* Created by: Robert French |
---|
2 | * |
---|
3 | * $Source: /afs/dev.mit.edu/source/repository/athena/bin/attach/util.c,v $ |
---|
4 | * $Author: epeisach $ |
---|
5 | * |
---|
6 | * Copyright (c) 1988 by the Massachusetts Institute of Technology. |
---|
7 | */ |
---|
8 | |
---|
9 | static char *rcsid_util_c = "$Header: /afs/dev.mit.edu/source/repository/athena/bin/attach/util.c,v 1.18 1992-08-02 11:32:55 epeisach Exp $"; |
---|
10 | |
---|
11 | #include "attach.h" |
---|
12 | |
---|
13 | #include <sys/stat.h> |
---|
14 | #include <fcntl.h> |
---|
15 | #include <pwd.h> |
---|
16 | #include <grp.h> |
---|
17 | #include <signal.h> |
---|
18 | #ifdef HESIOD |
---|
19 | #include <hesiod.h> |
---|
20 | #endif |
---|
21 | |
---|
22 | #define TOKSEP " \t\r\n" |
---|
23 | |
---|
24 | #ifdef ultrix |
---|
25 | #define max(a,b) (((a) > (b)) ? (a) : (b)) |
---|
26 | #endif |
---|
27 | |
---|
28 | extern int sys_nerr; |
---|
29 | extern char *sys_errlist[]; |
---|
30 | |
---|
31 | char exp_hesline[BUFSIZ]; /* Place to store explicit */ |
---|
32 | char *exp_hesptr[2]; /* ``hesiod'' entry */ |
---|
33 | char *abort_msg = "Operation aborted\n"; |
---|
34 | |
---|
35 | static missarg(); |
---|
36 | |
---|
37 | /* |
---|
38 | * These routines provide a way of locking out interrupts during |
---|
39 | * critical sections of code. After the critical sections of code are |
---|
40 | * executed, if a SIGTERM or SIGINT had arrived before, the program |
---|
41 | * terminates then. |
---|
42 | */ |
---|
43 | |
---|
44 | int caught_signal = 0; |
---|
45 | static int in_critical_code_p = 0; |
---|
46 | |
---|
47 | #ifdef POSIX |
---|
48 | static sigset_t osigmask; |
---|
49 | #else |
---|
50 | static int osigmask; |
---|
51 | #endif |
---|
52 | |
---|
53 | /* |
---|
54 | * Signal handler for SIGTERM & SIGINT |
---|
55 | */ |
---|
56 | sig_catch sig_trap() |
---|
57 | { |
---|
58 | if (in_critical_code_p) { |
---|
59 | caught_signal++; |
---|
60 | return; |
---|
61 | } |
---|
62 | terminate_program(); |
---|
63 | } |
---|
64 | |
---|
65 | /* |
---|
66 | * Enter critical section of code |
---|
67 | */ |
---|
68 | start_critical_code() |
---|
69 | { |
---|
70 | #ifdef POSIX |
---|
71 | sigset_t mysigmask; |
---|
72 | |
---|
73 | sigemptyset(&mysigmask); |
---|
74 | sigaddset(&mysigmask, SIGTSTP); |
---|
75 | sigaddset(&mysigmask, SIGTTIN); |
---|
76 | sigaddset(&mysigmask, SIGTTOU); |
---|
77 | |
---|
78 | if (in_critical_code_p++ == 0) |
---|
79 | sigprocmask(SIG_BLOCK, &mysigmask, &osigmask); |
---|
80 | #else |
---|
81 | if (in_critical_code_p++ == 0) |
---|
82 | osigmask=sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU)); |
---|
83 | #endif |
---|
84 | } |
---|
85 | |
---|
86 | /* |
---|
87 | * Exit critical section of code |
---|
88 | */ |
---|
89 | end_critical_code() |
---|
90 | { |
---|
91 | if (--in_critical_code_p == 0) { |
---|
92 | if (caught_signal) |
---|
93 | terminate_program(); |
---|
94 | #ifdef POSIX |
---|
95 | sigprocmask(SIG_SETMASK, &osigmask, (sigset_t *)0); |
---|
96 | #else |
---|
97 | sigsetmask(osigmask); |
---|
98 | #endif |
---|
99 | } |
---|
100 | } |
---|
101 | |
---|
102 | /* |
---|
103 | * terminate the program |
---|
104 | */ |
---|
105 | terminate_program() |
---|
106 | { |
---|
107 | exit(ERR_INTERRUPT); |
---|
108 | } |
---|
109 | |
---|
110 | /* |
---|
111 | * LOCK the mtab - wait for it if it's already locked |
---|
112 | */ |
---|
113 | |
---|
114 | /* |
---|
115 | * Unfortunately, mount and umount don't honor lock files, so these |
---|
116 | * locks are only valid for other attach processes. |
---|
117 | */ |
---|
118 | |
---|
119 | static int mtab_lock_fd = -1; |
---|
120 | |
---|
121 | lock_mtab() |
---|
122 | { |
---|
123 | char *lockfn; |
---|
124 | #ifdef POSIX |
---|
125 | struct flock fl; |
---|
126 | #endif |
---|
127 | |
---|
128 | if (mtab_lock_fd < 0) { |
---|
129 | if (!(lockfn = malloc(strlen(mtab_fn)+6))) { |
---|
130 | fprintf(stderr, "Can't malloc lockfile filename.\n"); |
---|
131 | fprintf(stderr, abort_msg); |
---|
132 | exit(ERR_FATAL); |
---|
133 | } |
---|
134 | (void) strcpy(lockfn, mtab_fn); |
---|
135 | (void) strcat(lockfn, ".lock"); |
---|
136 | mtab_lock_fd = open(lockfn, O_CREAT|O_RDWR, 0644); |
---|
137 | if (mtab_lock_fd < 0) { |
---|
138 | fprintf(stderr,"Can't open %s: %s\n", lockfn, |
---|
139 | sys_errlist[errno]); |
---|
140 | fprintf(stderr, abort_msg); |
---|
141 | exit(ERR_FATAL); |
---|
142 | } |
---|
143 | } |
---|
144 | #ifdef POSIX |
---|
145 | fl.l_type = F_WRLCK; |
---|
146 | fl.l_whence = SEEK_SET; |
---|
147 | fl.l_start = 0; |
---|
148 | fl.l_len = 0; |
---|
149 | fl.l_pid = getpid(); |
---|
150 | fcntl(mtab_lock_fd, F_SETLKW, &fl); |
---|
151 | #else |
---|
152 | flock(mtab_lock_fd, LOCK_EX); |
---|
153 | #endif |
---|
154 | } |
---|
155 | |
---|
156 | /* |
---|
157 | * UNLOCK the mtab |
---|
158 | */ |
---|
159 | unlock_mtab() |
---|
160 | { |
---|
161 | close(mtab_lock_fd); |
---|
162 | mtab_lock_fd = -1; |
---|
163 | } |
---|
164 | |
---|
165 | /* |
---|
166 | * Convert a string type to a filesystem type entry |
---|
167 | */ |
---|
168 | struct _fstypes *get_fs(s) |
---|
169 | char *s; |
---|
170 | { |
---|
171 | int i; |
---|
172 | |
---|
173 | if (s && *s) { |
---|
174 | for (i=0;fstypes[i].name;i++) { |
---|
175 | if (!strcasecmp(fstypes[i].name, s)) |
---|
176 | return (&fstypes[i]); |
---|
177 | } |
---|
178 | } |
---|
179 | return (NULL); |
---|
180 | } |
---|
181 | |
---|
182 | /* |
---|
183 | * Build a Hesiod line either from a Hesiod query or internal frobbing |
---|
184 | * if explicit is set. |
---|
185 | */ |
---|
186 | char **build_hesiod_line(name) |
---|
187 | char *name; |
---|
188 | { |
---|
189 | char **realhes; |
---|
190 | struct _fstypes *fsp; |
---|
191 | |
---|
192 | if (!explicit) { |
---|
193 | realhes = conf_filsys_resolve(name); |
---|
194 | #ifdef HESIOD |
---|
195 | if (!realhes || !*realhes) |
---|
196 | realhes = hes_resolve(name, "filsys"); |
---|
197 | #endif |
---|
198 | if (!realhes || !*realhes) |
---|
199 | fprintf(stderr, "%s: Can't resolve name\n", name); |
---|
200 | return (realhes); |
---|
201 | } |
---|
202 | |
---|
203 | fsp = get_fs(filsys_type ? filsys_type : "NFS"); |
---|
204 | if (!fsp) |
---|
205 | return (NULL); |
---|
206 | if (!fsp->explicit) { |
---|
207 | fprintf(stderr, "Explicit definitions for type %s not allowed\n", |
---|
208 | filsys_type); |
---|
209 | return (NULL); |
---|
210 | } |
---|
211 | |
---|
212 | return ((fsp->explicit)(name)); |
---|
213 | } |
---|
214 | |
---|
215 | /* |
---|
216 | * Parse a Hesiod record |
---|
217 | * |
---|
218 | * Returns 0 on success, -1 on failure |
---|
219 | */ |
---|
220 | int parse_hes(hes, at, errorname) |
---|
221 | char *hes, *errorname; |
---|
222 | struct _attachtab *at; |
---|
223 | { |
---|
224 | char *cp, *t; |
---|
225 | struct hostent *hent; |
---|
226 | int type; |
---|
227 | |
---|
228 | bzero(at, sizeof(struct _attachtab)); |
---|
229 | |
---|
230 | if (!*hes) |
---|
231 | goto bad_hes_line; |
---|
232 | |
---|
233 | |
---|
234 | at->fs = get_fs(strtok(hes, TOKSEP)); |
---|
235 | if (!at->fs) |
---|
236 | goto bad_hes_line; |
---|
237 | type = at->fs->type; |
---|
238 | |
---|
239 | if (type & TYPE_ERR) { |
---|
240 | strncpy(at->hostdir, strtok(NULL, ""), sizeof(at->hostdir)); |
---|
241 | return(0); |
---|
242 | } |
---|
243 | |
---|
244 | if (!(cp = strtok(NULL, (type & TYPE_MUL) ? "" : TOKSEP))) |
---|
245 | goto bad_hes_line; |
---|
246 | strcpy(at->hostdir, cp); |
---|
247 | |
---|
248 | if (type & ~(TYPE_UFS | TYPE_AFS | TYPE_MUL)) { |
---|
249 | if (!(cp = strtok(NULL, TOKSEP))) |
---|
250 | goto bad_hes_line; |
---|
251 | strcpy(at->host, cp); |
---|
252 | } else |
---|
253 | strcpy(at->host, "localhost"); |
---|
254 | |
---|
255 | if (type & TYPE_MUL) { |
---|
256 | t = at->hostdir; |
---|
257 | while (t = index(t,' ')) |
---|
258 | *t = ','; |
---|
259 | at->mode = '-'; |
---|
260 | strcpy(at->mntpt, "localhost"); |
---|
261 | } else { |
---|
262 | |
---|
263 | if (!(cp = strtok(NULL, TOKSEP))) |
---|
264 | goto bad_hes_line; |
---|
265 | at->mode = *cp; |
---|
266 | if (at->mode == 'x') |
---|
267 | at->mode = 'w'; /* Backwards compatibility */ |
---|
268 | if (at->fs->good_flags) { |
---|
269 | if (!index(at->fs->good_flags, at->mode)) |
---|
270 | goto bad_hes_line; /* Bad attach mode */ |
---|
271 | } |
---|
272 | |
---|
273 | if (!(cp = strtok(NULL, TOKSEP))) |
---|
274 | goto bad_hes_line; |
---|
275 | strcpy(at->mntpt, cp); |
---|
276 | } |
---|
277 | |
---|
278 | if (type & ~(TYPE_UFS | TYPE_AFS | TYPE_MUL)) { |
---|
279 | hent = gethostbyname(at->host); |
---|
280 | if (!hent) { |
---|
281 | fprintf(stderr,"%s: Can't resolve host %s\n",errorname, |
---|
282 | at->host); |
---|
283 | fprintf(stderr, abort_msg); |
---|
284 | return(-1); |
---|
285 | } |
---|
286 | bcopy(hent->h_addr_list[0], &at->hostaddr[0].s_addr, 4); |
---|
287 | strcpy(at->host, hent->h_name); |
---|
288 | } else |
---|
289 | at->hostaddr[0].s_addr = (long) 0; |
---|
290 | return(0); |
---|
291 | |
---|
292 | bad_hes_line: |
---|
293 | fprintf(stderr,"Badly formatted filesystem definition\n"); |
---|
294 | fprintf(stderr, abort_msg); |
---|
295 | return(-1); |
---|
296 | } |
---|
297 | |
---|
298 | /* |
---|
299 | * Make the directories necessary for a mount point - set the number |
---|
300 | * of directories created in the attachtab structure |
---|
301 | */ |
---|
302 | int make_mntpt(at) |
---|
303 | struct _attachtab *at; |
---|
304 | { |
---|
305 | char bfr[BUFSIZ],*ptr; |
---|
306 | int oldmask; |
---|
307 | struct stat statbuf; |
---|
308 | |
---|
309 | strcpy(bfr, at->mntpt); |
---|
310 | if (at->fs->flags & AT_FS_PARENTMNTPT) { |
---|
311 | ptr = rindex(bfr, '/'); |
---|
312 | if (ptr) |
---|
313 | *ptr = 0; |
---|
314 | else |
---|
315 | return(SUCCESS); |
---|
316 | } |
---|
317 | |
---|
318 | if (!stat(bfr, &statbuf)) { |
---|
319 | if ((statbuf.st_mode & S_IFMT) == S_IFDIR) |
---|
320 | return (SUCCESS); |
---|
321 | fprintf(stderr, "%s: %s is not a directory\n", at->hesiodname, |
---|
322 | at->mntpt); |
---|
323 | return (FAILURE); |
---|
324 | } |
---|
325 | |
---|
326 | oldmask = umask(022); |
---|
327 | |
---|
328 | ptr = bfr+1; /* Pass initial / */ |
---|
329 | |
---|
330 | at->rmdir = 0; |
---|
331 | |
---|
332 | while (ptr && *ptr) { |
---|
333 | strcpy(bfr, at->mntpt); |
---|
334 | ptr = index(ptr, '/'); |
---|
335 | if (ptr) |
---|
336 | *ptr++ = '\0'; |
---|
337 | if (debug_flag) |
---|
338 | printf("Making directory %s (%s)\n", bfr, ptr ? ptr : ""); |
---|
339 | if (mkdir(bfr, 0777)) { |
---|
340 | if (errno == EEXIST) |
---|
341 | continue; |
---|
342 | fprintf(stderr, "%s: Can't create directory %s: %s\n", |
---|
343 | at->hesiodname, bfr, sys_errlist[errno]); |
---|
344 | umask(oldmask); |
---|
345 | return (FAILURE); |
---|
346 | } |
---|
347 | else |
---|
348 | at->rmdir++; |
---|
349 | } |
---|
350 | umask(oldmask); |
---|
351 | return (SUCCESS); |
---|
352 | } |
---|
353 | |
---|
354 | /* |
---|
355 | * Delete a previously main mountpoint |
---|
356 | */ |
---|
357 | int rm_mntpt(at) |
---|
358 | struct _attachtab *at; |
---|
359 | { |
---|
360 | char bfr[BUFSIZ], *ptr; |
---|
361 | |
---|
362 | strcpy(bfr, at->mntpt); |
---|
363 | ptr = bfr; |
---|
364 | |
---|
365 | if (at->fs->flags & AT_FS_PARENTMNTPT) { |
---|
366 | ptr = rindex(bfr, '/'); |
---|
367 | if (ptr) |
---|
368 | *ptr = 0; |
---|
369 | else |
---|
370 | return(SUCCESS); |
---|
371 | } |
---|
372 | while (at->rmdir--) { |
---|
373 | if (debug_flag) |
---|
374 | printf("Deleting directory %s (%s)\n", bfr, ptr ? ptr : ""); |
---|
375 | if (rmdir(bfr)) { |
---|
376 | if (errno != ENOENT) { |
---|
377 | fprintf(stderr, |
---|
378 | "%s: Can't remove directory %s: %s\n", |
---|
379 | at->hesiodname, ptr, |
---|
380 | sys_errlist[errno]); |
---|
381 | return (FAILURE); |
---|
382 | } |
---|
383 | } |
---|
384 | ptr = rindex(bfr, '/'); |
---|
385 | if (ptr) |
---|
386 | *ptr = '\0'; |
---|
387 | else |
---|
388 | return (SUCCESS); |
---|
389 | } |
---|
390 | return (SUCCESS); |
---|
391 | } |
---|
392 | |
---|
393 | /* |
---|
394 | * Internal spiffed up getopt |
---|
395 | */ |
---|
396 | char internal_getopt(arg, cl) |
---|
397 | char *arg; |
---|
398 | struct command_list *cl; |
---|
399 | { |
---|
400 | int i; |
---|
401 | |
---|
402 | for (i=0;cl[i].small;i++) { |
---|
403 | if (cl[i].large && !strcmp(cl[i].large, arg)) |
---|
404 | return (cl[i].small[1]); |
---|
405 | if (!strcmp(cl[i].small, arg)) |
---|
406 | return (cl[i].small[1]); |
---|
407 | } |
---|
408 | return ('?'); |
---|
409 | } |
---|
410 | |
---|
411 | /* |
---|
412 | * Format a hesiod name into a name in /tmp...including replacing / |
---|
413 | * with @, etc. |
---|
414 | */ |
---|
415 | make_temp_name(filename, name) |
---|
416 | char *filename; |
---|
417 | char *name; |
---|
418 | { |
---|
419 | strcpy(filename, "/tmp/attach_"); |
---|
420 | filename = filename+strlen(filename); |
---|
421 | |
---|
422 | while (*name) { |
---|
423 | if (*name == '/') |
---|
424 | *filename++ = '@'; |
---|
425 | else |
---|
426 | *filename++ = *name; |
---|
427 | name++; |
---|
428 | } |
---|
429 | *filename = '\0'; |
---|
430 | } |
---|
431 | |
---|
432 | /* |
---|
433 | * Check to see if a filesystem is really being frobbed with by |
---|
434 | * another attach process. |
---|
435 | */ |
---|
436 | |
---|
437 | int really_in_use(name) |
---|
438 | char *name; |
---|
439 | { |
---|
440 | int fd, ret; |
---|
441 | char filename[BUFSIZ]; |
---|
442 | #ifdef POSIX |
---|
443 | struct flock fl; |
---|
444 | #endif |
---|
445 | |
---|
446 | make_temp_name(filename, name); |
---|
447 | |
---|
448 | if (debug_flag) |
---|
449 | printf("Checking lock on %s\n", filename); |
---|
450 | |
---|
451 | fd = open(filename, O_RDWR, 0644); |
---|
452 | if (!fd) |
---|
453 | return (0); |
---|
454 | |
---|
455 | #ifdef POSIX |
---|
456 | fl.l_type = F_WRLCK; |
---|
457 | fl.l_whence = SEEK_SET; |
---|
458 | fl.l_start = 0; |
---|
459 | fl.l_len = 0; |
---|
460 | fl.l_pid = getpid(); |
---|
461 | ret = (fcntl(fd, F_SETLK, &fl)==-1 && errno == EAGAIN); |
---|
462 | #else |
---|
463 | ret = (flock(fd, LOCK_EX | LOCK_NB) == -1 && errno == EWOULDBLOCK); |
---|
464 | #endif |
---|
465 | |
---|
466 | close(fd); |
---|
467 | return (ret); |
---|
468 | } |
---|
469 | |
---|
470 | /* |
---|
471 | * Mark a filesystem as being frobbed with |
---|
472 | */ |
---|
473 | |
---|
474 | void mark_in_use(name) |
---|
475 | char *name; |
---|
476 | { |
---|
477 | static int fd; |
---|
478 | static char filename[BUFSIZ]; |
---|
479 | #ifdef POSIX |
---|
480 | struct flock fl; |
---|
481 | #endif |
---|
482 | |
---|
483 | if (!name) { |
---|
484 | if (debug_flag) |
---|
485 | printf("Removing lock on %s\n", filename); |
---|
486 | close(fd); |
---|
487 | unlink(filename); |
---|
488 | return; |
---|
489 | } |
---|
490 | |
---|
491 | make_temp_name(filename, name); |
---|
492 | |
---|
493 | if (debug_flag) |
---|
494 | printf("Setting lock on %s: ", filename); |
---|
495 | |
---|
496 | /* |
---|
497 | * Unlink the old file in case someone else already has a lock on |
---|
498 | * it...we'll override them with our new file. |
---|
499 | */ |
---|
500 | unlink(filename); |
---|
501 | fd = open(filename, O_CREAT|O_RDWR, 0644); |
---|
502 | if (!fd) { |
---|
503 | fprintf(stderr,"Can't open %s: %s\n", filename, |
---|
504 | sys_errlist[errno]); |
---|
505 | fprintf(stderr, abort_msg); |
---|
506 | exit(ERR_FATAL); |
---|
507 | } |
---|
508 | |
---|
509 | if (debug_flag) |
---|
510 | printf("%d\n", fd); |
---|
511 | |
---|
512 | #ifdef POSIX |
---|
513 | fl.l_type = F_WRLCK; |
---|
514 | fl.l_whence = SEEK_SET; |
---|
515 | fl.l_start = 0; |
---|
516 | fl.l_len = 0; |
---|
517 | fl.l_pid = getpid(); |
---|
518 | fcntl(fd, F_SETLKW, &fl); |
---|
519 | #else |
---|
520 | flock(fd, LOCK_EX); |
---|
521 | #endif |
---|
522 | } |
---|
523 | |
---|
524 | #ifdef DEBUG |
---|
525 | /* |
---|
526 | * Dump used file descriptors...useful for debugging |
---|
527 | */ |
---|
528 | |
---|
529 | fd_dump() |
---|
530 | { |
---|
531 | int i; |
---|
532 | char b; |
---|
533 | |
---|
534 | printf("FD's in use: "); |
---|
535 | for (i=0;i<64;i++) |
---|
536 | if (read(i,&b,0) >= 0) |
---|
537 | printf("%d ",i); |
---|
538 | printf("\n"); |
---|
539 | } |
---|
540 | #endif |
---|
541 | |
---|
542 | /* |
---|
543 | * String comparison for filesystem names - case insensitive for hesiod, |
---|
544 | * sensitive for explicit. |
---|
545 | */ |
---|
546 | |
---|
547 | int hescmp(at, s) |
---|
548 | struct _attachtab *at; |
---|
549 | char *s; |
---|
550 | { |
---|
551 | if (at->explicit) |
---|
552 | return (strcmp(at->hesiodname, s)); |
---|
553 | return (strcasecmp(at->hesiodname, s)); |
---|
554 | } |
---|
555 | |
---|
556 | /* |
---|
557 | * Duplicate a string in malloc'ed memory |
---|
558 | */ |
---|
559 | char *strdup(s) |
---|
560 | char *s; |
---|
561 | { |
---|
562 | register char *cp; |
---|
563 | |
---|
564 | if (!(cp = malloc(strlen(s)+1))) { |
---|
565 | fprintf(stderr, "attach: out of memory, exiting...\n"); |
---|
566 | exit(1); |
---|
567 | } |
---|
568 | return(strcpy(cp,s)); |
---|
569 | } |
---|
570 | |
---|
571 | /* |
---|
572 | * Check to see if we have root priv's; give an error if we don't. |
---|
573 | */ |
---|
574 | void check_root_privs(progname) |
---|
575 | char *progname; |
---|
576 | { |
---|
577 | if (!real_uid || !effective_uid || (debug_flag)) |
---|
578 | return; |
---|
579 | fprintf(stderr, |
---|
580 | "%s must be setuid to root for this operation to succeed.\n", |
---|
581 | progname); |
---|
582 | exit(ERR_FATAL); |
---|
583 | /* NOTREACHED */ |
---|
584 | } |
---|
585 | |
---|
586 | void add_options(mopt, string) |
---|
587 | struct mntopts *mopt; |
---|
588 | char *string; |
---|
589 | { |
---|
590 | char *next, *arg, *str, *orig_str; |
---|
591 | |
---|
592 | orig_str = str = strdup(string); |
---|
593 | while (str && *str) { |
---|
594 | next = index(str, ','); |
---|
595 | if (next) { |
---|
596 | *next++ = '\0'; |
---|
597 | } |
---|
598 | arg = index(str, '='); |
---|
599 | if (arg) |
---|
600 | *arg++ = '\0'; |
---|
601 | if (!strcmp(str, "ro")) { |
---|
602 | mopt->flags |= M_RDONLY; |
---|
603 | #if defined(ultrix) && defined(NFS) |
---|
604 | if (mopt->type == MOUNT_NFS) { |
---|
605 | mopt->tsa.nfs.gfs_flags |= M_RONLY; |
---|
606 | mopt->tsa.nfs.flags |= NFSMNT_RONLY; |
---|
607 | } |
---|
608 | #endif /* ultrix && NFS */ |
---|
609 | } else if (!strcmp(str, "rw")) { |
---|
610 | #ifdef ultrix |
---|
611 | mopt->flags &= ~M_RDONLY; |
---|
612 | mopt->tsa.nfs.gfs_flags &= ~M_RONLY; |
---|
613 | mopt->tsa.nfs.flags &= ~NFSMNT_RONLY; |
---|
614 | #else /* !ultrix */ |
---|
615 | mopt->flags &= ~M_RDONLY; |
---|
616 | #endif /* ultrix */ |
---|
617 | } |
---|
618 | #ifdef ultrix |
---|
619 | /* process other ultrix options */ |
---|
620 | else if (!strcmp(str, "force")) { |
---|
621 | #ifdef NFS |
---|
622 | if (mopt->type == MOUNT_NFS) |
---|
623 | mopt->tsa.nfs.gfs_flags |= M_FORCE; |
---|
624 | else |
---|
625 | #endif /* NFS */ |
---|
626 | if (mopt->type == MOUNT_UFS) |
---|
627 | mopt->tsa.ufs.ufs_flags |= M_FORCE; |
---|
628 | } else if (!strcmp(str, "sync")) { |
---|
629 | #ifdef NFS |
---|
630 | if (mopt->type == MOUNT_NFS) |
---|
631 | mopt->tsa.nfs.gfs_flags |= M_SYNC; |
---|
632 | else |
---|
633 | #endif /* NFS */ |
---|
634 | if (mopt->type == MOUNT_UFS) |
---|
635 | mopt->tsa.ufs.ufs_flags |= M_SYNC; |
---|
636 | } else if (!strcmp(str, "pgthresh")) { |
---|
637 | int pgthresh; |
---|
638 | |
---|
639 | if (!arg) { |
---|
640 | missarg("pgthresh"); |
---|
641 | continue; |
---|
642 | } |
---|
643 | pgthresh = atoi(arg); |
---|
644 | pgthresh = max (pgthresh, MINPGTHRESH/PGUNITS); |
---|
645 | #ifdef NFS |
---|
646 | if (mopt->type == MOUNT_NFS) { |
---|
647 | mopt->tsa.nfs.pg_thresh = pgthresh; |
---|
648 | mopt->tsa.nfs.flags |= NFSMNT_PGTHRESH; |
---|
649 | } else |
---|
650 | #endif /* NFS */ |
---|
651 | if (mopt->type == MOUNT_UFS) |
---|
652 | mopt->tsa.ufs.ufs_pgthresh = pgthresh; |
---|
653 | } else if (!strcmp(str, "quota")) { |
---|
654 | if (mopt->type == MOUNT_UFS) |
---|
655 | mopt->tsa.ufs.ufs_flags |= M_QUOTA; |
---|
656 | } else if (!strcmp(str, "noexec")) { |
---|
657 | #ifdef NFS |
---|
658 | if (mopt->type == MOUNT_NFS) |
---|
659 | mopt->tsa.nfs.gfs_flags |= M_NOEXEC; |
---|
660 | else |
---|
661 | #endif /* NFS */ |
---|
662 | if (mopt->type == MOUNT_UFS) |
---|
663 | mopt->tsa.ufs.ufs_flags |= M_NOEXEC; |
---|
664 | } else if (!strcmp(str, "nocache")) { |
---|
665 | #ifdef NFS |
---|
666 | if (mopt->type == MOUNT_NFS) |
---|
667 | mopt->tsa.nfs.gfs_flags |= M_NOCACHE; |
---|
668 | else |
---|
669 | #endif /* NFS */ |
---|
670 | if (mopt->type == MOUNT_UFS) |
---|
671 | mopt->tsa.ufs.ufs_flags |= M_NOCACHE; |
---|
672 | } else if (!strcmp(str, "nodev")) { |
---|
673 | #ifdef NFS |
---|
674 | if (mopt->type == MOUNT_NFS) |
---|
675 | mopt->tsa.nfs.gfs_flags |= M_NODEV; |
---|
676 | else |
---|
677 | #endif /* NFS */ |
---|
678 | if (mopt->type == MOUNT_UFS) |
---|
679 | mopt->tsa.ufs.ufs_flags |= M_NODEV; |
---|
680 | } |
---|
681 | #endif /* ultrix */ |
---|
682 | #ifndef AIX |
---|
683 | else if (!strcmp(str, "nosuid")) { |
---|
684 | #ifdef ultrix |
---|
685 | #ifdef NFS |
---|
686 | if (mopt->type == MOUNT_NFS) |
---|
687 | mopt->tsa.nfs.gfs_flags |= M_NOSUID; |
---|
688 | else |
---|
689 | #endif /* NFS */ |
---|
690 | if (mopt->type == MOUNT_UFS) |
---|
691 | mopt->tsa.ufs.ufs_flags |= M_NOSUID; |
---|
692 | #else /* !ultrix */ |
---|
693 | mopt->flags |= M_NOSUID; |
---|
694 | #endif /* ultrix */ |
---|
695 | } |
---|
696 | #endif /* AIX */ |
---|
697 | #ifdef NFS |
---|
698 | else if (mopt->type == MOUNT_NFS) { |
---|
699 | if (!strcmp(str, "soft")) |
---|
700 | mopt->tsa.nfs.flags |= NFSMNT_SOFT; |
---|
701 | else if (!strcmp(str, "hard")) |
---|
702 | mopt->tsa.nfs.flags &= ~NFSMNT_SOFT; |
---|
703 | else if (!strcmp(str, "rsize")) { |
---|
704 | if (!arg) { |
---|
705 | missarg("rsize"); |
---|
706 | } |
---|
707 | mopt->tsa.nfs.rsize = atoi(arg); |
---|
708 | mopt->tsa.nfs.flags |= NFSMNT_RSIZE; |
---|
709 | } else if (!strcmp(str, "wsize")) { |
---|
710 | if (!arg) { |
---|
711 | missarg("wsize"); |
---|
712 | continue; |
---|
713 | } |
---|
714 | mopt->tsa.nfs.wsize = atoi(arg); |
---|
715 | mopt->tsa.nfs.flags |= NFSMNT_WSIZE; |
---|
716 | } else if (!strcmp(str, "timeo")) { |
---|
717 | if (!arg) { |
---|
718 | missarg("timeo"); |
---|
719 | continue; |
---|
720 | } |
---|
721 | mopt->tsa.nfs.timeo = atoi(arg); |
---|
722 | mopt->tsa.nfs.flags |= NFSMNT_TIMEO; |
---|
723 | } else if (!strcmp(str, "retrans")) { |
---|
724 | if (!arg) { |
---|
725 | missarg("retrans"); |
---|
726 | continue; |
---|
727 | } |
---|
728 | mopt->tsa.nfs.retrans = atoi(arg); |
---|
729 | mopt->tsa.nfs.flags |= NFSMNT_RETRANS; |
---|
730 | } else if (!strcmp(str, "port")) { |
---|
731 | if (!arg) { |
---|
732 | missarg("port"); |
---|
733 | continue; |
---|
734 | } |
---|
735 | mopt->nfs_port = atoi(arg); |
---|
736 | } |
---|
737 | #ifdef ultrix |
---|
738 | else if (!strcmp(str, "intr")) { |
---|
739 | mopt->tsa.nfs.flags |= NFSMNT_INT; |
---|
740 | } |
---|
741 | #endif /* ultrix */ |
---|
742 | } |
---|
743 | #endif |
---|
744 | str = next; |
---|
745 | } |
---|
746 | free(orig_str); |
---|
747 | } |
---|
748 | |
---|
749 | static missarg(arg) |
---|
750 | char *arg; |
---|
751 | { |
---|
752 | fprintf(stderr, |
---|
753 | "%s: missing argument to mount option; ignoring.\n", |
---|
754 | arg); |
---|
755 | } |
---|
756 | |
---|
757 | /* |
---|
758 | * Return a string describing the options in the mount options structure |
---|
759 | */ |
---|
760 | char *stropt(mopt) |
---|
761 | struct mntopts mopt; |
---|
762 | { |
---|
763 | static char buff[BUFSIZ]; |
---|
764 | char tmp[80]; |
---|
765 | |
---|
766 | buff[0] = '\0'; |
---|
767 | |
---|
768 | if (mopt.flags & M_RDONLY) |
---|
769 | (void) strcat(buff, ",ro"); |
---|
770 | else |
---|
771 | (void) strcat(buff, ",rw"); |
---|
772 | #ifdef M_NOSUID |
---|
773 | #ifdef ultrix |
---|
774 | #ifdef NFS |
---|
775 | if (mopt.type == MOUNT_NFS && (mopt.tsa.nfs.gfs_flags & M_NOSUID)) |
---|
776 | (void) strcat(buff, ",nosuid"); |
---|
777 | else |
---|
778 | #endif /* NFS */ |
---|
779 | if (mopt.type == MOUNT_UFS && (mopt.tsa.ufs.ufs_flags & M_NOSUID)) |
---|
780 | (void) strcat(buff, ",nosuid"); |
---|
781 | #else /* !ultrix */ |
---|
782 | if (mopt.flags & M_NOSUID) |
---|
783 | (void) strcat(buff, ",nosuid"); |
---|
784 | #endif /* ultrix */ |
---|
785 | #endif /* M_NOSUID */ |
---|
786 | #ifdef NFS |
---|
787 | if (mopt.type == MOUNT_NFS) { |
---|
788 | #ifdef ultrix |
---|
789 | if (mopt.tsa.nfs.gfs_flags & M_FORCE) |
---|
790 | (void) strcat(buff, ",force"); |
---|
791 | if (mopt.tsa.nfs.gfs_flags & M_SYNC) |
---|
792 | (void) strcat(buff, ",force"); |
---|
793 | if (mopt.tsa.nfs.flags & NFSMNT_PGTHRESH) { |
---|
794 | (void) strcat(buff, ",pgthresh="); |
---|
795 | (void) sprintf(tmp, "%d", mopt.tsa.nfs.pg_thresh); |
---|
796 | (void) strcat(buff, tmp); |
---|
797 | } |
---|
798 | if (mopt.tsa.nfs.gfs_flags & M_NOEXEC) |
---|
799 | (void) strcat(buff, ",noexec"); |
---|
800 | if (mopt.tsa.nfs.gfs_flags & M_NOCACHE) |
---|
801 | (void) strcat(buff, ",nocache"); |
---|
802 | if (mopt.tsa.nfs.gfs_flags & M_NODEV) |
---|
803 | (void) strcat(buff, ",nodev"); |
---|
804 | if (mopt.tsa.nfs.flags & NFSMNT_INT) |
---|
805 | (void) strcat(buff, ",intr"); |
---|
806 | #endif /* ultrix */ |
---|
807 | if (mopt.tsa.nfs.flags & NFSMNT_SOFT) |
---|
808 | (void) strcat(buff, ",soft"); |
---|
809 | if (mopt.tsa.nfs.flags & NFSMNT_RSIZE) { |
---|
810 | (void) strcat(buff, ",rsize="); |
---|
811 | (void) sprintf(tmp, "%d", mopt.tsa.nfs.rsize); |
---|
812 | (void) strcat(buff, tmp); |
---|
813 | } |
---|
814 | if (mopt.tsa.nfs.flags & NFSMNT_WSIZE) { |
---|
815 | (void) strcat(buff, ",wsize="); |
---|
816 | (void) sprintf(tmp, "%d", mopt.tsa.nfs.wsize); |
---|
817 | (void) strcat(buff, tmp); |
---|
818 | } |
---|
819 | if (mopt.tsa.nfs.flags & NFSMNT_TIMEO) { |
---|
820 | (void) strcat(buff, ",timeo="); |
---|
821 | (void) sprintf(tmp, "%d", mopt.tsa.nfs.timeo); |
---|
822 | (void) strcat(buff, tmp); |
---|
823 | } |
---|
824 | if (mopt.tsa.nfs.flags & NFSMNT_RETRANS) { |
---|
825 | (void) strcat(buff, ",retrans="); |
---|
826 | (void) sprintf(tmp, "%d", mopt.tsa.nfs.retrans); |
---|
827 | (void) strcat(buff, tmp); |
---|
828 | } |
---|
829 | if (mopt.nfs_port) { |
---|
830 | (void) strcat(buff, ",port="); |
---|
831 | (void) sprintf(tmp, "%d", mopt.nfs_port); |
---|
832 | (void) strcat(buff, tmp); |
---|
833 | } |
---|
834 | } |
---|
835 | #endif /* NFS */ |
---|
836 | #ifdef ultrix |
---|
837 | else if (mopt.type == MOUNT_UFS) { |
---|
838 | if (mopt.tsa.ufs.ufs_flags & M_QUOTA) |
---|
839 | (void) strcat(buff, ",quota"); |
---|
840 | if (mopt.tsa.ufs.ufs_flags & M_FORCE) |
---|
841 | (void) strcat(buff, ",force"); |
---|
842 | if (mopt.tsa.ufs.ufs_flags & M_SYNC) |
---|
843 | (void) strcat(buff, ",force"); |
---|
844 | if (mopt.tsa.ufs.ufs_pgthresh != DEFPGTHRESH) { |
---|
845 | (void) strcat(buff, ",pgthresh="); |
---|
846 | (void) sprintf(tmp, "%d", mopt.tsa.ufs.ufs_pgthresh); |
---|
847 | (void) strcat(buff, tmp); |
---|
848 | } |
---|
849 | if (mopt.tsa.ufs.ufs_flags & M_NOEXEC) |
---|
850 | (void) strcat(buff, ",noexec"); |
---|
851 | if (mopt.tsa.ufs.ufs_flags & M_NOCACHE) |
---|
852 | (void) strcat(buff, ",nocache"); |
---|
853 | if (mopt.tsa.ufs.ufs_flags & M_NODEV) |
---|
854 | (void) strcat(buff, ",nodev"); |
---|
855 | } |
---|
856 | #endif /* ultrix */ |
---|
857 | |
---|
858 | return(buff+1); |
---|
859 | } |
---|
860 | |
---|
861 | /* |
---|
862 | * Display the userid, given a uid (if possible) |
---|
863 | */ |
---|
864 | char *struid(uid) |
---|
865 | int uid; |
---|
866 | { |
---|
867 | struct passwd *pw; |
---|
868 | static char buff[64]; |
---|
869 | |
---|
870 | pw = getpwuid(uid); |
---|
871 | if (pw) |
---|
872 | strncpy(buff, pw->pw_name, sizeof(buff)); |
---|
873 | else |
---|
874 | sprintf(buff, "#%d", uid); |
---|
875 | return(buff); |
---|
876 | } |
---|
877 | |
---|
878 | /* |
---|
879 | * Compare if two hosts are the same |
---|
880 | */ |
---|
881 | int host_compare(host1, host2) |
---|
882 | char *host1; |
---|
883 | char *host2; |
---|
884 | { |
---|
885 | char bfr[BUFSIZ]; |
---|
886 | static char last_host[BUFSIZ] = "********"; |
---|
887 | static struct in_addr sin1, sin2; |
---|
888 | struct hostent *host; |
---|
889 | |
---|
890 | /* |
---|
891 | * Cache the last host1, for efficiency's sake. |
---|
892 | */ |
---|
893 | if (strcmp(host1, last_host)) { |
---|
894 | strcpy(last_host, host1); |
---|
895 | if ((sin1.s_addr = inet_addr(host1)) == -1) { |
---|
896 | if (host = gethostbyname(host1)) |
---|
897 | bcopy(host->h_addr, &sin1, (sizeof sin1)); |
---|
898 | else { |
---|
899 | if (debug_flag) { |
---|
900 | sprintf(bfr, "%s: gethostbyname", |
---|
901 | host1); |
---|
902 | perror(bfr); |
---|
903 | } |
---|
904 | return(!strcmp(host1, host2)); |
---|
905 | } |
---|
906 | } |
---|
907 | } |
---|
908 | if ((sin2.s_addr = inet_addr(host2)) == -1) { |
---|
909 | if (host = gethostbyname(host2)) |
---|
910 | bcopy(host->h_addr, &sin2, (sizeof sin2)); |
---|
911 | else { |
---|
912 | if (debug_flag) { |
---|
913 | sprintf(bfr, "%s: gethostbyname", host2); |
---|
914 | perror(bfr); |
---|
915 | } |
---|
916 | return(!strcmp(host1, host2)); |
---|
917 | } |
---|
918 | } |
---|
919 | return(!bcmp(&sin1, &sin2, (sizeof sin1))); |
---|
920 | } |
---|
921 | |
---|
922 | /* |
---|
923 | * Owner list code, originally written by jfc |
---|
924 | */ |
---|
925 | int clean_attachtab(atp) |
---|
926 | struct _attachtab *atp; |
---|
927 | { |
---|
928 | struct passwd *pw; |
---|
929 | int i; |
---|
930 | for(i=0;i<atp->nowners;i++) |
---|
931 | if(NULL == (pw = getpwuid(atp->owners[i]))) { |
---|
932 | int j; |
---|
933 | /* Unmap */ |
---|
934 | if (atp->fs->type == TYPE_NFS && do_nfsid) { |
---|
935 | if (debug_flag) |
---|
936 | fprintf(stderr, |
---|
937 | "nfs unmap(%s, %d)\n", |
---|
938 | atp->host, atp->owners[i]); |
---|
939 | (void) nfsid(atp->host, atp->hostaddr[0], |
---|
940 | MOUNTPROC_KUIDUMAP, 1, |
---|
941 | atp->hesiodname, 0, atp->owners[i]); |
---|
942 | } |
---|
943 | for(j=i+1;j<atp->nowners;j++) |
---|
944 | atp->owners[j-1] = atp->owners[j]; |
---|
945 | atp->nowners--; |
---|
946 | i--; |
---|
947 | } |
---|
948 | return atp->nowners; |
---|
949 | } |
---|
950 | |
---|
951 | void add_an_owner(atp,uid) |
---|
952 | uid_t uid; |
---|
953 | struct _attachtab *atp; |
---|
954 | { |
---|
955 | register int i; |
---|
956 | for(i=0;i<atp->nowners;i++) |
---|
957 | if(atp->owners[i] == uid) |
---|
958 | return; |
---|
959 | if(atp->nowners < MAXOWNERS) |
---|
960 | atp->owners[atp->nowners++] = uid; |
---|
961 | else |
---|
962 | /* fail silently */; |
---|
963 | } |
---|
964 | |
---|
965 | int is_an_owner(at,uid) |
---|
966 | uid_t uid; |
---|
967 | struct _attachtab *at; |
---|
968 | { |
---|
969 | register int i; |
---|
970 | if (!at->nowners) |
---|
971 | return(1); /* If no one claims it, anyone can have it */ |
---|
972 | for(i=0;i<at->nowners;i++) |
---|
973 | if(at->owners[i] == uid) |
---|
974 | return 1; |
---|
975 | return 0; |
---|
976 | } |
---|
977 | |
---|
978 | #ifdef ZEPHYR |
---|
979 | int wants_to_subscribe(at, uid, zero_too) |
---|
980 | uid_t uid; |
---|
981 | struct _attachtab *at; |
---|
982 | int zero_too; /* also true if root ? */ |
---|
983 | { |
---|
984 | register int i; |
---|
985 | |
---|
986 | for(i = 0;i < at->nowners;i++) |
---|
987 | if((zero_too && at->owners[i] == 0) || at->owners[i] == uid) |
---|
988 | return 1; |
---|
989 | return 0; |
---|
990 | } |
---|
991 | #endif |
---|
992 | |
---|
993 | int del_an_owner(at,uid) |
---|
994 | uid_t uid; |
---|
995 | struct _attachtab *at; |
---|
996 | { |
---|
997 | register int i; |
---|
998 | for(i=0;i<at->nowners;i++) |
---|
999 | if(at->owners[i] == uid) { |
---|
1000 | --at->nowners; |
---|
1001 | for(;i<at->nowners;i++) |
---|
1002 | at->owners[i] = at->owners[i+1]; |
---|
1003 | return at->nowners; |
---|
1004 | } |
---|
1005 | if(at->nowners == 0) |
---|
1006 | at->owners[0] = -1; |
---|
1007 | return at->nowners; |
---|
1008 | } |
---|
1009 | |
---|
1010 | char *ownerlist(atp) |
---|
1011 | struct _attachtab *atp; |
---|
1012 | { |
---|
1013 | static char ret[256]; |
---|
1014 | int i,len=1; |
---|
1015 | if(atp->nowners == 0) |
---|
1016 | return("{}"); |
---|
1017 | else if(atp->nowners == 1) |
---|
1018 | return struid(atp->owners[0]); |
---|
1019 | |
---|
1020 | ret[0] = '{'; |
---|
1021 | for(i=0;i<atp->nowners;i++) { |
---|
1022 | char *u = struid(atp->owners[i]); |
---|
1023 | int tmp = strlen(u); |
---|
1024 | if(i) |
---|
1025 | ret[len++] = ','; |
---|
1026 | if(len+tmp >= 255) { |
---|
1027 | ret[len++] = '}'; |
---|
1028 | ret[len] = '\0'; |
---|
1029 | return ret; |
---|
1030 | } |
---|
1031 | strcpy(ret+len,u); |
---|
1032 | len += tmp; |
---|
1033 | } |
---|
1034 | ret[len++] = '}'; |
---|
1035 | ret[len] = '\0'; |
---|
1036 | return ret; |
---|
1037 | } |
---|
1038 | |
---|
1039 | |
---|
1040 | int parse_username(s) |
---|
1041 | const char *s; |
---|
1042 | { |
---|
1043 | struct passwd *pw; |
---|
1044 | const char *os = s; |
---|
1045 | |
---|
1046 | pw = getpwnam((char *)s); |
---|
1047 | if (pw) |
---|
1048 | return(pw->pw_uid); |
---|
1049 | else { |
---|
1050 | if (*s == '#') |
---|
1051 | s++; |
---|
1052 | if (isdigit(*s)) |
---|
1053 | return(atoi(s)); |
---|
1054 | fprintf(stderr, "Can't parse username/uid string: %s\n", os); |
---|
1055 | exit(1); |
---|
1056 | /* NOTREACHED */ |
---|
1057 | } |
---|
1058 | } |
---|
1059 | |
---|
1060 | |
---|
1061 | int parse_groupname(s) |
---|
1062 | const char *s; |
---|
1063 | { |
---|
1064 | struct group *gr; |
---|
1065 | |
---|
1066 | gr = getgrnam((char *)s); |
---|
1067 | if (gr) |
---|
1068 | return(gr->gr_gid); |
---|
1069 | else { |
---|
1070 | if (*s == '#') |
---|
1071 | s++; |
---|
1072 | if (isdigit(*s)) |
---|
1073 | return(atoi(s)); |
---|
1074 | fprintf(stderr, "Can't parse groupname/gid string: %s\n", s); |
---|
1075 | exit(1); |
---|
1076 | /* NOTREACHED */ |
---|
1077 | } |
---|
1078 | } |
---|
1079 | |
---|
1080 | |
---|
1081 | char *errstr(e) |
---|
1082 | int e; |
---|
1083 | { |
---|
1084 | if(e < sys_nerr) |
---|
1085 | return sys_errlist[e]; |
---|
1086 | else |
---|
1087 | return "Unknown error"; |
---|
1088 | } |
---|