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