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