Commit | Line | Data |
---|---|---|
15637ed4 RG |
1 | /* |
2 | * Copyright (c) 1980, 1989 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * Redistribution and use in source and binary forms, with or without | |
6 | * modification, are permitted provided that the following conditions | |
7 | * are met: | |
8 | * 1. Redistributions of source code must retain the above copyright | |
9 | * notice, this list of conditions and the following disclaimer. | |
10 | * 2. Redistributions in binary form must reproduce the above copyright | |
11 | * notice, this list of conditions and the following disclaimer in the | |
12 | * documentation and/or other materials provided with the distribution. | |
13 | * 3. All advertising materials mentioning features or use of this software | |
14 | * must display the following acknowledgement: | |
15 | * This product includes software developed by the University of | |
16 | * California, Berkeley and its contributors. | |
17 | * 4. Neither the name of the University nor the names of its contributors | |
18 | * may be used to endorse or promote products derived from this software | |
19 | * without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
22 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
25 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
26 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
27 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
29 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
30 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
31 | * SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | #ifndef lint | |
35 | char copyright[] = | |
36 | "@(#) Copyright (c) 1980, 1989 The Regents of the University of California.\n\ | |
37 | All rights reserved.\n"; | |
38 | #endif /* not lint */ | |
39 | ||
40 | #ifndef lint | |
41 | static char sccsid[] = "@(#)mount.c 5.44 (Berkeley) 2/26/91"; | |
42 | #endif /* not lint */ | |
43 | ||
44 | #include <sys/param.h> | |
45 | #include <sys/file.h> | |
46 | #include <sys/time.h> | |
47 | #include <sys/wait.h> | |
48 | #include <sys/errno.h> | |
49 | #include <sys/signal.h> | |
50 | #include <sys/mount.h> | |
51 | #ifdef NFS | |
52 | #include <sys/socket.h> | |
53 | #include <sys/socketvar.h> | |
54 | #include <netdb.h> | |
55 | #include <rpc/rpc.h> | |
56 | #include <rpc/pmap_clnt.h> | |
57 | #include <rpc/pmap_prot.h> | |
58 | #include <nfs/rpcv2.h> | |
59 | #include <nfs/nfsv2.h> | |
60 | #include <nfs/nfs.h> | |
61 | #endif | |
62 | #include <fstab.h> | |
63 | #include <string.h> | |
64 | #include <stdio.h> | |
65 | #include <stdlib.h> | |
66 | #include "pathnames.h" | |
67 | ||
68 | #define DEFAULT_ROOTUID -2 | |
69 | ||
70 | #define BADTYPE(type) \ | |
71 | (strcmp(type, FSTAB_RO) && strcmp(type, FSTAB_RW) && \ | |
72 | strcmp(type, FSTAB_RQ)) | |
73 | #define SETTYPE(type) \ | |
74 | (!strcmp(type, FSTAB_RW) || !strcmp(type, FSTAB_RQ)) | |
75 | ||
76 | int fake, verbose, updateflg, mnttype; | |
77 | char *mntname, **envp; | |
78 | char **vfslist, **makevfslist(); | |
79 | static void prmount(); | |
80 | ||
81 | #ifdef NFS | |
82 | int xdr_dir(), xdr_fh(); | |
83 | char *getnfsargs(); | |
84 | struct nfs_args nfsdefargs = { | |
85 | (struct sockaddr *)0, | |
86 | SOCK_DGRAM, | |
87 | 0, | |
88 | (nfsv2fh_t *)0, | |
89 | 0, | |
90 | NFS_WSIZE, | |
91 | NFS_RSIZE, | |
92 | NFS_TIMEO, | |
93 | NFS_RETRANS, | |
94 | (char *)0, | |
95 | }; | |
96 | ||
97 | struct nfhret { | |
98 | u_long stat; | |
99 | nfsv2fh_t nfh; | |
100 | }; | |
101 | #define DEF_RETRY 10000 | |
102 | int retrycnt; | |
103 | #define BGRND 1 | |
104 | #define ISBGRND 2 | |
105 | int opflags = 0; | |
106 | #endif | |
107 | ||
108 | main(argc, argv, arge) | |
109 | int argc; | |
110 | char **argv; | |
111 | char **arge; | |
112 | { | |
113 | extern char *optarg; | |
114 | extern int optind; | |
115 | register struct fstab *fs; | |
116 | int all, ch, rval, flags, ret, pid, i; | |
117 | long mntsize; | |
118 | struct statfs *mntbuf, *getmntpt(); | |
119 | char *type, *options = NULL; | |
120 | FILE *pidfile; | |
121 | ||
122 | envp = arge; | |
123 | all = 0; | |
124 | type = NULL; | |
125 | mnttype = MOUNT_UFS; | |
126 | mntname = "ufs"; | |
127 | while ((ch = getopt(argc, argv, "afrwuvt:o:")) != EOF) | |
128 | switch((char)ch) { | |
129 | case 'a': | |
130 | all = 1; | |
131 | break; | |
132 | case 'f': | |
133 | fake = 1; | |
134 | break; | |
135 | case 'r': | |
136 | type = FSTAB_RO; | |
137 | break; | |
138 | case 'u': | |
139 | updateflg = MNT_UPDATE; | |
140 | break; | |
141 | case 'v': | |
142 | verbose = 1; | |
143 | break; | |
144 | case 'w': | |
145 | type = FSTAB_RW; | |
146 | break; | |
147 | case 'o': | |
148 | options = optarg; | |
149 | break; | |
150 | case 't': | |
151 | vfslist = makevfslist(optarg); | |
152 | mnttype = getmnttype(optarg); | |
153 | break; | |
154 | case '?': | |
155 | default: | |
156 | usage(); | |
157 | /* NOTREACHED */ | |
158 | } | |
159 | argc -= optind; | |
160 | argv += optind; | |
161 | ||
162 | /* NOSTRICT */ | |
163 | ||
164 | if (all) { | |
165 | rval = 0; | |
166 | while (fs = getfsent()) { | |
167 | if (BADTYPE(fs->fs_type)) | |
168 | continue; | |
169 | if (badvfsname(fs->fs_vfstype, vfslist)) | |
170 | continue; | |
171 | /* `/' is special, it's always mounted */ | |
172 | if (!strcmp(fs->fs_file, "/")) | |
173 | flags = MNT_UPDATE; | |
174 | else | |
175 | flags = updateflg; | |
176 | mnttype = getmnttype(fs->fs_vfstype); | |
177 | rval |= mountfs(fs->fs_spec, fs->fs_file, flags, | |
178 | type, options, fs->fs_mntops); | |
179 | } | |
180 | exit(rval); | |
181 | } | |
182 | ||
183 | if (argc == 0) { | |
184 | if (verbose || fake || type) | |
185 | usage(); | |
186 | if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { | |
187 | (void) fprintf(stderr, | |
188 | "mount: cannot get mount information\n"); | |
189 | exit(1); | |
190 | } | |
191 | for (i = 0; i < mntsize; i++) { | |
192 | if (badvfstype(mntbuf[i].f_type, vfslist)) | |
193 | continue; | |
194 | prmount(mntbuf[i].f_mntfromname, mntbuf[i].f_mntonname, | |
195 | mntbuf[i].f_flags); | |
196 | } | |
197 | exit(0); | |
198 | } | |
199 | ||
200 | if (argc == 1 && updateflg) { | |
201 | if ((mntbuf = getmntpt(*argv)) == NULL) { | |
202 | (void) fprintf(stderr, | |
203 | "mount: unknown special file or file system %s.\n", | |
204 | *argv); | |
205 | exit(1); | |
206 | } | |
207 | mnttype = mntbuf->f_type; | |
208 | #ifndef LETS_GET_SMALL | |
209 | if (!strcmp(mntbuf->f_mntfromname, "root_device")) { | |
210 | fs = getfsfile("/"); | |
211 | strcpy(mntbuf->f_mntfromname, fs->fs_spec); | |
212 | } | |
213 | #endif | |
214 | ret = mountfs(mntbuf->f_mntfromname, mntbuf->f_mntonname, | |
215 | updateflg, type, options, (char *)NULL); | |
216 | } else if (argc == 1) { | |
217 | #ifndef LETS_GET_SMALL | |
218 | if (!(fs = getfsfile(*argv)) && !(fs = getfsspec(*argv))) { | |
219 | (void) fprintf(stderr, | |
220 | "mount: unknown special file or file system %s.\n", | |
221 | *argv); | |
222 | exit(1); | |
223 | } | |
224 | if (BADTYPE(fs->fs_type)) { | |
225 | (void) fprintf(stderr, | |
226 | "mount: %s has unknown file system type.\n", *argv); | |
227 | exit(1); | |
228 | } | |
229 | mnttype = getmnttype(fs->fs_vfstype); | |
230 | ret = mountfs(fs->fs_spec, fs->fs_file, updateflg, | |
231 | type, options, fs->fs_mntops); | |
232 | #else | |
233 | exit(1); | |
234 | #endif | |
235 | } else if (argc != 2) { | |
236 | usage(); | |
237 | ret = 1; | |
238 | } else { | |
239 | /* | |
240 | * If -t flag has not been specified, and spec | |
241 | * contains either a ':' or a '@' then assume that | |
242 | * an NFS filesystem is being specified ala Sun. | |
243 | */ | |
244 | if (vfslist == (char **)0 && | |
245 | (index(argv[0], ':') || index(argv[0], '@'))) | |
246 | mnttype = MOUNT_NFS; | |
247 | ret = mountfs(argv[0], argv[1], updateflg, type, options, | |
248 | (char *)NULL); | |
249 | } | |
250 | #ifndef LETS_GET_SMALL | |
251 | if ((pidfile = fopen(_PATH_MOUNTDPID, "r")) != NULL) { | |
252 | pid = 0; | |
253 | fscanf(pidfile, "%d", &pid); | |
254 | fclose(pidfile); | |
255 | if (pid > 0) | |
256 | kill(pid, SIGHUP); | |
257 | } | |
258 | #endif | |
259 | exit (ret); | |
260 | } | |
261 | ||
262 | mountfs(spec, name, flags, type, options, mntopts) | |
263 | char *spec, *name, *type, *options, *mntopts; | |
264 | int flags; | |
265 | { | |
266 | union wait status; | |
267 | pid_t pid; | |
268 | int argc, i; | |
269 | struct ufs_args args; | |
270 | #ifdef NFS | |
271 | struct nfs_args nfsargs; | |
272 | #endif | |
273 | char *argp, *argv[50]; | |
274 | char execname[MAXPATHLEN + 1], flagval[12]; | |
275 | ||
276 | #ifdef NFS | |
277 | nfsargs = nfsdefargs; | |
278 | #endif | |
279 | if (mntopts) | |
280 | getstdopts(mntopts, &flags); | |
281 | if (options) | |
282 | getstdopts(options, &flags); | |
283 | if (type) | |
284 | getstdopts(type, &flags); | |
285 | switch (mnttype) { | |
286 | case MOUNT_UFS: | |
287 | if (mntopts) | |
288 | getufsopts(mntopts, &flags); | |
289 | if (options) | |
290 | getufsopts(options, &flags); | |
291 | args.fspec = spec; | |
292 | args.exroot = DEFAULT_ROOTUID; | |
293 | if (flags & MNT_RDONLY) | |
294 | args.exflags = MNT_EXRDONLY; | |
295 | else | |
296 | args.exflags = 0; | |
297 | argp = (caddr_t)&args; | |
298 | break; | |
299 | ||
300 | #ifdef NFS | |
301 | case MOUNT_NFS: | |
302 | retrycnt = DEF_RETRY; | |
303 | if (mntopts) | |
304 | getnfsopts(mntopts, &nfsargs, &opflags, &retrycnt); | |
305 | if (options) | |
306 | getnfsopts(options, &nfsargs, &opflags, &retrycnt); | |
307 | if (argp = getnfsargs(spec, &nfsargs)) | |
308 | break; | |
309 | return (1); | |
310 | #endif /* NFS */ | |
311 | ||
312 | #ifndef LETS_GET_SMALL | |
313 | case MOUNT_MFS: | |
314 | default: | |
315 | argv[0] = mntname; | |
316 | argc = 1; | |
317 | if (flags) { | |
318 | argv[argc++] = "-F"; | |
319 | sprintf(flagval, "%d", flags); | |
320 | argv[argc++] = flagval; | |
321 | } | |
322 | if (mntopts) | |
323 | argc += getexecopts(mntopts, &argv[argc]); | |
324 | if (options) | |
325 | argc += getexecopts(options, &argv[argc]); | |
326 | argv[argc++] = spec; | |
327 | argv[argc++] = name; | |
328 | argv[argc++] = NULL; | |
329 | sprintf(execname, "%s/mount_%s", _PATH_EXECDIR, mntname); | |
330 | if (verbose) { | |
331 | (void)printf("exec: %s", execname); | |
332 | for (i = 1; i < argc - 1; i++) | |
333 | (void)printf(" %s", argv[i]); | |
334 | (void)printf("\n"); | |
335 | } | |
336 | if (fake) | |
337 | break; | |
338 | if (pid = vfork()) { | |
339 | if (pid == -1) { | |
340 | perror("mount: vfork starting file system"); | |
341 | return (1); | |
342 | } | |
343 | if (waitpid(pid, (int *)&status, 0) != -1 && | |
344 | WIFEXITED(status) && | |
345 | WEXITSTATUS(status) != 0) | |
346 | return (WEXITSTATUS(status)); | |
347 | spec = mntname; | |
348 | goto out; | |
349 | } | |
350 | execve(execname, argv, envp); | |
351 | (void) fprintf(stderr, "mount: cannot exec %s for %s: ", | |
352 | execname, name); | |
353 | perror((char *)NULL); | |
354 | exit (1); | |
355 | #endif | |
356 | /* NOTREACHED */ | |
357 | ||
358 | } | |
359 | if (!fake && mount(mnttype, name, flags, argp)) { | |
360 | #ifdef NFS | |
361 | if (opflags & ISBGRND) | |
362 | exit(1); | |
363 | #endif | |
364 | (void) fprintf(stderr, "%s on %s: ", spec, name); | |
365 | switch (errno) { | |
366 | case EMFILE: | |
367 | (void) fprintf(stderr, "Mount table full\n"); | |
368 | break; | |
369 | case EINVAL: | |
370 | if (flags & MNT_UPDATE) | |
371 | (void) fprintf(stderr, "Specified device %s\n", | |
372 | "does not match mounted device"); | |
373 | else if (mnttype == MOUNT_UFS) | |
374 | (void) fprintf(stderr, "Bogus super block\n"); | |
375 | else | |
376 | perror((char *)NULL); | |
377 | break; | |
378 | default: | |
379 | perror((char *)NULL); | |
380 | break; | |
381 | } | |
382 | return(1); | |
383 | } | |
384 | ||
385 | out: | |
386 | if (verbose) | |
387 | prmount(spec, name, flags); | |
388 | ||
389 | #ifdef NFS | |
390 | if (opflags & ISBGRND) | |
391 | exit(1); | |
392 | #endif | |
393 | return(0); | |
394 | } | |
395 | ||
396 | static void | |
397 | prmount(spec, name, flags) | |
398 | char *spec, *name; | |
399 | register short flags; | |
400 | { | |
401 | register int first; | |
402 | ||
403 | #ifdef NFS | |
404 | if (opflags & ISBGRND) | |
405 | return; | |
406 | #endif | |
407 | (void)printf("%s on %s", spec, name); | |
408 | if (!(flags & MNT_VISFLAGMASK)) { | |
409 | (void)printf("\n"); | |
410 | return; | |
411 | } | |
412 | first = 0; | |
413 | #define PR(msg) (void)printf("%s%s", !first++ ? " (" : ", ", msg) | |
414 | if (flags & MNT_RDONLY) | |
415 | PR("read-only"); | |
416 | if (flags & MNT_NOEXEC) | |
417 | PR("noexec"); | |
418 | if (flags & MNT_NOSUID) | |
419 | PR("nosuid"); | |
420 | if (flags & MNT_NODEV) | |
421 | PR("nodev"); | |
4709afb5 CR |
422 | if (flags & MNT_NOCORE) |
423 | PR("nocore"); | |
15637ed4 RG |
424 | if (flags & MNT_SYNCHRONOUS) |
425 | PR("synchronous"); | |
426 | if (flags & MNT_QUOTA) | |
427 | PR("with quotas"); | |
428 | if (flags & MNT_LOCAL) | |
429 | PR("local"); | |
430 | if (flags & MNT_EXPORTED) | |
431 | if (flags & MNT_EXRDONLY) | |
432 | PR("NFS exported read-only"); | |
433 | else | |
434 | PR("NFS exported"); | |
435 | (void)printf(")\n"); | |
436 | } | |
437 | ||
438 | getmnttype(fstype) | |
439 | char *fstype; | |
440 | { | |
441 | ||
442 | mntname = fstype; | |
443 | if (!strcmp(fstype, "ufs")) | |
444 | return (MOUNT_UFS); | |
445 | if (!strcmp(fstype, "nfs")) | |
446 | return (MOUNT_NFS); | |
447 | if (!strcmp(fstype, "mfs")) | |
448 | return (MOUNT_MFS); | |
449 | return (0); | |
450 | } | |
451 | ||
452 | usage() | |
453 | { | |
454 | ||
455 | (void) fprintf(stderr, | |
456 | "usage:\n mount %s %s\n mount %s\n mount %s\n", | |
457 | "[ -frwu ] [ -t nfs | ufs | external_type ]", | |
458 | "[ -o options ] special node", | |
459 | "[ -afrwu ] [ -t nfs | ufs | external_type ]", | |
460 | "[ -frwu ] special | node"); | |
461 | exit(1); | |
462 | } | |
463 | ||
464 | getstdopts(options, flagp) | |
465 | char *options; | |
466 | int *flagp; | |
467 | { | |
468 | register char *opt; | |
469 | int negative; | |
470 | char optbuf[BUFSIZ]; | |
471 | ||
472 | (void)strcpy(optbuf, options); | |
473 | for (opt = strtok(optbuf, ","); opt; opt = strtok((char *)NULL, ",")) { | |
474 | if (opt[0] == 'n' && opt[1] == 'o') { | |
475 | negative++; | |
476 | opt += 2; | |
477 | } else { | |
478 | negative = 0; | |
479 | } | |
480 | if (!negative && !strcasecmp(opt, FSTAB_RO)) { | |
481 | *flagp |= MNT_RDONLY; | |
482 | continue; | |
483 | } | |
484 | if (!negative && !strcasecmp(opt, FSTAB_RW)) { | |
485 | *flagp &= ~MNT_RDONLY; | |
486 | continue; | |
487 | } | |
488 | if (!strcasecmp(opt, "exec")) { | |
489 | if (negative) | |
490 | *flagp |= MNT_NOEXEC; | |
491 | else | |
492 | *flagp &= ~MNT_NOEXEC; | |
493 | continue; | |
494 | } | |
495 | if (!strcasecmp(opt, "suid")) { | |
496 | if (negative) | |
497 | *flagp |= MNT_NOSUID; | |
498 | else | |
499 | *flagp &= ~MNT_NOSUID; | |
500 | continue; | |
501 | } | |
502 | if (!strcasecmp(opt, "dev")) { | |
503 | if (negative) | |
504 | *flagp |= MNT_NODEV; | |
505 | else | |
506 | *flagp &= ~MNT_NODEV; | |
507 | continue; | |
508 | } | |
4709afb5 CR |
509 | if (!strcasecmp(opt, "core")) { |
510 | if (negative) | |
511 | *flagp |= MNT_NOCORE; | |
512 | else | |
513 | *flagp &= ~MNT_NOCORE; | |
514 | continue; | |
515 | } | |
15637ed4 RG |
516 | if (!strcasecmp(opt, "synchronous")) { |
517 | if (!negative) | |
518 | *flagp |= MNT_SYNCHRONOUS; | |
519 | else | |
520 | *flagp &= ~MNT_SYNCHRONOUS; | |
521 | continue; | |
522 | } | |
523 | } | |
524 | } | |
525 | ||
526 | /* ARGSUSED */ | |
527 | getufsopts(options, flagp) | |
528 | char *options; | |
529 | int *flagp; | |
530 | { | |
531 | return; | |
532 | } | |
533 | ||
534 | getexecopts(options, argv) | |
535 | char *options; | |
536 | char **argv; | |
537 | { | |
538 | register int argc = 0; | |
539 | register char *opt; | |
540 | ||
541 | for (opt = strtok(options, ","); opt; opt = strtok((char *)NULL, ",")) { | |
542 | if (opt[0] != '-') | |
543 | continue; | |
544 | argv[argc++] = opt; | |
545 | if (opt[2] == '\0' || opt[2] != '=') | |
546 | continue; | |
547 | opt[2] = '\0'; | |
548 | argv[argc++] = &opt[3]; | |
549 | } | |
550 | return (argc); | |
551 | } | |
552 | ||
553 | struct statfs * | |
554 | getmntpt(name) | |
555 | char *name; | |
556 | { | |
557 | long mntsize; | |
558 | register long i; | |
559 | struct statfs *mntbuf; | |
560 | ||
561 | mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); | |
562 | for (i = 0; i < mntsize; i++) { | |
563 | if (!strcmp(mntbuf[i].f_mntfromname, name) || | |
564 | !strcmp(mntbuf[i].f_mntonname, name)) | |
565 | return (&mntbuf[i]); | |
566 | } | |
567 | return ((struct statfs *)0); | |
568 | } | |
569 | ||
570 | static int skipvfs; | |
571 | ||
572 | badvfstype(vfstype, vfslist) | |
573 | short vfstype; | |
574 | char **vfslist; | |
575 | { | |
576 | ||
577 | if (vfslist == 0) | |
578 | return(0); | |
579 | while (*vfslist) { | |
580 | if (vfstype == getmnttype(*vfslist)) | |
581 | return(skipvfs); | |
582 | vfslist++; | |
583 | } | |
584 | return (!skipvfs); | |
585 | } | |
586 | ||
587 | badvfsname(vfsname, vfslist) | |
588 | char *vfsname; | |
589 | char **vfslist; | |
590 | { | |
591 | ||
592 | if (vfslist == 0) | |
593 | return(0); | |
594 | while (*vfslist) { | |
595 | if (strcmp(vfsname, *vfslist) == 0) | |
596 | return(skipvfs); | |
597 | vfslist++; | |
598 | } | |
599 | return (!skipvfs); | |
600 | } | |
601 | ||
602 | char ** | |
603 | makevfslist(fslist) | |
604 | char *fslist; | |
605 | { | |
606 | register char **av, *nextcp; | |
607 | register int i; | |
608 | ||
609 | if (fslist == NULL) | |
610 | return (NULL); | |
611 | if (fslist[0] == 'n' && fslist[1] == 'o') { | |
612 | fslist += 2; | |
613 | skipvfs = 1; | |
614 | } | |
615 | for (i = 0, nextcp = fslist; *nextcp; nextcp++) | |
616 | if (*nextcp == ',') | |
617 | i++; | |
618 | av = (char **)malloc((size_t)(i+2) * sizeof(char *)); | |
619 | if (av == NULL) | |
620 | return (NULL); | |
621 | nextcp = fslist; | |
622 | i = 0; | |
623 | av[i++] = nextcp; | |
624 | while (nextcp = index(nextcp, ',')) { | |
625 | *nextcp++ = '\0'; | |
626 | av[i++] = nextcp; | |
627 | } | |
628 | av[i++] = 0; | |
629 | return (av); | |
630 | } | |
631 | ||
632 | #ifdef NFS | |
633 | exclusive(a, b) | |
634 | char *a, *b; | |
635 | { | |
636 | ||
637 | (void) fprintf(stderr, "mount: Options %s, %s mutually exclusive\n", | |
638 | a, b); | |
639 | exit(1); | |
640 | } | |
641 | ||
642 | /* | |
643 | * Handle the getoption arg. | |
644 | * Essentially update "opflags", "retrycnt" and "nfsargs" | |
645 | */ | |
646 | getnfsopts(optarg, nfsargsp, opflagsp, retrycntp) | |
647 | char *optarg; | |
648 | register struct nfs_args *nfsargsp; | |
649 | int *opflagsp; | |
650 | int *retrycntp; | |
651 | { | |
652 | register char *cp, *nextcp; | |
653 | int num; | |
654 | char *nump; | |
655 | ||
656 | for (cp = optarg; cp != NULL && *cp != '\0'; cp = nextcp) { | |
657 | if ((nextcp = index(cp, ',')) != NULL) | |
658 | *nextcp++ = '\0'; | |
659 | if ((nump = index(cp, '=')) != NULL) { | |
660 | *nump++ = '\0'; | |
661 | num = atoi(nump); | |
662 | } else | |
663 | num = -1; | |
664 | /* | |
665 | * Just test for a string match and do it | |
666 | */ | |
667 | if (!strcmp(cp, "bg")) { | |
668 | *opflagsp |= BGRND; | |
669 | } else if (!strcmp(cp, "soft")) { | |
670 | if (nfsargsp->flags & NFSMNT_SPONGY) | |
671 | exclusive("soft, spongy"); | |
672 | nfsargsp->flags |= NFSMNT_SOFT; | |
673 | } else if (!strcmp(cp, "spongy")) { | |
674 | if (nfsargsp->flags & NFSMNT_SOFT) | |
675 | exclusive("soft, spongy"); | |
676 | nfsargsp->flags |= NFSMNT_SPONGY; | |
677 | } else if (!strcmp(cp, "compress")) { | |
678 | nfsargsp->flags |= NFSMNT_COMPRESS; | |
679 | } else if (!strcmp(cp, "intr")) { | |
680 | nfsargsp->flags |= NFSMNT_INT; | |
681 | } else if (!strcmp(cp, "tcp")) { | |
682 | nfsargsp->sotype = SOCK_STREAM; | |
683 | } else if (!strcmp(cp, "noconn")) { | |
684 | nfsargsp->flags |= NFSMNT_NOCONN; | |
685 | } else if (!strcmp(cp, "retry") && num > 0) { | |
686 | *retrycntp = num; | |
687 | } else if (!strcmp(cp, "rsize") && num > 0) { | |
688 | nfsargsp->rsize = num; | |
689 | nfsargsp->flags |= NFSMNT_RSIZE; | |
690 | } else if (!strcmp(cp, "wsize") && num > 0) { | |
691 | nfsargsp->wsize = num; | |
692 | nfsargsp->flags |= NFSMNT_WSIZE; | |
693 | } else if (!strcmp(cp, "timeo") && num > 0) { | |
694 | nfsargsp->timeo = num; | |
695 | nfsargsp->flags |= NFSMNT_TIMEO; | |
696 | } else if (!strcmp(cp, "retrans") && num > 0) { | |
697 | nfsargsp->retrans = num; | |
698 | nfsargsp->flags |= NFSMNT_RETRANS; | |
699 | } | |
700 | } | |
701 | if (nfsargsp->sotype == SOCK_DGRAM) { | |
702 | if (nfsargsp->rsize > NFS_MAXDGRAMDATA) | |
703 | nfsargsp->rsize = NFS_MAXDGRAMDATA; | |
704 | if (nfsargsp->wsize > NFS_MAXDGRAMDATA) | |
705 | nfsargsp->wsize = NFS_MAXDGRAMDATA; | |
706 | } | |
707 | } | |
708 | ||
709 | char * | |
710 | getnfsargs(spec, nfsargsp) | |
711 | char *spec; | |
712 | struct nfs_args *nfsargsp; | |
713 | { | |
714 | register CLIENT *clp; | |
715 | struct hostent *hp; | |
716 | static struct sockaddr_in saddr; | |
717 | struct timeval pertry, try; | |
718 | enum clnt_stat clnt_stat; | |
719 | int so = RPC_ANYSOCK; | |
720 | char *fsp, *hostp, *delimp; | |
721 | u_short tport; | |
722 | static struct nfhret nfhret; | |
723 | static char nam[MNAMELEN + 1]; | |
724 | char buf[MAXPATHLEN + 1]; | |
725 | ||
726 | strncpy(buf, spec, MAXPATHLEN); | |
727 | buf[MAXPATHLEN] = '\0'; | |
728 | strncpy(nam, spec, MNAMELEN); | |
729 | nam[MNAMELEN] = '\0'; | |
730 | if ((delimp = index(buf, '@')) != NULL) { | |
731 | hostp = delimp + 1; | |
732 | fsp = buf; | |
733 | } else if ((delimp = index(buf, ':')) != NULL) { | |
734 | hostp = buf; | |
735 | fsp = delimp + 1; | |
736 | } else { | |
737 | (void) fprintf(stderr, | |
738 | "mount: No <host>:<dirpath> or <dirpath>@<host> spec\n"); | |
739 | return (0); | |
740 | } | |
741 | *delimp = '\0'; | |
742 | if ((hp = gethostbyname(hostp)) == NULL) { | |
743 | (void) fprintf(stderr, "mount: Can't get net id for host\n"); | |
744 | return (0); | |
745 | } | |
746 | bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length); | |
747 | nfhret.stat = ETIMEDOUT; /* Mark not yet successful */ | |
748 | while (retrycnt > 0) { | |
749 | saddr.sin_family = AF_INET; | |
750 | saddr.sin_port = htons(PMAPPORT); | |
751 | if ((tport = pmap_getport(&saddr, RPCPROG_NFS, | |
752 | NFS_VER2, IPPROTO_UDP)) == 0) { | |
753 | if ((opflags & ISBGRND) == 0) | |
754 | clnt_pcreateerror("NFS Portmap"); | |
755 | } else { | |
756 | saddr.sin_port = 0; | |
757 | pertry.tv_sec = 10; | |
758 | pertry.tv_usec = 0; | |
759 | if ((clp = clntudp_create(&saddr, RPCPROG_MNT, | |
760 | RPCMNT_VER1, pertry, &so)) == NULL) { | |
761 | if ((opflags & ISBGRND) == 0) | |
762 | clnt_pcreateerror("Cannot MNT PRC"); | |
763 | } else { | |
764 | clp->cl_auth = authunix_create_default(); | |
765 | try.tv_sec = 10; | |
766 | try.tv_usec = 0; | |
767 | clnt_stat = clnt_call(clp, RPCMNT_MOUNT, | |
768 | xdr_dir, fsp, xdr_fh, &nfhret, try); | |
769 | if (clnt_stat != RPC_SUCCESS) { | |
770 | if ((opflags & ISBGRND) == 0) | |
771 | clnt_perror(clp, "Bad MNT RPC"); | |
772 | } else { | |
773 | auth_destroy(clp->cl_auth); | |
774 | clnt_destroy(clp); | |
775 | retrycnt = 0; | |
776 | } | |
777 | } | |
778 | } | |
779 | if (--retrycnt > 0) { | |
780 | if (opflags & BGRND) { | |
781 | opflags &= ~BGRND; | |
782 | if (fork()) | |
783 | return (0); | |
784 | else | |
785 | opflags |= ISBGRND; | |
786 | } | |
787 | sleep(10); | |
788 | } | |
789 | } | |
790 | if (nfhret.stat) { | |
791 | if (opflags & ISBGRND) | |
792 | exit(1); | |
793 | (void) fprintf(stderr, "Mount RPC error on %s: ", spec); | |
794 | errno = nfhret.stat; | |
795 | perror((char *)NULL); | |
796 | return (0); | |
797 | } | |
798 | saddr.sin_port = htons(tport); | |
799 | nfsargsp->addr = (struct sockaddr *) &saddr; | |
800 | nfsargsp->fh = &nfhret.nfh; | |
801 | nfsargsp->hostname = nam; | |
802 | return ((caddr_t)nfsargsp); | |
803 | } | |
804 | ||
805 | /* | |
806 | * xdr routines for mount rpc's | |
807 | */ | |
808 | xdr_dir(xdrsp, dirp) | |
809 | XDR *xdrsp; | |
810 | char *dirp; | |
811 | { | |
812 | return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); | |
813 | } | |
814 | ||
815 | xdr_fh(xdrsp, np) | |
816 | XDR *xdrsp; | |
817 | struct nfhret *np; | |
818 | { | |
819 | if (!xdr_u_long(xdrsp, &(np->stat))) | |
820 | return (0); | |
821 | if (np->stat) | |
822 | return (1); | |
823 | return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH)); | |
824 | } | |
825 | #endif /* NFS */ |