V10/netfs/libnetb/fsmkidmap.c

Compare this file to the similar file:
Show the results in this format:

/*
 * make an ID map for the file server library
 * takes a /etc/passwd-like file and an optional `exception' list
 * of explicit mappings;
 * returns a list of local name-ID mappings to be combined
 * with those from the client to make an ID-ID map.
 */

#include <stdio.h>
#include <ctype.h>
#include "rf.h"

static Idmap *exmerge();
static int nextid();

extern char *malloc(), *realloc();

Idmap *
rfmkidmap(file, ex)
char *file;
Namemap *ex;
{
	Idmap *map;
	register Idmap *cur;
	register int size;
	register Idmap *last;
	int curoff;
	FILE *fp;

	if ((fp = fopen(file, "r")) == NULL)
		rfpanic("can't open map %s\n", file);
	size = 100;
	if ((map = (Idmap *)malloc(size*sizeof(Idmap))) == NULL)
		rfpanic("out of mem for %s map\n", file);
	last = &map[size - 1];
	for (cur = map;; cur++) {
		if (cur >= last) {
			curoff = cur - map;	/* realloc may move map */
			size += 100;
			if ((map = (Idmap *)realloc((char *)map, size*sizeof(Idmap))) == NULL)
				rfpanic("out of mem for %s map\n", file);
			last = &map[size - 1];
			cur = &map[curoff];
		}
		if (nextid(cur, fp) == 0)
			break;
	}
	cur->name[0] = 0;
	fclose(fp);
	return (exmerge(map, last, ex));
}

/*
 * pick out the next name and ID from the file
 * name:junk:number:junk until newline
 * this matches /etc/passwd and /etc/group,
 * and is simple enough to fake up
 */
static
nextid(cur, fp)
Idmap *cur;
register FILE *fp;
{
	register char *p;
	char buf[150];		/* assume big enough for now */

	for (;;) {
		if (fgets(buf, sizeof(buf), fp) == NULL)
			return (0);	/* EOF */
		p = buf;
		while (*p && *p != ':')
			p++;
		if (*p == 0)
			continue;
		*p++ = 0;
		strncpy(cur->name, buf, sizeof(cur->name)-1);
		cur->name[sizeof(cur->name)-1] = 0;
		while (*p && *p != ':')
			p++;
		if (*p == 0)
			continue;
		p++;
		if (!isdigit(*p) && *p != '-')
			continue;
		cur->id = atoi(p);
		return (1);
	}
}

static Idmap *
exmerge(map, last, ex)
Idmap *map, *last;
Namemap *ex;
{
	register Idmap *lp;
	register Namemap *ep;
	int size, curoff;
	static Namemap nilex;

	if (ex == NULL)
		ex = &nilex;
	for (ep = ex; ep->cname[0]; ep++) {
		if (ep->sname[0] == 0)
			ep->sid = RFNOID;
		else
			ep->sid = _rflookid(map, ep->sname);
	}
	for (lp = map; lp->name[0]; lp++)
		for (ep = ex; ep->cname[0]; ep++) {
			if (ep->cname[0] != lp->name[0])	/* hash */
				continue;
			if (strcmp(ep->cname, lp->name) == 0) {
				lp->id = ep->sid;
				ep->sid = RFNOID;
			}
		}
	/*
	 * add client names not in local file
	 * lp was left at the end of the map
	 */
	for (ep = ex; ep->cname[0]; ep++) {
		if (ep->sid == RFNOID)	/* no need to enter */
			continue;
		if (lp >= last) {
			curoff = lp - map;
			size = curoff + 10;
			if ((map = (Idmap *)realloc((char *)map,
			    size*sizeof(Idmap))) == NULL)
				rfpanic("out of mem merging except\n");
			last = &map[size - 1];
			lp = &map[curoff];
		}
		strncpy(lp->name, ep->cname, sizeof(lp->name)-1);
		lp->id = ep->sid;
		lp++;
	}
	lp->name[0] = 0;
	return (map);
}