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*39681Smckusick static char sccsid[] = "@(#)mountd.c 5.2 (Berkeley) 11/30/89"; 2938460Smckusick #endif not lint 3038460Smckusick 3138460Smckusick #include <stdio.h> 3238460Smckusick #include <strings.h> 3338460Smckusick #include <syslog.h> 3438460Smckusick #include <signal.h> 3538460Smckusick #include <fcntl.h> 3638460Smckusick #include <sys/param.h> 3738460Smckusick #include <sys/types.h> 3838460Smckusick #include <sys/ioctl.h> 3938460Smckusick #include <sys/stat.h> 40*39681Smckusick #include <sys/file.h> 4138460Smckusick #include <sys/dir.h> 4238460Smckusick #include <sys/uio.h> 4338460Smckusick #include <sys/namei.h> 4438460Smckusick #include <sys/mount.h> 4538460Smckusick #include <sys/socket.h> 4638460Smckusick #include <sys/socketvar.h> 4738460Smckusick #include <sys/errno.h> 4838460Smckusick #include <netdb.h> 4938460Smckusick #include <rpc/rpc.h> 5038460Smckusick #include <rpc/pmap_clnt.h> 5138460Smckusick #include <rpc/pmap_prot.h> 5238460Smckusick #include <nfs/rpcv2.h> 5338460Smckusick #include <nfs/nfsv2.h> 54*39681Smckusick #include "pathnames.h" 5538460Smckusick 5638460Smckusick struct ufid { 5738460Smckusick u_short ufid_len; 5838460Smckusick ino_t ufid_ino; 5938460Smckusick long ufid_gen; 6038460Smckusick }; 6138460Smckusick /* 6238460Smckusick * Structures for keeping the mount list and export list 6338460Smckusick */ 6438460Smckusick struct mountlist { 6538460Smckusick char ml_host[RPCMNT_NAMELEN+1]; 6638460Smckusick char ml_dirp[RPCMNT_PATHLEN+1]; 6738460Smckusick }; 6838460Smckusick 6938460Smckusick struct exportlist { 7038460Smckusick struct exportlist *ex_next; 7138460Smckusick struct exportlist *ex_prev; 7238460Smckusick struct grouplist *ex_groups; 7338460Smckusick int ex_rootuid; 7438460Smckusick int ex_exflags; 7538460Smckusick char ex_dirp[RPCMNT_PATHLEN+1]; 7638460Smckusick }; 7738460Smckusick 7838460Smckusick struct grouplist { 7938460Smckusick struct grouplist *gr_next; 80*39681Smckusick struct hostent *gr_hp; 8138460Smckusick }; 8238460Smckusick 8338460Smckusick /* Global defs */ 8438460Smckusick int xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist(); 8538460Smckusick int mntsrv(), get_exportlist(); 8638460Smckusick struct exportlist exphead; 87*39681Smckusick int mlfile; 8838460Smckusick char exname[MAXPATHLEN]; 8938460Smckusick int def_rootuid = -2; 9038460Smckusick extern int errno; 9138460Smckusick #ifdef DEBUG 9238460Smckusick int debug = 1; 9338460Smckusick #else 9438460Smckusick int debug = 0; 9538460Smckusick #endif 9638460Smckusick 9738460Smckusick /* 9838460Smckusick * Mountd server for NFS mount protocol as described in: 99*39681Smckusick * NFS: Network File System Protocol Specification, RFC1094, Appendix A 10038460Smckusick * The optional argument is the exports file name 101*39681Smckusick * default: _PATH_EXPORTS 10238460Smckusick */ 10338460Smckusick main(argc, argv) 10438460Smckusick int argc; 10538460Smckusick char *argv[]; 10638460Smckusick { 10738460Smckusick SVCXPRT *transp; 10838460Smckusick 10938460Smckusick if (debug == 0) { 11038460Smckusick if (fork()) 11138460Smckusick exit(0); 11238460Smckusick { int s; 11338460Smckusick for (s = 0; s < 10; s++) 11438460Smckusick (void) close(s); 11538460Smckusick } 11638460Smckusick (void) open("/", O_RDONLY); 11738460Smckusick (void) dup2(0, 1); 11838460Smckusick (void) dup2(0, 2); 11938460Smckusick { int tt = open("/dev/tty", O_RDWR); 12038460Smckusick if (tt > 0) { 12138460Smckusick ioctl(tt, TIOCNOTTY, (char *)0); 12238460Smckusick close(tt); 12338460Smckusick } 12438460Smckusick } 12538460Smckusick (void) setpgrp(0, 0); 12638460Smckusick signal(SIGTSTP, SIG_IGN); 12738460Smckusick signal(SIGTTIN, SIG_IGN); 12838460Smckusick signal(SIGTTOU, SIG_IGN); 12938460Smckusick signal(SIGINT, SIG_IGN); 13038460Smckusick signal(SIGQUIT, SIG_IGN); 13138460Smckusick signal(SIGTERM, SIG_IGN); 13238460Smckusick } 13338460Smckusick openlog("mountd:", LOG_PID, LOG_DAEMON); 13438460Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 13538460Smckusick if (argc == 2) { 13638460Smckusick strncpy(exname, argv[1], MAXPATHLEN-1); 13738460Smckusick exname[MAXPATHLEN-1] = '\0'; 13838460Smckusick } else 139*39681Smckusick strcpy(exname, _PATH_EXPORTS); 14038460Smckusick get_exportlist(); 14138460Smckusick signal(SIGHUP, get_exportlist); 142*39681Smckusick if ((mlfile = open(_PATH_RMOUNTLIST, (O_RDWR|O_CREAT), 0600)) < 0) { 143*39681Smckusick syslog(LOG_ERR, "Can't open mountlist file"); 144*39681Smckusick exit(1); 145*39681Smckusick } 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 { 166*39681Smckusick register struct grouplist *grp; 167*39681Smckusick register u_long **addrp; 16838460Smckusick register struct exportlist *ep; 169*39681Smckusick struct mountlist ml; 17038460Smckusick nfsv2fh_t nfh; 17138460Smckusick struct authunix_parms *ucr; 17238460Smckusick struct stat stb; 17338460Smckusick struct hostent *hp; 174*39681Smckusick u_long saddr; 17538460Smckusick char dirpath[RPCMNT_PATHLEN+1]; 17638460Smckusick int ok = 0; 17738460Smckusick int bad = ENOENT; 17838460Smckusick int omask; 179*39681Smckusick 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; 185*39681Smckusick uid = ucr->aup_uid; 186*39681Smckusick break; 18738460Smckusick case AUTH_NULL: 18838460Smckusick default: 189*39681Smckusick break; 19038460Smckusick } 19138460Smckusick 192*39681Smckusick saddr = transp->xp_raddr.sin_addr.s_addr; 193*39681Smckusick hp = (struct hostent *)0; 19438460Smckusick switch (rqstp->rq_proc) { 195*39681Smckusick case NULLPROC: 196*39681Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 197*39681Smckusick syslog(LOG_ERR, "Can't send reply"); 198*39681Smckusick return; 19938460Smckusick case RPCMNT_MOUNT: 200*39681Smckusick if (uid != 0) { 201*39681Smckusick svcerr_weakauth(transp); 202*39681Smckusick return; 203*39681Smckusick } 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; 225*39681Smckusick 226*39681Smckusick /* Check for a host match */ 227*39681Smckusick addrp = (u_long **)grp->gr_hp->h_addr_list; 228*39681Smckusick for (;;) { 229*39681Smckusick if (**addrp == saddr) 23038460Smckusick break; 231*39681Smckusick if (*++addrp == NULL) 232*39681Smckusick if (grp = grp->gr_next) { 233*39681Smckusick addrp = (u_long **) 234*39681Smckusick grp->gr_hp->h_addr_list; 235*39681Smckusick } else { 236*39681Smckusick bad = EACCES; 237*39681Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 238*39681Smckusick syslog(LOG_ERR, "Can't send reply"); 239*39681Smckusick sigsetmask(omask); 240*39681Smckusick return; 241*39681Smckusick } 24238460Smckusick } 243*39681Smckusick hp = grp->gr_hp; 244*39681Smckusick 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 } 264*39681Smckusick #ifdef notnow 265*39681Smckusick nfh.fh_generic.fh_fid.fid_gen = htonl(nfh.fh_generic.fh_fid.fid_gen); 266*39681Smckusick #endif 26738460Smckusick if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh)) 26838460Smckusick syslog(LOG_ERR, "Can't send reply"); 269*39681Smckusick if (hp == NULL) 270*39681Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 271*39681Smckusick if (hp) { 272*39681Smckusick if (!fnd_mnt(hp->h_name, dirpath)) { 273*39681Smckusick strcpy(ml.ml_host, hp->h_name); 274*39681Smckusick strcpy(ml.ml_dirp, dirpath); 275*39681Smckusick write(mlfile, (caddr_t)&ml, sizeof(ml)); 276*39681Smckusick } 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: 284*39681Smckusick if (uid != 0) { 285*39681Smckusick svcerr_weakauth(transp); 286*39681Smckusick return; 287*39681Smckusick } 28838460Smckusick if (!svc_getargs(transp, xdr_dir, dirpath)) { 28938460Smckusick svcerr_decode(transp); 29038460Smckusick return; 29138460Smckusick } 292*39681Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 293*39681Smckusick if (hp && fnd_mnt(hp->h_name, dirpath)) { 294*39681Smckusick ml.ml_host[0] = '\0'; 295*39681Smckusick 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: 301*39681Smckusick if (uid != 0) { 302*39681Smckusick svcerr_weakauth(transp); 303*39681Smckusick return; 304*39681Smckusick } 305*39681Smckusick hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET); 306*39681Smckusick if (hp) { 307*39681Smckusick lseek(mlfile, (off_t)0, L_SET); 308*39681Smckusick while (read(mlfile, (caddr_t)&ml, sizeof(ml)) == 309*39681Smckusick sizeof(ml)) { 310*39681Smckusick if (!strcmp(hp->h_name, ml.ml_host)) { 311*39681Smckusick lseek(mlfile, (off_t)-sizeof(ml), 312*39681Smckusick L_INCR); 313*39681Smckusick ml.ml_host[0] = '\0'; 314*39681Smckusick write(mlfile, (caddr_t)&ml, sizeof(ml)); 315*39681Smckusick } 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 { 359*39681Smckusick struct mountlist ml; 36038460Smckusick int true = 1; 36138460Smckusick int false = 0; 36238460Smckusick char *strp; 36338460Smckusick 364*39681Smckusick lseek(mlfile, (off_t)0, L_SET); 365*39681Smckusick while (read(mlfile, (caddr_t)&ml, sizeof(ml)) == sizeof(ml)) { 366*39681Smckusick if (ml.ml_host[0] != '\0') { 367*39681Smckusick if (!xdr_bool(xdrsp, &true)) 368*39681Smckusick return (0); 369*39681Smckusick strp = &ml.ml_host[0]; 370*39681Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 371*39681Smckusick return (0); 372*39681Smckusick strp = &ml.ml_dirp[0]; 373*39681Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 374*39681Smckusick return (0); 375*39681Smckusick } 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; 408*39681Smckusick 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 { 434*39681Smckusick register struct hostent *hp, *nhp; 435*39681Smckusick register char **addrp, **naddrp; 436*39681Smckusick register int i; 437*39681Smckusick register struct grouplist *grp, *grp2; 43838460Smckusick register struct exportlist *ep, *ep2; 43938460Smckusick FILE *inf; 44038460Smckusick char *cp, *endcp; 441*39681Smckusick char savedc; 44238460Smckusick int len; 44338460Smckusick int rootuid, exflags; 44438460Smckusick 44538460Smckusick /* 44638460Smckusick * First, get rid of the old list 44738460Smckusick */ 44838460Smckusick ep = exphead.ex_next; 44938460Smckusick while (ep != NULL) { 45038460Smckusick grp = ep->ex_groups; 45138460Smckusick while (grp != NULL) { 452*39681Smckusick addrp = grp->gr_hp->h_addr_list; 453*39681Smckusick while (*addrp) 454*39681Smckusick free(*addrp++); 455*39681Smckusick free((caddr_t)grp->gr_hp->h_addr_list); 456*39681Smckusick free(grp->gr_hp->h_name); 457*39681Smckusick free((caddr_t)grp->gr_hp); 45838460Smckusick grp2 = grp; 45938460Smckusick grp = grp->gr_next; 46038460Smckusick free((caddr_t)grp2); 46138460Smckusick } 46238460Smckusick ep2 = ep; 46338460Smckusick ep = ep->ex_next; 46438460Smckusick free((caddr_t)ep2); 46538460Smckusick } 46638460Smckusick 46738460Smckusick /* 46838460Smckusick * Read in the exports file and build the list, calling 46938460Smckusick * exportfs() as we go along 47038460Smckusick */ 47138460Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 47238460Smckusick if ((inf = fopen(exname, "r")) == NULL) { 47338460Smckusick syslog(LOG_ERR, "Can't open %s", exname); 47438460Smckusick exit(2); 47538460Smckusick } 47638460Smckusick while (fgets(line, LINESIZ, inf)) { 47738460Smckusick exflags = 0; 47838460Smckusick rootuid = def_rootuid; 47938460Smckusick cp = line; 48038460Smckusick nextfield(&cp, &endcp); 48138460Smckusick len = endcp-cp; 48238460Smckusick if (len <= RPCMNT_PATHLEN && len > 0) { 48338460Smckusick ep = (struct exportlist *)malloc(sizeof(*ep)); 48438460Smckusick ep->ex_next = ep->ex_prev = (struct exportlist *)0; 48538460Smckusick ep->ex_groups = (struct grouplist *)0; 48638460Smckusick bcopy(cp, ep->ex_dirp, len); 48738460Smckusick ep->ex_dirp[len] = '\0'; 48838460Smckusick } else 48938460Smckusick goto err; 49038460Smckusick cp = endcp; 49138460Smckusick nextfield(&cp, &endcp); 49238460Smckusick len = endcp-cp; 49338460Smckusick while (len > 0) { 494*39681Smckusick savedc = *endcp; 495*39681Smckusick *endcp = '\0'; 49638460Smckusick if (len <= RPCMNT_NAMELEN) { 49738460Smckusick if (*cp == '-') { 49838460Smckusick cp++; 49938460Smckusick switch (*cp) { 50038460Smckusick case 'o': 50138460Smckusick exflags |= M_EXRDONLY; 50238460Smckusick break; 50338460Smckusick case 'r': 50438460Smckusick if (*++cp == '=') 50538460Smckusick rootuid = atoi(++cp); 50638460Smckusick break; 50738460Smckusick default: 50838460Smckusick syslog(LOG_WARNING, 50938460Smckusick "Bad -%c option in %s", 51038460Smckusick *cp, exname); 51138460Smckusick break; 51238460Smckusick }; 513*39681Smckusick } else if (hp = gethostbyname(cp)) { 514*39681Smckusick grp = (struct grouplist *) 515*39681Smckusick malloc(sizeof(struct grouplist)); 51638460Smckusick if (grp == NULL) 51738460Smckusick goto err; 518*39681Smckusick nhp = grp->gr_hp = (struct hostent *) 519*39681Smckusick malloc(sizeof(struct hostent)); 520*39681Smckusick if (nhp == NULL) 521*39681Smckusick goto err; 522*39681Smckusick bcopy((caddr_t)hp, (caddr_t)nhp, 523*39681Smckusick sizeof(struct hostent)); 524*39681Smckusick i = strlen(hp->h_name)+1; 525*39681Smckusick nhp->h_name = (char *)malloc(i); 526*39681Smckusick if (nhp->h_name == NULL) 527*39681Smckusick goto err; 528*39681Smckusick bcopy(hp->h_name, nhp->h_name, i); 529*39681Smckusick addrp = hp->h_addr_list; 530*39681Smckusick i = 1; 531*39681Smckusick while (*addrp++) 532*39681Smckusick i++; 533*39681Smckusick naddrp = nhp->h_addr_list = (char **) 534*39681Smckusick malloc(i*sizeof(char *)); 535*39681Smckusick if (naddrp == NULL) 536*39681Smckusick goto err; 537*39681Smckusick addrp = hp->h_addr_list; 538*39681Smckusick while (*addrp) { 539*39681Smckusick *naddrp = (char *) 540*39681Smckusick malloc(hp->h_length); 541*39681Smckusick bcopy(*addrp, *naddrp, 542*39681Smckusick hp->h_length); 543*39681Smckusick addrp++; 544*39681Smckusick naddrp++; 545*39681Smckusick } 546*39681Smckusick *naddrp = (char *)0; 54738460Smckusick grp->gr_next = ep->ex_groups; 54838460Smckusick ep->ex_groups = grp; 54938460Smckusick } 55038460Smckusick } 55138460Smckusick cp = endcp; 552*39681Smckusick *cp = savedc; 55338460Smckusick nextfield(&cp, &endcp); 55438460Smckusick len = endcp-cp; 55538460Smckusick } 55638460Smckusick if (exportfs(ep->ex_dirp, rootuid, exflags) < 0) { 55738460Smckusick syslog(LOG_WARNING, "Can't export %s", ep->ex_dirp); 55838460Smckusick free((caddr_t)ep); 55938460Smckusick } else { 56038460Smckusick ep->ex_rootuid = rootuid; 56138460Smckusick ep->ex_exflags = exflags; 56238460Smckusick ep->ex_next = exphead.ex_next; 56338460Smckusick ep->ex_prev = &exphead; 56438460Smckusick if (ep->ex_next != NULL) 56538460Smckusick ep->ex_next->ex_prev = ep; 56638460Smckusick exphead.ex_next = ep; 56738460Smckusick } 56838460Smckusick } 56938460Smckusick fclose(inf); 57038460Smckusick return; 57138460Smckusick err: 572*39681Smckusick syslog(LOG_ERR, "Bad Exports File, mountd Failed"); 57338460Smckusick exit(2); 57438460Smckusick } 57538460Smckusick 57638460Smckusick /* 57738460Smckusick * Parse out the next white space separated field 57838460Smckusick */ 57938460Smckusick nextfield(cp, endcp) 58038460Smckusick char **cp; 58138460Smckusick char **endcp; 58238460Smckusick { 58338460Smckusick register char *p; 58438460Smckusick 58538460Smckusick p = *cp; 58638460Smckusick while (*p == ' ' || *p == '\t') 58738460Smckusick p++; 58838460Smckusick if (*p == '\n' || *p == '\0') { 58938460Smckusick *cp = *endcp = p; 59038460Smckusick return; 59138460Smckusick } 59238460Smckusick *cp = p++; 59338460Smckusick while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 59438460Smckusick p++; 59538460Smckusick *endcp = p; 59638460Smckusick } 597*39681Smckusick 598*39681Smckusick /* 599*39681Smckusick * Search the remote mounts file for a match. 600*39681Smckusick * Iff found 601*39681Smckusick * - set file offset to record and return TRUE 602*39681Smckusick * else 603*39681Smckusick * - set file offset to an unused record if found or eof otherwise 604*39681Smckusick * and return FALSE 605*39681Smckusick */ 606*39681Smckusick fnd_mnt(host, dirp) 607*39681Smckusick char *host; 608*39681Smckusick char *dirp; 609*39681Smckusick { 610*39681Smckusick struct mountlist ml; 611*39681Smckusick off_t off, pos; 612*39681Smckusick 613*39681Smckusick off = -1; 614*39681Smckusick pos = 0; 615*39681Smckusick lseek(mlfile, (off_t)0, L_SET); 616*39681Smckusick while (read(mlfile, (caddr_t)&ml, sizeof(ml)) == sizeof(ml)) { 617*39681Smckusick if (!strcmp(host, ml.ml_host) && !strcmp(dirp, ml.ml_dirp)) { 618*39681Smckusick lseek(mlfile, (off_t)-sizeof(ml), L_INCR); 619*39681Smckusick return (TRUE); 620*39681Smckusick } else if (ml.ml_host[0] == '\0') { 621*39681Smckusick off = pos; 622*39681Smckusick } 623*39681Smckusick pos += sizeof(ml); 624*39681Smckusick } 625*39681Smckusick if (off != -1) 626*39681Smckusick lseek(mlfile, off, L_SET); 627*39681Smckusick else 628*39681Smckusick lseek(mlfile, (off_t)0, L_XTND); 629*39681Smckusick return (FALSE); 630*39681Smckusick } 631