NEWSENDMAIL is the default
[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
2faf3d0a 6 * Herb Hasler and Rick Macklem at The University of Guelph.
e3ab21d9 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
c1ad7e36 18static char sccsid[] = "@(#)mountd.c 5.18 (Berkeley) %G%";
e3ab21d9
KM
19#endif not lint
20
2faf3d0a
KM
21#include <pwd.h>
22#include <grp.h>
23#include <unistd.h>
24#include <stdlib.h>
25#include <fcntl.h>
e3ab21d9 26#include <sys/param.h>
e3ab21d9
KM
27#include <sys/ioctl.h>
28#include <sys/stat.h>
c2282441 29#include <sys/file.h>
2faf3d0a 30#include <sys/ucred.h>
e3ab21d9
KM
31#include <sys/mount.h>
32#include <sys/socket.h>
e3ab21d9 33#include <sys/errno.h>
38dde0cd
KB
34#include <sys/signal.h>
35#include <stdio.h>
36#include <string.h>
37#include <syslog.h>
e3ab21d9
KM
38#include <netdb.h>
39#include <rpc/rpc.h>
40#include <rpc/pmap_clnt.h>
41#include <rpc/pmap_prot.h>
2faf3d0a
KM
42#ifdef ISO
43#include <netiso/iso.h>
44#endif
e3ab21d9
KM
45#include <nfs/rpcv2.h>
46#include <nfs/nfsv2.h>
c2282441 47#include "pathnames.h"
e3ab21d9 48
2faf3d0a
KM
49#define MNT_HOST 0
50#define MNT_GROUP 1
51#define MNT_ISO 2
52
53struct namelist {
54 char name[RPCMNT_NAMELEN+1];
55 struct namelist *next;
56};
57struct namegrp {
58 char gname[RPCMNT_NAMELEN+1];
59 struct namegrp *next;
60 struct namelist *names;
e3ab21d9
KM
61};
62/*
63 * Structures for keeping the mount list and export list
64 */
65struct mountlist {
e4fde528 66 struct mountlist *ml_next;
e3ab21d9
KM
67 char ml_host[RPCMNT_NAMELEN+1];
68 char ml_dirp[RPCMNT_PATHLEN+1];
69};
70
71struct exportlist {
72 struct exportlist *ex_next;
73 struct exportlist *ex_prev;
74 struct grouplist *ex_groups;
2faf3d0a 75 int ex_defset;
e3ab21d9
KM
76 char ex_dirp[RPCMNT_PATHLEN+1];
77};
78
2faf3d0a
KM
79union grouptypes {
80 struct hostent *gt_hostent;
81 struct groupnames *gt_grpname;
82#ifdef ISO
83 struct sockaddr_iso *gt_isoaddr;
84#endif
85};
86
e3ab21d9 87struct grouplist {
2faf3d0a
KM
88 int type;
89 int exflags;
90 struct ucred anoncr;
91 union grouptypes gr_ptr;
e3ab21d9 92 struct grouplist *gr_next;
2faf3d0a
KM
93};
94
95struct al_mnt {
96 struct al_mnt *al_next;
97 fsid_t al_mnted;
98};
99
100struct groupnames {
101 char gn_name[RPCMNT_NAMELEN+1];
102 struct grouplist *gn_glist;
103 struct groupnames *gn_next;
e3ab21d9
KM
104};
105
106/* Global defs */
04b79a9c 107int mntsrv(), umntall_each(), xdr_fhs(), xdr_mlist(), xdr_dir(), xdr_explist();
2faf3d0a
KM
108void get_exportlist(), send_umntall(), nextfield(), do_opt();
109void get_mountlist(), add_mlist(), del_mlist(), free_exp(), free_grp();
110void get_group(), get_host(), do_group();
111char *realpath();
112#ifdef ISO
113struct iso_addr *iso_addr();
114#endif
e3ab21d9 115struct exportlist exphead;
e4fde528 116struct mountlist *mlhead;
2faf3d0a 117struct groupnames *grpnames;
e3ab21d9 118char exname[MAXPATHLEN];
2faf3d0a
KM
119struct ucred def_anon = {
120 (u_short) 1,
121 (uid_t) -2,
122 1,
123 (gid_t) -2,
124};
e4fde528 125int root_only = 1;
e3ab21d9 126extern int errno;
2faf3d0a 127struct al_mnt *al_head = (struct al_mnt *)0;
e3ab21d9
KM
128#ifdef DEBUG
129int debug = 1;
44b35601
KM
130void SYSLOG __P((int, const char *, ...));
131#define syslog SYSLOG
e3ab21d9
KM
132#else
133int debug = 0;
134#endif
135
136/*
137 * Mountd server for NFS mount protocol as described in:
c2282441 138 * NFS: Network File System Protocol Specification, RFC1094, Appendix A
e4fde528 139 * The optional arguments are the exports file name
c2282441 140 * default: _PATH_EXPORTS
e4fde528 141 * and "-n" to allow nonroot mount.
e3ab21d9
KM
142 */
143main(argc, argv)
144 int argc;
e4fde528 145 char **argv;
e3ab21d9
KM
146{
147 SVCXPRT *transp;
e4fde528
KM
148 int c;
149 extern int optind;
150 extern char *optarg;
e3ab21d9 151
e4fde528
KM
152 while ((c = getopt(argc, argv, "n")) != EOF)
153 switch (c) {
154 case 'n':
155 root_only = 0;
156 break;
157 default:
158 fprintf(stderr, "Usage: mountd [-n] [export_file]\n");
159 exit(1);
160 };
161 argc -= optind;
162 argv += optind;
2faf3d0a 163 grpnames = (struct groupnames *)0;
e4fde528
KM
164 exphead.ex_next = exphead.ex_prev = (struct exportlist *)0;
165 mlhead = (struct mountlist *)0;
166 if (argc == 1) {
167 strncpy(exname, *argv, MAXPATHLEN-1);
168 exname[MAXPATHLEN-1] = '\0';
169 } else
170 strcpy(exname, _PATH_EXPORTS);
91e44e87 171 openlog("mountd:", LOG_PID, LOG_DAEMON);
2faf3d0a
KM
172 if (debug)
173 fprintf(stderr,"Getting export list.\n");
e4fde528 174 get_exportlist();
2faf3d0a
KM
175 if (debug)
176 fprintf(stderr,"Getting mount list.\n");
e4fde528 177 get_mountlist();
2faf3d0a
KM
178 if (debug)
179 fprintf(stderr,"Here we go.\n");
e3ab21d9 180 if (debug == 0) {
43d42ac6 181 daemon(0, 0);
e3ab21d9
KM
182 signal(SIGINT, SIG_IGN);
183 signal(SIGQUIT, SIG_IGN);
e3ab21d9 184 }
e3ab21d9 185 signal(SIGHUP, get_exportlist);
e4fde528 186 signal(SIGTERM, send_umntall);
ccb4677f
KM
187 { FILE *pidfile = fopen(_PATH_MOUNTDPID, "w");
188 if (pidfile != NULL) {
189 fprintf(pidfile, "%d\n", getpid());
190 fclose(pidfile);
191 }
192 }
e3ab21d9
KM
193 if ((transp = svcudp_create(RPC_ANYSOCK)) == NULL) {
194 syslog(LOG_ERR, "Can't create socket");
195 exit(1);
196 }
197 pmap_unset(RPCPROG_MNT, RPCMNT_VER1);
2faf3d0a
KM
198 if (!svc_register(transp, RPCPROG_MNT, RPCMNT_VER1, mntsrv,
199 IPPROTO_UDP)) {
e3ab21d9
KM
200 syslog(LOG_ERR, "Can't register mount");
201 exit(1);
202 }
203 svc_run();
204 syslog(LOG_ERR, "Mountd died");
43d42ac6 205 exit(1);
e3ab21d9
KM
206}
207
208/*
209 * The mount rpc service
210 */
211mntsrv(rqstp, transp)
212 register struct svc_req *rqstp;
213 register SVCXPRT *transp;
214{
e3ab21d9 215 register struct grouplist *grp;
c2282441
KM
216 register u_long **addrp;
217 register struct exportlist *ep;
e3ab21d9
KM
218 nfsv2fh_t nfh;
219 struct authunix_parms *ucr;
220 struct stat stb;
221 struct hostent *hp;
c2282441 222 u_long saddr;
2faf3d0a 223 char rpcpath[RPCMNT_PATHLEN+1], dirpath[MAXPATHLEN];
e3ab21d9 224 int bad = ENOENT;
2faf3d0a 225 int found, matched;
e3ab21d9 226 int omask;
c2282441 227 uid_t uid = -2;
e3ab21d9
KM
228
229 /* Get authorization */
230 switch (rqstp->rq_cred.oa_flavor) {
231 case AUTH_UNIX:
232 ucr = (struct authunix_parms *)rqstp->rq_clntcred;
c2282441
KM
233 uid = ucr->aup_uid;
234 break;
e3ab21d9
KM
235 case AUTH_NULL:
236 default:
c2282441 237 break;
e3ab21d9
KM
238 }
239
c2282441
KM
240 saddr = transp->xp_raddr.sin_addr.s_addr;
241 hp = (struct hostent *)0;
e3ab21d9 242 switch (rqstp->rq_proc) {
c2282441
KM
243 case NULLPROC:
244 if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
245 syslog(LOG_ERR, "Can't send reply");
246 return;
e3ab21d9 247 case RPCMNT_MOUNT:
2faf3d0a 248 if ((uid != 0 && root_only) || uid == -2) {
c2282441 249 svcerr_weakauth(transp);
e3ab21d9
KM
250 return;
251 }
2faf3d0a 252 if (!svc_getargs(transp, xdr_dir, rpcpath)) {
c2282441 253 svcerr_decode(transp);
e3ab21d9
KM
254 return;
255 }
256
2faf3d0a
KM
257 /*
258 * Get the real pathname and make sure it is a directory
259 * that exists.
260 */
261 if (realpath(rpcpath, dirpath) == 0 || stat(dirpath, &stb) < 0
262 || (stb.st_mode&S_IFMT) != S_IFDIR) {
263 chdir("/"); /* Just in case realpath doesn't */
264 if (debug)
265 fprintf(stderr,"stat failed on %s\n",dirpath);
e3ab21d9
KM
266 if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
267 syslog(LOG_ERR, "Can't send reply");
268 return;
269 }
270
e3ab21d9
KM
271 /* Check in the exports list */
272 omask = sigblock(sigmask(SIGHUP));
273 ep = exphead.ex_next;
2faf3d0a
KM
274 found = FALSE;
275 matched = FALSE;
276 while (ep != NULL && !found && !matched) {
277 struct grouplist *tgrp;
278 if (debug)
279 fprintf(stderr,"dirp=[%s]\n",ep->ex_dirp);
e3ab21d9 280 if (!strcmp(ep->ex_dirp, dirpath)) {
2faf3d0a
KM
281 if (ep->ex_defset)
282 grp = (struct grouplist *)0;
283 else
e3ab21d9 284 grp = ep->ex_groups;
2faf3d0a
KM
285 if (grp == NULL) {
286 if (debug)
287 fprintf(stderr,"grp is null\n");
288 found = TRUE;
289 }
290 while (grp && !found) {
291 matched = TRUE;
292 if (debug)
293 fprintf(stderr,"type = [%d]\n",grp->type);
294 if (grp->type == MNT_GROUP) {
295 tgrp = grp->gr_ptr.gt_grpname->gn_glist;
296 if (tgrp)
297 addrp = (u_long **)
298 tgrp->gr_ptr.gt_hostent->h_addr_list;
299 while(tgrp && !found) {
300 if (debug)
301 fprintf(stderr, "cmp [%d] [%d]\n",
302 **addrp,saddr);
303 if (**addrp == saddr) {
304 found = TRUE;
305 hp = tgrp->gr_ptr.gt_hostent;
306 break;
307 }
308 if (*++addrp == NULL) {
309 tgrp = tgrp->gr_next;
310 if (tgrp == NULL)
e3ab21d9 311 break;
2faf3d0a
KM
312 addrp = (u_long **)tgrp->
313 gr_ptr.gt_hostent->h_addr_list;
314 }
315 }
316 } else if (grp->type == MNT_HOST) {
317 addrp = (u_long **)
318 grp->gr_ptr.gt_hostent->h_addr_list;
319 while (*addrp) {
320 if (debug)
321 fprintf(stderr, "cmp [%d] [%d]\n",
322 **addrp,saddr);
323 if (**addrp == saddr) {
324 found = TRUE;
325 hp = grp->gr_ptr.gt_hostent;
326 break;
327 }
328 addrp++;
329 }
e3ab21d9 330 }
2faf3d0a
KM
331 grp = grp->gr_next;
332 }
e3ab21d9
KM
333 }
334 ep = ep->ex_next;
335 }
2faf3d0a 336 if (!found) {
e3ab21d9
KM
337 bad = EACCES;
338 if (!svc_sendreply(transp, xdr_long, (caddr_t)&bad))
339 syslog(LOG_ERR, "Can't send reply");
2faf3d0a 340 sigsetmask(omask);
e3ab21d9 341 return;
2faf3d0a
KM
342 } else {
343 /* Get the file handle */
344 bzero((caddr_t)&nfh, sizeof(nfh));
345 if (getfh(dirpath, (fhandle_t *)&nfh) < 0) {
346 bad = errno;
347 fprintf(stderr,
348 "Couldn't get file handle for %s.\n",
349 dirpath);
350 if (!svc_sendreply(transp, xdr_long,
351 (caddr_t)&bad))
352 syslog(LOG_ERR, "Can't send reply");
353 sigsetmask(omask);
354 return;
355 }
356 if (!svc_sendreply(transp, xdr_fhs, (caddr_t)&nfh))
e3ab21d9 357 syslog(LOG_ERR, "Can't send reply");
2faf3d0a
KM
358 if (hp == NULL)
359 hp = gethostbyaddr((caddr_t)&saddr,
360 sizeof(saddr), AF_INET);
361 if (hp)
362 add_mlist(hp->h_name, dirpath);
363 else
364 add_mlist(inet_ntoa(transp->xp_raddr.sin_addr),
365 dirpath);
366 if (debug)
367 fprintf(stderr,"Mount successfull.\n");
e3ab21d9 368 }
2faf3d0a 369 sigsetmask(omask);
e3ab21d9
KM
370 return;
371 case RPCMNT_DUMP:
372 if (!svc_sendreply(transp, xdr_mlist, (caddr_t)0))
373 syslog(LOG_ERR, "Can't send reply");
374 return;
375 case RPCMNT_UMOUNT:
2faf3d0a 376 if ((uid != 0 && root_only) || uid == -2) {
c2282441
KM
377 svcerr_weakauth(transp);
378 return;
379 }
e3ab21d9
KM
380 if (!svc_getargs(transp, xdr_dir, dirpath)) {
381 svcerr_decode(transp);
382 return;
383 }
e3ab21d9
KM
384 if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
385 syslog(LOG_ERR, "Can't send reply");
e4fde528
KM
386 hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);
387 if (hp)
388 del_mlist(hp->h_name, dirpath);
2faf3d0a 389 del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), dirpath);
e3ab21d9
KM
390 return;
391 case RPCMNT_UMNTALL:
2faf3d0a 392 if ((uid != 0 && root_only) || uid == -2) {
c2282441
KM
393 svcerr_weakauth(transp);
394 return;
395 }
e3ab21d9
KM
396 if (!svc_sendreply(transp, xdr_void, (caddr_t)0))
397 syslog(LOG_ERR, "Can't send reply");
e4fde528
KM
398 hp = gethostbyaddr((caddr_t)&saddr, sizeof(saddr), AF_INET);
399 if (hp)
400 del_mlist(hp->h_name, (char *)0);
2faf3d0a 401 del_mlist(inet_ntoa(transp->xp_raddr.sin_addr), (char *)0);
e3ab21d9
KM
402 return;
403 case RPCMNT_EXPORT:
404 if (!svc_sendreply(transp, xdr_explist, (caddr_t)0))
405 syslog(LOG_ERR, "Can't send reply");
406 return;
407 default:
408 svcerr_noproc(transp);
409 return;
410 }
411}
412
413/*
414 * Xdr conversion for a dirpath string
415 */
416xdr_dir(xdrsp, dirp)
417 XDR *xdrsp;
418 char *dirp;
419{
420 return (xdr_string(xdrsp, &dirp, RPCMNT_PATHLEN));
421}
422
423/*
424 * Xdr routine to generate fhstatus
425 */
426xdr_fhs(xdrsp, nfh)
427 XDR *xdrsp;
428 nfsv2fh_t *nfh;
429{
430 int ok = 0;
431
432 if (!xdr_long(xdrsp, &ok))
433 return (0);
e3ab21d9
KM
434 return (xdr_opaque(xdrsp, (caddr_t)nfh, NFSX_FH));
435}
436
437xdr_mlist(xdrsp, cp)
438 XDR *xdrsp;
439 caddr_t cp;
440{
e4fde528 441 register struct mountlist *mlp;
e3ab21d9
KM
442 int true = 1;
443 int false = 0;
444 char *strp;
445
e4fde528
KM
446 mlp = mlhead;
447 while (mlp) {
448 if (!xdr_bool(xdrsp, &true))
449 return (0);
450 strp = &mlp->ml_host[0];
451 if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
452 return (0);
453 strp = &mlp->ml_dirp[0];
454 if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
455 return (0);
456 mlp = mlp->ml_next;
e3ab21d9
KM
457 }
458 if (!xdr_bool(xdrsp, &false))
459 return (0);
460 return (1);
461}
462
463/*
464 * Xdr conversion for export list
465 */
466xdr_explist(xdrsp, cp)
467 XDR *xdrsp;
468 caddr_t cp;
469{
470 register struct exportlist *ep;
2faf3d0a 471 register struct grouplist *grp, *tgrp;
e3ab21d9
KM
472 int true = 1;
473 int false = 0;
474 char *strp;
475 int omask;
476
477 omask = sigblock(sigmask(SIGHUP));
478 ep = exphead.ex_next;
479 while (ep != NULL) {
480 if (!xdr_bool(xdrsp, &true))
481 goto errout;
482 strp = &ep->ex_dirp[0];
483 if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN))
484 goto errout;
485 grp = ep->ex_groups;
486 while (grp != NULL) {
2faf3d0a
KM
487 if (grp->type == MNT_GROUP) {
488 tgrp = grp->gr_ptr.gt_grpname->gn_glist;
489 while (tgrp) {
490 if (!xdr_bool(xdrsp, &true))
491 goto errout;
492 strp = tgrp->gr_ptr.gt_hostent->h_name;
493 if (!xdr_string(xdrsp, &strp,
494 RPCMNT_NAMELEN))
495 goto errout;
496 tgrp = tgrp->gr_next;
497 }
498 } else if (grp->type == MNT_HOST) {
499 if (!xdr_bool(xdrsp, &true))
500 goto errout;
501 strp = grp->gr_ptr.gt_hostent->h_name;
502 if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN))
503 goto errout;
504 }
e3ab21d9
KM
505 grp = grp->gr_next;
506 }
507 if (!xdr_bool(xdrsp, &false))
508 goto errout;
509 ep = ep->ex_next;
510 }
511 sigsetmask(omask);
512 if (!xdr_bool(xdrsp, &false))
513 return (0);
514 return (1);
515errout:
516 sigsetmask(omask);
517 return (0);
518}
519
520#define LINESIZ 10240
521char line[LINESIZ];
522
523/*
524 * Get the export list
525 */
04b79a9c 526void
e3ab21d9
KM
527get_exportlist()
528{
2faf3d0a
KM
529 struct grouplist *grp, *tgrp;
530 struct al_mnt *al_mp, *t_almp;
c2282441 531 register struct exportlist *ep, *ep2;
2faf3d0a
KM
532 struct groupnames *t_gn, *t_gn2;
533 struct ucred anoncr;
e3ab21d9
KM
534 FILE *inf;
535 char *cp, *endcp;
c2282441 536 char savedc;
2faf3d0a
KM
537 int len, dirplen, def_set;
538 int exflags;
e3ab21d9
KM
539
540 /*
541 * First, get rid of the old list
542 */
543 ep = exphead.ex_next;
544 while (ep != NULL) {
e3ab21d9
KM
545 ep2 = ep;
546 ep = ep->ex_next;
e4fde528 547 free_exp(ep2);
e3ab21d9 548 }
2faf3d0a
KM
549 exphead.ex_next = exphead.ex_prev = (struct exportlist *)0;
550
551 t_gn = grpnames;
552 while(t_gn != NULL) {
553 t_gn2 = t_gn;
554 t_gn = t_gn->gn_next;
555 free_grp(t_gn2);
556 }
557 grpnames = (struct groupnames *)0;
558
559 al_mp = al_head;
560 while (al_mp) {
561 t_almp = al_mp;
562 al_mp = al_mp->al_next;
563 free((caddr_t)t_almp);
564 }
565 al_head = (struct al_mnt *)0;
e3ab21d9
KM
566
567 /*
568 * Read in the exports file and build the list, calling
2faf3d0a 569 * mount() as we go along to push the export rules into the kernel.
e3ab21d9 570 */
e3ab21d9
KM
571 if ((inf = fopen(exname, "r")) == NULL) {
572 syslog(LOG_ERR, "Can't open %s", exname);
573 exit(2);
574 }
575 while (fgets(line, LINESIZ, inf)) {
2faf3d0a
KM
576 def_set = TRUE;
577 if (debug)
578 fprintf(stderr,"Got line %s\n",line);
e3ab21d9
KM
579 cp = line;
580 nextfield(&cp, &endcp);
2faf3d0a
KM
581 if (*cp == '#')
582 goto nextline;
583 if (*cp != '/') {
584 /* create group listing of names */
585 get_group(cp, ep);
586 goto nextline;
e4fde528 587 }
2faf3d0a
KM
588 exflags = MNT_EXPORTED;
589 anoncr = def_anon;
e4fde528
KM
590
591 /*
592 * Create new exports list entry
593 */
e3ab21d9
KM
594 len = endcp-cp;
595 if (len <= RPCMNT_PATHLEN && len > 0) {
2faf3d0a
KM
596 /*
597 * See if this directory is already in the list.
598 */
599 ep = exphead.ex_next;
600 while (ep) {
601 if (!strcmp(ep->ex_dirp, cp))
602 break;
603 ep = ep->ex_next;
604 }
605 if (ep == (struct exportlist *)0) {
606 ep = (struct exportlist *)malloc(sizeof(*ep));
607 if (ep == NULL)
608 goto err;
609 ep->ex_next = (struct exportlist *)0;
610 ep->ex_prev = (struct exportlist *)0;
611 ep->ex_groups = (struct grouplist *)0;
612 ep->ex_defset = FALSE;
613 bcopy(cp, ep->ex_dirp, len);
614 ep->ex_dirp[len] = '\0';
615 }
e4fde528 616 dirplen = len;
2faf3d0a
KM
617 if (debug)
618 fprintf(stderr, "Making new ep. [%s]\n",
619 ep->ex_dirp);
5b83dcdd 620 } else {
2faf3d0a
KM
621 syslog(LOG_ERR, "Bad Exports File line: %s\n", line);
622 goto nextline;
5b83dcdd 623 }
e3ab21d9
KM
624 cp = endcp;
625 nextfield(&cp, &endcp);
626 len = endcp-cp;
627 while (len > 0) {
c2282441
KM
628 savedc = *endcp;
629 *endcp = '\0';
5b83dcdd
KM
630 if (len > RPCMNT_NAMELEN)
631 goto more;
632 if (*cp == '-') {
2faf3d0a
KM
633 do_opt(cp + 1, ep, &exflags, &anoncr);
634 exflags |= MNT_EXPORTED;
635 def_set = TRUE;
636 if (debug)
637 fprintf(stderr, "got r=%d, ex=%d\n",
638 anoncr.cr_uid,exflags);
5b83dcdd 639 goto more;
2faf3d0a
KM
640 } else {
641 def_set = FALSE;
642 if (*cp == '$') {
643 do_group(cp + 1, endcp, &grp);
644 grp->type = MNT_GROUP;
645 } else {
646 get_host(cp, endcp, ep, &grp);
647 }
648 if (grp != NULL) {
649 grp->exflags = exflags;
650 grp->anoncr = anoncr;
651 grp->gr_next = ep->ex_groups;
652 ep->ex_groups = grp;
e3ab21d9
KM
653 }
654 }
5b83dcdd 655 more:
e3ab21d9 656 cp = endcp;
c2282441 657 *cp = savedc;
e3ab21d9 658 nextfield(&cp, &endcp);
5b83dcdd 659 len = endcp - cp;
e3ab21d9 660 }
2faf3d0a
KM
661 if (def_set == TRUE) {
662 if (ep->ex_defset == TRUE)
663 syslog(LOG_ERR, "Default specified again dir:%s\n",
664 ep->ex_dirp);
665 else {
666 struct hostent *hpe;
667
668 ep->ex_defset = TRUE;
669 if (debug)
670 fprintf(stderr,"Adding a default entry\n");
671 /* add a default group and make the grp list NULL */
672 hpe = (struct hostent *)malloc(sizeof(struct hostent));
673 if (hpe == NULL) {
674 syslog(LOG_ERR,"No more memory: mountd Failed");
675 exit(2);
676 }
677 tgrp = (struct grouplist *)
678 malloc(sizeof(struct grouplist));
679 if (tgrp == NULL) {
680 syslog(LOG_ERR,"No more memory: mountd Failed");
681 exit(2);
682 }
683 tgrp->anoncr = anoncr;
684 tgrp->exflags = exflags;
0fe25249
KM
685 tgrp->type = MNT_HOST;
686 hpe->h_name = (char *)0;
2faf3d0a
KM
687 hpe->h_addrtype = AF_INET;
688 hpe->h_length = sizeof (u_long);
0fe25249 689 hpe->h_addr_list = (char **)0;
2faf3d0a
KM
690 tgrp->gr_ptr.gt_hostent = hpe;
691 tgrp->gr_next = ep->ex_groups;
692 ep->ex_groups = tgrp;
693 }
694 }
695 grp = ep->ex_groups;
696 while (grp != NULL) {
697 exflags = grp->exflags;
698 anoncr = grp->anoncr;
699 if (grp->type == MNT_GROUP) {
700 tgrp = grp->gr_ptr.gt_grpname->gn_glist;
701 while(tgrp != NULL) {
702 if (do_mount(ep, tgrp, exflags, &anoncr,
703 dirplen) == FALSE)
704 goto nextline;
705 tgrp = tgrp->gr_next;
706 }
707 } else {
708 if (do_mount(ep, grp, exflags, &anoncr, dirplen)
709 == FALSE)
710 goto nextline;
711 }
712 grp = grp->gr_next;
713 }
714 if (cp)
715 *cp = savedc;
716 if (ep->ex_prev == (struct exportlist *)0) {
717 ep->ex_next = exphead.ex_next;
718 ep->ex_prev = &exphead;
719 if (ep->ex_next != NULL)
720 ep->ex_next->ex_prev = ep;
721 exphead.ex_next = ep;
722 }
723nextline:
724 ;
725 }
726 fclose(inf);
727 return;
728err:
729 syslog(LOG_ERR, "No more memory: mountd Failed");
730 exit(2);
731}
732
733do_mount(ep, grp, exflags, anoncrp, dirplen)
734 struct exportlist *ep;
735 struct grouplist *grp;
736 int exflags, dirplen;
737 struct ucred *anoncrp;
738{
739 int done, found;
740 register u_long **addrp;
741 struct sockaddr_in sin;
742 struct statfs stfsbuf;
743 struct ufs_args args, targs;
744 struct al_mnt *al_mp;
745 char *cp, savedc;
746
747 args.fspec = 0;
748 args.exflags = exflags;
749 args.anon = *anoncrp;
750 sin.sin_family = AF_INET;
751 sin.sin_port = 0;
752 sin.sin_len = sizeof(sin);
753 if (grp->type == MNT_HOST)
754 addrp = (u_long **)grp->gr_ptr.gt_hostent->h_addr_list;
755 done = FALSE;
756 while(!done) {
757 if (grp->type == MNT_HOST) {
0fe25249 758 if (grp->gr_ptr.gt_hostent->h_name)
2faf3d0a 759 sin.sin_addr.s_addr = **addrp;
0fe25249
KM
760 else
761 sin.sin_addr.s_addr = INADDR_ANY;
2faf3d0a
KM
762 args.saddr = (struct sockaddr *)&sin;
763 args.slen = sizeof(sin);
764#ifdef ISO
765 } else if (grp->type == MNT_ISO) {
766 args.saddr = (struct sockaddr *)grp->gr_ptr.gt_isoaddr;
767 args.slen = sizeof (struct sockaddr_iso);
768#endif /* ISO */
769 } else {
770 syslog(LOG_ERR, "Bad grouptype");
771 free_exp(ep);
772 return (FALSE);
773 }
774 if (statfs(ep->ex_dirp, &stfsbuf) < 0) {
775 if (debug) {
776 fprintf(stderr,"statfs failed.\n");
777 }
778 syslog(LOG_ERR, "Invalid path: %s", ep->ex_dirp);
779 free_exp(ep);
780 return(FALSE);
781 }
782 found = FALSE;
783 for (al_mp = al_head; al_mp && !found; al_mp = al_mp->al_next)
784 if (al_mp->al_mnted.val[0] == stfsbuf.f_fsid.val[0] &&
785 al_mp->al_mnted.val[1] == stfsbuf.f_fsid.val[1])
786 found = TRUE;
787 if (!found) {
788 /* first time for fs, so must send a MNT_DELEXPORT
789 * to clear the old export list held in the kernel
790 * for this fs.
791 */
792 al_mp = (struct al_mnt *)malloc(sizeof (struct al_mnt));
793 al_mp->al_mnted = stfsbuf.f_fsid;
794 al_mp->al_next = al_head;
795 al_head = al_mp;
796 targs.fspec = 0;
797 targs.exflags = MNT_DELEXPORT;
e4fde528 798 cp = (char *)0;
2faf3d0a
KM
799 while (mount(MOUNT_UFS, ep->ex_dirp,
800 stfsbuf.f_flags | MNT_UPDATE, &targs) < 0) {
801 if (debug) {
802 fprintf(stderr,
803 "tried [%s][%d]\n",
804 ep->ex_dirp,errno);
805 }
e4fde528
KM
806 if (cp == NULL)
807 cp = ep->ex_dirp + dirplen - 1;
808 else
809 *cp = savedc;
2faf3d0a 810 cp--;
e4fde528
KM
811 /* back up over the last component */
812 while (*cp == '/' && cp > ep->ex_dirp)
813 cp--;
814 while (*(cp - 1) != '/' && cp > ep->ex_dirp)
815 cp--;
816 if (cp == ep->ex_dirp) {
2faf3d0a
KM
817 if (debug) {
818 fprintf(stderr,"mnt unsucc\n");
819 }
820 syslog(LOG_ERR,
821 "Can't export %s", ep->ex_dirp);
e4fde528 822 free_exp(ep);
2faf3d0a 823 return(FALSE);
e4fde528
KM
824 }
825 savedc = *cp;
826 *cp = '\0';
827 }
2faf3d0a 828 if (cp != NULL) {
e4fde528 829 *cp = savedc;
2faf3d0a
KM
830 }
831 }
832 cp = (char *)0;
833 while (mount(MOUNT_UFS, ep->ex_dirp,
834 stfsbuf.f_flags | MNT_UPDATE, &args) < 0) {
835 if (errno == EPERM) {
836 syslog(LOG_ERR,
837 "Can't change attributes for %s.\n",
838 ep->ex_dirp);
839 if (cp != NULL)
840 *cp = savedc;
841 break;
842 }
843 if (cp == NULL)
844 cp = ep->ex_dirp + dirplen - 1;
845 else
846 *cp = savedc;
847 cp--;
848 /* back up over the last component */
849 while (*cp == '/' && cp > ep->ex_dirp)
850 cp--;
851 while (*(cp - 1) != '/' && cp > ep->ex_dirp)
852 cp--;
853 if (cp == ep->ex_dirp) {
854 if (debug) {
855 fprintf(stderr,"mnt unsucc\n");
856 }
857 syslog(LOG_ERR, "Can't export %s", ep->ex_dirp);
858 free_exp(ep);
859 return(FALSE);
860 }
861 savedc = *cp;
862 *cp = '\0';
863 }
864 if (addrp == NULL)
865 done = TRUE;
866 else {
867 ++addrp;
868 if (*addrp == NULL)
869 done = TRUE;
870 }
871 if (cp != NULL)
872 *cp = savedc;
e3ab21d9 873 }
2faf3d0a 874 return(TRUE);
e3ab21d9
KM
875}
876
2faf3d0a 877
e3ab21d9
KM
878/*
879 * Parse out the next white space separated field
880 */
2faf3d0a 881void
e3ab21d9
KM
882nextfield(cp, endcp)
883 char **cp;
884 char **endcp;
885{
886 register char *p;
887
888 p = *cp;
889 while (*p == ' ' || *p == '\t')
890 p++;
891 if (*p == '\n' || *p == '\0') {
892 *cp = *endcp = p;
893 return;
894 }
895 *cp = p++;
896 while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
897 p++;
898 *endcp = p;
899}
c2282441
KM
900
901/*
e4fde528 902 * Parse the option string
c2282441 903 */
2faf3d0a
KM
904void
905do_opt(cpopt, ep, exflagsp, cr)
e4fde528 906 register char *cpopt;
2faf3d0a
KM
907 struct exportlist *ep;
908 int *exflagsp;
909 struct ucred *cr;
c2282441 910{
e4fde528 911 register char *cpoptarg, *cpoptend;
0fe25249 912 int allflag = 1;
e4fde528
KM
913
914 while (cpopt && *cpopt) {
915 if (cpoptend = index(cpopt, ','))
916 *cpoptend++ = '\0';
917 if (cpoptarg = index(cpopt, '='))
918 *cpoptarg++ = '\0';
919 if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) {
2faf3d0a
KM
920 *exflagsp |= MNT_EXRDONLY;
921 } else if ((!strcmp(cpopt, "root") || !strcmp(cpopt, "r") ||
c1ad7e36 922 !(allflag = strcmp(cpopt, "all"))) && cpoptarg) {
2faf3d0a
KM
923 parsecred(cpoptarg, cr);
924 if (allflag == 0)
925 *exflagsp |= MNT_EXPORTANON;
926 } else if (!strcmp(cpopt, "kerb") || !strcmp(cpopt, "k")) {
927 *exflagsp |= MNT_EXKERB;
e4fde528 928 } else
2faf3d0a 929 syslog(LOG_ERR, "opt %s ignored for %s", cpopt,
e4fde528
KM
930 ep->ex_dirp);
931 cpopt = cpoptend;
932 }
933}
934
2faf3d0a
KM
935/*
936 * Parse a description of a credential.
937 */
938parsecred(namelist, cr)
939 char *namelist;
940 register struct ucred *cr;
941{
942 register char *name;
943 register int cnt;
944 char *names;
945 struct passwd *pw;
946 struct group *gr;
947 int ngroups, groups[NGROUPS + 1];
948
949 /*
950 * Set up the unpriviledged user.
951 */
952 cr->cr_ref = 1;
953 cr->cr_uid = -2;
954 cr->cr_groups[0] = -2;
955 cr->cr_ngroups = 1;
956 /*
957 * Get the user's password table entry.
958 */
959 names = strsep(&namelist, " \t\n");
960 name = strsep(&names, ":");
961 if (isdigit(*name) || *name == '-')
962 pw = getpwuid(atoi(name));
963 else
964 pw = getpwnam(name);
965 /*
966 * Credentials specified as those of a user.
967 */
968 if (names == NULL) {
969 if (pw == NULL) {
970 syslog(LOG_ERR, "Unknown user: %s\n", name);
971 return;
972 }
973 cr->cr_uid = pw->pw_uid;
974 ngroups = NGROUPS + 1;
975 if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups))
976 syslog(LOG_ERR, "Too many groups\n");
977 /*
978 * Convert from int's to gid_t's and compress out duplicate
979 */
980 cr->cr_ngroups = ngroups - 1;
981 cr->cr_groups[0] = groups[0];
982 for (cnt = 2; cnt < ngroups; cnt++)
983 cr->cr_groups[cnt - 1] = groups[cnt];
984 return;
985 }
986 /*
987 * Explicit credential specified as a colon separated list:
988 * uid:gid:gid:...
989 */
990 if (pw != NULL)
991 cr->cr_uid = pw->pw_uid;
992 else if (isdigit(*name) || *name == '-')
993 cr->cr_uid = atoi(name);
994 else {
995 syslog(LOG_ERR, "Unknown user: %s\n", name);
996 return;
997 }
998 cr->cr_ngroups = 0;
999 while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS) {
1000 name = strsep(&names, ":");
1001 if (isdigit(*name) || *name == '-') {
1002 cr->cr_groups[cr->cr_ngroups++] = atoi(name);
1003 } else {
1004 if ((gr = getgrnam(name)) == NULL) {
1005 syslog(LOG_ERR, "Unknown group: %s\n", name);
1006 continue;
1007 }
1008 cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid;
1009 }
1010 }
1011 if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS)
1012 syslog(LOG_ERR, "Too many groups\n");
1013}
1014
e4fde528
KM
1015#define STRSIZ (RPCMNT_NAMELEN+RPCMNT_PATHLEN+50)
1016/*
1017 * Routines that maintain the remote mounttab
1018 */
2faf3d0a
KM
1019void
1020get_mountlist()
e4fde528
KM
1021{
1022 register struct mountlist *mlp, **mlpp;
1023 register char *eos, *dirp;
1024 int len;
1025 char str[STRSIZ];
1026 FILE *mlfile;
1027
0fe25249 1028 if ((mlfile = fopen(_PATH_RMOUNTLIST, "r")) == NULL) {
2faf3d0a 1029 syslog(LOG_ERR, "Can't open %s", _PATH_RMOUNTLIST);
e4fde528
KM
1030 return;
1031 }
1032 mlpp = &mlhead;
1033 while (fgets(str, STRSIZ, mlfile) != NULL) {
1034 if ((dirp = index(str, '\t')) == NULL &&
1035 (dirp = index(str, ' ')) == NULL)
1036 continue;
1037 mlp = (struct mountlist *)malloc(sizeof (*mlp));
1038 len = dirp-str;
1039 if (len > RPCMNT_NAMELEN)
1040 len = RPCMNT_NAMELEN;
1041 bcopy(str, mlp->ml_host, len);
1042 mlp->ml_host[len] = '\0';
1043 while (*dirp == '\t' || *dirp == ' ')
1044 dirp++;
1045 if ((eos = index(dirp, '\t')) == NULL &&
1046 (eos = index(dirp, ' ')) == NULL &&
1047 (eos = index(dirp, '\n')) == NULL)
1048 len = strlen(dirp);
1049 else
1050 len = eos-dirp;
1051 if (len > RPCMNT_PATHLEN)
1052 len = RPCMNT_PATHLEN;
1053 bcopy(dirp, mlp->ml_dirp, len);
1054 mlp->ml_dirp[len] = '\0';
1055 mlp->ml_next = (struct mountlist *)0;
1056 *mlpp = mlp;
1057 mlpp = &mlp->ml_next;
1058 }
1059 fclose(mlfile);
1060}
1061
2faf3d0a
KM
1062void
1063del_mlist(hostp, dirp)
e4fde528
KM
1064 register char *hostp, *dirp;
1065{
1066 register struct mountlist *mlp, **mlpp;
0fe25249 1067 struct mountlist *mlp2;
e4fde528
KM
1068 FILE *mlfile;
1069 int fnd = 0;
1070
1071 mlpp = &mlhead;
1072 mlp = mlhead;
1073 while (mlp) {
1074 if (!strcmp(mlp->ml_host, hostp) &&
1075 (!dirp || !strcmp(mlp->ml_dirp, dirp))) {
1076 fnd = 1;
0fe25249
KM
1077 mlp2 = mlp;
1078 *mlpp = mlp = mlp->ml_next;
1079 free((caddr_t)mlp2);
1080 } else {
1081 mlpp = &mlp->ml_next;
1082 mlp = mlp->ml_next;
e4fde528 1083 }
e4fde528
KM
1084 }
1085 if (fnd) {
1086 if ((mlfile = fopen(_PATH_RMOUNTLIST, "w")) == NULL) {
2faf3d0a 1087 syslog(LOG_WARNING,"Can't update %s", _PATH_RMOUNTLIST);
e4fde528
KM
1088 return;
1089 }
1090 mlp = mlhead;
1091 while (mlp) {
1092 fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp);
1093 mlp = mlp->ml_next;
c2282441 1094 }
e4fde528
KM
1095 fclose(mlfile);
1096 }
1097}
1098
2faf3d0a
KM
1099void
1100add_mlist(hostp, dirp)
e4fde528
KM
1101 register char *hostp, *dirp;
1102{
1103 register struct mountlist *mlp, **mlpp;
1104 FILE *mlfile;
1105
1106 mlpp = &mlhead;
1107 mlp = mlhead;
1108 while (mlp) {
1109 if (!strcmp(mlp->ml_host, hostp) && !strcmp(mlp->ml_dirp, dirp))
1110 return;
1111 mlpp = &mlp->ml_next;
1112 mlp = mlp->ml_next;
1113 }
1114 mlp = (struct mountlist *)malloc(sizeof (*mlp));
1115 strncpy(mlp->ml_host, hostp, RPCMNT_NAMELEN);
1116 mlp->ml_host[RPCMNT_NAMELEN] = '\0';
1117 strncpy(mlp->ml_dirp, dirp, RPCMNT_PATHLEN);
1118 mlp->ml_dirp[RPCMNT_PATHLEN] = '\0';
1119 mlp->ml_next = (struct mountlist *)0;
1120 *mlpp = mlp;
1121 if ((mlfile = fopen(_PATH_RMOUNTLIST, "a")) == NULL) {
1122 syslog(LOG_WARNING, "Can't update %s", _PATH_RMOUNTLIST);
1123 return;
1124 }
1125 fprintf(mlfile, "%s %s\n", mlp->ml_host, mlp->ml_dirp);
1126 fclose(mlfile);
1127}
1128
1129/*
1130 * This function is called via. SIGTERM when the system is going down.
1131 * It sends a broadcast RPCMNT_UMNTALL.
1132 */
04b79a9c 1133void
e4fde528
KM
1134send_umntall()
1135{
1136 (void) clnt_broadcast(RPCPROG_MNT, RPCMNT_VER1, RPCMNT_UMNTALL,
1137 xdr_void, (caddr_t)0, xdr_void, (caddr_t)0, umntall_each);
2faf3d0a 1138 exit(0);
e4fde528
KM
1139}
1140
1141umntall_each(resultsp, raddr)
1142 caddr_t resultsp;
1143 struct sockaddr_in *raddr;
1144{
1145 return (1);
1146}
1147
1148/*
1149 * Free up an exports list component
1150 */
2faf3d0a 1151void
e4fde528
KM
1152free_exp(ep)
1153 register struct exportlist *ep;
1154{
1155 register struct grouplist *grp;
e4fde528
KM
1156 struct grouplist *grp2;
1157
1158 grp = ep->ex_groups;
1159 while (grp != NULL) {
e4fde528
KM
1160 grp2 = grp;
1161 grp = grp->gr_next;
2faf3d0a 1162 free_grp(grp2);
c2282441 1163 }
e4fde528 1164 free((caddr_t)ep);
c2282441 1165}
2faf3d0a
KM
1166
1167/*
1168 * Free up a group list.
1169 */
1170void
1171free_grp(grp)
1172 register struct grouplist *grp;
1173{
1174 register char **addrp;
1175
1176 if (grp->type == MNT_HOST) {
0fe25249
KM
1177 if (grp->gr_ptr.gt_hostent->h_name) {
1178 addrp = grp->gr_ptr.gt_hostent->h_addr_list;
1179 while (addrp && *addrp)
1180 free(*addrp++);
1181 free((caddr_t)grp->gr_ptr.gt_hostent->h_addr_list);
1182 free(grp->gr_ptr.gt_hostent->h_name);
1183 }
2faf3d0a
KM
1184 free((caddr_t)grp->gr_ptr.gt_hostent);
1185 }
1186#ifdef ISO
1187 else if (grp->type == MNT_ISO)
1188 free((caddr_t)grp->gr_ptr.gt_isoaddr);
1189#endif
1190 free((caddr_t)grp);
1191}
1192
1193void
1194get_group(line, ep)
1195 char *line;
1196 struct export_list *ep;
1197{
1198 int done;
1199 struct grouplist *grp;
1200 struct groupnames *t_gn;
1201 char *cp, *endcp, savedc;
1202
1203 cp = line;
1204 nextfield(&cp, &endcp);
1205 savedc = *endcp;
1206 *endcp = NULL;
1207 if (*(endcp-1) == '=') {
1208 *(endcp-1) = NULL;
1209 }
1210 /* check to see if this group exists already */
1211 t_gn = grpnames;
1212 while(t_gn != NULL) {
1213 if (strcmp(t_gn->gn_name,cp) == 0) {
1214 syslog(LOG_ERR,"Group redifined, second ignored.");
1215 return;
1216 }
1217 t_gn = t_gn->gn_next;
1218 }
1219
1220 /* make a new group list entry */
1221 t_gn = (struct groupnames *)malloc(sizeof(struct groupnames));
1222 if (t_gn == NULL) {
1223 syslog(LOG_ERR,"Group: Couldn't Malloc.");
1224 exit(2);
1225 }
1226 strcpy(t_gn->gn_name,cp);
1227 t_gn->gn_next = grpnames;
1228 grpnames = t_gn;
1229 t_gn->gn_glist = NULL;
1230 *endcp = savedc;
1231 cp = endcp;
1232 done = FALSE;
1233 while(!done) {
1234 nextfield(&cp, &endcp);
1235 if (cp == endcp)
1236 done = TRUE;
1237 else {
1238 savedc = *endcp;
1239 *endcp = NULL;
1240 if (strcmp(cp, "=")) {
1241 /* add to group list */
1242 get_host(cp, endcp, ep, &grp);
1243 if (grp != NULL) {
1244 grp->gr_next = t_gn->gn_glist;
1245 t_gn->gn_glist = grp;
1246 }
1247 }
1248 *endcp = savedc;
1249 cp = endcp;
1250 }
1251 }
1252}
1253
1254void
1255get_host(cp, endcp, ep, gp)
1256 char *cp, *endcp;
1257 struct exportlist *ep;
1258 struct grouplist **gp;
1259{
1260 register struct hostent *hp, *nhp;
1261 register struct grouplist *grp;
1262 register char **addrp, **naddrp;
1263 struct hostent t_host;
1264 int i;
1265 u_long saddr;
1266 char *aptr[2];
1267#ifdef ISO
1268 struct iso_addr *isop;
1269 struct sockaddr_iso *isoaddr;
1270#endif
1271
1272 if (isdigit(*cp)) {
1273 saddr = inet_addr(cp);
1274 if (saddr == -1) {
1275 syslog(LOG_ERR,
1276 "Bad Exports File, %s: %s", cp,
1277 "inet_addr failed, ignored");
1278 *gp = NULL;
1279 return;
1280 }
1281 hp = &t_host;
1282 hp->h_name = cp;
1283 hp->h_addrtype = AF_INET;
1284 hp->h_length = sizeof (u_long);
1285 hp->h_addr_list = aptr;
1286 aptr[0] = (char *)&saddr;
1287 aptr[1] = (char *)0;
1288#ifdef ISO
1289 } else if (!strncmp(cp, "iso=", 4)) {
1290 if ((isop = iso_addr(cp + 4)) == NULL) {
1291 syslog(LOG_ERR,
1292 "Bad Exports File, %s: %s", cp,
1293 "iso_addr failed, ignored");
1294 *gp = NULL;
1295 return;
1296 }
1297 isoaddr = (struct sockaddr_iso *)
1298 malloc(sizeof (struct sockaddr_iso));
1299 if (isoaddr == NULL)
1300 goto err1;
1301 bzero((caddr_t)isoaddr, sizeof (struct sockaddr_iso));
1302 bcopy((caddr_t)isop, (caddr_t)isoaddr->siso_addr,
1303 sizeof (struct iso_addr));
1304 isoaddr->siso_len = sizeof (struct sockaddr_iso);
1305 isoaddr->siso_family = AF_ISO;
1306 grp = (struct grouplist *)
1307 malloc(sizeof(struct grouplist));
1308 if (grp == NULL)
1309 goto err1;
1310 grp->type = MNT_ISO;
1311 grp->gr_ptr.gt_isoaddr = isoaddr;
1312 *gp = grp;
1313 return;
1314#endif /* ISO */
1315 } else if ((hp = gethostbyname(cp)) == NULL) {
1316 syslog(LOG_ERR, "Bad Exports File, %s: %s",
1317 cp, "Gethostbyname failed, ignored");
1318 *gp = NULL;
1319 return;
1320 }
1321 grp = (struct grouplist *)
1322 malloc(sizeof(struct grouplist));
1323 if (grp == NULL)
1324 goto err1;
1325 grp->type = MNT_HOST;
1326 nhp = grp->gr_ptr.gt_hostent = (struct hostent *)
1327 malloc(sizeof(struct hostent));
1328 if (nhp == NULL)
1329 goto err1;
1330 bcopy((caddr_t)hp, (caddr_t)nhp,
1331 sizeof(struct hostent));
1332 i = strlen(hp->h_name)+1;
1333 nhp->h_name = (char *)malloc(i);
1334 if (nhp->h_name == NULL)
1335 goto err1;
1336 bcopy(hp->h_name, nhp->h_name, i);
1337 addrp = hp->h_addr_list;
1338 i = 1;
1339 while (*addrp++)
1340 i++;
1341 naddrp = nhp->h_addr_list = (char **)
1342 malloc(i*sizeof(char *));
1343 if (naddrp == NULL)
1344 goto err1;
1345 addrp = hp->h_addr_list;
1346 while (*addrp) {
1347 *naddrp = (char *)
1348 malloc(hp->h_length);
1349 if (*naddrp == NULL)
1350 goto err1;
1351 bcopy(*addrp, *naddrp,
1352 hp->h_length);
1353 addrp++;
1354 naddrp++;
1355 }
1356 *naddrp = (char *)0;
1357 *gp = grp;
1358 return;
1359err1:
1360 syslog(LOG_ERR, "No more memory: mountd Failed");
1361 exit(2);
1362}
1363
1364void
1365do_group(cp, endcp, gp)
1366 char *cp, *endcp;
1367 struct grouplist **gp;
1368{
1369 int found;
1370 struct groupnames *t_gn;
1371
1372 t_gn = grpnames;
1373 found = FALSE;
1374 while((t_gn != NULL) && !found) {
1375 if(strcmp(t_gn->gn_name,cp) == 0) {
1376 found = TRUE;
1377 *gp = (struct grouplist *)
1378 malloc(sizeof(struct grouplist));
1379 if (*gp == NULL) {
1380 syslog(LOG_ERR,"No more memory: mountd Failed");
1381 exit(2);
1382 }
1383 (*gp)->gr_ptr.gt_grpname = (struct groupnames *)
1384 malloc(sizeof(struct groupnames));
1385 if ((*gp)->gr_ptr.gt_grpname == NULL) {
1386 syslog(LOG_ERR,"No more memory: mountd Failed");
1387 exit(2);
1388 }
1389 (*gp)->gr_ptr.gt_grpname->gn_glist = t_gn->gn_glist;
1390 return;
1391 }
1392 t_gn = t_gn->gn_next;
1393 }
1394 *gp = NULL;
1395}
1396
1397/*
1398 * char *realpath(const char *path, char resolved_path[MAXPATHLEN])
1399 *
1400 * find the real name of path, by removing all ".", ".."
1401 * and symlink components.
1402 *
1403 * Jan-Simon Pendry, September 1991.
1404 */
1405char *
1406realpath(path, resolved)
1407 char *path;
1408 char resolved[MAXPATHLEN];
1409{
1410 int d = open(".", O_RDONLY);
1411 int rootd = 0;
1412 char *p, *q;
1413 struct stat stb;
1414 char wbuf[MAXPATHLEN];
1415
1416 strcpy(resolved, path);
1417
1418 if (d < 0)
1419 return 0;
1420
1421loop:;
1422 q = strrchr(resolved, '/');
1423 if (q) {
1424 p = q + 1;
1425 if (q == resolved)
1426 q = "/";
1427 else {
1428 do
1429 --q;
1430 while (q > resolved && *q == '/');
1431 q[1] = '\0';
1432 q = resolved;
1433 }
1434 if (chdir(q) < 0)
1435 goto out;
1436 } else
1437 p = resolved;
1438
1439 if (lstat(p, &stb) == 0) {
1440 if (S_ISLNK(stb.st_mode)) {
1441 int n = readlink(p, resolved, MAXPATHLEN);
1442 if (n < 0)
1443 goto out;
1444 resolved[n] = '\0';
1445 goto loop;
1446 }
1447 if (S_ISDIR(stb.st_mode)) {
1448 if (chdir(p) < 0)
1449 goto out;
1450 p = "";
1451 }
1452 }
1453
1454 strcpy(wbuf, p);
1455 if (getcwd(resolved, MAXPATHLEN) == 0)
1456 goto out;
1457 if (resolved[0] == '/' && resolved[1] == '\0')
1458 rootd = 1;
1459
1460 if (*wbuf) {
1461 if (strlen(resolved) + strlen(wbuf) + rootd + 1 > MAXPATHLEN) {
1462 errno = ENAMETOOLONG;
1463 goto out;
1464 }
1465 if (rootd == 0)
1466 strcat(resolved, "/");
1467 strcat(resolved, wbuf);
1468 }
1469
1470 if (fchdir(d) < 0)
1471 goto out;
1472 (void) close(d);
1473
1474 return resolved;
1475
1476out:;
1477 (void) close(d);
1478 return 0;
1479}
44b35601
KM
1480
1481#ifdef DEBUG
1482void
1483SYSLOG(int pri, const char *fmt, ...)
1484{
1485 va_list ap;
1486
1487 va_start(ap, fmt);
1488 vfprintf(stderr, fmt, ap);
1489 va_end(ap);
1490}
1491#endif /* DEBUG */