📄 util.c
字号:
intisclient(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 inthasname(Attr *a0, Attr *a1, char *name){ return _findattr(a0, name) || _findattr(a1, name);}static inthasnameval(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;}intmatchattr(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; }voidmemrandom(void *p, int n){ uchar *cp; for(cp = (uchar*)p; n > 0; n--) *cp++ = fastrand();}/* * keep caphash fd open since opens of it could be disabled */static int caphashfd;voidinitcap(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){ uchar rand[20]; char *cap; char *key; int nfrom, nto; uchar hash[SHA1dlen]; if(caphashfd < 0) return nil; /* create the capability */ nto = strlen(to); nfrom = strlen(from); cap = emalloc(nfrom+1+nto+1+sizeof(rand)*3+1); sprint(cap, "%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((uchar*)cap, strlen(cap), (uchar*)key, strlen(key), hash, nil); /* give the kernel the hash */ key[-1] = '@'; if(write(caphashfd, hash, SHA1dlen) < 0){ free(cap); return nil; } return cap;}intphaseerror(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 intoutin(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 */voidpromptforhostowner(void){ char owner[64], *p; /* hack for bitsy; can't prompt during boot */ if(p = getenv("user")){ 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. */intreplacekey(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\n", getcallerpc(&to)); 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(&a)); _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(&a)); }continue2:; } return a; }voidsetmalloctaghere(void *v){ setmalloctag(v, getcallerpc(&v));}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;}inttoosmall(Fsstate *fss, uint n){ fss->rpc.nwant = n; return RpcToosmall;}voidwritehostowner(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); }}intattrnamefmt(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);}voiddisablekey(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 */}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -