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