1*38460Smckusick /* 2*38460Smckusick * Copyright (c) 1989 The Regents of the University of California. 3*38460Smckusick * All rights reserved. 4*38460Smckusick * 5*38460Smckusick * This code is derived from software contributed to Berkeley by 6*38460Smckusick * Rick Macklem at The University of Guelph. 7*38460Smckusick * 8*38460Smckusick * Redistribution and use in source and binary forms are permitted 9*38460Smckusick * provided that the above copyright notice and this paragraph are 10*38460Smckusick * duplicated in all such forms and that any documentation, 11*38460Smckusick * advertising materials, and other materials related to such 12*38460Smckusick * distribution and use acknowledge that the software was developed 13*38460Smckusick * by the University of California, Berkeley. The name of the 14*38460Smckusick * University may not be used to endorse or promote products derived 15*38460Smckusick * from this software without specific prior written permission. 16*38460Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17*38460Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18*38460Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19*38460Smckusick */ 20*38460Smckusick 21*38460Smckusick #ifndef lint 22*38460Smckusick char copyright[] = 23*38460Smckusick "@(#) Copyright (c) 1989 Regents of the University of California.\n\ 24*38460Smckusick All rights reserved.\n"; 25*38460Smckusick #endif not lint 26*38460Smckusick 27*38460Smckusick #ifndef lint 28*38460Smckusick static char sccsid[] = "@(#)mountd.c 5.1 (Berkeley) 07/16/89"; 29*38460Smckusick #endif not lint 30*38460Smckusick 31*38460Smckusick #include <stdio.h> 32*38460Smckusick #include <strings.h> 33*38460Smckusick #include <syslog.h> 34*38460Smckusick #include <signal.h> 35*38460Smckusick #include <fcntl.h> 36*38460Smckusick #include <sys/param.h> 37*38460Smckusick #include <sys/types.h> 38*38460Smckusick #include <sys/ioctl.h> 39*38460Smckusick #include <sys/stat.h> 40*38460Smckusick #include <sys/dir.h> 41*38460Smckusick #include <sys/uio.h> 42*38460Smckusick #include <sys/namei.h> 43*38460Smckusick #include <sys/mount.h> 44*38460Smckusick #include <sys/socket.h> 45*38460Smckusick #include <sys/socketvar.h> 46*38460Smckusick #include <sys/errno.h> 47*38460Smckusick #include <netdb.h> 48*38460Smckusick #include <rpc/rpc.h> 49*38460Smckusick #include <rpc/pmap_clnt.h> 50*38460Smckusick #include <rpc/pmap_prot.h> 51*38460Smckusick #include <nfs/rpcv2.h> 52*38460Smckusick #include <nfs/nfsv2.h> 53*38460Smckusick 54*38460Smckusick struct ufid { 55*38460Smckusick u_short ufid_len; 56*38460Smckusick ino_t ufid_ino; 57*38460Smckusick long ufid_gen; 58*38460Smckusick }; 59*38460Smckusick /* 60*38460Smckusick * Structures for keeping the mount list and export list 61*38460Smckusick */ 62*38460Smckusick struct mountlist { 63*38460Smckusick struct mountlist *ml_next; 64*38460Smckusick struct mountlist *ml_prev; 65*38460Smckusick char ml_host[RPCMNT_NAMELEN+1]; 66*38460Smckusick char ml_dirp[RPCMNT_PATHLEN+1]; 67*38460Smckusick }; 68*38460Smckusick 69*38460Smckusick struct exportlist { 70*38460Smckusick struct exportlist *ex_next; 71*38460Smckusick struct exportlist *ex_prev; 72*38460Smckusick struct grouplist *ex_groups; 73*38460Smckusick int ex_rootuid; 74*38460Smckusick int ex_exflags; 75*38460Smckusick char ex_dirp[RPCMNT_PATHLEN+1]; 76*38460Smckusick }; 77*38460Smckusick 78*38460Smckusick struct grouplist { 79*38460Smckusick struct grouplist *gr_next; 80*38460Smckusick char gr_name[RPCMNT_NAMELEN+1]; 81*38460Smckusick }; 82*38460Smckusick 83*38460Smckusick /* Global defs */ 84*38460Smckusick int xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist(); 85*38460Smckusick int mntsrv(), get_exportlist(); 86*38460Smckusick struct exportlist exphead; 87*38460Smckusick struct mountlist mlhead; 88*38460Smckusick char exname[MAXPATHLEN]; 89*38460Smckusick int def_rootuid = -2; 90*38460Smckusick extern int errno; 91*38460Smckusick #ifdef DEBUG 92*38460Smckusick int debug = 1; 93*38460Smckusick #else 94*38460Smckusick int debug = 0; 95*38460Smckusick #endif 96*38460Smckusick 97*38460Smckusick /* 98*38460Smckusick * Mountd server for NFS mount protocol as described in: 99*38460Smckusick * Networking on the Sun Workstation, 100*38460Smckusick * Part #800-1324-03 Rev. B 101*38460Smckusick * Network File System Protocol Specification Chap. 3 102*38460Smckusick * The optional argument is the exports file name 103*38460Smckusick * default: /etc/exports 104*38460Smckusick */ 105*38460Smckusick main(argc, argv) 106*38460Smckusick int argc; 107*38460Smckusick char *argv[]; 108*38460Smckusick { 109*38460Smckusick SVCXPRT *transp; 110*38460Smckusick 111*38460Smckusick if (debug == 0) { 112*38460Smckusick if (fork()) 113*38460Smckusick exit(0); 114*38460Smckusick { int s; 115*38460Smckusick for (s = 0; s < 10; s++) 116*38460Smckusick (void) close(s); 117*38460Smckusick } 118*38460Smckusick (void) open("/", O_RDONLY); 119*38460Smckusick (void) dup2(0, 1); 120*38460Smckusick (void) dup2(0, 2); 121*38460Smckusick { int tt = open("/dev/tty", O_RDWR); 122*38460Smckusick if (tt > 0) { 123*38460Smckusick ioctl(tt, TIOCNOTTY, (char *)0); 124*38460Smckusick close(tt); 125*38460Smckusick } 126*38460Smckusick } 127*38460Smckusick (void) setpgrp(0, 0); 128*38460Smckusick signal(SIGTSTP, SIG_IGN); 129*38460Smckusick signal(SIGTTIN, SIG_IGN); 130*38460Smckusick signal(SIGTTOU, SIG_IGN); 131*38460Smckusick signal(SIGINT, SIG_IGN); 132*38460Smckusick signal(SIGQUIT, SIG_IGN); 133*38460Smckusick signal(SIGTERM, SIG_IGN); 134*38460Smckusick } 135*38460Smckusick openlog("mountd:", LOG_PID, LOG_DAEMON); 136*38460Smckusick mlhead.ml_next = mlhead.ml_prev = (struct mountlist *)0; 137*38460Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 138*38460Smckusick if (argc == 2) { 139*38460Smckusick strncpy(exname, argv[1], MAXPATHLEN-1); 140*38460Smckusick exname[MAXPATHLEN-1] = '\0'; 141*38460Smckusick } else 142*38460Smckusick strcpy(exname, "/etc/exports"); 143*38460Smckusick get_exportlist(); 144*38460Smckusick signal(SIGHUP, get_exportlist); 145*38460Smckusick if ((transp = svcudp_create(RPC_ANYSOCK)) == NULL) { 146*38460Smckusick syslog(LOG_ERR, "Can't create socket"); 147*38460Smckusick exit(1); 148*38460Smckusick } 149*38460Smckusick pmap_unset(RPCPROG_MNT, RPCMNT_VER1); 150*38460Smckusick if (!svc_register(transp, RPCPROG_MNT, RPCMNT_VER1, mntsrv, IPPROTO_UDP)) { 151*38460Smckusick syslog(LOG_ERR, "Can't register mount"); 152*38460Smckusick exit(1); 153*38460Smckusick } 154*38460Smckusick svc_run(); 155*38460Smckusick syslog(LOG_ERR, "Mountd died"); 156*38460Smckusick } 157*38460Smckusick 158*38460Smckusick /* 159*38460Smckusick * The mount rpc service 160*38460Smckusick */ 161*38460Smckusick mntsrv(rqstp, transp) 162*38460Smckusick register struct svc_req *rqstp; 163*38460Smckusick register SVCXPRT *transp; 164*38460Smckusick { 165*38460Smckusick register struct mountlist *mlp; 166*38460Smckusick register struct exportlist *ep; 167*38460Smckusick register struct grouplist *grp; 168*38460Smckusick struct mountlist *mlp2; 169*38460Smckusick nfsv2fh_t nfh; 170*38460Smckusick struct authunix_parms *ucr; 171*38460Smckusick struct stat stb; 172*38460Smckusick struct hostent *hp; 173*38460Smckusick struct sockaddr_in saddr; 174*38460Smckusick char dirpath[RPCMNT_PATHLEN+1]; 175*38460Smckusick int ok = 0; 176*38460Smckusick int bad = ENOENT; 177*38460Smckusick int omask; 178*38460Smckusick 179*38460Smckusick fprintf(stderr,"in mntsrv\n"); 180*38460Smckusick if (rqstp->rq_proc == NULLPROC) { 181*38460Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 182*38460Smckusick syslog(LOG_ERR, "Can't send reply"); 183*38460Smckusick return; 184*38460Smckusick } 185*38460Smckusick 186*38460Smckusick /* Get authorization */ 187*38460Smckusick switch (rqstp->rq_cred.oa_flavor) { 188*38460Smckusick case AUTH_UNIX: 189*38460Smckusick ucr = (struct authunix_parms *)rqstp->rq_clntcred; 190*38460Smckusick if (ucr->aup_uid == 0) 191*38460Smckusick break; 192*38460Smckusick /* Fall thru to */ 193*38460Smckusick fprintf(stderr,"weak auth\n"); 194*38460Smckusick case AUTH_NULL: 195*38460Smckusick default: 196*38460Smckusick svcerr_weakauth(transp); 197*38460Smckusick return; 198*38460Smckusick } 199*38460Smckusick 200*38460Smckusick saddr.sin_family = AF_INET; 201*38460Smckusick saddr.sin_addr.s_addr = ntohl(transp->xp_raddr.sin_addr.s_addr); 202*38460Smckusick saddr.sin_port = 0; 203*38460Smckusick hp = gethostbyaddr((caddr_t)&saddr, transp->xp_addrlen, AF_INET); 204*38460Smckusick fprintf(stderr,"net_addr=0x%x\n",transp->xp_raddr.sin_addr.s_addr); 205*38460Smckusick fprintf(stderr,"aft gethost hp=0x%x\n",hp); 206*38460Smckusick switch (rqstp->rq_proc) { 207*38460Smckusick case RPCMNT_MOUNT: 208*38460Smckusick fprintf(stderr,"in mnt req\n"); 209*38460Smckusick if (!svc_getargs(transp, xdr_dir, dirpath)) { 210*38460Smckusick svcerr_decode(transp); 211*38460Smckusick return; 212*38460Smckusick } 213*38460Smckusick 214*38460Smckusick fprintf(stderr,"dirpath=%s\n",dirpath); 215*38460Smckusick /* If no hostname, return err */ 216*38460Smckusick #ifdef notdef 217*38460Smckusick if (hp == NULL) { 218*38460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 219*38460Smckusick syslog(LOG_ERR, "Can't send reply"); 220*38460Smckusick return; 221*38460Smckusick } 222*38460Smckusick 223*38460Smckusick #endif 224*38460Smckusick /* Check to see if it's a valid dirpath */ 225*38460Smckusick if (stat(dirpath, &stb) < 0 || (stb.st_mode&S_IFMT) != 226*38460Smckusick S_IFDIR) { 227*38460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 228*38460Smckusick syslog(LOG_ERR, "Can't send reply"); 229*38460Smckusick return; 230*38460Smckusick } 231*38460Smckusick 232*38460Smckusick fprintf(stderr,"Look in exports list\n"); 233*38460Smckusick /* Check in the exports list */ 234*38460Smckusick omask = sigblock(sigmask(SIGHUP)); 235*38460Smckusick ep = exphead.ex_next; 236*38460Smckusick while (ep != NULL) { 237*38460Smckusick if (!strcmp(ep->ex_dirp, dirpath)) { 238*38460Smckusick grp = ep->ex_groups; 239*38460Smckusick if (grp == NULL) 240*38460Smckusick break; 241*38460Smckusick while (grp != NULL) { 242*38460Smckusick if (!strcmp(grp->gr_name, hp->h_name)) 243*38460Smckusick break; 244*38460Smckusick grp = grp->gr_next; 245*38460Smckusick } 246*38460Smckusick bad = EACCES; 247*38460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 248*38460Smckusick syslog(LOG_ERR, "Can't send reply"); 249*38460Smckusick sigsetmask(omask); 250*38460Smckusick return; 251*38460Smckusick } 252*38460Smckusick ep = ep->ex_next; 253*38460Smckusick } 254*38460Smckusick sigsetmask(omask); 255*38460Smckusick if (ep == NULL) { 256*38460Smckusick bad = EACCES; 257*38460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 258*38460Smckusick syslog(LOG_ERR, "Can't send reply"); 259*38460Smckusick return; 260*38460Smckusick } 261*38460Smckusick 262*38460Smckusick fprintf(stderr,"get file handle\n"); 263*38460Smckusick /* Get the file handle */ 264*38460Smckusick bzero((caddr_t)&nfh, sizeof(nfh)); 265*38460Smckusick if (getfh(dirpath, (fhandle_t *)&nfh) < 0) { 266*38460Smckusick bad = errno; 267*38460Smckusick if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad)) 268*38460Smckusick syslog(LOG_ERR, "Can't send reply"); 269*38460Smckusick return; 270*38460Smckusick } 271*38460Smckusick { struct ufid *ufp; 272*38460Smckusick ufp = (struct ufid *)&nfh.fh_generic; 273*38460Smckusick fprintf(stderr,"ftyp=%d fnum=%d\n",nfh.fh_generic.fh_fsid.val[1], 274*38460Smckusick nfh.fh_generic.fh_fsid.val[0]); 275*38460Smckusick fprintf(stderr,"fid num=%d gen=%d\n",ufp->ufid_ino,ufp->ufid_gen); 276*38460Smckusick } 277*38460Smckusick if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh)) 278*38460Smckusick syslog(LOG_ERR, "Can't send reply"); 279*38460Smckusick mlp = (struct mountlist *)malloc(sizeof(struct mountlist)); 280*38460Smckusick fprintf(stderr,"add to list\n"); 281*38460Smckusick #ifdef notdef 282*38460Smckusick if (mlp != NULL) { 283*38460Smckusick strcpy(mlp->ml_host, hp->h_name); 284*38460Smckusick strcpy(mlp->ml_dirp, dirpath); 285*38460Smckusick mlp->ml_prev = &mlhead; 286*38460Smckusick mlp->ml_next = mlhead.ml_next; 287*38460Smckusick if (mlhead.ml_next != NULL) 288*38460Smckusick mlhead.ml_next->ml_prev = mlp; 289*38460Smckusick mlhead.ml_next = mlp; 290*38460Smckusick } 291*38460Smckusick #endif 292*38460Smckusick return; 293*38460Smckusick case RPCMNT_DUMP: 294*38460Smckusick if (!svc_sendreply(transp, xdr_mlist, (caddr_t)0)) 295*38460Smckusick syslog(LOG_ERR, "Can't send reply"); 296*38460Smckusick return; 297*38460Smckusick case RPCMNT_UMOUNT: 298*38460Smckusick if (!svc_getargs(transp, xdr_dir, dirpath)) { 299*38460Smckusick svcerr_decode(transp); 300*38460Smckusick return; 301*38460Smckusick } 302*38460Smckusick if (hp != NULL) { 303*38460Smckusick mlp = mlhead.ml_next; 304*38460Smckusick while (mlp != NULL) { 305*38460Smckusick if (!strcmp(mlp->ml_host, hp->h_name) && 306*38460Smckusick !strcmp(mlp->ml_dirp, dirpath)) { 307*38460Smckusick mlp->ml_prev->ml_next = mlp->ml_next; 308*38460Smckusick if (mlp->ml_next != NULL) 309*38460Smckusick mlp->ml_next->ml_prev = 310*38460Smckusick mlp->ml_prev; 311*38460Smckusick free((caddr_t)mlp); 312*38460Smckusick break; 313*38460Smckusick } 314*38460Smckusick mlp = mlp->ml_next; 315*38460Smckusick } 316*38460Smckusick } 317*38460Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 318*38460Smckusick syslog(LOG_ERR, "Can't send reply"); 319*38460Smckusick return; 320*38460Smckusick case RPCMNT_UMNTALL: 321*38460Smckusick if (hp != NULL) { 322*38460Smckusick mlp = mlhead.ml_next; 323*38460Smckusick while (mlp != NULL) { 324*38460Smckusick if (!strcmp(mlp->ml_host, hp->h_name)) { 325*38460Smckusick mlp2 = mlp; 326*38460Smckusick mlp->ml_prev->ml_next = mlp->ml_next; 327*38460Smckusick if (mlp->ml_next != NULL) 328*38460Smckusick mlp->ml_next->ml_prev = 329*38460Smckusick mlp->ml_prev; 330*38460Smckusick mlp = mlp->ml_next; 331*38460Smckusick free((caddr_t)mlp2); 332*38460Smckusick } else 333*38460Smckusick mlp = mlp->ml_next; 334*38460Smckusick } 335*38460Smckusick } 336*38460Smckusick if (!svc_sendreply(transp, xdr_void, (caddr_t)0)) 337*38460Smckusick syslog(LOG_ERR, "Can't send reply"); 338*38460Smckusick return; 339*38460Smckusick case RPCMNT_EXPORT: 340*38460Smckusick if (!svc_sendreply(transp, xdr_explist, (caddr_t)0)) 341*38460Smckusick syslog(LOG_ERR, "Can't send reply"); 342*38460Smckusick return; 343*38460Smckusick default: 344*38460Smckusick svcerr_noproc(transp); 345*38460Smckusick return; 346*38460Smckusick } 347*38460Smckusick } 348*38460Smckusick 349*38460Smckusick /* 350*38460Smckusick * Xdr conversion for a dirpath string 351*38460Smckusick */ 352*38460Smckusick xdr_dir(xdrsp, dirp) 353*38460Smckusick XDR *xdrsp; 354*38460Smckusick char *dirp; 355*38460Smckusick { 356*38460Smckusick return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN)); 357*38460Smckusick } 358*38460Smckusick 359*38460Smckusick /* 360*38460Smckusick * Xdr routine to generate fhstatus 361*38460Smckusick */ 362*38460Smckusick xdr_fhs(xdrsp, nfh) 363*38460Smckusick XDR *xdrsp; 364*38460Smckusick nfsv2fh_t *nfh; 365*38460Smckusick { 366*38460Smckusick int ok = 0; 367*38460Smckusick 368*38460Smckusick if (!xdr_long(xdrsp, &ok)) 369*38460Smckusick return (0); 370*38460Smckusick fprintf(stderr,"eo xdr_fhs\n"); 371*38460Smckusick return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH)); 372*38460Smckusick } 373*38460Smckusick 374*38460Smckusick xdr_mlist(xdrsp, cp) 375*38460Smckusick XDR *xdrsp; 376*38460Smckusick caddr_t cp; 377*38460Smckusick { 378*38460Smckusick register struct mountlist *mlp; 379*38460Smckusick int true = 1; 380*38460Smckusick int false = 0; 381*38460Smckusick char *strp; 382*38460Smckusick 383*38460Smckusick mlp = mlhead.ml_next; 384*38460Smckusick while (mlp != NULL) { 385*38460Smckusick if (!xdr_bool(xdrsp, &true)) 386*38460Smckusick return (0); 387*38460Smckusick strp = &mlp->ml_host[0]; 388*38460Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 389*38460Smckusick return (0); 390*38460Smckusick strp = &mlp->ml_dirp[0]; 391*38460Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 392*38460Smckusick return (0); 393*38460Smckusick mlp = mlp->ml_next; 394*38460Smckusick } 395*38460Smckusick if (!xdr_bool(xdrsp, &false)) 396*38460Smckusick return (0); 397*38460Smckusick return (1); 398*38460Smckusick } 399*38460Smckusick 400*38460Smckusick /* 401*38460Smckusick * Xdr conversion for export list 402*38460Smckusick */ 403*38460Smckusick xdr_explist(xdrsp, cp) 404*38460Smckusick XDR *xdrsp; 405*38460Smckusick caddr_t cp; 406*38460Smckusick { 407*38460Smckusick register struct exportlist *ep; 408*38460Smckusick register struct grouplist *grp; 409*38460Smckusick int true = 1; 410*38460Smckusick int false = 0; 411*38460Smckusick char *strp; 412*38460Smckusick int omask; 413*38460Smckusick 414*38460Smckusick omask = sigblock(sigmask(SIGHUP)); 415*38460Smckusick ep = exphead.ex_next; 416*38460Smckusick while (ep != NULL) { 417*38460Smckusick if (!xdr_bool(xdrsp, &true)) 418*38460Smckusick goto errout; 419*38460Smckusick strp = &ep->ex_dirp[0]; 420*38460Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 421*38460Smckusick goto errout; 422*38460Smckusick grp = ep->ex_groups; 423*38460Smckusick while (grp != NULL) { 424*38460Smckusick if (!xdr_bool(xdrsp, &true)) 425*38460Smckusick goto errout; 426*38460Smckusick strp = &grp->gr_name[0]; 427*38460Smckusick if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 428*38460Smckusick goto errout; 429*38460Smckusick grp = grp->gr_next; 430*38460Smckusick } 431*38460Smckusick if (!xdr_bool(xdrsp, &false)) 432*38460Smckusick goto errout; 433*38460Smckusick ep = ep->ex_next; 434*38460Smckusick } 435*38460Smckusick sigsetmask(omask); 436*38460Smckusick if (!xdr_bool(xdrsp, &false)) 437*38460Smckusick return (0); 438*38460Smckusick return (1); 439*38460Smckusick errout: 440*38460Smckusick sigsetmask(omask); 441*38460Smckusick return (0); 442*38460Smckusick } 443*38460Smckusick 444*38460Smckusick #define LINESIZ 10240 445*38460Smckusick char line[LINESIZ]; 446*38460Smckusick 447*38460Smckusick /* 448*38460Smckusick * Get the export list 449*38460Smckusick */ 450*38460Smckusick get_exportlist() 451*38460Smckusick { 452*38460Smckusick register struct exportlist *ep, *ep2; 453*38460Smckusick register struct grouplist *grp, *grp2; 454*38460Smckusick FILE *inf; 455*38460Smckusick char *cp, *endcp; 456*38460Smckusick int len; 457*38460Smckusick int rootuid, exflags; 458*38460Smckusick 459*38460Smckusick /* 460*38460Smckusick * First, get rid of the old list 461*38460Smckusick */ 462*38460Smckusick ep = exphead.ex_next; 463*38460Smckusick while (ep != NULL) { 464*38460Smckusick grp = ep->ex_groups; 465*38460Smckusick while (grp != NULL) { 466*38460Smckusick grp2 = grp; 467*38460Smckusick grp = grp->gr_next; 468*38460Smckusick free((caddr_t)grp2); 469*38460Smckusick } 470*38460Smckusick ep2 = ep; 471*38460Smckusick ep = ep->ex_next; 472*38460Smckusick free((caddr_t)ep2); 473*38460Smckusick } 474*38460Smckusick 475*38460Smckusick /* 476*38460Smckusick * Read in the exports file and build the list, calling 477*38460Smckusick * exportfs() as we go along 478*38460Smckusick */ 479*38460Smckusick exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 480*38460Smckusick if ((inf = fopen(exname, "r")) == NULL) { 481*38460Smckusick syslog(LOG_ERR, "Can't open %s", exname); 482*38460Smckusick exit(2); 483*38460Smckusick } 484*38460Smckusick while (fgets(line, LINESIZ, inf)) { 485*38460Smckusick exflags = 0; 486*38460Smckusick rootuid = def_rootuid; 487*38460Smckusick cp = line; 488*38460Smckusick nextfield(&cp, &endcp); 489*38460Smckusick len = endcp-cp; 490*38460Smckusick if (len <= RPCMNT_PATHLEN && len > 0) { 491*38460Smckusick ep = (struct exportlist *)malloc(sizeof(*ep)); 492*38460Smckusick ep->ex_next = ep->ex_prev = (struct exportlist *)0; 493*38460Smckusick ep->ex_groups = (struct grouplist *)0; 494*38460Smckusick bcopy(cp, ep->ex_dirp, len); 495*38460Smckusick ep->ex_dirp[len] = '\0'; 496*38460Smckusick } else 497*38460Smckusick goto err; 498*38460Smckusick cp = endcp; 499*38460Smckusick nextfield(&cp, &endcp); 500*38460Smckusick len = endcp-cp; 501*38460Smckusick while (len > 0) { 502*38460Smckusick if (len <= RPCMNT_NAMELEN) { 503*38460Smckusick if (*cp == '-') { 504*38460Smckusick cp++; 505*38460Smckusick switch (*cp) { 506*38460Smckusick case 'o': 507*38460Smckusick exflags |= M_EXRDONLY; 508*38460Smckusick break; 509*38460Smckusick case 'r': 510*38460Smckusick if (*++cp == '=') 511*38460Smckusick rootuid = atoi(++cp); 512*38460Smckusick break; 513*38460Smckusick default: 514*38460Smckusick syslog(LOG_WARNING, 515*38460Smckusick "Bad -%c option in %s", 516*38460Smckusick *cp, exname); 517*38460Smckusick break; 518*38460Smckusick }; 519*38460Smckusick } else { 520*38460Smckusick grp = (struct grouplist *)malloc(*grp); 521*38460Smckusick if (grp == NULL) 522*38460Smckusick goto err; 523*38460Smckusick bcopy(cp, grp->gr_name, len); 524*38460Smckusick grp->gr_name[len] = '\0'; 525*38460Smckusick grp->gr_next = ep->ex_groups; 526*38460Smckusick ep->ex_groups = grp; 527*38460Smckusick } 528*38460Smckusick } 529*38460Smckusick cp = endcp; 530*38460Smckusick nextfield(&cp, &endcp); 531*38460Smckusick len = endcp-cp; 532*38460Smckusick } 533*38460Smckusick if (exportfs(ep->ex_dirp, rootuid, exflags) < 0) { 534*38460Smckusick syslog(LOG_WARNING, "Can't export %s", ep->ex_dirp); 535*38460Smckusick free((caddr_t)ep); 536*38460Smckusick } else { 537*38460Smckusick ep->ex_rootuid = rootuid; 538*38460Smckusick ep->ex_exflags = exflags; 539*38460Smckusick ep->ex_next = exphead.ex_next; 540*38460Smckusick ep->ex_prev = &exphead; 541*38460Smckusick if (ep->ex_next != NULL) 542*38460Smckusick ep->ex_next->ex_prev = ep; 543*38460Smckusick exphead.ex_next = ep; 544*38460Smckusick } 545*38460Smckusick } 546*38460Smckusick fclose(inf); 547*38460Smckusick return; 548*38460Smckusick err: 549*38460Smckusick syslog(LOG_ERR, "Bad /etc/exports, mountd Failed"); 550*38460Smckusick exit(2); 551*38460Smckusick } 552*38460Smckusick 553*38460Smckusick /* 554*38460Smckusick * Parse out the next white space separated field 555*38460Smckusick */ 556*38460Smckusick nextfield(cp, endcp) 557*38460Smckusick char **cp; 558*38460Smckusick char **endcp; 559*38460Smckusick { 560*38460Smckusick register char *p; 561*38460Smckusick 562*38460Smckusick p = *cp; 563*38460Smckusick while (*p == ' ' || *p == '\t') 564*38460Smckusick p++; 565*38460Smckusick if (*p == '\n' || *p == '\0') { 566*38460Smckusick *cp = *endcp = p; 567*38460Smckusick return; 568*38460Smckusick } 569*38460Smckusick *cp = p++; 570*38460Smckusick while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 571*38460Smckusick p++; 572*38460Smckusick *endcp = p; 573*38460Smckusick } 574