12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013 |
- /*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
- #include "dat.h"
- static char secstore[100]; /* server name */
- /* bind in the default network and cs */
- static int
- bindnetcs(void)
- {
- int srvfd;
- if(access("/net/tcp", AEXIST) < 0)
- bind("#I", "/net", MBEFORE);
- if(access("/net/cs", AEXIST) < 0){
- if((srvfd = open("#s/cs", ORDWR)) >= 0){
- if(mount(srvfd, -1, "/net", MBEFORE, "", 'M') >= 0)
- return 0;
- close(srvfd);
- }
- return -1;
- }
- return 0;
- }
- int
- _authdial(char *net, char *authdom)
- {
- int fd, vanilla;
- vanilla = net==nil || strcmp(net, "/net")==0;
- if(!vanilla || bindnetcs()>=0)
- return authdial(net, authdom);
- /*
- * If we failed to mount /srv/cs, assume that
- * we're still bootstrapping the system and dial
- * the one auth server passed to us on the command line.
- * In normal operation, it is important *not* to do this,
- * because the bootstrap auth server is only good for
- * a single auth domain.
- *
- * The ticket request code should really check the
- * remote authentication domain too.
- */
- /* use the auth server passed to us as an arg */
- if(authaddr == nil)
- return -1;
- fd = dial(netmkaddr(authaddr, "tcp", "567"), 0, 0, 0);
- if(fd >= 0)
- return fd;
- return dial(netmkaddr(authaddr, "il", "566"), 0, 0, 0);
- }
- int
- secdial(void)
- {
- char *p, buf[80], *f[3];
- int fd, nf;
- p = secstore; /* take it from writehostowner, if set there */
- if(*p == 0) /* else use the authserver */
- p = "$auth";
- if(bindnetcs() >= 0)
- return dial(netmkaddr(p, "net", "secstore"), 0, 0, 0);
- /* translate $auth ourselves.
- * authaddr is something like il!host!566 or tcp!host!567.
- * extract host, accounting for a change of format to something
- * like il!host or tcp!host or host.
- */
- if(strcmp(p, "$auth")==0){
- if(authaddr == nil)
- return -1;
- safecpy(buf, authaddr, sizeof buf);
- nf = getfields(buf, f, nelem(f), 0, "!");
- switch(nf){
- default:
- return -1;
- case 1:
- p = f[0];
- break;
- case 2:
- case 3:
- p = f[1];
- break;
- }
- }
- fd = dial(netmkaddr(p, "tcp", "5356"), 0, 0, 0);
- if(fd >= 0)
- return fd;
- return -1;
- }
- /*
- * prompt user for a key. don't care about memory leaks, runs standalone
- */
- static Attr*
- promptforkey(char *params)
- {
- char *v;
- int fd;
- Attr *a, *attr;
- char *def;
- fd = open("/dev/cons", ORDWR);
- if(fd < 0)
- sysfatal("opening /dev/cons: %r");
- attr = _parseattr(params);
- fprint(fd, "\n!Adding key:");
- for(a=attr; a; a=a->next)
- if(a->type != AttrQuery && a->name[0] != '!')
- fprint(fd, " %q=%q", a->name, a->val);
- fprint(fd, "\n");
- for(a=attr; a; a=a->next){
- v = a->name;
- if(a->type != AttrQuery || v[0]=='!')
- continue;
- def = nil;
- if(strcmp(v, "user") == 0)
- def = getuser();
- a->val = readcons(v, def, 0);
- if(a->val == nil)
- sysfatal("user terminated key input");
- a->type = AttrNameval;
- }
- for(a=attr; a; a=a->next){
- v = a->name;
- if(a->type != AttrQuery || v[0]!='!')
- continue;
- def = nil;
- if(strcmp(v+1, "user") == 0)
- def = getuser();
- a->val = readcons(v+1, def, 1);
- if(a->val == nil)
- sysfatal("user terminated key input");
- a->type = AttrNameval;
- }
- fprint(fd, "!\n");
- close(fd);
- return attr;
- }
- /*
- * send a key to the mounted factotum
- */
- static int
- sendkey(Attr *attr)
- {
- int fd, rv;
- char buf[1024];
- fd = open("/mnt/factotum/ctl", ORDWR);
- if(fd < 0)
- sysfatal("opening /mnt/factotum/ctl: %r");
- rv = fprint(fd, "key %A\n", attr);
- read(fd, buf, sizeof buf);
- close(fd);
- return rv;
- }
- /* askuser */
- void
- askuser(char *params)
- {
- Attr *attr;
- attr = promptforkey(params);
- if(attr == nil)
- sysfatal("no key supplied");
- if(sendkey(attr) < 0)
- sysfatal("sending key to factotum: %r");
- }
- uint32_t conftaggen;
- int
- canusekey(Fsstate *fss, Key *k)
- {
- int i;
- if(_strfindattr(k->attr, "confirm")){
- for(i=0; i<fss->nconf; i++)
- if(fss->conf[i].key == k)
- return fss->conf[i].canuse;
- if(fss->nconf%16 == 0)
- fss->conf = erealloc(fss->conf, (fss->nconf+16)*(sizeof(fss->conf[0])));
- fss->conf[fss->nconf].key = k;
- k->ref++;
- fss->conf[fss->nconf].canuse = -1;
- fss->conf[fss->nconf].tag = conftaggen++;
- fss->nconf++;
- return -1;
- }
- return 1;
- }
- /* closekey */
- void
- closekey(Key *k)
- {
- if(k == nil)
- return;
- if(--k->ref != 0)
- return;
- if(k->proto && k->proto->closekey)
- (*k->proto->closekey)(k);
- _freeattr(k->attr);
- _freeattr(k->privattr);
- k->attr = (void*)~1;
- k->privattr = (void*)~1;
- k->proto = nil;
- free(k);
- }
- static uint8_t*
- pstring(uint8_t *p, uint8_t *e, char *s)
- {
- uint n;
- if(p == nil)
- return nil;
- if(s == nil)
- s = "";
- n = strlen(s);
- if(p+n+BIT16SZ >= e)
- return nil;
- PBIT16(p, n);
- p += BIT16SZ;
- memmove(p, s, n);
- p += n;
- return p;
- }
- static uint8_t*
- pcarray(uint8_t *p, uint8_t *e, uint8_t *s, uint n)
- {
- if(p == nil)
- return nil;
- if(s == nil){
- if(n > 0)
- sysfatal("pcarray");
- s = (uint8_t*)"";
- }
- if(p+n+BIT16SZ >= e)
- return nil;
- PBIT16(p, n);
- p += BIT16SZ;
- memmove(p, s, n);
- p += n;
- return p;
- }
- uint8_t*
- convAI2M(AuthInfo *ai, uint8_t *p, int n)
- {
- uint8_t *e = p+n;
- p = pstring(p, e, ai->cuid);
- p = pstring(p, e, ai->suid);
- p = pstring(p, e, ai->cap);
- p = pcarray(p, e, ai->secret, ai->nsecret);
- return p;
- }
- int
- failure(Fsstate *s, char *fmt, ...)
- {
- char e[ERRMAX];
- va_list arg;
- if(fmt == nil)
- rerrstr(s->err, sizeof(s->err));
- else {
- va_start(arg, fmt);
- vsnprint(e, sizeof e, fmt, arg);
- va_end(arg);
- strecpy(s->err, s->err+sizeof(s->err), e);
- werrstr(e);
- }
- flog("%d: failure %s", s->seqnum, s->err);
- return RpcFailure;
- }
- static int
- hasqueries(Attr *a)
- {
- for(; a; a=a->next)
- if(a->type == AttrQuery)
- return 1;
- return 0;
- }
- char *ignored[] = {
- "role",
- "disabled",
- };
- static int
- ignoreattr(char *s)
- {
- int i;
- for(i=0; i<nelem(ignored); i++)
- if(strcmp(ignored[i], s)==0)
- return 1;
- return 0;
- }
- Keyinfo*
- mkkeyinfo(Keyinfo *k, Fsstate *fss, Attr *attr)
- {
- memset(k, 0, sizeof *k);
- k->fss = fss;
- k->user = fss->sysuser;
- if(attr)
- k->attr = attr;
- else
- k->attr = fss->attr;
- return k;
- }
- int
- findkey(Key **ret, Keyinfo *ki, char *fmt, ...)
- {
- int i, s, nmatch;
- char buf[1024], *p, *who;
- va_list arg;
- Attr *a, *attr0, *attr1, *attr2, *attr3, **l;
- Key *k;
- *ret = nil;
- who = ki->user;
- attr0 = ki->attr;
- if(fmt){
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof buf, fmt, arg);
- va_end(arg);
- attr1 = _parseattr(buf);
- }else
- attr1 = nil;
- if(who && strcmp(who, owner) == 0)
- who = nil;
- if(who){
- snprint(buf, sizeof buf, "owner=%q", who);
- attr2 = _parseattr(buf);
- attr3 = _parseattr("owner=*");
- }else
- attr2 = attr3 = nil;
- p = _strfindattr(attr0, "proto");
- if(p == nil)
- p = _strfindattr(attr1, "proto");
- if(p && findproto(p) == nil){
- werrstr("unknown protocol %s", p);
- _freeattr(attr1);
- _freeattr(attr2);
- _freeattr(attr3);
- return failure(ki->fss, nil);
- }
- nmatch = 0;
- for(i=0; i<ring->nkey; i++){
- k = ring->key[i];
- if(_strfindattr(k->attr, "disabled") && !ki->usedisabled)
- continue;
- if(matchattr(attr0, k->attr, k->privattr) && matchattr(attr1, k->attr, k->privattr)){
- /* check ownership */
- if(!matchattr(attr2, k->attr, nil) && !matchattr(attr3, k->attr, nil))
- continue;
- if(nmatch++ < ki->skip)
- continue;
- if(!ki->noconf){
- switch(canusekey(ki->fss, k)){
- case -1:
- _freeattr(attr1);
- return RpcConfirm;
- case 0:
- continue;
- case 1:
- break;
- }
- }
- _freeattr(attr1);
- _freeattr(attr2);
- _freeattr(attr3);
- k->ref++;
- *ret = k;
- return RpcOk;
- }
- }
- flog("%d: no key matches %A %A %A %A", ki->fss->seqnum, attr0, attr1, attr2, attr3);
- werrstr("no key matches %A %A", attr0, attr1);
- _freeattr(attr2);
- _freeattr(attr3);
- s = RpcFailure;
- if(askforkeys && who==nil && (hasqueries(attr0) || hasqueries(attr1))){
- if(nmatch == 0){
- attr0 = _copyattr(attr0);
- for(l=&attr0; *l; l=&(*l)->next)
- ;
- *l = attr1;
- for(l=&attr0; *l; ){
- if(ignoreattr((*l)->name)){
- a = *l;
- *l = (*l)->next;
- a->next = nil;
- _freeattr(a);
- }else
- l = &(*l)->next;
- }
- attr0 = sortattr(attr0);
- snprint(ki->fss->keyinfo, sizeof ki->fss->keyinfo, "%A", attr0);
- _freeattr(attr0);
- attr1 = nil; /* attr1 was linked to attr0 */
- }else
- ki->fss->keyinfo[0] = '\0';
- s = RpcNeedkey;
- }
- _freeattr(attr1);
- if(s == RpcFailure)
- return failure(ki->fss, nil); /* loads error string */
- return s;
- }
- int
- findp9authkey(Key **k, Fsstate *fss)
- {
- char *dom;
- Keyinfo ki;
- /*
- * We don't use fss->attr here because we don't
- * care about what the user name is set to, for instance.
- */
- mkkeyinfo(&ki, fss, nil);
- ki.attr = nil;
- ki.user = nil;
- if((dom = _strfindattr(fss->attr, "dom")) != nil)
- return findkey(k, &ki, "proto=p9sk1 dom=%q role=server user?", dom);
- else
- return findkey(k, &ki, "proto=p9sk1 role=server dom? user?");
- }
- Proto*
- findproto(char *name)
- {
- int i;
- for(i=0; prototab[i]; i++)
- if(strcmp(name, prototab[i]->name) == 0)
- return prototab[i];
- return nil;
- }
- char*
- getnvramkey(int flag, char **secstorepw)
- {
- char *s;
- Nvrsafe safe;
- char spw[CONFIGLEN+1];
- int i;
- memset(&safe, 0, sizeof safe);
- /*
- * readnvram can return -1 meaning nvram wasn't written,
- * but safe still holds good data.
- */
- if(readnvram(&safe, flag)<0 && safe.authid[0]==0)
- return nil;
- /*
- * we're using the config area to hold the secstore
- * password. if there's anything there, return it.
- */
- memmove(spw, safe.config, CONFIGLEN);
- spw[CONFIGLEN] = 0;
- if(spw[0] != 0)
- *secstorepw = estrdup(spw);
- /*
- * only use nvram key if it is non-zero
- */
- for(i = 0; i < DESKEYLEN; i++)
- if(safe.machkey[i] != 0)
- break;
- if(i == DESKEYLEN)
- return nil;
- s = emalloc(512);
- fmtinstall('H', encodefmt);
- snprint(s, 512, "key proto=p9sk1 user=%q dom=%q !hex=%.*H !password=______",
- safe.authid, safe.authdom, DESKEYLEN, safe.machkey);
- writehostowner(safe.authid);
- return s;
- }
- int
- isclient(char *role)
- {
- if(role == nil){
- werrstr("role not specified");
- return -1;
- }
- if(strcmp(role, "server") == 0)
- return 0;
- if(strcmp(role, "client") == 0)
- return 1;
- werrstr("unknown role %q", role);
- return -1;
- }
- static int
- hasname(Attr *a0, Attr *a1, char *name)
- {
- return _findattr(a0, name) || _findattr(a1, name);
- }
- static int
- hasnameval(Attr *a0, Attr *a1, char *name, char *val)
- {
- Attr *a;
- for(a=_findattr(a0, name); a; a=_findattr(a->next, name))
- if(strcmp(a->val, val) == 0)
- return 1;
- for(a=_findattr(a1, name); a; a=_findattr(a->next, name))
- if(strcmp(a->val, val) == 0)
- return 1;
- return 0;
- }
- int
- matchattr(Attr *pat, Attr *a0, Attr *a1)
- {
- int type;
- for(; pat; pat=pat->next){
- type = pat->type;
- if(ignoreattr(pat->name))
- type = AttrDefault;
- switch(type){
- case AttrQuery: /* name=something be present */
- if(!hasname(a0, a1, pat->name))
- return 0;
- break;
- case AttrNameval: /* name=val must be present */
- if(!hasnameval(a0, a1, pat->name, pat->val))
- return 0;
- break;
- case AttrDefault: /* name=val must be present if name=anything is present */
- if(hasname(a0, a1, pat->name) && !hasnameval(a0, a1, pat->name, pat->val))
- return 0;
- break;
- }
- }
- return 1;
- }
- void
- memrandom(void *p, int n)
- {
- uint8_t *cp;
- for(cp = (uint8_t*)p; n > 0; n--)
- *cp++ = fastrand();
- }
- /*
- * keep caphash fd open since opens of it could be disabled
- */
- static int caphashfd;
- void
- initcap(void)
- {
- caphashfd = open("#¤/caphash", OWRITE);
- // if(caphashfd < 0)
- // fprint(2, "%s: opening #¤/caphash: %r\n", argv0);
- }
- /*
- * create a change uid capability
- */
- char*
- mkcap(char *from, char *to)
- {
- uint8_t rand[20];
- char *cap;
- char *key;
- int nfrom, nto, ncap;
- uint8_t hash[SHA1dlen];
- if(caphashfd < 0)
- return nil;
- /* create the capability */
- nto = strlen(to);
- nfrom = strlen(from);
- ncap = nfrom + 1 + nto + 1 + sizeof(rand)*3 + 1;
- cap = emalloc(ncap);
- snprint(cap, ncap, "%s@%s", from, to);
- memrandom(rand, sizeof(rand));
- key = cap+nfrom+1+nto+1;
- enc64(key, sizeof(rand)*3, rand, sizeof(rand));
- /* hash the capability */
- hmac_sha1((uint8_t*)cap, strlen(cap), (uint8_t*)key, strlen(key),
- hash, nil);
- /* give the kernel the hash */
- key[-1] = '@';
- if(write(caphashfd, hash, SHA1dlen) < 0){
- free(cap);
- return nil;
- }
- return cap;
- }
- int
- phaseerror(Fsstate *s, char *op)
- {
- char tmp[32];
- werrstr("protocol phase error: %s in state %s", op, phasename(s, s->phase, tmp));
- return RpcPhase;
- }
- char*
- phasename(Fsstate *fss, int phase, char *tmp)
- {
- char *name;
- if(fss->phase == Broken)
- name = "Broken";
- else if(phase == Established)
- name = "Established";
- else if(phase == Notstarted)
- name = "Notstarted";
- else if(phase < 0 || phase >= fss->maxphase
- || (name = fss->phasename[phase]) == nil){
- sprint(tmp, "%d", phase);
- name = tmp;
- }
- return name;
- }
- static int
- outin(char *prompt, char *def, int len)
- {
- char *s;
- s = readcons(prompt, def, 0);
- if(s == nil)
- return -1;
- if(s == nil)
- sysfatal("s==nil???");
- strncpy(def, s, len);
- def[len-1] = 0;
- free(s);
- return strlen(def);
- }
- /*
- * get host owner and set it
- */
- void
- promptforhostowner(void)
- {
- char owner[64], *p;
- /* hack for bitsy; can't prompt during boot */
- if((p = getenv("user")) != nil){
- writehostowner(p);
- free(p);
- return;
- }
- free(p);
- strcpy(owner, "none");
- do{
- outin("user", owner, sizeof(owner));
- } while(*owner == 0);
- writehostowner(owner);
- }
- char*
- estrappend(char *s, char *fmt, ...)
- {
- char *t;
- va_list arg;
- va_start(arg, fmt);
- t = vsmprint(fmt, arg);
- if(t == nil)
- sysfatal("out of memory");
- va_end(arg);
- s = erealloc(s, strlen(s)+strlen(t)+1);
- strcat(s, t);
- free(t);
- return s;
- }
- /*
- * prompt for a string with a possible default response
- */
- char*
- readcons(char *prompt, char *def, int raw)
- {
- int fdin, fdout, ctl, n;
- char line[10];
- char *s;
- fdin = open("/dev/cons", OREAD);
- if(fdin < 0)
- fdin = 0;
- fdout = open("/dev/cons", OWRITE);
- if(fdout < 0)
- fdout = 1;
- if(def != nil)
- fprint(fdout, "%s[%s]: ", prompt, def);
- else
- fprint(fdout, "%s: ", prompt);
- if(raw){
- ctl = open("/dev/consctl", OWRITE);
- if(ctl >= 0)
- write(ctl, "rawon", 5);
- } else
- ctl = -1;
- s = estrdup("");
- for(;;){
- n = read(fdin, line, 1);
- if(n == 0){
- Error:
- close(fdin);
- close(fdout);
- if(ctl >= 0)
- close(ctl);
- free(s);
- return nil;
- }
- if(n < 0)
- goto Error;
- if(line[0] == 0x7f)
- goto Error;
- if(n == 0 || line[0] == '\n' || line[0] == '\r'){
- if(raw){
- write(ctl, "rawoff", 6);
- write(fdout, "\n", 1);
- }
- close(ctl);
- close(fdin);
- close(fdout);
- if(*s == 0 && def != nil)
- s = estrappend(s, "%s", def);
- return s;
- }
- if(line[0] == '\b'){
- if(strlen(s) > 0)
- s[strlen(s)-1] = 0;
- } else if(line[0] == 0x15) { /* ^U: line kill */
- if(def != nil)
- fprint(fdout, "\n%s[%s]: ", prompt, def);
- else
- fprint(fdout, "\n%s: ", prompt);
- s[0] = 0;
- } else {
- s = estrappend(s, "%c", line[0]);
- }
- }
- }
- /*
- * Insert a key into the keyring.
- * If the public attributes are identical to some other key, replace that one.
- */
- int
- replacekey(Key *kn, int before)
- {
- int i;
- Key *k;
- for(i=0; i<ring->nkey; i++){
- k = ring->key[i];
- if(matchattr(kn->attr, k->attr, nil) && matchattr(k->attr, kn->attr, nil)){
- closekey(k);
- kn->ref++;
- ring->key[i] = kn;
- return 0;
- }
- }
- if(ring->nkey%16 == 0)
- ring->key = erealloc(ring->key, (ring->nkey+16)*sizeof(ring->key[0]));
- kn->ref++;
- if(before){
- memmove(ring->key+1, ring->key, ring->nkey*sizeof ring->key[0]);
- ring->key[0] = kn;
- ring->nkey++;
- }else
- ring->key[ring->nkey++] = kn;
- return 0;
- }
- char*
- safecpy(char *to, char *from, int n)
- {
- memset(to, 0, n);
- if(n == 1)
- return to;
- if(from==nil)
- sysfatal("safecpy called with from==nil, pc=%#p",
- getcallerpc());
- strncpy(to, from, n-1);
- return to;
- }
- Attr*
- setattr(Attr *a, char *fmt, ...)
- {
- char buf[1024];
- va_list arg;
- Attr *b;
- va_start(arg, fmt);
- vseprint(buf, buf+sizeof buf, fmt, arg);
- va_end(arg);
- b = _parseattr(buf);
- a = setattrs(a, b);
- setmalloctag(a, getcallerpc());
- _freeattr(b);
- return a;
- }
- /*
- * add attributes in list b to list a. If any attributes are in
- * both lists, replace those in a by those in b.
- */
- Attr*
- setattrs(Attr *a, Attr *b)
- {
- int found;
- Attr **l, *freea;
- for(; b; b=b->next){
- found = 0;
- for(l=&a; *l; ){
- if(strcmp(b->name, (*l)->name) == 0){
- switch(b->type){
- case AttrNameval:
- if(!found){
- found = 1;
- free((*l)->val);
- (*l)->val = estrdup(b->val);
- (*l)->type = AttrNameval;
- l = &(*l)->next;
- }else{
- freea = *l;
- *l = (*l)->next;
- freea->next = nil;
- _freeattr(freea);
- }
- break;
- case AttrQuery:
- goto continue2;
- }
- }else
- l = &(*l)->next;
- }
- if(found == 0){
- *l = _mkattr(b->type, b->name, b->val, nil);
- setmalloctag(*l, getcallerpc());
- }
- continue2:;
- }
- return a;
- }
- void
- setmalloctaghere(void *v)
- {
- setmalloctag(v, getcallerpc());
- }
- Attr*
- sortattr(Attr *a)
- {
- int i;
- Attr *anext, *a0, *a1, **l;
- if(a == nil || a->next == nil)
- return a;
- /* cut list in halves */
- a0 = nil;
- a1 = nil;
- i = 0;
- for(; a; a=anext){
- anext = a->next;
- if(i++%2){
- a->next = a0;
- a0 = a;
- }else{
- a->next = a1;
- a1 = a;
- }
- }
- /* sort */
- a0 = sortattr(a0);
- a1 = sortattr(a1);
- /* merge */
- l = &a;
- while(a0 || a1){
- if(a1==nil){
- anext = a0;
- a0 = a0->next;
- }else if(a0==nil){
- anext = a1;
- a1 = a1->next;
- }else if(strcmp(a0->name, a1->name) < 0){
- anext = a0;
- a0 = a0->next;
- }else{
- anext = a1;
- a1 = a1->next;
- }
- *l = anext;
- l = &(*l)->next;
- }
- *l = nil;
- return a;
- }
- int
- toosmall(Fsstate *fss, uint n)
- {
- fss->rpc.nwant = n;
- return RpcToosmall;
- }
- void
- writehostowner(char *owner)
- {
- int fd;
- char *s;
- if((s = strchr(owner,'@')) != nil){
- *s++ = 0;
- strncpy(secstore, s, (sizeof secstore)-1);
- }
- fd = open("#c/hostowner", OWRITE);
- if(fd >= 0){
- if(fprint(fd, "%s", owner) < 0)
- fprint(2, "factotum: setting #c/hostowner to %q: %r\n",
- owner);
- close(fd);
- }
- }
- int
- attrnamefmt(Fmt *fmt)
- {
- char *b, buf[1024], *ebuf;
- Attr *a;
- ebuf = buf+sizeof buf;
- b = buf;
- strcpy(buf, " ");
- for(a=va_arg(fmt->args, Attr*); a; a=a->next){
- if(a->name == nil)
- continue;
- b = seprint(b, ebuf, " %q?", a->name);
- }
- return fmtstrcpy(fmt, buf+1);
- }
- void
- disablekey(Key *k)
- {
- Attr *a;
- if(sflag) /* not on servers */
- return;
- for(a=k->attr; a; a=a->next){
- if(a->type==AttrNameval && strcmp(a->name, "disabled") == 0)
- return;
- if(a->next == nil)
- break;
- }
- if(a)
- a->next = _mkattr(AttrNameval, "disabled", "by.factotum", nil);
- else
- k->attr = _mkattr(AttrNameval, "disabled", "by.factotum", nil); /* not reached: always a proto attribute */
- }
|