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