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