ANSI fixes (one real bug!)
[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
5b83dcdd 18static char sccsid[] = "@(#)mountd.c 5.13 (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 */
70int xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist();
e4fde528
KM
71int mntsrv(), get_exportlist(), send_umntall(), umntall_each();
72void get_mountlist(), add_mlist(), del_mlist();
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 */
399get_exportlist()
400{
c2282441
KM
401 register struct hostent *hp, *nhp;
402 register char **addrp, **naddrp;
403 register int i;
e4fde528 404 register struct grouplist *grp;
c2282441 405 register struct exportlist *ep, *ep2;
76bf9405 406 struct statfs stfsbuf;
dd66e524 407 struct ufs_args args;
e4fde528 408 struct stat sb;
e3ab21d9
KM
409 FILE *inf;
410 char *cp, *endcp;
c2282441 411 char savedc;
e4fde528 412 int len, dirplen;
e3ab21d9 413 int rootuid, exflags;
e4fde528
KM
414 u_long saddr;
415 struct exportlist *fep;
e3ab21d9
KM
416
417 /*
418 * First, get rid of the old list
419 */
420 ep = exphead.ex_next;
421 while (ep != NULL) {
e3ab21d9
KM
422 ep2 = ep;
423 ep = ep->ex_next;
e4fde528 424 free_exp(ep2);
e3ab21d9
KM
425 }
426
427 /*
428 * Read in the exports file and build the list, calling
429 * exportfs() as we go along
430 */
431 exphead.ex_next = exphead.ex_prev = (struct exportlist *)0;
432 if ((inf = fopen(exname, "r")) == NULL) {
433 syslog(LOG_ERR, "Can't open %s", exname);
434 exit(2);
435 }
436 while (fgets(line, LINESIZ, inf)) {
b5cedeb3 437 exflags = MNT_EXPORTED;
e3ab21d9
KM
438 rootuid = def_rootuid;
439 cp = line;
440 nextfield(&cp, &endcp);
e4fde528
KM
441
442 /*
443 * Get file system devno and see if an entry for this
444 * file system already exists.
445 */
446 savedc = *endcp;
447 *endcp = '\0';
5b83dcdd
KM
448 if (stat(cp, &sb) < 0 || (sb.st_mode & S_IFMT) != S_IFDIR) {
449 syslog(LOG_ERR,
450 "Bad Exports File, %s: %s, mountd Failed",
451 cp, "Not a directory");
452 exit(2);
453 }
e4fde528
KM
454 fep = (struct exportlist *)0;
455 ep = exphead.ex_next;
456 while (ep) {
457 if (ep->ex_dev == sb.st_dev) {
458 fep = ep;
459 break;
460 }
461 ep = ep->ex_next;
462 }
463 *endcp = savedc;
464
465 /*
466 * Create new exports list entry
467 */
e3ab21d9
KM
468 len = endcp-cp;
469 if (len <= RPCMNT_PATHLEN && len > 0) {
470 ep = (struct exportlist *)malloc(sizeof(*ep));
5b83dcdd
KM
471 if (ep == NULL)
472 goto err;
e3ab21d9
KM
473 ep->ex_next = ep->ex_prev = (struct exportlist *)0;
474 ep->ex_groups = (struct grouplist *)0;
475 bcopy(cp, ep->ex_dirp, len);
476 ep->ex_dirp[len] = '\0';
e4fde528 477 dirplen = len;
5b83dcdd
KM
478 } else {
479 syslog(LOG_ERR, "Bad Exports File, mountd Failed");
480 exit(2);
481 }
e3ab21d9
KM
482 cp = endcp;
483 nextfield(&cp, &endcp);
484 len = endcp-cp;
485 while (len > 0) {
c2282441
KM
486 savedc = *endcp;
487 *endcp = '\0';
5b83dcdd
KM
488 if (len > RPCMNT_NAMELEN)
489 goto more;
490 if (*cp == '-') {
491 do_opt(cp + 1, fep, ep, &exflags, &rootuid);
492 goto more;
493 }
494 if (isdigit(*cp)) {
495 saddr = inet_addr(cp);
496 if (saddr == -1 ||
497 (hp = gethostbyaddr((caddr_t)&saddr,
498 sizeof(saddr), AF_INET)) == NULL) {
499 syslog(LOG_ERR,
500 "Bad Exports File, %s: %s", cp,
501 "Gethostbyaddr failed, ignored");
502 goto more;
e3ab21d9 503 }
5b83dcdd
KM
504 } else if ((hp = gethostbyname(cp)) == NULL) {
505 syslog(LOG_ERR, "Bad Exports File, %s: %s",
506 cp, "Gethostbyname failed, ignored");
507 goto more;
508 }
509 grp = (struct grouplist *)
510 malloc(sizeof(struct grouplist));
511 if (grp == NULL)
512 goto err;
513 nhp = grp->gr_hp = (struct hostent *)
514 malloc(sizeof(struct hostent));
515 if (nhp == NULL)
516 goto err;
517 bcopy((caddr_t)hp, (caddr_t)nhp,
518 sizeof(struct hostent));
519 i = strlen(hp->h_name)+1;
520 nhp->h_name = (char *)malloc(i);
521 if (nhp->h_name == NULL)
522 goto err;
523 bcopy(hp->h_name, nhp->h_name, i);
524 addrp = hp->h_addr_list;
525 i = 1;
526 while (*addrp++)
527 i++;
528 naddrp = nhp->h_addr_list = (char **)
529 malloc(i*sizeof(char *));
530 if (naddrp == NULL)
531 goto err;
532 addrp = hp->h_addr_list;
533 while (*addrp) {
534 *naddrp = (char *)
535 malloc(hp->h_length);
536 if (*naddrp == NULL)
537 goto err;
538 bcopy(*addrp, *naddrp,
539 hp->h_length);
540 addrp++;
541 naddrp++;
e3ab21d9 542 }
5b83dcdd
KM
543 *naddrp = (char *)0;
544 grp->gr_next = ep->ex_groups;
545 ep->ex_groups = grp;
546 more:
e3ab21d9 547 cp = endcp;
c2282441 548 *cp = savedc;
e3ab21d9 549 nextfield(&cp, &endcp);
5b83dcdd 550 len = endcp - cp;
e3ab21d9 551 }
e4fde528
KM
552 if (fep == NULL) {
553 args.fspec = 0;
554 args.exflags = exflags;
555 args.exroot = rootuid;
556 cp = (char *)0;
76bf9405
KM
557 while (statfs(ep->ex_dirp, &stfsbuf) < 0 ||
558 mount(MOUNT_UFS, ep->ex_dirp,
559 stfsbuf.f_flags|MNT_UPDATE, &args) < 0) {
e4fde528
KM
560 if (cp == NULL)
561 cp = ep->ex_dirp + dirplen - 1;
562 else
563 *cp = savedc;
564 /* back up over the last component */
565 while (*cp == '/' && cp > ep->ex_dirp)
566 cp--;
567 while (*(cp - 1) != '/' && cp > ep->ex_dirp)
568 cp--;
569 if (cp == ep->ex_dirp) {
570 syslog(LOG_WARNING,
571 "Can't export %s", ep->ex_dirp);
572 free_exp(ep);
573 goto nextline;
574 }
575 savedc = *cp;
576 *cp = '\0';
577 }
578 if (cp)
579 *cp = savedc;
e3ab21d9
KM
580 ep->ex_rootuid = rootuid;
581 ep->ex_exflags = exflags;
e4fde528
KM
582 } else {
583 ep->ex_rootuid = fep->ex_rootuid;
584 ep->ex_exflags = fep->ex_exflags;
e3ab21d9 585 }
e4fde528
KM
586 ep->ex_dev = sb.st_dev;
587 ep->ex_next = exphead.ex_next;
588 ep->ex_prev = &exphead;
589 if (ep->ex_next != NULL)
590 ep->ex_next->ex_prev = ep;
591 exphead.ex_next = ep;
592nextline:
593 ;
e3ab21d9
KM
594 }
595 fclose(inf);
596 return;
597err:
5b83dcdd 598 syslog(LOG_ERR, "No more memory: mountd Failed");
e3ab21d9
KM
599 exit(2);
600}
601
602/*
603 * Parse out the next white space separated field
604 */
605nextfield(cp, endcp)
606 char **cp;
607 char **endcp;
608{
609 register char *p;
610
611 p = *cp;
612 while (*p == ' ' || *p == '\t')
613 p++;
614 if (*p == '\n' || *p == '\0') {
615 *cp = *endcp = p;
616 return;
617 }
618 *cp = p++;
619 while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
620 p++;
621 *endcp = p;
622}
c2282441
KM
623
624/*
e4fde528 625 * Parse the option string
c2282441 626 */
e4fde528
KM
627do_opt(cpopt, fep, ep, exflagsp, rootuidp)
628 register char *cpopt;
629 struct exportlist *fep, *ep;
630 int *exflagsp, *rootuidp;
c2282441 631{
e4fde528
KM
632 register char *cpoptarg, *cpoptend;
633
634 while (cpopt && *cpopt) {
635 if (cpoptend = index(cpopt, ','))
636 *cpoptend++ = '\0';
637 if (cpoptarg = index(cpopt, '='))
638 *cpoptarg++ = '\0';
639 if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) {
640 if (fep && (fep->ex_exflags & MNT_EXRDONLY) == 0)
641 syslog(LOG_WARNING, "ro failed for %s",
642 ep->ex_dirp);
643 else
644 *exflagsp |= MNT_EXRDONLY;
645 } else if (!strcmp(cpopt, "root") || !strcmp(cpopt, "r")) {
646 if (cpoptarg && isdigit(*cpoptarg)) {
647 *rootuidp = atoi(cpoptarg);
648 if (fep && fep->ex_rootuid != *rootuidp)
649 syslog(LOG_WARNING,
650 "uid failed for %s",
651 ep->ex_dirp);
652 } else
653 syslog(LOG_WARNING,
654 "uid failed for %s",
655 ep->ex_dirp);
656 } else
657 syslog(LOG_WARNING, "opt %s ignored for %s", cpopt,
658 ep->ex_dirp);
659 cpopt = cpoptend;
660 }
661}
662
663#define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50)
664/*
665 * Routines that maintain the remote mounttab
666 */
667void get_mountlist()
668{
669 register struct mountlist *mlp, **mlpp;
670 register char *eos, *dirp;
671 int len;
672 char str[STRSIZ];
673 FILE *mlfile;
674
91e44e87
KM
675 if (((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) &&
676 ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL)) {
e4fde528
KM
677 syslog(LOG_WARNING, "Can't open %s", _PATH_RMOUNTLIST);
678 return;
679 }
680 mlpp = &mlhead;
681 while (fgets(str, STRSIZ, mlfile) != NULL) {
682 if ((dirp = index(str, '\t')) == NULL &&
683 (dirp = index(str, ' ')) == NULL)
684 continue;
685 mlp = (struct mountlist *)malloc(sizeof (*mlp));
686 len = dirp-str;
687 if (len > RPCMNT_NAMELEN)
688 len = RPCMNT_NAMELEN;
689 bcopy(str, mlp->ml_host, len);
690 mlp->ml_host[len] = '\0';
691 while (*dirp == '\t' || *dirp == ' ')
692 dirp++;
693 if ((eos = index(dirp, '\t')) == NULL &&
694 (eos = index(dirp, ' ')) == NULL &&
695 (eos = index(dirp, '\n')) == NULL)
696 len = strlen(dirp);
697 else
698 len = eos-dirp;
699 if (len > RPCMNT_PATHLEN)
700 len = RPCMNT_PATHLEN;
701 bcopy(dirp, mlp->ml_dirp, len);
702 mlp->ml_dirp[len] = '\0';
703 mlp->ml_next = (struct mountlist *)0;
704 *mlpp = mlp;
705 mlpp = &mlp->ml_next;
706 }
707 fclose(mlfile);
708}
709
710void del_mlist(hostp, dirp)
711 register char *hostp, *dirp;
712{
713 register struct mountlist *mlp, **mlpp;
714 FILE *mlfile;
715 int fnd = 0;
716
717 mlpp = &mlhead;
718 mlp = mlhead;
719 while (mlp) {
720 if (!strcmp(mlp->ml_host, hostp) &&
721 (!dirp || !strcmp(mlp->ml_dirp, dirp))) {
722 fnd = 1;
723 *mlpp = mlp->ml_next;
724 free((caddr_t)mlp);
725 }
726 mlpp = &mlp->ml_next;
727 mlp = mlp->ml_next;
728 }
729 if (fnd) {
730 if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) {
731 syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST);
732 return;
733 }
734 mlp = mlhead;
735 while (mlp) {
736 fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp);
737 mlp = mlp->ml_next;
c2282441 738 }
e4fde528
KM
739 fclose(mlfile);
740 }
741}
742
743void add_mlist(hostp, dirp)
744 register char *hostp, *dirp;
745{
746 register struct mountlist *mlp, **mlpp;
747 FILE *mlfile;
748
749 mlpp = &mlhead;
750 mlp = mlhead;
751 while (mlp) {
752 if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp))
753 return;
754 mlpp = &mlp->ml_next;
755 mlp = mlp->ml_next;
756 }
757 mlp = (struct mountlist *)malloc(sizeof (*mlp));
758 strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN);
759 mlp->ml_host[RPCMNT_NAMELEN] = '\0';
760 strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN);
761 mlp->ml_dirp[RPCMNT_PATHLEN] = '\0';
762 mlp->ml_next = (struct mountlist *)0;
763 *mlpp = mlp;
764 if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) {
765 syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST);
766 return;
767 }
768 fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp);
769 fclose(mlfile);
770}
771
772/*
773 * This function is called via. SIGTERM when the system is going down.
774 * It sends a broadcast RPCMNT_UMNTALL.
775 */
776send_umntall()
777{
778 (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL,
779 xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each);
780 exit();
781}
782
783umntall_each(resultsp, raddr)
784 caddr_t resultsp;
785 struct sockaddr_in *raddr;
786{
787 return (1);
788}
789
790/*
791 * Free up an exports list component
792 */
793free_exp(ep)
794 register struct exportlist *ep;
795{
796 register struct grouplist *grp;
797 register char **addrp;
798 struct grouplist *grp2;
799
800 grp = ep->ex_groups;
801 while (grp != NULL) {
802 addrp = grp->gr_hp->h_addr_list;
803 while (*addrp)
804 free(*addrp++);
805 free((caddr_t)grp->gr_hp->h_addr_list);
806 free(grp->gr_hp->h_name);
807 free((caddr_t)grp->gr_hp);
808 grp2 = grp;
809 grp = grp->gr_next;
810 free((caddr_t)grp2);
c2282441 811 }
e4fde528 812 free((caddr_t)ep);
c2282441 813}