Plan 9 from Bell Labs’s /usr/web/sources/contrib/blstuart/θfs/uid.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


/*
 * Copyright (c) 2013, Coraid, Inc.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Coraid nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL CORAID BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <u.h>
#include <libc.h>
#include <thread.h>
#include <fcall.h>
#include <9p.h>
#include "dat.h"

#define MAXFIELDS 100

typedef struct Filebuf Filebuf;
typedef struct P9user P9user;
typedef struct Unixgroup Unixgroup;
typedef struct Unixsys Unixsys;
typedef struct Unixuser Unixuser;

struct Filebuf
{
	char *buf;
	char **lines;
	int nlines;
};

struct P9user
{
	char *id;
	char *name;
	char *leader;
	char **members;
	int nmembers;
};

struct Unixgroup
{
	char *name;
	int id;
	char **members;
	int nmembers;
};

struct Unixsys
{
	char *name;
	int nusers, ngroups;
	Unixuser *users;
	Unixgroup *groups;
	Unixsys *next;
};

struct Unixuser
{
	char *name;
	int id;
};

static P9user *p9users;
static int np9users;
static Unixsys *unixhd;

void
dumpusers(int fd)
{
	P9user *u;
	Unixsys *us;
	int i, j;

	fprint(fd, "/adm/users:\n");
	for(u = p9users, i = 0; i < np9users; ++u, ++i) {
		fprint(fd, "	id:%s name:%s leader:%s nmembers:%d\n	",
			u->id, u->name, u->leader, u->nmembers);
		for(j = 0; j < u->nmembers; ++j)
			fprint(fd, "%s ", u->members[j]);
		fprint(fd, "\n");
	}
	fprint(fd, "/adm/nfs:\n");
	for(us = unixhd; us; us = us->next) {
		fprint(fd, "	name=%s nusers=%d ngroup=%d\n",
			us->name, us->nusers, us->ngroups);
		fprint(fd, "		users: ");
		for(i = 0; i < us->nusers; ++i)
			fprint(fd, "%s:%d, ", us->users[i].name, us->users[i].id);
		fprint(fd, "\n		groups: ");
		for(i = 0; i < us->ngroups; ++i)
			fprint(fd, "%s:%d, ", us->groups[i].name, us->groups[i].id);
		fprint(fd, "\n");
	}
}

static Filebuf *
loadfile(char *name)
{
	Filebuf *fb;
	char *p;
	uvlong len;
	uvlong qpath, meta;
	long n;

	qpath = p2q(-1, name, 0);
	if(qpath == 0)
		return nil;
	meta = q2m(-1, qpath, 0);
	if(meta == 0)
		return nil;
	if(getmetaint(-1, meta, "length", &len) == MTnone)
		return nil;
	fb = θmalloc(sizeof(Filebuf));
	fb->buf = θmalloc(len+1);
	n = θpread(-1, qpath, fb->buf, len, 0);
	if(n < len) {
		free(fb->buf);
		free(fb);
		return nil;
	}
	fb->buf[len] = 0;
	for(p = fb->buf; p < fb->buf + n; ++p)
		if(*p == '\n')
			++fb->nlines;
	fb->lines = θmalloc(fb->nlines * sizeof(char *));
	gettokens(fb->buf, fb->lines, fb->nlines, "\n");
	return fb;
}

static void
freefile(Filebuf *fb)
{
	free(fb->buf);
	free(fb->lines);
	free(fb);
}

static void
loadusers(void)
{
	Filebuf *fb;
	char *flds[MAXFIELDS];
	int i, j, n;

	np9users = 0;
	fb = loadfile("//adm/users");
	if(fb == nil)
		return;
	if(p9users)
		free(p9users);
	p9users = θmalloc(fb->nlines * sizeof(P9user));
	for(i = 0; i < fb->nlines; ++i) {
		if(fb->lines[i][0] == '#')
			continue;
		n = getfields(fb->lines[i], flds, MAXFIELDS, 0, ":,");
		if(n < 3)
			continue;
		if(n == 3 || flds[3] == nil || flds[3][0] == 0)
			p9users[np9users].nmembers = 0;
		else
			p9users[np9users].nmembers = n - 3;
		p9users[np9users].id = estrdup9p(flds[0]);
		p9users[np9users].name = estrdup9p(flds[1]);
		if(flds[2] && flds[2][0] != '\0')
			p9users[np9users].leader = estrdup9p(flds[2]);
		else
			p9users[np9users].leader = estrdup9p(flds[1]);
		p9users[np9users].members = θmalloc((n - 3) * sizeof(char *));
		for(j = 3; j < n; ++j)
			p9users[np9users].members[j-3] = estrdup9p(flds[j]);
		++np9users;
	}
	freefile(fb);
}

static Unixsys *
buildsys(char *toks[3])
{
	Filebuf *ufb, *gfb;
	Unixsys *us;
	char *flds[MAXFIELDS];
	int i, j, k, n;

	ufb = loadfile(toks[1]);
	if(ufb == nil)
		return nil;
	gfb = loadfile(toks[2]);
	if(gfb == nil) {
		freefile(ufb);
		return nil;
	}
	us = θmalloc(sizeof(Unixsys));
	us->name = estrdup9p(toks[0]);
	us->nusers = ufb->nlines;
	us->users = θmalloc(us->nusers *sizeof(Unixuser));
	us->ngroups = gfb->nlines;
	us->groups = θmalloc(us->ngroups *sizeof(Unixgroup));
	for(i = 0, k = 0; i < us->nusers; ++i) {
		if(ufb->lines[i][0] == '#')
			continue;
		n = getfields(ufb->lines[i], flds, MAXFIELDS, 0, ":");
		if(n < 3)
			continue;
		us->users[k].name = estrdup9p(flds[0]);
		if(us->users[k].name == nil)
			continue;
		us->users[k].id = atoi(flds[2]);
		++k;
	}
	us->nusers = k;
	for(i = 0, k = 0; i < us->ngroups; ++i) {
		if(gfb->lines[i][0] == '#')
			continue;
		n = getfields(gfb->lines[i], flds, MAXFIELDS, 0, ":,");
		if(n < 3)
			continue;
		us->groups[k].name = estrdup9p(flds[0]);
		if(us->groups[k].name == nil)
			continue;
		us->groups[k].id = atoi(flds[2]);
		us->groups[k].nmembers = n - 3;
		us->groups[k].members = θmalloc(us->groups[k].nmembers * sizeof(char *));
		for(j = 0; j < us->groups[k].nmembers; ++j)
			us->groups[k].members[j] = estrdup9p(flds[j+3]);
		++k;
	}
	us->ngroups = k;
	freefile(ufb);
	freefile(gfb);
	return us;
}

void
inituid(void)
{
	Filebuf *fb;
	Unixsys *us;
	char *toks[3];
	int i, j;

	loadusers();

//	dumpusers();

	fb = loadfile("//adm/nfs");
	if(fb != nil) {
		while(unixhd) {
			us = unixhd;
			unixhd = unixhd->next;
			free(us->name);
			for(i = 0; i < us->nusers; ++i)
				free(us->users[i].name);
			free(us->users);
			for(i = 0; i < us->ngroups; ++i) {
				free(us->groups[i].name);
				for(j = 0; j < us->groups[i].nmembers; ++j)
					free(us->groups[i].members[j]);
				free(us->groups[i].members);
			}
			free(us->groups);
			free(us);
		}
		for(i = 0; i < fb->nlines; ++i) {
			tokenize(fb->lines[i], toks, 3);
			us = buildsys(toks);
			if(us) {
				us->next = unixhd;
				unixhd = us;
			}
		}
		freefile(fb);
	}
}

int
ingroup(char *user, char *group)
{
	int i, j;

	if(strcmp(user, group) == 0)
		return 1;
	for(i = 0; i < np9users && strcmp(group, p9users[i].name); ++i) ;
	if(i >= np9users)
		return 0;
	for(j = 0; j < p9users[i].nmembers && strcmp(user, p9users[i].members[j]); ++j) ;
	if(j >= p9users[i].nmembers)
		return 0;
	return 1;
}

int
isleader(char *user, char *group)
{
	int i;

	for(i = 0; i < np9users && strcmp(group, p9users[i].name); ++i) ;
	if(i >= np9users)
		return 0;
	if(p9users[i].leader == nil)
		return 0;
	if(strcmp(user, p9users[i].leader) == 0)
		return 1;
	return 0;
}

char *
id2uname(char *sys, int id)
{
	Unixsys *s;
	int i;

	if(debugnfs)
		fprint(2, "In id2uname sys=%s, id=%d\n", sys, id);
	for(s = unixhd; s && strcmp(s->name, sys) != 0; s = s->next) ;
	if(s == nil)
		return nil;
	for(i = 0; i < s->nusers && s->users[i].id != id; ++i) ;
	if(i >= s->nusers)
		return nil;
	return s->users[i].name;
}

int
uname2id(char *sys, char *uname)
{
	Unixsys *s;
	int i;

	if(debugnfs)
		fprint(2, "in uname2id: sys=%s uname=%s\n", sys, uname);
	for(s = unixhd; s && strcmp(s->name, sys) != 0; s = s->next) ;
	if(s == nil)
		return -2;
	if(uname) {
		for(i = 0; i < s->nusers && strcmp(s->users[i].name, uname) != 0; ++i) ;
		if(i < s->nusers)
			return s->users[i].id;
	}
	for(i = 0; i < s->nusers && strcmp(s->users[i].name, "nfsnobody") != 0; ++i) ;
	if(i < s->nusers)
		return s->users[i].id;
	for(i = 0; i < s->nusers && strcmp(s->users[i].name, "nobody") != 0; ++i) ;
	if(i < s->nusers)
		return s->users[i].id;
	return -2;
}

char *
id2gname(char *sys, int id)
{
	Unixsys *s;
	int i;

	for(s = unixhd; s && strcmp(s->name, sys) != 0; s = s->next) ;
	if(s == nil)
		return nil;
	for(i = 0; i < s->ngroups && s->groups[i].id != id; ++i) ;
	if(i >= s->ngroups)
		return nil;
	return s->groups[i].name;
}

int
gname2id(char *sys, char *gname)
{
	Unixsys *s;
	int i;

	if(debugnfs)
		fprint(2, "In gname2id: sys=%s gname=%s\n", sys, gname);
	for(s = unixhd; s && strcmp(s->name, sys) != 0; s = s->next) ;
	if(s == nil)
		return -2;
	if(gname) {
		for(i = 0; i < s->ngroups && strcmp(gname, s->groups[i].name) != 0; ++i) ;
		if(i < s->ngroups)
			return s->groups[i].id;
	}
	for(i = 0; i < s->ngroups && strcmp(s->groups[i].name, "nfsnobody") != 0; ++i) ;
	if(i < s->ngroups)
		return s->groups[i].id;
	for(i = 0; i < s->ngroups && strcmp(s->groups[i].name, "nobody") != 0; ++i) ;
	if(i < s->ngroups)
		return s->groups[i].id;
	return -2;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].