121156Sdist /* 239322Smckusick * Copyright (c) 1980, 1989 The Regents of the University of California. 339322Smckusick * All rights reserved. 439322Smckusick * 542702Sbostic * %sccs.include.redist.c% 621156Sdist */ 721156Sdist 810811Ssam #ifndef lint 921156Sdist char copyright[] = 1039322Smckusick "@(#) Copyright (c) 1980, 1989 The Regents of the University of California.\n\ 1121156Sdist All rights reserved.\n"; 1239322Smckusick #endif /* not lint */ 131057Sbill 1421156Sdist #ifndef lint 15*52097Sbostic static char sccsid[] = "@(#)mount.c 5.45 (Berkeley) 12/31/91"; 1639322Smckusick #endif /* not lint */ 1721156Sdist 1812808Ssam #include <sys/param.h> 1935339Sbostic #include <sys/file.h> 2038445Smckusick #include <sys/time.h> 2139133Smckusick #include <sys/wait.h> 2245524Sbostic #include <sys/errno.h> 2345524Sbostic #include <sys/signal.h> 2438445Smckusick #include <sys/mount.h> 2538445Smckusick #ifdef NFS 2638445Smckusick #include <sys/socket.h> 2738445Smckusick #include <sys/socketvar.h> 2838445Smckusick #include <netdb.h> 2938445Smckusick #include <rpc/rpc.h> 3038445Smckusick #include <rpc/pmap_clnt.h> 3138445Smckusick #include <rpc/pmap_prot.h> 3238445Smckusick #include <nfs/rpcv2.h> 3338445Smckusick #include <nfs/nfsv2.h> 3438445Smckusick #include <nfs/nfs.h> 3538445Smckusick #endif 3645524Sbostic #include <fstab.h> 3745524Sbostic #include <string.h> 3845524Sbostic #include <stdio.h> 3945524Sbostic #include <stdlib.h> 4045524Sbostic #include "pathnames.h" 411057Sbill 4240369Smckusick #define DEFAULT_ROOTUID -2 4340369Smckusick 4435339Sbostic #define BADTYPE(type) \ 4535339Sbostic (strcmp(type, FSTAB_RO) && strcmp(type, FSTAB_RW) && \ 4635339Sbostic strcmp(type, FSTAB_RQ)) 4735339Sbostic #define SETTYPE(type) \ 4835339Sbostic (!strcmp(type, FSTAB_RW) || !strcmp(type, FSTAB_RQ)) 491057Sbill 5039333Smckusick int fake, verbose, updateflg, mnttype; 5139322Smckusick char *mntname, **envp; 5240051Smckusick char **vfslist, **makevfslist(); 5346708Sbostic static void prmount(); 5439131Smckusick 5538445Smckusick #ifdef NFS 5638445Smckusick int xdr_dir(), xdr_fh(); 5738632Smckusick char *getnfsargs(); 5841911Smckusick struct nfs_args nfsdefargs = { 5941911Smckusick (struct sockaddr *)0, 6041911Smckusick SOCK_DGRAM, 6141911Smckusick 0, 6238445Smckusick (nfsv2fh_t *)0, 6338445Smckusick 0, 6438445Smckusick NFS_WSIZE, 6538445Smckusick NFS_RSIZE, 6638445Smckusick NFS_TIMEO, 6738445Smckusick NFS_RETRANS, 6838445Smckusick (char *)0, 6938445Smckusick }; 705073Sroot 7138445Smckusick struct nfhret { 7238445Smckusick u_long stat; 7338445Smckusick nfsv2fh_t nfh; 7438445Smckusick }; 7540051Smckusick #define DEF_RETRY 10000 7640051Smckusick int retrycnt; 7738445Smckusick #define BGRND 1 7838445Smckusick #define ISBGRND 2 7938445Smckusick int opflags = 0; 8038445Smckusick #endif 8138445Smckusick 8239131Smckusick main(argc, argv, arge) 835073Sroot int argc; 845073Sroot char **argv; 8539131Smckusick char **arge; 861057Sbill { 8735339Sbostic extern char *optarg; 8835339Sbostic extern int optind; 8935339Sbostic register struct fstab *fs; 9040496Smckusick int all, ch, rval, flags, ret, pid, i; 9138632Smckusick long mntsize; 9239465Smckusick struct statfs *mntbuf, *getmntpt(); 9339131Smckusick char *type, *options = NULL; 9440496Smckusick FILE *pidfile; 951057Sbill 9639131Smckusick envp = arge; 9735339Sbostic all = 0; 9835339Sbostic type = NULL; 9938445Smckusick mnttype = MOUNT_UFS; 10039322Smckusick mntname = "ufs"; 10139333Smckusick while ((ch = getopt(argc, argv, "afrwuvt:o:")) != EOF) 10235339Sbostic switch((char)ch) { 10335339Sbostic case 'a': 10435339Sbostic all = 1; 10535339Sbostic break; 10635339Sbostic case 'f': 10735339Sbostic fake = 1; 10835339Sbostic break; 10935339Sbostic case 'r': 11012808Ssam type = FSTAB_RO; 11135339Sbostic break; 11239333Smckusick case 'u': 11341403Smckusick updateflg = MNT_UPDATE; 11439333Smckusick break; 11535339Sbostic case 'v': 11635339Sbostic verbose = 1; 11735339Sbostic break; 11835339Sbostic case 'w': 11935339Sbostic type = FSTAB_RW; 12035339Sbostic break; 12139131Smckusick case 'o': 12239131Smckusick options = optarg; 12339131Smckusick break; 12438445Smckusick case 't': 12540051Smckusick vfslist = makevfslist(optarg); 12639322Smckusick mnttype = getmnttype(optarg); 12739322Smckusick break; 12835339Sbostic case '?': 12935339Sbostic default: 13035339Sbostic usage(); 13139131Smckusick /* NOTREACHED */ 1325073Sroot } 13335339Sbostic argc -= optind; 13435339Sbostic argv += optind; 13535339Sbostic 13635339Sbostic /* NOSTRICT */ 13735339Sbostic 1384460Sroot if (all) { 13935369Sbostic rval = 0; 14039333Smckusick while (fs = getfsent()) { 14135372Sbostic if (BADTYPE(fs->fs_type)) 14235372Sbostic continue; 14340844Smckusick if (badvfsname(fs->fs_vfstype, vfslist)) 14440051Smckusick continue; 14535372Sbostic /* `/' is special, it's always mounted */ 14635372Sbostic if (!strcmp(fs->fs_file, "/")) 14741403Smckusick flags = MNT_UPDATE; 14839333Smckusick else 14939333Smckusick flags = updateflg; 15039333Smckusick mnttype = getmnttype(fs->fs_vfstype); 15139333Smckusick rval |= mountfs(fs->fs_spec, fs->fs_file, flags, 15239333Smckusick type, options, fs->fs_mntops); 15335372Sbostic } 15435341Sbostic exit(rval); 15535339Sbostic } 1565073Sroot 15735339Sbostic if (argc == 0) { 15835339Sbostic if (verbose || fake || type) 15935339Sbostic usage(); 16040337Smckusick if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) { 16145689Smckusick (void) fprintf(stderr, 16239319Smckusick "mount: cannot get mount information\n"); 16338632Smckusick exit(1); 16438632Smckusick } 16540844Smckusick for (i = 0; i < mntsize; i++) { 16640844Smckusick if (badvfstype(mntbuf[i].f_type, vfslist)) 16740844Smckusick continue; 16838632Smckusick prmount(mntbuf[i].f_mntfromname, mntbuf[i].f_mntonname, 16939316Smckusick mntbuf[i].f_flags); 17040844Smckusick } 1714460Sroot exit(0); 1721057Sbill } 17312808Ssam 17439465Smckusick if (argc == 1 && updateflg) { 17539465Smckusick if ((mntbuf = getmntpt(*argv)) == NULL) { 17645689Smckusick (void) fprintf(stderr, 17739465Smckusick "mount: unknown special file or file system %s.\n", 17839465Smckusick *argv); 17939465Smckusick exit(1); 18039465Smckusick } 18139465Smckusick mnttype = mntbuf->f_type; 18240124Smckusick if (!strcmp(mntbuf->f_mntfromname, "root_device")) { 18340124Smckusick fs = getfsfile("/"); 18440124Smckusick strcpy(mntbuf->f_mntfromname, fs->fs_spec); 18540124Smckusick } 18640496Smckusick ret = mountfs(mntbuf->f_mntfromname, mntbuf->f_mntonname, 18742253Sbostic updateflg, type, options, (char *)NULL); 18840496Smckusick } else if (argc == 1) { 18935339Sbostic if (!(fs = getfsfile(*argv)) && !(fs = getfsspec(*argv))) { 19045689Smckusick (void) fprintf(stderr, 19135339Sbostic "mount: unknown special file or file system %s.\n", 19235339Sbostic *argv); 19335339Sbostic exit(1); 19435339Sbostic } 19535339Sbostic if (BADTYPE(fs->fs_type)) { 19645689Smckusick (void) fprintf(stderr, 19735339Sbostic "mount: %s has unknown file system type.\n", *argv); 19835339Sbostic exit(1); 19935339Sbostic } 20039333Smckusick mnttype = getmnttype(fs->fs_vfstype); 20140496Smckusick ret = mountfs(fs->fs_spec, fs->fs_file, updateflg, 20240496Smckusick type, options, fs->fs_mntops); 20340496Smckusick } else if (argc != 2) { 20440496Smckusick usage(); 20540496Smckusick ret = 1; 20640496Smckusick } else { 20742857Smckusick /* 20842857Smckusick * If -t flag has not been specified, and spec 20942857Smckusick * contains either a ':' or a '@' then assume that 21042857Smckusick * an NFS filesystem is being specified ala Sun. 21142857Smckusick */ 21242857Smckusick if (vfslist == (char **)0 && 21342857Smckusick (index(argv[0], ':') || index(argv[0], '@'))) 21442857Smckusick mnttype = MOUNT_NFS; 21542253Sbostic ret = mountfs(argv[0], argv[1], updateflg, type, options, 21642253Sbostic (char *)NULL); 21712808Ssam } 21840496Smckusick if ((pidfile = fopen(_PATH_MOUNTDPID, "r")) != NULL) { 21940496Smckusick pid = 0; 22040496Smckusick fscanf(pidfile, "%d", &pid); 22140496Smckusick fclose(pidfile); 22240496Smckusick if (pid > 0) 22340496Smckusick kill(pid, SIGHUP); 22440496Smckusick } 22540496Smckusick exit (ret); 22612808Ssam } 22712808Ssam 22839333Smckusick mountfs(spec, name, flags, type, options, mntopts) 22939131Smckusick char *spec, *name, *type, *options, *mntopts; 23039333Smckusick int flags; 23112808Ssam { 23242253Sbostic union wait status; 23342253Sbostic pid_t pid; 23442253Sbostic int argc, i; 23538070Smckusick struct ufs_args args; 23641911Smckusick struct nfs_args nfsargs; 23739131Smckusick char *argp, *argv[50]; 23839322Smckusick char execname[MAXPATHLEN + 1], flagval[12]; 2391057Sbill 24041911Smckusick nfsargs = nfsdefargs; 24139333Smckusick if (mntopts) 24239333Smckusick getstdopts(mntopts, &flags); 24339316Smckusick if (options) 24439316Smckusick getstdopts(options, &flags); 24539333Smckusick if (type) 24639333Smckusick getstdopts(type, &flags); 24739316Smckusick switch (mnttype) { 248*52097Sbostic case MOUNT_LFS: 24939316Smckusick case MOUNT_UFS: 25039333Smckusick if (mntopts) 25139333Smckusick getufsopts(mntopts, &flags); 25239316Smckusick if (options) 25339316Smckusick getufsopts(options, &flags); 25439316Smckusick args.fspec = spec; 25540369Smckusick args.exroot = DEFAULT_ROOTUID; 25641403Smckusick if (flags & MNT_RDONLY) 25741403Smckusick args.exflags = MNT_EXRDONLY; 25840496Smckusick else 25940496Smckusick args.exflags = 0; 26039316Smckusick argp = (caddr_t)&args; 26139316Smckusick break; 26238632Smckusick 26338632Smckusick #ifdef NFS 26439316Smckusick case MOUNT_NFS: 26540051Smckusick retrycnt = DEF_RETRY; 26639333Smckusick if (mntopts) 26739333Smckusick getnfsopts(mntopts, &nfsargs, &opflags, &retrycnt); 26839316Smckusick if (options) 26939333Smckusick getnfsopts(options, &nfsargs, &opflags, &retrycnt); 27041911Smckusick if (argp = getnfsargs(spec, &nfsargs)) 27139316Smckusick break; 27239316Smckusick return (1); 27338632Smckusick #endif /* NFS */ 27438632Smckusick 27539316Smckusick case MOUNT_MFS: 27639322Smckusick default: 27739322Smckusick argv[0] = mntname; 27839329Smckusick argc = 1; 27939322Smckusick if (flags) { 28039322Smckusick argv[argc++] = "-F"; 28139322Smckusick sprintf(flagval, "%d", flags); 28239322Smckusick argv[argc++] = flagval; 28339322Smckusick } 28439333Smckusick if (mntopts) 28539333Smckusick argc += getexecopts(mntopts, &argv[argc]); 28639329Smckusick if (options) 28739329Smckusick argc += getexecopts(options, &argv[argc]); 28839316Smckusick argv[argc++] = spec; 28939316Smckusick argv[argc++] = name; 29039521Smckusick argv[argc++] = NULL; 29139603Smckusick sprintf(execname, "%s/mount_%s", _PATH_EXECDIR, mntname); 29239316Smckusick if (verbose) { 29342253Sbostic (void)printf("exec: %s", execname); 29442253Sbostic for (i = 1; i < argc - 1; i++) 29542253Sbostic (void)printf(" %s", argv[i]); 29642253Sbostic (void)printf("\n"); 29739316Smckusick } 29839316Smckusick if (fake) 29939316Smckusick break; 30042253Sbostic if (pid = vfork()) { 30142253Sbostic if (pid == -1) { 30239322Smckusick perror("mount: vfork starting file system"); 30339316Smckusick return (1); 30439131Smckusick } 30546708Sbostic if (waitpid(pid, (int *)&status, 0) != -1 && 30639316Smckusick WIFEXITED(status) && 30739316Smckusick WEXITSTATUS(status) != 0) 30839316Smckusick return (WEXITSTATUS(status)); 30939322Smckusick spec = mntname; 31039316Smckusick goto out; 31139316Smckusick } 31239322Smckusick execve(execname, argv, envp); 31345689Smckusick (void) fprintf(stderr, "mount: cannot exec %s for %s: ", 31439603Smckusick execname, name); 31542253Sbostic perror((char *)NULL); 31639316Smckusick exit (1); 31739316Smckusick /* NOTREACHED */ 31838632Smckusick 31939316Smckusick } 32039316Smckusick if (!fake && mount(mnttype, name, flags, argp)) { 32139316Smckusick if (opflags & ISBGRND) 32239316Smckusick exit(1); 32345689Smckusick (void) fprintf(stderr, "%s on %s: ", spec, name); 32439316Smckusick switch (errno) { 32539316Smckusick case EMFILE: 32645689Smckusick (void) fprintf(stderr, "Mount table full\n"); 32739316Smckusick break; 32839316Smckusick case EINVAL: 32941403Smckusick if (flags & MNT_UPDATE) 33045689Smckusick (void) fprintf(stderr, "Specified device %s\n", 33145689Smckusick "does not match mounted device"); 33245569Skarels else if (mnttype == MOUNT_UFS) 33345689Smckusick (void) fprintf(stderr, "Bogus super block\n"); 33439333Smckusick else 33545569Skarels perror((char *)NULL); 33639316Smckusick break; 33739316Smckusick default: 33839316Smckusick perror((char *)NULL); 33939316Smckusick break; 3404460Sroot } 34139316Smckusick return(1); 3424460Sroot } 34335339Sbostic 34439131Smckusick out: 34512808Ssam if (verbose) 34639316Smckusick prmount(spec, name, flags); 34735339Sbostic 34838445Smckusick if (opflags & ISBGRND) 34942253Sbostic exit(1); 35042253Sbostic return(0); 3511057Sbill } 35235339Sbostic 35346708Sbostic static void 35439316Smckusick prmount(spec, name, flags) 35539316Smckusick char *spec, *name; 35642253Sbostic register short flags; 35735339Sbostic { 35842253Sbostic register int first; 35938632Smckusick 36038445Smckusick if (opflags & ISBGRND) 36138445Smckusick return; 36242253Sbostic (void)printf("%s on %s", spec, name); 36342253Sbostic if (!(flags & MNT_VISFLAGMASK)) { 36442253Sbostic (void)printf("\n"); 36542253Sbostic return; 36642253Sbostic } 36742253Sbostic first = 0; 36842253Sbostic #define PR(msg) (void)printf("%s%s", !first++ ? " (" : ", ", msg) 36941403Smckusick if (flags & MNT_RDONLY) 37042253Sbostic PR("read-only"); 37141403Smckusick if (flags & MNT_NOEXEC) 37242253Sbostic PR("noexec"); 37341403Smckusick if (flags & MNT_NOSUID) 37442253Sbostic PR("nosuid"); 37541403Smckusick if (flags & MNT_NODEV) 37642253Sbostic PR("nodev"); 37741403Smckusick if (flags & MNT_SYNCHRONOUS) 37842253Sbostic PR("synchronous"); 37941403Smckusick if (flags & MNT_QUOTA) 38042253Sbostic PR("with quotas"); 38141403Smckusick if (flags & MNT_LOCAL) 38242253Sbostic PR("local"); 38341403Smckusick if (flags & MNT_EXPORTED) 38441403Smckusick if (flags & MNT_EXRDONLY) 38542253Sbostic PR("NFS exported read-only"); 38641285Smckusick else 38742253Sbostic PR("NFS exported"); 38842253Sbostic (void)printf(")\n"); 38935339Sbostic } 39035339Sbostic 39139133Smckusick getmnttype(fstype) 39239133Smckusick char *fstype; 39339133Smckusick { 39439133Smckusick 39539322Smckusick mntname = fstype; 39639133Smckusick if (!strcmp(fstype, "ufs")) 39739133Smckusick return (MOUNT_UFS); 39839133Smckusick if (!strcmp(fstype, "nfs")) 39939133Smckusick return (MOUNT_NFS); 40039133Smckusick if (!strcmp(fstype, "mfs")) 40139133Smckusick return (MOUNT_MFS); 402*52097Sbostic if (!strcmp(fstype, "lfs")) 403*52097Sbostic return (MOUNT_LFS); 40439133Smckusick return (0); 40539133Smckusick } 40639133Smckusick 40738632Smckusick usage() 40835339Sbostic { 40940871Smckusick 41045689Smckusick (void) fprintf(stderr, 41145689Smckusick "usage:\n mount %s %s\n mount %s\n mount %s\n", 41240871Smckusick "[ -frwu ] [ -t nfs | ufs | external_type ]", 41340871Smckusick "[ -o options ] special node", 41440871Smckusick "[ -afrwu ] [ -t nfs | ufs | external_type ]", 41540871Smckusick "[ -frwu ] special | node"); 41635339Sbostic exit(1); 41735339Sbostic } 41835339Sbostic 41939316Smckusick getstdopts(options, flagp) 42039316Smckusick char *options; 42142253Sbostic int *flagp; 42239316Smckusick { 42339316Smckusick register char *opt; 42439316Smckusick int negative; 42542253Sbostic char optbuf[BUFSIZ]; 42639316Smckusick 42742253Sbostic (void)strcpy(optbuf, options); 42842253Sbostic for (opt = strtok(optbuf, ","); opt; opt = strtok((char *)NULL, ",")) { 42939316Smckusick if (opt[0] == 'n' && opt[1] == 'o') { 43039316Smckusick negative++; 43139316Smckusick opt += 2; 43239316Smckusick } else { 43339316Smckusick negative = 0; 43439316Smckusick } 43539333Smckusick if (!negative && !strcasecmp(opt, FSTAB_RO)) { 43641403Smckusick *flagp |= MNT_RDONLY; 43739333Smckusick continue; 43839333Smckusick } 43939333Smckusick if (!negative && !strcasecmp(opt, FSTAB_RW)) { 44041403Smckusick *flagp &= ~MNT_RDONLY; 44139333Smckusick continue; 44239333Smckusick } 44339316Smckusick if (!strcasecmp(opt, "exec")) { 44439316Smckusick if (negative) 44541403Smckusick *flagp |= MNT_NOEXEC; 44639333Smckusick else 44741403Smckusick *flagp &= ~MNT_NOEXEC; 44839316Smckusick continue; 44939316Smckusick } 45039316Smckusick if (!strcasecmp(opt, "suid")) { 45139316Smckusick if (negative) 45241403Smckusick *flagp |= MNT_NOSUID; 45339333Smckusick else 45441403Smckusick *flagp &= ~MNT_NOSUID; 45539316Smckusick continue; 45639316Smckusick } 45739316Smckusick if (!strcasecmp(opt, "dev")) { 45839316Smckusick if (negative) 45941403Smckusick *flagp |= MNT_NODEV; 46039333Smckusick else 46141403Smckusick *flagp &= ~MNT_NODEV; 46239316Smckusick continue; 46339316Smckusick } 46439316Smckusick if (!strcasecmp(opt, "synchronous")) { 46539316Smckusick if (!negative) 46641403Smckusick *flagp |= MNT_SYNCHRONOUS; 46739333Smckusick else 46841403Smckusick *flagp &= ~MNT_SYNCHRONOUS; 46939316Smckusick continue; 47039316Smckusick } 47139316Smckusick } 47239316Smckusick } 47339316Smckusick 47442253Sbostic /* ARGSUSED */ 47539131Smckusick getufsopts(options, flagp) 47639131Smckusick char *options; 47742253Sbostic int *flagp; 47839131Smckusick { 47939131Smckusick return; 48039131Smckusick } 48139131Smckusick 48239329Smckusick getexecopts(options, argv) 48339131Smckusick char *options; 48439131Smckusick char **argv; 48539131Smckusick { 48639131Smckusick register int argc = 0; 48739131Smckusick register char *opt; 48839131Smckusick 48942253Sbostic for (opt = strtok(options, ","); opt; opt = strtok((char *)NULL, ",")) { 49039131Smckusick if (opt[0] != '-') 49139131Smckusick continue; 49239131Smckusick argv[argc++] = opt; 49339131Smckusick if (opt[2] == '\0' || opt[2] != '=') 49439131Smckusick continue; 49539131Smckusick opt[2] = '\0'; 49639131Smckusick argv[argc++] = &opt[3]; 49739131Smckusick } 49839131Smckusick return (argc); 49939131Smckusick } 50039131Smckusick 50139465Smckusick struct statfs * 50239465Smckusick getmntpt(name) 50339465Smckusick char *name; 50439465Smckusick { 50539465Smckusick long mntsize; 50639465Smckusick register long i; 50739465Smckusick struct statfs *mntbuf; 50839465Smckusick 50940337Smckusick mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 51039465Smckusick for (i = 0; i < mntsize; i++) { 51139465Smckusick if (!strcmp(mntbuf[i].f_mntfromname, name) || 51239465Smckusick !strcmp(mntbuf[i].f_mntonname, name)) 51339465Smckusick return (&mntbuf[i]); 51439465Smckusick } 51539465Smckusick return ((struct statfs *)0); 51639465Smckusick } 51739465Smckusick 51840051Smckusick static int skipvfs; 51940051Smckusick 52040051Smckusick badvfstype(vfstype, vfslist) 52142253Sbostic short vfstype; 52240051Smckusick char **vfslist; 52340051Smckusick { 52440051Smckusick 52540051Smckusick if (vfslist == 0) 52640051Smckusick return(0); 52740051Smckusick while (*vfslist) { 52840844Smckusick if (vfstype == getmnttype(*vfslist)) 52940051Smckusick return(skipvfs); 53040051Smckusick vfslist++; 53140051Smckusick } 53240051Smckusick return (!skipvfs); 53340051Smckusick } 53440051Smckusick 53540844Smckusick badvfsname(vfsname, vfslist) 53640844Smckusick char *vfsname; 53740844Smckusick char **vfslist; 53840844Smckusick { 53940844Smckusick 54040844Smckusick if (vfslist == 0) 54140844Smckusick return(0); 54240844Smckusick while (*vfslist) { 54340844Smckusick if (strcmp(vfsname, *vfslist) == 0) 54440844Smckusick return(skipvfs); 54540844Smckusick vfslist++; 54640844Smckusick } 54740844Smckusick return (!skipvfs); 54840844Smckusick } 54940844Smckusick 55040051Smckusick char ** 55140051Smckusick makevfslist(fslist) 55240051Smckusick char *fslist; 55340051Smckusick { 55440051Smckusick register char **av, *nextcp; 55540051Smckusick register int i; 55640051Smckusick 55740051Smckusick if (fslist == NULL) 55840051Smckusick return (NULL); 55940051Smckusick if (fslist[0] == 'n' && fslist[1] == 'o') { 56040051Smckusick fslist += 2; 56140051Smckusick skipvfs = 1; 56240051Smckusick } 56340051Smckusick for (i = 0, nextcp = fslist; *nextcp; nextcp++) 56440051Smckusick if (*nextcp == ',') 56540051Smckusick i++; 56642253Sbostic av = (char **)malloc((size_t)(i+2) * sizeof(char *)); 56740051Smckusick if (av == NULL) 56840051Smckusick return (NULL); 56940051Smckusick nextcp = fslist; 57040051Smckusick i = 0; 57140051Smckusick av[i++] = nextcp; 57240051Smckusick while (nextcp = index(nextcp, ',')) { 57340051Smckusick *nextcp++ = '\0'; 57440051Smckusick av[i++] = nextcp; 57540051Smckusick } 57640051Smckusick av[i++] = 0; 57740051Smckusick return (av); 57840051Smckusick } 57940051Smckusick 58038632Smckusick #ifdef NFS 58145689Smckusick exclusive(a, b) 58245689Smckusick char *a, *b; 58345689Smckusick { 58445689Smckusick 58545689Smckusick (void) fprintf(stderr, "mount: Options %s, %s mutually exclusive\n", 58645689Smckusick a, b); 58745689Smckusick exit(1); 58845689Smckusick } 58945689Smckusick 59039131Smckusick /* 59139131Smckusick * Handle the getoption arg. 59239131Smckusick * Essentially update "opflags", "retrycnt" and "nfsargs" 59339131Smckusick */ 59439131Smckusick getnfsopts(optarg, nfsargsp, opflagsp, retrycntp) 59539131Smckusick char *optarg; 59645689Smckusick register struct nfs_args *nfsargsp; 59739131Smckusick int *opflagsp; 59839131Smckusick int *retrycntp; 59939131Smckusick { 60039131Smckusick register char *cp, *nextcp; 60139131Smckusick int num; 60239131Smckusick char *nump; 60339131Smckusick 60445689Smckusick for (cp = optarg; cp != NULL && *cp != '\0'; cp = nextcp) { 60539131Smckusick if ((nextcp = index(cp, ',')) != NULL) 60639131Smckusick *nextcp++ = '\0'; 60739131Smckusick if ((nump = index(cp, '=')) != NULL) { 60839131Smckusick *nump++ = '\0'; 60939131Smckusick num = atoi(nump); 61039131Smckusick } else 61139131Smckusick num = -1; 61239131Smckusick /* 61339131Smckusick * Just test for a string match and do it 61439131Smckusick */ 61539131Smckusick if (!strcmp(cp, "bg")) { 61639131Smckusick *opflagsp |= BGRND; 61739131Smckusick } else if (!strcmp(cp, "soft")) { 61845689Smckusick if (nfsargsp->flags & NFSMNT_SPONGY) 61945689Smckusick exclusive("soft, spongy"); 62039131Smckusick nfsargsp->flags |= NFSMNT_SOFT; 62143416Smckusick } else if (!strcmp(cp, "spongy")) { 62245689Smckusick if (nfsargsp->flags & NFSMNT_SOFT) 62345689Smckusick exclusive("soft, spongy"); 62443416Smckusick nfsargsp->flags |= NFSMNT_SPONGY; 62545284Smckusick } else if (!strcmp(cp, "compress")) { 62645284Smckusick nfsargsp->flags |= NFSMNT_COMPRESS; 62739131Smckusick } else if (!strcmp(cp, "intr")) { 62839131Smckusick nfsargsp->flags |= NFSMNT_INT; 62941911Smckusick } else if (!strcmp(cp, "tcp")) { 63041911Smckusick nfsargsp->sotype = SOCK_STREAM; 63141911Smckusick } else if (!strcmp(cp, "noconn")) { 63241911Smckusick nfsargsp->flags |= NFSMNT_NOCONN; 63339131Smckusick } else if (!strcmp(cp, "retry") && num > 0) { 63439131Smckusick *retrycntp = num; 63539131Smckusick } else if (!strcmp(cp, "rsize") && num > 0) { 63639131Smckusick nfsargsp->rsize = num; 63739131Smckusick nfsargsp->flags |= NFSMNT_RSIZE; 63839131Smckusick } else if (!strcmp(cp, "wsize") && num > 0) { 63939131Smckusick nfsargsp->wsize = num; 64039131Smckusick nfsargsp->flags |= NFSMNT_WSIZE; 64139131Smckusick } else if (!strcmp(cp, "timeo") && num > 0) { 64239131Smckusick nfsargsp->timeo = num; 64339131Smckusick nfsargsp->flags |= NFSMNT_TIMEO; 64439131Smckusick } else if (!strcmp(cp, "retrans") && num > 0) { 64539131Smckusick nfsargsp->retrans = num; 64639131Smckusick nfsargsp->flags |= NFSMNT_RETRANS; 64739131Smckusick } 64839131Smckusick } 64943416Smckusick if (nfsargsp->sotype == SOCK_DGRAM) { 65043416Smckusick if (nfsargsp->rsize > NFS_MAXDGRAMDATA) 65143416Smckusick nfsargsp->rsize = NFS_MAXDGRAMDATA; 65243416Smckusick if (nfsargsp->wsize > NFS_MAXDGRAMDATA) 65343416Smckusick nfsargsp->wsize = NFS_MAXDGRAMDATA; 65443416Smckusick } 65539131Smckusick } 65639131Smckusick 65738632Smckusick char * 65841911Smckusick getnfsargs(spec, nfsargsp) 65938632Smckusick char *spec; 66041911Smckusick struct nfs_args *nfsargsp; 66135339Sbostic { 66238632Smckusick register CLIENT *clp; 66338632Smckusick struct hostent *hp; 66439604Smckusick static struct sockaddr_in saddr; 66538632Smckusick struct timeval pertry, try; 66638632Smckusick enum clnt_stat clnt_stat; 66738632Smckusick int so = RPC_ANYSOCK; 66845569Skarels char *fsp, *hostp, *delimp; 66938632Smckusick u_short tport; 67039604Smckusick static struct nfhret nfhret; 67139604Smckusick static char nam[MNAMELEN + 1]; 67245569Skarels char buf[MAXPATHLEN + 1]; 67338632Smckusick 67445569Skarels strncpy(buf, spec, MAXPATHLEN); 67545569Skarels buf[MAXPATHLEN] = '\0'; 67638632Smckusick strncpy(nam, spec, MNAMELEN); 67738632Smckusick nam[MNAMELEN] = '\0'; 67845569Skarels if ((delimp = index(buf, '@')) != NULL) { 67938632Smckusick hostp = delimp + 1; 68045569Skarels fsp = buf; 68145569Skarels } else if ((delimp = index(buf, ':')) != NULL) { 68245569Skarels hostp = buf; 68345569Skarels fsp = delimp + 1; 68438632Smckusick } else { 68545689Smckusick (void) fprintf(stderr, 68645689Smckusick "mount: No <host>:<dirpath> or <dirpath>@<host> spec\n"); 68738632Smckusick return (0); 68838632Smckusick } 68938632Smckusick *delimp = '\0'; 69038632Smckusick if ((hp = gethostbyname(hostp)) == NULL) { 69145689Smckusick (void) fprintf(stderr, "mount: Can't get net id for host\n"); 69238632Smckusick return (0); 69338632Smckusick } 69438632Smckusick bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length); 69545569Skarels nfhret.stat = ETIMEDOUT; /* Mark not yet successful */ 69638632Smckusick while (retrycnt > 0) { 69738632Smckusick saddr.sin_family = AF_INET; 69838632Smckusick saddr.sin_port = htons(PMAPPORT); 69938632Smckusick if ((tport = pmap_getport(&saddr, RPCPROG_NFS, 70038632Smckusick NFS_VER2, IPPROTO_UDP)) == 0) { 70138632Smckusick if ((opflags & ISBGRND) == 0) 70238632Smckusick clnt_pcreateerror("NFS Portmap"); 70338632Smckusick } else { 70438632Smckusick saddr.sin_port = 0; 70538632Smckusick pertry.tv_sec = 10; 70638632Smckusick pertry.tv_usec = 0; 70738632Smckusick if ((clp = clntudp_create(&saddr, RPCPROG_MNT, 70838632Smckusick RPCMNT_VER1, pertry, &so)) == NULL) { 70938632Smckusick if ((opflags & ISBGRND) == 0) 71038632Smckusick clnt_pcreateerror("Cannot MNT PRC"); 71138632Smckusick } else { 71238632Smckusick clp->cl_auth = authunix_create_default(); 71338632Smckusick try.tv_sec = 10; 71438632Smckusick try.tv_usec = 0; 71538632Smckusick clnt_stat = clnt_call(clp, RPCMNT_MOUNT, 71645569Skarels xdr_dir, fsp, xdr_fh, &nfhret, try); 71738632Smckusick if (clnt_stat != RPC_SUCCESS) { 71838632Smckusick if ((opflags & ISBGRND) == 0) 71938632Smckusick clnt_perror(clp, "Bad MNT RPC"); 72038632Smckusick } else { 72138632Smckusick auth_destroy(clp->cl_auth); 72238632Smckusick clnt_destroy(clp); 72338632Smckusick retrycnt = 0; 72438632Smckusick } 72538632Smckusick } 72638632Smckusick } 72738632Smckusick if (--retrycnt > 0) { 72838632Smckusick if (opflags & BGRND) { 72938632Smckusick opflags &= ~BGRND; 73038632Smckusick if (fork()) 73138632Smckusick return (0); 73238632Smckusick else 73338632Smckusick opflags |= ISBGRND; 73438632Smckusick } 73538632Smckusick sleep(10); 73638632Smckusick } 73738632Smckusick } 73838632Smckusick if (nfhret.stat) { 73938632Smckusick if (opflags & ISBGRND) 74038632Smckusick exit(1); 74145689Smckusick (void) fprintf(stderr, "Mount RPC error on %s: ", spec); 74239521Smckusick errno = nfhret.stat; 74342253Sbostic perror((char *)NULL); 74438632Smckusick return (0); 74538632Smckusick } 74638632Smckusick saddr.sin_port = htons(tport); 74741911Smckusick nfsargsp->addr = (struct sockaddr *) &saddr; 74841911Smckusick nfsargsp->fh = &nfhret.nfh; 74941911Smckusick nfsargsp->hostname = nam; 75041911Smckusick return ((caddr_t)nfsargsp); 75135339Sbostic } 75238445Smckusick 75338445Smckusick /* 75438445Smckusick * xdr routines for mount rpc's 75538445Smckusick */ 75638445Smckusick xdr_dir(xdrsp, dirp) 75738445Smckusick XDR *xdrsp; 75838445Smckusick char *dirp; 75938445Smckusick { 76038445Smckusick return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 76138445Smckusick } 76238445Smckusick 76338445Smckusick xdr_fh(xdrsp, np) 76438445Smckusick XDR *xdrsp; 76538445Smckusick struct nfhret *np; 76638445Smckusick { 76738445Smckusick if (!xdr_u_long(xdrsp, &(np->stat))) 76838445Smckusick return (0); 76938445Smckusick if (np->stat) 77038445Smckusick return (1); 77138445Smckusick return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH)); 77238445Smckusick } 77338632Smckusick #endif /* NFS */ 774