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

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Rick Macklem at The University of Guelph.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. char copyright[] =
  39. "@(#) Copyright (c) 1989 Regents of the University of California.\n\
  40.  All rights reserved.\n";
  41. #endif not lint
  42.  
  43. #ifndef lint
  44. static char sccsid[] = "@(#)mountd.c    5.14 (Berkeley) 2/26/91";
  45. #endif not lint
  46.  
  47. #include <sys/param.h>
  48. #include <sys/ioctl.h>
  49. #include <sys/stat.h>
  50. #include <sys/file.h>
  51. #include <sys/mount.h>
  52. #include <sys/socket.h>
  53. #include <sys/errno.h>
  54. #include <sys/signal.h>
  55. #include <stdio.h>
  56. #include <string.h>
  57. #include <syslog.h>
  58. #include <netdb.h>
  59. #include <rpc/rpc.h>
  60. #include <rpc/pmap_clnt.h>
  61. #include <rpc/pmap_prot.h>
  62. #include <nfs/rpcv2.h>
  63. #include <nfs/nfsv2.h>
  64. #include "pathnames.h"
  65.  
  66. struct ufid {
  67.     u_short    ufid_len;
  68.     ino_t    ufid_ino;
  69.     long    ufid_gen;
  70. };
  71. /*
  72.  * Structures for keeping the mount list and export list
  73.  */
  74. struct mountlist {
  75.     struct mountlist *ml_next;
  76.     char    ml_host[RPCMNT_NAMELEN+1];
  77.     char    ml_dirp[RPCMNT_PATHLEN+1];
  78. };
  79.  
  80. struct exportlist {
  81.     struct exportlist *ex_next;
  82.     struct exportlist *ex_prev;
  83.     struct grouplist *ex_groups;
  84.     int    ex_rootuid;
  85.     int    ex_exflags;
  86.     dev_t    ex_dev;
  87.     char    ex_dirp[RPCMNT_PATHLEN+1];
  88. };
  89.  
  90. struct grouplist {
  91.     struct grouplist *gr_next;
  92.     struct hostent *gr_hp;
  93. };
  94.  
  95. /* Global defs */
  96. int mntsrv(), umntall_each(), xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist();
  97. void add_mlist(), del_mlist(), get_exportlist(), get_mountlist();
  98. void send_umntall();
  99. struct exportlist exphead;
  100. struct mountlist *mlhead;
  101. char exname[MAXPATHLEN];
  102. int def_rootuid = -2;
  103. int root_only = 1;
  104. extern int errno;
  105. #ifdef DEBUG
  106. int debug = 1;
  107. #else
  108. int debug = 0;
  109. #endif
  110.  
  111. /*
  112.  * Mountd server for NFS mount protocol as described in:
  113.  * NFS: Network File System Protocol Specification, RFC1094, Appendix A
  114.  * The optional arguments are the exports file name
  115.  * default: _PATH_EXPORTS
  116.  * and "-n" to allow nonroot mount.
  117.  */
  118. main(argc, argv)
  119.     int argc;
  120.     char **argv;
  121. {
  122.     SVCXPRT *transp;
  123.     int c;
  124.     extern int optind;
  125.     extern char *optarg;
  126.  
  127.     while ((c = getopt(argc, argv, "n")) != EOF)
  128.         switch (c) {
  129.         case 'n':
  130.             root_only = 0;
  131.             break;
  132.         default:
  133.             fprintf(stderr, "Usage: mountd [-n] [export_file]\n");
  134.             exit(1);
  135.         };
  136.     argc -= optind;
  137.     argv += optind;
  138.     exphead.ex_next = exphead.ex_prev = (struct exportlist *)0;
  139.     mlhead = (struct mountlist *)0;
  140.     if (argc == 1) {
  141.         strncpy(exname, *argv, MAXPATHLEN-1);
  142.         exname[MAXPATHLEN-1] = '\0';
  143.     } else
  144.         strcpy(exname, _PATH_EXPORTS);
  145.     openlog("mountd:", LOG_PID, LOG_DAEMON);
  146.     get_exportlist();
  147.     get_mountlist();
  148.     if (debug == 0) {
  149.         daemon(0, 0);
  150.         signal(SIGINT, SIG_IGN);
  151.         signal(SIGQUIT, SIG_IGN);
  152.     }
  153.     signal(SIGHUP, get_exportlist);
  154.     signal(SIGTERM, send_umntall);
  155.     { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w");
  156.       if (pidfile != NULL) {
  157.         fprintf(pidfile, "%d\n", getpid());
  158.         fclose(pidfile);
  159.       }
  160.     }
  161.     if ((transp = svcudp_create(RPC_ANYSOCK)) == NULL) {
  162.         syslog(LOG_ERR, "Can't create socket");
  163.         exit(1);
  164.     }
  165.     pmap_unset(RPCPROG_MNT, RPCMNT_VER1);
  166.     if (!svc_register(transp, RPCPROG_MNT, RPCMNT_VER1, mntsrv, IPPROTO_UDP)) {
  167.         syslog(LOG_ERR, "Can't register mount");
  168.         exit(1);
  169.     }
  170.     svc_run();
  171.     syslog(LOG_ERR, "Mountd died");
  172.     exit(1);
  173. }
  174.  
  175. /*
  176.  * The mount rpc service
  177.  */
  178. mntsrv(rqstp, transp)
  179.     register struct svc_req *rqstp;
  180.     register SVCXPRT *transp;
  181. {
  182.     register struct grouplist *grp;
  183.     register u_long **addrp;
  184.     register struct exportlist *ep;
  185.     nfsv2fh_t nfh;
  186.     struct authunix_parms *ucr;
  187.     struct stat stb;
  188.     struct hostent *hp;
  189.     u_long saddr;
  190.     char dirpath[RPCMNT_PATHLEN+1];
  191.     int bad = ENOENT;
  192.     int omask;
  193.     uid_t uid = -2;
  194.  
  195.     /* Get authorization */
  196.     switch (rqstp->rq_cred.oa_flavor) {
  197.     case AUTH_UNIX:
  198.         ucr = (struct authunix_parms *)rqstp->rq_clntcred;
  199.         uid = ucr->aup_uid;
  200.         break;
  201.     case AUTH_NULL:
  202.     default:
  203.         break;
  204.     }
  205.  
  206.     saddr = transp->xp_raddr.sin_addr.s_addr;
  207.     hp = (struct hostent *)0;
  208.     switch (rqstp->rq_proc) {
  209.     case NULLPROC:
  210.         if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
  211.             syslog(LOG_ERR, "Can't send reply");
  212.         return;
  213.     case RPCMNT_MOUNT:
  214.         if (uid != 0 && root_only) {
  215.             svcerr_weakauth(transp);
  216.             return;
  217.         }
  218.         if (!svc_getargs(transp, xdr_dir, dirpath)) {
  219.             svcerr_decode(transp);
  220.             return;
  221.         }
  222.  
  223.         /* Check to see if it's a valid dirpath */
  224.         if (stat(dirpath, &stb) < 0 || (stb.st_mode&S_IFMT) !=
  225.             S_IFDIR) {
  226.             if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
  227.                 syslog(LOG_ERR, "Can't send reply");
  228.             return;
  229.         }
  230.  
  231.         /* Check in the exports list */
  232.         omask = sigblock(sigmask(SIGHUP));
  233.         ep = exphead.ex_next;
  234.         while (ep != NULL) {
  235.             if (!strcmp(ep->ex_dirp, dirpath)) {
  236.                 grp = ep->ex_groups;
  237.                 if (grp == NULL)
  238.                     break;
  239.  
  240.                 /* Check for a host match */
  241.                 addrp = (u_long **)grp->gr_hp->h_addr_list;
  242.                 for (;;) {
  243.                     if (**addrp == saddr)
  244.                         break;
  245.                     if (*++addrp == NULL)
  246.                         if (grp = grp->gr_next) {
  247.                             addrp = (u_long **)
  248.                                 grp->gr_hp->h_addr_list;
  249.                         } else {
  250.                             bad = EACCES;
  251.                             if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
  252.                                 syslog(LOG_ERR, "Can't send reply");
  253.                             sigsetmask(omask);
  254.                             return;
  255.                         }
  256.                 }
  257.                 hp = grp->gr_hp;
  258.                 break;
  259.             }
  260.             ep = ep->ex_next;
  261.         }
  262.         sigsetmask(omask);
  263.         if (ep == NULL) {
  264.             bad = EACCES;
  265.             if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
  266.                 syslog(LOG_ERR, "Can't send reply");
  267.             return;
  268.         }
  269.  
  270.         /* Get the file handle */
  271.         bzero((caddr_t)&nfh, sizeof(nfh));
  272.         if (getfh(dirpath, (fhandle_t *)&nfh) < 0) {
  273.             bad = errno;
  274.             if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
  275.                 syslog(LOG_ERR, "Can't send reply");
  276.             return;
  277.         }
  278.         if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh))
  279.             syslog(LOG_ERR, "Can't send reply");
  280.         if (hp == NULL)
  281.             hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);
  282.         if (hp)
  283.             add_mlist(hp->h_name, dirpath);
  284.         return;
  285.     case RPCMNT_DUMP:
  286.         if (!svc_sendreply(transp, xdr_mlist, (caddr_t)0))
  287.             syslog(LOG_ERR, "Can't send reply");
  288.         return;
  289.     case RPCMNT_UMOUNT:
  290.         if (uid != 0 && root_only) {
  291.             svcerr_weakauth(transp);
  292.             return;
  293.         }
  294.         if (!svc_getargs(transp, xdr_dir, dirpath)) {
  295.             svcerr_decode(transp);
  296.             return;
  297.         }
  298.         if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
  299.             syslog(LOG_ERR, "Can't send reply");
  300.         hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);
  301.         if (hp)
  302.             del_mlist(hp->h_name, dirpath);
  303.         return;
  304.     case RPCMNT_UMNTALL:
  305.         if (uid != 0 && root_only) {
  306.             svcerr_weakauth(transp);
  307.             return;
  308.         }
  309.         if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
  310.             syslog(LOG_ERR, "Can't send reply");
  311.         hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);
  312.         if (hp)
  313.             del_mlist(hp->h_name, (char *)0);
  314.         return;
  315.     case RPCMNT_EXPORT:
  316.         if (!svc_sendreply(transp, xdr_explist, (caddr_t)0))
  317.             syslog(LOG_ERR, "Can't send reply");
  318.         return;
  319.     default:
  320.         svcerr_noproc(transp);
  321.         return;
  322.     }
  323. }
  324.  
  325. /*
  326.  * Xdr conversion for a dirpath string
  327.  */
  328. xdr_dir(xdrsp, dirp)
  329.     XDR *xdrsp;
  330.     char *dirp;
  331. {
  332.     return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
  333. }
  334.  
  335. /*
  336.  * Xdr routine to generate fhstatus
  337.  */
  338. xdr_fhs(xdrsp, nfh)
  339.     XDR *xdrsp;
  340.     nfsv2fh_t *nfh;
  341. {
  342.     int ok = 0;
  343.  
  344.     if (!xdr_long(xdrsp, &ok))
  345.         return (0);
  346.     return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH));
  347. }
  348.  
  349. xdr_mlist(xdrsp, cp)
  350.     XDR *xdrsp;
  351.     caddr_t cp;
  352. {
  353.     register struct mountlist *mlp;
  354.     int true = 1;
  355.     int false = 0;
  356.     char *strp;
  357.  
  358.     mlp = mlhead;
  359.     while (mlp) {
  360.         if (!xdr_bool(xdrsp, &true))
  361.             return (0);
  362.         strp = &mlp->ml_host[0];
  363.         if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
  364.             return (0);
  365.         strp = &mlp->ml_dirp[0];
  366.         if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
  367.             return (0);
  368.         mlp = mlp->ml_next;
  369.     }
  370.     if (!xdr_bool(xdrsp, &false))
  371.         return (0);
  372.     return (1);
  373. }
  374.  
  375. /*
  376.  * Xdr conversion for export list
  377.  */
  378. xdr_explist(xdrsp, cp)
  379.     XDR *xdrsp;
  380.     caddr_t cp;
  381. {
  382.     register struct exportlist *ep;
  383.     register struct grouplist *grp;
  384.     int true = 1;
  385.     int false = 0;
  386.     char *strp;
  387.     int omask;
  388.  
  389.     omask = sigblock(sigmask(SIGHUP));
  390.     ep = exphead.ex_next;
  391.     while (ep != NULL) {
  392.         if (!xdr_bool(xdrsp, &true))
  393.             goto errout;
  394.         strp = &ep->ex_dirp[0];
  395.         if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
  396.             goto errout;
  397.         grp = ep->ex_groups;
  398.         while (grp != NULL) {
  399.             if (!xdr_bool(xdrsp, &true))
  400.                 goto errout;
  401.             strp = grp->gr_hp->h_name;
  402.             if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
  403.                 goto errout;
  404.             grp = grp->gr_next;
  405.         }
  406.         if (!xdr_bool(xdrsp, &false))
  407.             goto errout;
  408.         ep = ep->ex_next;
  409.     }
  410.     sigsetmask(omask);
  411.     if (!xdr_bool(xdrsp, &false))
  412.         return (0);
  413.     return (1);
  414. errout:
  415.     sigsetmask(omask);
  416.     return (0);
  417. }
  418.  
  419. #define LINESIZ    10240
  420. char line[LINESIZ];
  421.  
  422. /*
  423.  * Get the export list
  424.  */
  425. void
  426. get_exportlist()
  427. {
  428.     register struct hostent *hp, *nhp;
  429.     register char **addrp, **naddrp;
  430.     register int i;
  431.     register struct grouplist *grp;
  432.     register struct exportlist *ep, *ep2;
  433.     struct statfs stfsbuf;
  434.     struct ufs_args args;
  435.     struct stat sb;
  436.     FILE *inf;
  437.     char *cp, *endcp;
  438.     char savedc;
  439.     int len, dirplen;
  440.     int rootuid, exflags;
  441.     u_long saddr;
  442.     struct exportlist *fep;
  443.  
  444.     /*
  445.      * First, get rid of the old list
  446.      */
  447.     ep = exphead.ex_next;
  448.     while (ep != NULL) {
  449.         ep2 = ep;
  450.         ep = ep->ex_next;
  451.         free_exp(ep2);
  452.     }
  453.  
  454.     /*
  455.      * Read in the exports file and build the list, calling
  456.      * exportfs() as we go along
  457.      */
  458.     exphead.ex_next = exphead.ex_prev = (struct exportlist *)0;
  459.     if ((inf = fopen(exname, "r")) == NULL) {
  460.         syslog(LOG_ERR, "Can't open %s", exname);
  461.         exit(2);
  462.     }
  463.     while (fgets(line, LINESIZ, inf)) {
  464.         exflags = MNT_EXPORTED;
  465.         rootuid = def_rootuid;
  466.         cp = line;
  467.         nextfield(&cp, &endcp);
  468.  
  469.         /*
  470.          * Get file system devno and see if an entry for this
  471.          * file system already exists.
  472.          */
  473.         savedc = *endcp;
  474.         *endcp = '\0';
  475.         if (stat(cp, &sb) < 0 || (sb.st_mode & S_IFMT) != S_IFDIR) {
  476.             syslog(LOG_ERR,
  477.                 "Bad Exports File, %s: %s, mountd Failed",
  478.                 cp, "Not a directory");
  479.             exit(2);
  480.         }
  481.         fep = (struct exportlist *)0;
  482.         ep = exphead.ex_next;
  483.         while (ep) {
  484.             if (ep->ex_dev == sb.st_dev) {
  485.                 fep = ep;
  486.                 break;
  487.             }
  488.             ep = ep->ex_next;
  489.         }
  490.         *endcp = savedc;
  491.  
  492.         /*
  493.          * Create new exports list entry
  494.          */
  495.         len = endcp-cp;
  496.         if (len <= RPCMNT_PATHLEN && len > 0) {
  497.             ep = (struct exportlist *)malloc(sizeof(*ep));
  498.             if (ep == NULL)
  499.                 goto err;
  500.             ep->ex_next = ep->ex_prev = (struct exportlist *)0;
  501.             ep->ex_groups = (struct grouplist *)0;
  502.             bcopy(cp, ep->ex_dirp, len);
  503.             ep->ex_dirp[len] = '\0';
  504.             dirplen = len;
  505.         } else {
  506.             syslog(LOG_ERR, "Bad Exports File, mountd Failed");
  507.             exit(2);
  508.         }
  509.         cp = endcp;
  510.         nextfield(&cp, &endcp);
  511.         len = endcp-cp;
  512.         while (len > 0) {
  513.             savedc = *endcp;
  514.             *endcp = '\0';
  515.             if (len > RPCMNT_NAMELEN)
  516.                 goto more;
  517.             if (*cp == '-') {
  518.                 do_opt(cp + 1, fep, ep, &exflags, &rootuid);
  519.                 goto more;
  520.             }
  521.             if (isdigit(*cp)) {
  522.                 saddr = inet_addr(cp);
  523.                 if (saddr == -1 ||
  524.                     (hp = gethostbyaddr((caddr_t)&saddr,
  525.                      sizeof(saddr), AF_INET)) == NULL) {
  526.                     syslog(LOG_ERR,
  527.                         "Bad Exports File, %s: %s", cp,
  528.                         "Gethostbyaddr failed, ignored");
  529.                     goto more;
  530.                 }
  531.             } else if ((hp = gethostbyname(cp)) == NULL) {
  532.                 syslog(LOG_ERR, "Bad Exports File, %s: %s",
  533.                     cp, "Gethostbyname failed, ignored");
  534.                 goto more;
  535.             }
  536.             grp = (struct grouplist *)
  537.                 malloc(sizeof(struct grouplist));
  538.             if (grp == NULL)
  539.                 goto err;
  540.             nhp = grp->gr_hp = (struct hostent *)
  541.                 malloc(sizeof(struct hostent));
  542.             if (nhp == NULL)
  543.                 goto err;
  544.             bcopy((caddr_t)hp, (caddr_t)nhp,
  545.                 sizeof(struct hostent));
  546.             i = strlen(hp->h_name)+1;
  547.             nhp->h_name = (char *)malloc(i);
  548.             if (nhp->h_name == NULL)
  549.                 goto err;
  550.             bcopy(hp->h_name, nhp->h_name, i);
  551.             addrp = hp->h_addr_list;
  552.             i = 1;
  553.             while (*addrp++)
  554.                 i++;
  555.             naddrp = nhp->h_addr_list = (char **)
  556.                 malloc(i*sizeof(char *));
  557.             if (naddrp == NULL)
  558.                 goto err;
  559.             addrp = hp->h_addr_list;
  560.             while (*addrp) {
  561.                 *naddrp = (char *)
  562.                     malloc(hp->h_length);
  563.                 if (*naddrp == NULL)
  564.                     goto err;
  565.                 bcopy(*addrp, *naddrp,
  566.                     hp->h_length);
  567.                 addrp++;
  568.                 naddrp++;
  569.             }
  570.             *naddrp = (char *)0;
  571.             grp->gr_next = ep->ex_groups;
  572.             ep->ex_groups = grp;
  573.         more:
  574.             cp = endcp;
  575.             *cp = savedc;
  576.             nextfield(&cp, &endcp);
  577.             len = endcp - cp;
  578.         }
  579.         if (fep == NULL) {
  580.             args.fspec = 0;
  581.             args.exflags = exflags;
  582.             args.exroot = rootuid;
  583.             cp = (char *)0;
  584.             while (statfs(ep->ex_dirp, &stfsbuf) < 0 ||
  585.                    mount(MOUNT_UFS, ep->ex_dirp,
  586.                      stfsbuf.f_flags|MNT_UPDATE, &args) < 0) {
  587.                 if (cp == NULL)
  588.                     cp = ep->ex_dirp + dirplen - 1;
  589.                 else
  590.                     *cp = savedc;
  591.                 /* back up over the last component */
  592.                 while (*cp == '/' && cp > ep->ex_dirp)
  593.                     cp--;
  594.                 while (*(cp - 1) != '/' && cp > ep->ex_dirp)
  595.                     cp--;
  596.                 if (cp == ep->ex_dirp) {
  597.                     syslog(LOG_WARNING,
  598.                           "Can't export %s", ep->ex_dirp);
  599.                     free_exp(ep);
  600.                     goto nextline;
  601.                 }
  602.                 savedc = *cp;
  603.                 *cp = '\0';
  604.             }
  605.             if (cp)
  606.                 *cp = savedc;
  607.             ep->ex_rootuid = rootuid;
  608.             ep->ex_exflags = exflags;
  609.         } else {
  610.             ep->ex_rootuid = fep->ex_rootuid;
  611.             ep->ex_exflags = fep->ex_exflags;
  612.         }
  613.         ep->ex_dev = sb.st_dev;
  614.         ep->ex_next = exphead.ex_next;
  615.         ep->ex_prev = &exphead;
  616.         if (ep->ex_next != NULL)
  617.             ep->ex_next->ex_prev = ep;
  618.         exphead.ex_next = ep;
  619. nextline:
  620.         ;
  621.     }
  622.     fclose(inf);
  623.     return;
  624. err:
  625.     syslog(LOG_ERR, "No more memory: mountd Failed");
  626.     exit(2);
  627. }
  628.  
  629. /*
  630.  * Parse out the next white space separated field
  631.  */
  632. nextfield(cp, endcp)
  633.     char **cp;
  634.     char **endcp;
  635. {
  636.     register char *p;
  637.  
  638.     p = *cp;
  639.     while (*p == ' ' || *p == '\t')
  640.         p++;
  641.     if (*p == '\n' || *p == '\0') {
  642.         *cp = *endcp = p;
  643.         return;
  644.     }
  645.     *cp = p++;
  646.     while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
  647.         p++;
  648.     *endcp = p;
  649. }
  650.  
  651. /*
  652.  * Parse the option string
  653.  */
  654. do_opt(cpopt, fep, ep, exflagsp, rootuidp)
  655.     register char *cpopt;
  656.     struct exportlist *fep, *ep;
  657.     int *exflagsp, *rootuidp;
  658. {
  659.     register char *cpoptarg, *cpoptend;
  660.  
  661.     while (cpopt && *cpopt) {
  662.         if (cpoptend = index(cpopt, ','))
  663.             *cpoptend++ = '\0';
  664.         if (cpoptarg = index(cpopt, '='))
  665.             *cpoptarg++ = '\0';
  666.         if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) {
  667.             if (fep && (fep->ex_exflags & MNT_EXRDONLY) == 0)
  668.                 syslog(LOG_WARNING, "ro failed for %s",
  669.                        ep->ex_dirp);
  670.             else
  671.                 *exflagsp |= MNT_EXRDONLY;
  672.         } else if (!strcmp(cpopt, "root") || !strcmp(cpopt, "r")) {
  673.             if (cpoptarg && isdigit(*cpoptarg)) {
  674.                 *rootuidp = atoi(cpoptarg);
  675.                 if (fep && fep->ex_rootuid != *rootuidp)
  676.                     syslog(LOG_WARNING,
  677.                            "uid failed for %s",
  678.                            ep->ex_dirp);
  679.             } else
  680.                 syslog(LOG_WARNING,
  681.                        "uid failed for %s",
  682.                        ep->ex_dirp);
  683.         } else
  684.             syslog(LOG_WARNING, "opt %s ignored for %s", cpopt,
  685.                    ep->ex_dirp);
  686.         cpopt = cpoptend;
  687.     }
  688. }
  689.  
  690. #define    STRSIZ    (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50)
  691. /*
  692.  * Routines that maintain the remote mounttab
  693.  */
  694. void get_mountlist()
  695. {
  696.     register struct mountlist *mlp, **mlpp;
  697.     register char *eos, *dirp;
  698.     int len;
  699.     char str[STRSIZ];
  700.     FILE *mlfile;
  701.  
  702.     if (((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) &&
  703.         ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL)) {
  704.         syslog(LOG_WARNING, "Can't open %s", _PATH_RMOUNTLIST);
  705.         return;
  706.     }
  707.     mlpp = &mlhead;
  708.     while (fgets(str, STRSIZ, mlfile) != NULL) {
  709.         if ((dirp = index(str, '\t')) == NULL &&
  710.             (dirp = index(str, ' ')) == NULL)
  711.             continue;
  712.         mlp = (struct mountlist *)malloc(sizeof (*mlp));
  713.         len = dirp-str;
  714.         if (len > RPCMNT_NAMELEN)
  715.             len = RPCMNT_NAMELEN;
  716.         bcopy(str, mlp->ml_host, len);
  717.         mlp->ml_host[len] = '\0';
  718.         while (*dirp == '\t' || *dirp == ' ')
  719.             dirp++;
  720.         if ((eos = index(dirp, '\t')) == NULL &&
  721.             (eos = index(dirp, ' ')) == NULL &&
  722.             (eos = index(dirp, '\n')) == NULL)
  723.             len = strlen(dirp);
  724.         else
  725.             len = eos-dirp;
  726.         if (len > RPCMNT_PATHLEN)
  727.             len = RPCMNT_PATHLEN;
  728.         bcopy(dirp, mlp->ml_dirp, len);
  729.         mlp->ml_dirp[len] = '\0';
  730.         mlp->ml_next = (struct mountlist *)0;
  731.         *mlpp = mlp;
  732.         mlpp = &mlp->ml_next;
  733.     }
  734.     fclose(mlfile);
  735. }
  736.  
  737. void del_mlist(hostp, dirp)
  738.     register char *hostp, *dirp;
  739. {
  740.     register struct mountlist *mlp, **mlpp;
  741.     FILE *mlfile;
  742.     int fnd = 0;
  743.  
  744.     mlpp = &mlhead;
  745.     mlp = mlhead;
  746.     while (mlp) {
  747.         if (!strcmp(mlp->ml_host, hostp) &&
  748.             (!dirp || !strcmp(mlp->ml_dirp, dirp))) {
  749.             fnd = 1;
  750.             *mlpp = mlp->ml_next;
  751.             free((caddr_t)mlp);
  752.         }
  753.         mlpp = &mlp->ml_next;
  754.         mlp = mlp->ml_next;
  755.     }
  756.     if (fnd) {
  757.         if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) {
  758.             syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST);
  759.             return;
  760.         }
  761.         mlp = mlhead;
  762.         while (mlp) {
  763.             fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp);
  764.             mlp = mlp->ml_next;
  765.         }
  766.         fclose(mlfile);
  767.     }
  768. }
  769.  
  770. void add_mlist(hostp, dirp)
  771.     register char *hostp, *dirp;
  772. {
  773.     register struct mountlist *mlp, **mlpp;
  774.     FILE *mlfile;
  775.  
  776.     mlpp = &mlhead;
  777.     mlp = mlhead;
  778.     while (mlp) {
  779.         if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp))
  780.             return;
  781.         mlpp = &mlp->ml_next;
  782.         mlp = mlp->ml_next;
  783.     }
  784.     mlp = (struct mountlist *)malloc(sizeof (*mlp));
  785.     strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN);
  786.     mlp->ml_host[RPCMNT_NAMELEN] = '\0';
  787.     strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN);
  788.     mlp->ml_dirp[RPCMNT_PATHLEN] = '\0';
  789.     mlp->ml_next = (struct mountlist *)0;
  790.     *mlpp = mlp;
  791.     if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) {
  792.         syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST);
  793.         return;
  794.     }
  795.     fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp);
  796.     fclose(mlfile);
  797. }
  798.  
  799. /*
  800.  * This function is called via. SIGTERM when the system is going down.
  801.  * It sends a broadcast RPCMNT_UMNTALL.
  802.  */
  803. void
  804. send_umntall()
  805. {
  806.     (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL,
  807.         xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each);
  808.     exit();
  809. }
  810.  
  811. umntall_each(resultsp, raddr)
  812.     caddr_t resultsp;
  813.     struct sockaddr_in *raddr;
  814. {
  815.     return (1);
  816. }
  817.  
  818. /*
  819.  * Free up an exports list component
  820.  */
  821. free_exp(ep)
  822.     register struct exportlist *ep;
  823. {
  824.     register struct grouplist *grp;
  825.     register char **addrp;
  826.     struct grouplist *grp2;
  827.  
  828.     grp = ep->ex_groups;
  829.     while (grp != NULL) {
  830.         addrp = grp->gr_hp->h_addr_list;
  831.         while (*addrp)
  832.             free(*addrp++);
  833.         free((caddr_t)grp->gr_hp->h_addr_list);
  834.         free(grp->gr_hp->h_name);
  835.         free((caddr_t)grp->gr_hp);
  836.         grp2 = grp;
  837.         grp = grp->gr_next;
  838.         free((caddr_t)grp2);
  839.     }
  840.     free((caddr_t)ep);
  841. }
  842.