home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sbin / mount / mount.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-04  |  17.7 KB  |  797 lines

  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.         if (!strcmp(mntbuf->f_mntfromname, "root_device")) {
  209.             fs = getfsfile("/");
  210.             strcpy(mntbuf->f_mntfromname, fs->fs_spec);
  211.         }
  212.         ret = mountfs(mntbuf->f_mntfromname, mntbuf->f_mntonname,
  213.             updateflg, type, options, (char *)NULL);
  214.     } else if (argc == 1) {
  215.         if (!(fs = getfsfile(*argv)) && !(fs = getfsspec(*argv))) {
  216.             (void) fprintf(stderr,
  217.                 "mount: unknown special file or file system %s.\n",
  218.                 *argv);
  219.             exit(1);
  220.         }
  221.         if (BADTYPE(fs->fs_type)) {
  222.             (void) fprintf(stderr,
  223.                 "mount: %s has unknown file system type.\n", *argv);
  224.             exit(1);
  225.         }
  226.         mnttype = getmnttype(fs->fs_vfstype);
  227.         ret = mountfs(fs->fs_spec, fs->fs_file, updateflg,
  228.             type, options, fs->fs_mntops);
  229.     } else if (argc != 2) {
  230.         usage();
  231.         ret = 1;
  232.     } else {
  233.         /*
  234.          * If -t flag has not been specified, and spec
  235.          * contains either a ':' or a '@' then assume that
  236.          * an NFS filesystem is being specified ala Sun.
  237.          */
  238.         if (vfslist == (char **)0 &&
  239.             (index(argv[0], ':') || index(argv[0], '@')))
  240.             mnttype = MOUNT_NFS;
  241.         ret = mountfs(argv[0], argv[1], updateflg, type, options,
  242.             (char *)NULL);
  243.     }
  244.     if ((pidfile = fopen(_PATH_MOUNTDPID, "r")) != NULL) {
  245.         pid = 0;
  246.         fscanf(pidfile, "%d", &pid);
  247.         fclose(pidfile);
  248.         if (pid > 0)
  249.             kill(pid, SIGHUP);
  250.     }
  251.     exit (ret);
  252. }
  253.  
  254. mountfs(spec, name, flags, type, options, mntopts)
  255.     char *spec, *name, *type, *options, *mntopts;
  256.     int flags;
  257. {
  258.     union wait status;
  259.     pid_t pid;
  260.     int argc, i;
  261.     struct ufs_args args;
  262.     struct nfs_args nfsargs;
  263.     char *argp, *argv[50];
  264.     char execname[MAXPATHLEN + 1], flagval[12];
  265.  
  266.     nfsargs = nfsdefargs;
  267.     if (mntopts)
  268.         getstdopts(mntopts, &flags);
  269.     if (options)
  270.         getstdopts(options, &flags);
  271.     if (type)
  272.         getstdopts(type, &flags);
  273.     switch (mnttype) {
  274.     case MOUNT_UFS:
  275.         if (mntopts)
  276.             getufsopts(mntopts, &flags);
  277.         if (options)
  278.             getufsopts(options, &flags);
  279.         args.fspec = spec;
  280.         args.exroot = DEFAULT_ROOTUID;
  281.         if (flags & MNT_RDONLY)
  282.             args.exflags = MNT_EXRDONLY;
  283.         else
  284.             args.exflags = 0;
  285.         argp = (caddr_t)&args;
  286.         break;
  287.  
  288. #ifdef NFS
  289.     case MOUNT_NFS:
  290.         retrycnt = DEF_RETRY;
  291.         if (mntopts)
  292.             getnfsopts(mntopts, &nfsargs, &opflags, &retrycnt);
  293.         if (options)
  294.             getnfsopts(options, &nfsargs, &opflags, &retrycnt);
  295.         if (argp = getnfsargs(spec, &nfsargs))
  296.             break;
  297.         return (1);
  298. #endif /* NFS */
  299.  
  300.     case MOUNT_MFS:
  301.     default:
  302.         argv[0] = mntname;
  303.         argc = 1;
  304.         if (flags) {
  305.             argv[argc++] = "-F";
  306.             sprintf(flagval, "%d", flags);
  307.             argv[argc++] = flagval;
  308.         }
  309.         if (mntopts)
  310.             argc += getexecopts(mntopts, &argv[argc]);
  311.         if (options)
  312.             argc += getexecopts(options, &argv[argc]);
  313.         argv[argc++] = spec;
  314.         argv[argc++] = name;
  315.         argv[argc++] = NULL;
  316.         sprintf(execname, "%s/mount_%s", _PATH_EXECDIR, mntname);
  317.         if (verbose) {
  318.             (void)printf("exec: %s", execname);
  319.             for (i = 1; i < argc - 1; i++)
  320.                 (void)printf(" %s", argv[i]);
  321.             (void)printf("\n");
  322.         }
  323.         if (fake)
  324.             break;
  325.         if (pid = vfork()) {
  326.             if (pid == -1) {
  327.                 perror("mount: vfork starting file system");
  328.                 return (1);
  329.             }
  330.             if (waitpid(pid, (int *)&status, 0) != -1 &&
  331.                 WIFEXITED(status) &&
  332.                 WEXITSTATUS(status) != 0)
  333.                 return (WEXITSTATUS(status));
  334.             spec = mntname;
  335.             goto out;
  336.         }
  337.         execve(execname, argv, envp);
  338.         (void) fprintf(stderr, "mount: cannot exec %s for %s: ",
  339.             execname, name);
  340.         perror((char *)NULL);
  341.         exit (1);
  342.         /* NOTREACHED */
  343.  
  344.     }
  345.     if (!fake && mount(mnttype, name, flags, argp)) {
  346.         if (opflags & ISBGRND)
  347.             exit(1);
  348.         (void) fprintf(stderr, "%s on %s: ", spec, name);
  349.         switch (errno) {
  350.         case EMFILE:
  351.             (void) fprintf(stderr, "Mount table full\n");
  352.             break;
  353.         case EINVAL:
  354.             if (flags & MNT_UPDATE)
  355.                 (void) fprintf(stderr, "Specified device %s\n",
  356.                     "does not match mounted device");
  357.             else if (mnttype == MOUNT_UFS)
  358.                 (void) fprintf(stderr, "Bogus super block\n");
  359.             else
  360.                 perror((char *)NULL);
  361.             break;
  362.         default:
  363.             perror((char *)NULL);
  364.             break;
  365.         }
  366.         return(1);
  367.     }
  368.  
  369. out:
  370.     if (verbose)
  371.         prmount(spec, name, flags);
  372.  
  373.     if (opflags & ISBGRND)
  374.         exit(1);
  375.     return(0);
  376. }
  377.  
  378. static void
  379. prmount(spec, name, flags)
  380.     char *spec, *name;
  381.     register short flags;
  382. {
  383.     register int first;
  384.  
  385.     if (opflags & ISBGRND)
  386.         return;
  387.     (void)printf("%s on %s", spec, name);
  388.     if (!(flags & MNT_VISFLAGMASK)) {
  389.         (void)printf("\n");
  390.         return;
  391.     }
  392.     first = 0;
  393. #define    PR(msg)    (void)printf("%s%s", !first++ ? " (" : ", ", msg)
  394.     if (flags & MNT_RDONLY)
  395.         PR("read-only");
  396.     if (flags & MNT_NOEXEC)
  397.         PR("noexec");
  398.     if (flags & MNT_NOSUID)
  399.         PR("nosuid");
  400.     if (flags & MNT_NODEV)
  401.         PR("nodev");
  402.     if (flags & MNT_SYNCHRONOUS)
  403.         PR("synchronous");
  404.     if (flags & MNT_QUOTA)
  405.         PR("with quotas");
  406.     if (flags & MNT_LOCAL)
  407.         PR("local");
  408.     if (flags & MNT_EXPORTED)
  409.         if (flags & MNT_EXRDONLY)
  410.             PR("NFS exported read-only");
  411.         else
  412.             PR("NFS exported");
  413.     (void)printf(")\n");
  414. }
  415.  
  416. getmnttype(fstype)
  417.     char *fstype;
  418. {
  419.  
  420.     mntname = fstype;
  421.     if (!strcmp(fstype, "ufs"))
  422.         return (MOUNT_UFS);
  423.     if (!strcmp(fstype, "nfs"))
  424.         return (MOUNT_NFS);
  425.     if (!strcmp(fstype, "mfs"))
  426.         return (MOUNT_MFS);
  427.     return (0);
  428. }
  429.  
  430. usage()
  431. {
  432.  
  433.     (void) fprintf(stderr,
  434.         "usage:\n  mount %s %s\n  mount %s\n  mount %s\n",
  435.         "[ -frwu ] [ -t nfs | ufs | external_type ]",
  436.         "[ -o options ] special node",
  437.         "[ -afrwu ] [ -t nfs | ufs | external_type ]",
  438.         "[ -frwu ] special | node");
  439.     exit(1);
  440. }
  441.  
  442. getstdopts(options, flagp)
  443.     char *options;
  444.     int *flagp;
  445. {
  446.     register char *opt;
  447.     int negative;
  448.     char optbuf[BUFSIZ];
  449.  
  450.     (void)strcpy(optbuf, options);
  451.     for (opt = strtok(optbuf, ","); opt; opt = strtok((char *)NULL, ",")) {
  452.         if (opt[0] == 'n' && opt[1] == 'o') {
  453.             negative++;
  454.             opt += 2;
  455.         } else {
  456.             negative = 0;
  457.         }
  458.         if (!negative && !strcasecmp(opt, FSTAB_RO)) {
  459.             *flagp |= MNT_RDONLY;
  460.             continue;
  461.         }
  462.         if (!negative && !strcasecmp(opt, FSTAB_RW)) {
  463.             *flagp &= ~MNT_RDONLY;
  464.             continue;
  465.         }
  466.         if (!strcasecmp(opt, "exec")) {
  467.             if (negative)
  468.                 *flagp |= MNT_NOEXEC;
  469.             else
  470.                 *flagp &= ~MNT_NOEXEC;
  471.             continue;
  472.         }
  473.         if (!strcasecmp(opt, "suid")) {
  474.             if (negative)
  475.                 *flagp |= MNT_NOSUID;
  476.             else
  477.                 *flagp &= ~MNT_NOSUID;
  478.             continue;
  479.         }
  480.         if (!strcasecmp(opt, "dev")) {
  481.             if (negative)
  482.                 *flagp |= MNT_NODEV;
  483.             else
  484.                 *flagp &= ~MNT_NODEV;
  485.             continue;
  486.         }
  487.         if (!strcasecmp(opt, "synchronous")) {
  488.             if (!negative)
  489.                 *flagp |= MNT_SYNCHRONOUS;
  490.             else
  491.                 *flagp &= ~MNT_SYNCHRONOUS;
  492.             continue;
  493.         }
  494.     }
  495. }
  496.  
  497. /* ARGSUSED */
  498. getufsopts(options, flagp)
  499.     char *options;
  500.     int *flagp;
  501. {
  502.     return;
  503. }
  504.  
  505. getexecopts(options, argv)
  506.     char *options;
  507.     char **argv;
  508. {
  509.     register int argc = 0;
  510.     register char *opt;
  511.  
  512.     for (opt = strtok(options, ","); opt; opt = strtok((char *)NULL, ",")) {
  513.         if (opt[0] != '-')
  514.             continue;
  515.         argv[argc++] = opt;
  516.         if (opt[2] == '\0' || opt[2] != '=')
  517.             continue;
  518.         opt[2] = '\0';
  519.         argv[argc++] = &opt[3];
  520.     }
  521.     return (argc);
  522. }
  523.  
  524. struct statfs *
  525. getmntpt(name)
  526.     char *name;
  527. {
  528.     long mntsize;
  529.     register long i;
  530.     struct statfs *mntbuf;
  531.  
  532.     mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
  533.     for (i = 0; i < mntsize; i++) {
  534.         if (!strcmp(mntbuf[i].f_mntfromname, name) ||
  535.             !strcmp(mntbuf[i].f_mntonname, name))
  536.             return (&mntbuf[i]);
  537.     }
  538.     return ((struct statfs *)0);
  539. }
  540.  
  541. static int skipvfs;
  542.  
  543. badvfstype(vfstype, vfslist)
  544.     short vfstype;
  545.     char **vfslist;
  546. {
  547.  
  548.     if (vfslist == 0)
  549.         return(0);
  550.     while (*vfslist) {
  551.         if (vfstype == getmnttype(*vfslist))
  552.             return(skipvfs);
  553.         vfslist++;
  554.     }
  555.     return (!skipvfs);
  556. }
  557.  
  558. badvfsname(vfsname, vfslist)
  559.     char *vfsname;
  560.     char **vfslist;
  561. {
  562.  
  563.     if (vfslist == 0)
  564.         return(0);
  565.     while (*vfslist) {
  566.         if (strcmp(vfsname, *vfslist) == 0)
  567.             return(skipvfs);
  568.         vfslist++;
  569.     }
  570.     return (!skipvfs);
  571. }
  572.  
  573. char **
  574. makevfslist(fslist)
  575.     char *fslist;
  576. {
  577.     register char **av, *nextcp;
  578.     register int i;
  579.  
  580.     if (fslist == NULL)
  581.         return (NULL);
  582.     if (fslist[0] == 'n' && fslist[1] == 'o') {
  583.         fslist += 2;
  584.         skipvfs = 1;
  585.     }
  586.     for (i = 0, nextcp = fslist; *nextcp; nextcp++)
  587.         if (*nextcp == ',')
  588.             i++;
  589.     av = (char **)malloc((size_t)(i+2) * sizeof(char *));
  590.     if (av == NULL)
  591.         return (NULL);
  592.     nextcp = fslist;
  593.     i = 0;
  594.     av[i++] = nextcp;
  595.     while (nextcp = index(nextcp, ',')) {
  596.         *nextcp++ = '\0';
  597.         av[i++] = nextcp;
  598.     }
  599.     av[i++] = 0;
  600.     return (av);
  601. }
  602.  
  603. #ifdef NFS
  604. exclusive(a, b)
  605.     char *a, *b;
  606. {
  607.  
  608.     (void) fprintf(stderr, "mount: Options %s, %s mutually exclusive\n",
  609.         a, b);
  610.     exit(1);
  611. }
  612.  
  613. /*
  614.  * Handle the getoption arg.
  615.  * Essentially update "opflags", "retrycnt" and "nfsargs"
  616.  */
  617. getnfsopts(optarg, nfsargsp, opflagsp, retrycntp)
  618.     char *optarg;
  619.     register struct nfs_args *nfsargsp;
  620.     int *opflagsp;
  621.     int *retrycntp;
  622. {
  623.     register char *cp, *nextcp;
  624.     int num;
  625.     char *nump;
  626.  
  627.     for (cp = optarg; cp != NULL && *cp != '\0'; cp = nextcp) {
  628.         if ((nextcp = index(cp, ',')) != NULL)
  629.             *nextcp++ = '\0';
  630.         if ((nump = index(cp, '=')) != NULL) {
  631.             *nump++ = '\0';
  632.             num = atoi(nump);
  633.         } else
  634.             num = -1;
  635.         /*
  636.          * Just test for a string match and do it
  637.          */
  638.         if (!strcmp(cp, "bg")) {
  639.             *opflagsp |= BGRND;
  640.         } else if (!strcmp(cp, "soft")) {
  641.             if (nfsargsp->flags & NFSMNT_SPONGY)
  642.                 exclusive("soft, spongy");
  643.             nfsargsp->flags |= NFSMNT_SOFT;
  644.         } else if (!strcmp(cp, "spongy")) {
  645.             if (nfsargsp->flags & NFSMNT_SOFT)
  646.                 exclusive("soft, spongy");
  647.             nfsargsp->flags |= NFSMNT_SPONGY;
  648.         } else if (!strcmp(cp, "compress")) {
  649.             nfsargsp->flags |= NFSMNT_COMPRESS;
  650.         } else if (!strcmp(cp, "intr")) {
  651.             nfsargsp->flags |= NFSMNT_INT;
  652.         } else if (!strcmp(cp, "tcp")) {
  653.             nfsargsp->sotype = SOCK_STREAM;
  654.         } else if (!strcmp(cp, "noconn")) {
  655.             nfsargsp->flags |= NFSMNT_NOCONN;
  656.         } else if (!strcmp(cp, "retry") && num > 0) {
  657.             *retrycntp = num;
  658.         } else if (!strcmp(cp, "rsize") && num > 0) {
  659.             nfsargsp->rsize = num;
  660.             nfsargsp->flags |= NFSMNT_RSIZE;
  661.         } else if (!strcmp(cp, "wsize") && num > 0) {
  662.             nfsargsp->wsize = num;
  663.             nfsargsp->flags |= NFSMNT_WSIZE;
  664.         } else if (!strcmp(cp, "timeo") && num > 0) {
  665.             nfsargsp->timeo = num;
  666.             nfsargsp->flags |= NFSMNT_TIMEO;
  667.         } else if (!strcmp(cp, "retrans") && num > 0) {
  668.             nfsargsp->retrans = num;
  669.             nfsargsp->flags |= NFSMNT_RETRANS;
  670.         }
  671.     }
  672.     if (nfsargsp->sotype == SOCK_DGRAM) {
  673.         if (nfsargsp->rsize > NFS_MAXDGRAMDATA)
  674.             nfsargsp->rsize = NFS_MAXDGRAMDATA;
  675.         if (nfsargsp->wsize > NFS_MAXDGRAMDATA)
  676.             nfsargsp->wsize = NFS_MAXDGRAMDATA;
  677.     }
  678. }
  679.  
  680. char *
  681. getnfsargs(spec, nfsargsp)
  682.     char *spec;
  683.     struct nfs_args *nfsargsp;
  684. {
  685.     register CLIENT *clp;
  686.     struct hostent *hp;
  687.     static struct sockaddr_in saddr;
  688.     struct timeval pertry, try;
  689.     enum clnt_stat clnt_stat;
  690.     int so = RPC_ANYSOCK;
  691.     char *fsp, *hostp, *delimp;
  692.     u_short tport;
  693.     static struct nfhret nfhret;
  694.     static char nam[MNAMELEN + 1];
  695.     char buf[MAXPATHLEN + 1];
  696.  
  697.     strncpy(buf, spec, MAXPATHLEN);
  698.     buf[MAXPATHLEN] = '\0';
  699.     strncpy(nam, spec, MNAMELEN);
  700.     nam[MNAMELEN] = '\0';
  701.     if ((delimp = index(buf, '@')) != NULL) {
  702.         hostp = delimp + 1;
  703.         fsp = buf;
  704.     } else if ((delimp = index(buf, ':')) != NULL) {
  705.         hostp = buf;
  706.         fsp = delimp + 1;
  707.     } else {
  708.         (void) fprintf(stderr,
  709.             "mount: No <host>:<dirpath> or <dirpath>@<host> spec\n");
  710.         return (0);
  711.     }
  712.     *delimp = '\0';
  713.     if ((hp = gethostbyname(hostp)) == NULL) {
  714.         (void) fprintf(stderr, "mount: Can't get net id for host\n");
  715.         return (0);
  716.     }
  717.     bcopy(hp->h_addr, (caddr_t)&saddr.sin_addr, hp->h_length);
  718.     nfhret.stat = ETIMEDOUT;    /* Mark not yet successful */
  719.     while (retrycnt > 0) {
  720.         saddr.sin_family = AF_INET;
  721.         saddr.sin_port = htons(PMAPPORT);
  722.         if ((tport = pmap_getport(&saddr, RPCPROG_NFS,
  723.             NFS_VER2, IPPROTO_UDP)) == 0) {
  724.             if ((opflags & ISBGRND) == 0)
  725.                 clnt_pcreateerror("NFS Portmap");
  726.         } else {
  727.             saddr.sin_port = 0;
  728.             pertry.tv_sec = 10;
  729.             pertry.tv_usec = 0;
  730.             if ((clp = clntudp_create(&saddr, RPCPROG_MNT,
  731.                 RPCMNT_VER1, pertry, &so)) == NULL) {
  732.                 if ((opflags & ISBGRND) == 0)
  733.                     clnt_pcreateerror("Cannot MNT PRC");
  734.             } else {
  735.                 clp->cl_auth = authunix_create_default();
  736.                 try.tv_sec = 10;
  737.                 try.tv_usec = 0;
  738.                 clnt_stat = clnt_call(clp, RPCMNT_MOUNT,
  739.                     xdr_dir, fsp, xdr_fh, &nfhret, try);
  740.                 if (clnt_stat != RPC_SUCCESS) {
  741.                     if ((opflags & ISBGRND) == 0)
  742.                         clnt_perror(clp, "Bad MNT RPC");
  743.                 } else {
  744.                     auth_destroy(clp->cl_auth);
  745.                     clnt_destroy(clp);
  746.                     retrycnt = 0;
  747.                 }
  748.             }
  749.         }
  750.         if (--retrycnt > 0) {
  751.             if (opflags & BGRND) {
  752.                 opflags &= ~BGRND;
  753.                 if (fork())
  754.                     return (0);
  755.                 else
  756.                     opflags |= ISBGRND;
  757.             } 
  758.             sleep(10);
  759.         }
  760.     }
  761.     if (nfhret.stat) {
  762.         if (opflags & ISBGRND)
  763.             exit(1);
  764.         (void) fprintf(stderr, "Mount RPC error on %s: ", spec);
  765.         errno = nfhret.stat;
  766.         perror((char *)NULL);
  767.         return (0);
  768.     }
  769.     saddr.sin_port = htons(tport);
  770.     nfsargsp->addr = (struct sockaddr *) &saddr;
  771.     nfsargsp->fh = &nfhret.nfh;
  772.     nfsargsp->hostname = nam;
  773.     return ((caddr_t)nfsargsp);
  774. }
  775.  
  776. /*
  777.  * xdr routines for mount rpc's
  778.  */
  779. xdr_dir(xdrsp, dirp)
  780.     XDR *xdrsp;
  781.     char *dirp;
  782. {
  783.     return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
  784. }
  785.  
  786. xdr_fh(xdrsp, np)
  787.     XDR *xdrsp;
  788.     struct nfhret *np;
  789. {
  790.     if (!xdr_u_long(xdrsp, &(np->stat)))
  791.         return (0);
  792.     if (np->stat)
  793.         return (1);
  794.     return (xdr_opaque(xdrsp, (caddr_t)&(np->nfh), NFSX_FH));
  795. }
  796. #endif /* NFS */
  797.