138460Smckusick /* 238460Smckusick * Copyright (c) 1989 The Regents of the University of California. 338460Smckusick * All rights reserved. 438460Smckusick * 538460Smckusick * This code is derived from software contributed to Berkeley by 638460Smckusick * Rick Macklem at The University of Guelph. 738460Smckusick * 838460Smckusick * Redistribution and use in source and binary forms are permitted 938460Smckusick * provided that the above copyright notice and this paragraph are 1038460Smckusick * duplicated in all such forms and that any documentation, 1138460Smckusick * advertising materials, and other materials related to such 1238460Smckusick * distribution and use acknowledge that the software was developed 1338460Smckusick * by the University of California, Berkeley. The name of the 1438460Smckusick * University may not be used to endorse or promote products derived 1538460Smckusick * from this software without specific prior written permission. 1638460Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1738460Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1838460Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1938460Smckusick */ 2038460Smckusick 2138460Smckusick #ifndef lint 2238460Smckusick char copyright[] = 2338460Smckusick "@(#) Copyright (c) 1989 Regents of the University of California.\n\ 2438460Smckusick All rights reserved.\n"; 2538460Smckusick #endif not lint 2638460Smckusick 2738460Smckusick #ifndef lint 28*42038Sbostic static char sccsid[] = "@(#)mountd.c 5.7 (Berkeley) 05/15/90"; 2938460Smckusick #endif not lint 3038460Smckusick 3138460Smckusick #include <sys/param.h> 3238460Smckusick #include <sys/ioctl.h> 3338460Smckusick #include <sys/stat.h> 3439681Smckusick #include <sys/file.h> 3538460Smckusick #include <sys/mount.h> 3638460Smckusick #include <sys/socket.h> 3738460Smckusick #include <sys/errno.h> 38*42038Sbostic #include <sys/signal.h> 39*42038Sbostic #include <stdio.h> 40*42038Sbostic #include <string.h> 41*42038Sbostic #include <syslog.h> 4238460Smckusick #include <netdb.h> 4338460Smckusick #include <rpc/rpc.h> 4438460Smckusick #include <rpc/pmap_clnt.h> 4538460Smckusick #include <rpc/pmap_prot.h> 4638460Smckusick #include <nfs/rpcv2.h> 4738460Smckusick #include <nfs/nfsv2.h> 4839681Smckusick #include "pathnames.h" 4938460Smckusick 5038460Smckusick struct ufid { 5138460Smckusick u_short ufid_len; 5238460Smckusick ino_t ufid_ino; 5338460Smckusick long ufid_gen; 5438460Smckusick }; 5538460Smckusick /* 5638460Smckusick * Structures for keeping the mount list and export list 5738460Smckusick */ 5838460Smckusick struct mountlist { 5938460Smckusick char ml_host[RPCMNT_NAMELEN+1]; 6038460Smckusick char ml_dirp[RPCMNT_PATHLEN+1]; 6138460Smckusick }; 6238460Smckusick 6338460Smckusick struct exportlist { 6438460Smckusick struct exportlist *ex_next; 6538460Smckusick struct exportlist *ex_prev; 6638460Smckusick struct grouplist *ex_groups; 6738460Smckusick int ex_rootuid; 6838460Smckusick int ex_exflags; 6938460Smckusick char ex_dirp[RPCMNT_PATHLEN+1]; 7038460Smckusick }; 7138460Smckusick 7238460Smckusick struct grouplist { 7338460Smckusick struct grouplist *gr_next; 7439681Smckusick struct hostent *gr_hp; 7538460Smckusick }; 7638460Smckusick 7738460Smckusick /* Global defs */ 7838460Smckusick int xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist(); 7938460Smckusick int mntsrv(), get_exportlist(); 8038460Smckusick struct exportlist exphead; 8139681Smckusick int mlfile; 8238460Smckusick char exname[MAXPATHLEN]; 8338460Smckusick int def_rootuid = -2; 8438460Smckusick extern int errno; 8538460Smckusick #ifdef DEBUG 8638460Smckusick int debug = 1; 8738460Smckusick #else 8838460Smckusick int debug = 0; 8938460Smckusick #endif 9038460Smckusick 9138460Smckusick /* 9238460Smckusick * Mountd server for NFS mount protocol as described in: 9339681Smckusick * NFS: Network File System Protocol Specification, RFC1094, Appendix A 9438460Smckusick * The optional argument is the exports file name 9539681Smckusick * default: _PATH_EXPORTS 9638460Smckusick */ 9738460Smckusick main(argc, argv) 9838460Smckusick int argc; 9938460Smckusick char *argv[]; 10038460Smckusick { 10138460Smckusick SVCXPRT *transp; 10238460Smckusick 10338460Smckusick if (debug == 0) { 10438460Smckusick if (fork()) 10538460Smckusick exit(0); 10638460Smckusick { int s; 10738460Smckusick for (s = 0; s < 10; s++) 10838460Smckusick (void) close(s); 10938460Smckusick } 11038460Smckusick (void) open("/", O_RDONLY); 11138460Smckusick (void) dup2(0, 1); 11238460Smckusick (void) dup2(0, 2); 11338460Smckusick { int tt = open("/dev/tty", O_RDWR); 11438460Smckusick if (tt > 0) { 11538460Smckusick ioctl(tt, TIOCNOTTY, (char *)0); 11638460Smckusick close(tt); 11738460Smckusick } 11838460Smckusick } 11938460Smckusick (void) setpgrp(0, 0); 12038460Smckusick signal(SIGTSTP, SIG_IGN); 12138460Smckusick signal(SIGTTIN, SIG_IGN); 12238460Smckusick signal(SIGTTOU, SIG_IGN); 12338460Smckusick signal(SIGINT, SIG_IGN); 12438460Smckusick signal(SIGQUIT, SIG_IGN); 12538460Smckusick signal(SIGTERM, SIG_IGN); 12638460Smckusick } 12738460Smckusick openlog("mountd:", LOG_PID, LOG_DAEMON); 12838460Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 12938460Smckusick if (argc == 2) { 13038460Smckusick strncpy(exname, argv[1], MAXPATHLEN-1); 13138460Smckusick exname[MAXPATHLEN-1] = '\0'; 13238460Smckusick } else 13339681Smckusick strcpy(exname, _PATH_EXPORTS); 13438460Smckusick get_exportlist(); 13538460Smckusick signal(SIGHUP, get_exportlist); 13640494Smckusick { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w"); 13740494Smckusick if (pidfile != NULL) { 13840494Smckusick fprintf(pidfile, "%d\n", getpid()); 13940494Smckusick fclose(pidfile); 14040494Smckusick } 14140494Smckusick } 14239681Smckusick if ((mlfile = open(_PATH_RMOUNTLIST, (O_RDWR|O_CREAT), 0600)) < 0) { 14339681Smckusick syslog(LOG_ERR, "Can't open mountlist file"); 14439681Smckusick exit(1); 14539681Smckusick } 14638460Smckusick if ((transp = svcudp_create(RPC_ANYSOCK)) == NULL) { 14738460Smckusick syslog(LOG_ERR, "Can't create socket"); 14838460Smckusick exit(1); 14938460Smckusick } 15038460Smckusick pmap_unset(RPCPROG_MNT, RPCMNT_VER1); 15138460Smckusick if (!svc_register(transp, RPCPROG_MNT, RPCMNT_VER1, mntsrv, IPPROTO_UDP)) { 15238460Smckusick syslog(LOG_ERR, "Can't register mount"); 15338460Smckusick exit(1); 15438460Smckusick } 15538460Smckusick svc_run(); 15638460Smckusick syslog(LOG_ERR, "Mountd died"); 15738460Smckusick } 15838460Smckusick 15938460Smckusick /* 16038460Smckusick * The mount rpc service 16138460Smckusick */ 16238460Smckusick mntsrv(rqstp, transp) 16338460Smckusick register struct svc_req *rqstp; 16438460Smckusick register SVCXPRT *transp; 16538460Smckusick { 16639681Smckusick register struct grouplist *grp; 16739681Smckusick register u_long **addrp; 16838460Smckusick register struct exportlist *ep; 16939681Smckusick struct mountlist ml; 17038460Smckusick nfsv2fh_t nfh; 17138460Smckusick struct authunix_parms *ucr; 17238460Smckusick struct stat stb; 17338460Smckusick struct hostent *hp; 17439681Smckusick u_long saddr; 17538460Smckusick char dirpath[RPCMNT_PATHLEN+1]; 17638460Smckusick int ok = 0; 17738460Smckusick int bad = ENOENT; 17838460Smckusick int omask; 17939681Smckusick uid_t uid = -2; 18038460Smckusick 18138460Smckusick /* Get authorization */ 18238460Smckusick switch (rqstp->rq_cred.oa_flavor) { 18338460Smckusick case AUTH_UNIX: 18438460Smckusick ucr = (struct authunix_parms *)rqstp->rq_clntcred; 18539681Smckusick uid = ucr->aup_uid; 18639681Smckusick break; 18738460Smckusick case AUTH_NULL: 18838460Smckusick default: 18939681Smckusick break; 19038460Smckusick } 19138460Smckusick 19239681Smckusick saddr = transp->xp_raddr.sin_addr.s_addr; 19339681Smckusick hp = (struct hostent *)0; 19438460Smckusick switch (rqstp->rq_proc) { 19539681Smckusick case NULLPROC: 19639681Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 19739681Smckusick syslog(LOG_ERR, "Can't send reply"); 19839681Smckusick return; 19938460Smckusick case RPCMNT_MOUNT: 20039681Smckusick if (uid != 0) { 20139681Smckusick svcerr_weakauth(transp); 20239681Smckusick return; 20339681Smckusick } 20438460Smckusick if (!svc_getargs(transp, xdr_dir, dirpath)) { 20538460Smckusick svcerr_decode(transp); 20638460Smckusick return; 20738460Smckusick } 20838460Smckusick 20938460Smckusick /* Check to see if it's a valid dirpath */ 21038460Smckusick if (stat(dirpath, &stb) < 0 || (stb.st_mode&S_IFMT) != 21138460Smckusick S_IFDIR) { 21238460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 21338460Smckusick syslog(LOG_ERR, "Can't send reply"); 21438460Smckusick return; 21538460Smckusick } 21638460Smckusick 21738460Smckusick /* Check in the exports list */ 21838460Smckusick omask = sigblock(sigmask(SIGHUP)); 21938460Smckusick ep = exphead.ex_next; 22038460Smckusick while (ep != NULL) { 22138460Smckusick if (!strcmp(ep->ex_dirp, dirpath)) { 22238460Smckusick grp = ep->ex_groups; 22338460Smckusick if (grp == NULL) 22438460Smckusick break; 22539681Smckusick 22639681Smckusick /* Check for a host match */ 22739681Smckusick addrp = (u_long **)grp->gr_hp->h_addr_list; 22839681Smckusick for (;;) { 22939681Smckusick if (**addrp == saddr) 23038460Smckusick break; 23139681Smckusick if (*++addrp == NULL) 23239681Smckusick if (grp = grp->gr_next) { 23339681Smckusick addrp = (u_long **) 23439681Smckusick grp->gr_hp->h_addr_list; 23539681Smckusick } else { 23639681Smckusick bad = EACCES; 23739681Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 23839681Smckusick syslog(LOG_ERR, "Can't send reply"); 23939681Smckusick sigsetmask(omask); 24039681Smckusick return; 24139681Smckusick } 24238460Smckusick } 24339681Smckusick hp = grp->gr_hp; 24439681Smckusick break; 24538460Smckusick } 24638460Smckusick ep = ep->ex_next; 24738460Smckusick } 24838460Smckusick sigsetmask(omask); 24938460Smckusick if (ep == NULL) { 25038460Smckusick bad = EACCES; 25138460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 25238460Smckusick syslog(LOG_ERR, "Can't send reply"); 25338460Smckusick return; 25438460Smckusick } 25538460Smckusick 25638460Smckusick /* Get the file handle */ 25738460Smckusick bzero((caddr_t)&nfh, sizeof(nfh)); 25838460Smckusick if (getfh(dirpath, (fhandle_t *)&nfh) < 0) { 25938460Smckusick bad = errno; 26038460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 26138460Smckusick syslog(LOG_ERR, "Can't send reply"); 26238460Smckusick return; 26338460Smckusick } 26439681Smckusick #ifdef notnow 26539681Smckusick nfh.fh_generic.fh_fid.fid_gen = htonl(nfh.fh_generic.fh_fid.fid_gen); 26639681Smckusick #endif 26738460Smckusick if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh)) 26838460Smckusick syslog(LOG_ERR, "Can't send reply"); 26939681Smckusick if (hp == NULL) 27039681Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 27139681Smckusick if (hp) { 27239681Smckusick if (!fnd_mnt(hp->h_name, dirpath)) { 27339681Smckusick strcpy(ml.ml_host, hp->h_name); 27439681Smckusick strcpy(ml.ml_dirp, dirpath); 27539681Smckusick write(mlfile, (caddr_t)&ml, sizeof(ml)); 27639681Smckusick } 27738460Smckusick } 27838460Smckusick return; 27938460Smckusick case RPCMNT_DUMP: 28038460Smckusick if (!svc_sendreply(transp, xdr_mlist, (caddr_t)0)) 28138460Smckusick syslog(LOG_ERR, "Can't send reply"); 28238460Smckusick return; 28338460Smckusick case RPCMNT_UMOUNT: 28439681Smckusick if (uid != 0) { 28539681Smckusick svcerr_weakauth(transp); 28639681Smckusick return; 28739681Smckusick } 28838460Smckusick if (!svc_getargs(transp, xdr_dir, dirpath)) { 28938460Smckusick svcerr_decode(transp); 29038460Smckusick return; 29138460Smckusick } 29239681Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 29339681Smckusick if (hp && fnd_mnt(hp->h_name, dirpath)) { 29439681Smckusick ml.ml_host[0] = '\0'; 29539681Smckusick write(mlfile, (caddr_t)&ml, sizeof(ml)); 29638460Smckusick } 29738460Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 29838460Smckusick syslog(LOG_ERR, "Can't send reply"); 29938460Smckusick return; 30038460Smckusick case RPCMNT_UMNTALL: 30139681Smckusick if (uid != 0) { 30239681Smckusick svcerr_weakauth(transp); 30339681Smckusick return; 30439681Smckusick } 30539681Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 30639681Smckusick if (hp) { 30739681Smckusick lseek(mlfile, (off_t)0, L_SET); 30839681Smckusick while (read(mlfile, (caddr_t)&ml, sizeof(ml)) == 30939681Smckusick sizeof(ml)) { 31039681Smckusick if (!strcmp(hp->h_name, ml.ml_host)) { 31139681Smckusick lseek(mlfile, (off_t)-sizeof(ml), 31239681Smckusick L_INCR); 31339681Smckusick ml.ml_host[0] = '\0'; 31439681Smckusick write(mlfile, (caddr_t)&ml, sizeof(ml)); 31539681Smckusick } 31638460Smckusick } 31738460Smckusick } 31838460Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 31938460Smckusick syslog(LOG_ERR, "Can't send reply"); 32038460Smckusick return; 32138460Smckusick case RPCMNT_EXPORT: 32238460Smckusick if (!svc_sendreply(transp, xdr_explist, (caddr_t)0)) 32338460Smckusick syslog(LOG_ERR, "Can't send reply"); 32438460Smckusick return; 32538460Smckusick default: 32638460Smckusick svcerr_noproc(transp); 32738460Smckusick return; 32838460Smckusick } 32938460Smckusick } 33038460Smckusick 33138460Smckusick /* 33238460Smckusick * Xdr conversion for a dirpath string 33338460Smckusick */ 33438460Smckusick xdr_dir(xdrsp, dirp) 33538460Smckusick XDR *xdrsp; 33638460Smckusick char *dirp; 33738460Smckusick { 33838460Smckusick return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 33938460Smckusick } 34038460Smckusick 34138460Smckusick /* 34238460Smckusick * Xdr routine to generate fhstatus 34338460Smckusick */ 34438460Smckusick xdr_fhs(xdrsp, nfh) 34538460Smckusick XDR *xdrsp; 34638460Smckusick nfsv2fh_t *nfh; 34738460Smckusick { 34838460Smckusick int ok = 0; 34938460Smckusick 35038460Smckusick if (!xdr_long(xdrsp, &ok)) 35138460Smckusick return (0); 35238460Smckusick return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH)); 35338460Smckusick } 35438460Smckusick 35538460Smckusick xdr_mlist(xdrsp, cp) 35638460Smckusick XDR *xdrsp; 35738460Smckusick caddr_t cp; 35838460Smckusick { 35939681Smckusick struct mountlist ml; 36038460Smckusick int true = 1; 36138460Smckusick int false = 0; 36238460Smckusick char *strp; 36338460Smckusick 36439681Smckusick lseek(mlfile, (off_t)0, L_SET); 36539681Smckusick while (read(mlfile, (caddr_t)&ml, sizeof(ml)) == sizeof(ml)) { 36639681Smckusick if (ml.ml_host[0] != '\0') { 36739681Smckusick if (!xdr_bool(xdrsp, &true)) 36839681Smckusick return (0); 36939681Smckusick strp = &ml.ml_host[0]; 37039681Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 37139681Smckusick return (0); 37239681Smckusick strp = &ml.ml_dirp[0]; 37339681Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 37439681Smckusick return (0); 37539681Smckusick } 37638460Smckusick } 37738460Smckusick if (!xdr_bool(xdrsp, &false)) 37838460Smckusick return (0); 37938460Smckusick return (1); 38038460Smckusick } 38138460Smckusick 38238460Smckusick /* 38338460Smckusick * Xdr conversion for export list 38438460Smckusick */ 38538460Smckusick xdr_explist(xdrsp, cp) 38638460Smckusick XDR *xdrsp; 38738460Smckusick caddr_t cp; 38838460Smckusick { 38938460Smckusick register struct exportlist *ep; 39038460Smckusick register struct grouplist *grp; 39138460Smckusick int true = 1; 39238460Smckusick int false = 0; 39338460Smckusick char *strp; 39438460Smckusick int omask; 39538460Smckusick 39638460Smckusick omask = sigblock(sigmask(SIGHUP)); 39738460Smckusick ep = exphead.ex_next; 39838460Smckusick while (ep != NULL) { 39938460Smckusick if (!xdr_bool(xdrsp, &true)) 40038460Smckusick goto errout; 40138460Smckusick strp = &ep->ex_dirp[0]; 40238460Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 40338460Smckusick goto errout; 40438460Smckusick grp = ep->ex_groups; 40538460Smckusick while (grp != NULL) { 40638460Smckusick if (!xdr_bool(xdrsp, &true)) 40738460Smckusick goto errout; 40839681Smckusick strp = grp->gr_hp->h_name; 40938460Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 41038460Smckusick goto errout; 41138460Smckusick grp = grp->gr_next; 41238460Smckusick } 41338460Smckusick if (!xdr_bool(xdrsp, &false)) 41438460Smckusick goto errout; 41538460Smckusick ep = ep->ex_next; 41638460Smckusick } 41738460Smckusick sigsetmask(omask); 41838460Smckusick if (!xdr_bool(xdrsp, &false)) 41938460Smckusick return (0); 42038460Smckusick return (1); 42138460Smckusick errout: 42238460Smckusick sigsetmask(omask); 42338460Smckusick return (0); 42438460Smckusick } 42538460Smckusick 42638460Smckusick #define LINESIZ 10240 42738460Smckusick char line[LINESIZ]; 42838460Smckusick 42938460Smckusick /* 43038460Smckusick * Get the export list 43138460Smckusick */ 43238460Smckusick get_exportlist() 43338460Smckusick { 43439681Smckusick register struct hostent *hp, *nhp; 43539681Smckusick register char **addrp, **naddrp; 43639681Smckusick register int i; 43739681Smckusick register struct grouplist *grp, *grp2; 43838460Smckusick register struct exportlist *ep, *ep2; 43940368Smckusick struct ufs_args args; 44038460Smckusick FILE *inf; 44138460Smckusick char *cp, *endcp; 44239681Smckusick char savedc; 44338460Smckusick int len; 44438460Smckusick int rootuid, exflags; 44538460Smckusick 44638460Smckusick /* 44738460Smckusick * First, get rid of the old list 44838460Smckusick */ 44938460Smckusick ep = exphead.ex_next; 45038460Smckusick while (ep != NULL) { 45138460Smckusick grp = ep->ex_groups; 45238460Smckusick while (grp != NULL) { 45339681Smckusick addrp = grp->gr_hp->h_addr_list; 45439681Smckusick while (*addrp) 45539681Smckusick free(*addrp++); 45639681Smckusick free((caddr_t)grp->gr_hp->h_addr_list); 45739681Smckusick free(grp->gr_hp->h_name); 45839681Smckusick free((caddr_t)grp->gr_hp); 45938460Smckusick grp2 = grp; 46038460Smckusick grp = grp->gr_next; 46138460Smckusick free((caddr_t)grp2); 46238460Smckusick } 46338460Smckusick ep2 = ep; 46438460Smckusick ep = ep->ex_next; 46538460Smckusick free((caddr_t)ep2); 46638460Smckusick } 46738460Smckusick 46838460Smckusick /* 46938460Smckusick * Read in the exports file and build the list, calling 47038460Smckusick * exportfs() as we go along 47138460Smckusick */ 47238460Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 47338460Smckusick if ((inf = fopen(exname, "r")) == NULL) { 47438460Smckusick syslog(LOG_ERR, "Can't open %s", exname); 47538460Smckusick exit(2); 47638460Smckusick } 47738460Smckusick while (fgets(line, LINESIZ, inf)) { 47841404Smckusick exflags = MNT_EXPORTED; 47938460Smckusick rootuid = def_rootuid; 48038460Smckusick cp = line; 48138460Smckusick nextfield(&cp, &endcp); 48238460Smckusick len = endcp-cp; 48338460Smckusick if (len <= RPCMNT_PATHLEN && len > 0) { 48438460Smckusick ep = (struct exportlist *)malloc(sizeof(*ep)); 48538460Smckusick ep->ex_next = ep->ex_prev = (struct exportlist *)0; 48638460Smckusick ep->ex_groups = (struct grouplist *)0; 48738460Smckusick bcopy(cp, ep->ex_dirp, len); 48838460Smckusick ep->ex_dirp[len] = '\0'; 48938460Smckusick } else 49038460Smckusick goto err; 49138460Smckusick cp = endcp; 49238460Smckusick nextfield(&cp, &endcp); 49338460Smckusick len = endcp-cp; 49438460Smckusick while (len > 0) { 49539681Smckusick savedc = *endcp; 49639681Smckusick *endcp = '\0'; 49738460Smckusick if (len <= RPCMNT_NAMELEN) { 49838460Smckusick if (*cp == '-') { 49938460Smckusick cp++; 50038460Smckusick switch (*cp) { 50138460Smckusick case 'o': 50241404Smckusick exflags |= MNT_EXRDONLY; 50338460Smckusick break; 50438460Smckusick case 'r': 50538460Smckusick if (*++cp == '=') 50638460Smckusick rootuid = atoi(++cp); 50738460Smckusick break; 50838460Smckusick default: 50938460Smckusick syslog(LOG_WARNING, 51038460Smckusick "Bad -%c option in %s", 51138460Smckusick *cp, exname); 51238460Smckusick break; 51338460Smckusick }; 51439681Smckusick } else if (hp = gethostbyname(cp)) { 51539681Smckusick grp = (struct grouplist *) 51639681Smckusick malloc(sizeof(struct grouplist)); 51738460Smckusick if (grp == NULL) 51838460Smckusick goto err; 51939681Smckusick nhp = grp->gr_hp = (struct hostent *) 52039681Smckusick malloc(sizeof(struct hostent)); 52139681Smckusick if (nhp == NULL) 52239681Smckusick goto err; 52339681Smckusick bcopy((caddr_t)hp, (caddr_t)nhp, 52439681Smckusick sizeof(struct hostent)); 52539681Smckusick i = strlen(hp->h_name)+1; 52639681Smckusick nhp->h_name = (char *)malloc(i); 52739681Smckusick if (nhp->h_name == NULL) 52839681Smckusick goto err; 52939681Smckusick bcopy(hp->h_name, nhp->h_name, i); 53039681Smckusick addrp = hp->h_addr_list; 53139681Smckusick i = 1; 53239681Smckusick while (*addrp++) 53339681Smckusick i++; 53439681Smckusick naddrp = nhp->h_addr_list = (char **) 53539681Smckusick malloc(i*sizeof(char *)); 53639681Smckusick if (naddrp == NULL) 53739681Smckusick goto err; 53839681Smckusick addrp = hp->h_addr_list; 53939681Smckusick while (*addrp) { 54039681Smckusick *naddrp = (char *) 54139681Smckusick malloc(hp->h_length); 54239681Smckusick bcopy(*addrp, *naddrp, 54339681Smckusick hp->h_length); 54439681Smckusick addrp++; 54539681Smckusick naddrp++; 54639681Smckusick } 54739681Smckusick *naddrp = (char *)0; 54838460Smckusick grp->gr_next = ep->ex_groups; 54938460Smckusick ep->ex_groups = grp; 55038460Smckusick } 55138460Smckusick } 55238460Smckusick cp = endcp; 55339681Smckusick *cp = savedc; 55438460Smckusick nextfield(&cp, &endcp); 55538460Smckusick len = endcp-cp; 55638460Smckusick } 55740368Smckusick args.fspec = 0; 55840368Smckusick args.exflags = exflags; 55940368Smckusick args.exroot = rootuid; 56041404Smckusick if (mount(MOUNT_UFS, ep->ex_dirp, MNT_UPDATE, &args) < 0) { 56138460Smckusick syslog(LOG_WARNING, "Can't export %s", ep->ex_dirp); 56238460Smckusick free((caddr_t)ep); 56338460Smckusick } else { 56438460Smckusick ep->ex_rootuid = rootuid; 56538460Smckusick ep->ex_exflags = exflags; 56638460Smckusick ep->ex_next = exphead.ex_next; 56738460Smckusick ep->ex_prev = &exphead; 56838460Smckusick if (ep->ex_next != NULL) 56938460Smckusick ep->ex_next->ex_prev = ep; 57038460Smckusick exphead.ex_next = ep; 57138460Smckusick } 57238460Smckusick } 57338460Smckusick fclose(inf); 57438460Smckusick return; 57538460Smckusick err: 57639681Smckusick syslog(LOG_ERR, "Bad Exports File, mountd Failed"); 57738460Smckusick exit(2); 57838460Smckusick } 57938460Smckusick 58038460Smckusick /* 58138460Smckusick * Parse out the next white space separated field 58238460Smckusick */ 58338460Smckusick nextfield(cp, endcp) 58438460Smckusick char **cp; 58538460Smckusick char **endcp; 58638460Smckusick { 58738460Smckusick register char *p; 58838460Smckusick 58938460Smckusick p = *cp; 59038460Smckusick while (*p == ' ' || *p == '\t') 59138460Smckusick p++; 59238460Smckusick if (*p == '\n' || *p == '\0') { 59338460Smckusick *cp = *endcp = p; 59438460Smckusick return; 59538460Smckusick } 59638460Smckusick *cp = p++; 59738460Smckusick while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 59838460Smckusick p++; 59938460Smckusick *endcp = p; 60038460Smckusick } 60139681Smckusick 60239681Smckusick /* 60339681Smckusick * Search the remote mounts file for a match. 60439681Smckusick * Iff found 60539681Smckusick * - set file offset to record and return TRUE 60639681Smckusick * else 60739681Smckusick * - set file offset to an unused record if found or eof otherwise 60839681Smckusick * and return FALSE 60939681Smckusick */ 61039681Smckusick fnd_mnt(host, dirp) 61139681Smckusick char *host; 61239681Smckusick char *dirp; 61339681Smckusick { 61439681Smckusick struct mountlist ml; 61539681Smckusick off_t off, pos; 61639681Smckusick 61739681Smckusick off = -1; 61839681Smckusick pos = 0; 61939681Smckusick lseek(mlfile, (off_t)0, L_SET); 62039681Smckusick while (read(mlfile, (caddr_t)&ml, sizeof(ml)) == sizeof(ml)) { 62139681Smckusick if (!strcmp(host, ml.ml_host) && !strcmp(dirp, ml.ml_dirp)) { 62239681Smckusick lseek(mlfile, (off_t)-sizeof(ml), L_INCR); 62339681Smckusick return (TRUE); 62439681Smckusick } else if (ml.ml_host[0] == '\0') { 62539681Smckusick off = pos; 62639681Smckusick } 62739681Smckusick pos += sizeof(ml); 62839681Smckusick } 62939681Smckusick if (off != -1) 63039681Smckusick lseek(mlfile, off, L_SET); 63139681Smckusick else 63239681Smckusick lseek(mlfile, (off_t)0, L_XTND); 63339681Smckusick return (FALSE); 63439681Smckusick } 635