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.12 (Berkeley) 08/31/90"; 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 xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist(); 71 int mntsrv(), get_exportlist(), send_umntall(), umntall_each(); 72 void get_mountlist(), add_mlist(), del_mlist(); 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 get_exportlist() 400 { 401 register struct hostent *hp, *nhp; 402 register char **addrp, **naddrp; 403 register int i; 404 register struct grouplist *grp; 405 register struct exportlist *ep, *ep2; 406 struct statfs stfsbuf; 407 struct ufs_args args; 408 struct stat sb; 409 FILE *inf; 410 char *cp, *endcp; 411 char savedc; 412 int len, dirplen; 413 int rootuid, exflags; 414 u_long saddr; 415 struct exportlist *fep; 416 417 /* 418 * First, get rid of the old list 419 */ 420 ep = exphead.ex_next; 421 while (ep != NULL) { 422 ep2 = ep; 423 ep = ep->ex_next; 424 free_exp(ep2); 425 } 426 427 /* 428 * Read in the exports file and build the list, calling 429 * exportfs() as we go along 430 */ 431 exphead.ex_next = exphead.ex_prev = (struct exportlist *)0; 432 if ((inf = fopen(exname, "r")) == NULL) { 433 syslog(LOG_ERR, "Can't open %s", exname); 434 exit(2); 435 } 436 while (fgets(line, LINESIZ, inf)) { 437 exflags = MNT_EXPORTED; 438 rootuid = def_rootuid; 439 cp = line; 440 nextfield(&cp, &endcp); 441 442 /* 443 * Get file system devno and see if an entry for this 444 * file system already exists. 445 */ 446 savedc = *endcp; 447 *endcp = '\0'; 448 if (stat(cp, &sb) < 0 || (sb.st_mode & S_IFMT) != S_IFDIR) 449 goto err; 450 fep = (struct exportlist *)0; 451 ep = exphead.ex_next; 452 while (ep) { 453 if (ep->ex_dev == sb.st_dev) { 454 fep = ep; 455 break; 456 } 457 ep = ep->ex_next; 458 } 459 *endcp = savedc; 460 461 /* 462 * Create new exports list entry 463 */ 464 len = endcp-cp; 465 if (len <= RPCMNT_PATHLEN && len > 0) { 466 ep = (struct exportlist *)malloc(sizeof(*ep)); 467 ep->ex_next = ep->ex_prev = (struct exportlist *)0; 468 ep->ex_groups = (struct grouplist *)0; 469 bcopy(cp, ep->ex_dirp, len); 470 ep->ex_dirp[len] = '\0'; 471 dirplen = len; 472 } else 473 goto err; 474 cp = endcp; 475 nextfield(&cp, &endcp); 476 len = endcp-cp; 477 while (len > 0) { 478 savedc = *endcp; 479 *endcp = '\0'; 480 if (len <= RPCMNT_NAMELEN) { 481 if (*cp == '-') { 482 do_opt(cp+1, fep, ep, &exflags, &rootuid); 483 } else { 484 if (isdigit(*cp)) { 485 saddr = inet_addr(cp); 486 if (saddr == -1 || 487 (hp = gethostbyaddr((caddr_t)&saddr, 488 sizeof(saddr), AF_INET)) == NULL) 489 goto err; 490 } else if ((hp = gethostbyname(cp)) == NULL) 491 goto err; 492 grp = (struct grouplist *) 493 malloc(sizeof(struct grouplist)); 494 if (grp == NULL) 495 goto err; 496 nhp = grp->gr_hp = (struct hostent *) 497 malloc(sizeof(struct hostent)); 498 if (nhp == NULL) 499 goto err; 500 bcopy((caddr_t)hp, (caddr_t)nhp, 501 sizeof(struct hostent)); 502 i = strlen(hp->h_name)+1; 503 nhp->h_name = (char *)malloc(i); 504 if (nhp->h_name == NULL) 505 goto err; 506 bcopy(hp->h_name, nhp->h_name, i); 507 addrp = hp->h_addr_list; 508 i = 1; 509 while (*addrp++) 510 i++; 511 naddrp = nhp->h_addr_list = (char **) 512 malloc(i*sizeof(char *)); 513 if (naddrp == NULL) 514 goto err; 515 addrp = hp->h_addr_list; 516 while (*addrp) { 517 *naddrp = (char *) 518 malloc(hp->h_length); 519 if (*naddrp == NULL) 520 goto err; 521 bcopy(*addrp, *naddrp, 522 hp->h_length); 523 addrp++; 524 naddrp++; 525 } 526 *naddrp = (char *)0; 527 grp->gr_next = ep->ex_groups; 528 ep->ex_groups = grp; 529 } 530 } 531 cp = endcp; 532 *cp = savedc; 533 nextfield(&cp, &endcp); 534 len = endcp-cp; 535 } 536 if (fep == NULL) { 537 args.fspec = 0; 538 args.exflags = exflags; 539 args.exroot = rootuid; 540 cp = (char *)0; 541 while (statfs(ep->ex_dirp, &stfsbuf) < 0 || 542 mount(MOUNT_UFS, ep->ex_dirp, 543 stfsbuf.f_flags|MNT_UPDATE, &args) < 0) { 544 if (cp == NULL) 545 cp = ep->ex_dirp + dirplen - 1; 546 else 547 *cp = savedc; 548 /* back up over the last component */ 549 while (*cp == '/' && cp > ep->ex_dirp) 550 cp--; 551 while (*(cp - 1) != '/' && cp > ep->ex_dirp) 552 cp--; 553 if (cp == ep->ex_dirp) { 554 syslog(LOG_WARNING, 555 "Can't export %s", ep->ex_dirp); 556 free_exp(ep); 557 goto nextline; 558 } 559 savedc = *cp; 560 *cp = '\0'; 561 } 562 if (cp) 563 *cp = savedc; 564 ep->ex_rootuid = rootuid; 565 ep->ex_exflags = exflags; 566 } else { 567 ep->ex_rootuid = fep->ex_rootuid; 568 ep->ex_exflags = fep->ex_exflags; 569 } 570 ep->ex_dev = sb.st_dev; 571 ep->ex_next = exphead.ex_next; 572 ep->ex_prev = &exphead; 573 if (ep->ex_next != NULL) 574 ep->ex_next->ex_prev = ep; 575 exphead.ex_next = ep; 576 nextline: 577 ; 578 } 579 fclose(inf); 580 return; 581 err: 582 syslog(LOG_ERR, "Bad Exports File, mountd Failed"); 583 exit(2); 584 } 585 586 /* 587 * Parse out the next white space separated field 588 */ 589 nextfield(cp, endcp) 590 char **cp; 591 char **endcp; 592 { 593 register char *p; 594 595 p = *cp; 596 while (*p == ' ' || *p == '\t') 597 p++; 598 if (*p == '\n' || *p == '\0') { 599 *cp = *endcp = p; 600 return; 601 } 602 *cp = p++; 603 while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0') 604 p++; 605 *endcp = p; 606 } 607 608 /* 609 * Parse the option string 610 */ 611 do_opt(cpopt, fep, ep, exflagsp, rootuidp) 612 register char *cpopt; 613 struct exportlist *fep, *ep; 614 int *exflagsp, *rootuidp; 615 { 616 register char *cpoptarg, *cpoptend; 617 618 while (cpopt && *cpopt) { 619 if (cpoptend = index(cpopt, ',')) 620 *cpoptend++ = '\0'; 621 if (cpoptarg = index(cpopt, '=')) 622 *cpoptarg++ = '\0'; 623 if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) { 624 if (fep && (fep->ex_exflags & MNT_EXRDONLY) == 0) 625 syslog(LOG_WARNING, "ro failed for %s", 626 ep->ex_dirp); 627 else 628 *exflagsp |= MNT_EXRDONLY; 629 } else if (!strcmp(cpopt, "root") || !strcmp(cpopt, "r")) { 630 if (cpoptarg && isdigit(*cpoptarg)) { 631 *rootuidp = atoi(cpoptarg); 632 if (fep && fep->ex_rootuid != *rootuidp) 633 syslog(LOG_WARNING, 634 "uid failed for %s", 635 ep->ex_dirp); 636 } else 637 syslog(LOG_WARNING, 638 "uid failed for %s", 639 ep->ex_dirp); 640 } else 641 syslog(LOG_WARNING, "opt %s ignored for %s", cpopt, 642 ep->ex_dirp); 643 cpopt = cpoptend; 644 } 645 } 646 647 #define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50) 648 /* 649 * Routines that maintain the remote mounttab 650 */ 651 void get_mountlist() 652 { 653 register struct mountlist *mlp, **mlpp; 654 register char *eos, *dirp; 655 int len; 656 char str[STRSIZ]; 657 FILE *mlfile; 658 659 if (((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) && 660 ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL)) { 661 syslog(LOG_WARNING, "Can't open %s", _PATH_RMOUNTLIST); 662 return; 663 } 664 mlpp = &mlhead; 665 while (fgets(str, STRSIZ, mlfile) != NULL) { 666 if ((dirp = index(str, '\t')) == NULL && 667 (dirp = index(str, ' ')) == NULL) 668 continue; 669 mlp = (struct mountlist *)malloc(sizeof (*mlp)); 670 len = dirp-str; 671 if (len > RPCMNT_NAMELEN) 672 len = RPCMNT_NAMELEN; 673 bcopy(str, mlp->ml_host, len); 674 mlp->ml_host[len] = '\0'; 675 while (*dirp == '\t' || *dirp == ' ') 676 dirp++; 677 if ((eos = index(dirp, '\t')) == NULL && 678 (eos = index(dirp, ' ')) == NULL && 679 (eos = index(dirp, '\n')) == NULL) 680 len = strlen(dirp); 681 else 682 len = eos-dirp; 683 if (len > RPCMNT_PATHLEN) 684 len = RPCMNT_PATHLEN; 685 bcopy(dirp, mlp->ml_dirp, len); 686 mlp->ml_dirp[len] = '\0'; 687 mlp->ml_next = (struct mountlist *)0; 688 *mlpp = mlp; 689 mlpp = &mlp->ml_next; 690 } 691 fclose(mlfile); 692 } 693 694 void del_mlist(hostp, dirp) 695 register char *hostp, *dirp; 696 { 697 register struct mountlist *mlp, **mlpp; 698 FILE *mlfile; 699 int fnd = 0; 700 701 mlpp = &mlhead; 702 mlp = mlhead; 703 while (mlp) { 704 if (!strcmp(mlp->ml_host, hostp) && 705 (!dirp || !strcmp(mlp->ml_dirp, dirp))) { 706 fnd = 1; 707 *mlpp = mlp->ml_next; 708 free((caddr_t)mlp); 709 } 710 mlpp = &mlp->ml_next; 711 mlp = mlp->ml_next; 712 } 713 if (fnd) { 714 if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) { 715 syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST); 716 return; 717 } 718 mlp = mlhead; 719 while (mlp) { 720 fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 721 mlp = mlp->ml_next; 722 } 723 fclose(mlfile); 724 } 725 } 726 727 void add_mlist(hostp, dirp) 728 register char *hostp, *dirp; 729 { 730 register struct mountlist *mlp, **mlpp; 731 FILE *mlfile; 732 733 mlpp = &mlhead; 734 mlp = mlhead; 735 while (mlp) { 736 if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp)) 737 return; 738 mlpp = &mlp->ml_next; 739 mlp = mlp->ml_next; 740 } 741 mlp = (struct mountlist *)malloc(sizeof (*mlp)); 742 strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN); 743 mlp->ml_host[RPCMNT_NAMELEN] = '\0'; 744 strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN); 745 mlp->ml_dirp[RPCMNT_PATHLEN] = '\0'; 746 mlp->ml_next = (struct mountlist *)0; 747 *mlpp = mlp; 748 if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) { 749 syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST); 750 return; 751 } 752 fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp); 753 fclose(mlfile); 754 } 755 756 /* 757 * This function is called via. SIGTERM when the system is going down. 758 * It sends a broadcast RPCMNT_UMNTALL. 759 */ 760 send_umntall() 761 { 762 (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL, 763 xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each); 764 exit(); 765 } 766 767 umntall_each(resultsp, raddr) 768 caddr_t resultsp; 769 struct sockaddr_in *raddr; 770 { 771 return (1); 772 } 773 774 /* 775 * Free up an exports list component 776 */ 777 free_exp(ep) 778 register struct exportlist *ep; 779 { 780 register struct grouplist *grp; 781 register char **addrp; 782 struct grouplist *grp2; 783 784 grp = ep->ex_groups; 785 while (grp != NULL) { 786 addrp = grp->gr_hp->h_addr_list; 787 while (*addrp) 788 free(*addrp++); 789 free((caddr_t)grp->gr_hp->h_addr_list); 790 free(grp->gr_hp->h_name); 791 free((caddr_t)grp->gr_hp); 792 grp2 = grp; 793 grp = grp->gr_next; 794 free((caddr_t)grp2); 795 } 796 free((caddr_t)ep); 797 } 798