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