386BSD 0.1 development
[unix-history] / usr / src / sbin / mountd / mountd.c
CommitLineData
2f2881da
WJ
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
38char 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
44static 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
66struct 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 */
74struct mountlist {
75 struct mountlist *ml_next;
76 char ml_host[RPCMNT_NAMELEN+1];
77 char ml_dirp[RPCMNT_PATHLEN+1];
78};
79
80struct 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
90struct grouplist {
91 struct grouplist *gr_next;
92 struct hostent *gr_hp;
93};
94
95/* Global defs */
96int mntsrv(), umntall_each(), xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist();
97void add_mlist(), del_mlist(), get_exportlist(), get_mountlist();
98void send_umntall();
99struct exportlist exphead;
100struct mountlist *mlhead;
101char exname[MAXPATHLEN];
102int def_rootuid = -2;
103int root_only = 1;
104extern int errno;
105#ifdef DEBUG
106int debug = 1;
107#else
108int 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 */
118main(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 */
178mntsrv(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 */
328xdr_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 */
338xdr_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
349xdr_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 */
378xdr_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);
414errout:
415 sigsetmask(omask);
416 return (0);
417}
418
419#define LINESIZ 10240
420char line[LINESIZ];
421
422/*
423 * Get the export list
424 */
425void
426get_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 if (cp == NULL)
588 cp = ep->ex_dirp + dirplen - 1;
589 else
590 *cp = savedc;
591 /* back up over the last component */
592 while (*cp == '/' && cp > ep->ex_dirp)
593 cp--;
594 while (*(cp - 1) != '/' && cp > ep->ex_dirp)
595 cp--;
596 if (cp == ep->ex_dirp) {
597 syslog(LOG_WARNING,
598 "Can't export %s", ep->ex_dirp);
599 free_exp(ep);
600 goto nextline;
601 }
602 savedc = *cp;
603 *cp = '\0';
604 }
605 if (cp)
606 *cp = savedc;
607 ep->ex_rootuid = rootuid;
608 ep->ex_exflags = exflags;
609 } else {
610 ep->ex_rootuid = fep->ex_rootuid;
611 ep->ex_exflags = fep->ex_exflags;
612 }
613 ep->ex_dev = sb.st_dev;
614 ep->ex_next = exphead.ex_next;
615 ep->ex_prev = &exphead;
616 if (ep->ex_next != NULL)
617 ep->ex_next->ex_prev = ep;
618 exphead.ex_next = ep;
619nextline:
620 ;
621 }
622 fclose(inf);
623 return;
624err:
625 syslog(LOG_ERR, "No more memory: mountd Failed");
626 exit(2);
627}
628
629/*
630 * Parse out the next white space separated field
631 */
632nextfield(cp, endcp)
633 char **cp;
634 char **endcp;
635{
636 register char *p;
637
638 p = *cp;
639 while (*p == ' ' || *p == '\t')
640 p++;
641 if (*p == '\n' || *p == '\0') {
642 *cp = *endcp = p;
643 return;
644 }
645 *cp = p++;
646 while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
647 p++;
648 *endcp = p;
649}
650
651/*
652 * Parse the option string
653 */
654do_opt(cpopt, fep, ep, exflagsp, rootuidp)
655 register char *cpopt;
656 struct exportlist *fep, *ep;
657 int *exflagsp, *rootuidp;
658{
659 register char *cpoptarg, *cpoptend;
660
661 while (cpopt && *cpopt) {
662 if (cpoptend = index(cpopt, ','))
663 *cpoptend++ = '\0';
664 if (cpoptarg = index(cpopt, '='))
665 *cpoptarg++ = '\0';
666 if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) {
667 if (fep && (fep->ex_exflags & MNT_EXRDONLY) == 0)
668 syslog(LOG_WARNING, "ro failed for %s",
669 ep->ex_dirp);
670 else
671 *exflagsp |= MNT_EXRDONLY;
672 } else if (!strcmp(cpopt, "root") || !strcmp(cpopt, "r")) {
673 if (cpoptarg && isdigit(*cpoptarg)) {
674 *rootuidp = atoi(cpoptarg);
675 if (fep && fep->ex_rootuid != *rootuidp)
676 syslog(LOG_WARNING,
677 "uid failed for %s",
678 ep->ex_dirp);
679 } else
680 syslog(LOG_WARNING,
681 "uid failed for %s",
682 ep->ex_dirp);
683 } else
684 syslog(LOG_WARNING, "opt %s ignored for %s", cpopt,
685 ep->ex_dirp);
686 cpopt = cpoptend;
687 }
688}
689
690#define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50)
691/*
692 * Routines that maintain the remote mounttab
693 */
694void get_mountlist()
695{
696 register struct mountlist *mlp, **mlpp;
697 register char *eos, *dirp;
698 int len;
699 char str[STRSIZ];
700 FILE *mlfile;
701
702 if (((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) &&
703 ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL)) {
704 syslog(LOG_WARNING, "Can't open %s", _PATH_RMOUNTLIST);
705 return;
706 }
707 mlpp = &mlhead;
708 while (fgets(str, STRSIZ, mlfile) != NULL) {
709 if ((dirp = index(str, '\t')) == NULL &&
710 (dirp = index(str, ' ')) == NULL)
711 continue;
712 mlp = (struct mountlist *)malloc(sizeof (*mlp));
713 len = dirp-str;
714 if (len > RPCMNT_NAMELEN)
715 len = RPCMNT_NAMELEN;
716 bcopy(str, mlp->ml_host, len);
717 mlp->ml_host[len] = '\0';
718 while (*dirp == '\t' || *dirp == ' ')
719 dirp++;
720 if ((eos = index(dirp, '\t')) == NULL &&
721 (eos = index(dirp, ' ')) == NULL &&
722 (eos = index(dirp, '\n')) == NULL)
723 len = strlen(dirp);
724 else
725 len = eos-dirp;
726 if (len > RPCMNT_PATHLEN)
727 len = RPCMNT_PATHLEN;
728 bcopy(dirp, mlp->ml_dirp, len);
729 mlp->ml_dirp[len] = '\0';
730 mlp->ml_next = (struct mountlist *)0;
731 *mlpp = mlp;
732 mlpp = &mlp->ml_next;
733 }
734 fclose(mlfile);
735}
736
737void del_mlist(hostp, dirp)
738 register char *hostp, *dirp;
739{
740 register struct mountlist *mlp, **mlpp;
741 FILE *mlfile;
742 int fnd = 0;
743
744 mlpp = &mlhead;
745 mlp = mlhead;
746 while (mlp) {
747 if (!strcmp(mlp->ml_host, hostp) &&
748 (!dirp || !strcmp(mlp->ml_dirp, dirp))) {
749 fnd = 1;
750 *mlpp = mlp->ml_next;
751 free((caddr_t)mlp);
752 }
753 mlpp = &mlp->ml_next;
754 mlp = mlp->ml_next;
755 }
756 if (fnd) {
757 if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) {
758 syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST);
759 return;
760 }
761 mlp = mlhead;
762 while (mlp) {
763 fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp);
764 mlp = mlp->ml_next;
765 }
766 fclose(mlfile);
767 }
768}
769
770void add_mlist(hostp, dirp)
771 register char *hostp, *dirp;
772{
773 register struct mountlist *mlp, **mlpp;
774 FILE *mlfile;
775
776 mlpp = &mlhead;
777 mlp = mlhead;
778 while (mlp) {
779 if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp))
780 return;
781 mlpp = &mlp->ml_next;
782 mlp = mlp->ml_next;
783 }
784 mlp = (struct mountlist *)malloc(sizeof (*mlp));
785 strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN);
786 mlp->ml_host[RPCMNT_NAMELEN] = '\0';
787 strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN);
788 mlp->ml_dirp[RPCMNT_PATHLEN] = '\0';
789 mlp->ml_next = (struct mountlist *)0;
790 *mlpp = mlp;
791 if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) {
792 syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST);
793 return;
794 }
795 fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp);
796 fclose(mlfile);
797}
798
799/*
800 * This function is called via. SIGTERM when the system is going down.
801 * It sends a broadcast RPCMNT_UMNTALL.
802 */
803void
804send_umntall()
805{
806 (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL,
807 xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each);
808 exit();
809}
810
811umntall_each(resultsp, raddr)
812 caddr_t resultsp;
813 struct sockaddr_in *raddr;
814{
815 return (1);
816}
817
818/*
819 * Free up an exports list component
820 */
821free_exp(ep)
822 register struct exportlist *ep;
823{
824 register struct grouplist *grp;
825 register char **addrp;
826 struct grouplist *grp2;
827
828 grp = ep->ex_groups;
829 while (grp != NULL) {
830 addrp = grp->gr_hp->h_addr_list;
831 while (*addrp)
832 free(*addrp++);
833 free((caddr_t)grp->gr_hp->h_addr_list);
834 free(grp->gr_hp->h_name);
835 free((caddr_t)grp->gr_hp);
836 grp2 = grp;
837 grp = grp->gr_next;
838 free((caddr_t)grp2);
839 }
840 free((caddr_t)ep);
841}