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