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