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