diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/9nfs/unixnames.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/9nfs/unixnames.c')
-rwxr-xr-x | sys/src/cmd/9nfs/unixnames.c | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/sys/src/cmd/9nfs/unixnames.c b/sys/src/cmd/9nfs/unixnames.c new file mode 100755 index 000000000..7b12fbb30 --- /dev/null +++ b/sys/src/cmd/9nfs/unixnames.c @@ -0,0 +1,322 @@ +#include "all.h" + +static void uxfree(Unixid*); + +static Unixid * xfree; + +Unixidmap *idhead, *idtail; + +Unixscmap *scmap; + +#define UNUSED 0x7FFFFFFF + +/* + * Sadly we have to use the IP address, since some systems (FreeBSD in particular) + * do not believe it to be safe to depend on the hostname and so refuse to send it. + * I dislike making this IP-centric, but so be it. + * We keep a cache of host names in getdom. + */ +Unixidmap * +pair2idmap(char *server, ulong clientip) +{ + Resub match; + Unixscmap *m, *mp; + Unixidmap *r; + char dom[256]; + + for(mp=0,m=scmap; m; mp=m,m=m->next){ + if(m->server[0] != server[0]) + continue; + if(strcmp(m->server, server)) + continue; + if(m->clientip != clientip) + continue; + if(mp){ + mp->next = m->next; + m->next = scmap; + scmap = m; + } + r = m->map; + if(r->u.timestamp != 0 && r->g.timestamp != 0) + return r; + scmap = m->next; + free(m); + break; + } + if(rpcdebug) + fprint(2, "looking for %lux\n", clientip); + if(getdom(clientip, dom, sizeof dom)<0){ + clog("auth: unknown ip address"); + return nil; + } + if(rpcdebug) + fprint(2, "dom is %s\n", dom); + for(r=idhead; r; r=r->next){ + if(r->u.timestamp == 0 || r->g.timestamp == 0) + continue; + match.sp = match.ep = 0; + if(regexec(r->sexp, server, &match, 1) == 0) + continue; + if(match.sp != server || match.ep <= match.sp || *match.ep) + continue; + match.sp = match.ep = 0; + if(regexec(r->cexp, dom, &match, 1) == 0) + continue; + if(match.sp != dom || match.ep <= match.sp || *match.ep) + continue; + m = malloc(sizeof(Unixscmap)); + m->next = scmap; + scmap = m; + m->server = strstore(server); + m->clientip = clientip; + m->map = r; + break; + } + return r; +} + +int +readunixidmaps(char *file) +{ + Waitmsg *w; + Biobuf *in; + Unixidmap *m; + int i, arc; char *arv[16], buf[256]; + char *l; +// long savalarm; + +// savalarm = alarm(0); + in = Bopen(file, OREAD); + if(in == 0){ + clog("readunixidmaps can't open %s: %r\n", file); +// alarm(savalarm); + return -1; + } + for(m=idhead; m; m=m->next) + m->flag = 0; + while(l = Brdline(in, '\n')){ /* assign = */ + l[Blinelen(in)-1] = 0; + arc = strparse(l, nelem(arv), arv); + if(arc > 0 && arv[0][0] == '!'){ + ++arv[0]; + snprint(buf, sizeof buf, "/bin/%s", arv[0]); + if(chatty){ + chat("!"); + for(i=0; i<arc; i++) + chat(" %s", arv[i]); + chat("..."); + } + w = system(buf, arv); + if(w == nil) + chat("err: %r\n"); + else if(w->msg && w->msg[0]) + chat("status: %s\n", w->msg); + else + chat("OK\n"); + free(w); + continue; + } + if(arc != 4) + continue; + for(m=idhead; m; m=m->next) + if(strcmp(arv[0], m->server) == 0 && + strcmp(arv[1], m->client) == 0) + break; + if(m == 0){ + m = malloc(sizeof(Unixidmap)); + if(idtail) + idtail->next = m; + else + idhead = m; + idtail = m; + m->next = 0; + m->server = strstore(arv[0]); + m->client = strstore(arv[1]); + m->sexp = regcomp(m->server); + m->cexp = regcomp(m->client); + m->u.file = strstore(arv[2]); + m->u.style = 'u'; + m->u.timestamp = 0; + m->u.ids = 0; + m->g.file = strstore(arv[3]); + m->g.style = 'u'; + m->g.timestamp = 0; + m->g.ids = 0; + }else{ + if(!m->u.file || strcmp(m->u.file, arv[2]) != 0){ + m->u.file = strstore(arv[2]); + m->u.timestamp = 0; + } + if(!m->g.file || strcmp(m->g.file, arv[3]) != 0){ + m->g.file = strstore(arv[3]); + m->g.timestamp = 0; + } + } + m->flag = 1; + checkunixmap(&m->u); + checkunixmap(&m->g); + } + Bterm(in); + for(m=idhead; m; m=m->next) + if(m->flag == 0){ + m->u.file = 0; + m->u.timestamp = 0; + uxfree(m->u.ids); + m->u.ids = 0; + m->g.file = 0; + m->g.timestamp = 0; + uxfree(m->g.ids); + m->g.ids = 0; + } +// alarm(savalarm); + return 0; +} + +static void +uxfree(Unixid *x) +{ + Unixid *tail; + int count=0; + + if(x){ + tail = x; + if(tail->id < 0) + abort(); + tail->id = UNUSED; + while(tail->next){ + tail = tail->next; + ++count; + if(tail->id == UNUSED) + abort(); + tail->id = UNUSED; + } + tail->next = xfree; + xfree = x; + } +} + +int +checkunixmap(Unixmap *u) +{ + Dir *dir; + + dir = dirstat(u->file); + if(dir == nil){ + clog("checkunixmap can't stat %s: %r\n", u->file); + return -1; + } + if(u->timestamp > dir->mtime){ + free(dir); + return 0; + } + uxfree(u->ids); + u->ids = readunixids(u->file, u->style); + u->timestamp = time(0); + free(dir); + return 1; +} + +int +name2id(Unixid **list, char *name) +{ + Unixid *x, *xp; + + for(xp=0,x=*list; x; xp=x,x=x->next){ + if(x->name[0] == name[0] && strcmp(x->name, name) == 0){ + if(xp){ + xp->next = x->next; + x->next = *list; + *list = x; + } + return x->id; + } + } + return -1; +} + +char * +id2name(Unixid **list, int id) +{ + Unixid *x, *xp; + + for(xp=0,x=*list; x; xp=x,x=x->next){ + if(x->id == id){ + if(xp){ + xp->next = x->next; + x->next = *list; + *list = x; + } + return x->name; + } + } + return "none"; +} + +void +idprint(int fd, Unixid *xp) +{ + while(xp){ + fprint(fd, "%d\t%s\n", xp->id, xp->name); + xp = xp->next; + } +} + +/* + * style '9': 3:tom:tom: + * style 'u': sysadm:*:0:0:System-Administrator:/usr/admin:/bin/sh + */ + +Unixid * +readunixids(char *file, int style) +{ + Biobuf *in; + char *l, *name = 0; + Unixid *x, *xp = 0; + int id = 0; + + in = Bopen(file, OREAD); + if(in == 0){ + clog("readunixids can't open %s: %r\n", file); + return 0; + } + while(l = Brdline(in, '\n')){ /* assign = */ + l[Blinelen(in)-1] = 0; + switch(style){ + case '9': + id = strtol(l, &l, 10); + if(*l != ':') + continue; + name = ++l; + l = strchr(l, ':'); + if(l == 0) + continue; + *l = 0; + break; + case 'u': + name = l; + l = strchr(l, ':'); + if(l == 0) + continue; + *l++ = 0; + /* skip password */ + l = strchr(l, ':'); + if(l == 0) + continue; + id = strtol(l+1, 0, 10); + break; + default: + panic("unknown unixid style %d\n", style); + } + if(id == UNUSED) + id = -1; /* any value will do */ + if(!(x = xfree)) /* assign = */ + x = listalloc(1024/sizeof(Unixid), sizeof(Unixid)); + xfree = x->next; + x->id = id; + x->name = strstore(name); + x->next = xp; + xp = x; + } + Bterm(in); + return xp; +} |