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