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