19a747e4fSDavid du Colombier #include "dat.h"
29a747e4fSDavid du Colombier
39a747e4fSDavid du Colombier int askforkeys = 1;
49a747e4fSDavid du Colombier char *authaddr;
59a747e4fSDavid du Colombier int debug;
64de34a7eSDavid du Colombier int doprivate = 1;
79a747e4fSDavid du Colombier int gflag;
89a747e4fSDavid du Colombier char *owner;
99a747e4fSDavid du Colombier int kflag;
109a747e4fSDavid du Colombier char *mtpt = "/mnt";
119a747e4fSDavid du Colombier Keyring *ring;
129a747e4fSDavid du Colombier char *service;
139a747e4fSDavid du Colombier int sflag;
149a747e4fSDavid du Colombier int uflag;
159a747e4fSDavid du Colombier
169a747e4fSDavid du Colombier extern Srv fs;
179a747e4fSDavid du Colombier static void notifyf(void*, char*);
189a747e4fSDavid du Colombier static void private(void);
199a747e4fSDavid du Colombier
209a747e4fSDavid du Colombier char Easproto[] = "auth server protocol botch";
219a747e4fSDavid du Colombier char Ebadarg[] = "invalid argument";
229a747e4fSDavid du Colombier char Ebadkey[] = "bad key";
239a747e4fSDavid du Colombier char Enegotiation[] = "negotiation failed, no common protocols or keys";
249a747e4fSDavid du Colombier char Etoolarge[] = "rpc too large";
259a747e4fSDavid du Colombier
269a747e4fSDavid du Colombier Proto*
279a747e4fSDavid du Colombier prototab[] =
289a747e4fSDavid du Colombier {
299a747e4fSDavid du Colombier &apop,
309a747e4fSDavid du Colombier &chap,
319a747e4fSDavid du Colombier &cram,
325ab4dd4cSDavid du Colombier &httpdigest,
339a747e4fSDavid du Colombier &mschap,
349a747e4fSDavid du Colombier &p9any,
359a747e4fSDavid du Colombier &p9cr,
369a747e4fSDavid du Colombier &p9sk1,
379a747e4fSDavid du Colombier &p9sk2,
389a747e4fSDavid du Colombier &pass,
3949eeb88aSDavid du Colombier /* &srs, */
402ebbfa15SDavid du Colombier &rsa,
419a747e4fSDavid du Colombier &vnc,
42fb7f0c93SDavid du Colombier &wep,
439a747e4fSDavid du Colombier nil,
449a747e4fSDavid du Colombier };
459a747e4fSDavid du Colombier
469a747e4fSDavid du Colombier void
usage(void)479a747e4fSDavid du Colombier usage(void)
489a747e4fSDavid du Colombier {
4914cc0f53SDavid du Colombier fprint(2, "usage: %s [-DSdknpu] [-a authaddr] [-m mtpt] [-s service]\n",
5014cc0f53SDavid du Colombier argv0);
519a747e4fSDavid du Colombier fprint(2, "or %s -g 'params'\n", argv0);
529a747e4fSDavid du Colombier exits("usage");
539a747e4fSDavid du Colombier }
549a747e4fSDavid du Colombier
559a747e4fSDavid du Colombier void
main(int argc,char ** argv)569a747e4fSDavid du Colombier main(int argc, char **argv)
579a747e4fSDavid du Colombier {
589a747e4fSDavid du Colombier int i, trysecstore;
599a747e4fSDavid du Colombier char err[ERRMAX], *s;
609a747e4fSDavid du Colombier Dir d;
619a747e4fSDavid du Colombier Proto *p;
629a747e4fSDavid du Colombier char *secstorepw;
639a747e4fSDavid du Colombier
649a747e4fSDavid du Colombier trysecstore = 1;
659a747e4fSDavid du Colombier secstorepw = nil;
669a747e4fSDavid du Colombier
679a747e4fSDavid du Colombier ARGBEGIN{
689a747e4fSDavid du Colombier case 'D':
699a747e4fSDavid du Colombier chatty9p++;
709a747e4fSDavid du Colombier break;
719a747e4fSDavid du Colombier case 'S': /* server: read nvram, no prompting for keys */
729a747e4fSDavid du Colombier askforkeys = 0;
739a747e4fSDavid du Colombier trysecstore = 0;
749a747e4fSDavid du Colombier sflag = 1;
759a747e4fSDavid du Colombier break;
769a747e4fSDavid du Colombier case 'a':
779a747e4fSDavid du Colombier authaddr = EARGF(usage());
789a747e4fSDavid du Colombier break;
799a747e4fSDavid du Colombier case 'd':
809a747e4fSDavid du Colombier debug = 1;
814de34a7eSDavid du Colombier doprivate = 0;
829a747e4fSDavid du Colombier break;
839a747e4fSDavid du Colombier case 'g': /* get: prompt for key for name and domain */
849a747e4fSDavid du Colombier gflag = 1;
859a747e4fSDavid du Colombier break;
869a747e4fSDavid du Colombier case 'k': /* reinitialize nvram */
879a747e4fSDavid du Colombier kflag = 1;
889a747e4fSDavid du Colombier break;
899a747e4fSDavid du Colombier case 'm': /* set default mount point */
909a747e4fSDavid du Colombier mtpt = EARGF(usage());
919a747e4fSDavid du Colombier break;
929a747e4fSDavid du Colombier case 'n':
939a747e4fSDavid du Colombier trysecstore = 0;
949a747e4fSDavid du Colombier break;
954de34a7eSDavid du Colombier case 'p':
964de34a7eSDavid du Colombier doprivate = 0;
974de34a7eSDavid du Colombier break;
989a747e4fSDavid du Colombier case 's': /* set service name */
999a747e4fSDavid du Colombier service = EARGF(usage());
1009a747e4fSDavid du Colombier break;
1019a747e4fSDavid du Colombier case 'u': /* user: set hostowner */
1029a747e4fSDavid du Colombier uflag = 1;
1039a747e4fSDavid du Colombier break;
104d9306527SDavid du Colombier default:
105d9306527SDavid du Colombier usage();
1069a747e4fSDavid du Colombier }ARGEND
1079a747e4fSDavid du Colombier
108d9306527SDavid du Colombier if(argc != 0 && !gflag)
109d9306527SDavid du Colombier usage();
1104de34a7eSDavid du Colombier if(doprivate)
1119a747e4fSDavid du Colombier private();
1129a747e4fSDavid du Colombier
1133ff48bf5SDavid du Colombier initcap();
1143ff48bf5SDavid du Colombier
1159a747e4fSDavid du Colombier quotefmtinstall();
1169a747e4fSDavid du Colombier fmtinstall('A', _attrfmt);
1175d459b5aSDavid du Colombier fmtinstall('N', attrnamefmt);
1189a747e4fSDavid du Colombier fmtinstall('H', encodefmt);
1199a747e4fSDavid du Colombier
1209a747e4fSDavid du Colombier ring = emalloc(sizeof(*ring));
121260f7b65SDavid du Colombier notify(notifyf);
1229a747e4fSDavid du Colombier
1239a747e4fSDavid du Colombier if(gflag){
1249a747e4fSDavid du Colombier if(argc != 1)
1259a747e4fSDavid du Colombier usage();
1269a747e4fSDavid du Colombier askuser(argv[0]);
1279a747e4fSDavid du Colombier exits(nil);
1289a747e4fSDavid du Colombier }
1299a747e4fSDavid du Colombier
1309a747e4fSDavid du Colombier for(i=0; prototab[i]; i++){
1319a747e4fSDavid du Colombier p = prototab[i];
1329a747e4fSDavid du Colombier if(p->name == nil)
1339a747e4fSDavid du Colombier sysfatal("protocol %d has no name", i);
1349a747e4fSDavid du Colombier if(p->init == nil)
1359a747e4fSDavid du Colombier sysfatal("protocol %s has no init", p->name);
1369a747e4fSDavid du Colombier if(p->write == nil)
1379a747e4fSDavid du Colombier sysfatal("protocol %s has no write", p->name);
1389a747e4fSDavid du Colombier if(p->read == nil)
1399a747e4fSDavid du Colombier sysfatal("protocol %s has no read", p->name);
1409a747e4fSDavid du Colombier if(p->close == nil)
1419a747e4fSDavid du Colombier sysfatal("protocol %s has no close", p->name);
1429a747e4fSDavid du Colombier if(p->keyprompt == nil)
1439a747e4fSDavid du Colombier p->keyprompt = "";
1449a747e4fSDavid du Colombier }
1459a747e4fSDavid du Colombier
1469a747e4fSDavid du Colombier if(sflag){
1479a747e4fSDavid du Colombier s = getnvramkey(kflag ? NVwrite : NVwriteonerr, &secstorepw);
1489a747e4fSDavid du Colombier if(s == nil)
1499a747e4fSDavid du Colombier fprint(2, "factotum warning: cannot read nvram: %r\n");
15070b8e010SDavid du Colombier else if(ctlwrite(s, 0) < 0)
1519a747e4fSDavid du Colombier fprint(2, "factotum warning: cannot add nvram key: %r\n");
1529a747e4fSDavid du Colombier if(secstorepw != nil)
1539a747e4fSDavid du Colombier trysecstore = 1;
1546822557bSDavid du Colombier if (s != nil) {
155d9306527SDavid du Colombier memset(s, 0, strlen(s));
156d9306527SDavid du Colombier free(s);
1576822557bSDavid du Colombier }
1589a747e4fSDavid du Colombier } else if(uflag)
1599a747e4fSDavid du Colombier promptforhostowner();
160fb7f0c93SDavid du Colombier owner = getuser();
1619a747e4fSDavid du Colombier
1629a747e4fSDavid du Colombier if(trysecstore){
1639a747e4fSDavid du Colombier if(havesecstore() == 1){
1649a747e4fSDavid du Colombier while(secstorefetch(secstorepw) < 0){
1659a747e4fSDavid du Colombier rerrstr(err, sizeof err);
1669a747e4fSDavid du Colombier if(strcmp(err, "cancel") == 0)
1679a747e4fSDavid du Colombier break;
168d854de59SDavid du Colombier fprint(2, "factotum: secstorefetch: %r\n");
1695d459b5aSDavid du Colombier fprint(2, "Enter an empty password to quit.\n");
170d9306527SDavid du Colombier free(secstorepw);
1719a747e4fSDavid du Colombier secstorepw = nil; /* just try nvram pw once */
1729a747e4fSDavid du Colombier }
1739a747e4fSDavid du Colombier }else{
1749a747e4fSDavid du Colombier /*
1759a747e4fSDavid du Colombier rerrstr(err, sizeof err);
1769a747e4fSDavid du Colombier if(*err)
177d854de59SDavid du Colombier fprint(2, "factotum: havesecstore: %r\n");
1789a747e4fSDavid du Colombier */
1799a747e4fSDavid du Colombier }
1809a747e4fSDavid du Colombier }
1819a747e4fSDavid du Colombier
1829a747e4fSDavid du Colombier postmountsrv(&fs, service, mtpt, MBEFORE);
1839a747e4fSDavid du Colombier if(service){
1849a747e4fSDavid du Colombier nulldir(&d);
1859a747e4fSDavid du Colombier d.mode = 0666;
1869a747e4fSDavid du Colombier s = emalloc(10+strlen(service));
1879a747e4fSDavid du Colombier strcpy(s, "/srv/");
1889a747e4fSDavid du Colombier strcat(s, service);
1899a747e4fSDavid du Colombier if(dirwstat(s, &d) < 0)
1909a747e4fSDavid du Colombier fprint(2, "factotum warning: cannot chmod 666 %s: %r\n", s);
1919a747e4fSDavid du Colombier free(s);
1929a747e4fSDavid du Colombier }
1939a747e4fSDavid du Colombier exits(nil);
1949a747e4fSDavid du Colombier }
1959a747e4fSDavid du Colombier
1969a747e4fSDavid du Colombier char *pmsg = "Warning! %s can't protect itself from debugging: %r\n";
197b7b24591SDavid du Colombier char *smsg = "Warning! %s can't turn off swapping: %r\n";
1989a747e4fSDavid du Colombier
1999a747e4fSDavid du Colombier /* don't allow other processes to debug us and steal keys */
2009a747e4fSDavid du Colombier static void
private(void)2019a747e4fSDavid du Colombier private(void)
2029a747e4fSDavid du Colombier {
2039a747e4fSDavid du Colombier int fd;
2049a747e4fSDavid du Colombier char buf[64];
2059a747e4fSDavid du Colombier
2069a747e4fSDavid du Colombier snprint(buf, sizeof(buf), "#p/%d/ctl", getpid());
2079a747e4fSDavid du Colombier fd = open(buf, OWRITE);
2089a747e4fSDavid du Colombier if(fd < 0){
2099a747e4fSDavid du Colombier fprint(2, pmsg, argv0);
2109a747e4fSDavid du Colombier return;
2119a747e4fSDavid du Colombier }
2129a747e4fSDavid du Colombier if(fprint(fd, "private") < 0)
2139a747e4fSDavid du Colombier fprint(2, pmsg, argv0);
214b7b24591SDavid du Colombier if(fprint(fd, "noswap") < 0)
215b7b24591SDavid du Colombier fprint(2, smsg, argv0);
2169a747e4fSDavid du Colombier close(fd);
2179a747e4fSDavid du Colombier }
2189a747e4fSDavid du Colombier
2199a747e4fSDavid du Colombier static void
notifyf(void *,char * s)2209a747e4fSDavid du Colombier notifyf(void*, char *s)
2219a747e4fSDavid du Colombier {
2229a747e4fSDavid du Colombier if(strncmp(s, "interrupt", 9) == 0)
2239a747e4fSDavid du Colombier noted(NCONT);
2249a747e4fSDavid du Colombier noted(NDFLT);
2259a747e4fSDavid du Colombier }
2269a747e4fSDavid du Colombier
2279a747e4fSDavid du Colombier enum
2289a747e4fSDavid du Colombier {
2299a747e4fSDavid du Colombier Qroot,
2309a747e4fSDavid du Colombier Qfactotum,
2319a747e4fSDavid du Colombier Qrpc,
2329a747e4fSDavid du Colombier Qkeylist,
2339a747e4fSDavid du Colombier Qprotolist,
2349a747e4fSDavid du Colombier Qconfirm,
2359a747e4fSDavid du Colombier Qlog,
2369a747e4fSDavid du Colombier Qctl,
2379a747e4fSDavid du Colombier Qneedkey,
2389a747e4fSDavid du Colombier };
2399a747e4fSDavid du Colombier
2409a747e4fSDavid du Colombier Qid
mkqid(int type,int path)2419a747e4fSDavid du Colombier mkqid(int type, int path)
2429a747e4fSDavid du Colombier {
2439a747e4fSDavid du Colombier Qid q;
2449a747e4fSDavid du Colombier
2459a747e4fSDavid du Colombier q.type = type;
2469a747e4fSDavid du Colombier q.path = path;
2479a747e4fSDavid du Colombier q.vers = 0;
2489a747e4fSDavid du Colombier return q;
2499a747e4fSDavid du Colombier }
2509a747e4fSDavid du Colombier
2519a747e4fSDavid du Colombier static void
fsattach(Req * r)2529a747e4fSDavid du Colombier fsattach(Req *r)
2539a747e4fSDavid du Colombier {
2549a747e4fSDavid du Colombier r->fid->qid = mkqid(QTDIR, Qroot);
2559a747e4fSDavid du Colombier r->ofcall.qid = r->fid->qid;
2569a747e4fSDavid du Colombier respond(r, nil);
2579a747e4fSDavid du Colombier }
2589a747e4fSDavid du Colombier
2599a747e4fSDavid du Colombier static struct {
2609a747e4fSDavid du Colombier char *name;
2619a747e4fSDavid du Colombier int qidpath;
2629a747e4fSDavid du Colombier ulong perm;
2639a747e4fSDavid du Colombier } dirtab[] = {
2649a747e4fSDavid du Colombier "confirm", Qconfirm, 0600|DMEXCL, /* we know this is slot #0 below */
2659a747e4fSDavid du Colombier "needkey", Qneedkey, 0600|DMEXCL, /* we know this is slot #1 below */
266fb7f0c93SDavid du Colombier "ctl", Qctl, 0644,
2679a747e4fSDavid du Colombier "rpc", Qrpc, 0666,
2689a747e4fSDavid du Colombier "proto", Qprotolist, 0444,
2699a747e4fSDavid du Colombier "log", Qlog, 0400|DMEXCL,
2709a747e4fSDavid du Colombier };
2719a747e4fSDavid du Colombier static int inuse[nelem(dirtab)];
2729a747e4fSDavid du Colombier int *confirminuse = &inuse[0];
2739a747e4fSDavid du Colombier int *needkeyinuse = &inuse[1];
2749a747e4fSDavid du Colombier
2759a747e4fSDavid du Colombier static void
fillstat(Dir * dir,char * name,int type,int path,ulong perm)2769a747e4fSDavid du Colombier fillstat(Dir *dir, char *name, int type, int path, ulong perm)
2779a747e4fSDavid du Colombier {
2789a747e4fSDavid du Colombier dir->name = estrdup(name);
279fb7f0c93SDavid du Colombier dir->uid = estrdup(owner);
280fb7f0c93SDavid du Colombier dir->gid = estrdup(owner);
2819a747e4fSDavid du Colombier dir->mode = perm;
2829a747e4fSDavid du Colombier dir->length = 0;
2839a747e4fSDavid du Colombier dir->qid = mkqid(type, path);
2849a747e4fSDavid du Colombier dir->atime = time(0);
2859a747e4fSDavid du Colombier dir->mtime = time(0);
2869a747e4fSDavid du Colombier dir->muid = estrdup("");
2879a747e4fSDavid du Colombier }
2889a747e4fSDavid du Colombier
2899a747e4fSDavid du Colombier static int
rootdirgen(int n,Dir * dir,void *)2909a747e4fSDavid du Colombier rootdirgen(int n, Dir *dir, void*)
2919a747e4fSDavid du Colombier {
2929a747e4fSDavid du Colombier if(n > 0)
2939a747e4fSDavid du Colombier return -1;
2949a747e4fSDavid du Colombier fillstat(dir, "factotum", QTDIR, Qfactotum, DMDIR|0555);
2959a747e4fSDavid du Colombier return 0;
2969a747e4fSDavid du Colombier }
2979a747e4fSDavid du Colombier
2989a747e4fSDavid du Colombier static int
fsdirgen(int n,Dir * dir,void *)2999a747e4fSDavid du Colombier fsdirgen(int n, Dir *dir, void*)
3009a747e4fSDavid du Colombier {
3019a747e4fSDavid du Colombier if(n >= nelem(dirtab))
3029a747e4fSDavid du Colombier return -1;
3039a747e4fSDavid du Colombier fillstat(dir, dirtab[n].name, 0, dirtab[n].qidpath, dirtab[n].perm);
3049a747e4fSDavid du Colombier return 0;
3059a747e4fSDavid du Colombier }
3069a747e4fSDavid du Colombier
3079a747e4fSDavid du Colombier static char*
fswalk1(Fid * fid,char * name,Qid * qid)3089a747e4fSDavid du Colombier fswalk1(Fid *fid, char *name, Qid *qid)
3099a747e4fSDavid du Colombier {
3109a747e4fSDavid du Colombier int i;
3119a747e4fSDavid du Colombier
3129a747e4fSDavid du Colombier switch((ulong)fid->qid.path){
3139a747e4fSDavid du Colombier default:
3149a747e4fSDavid du Colombier return "cannot happen";
3159a747e4fSDavid du Colombier case Qroot:
3169a747e4fSDavid du Colombier if(strcmp(name, "factotum") == 0){
3179a747e4fSDavid du Colombier *qid = mkqid(QTDIR, Qfactotum);
3189a747e4fSDavid du Colombier fid->qid = *qid;
3199a747e4fSDavid du Colombier return nil;
3209a747e4fSDavid du Colombier }
3219a747e4fSDavid du Colombier if(strcmp(name, "..") == 0){
3229a747e4fSDavid du Colombier *qid = fid->qid;
3239a747e4fSDavid du Colombier return nil;
3249a747e4fSDavid du Colombier }
3259a747e4fSDavid du Colombier return "not found";
3269a747e4fSDavid du Colombier case Qfactotum:
3279a747e4fSDavid du Colombier for(i=0; i<nelem(dirtab); i++)
3289a747e4fSDavid du Colombier if(strcmp(name, dirtab[i].name) == 0){
3299a747e4fSDavid du Colombier *qid = mkqid(0, dirtab[i].qidpath);
3309a747e4fSDavid du Colombier fid->qid = *qid;
3319a747e4fSDavid du Colombier return nil;
3329a747e4fSDavid du Colombier }
3339a747e4fSDavid du Colombier if(strcmp(name, "..") == 0){
3349a747e4fSDavid du Colombier *qid = mkqid(QTDIR, Qroot);
3359a747e4fSDavid du Colombier fid->qid = *qid;
3369a747e4fSDavid du Colombier return nil;
3379a747e4fSDavid du Colombier }
3389a747e4fSDavid du Colombier return "not found";
3399a747e4fSDavid du Colombier }
3409a747e4fSDavid du Colombier }
3419a747e4fSDavid du Colombier
3429a747e4fSDavid du Colombier static void
fsstat(Req * r)3439a747e4fSDavid du Colombier fsstat(Req *r)
3449a747e4fSDavid du Colombier {
3459a747e4fSDavid du Colombier int i;
3469a747e4fSDavid du Colombier ulong path;
3479a747e4fSDavid du Colombier
3489a747e4fSDavid du Colombier path = r->fid->qid.path;
3499a747e4fSDavid du Colombier if(path == Qroot){
3509a747e4fSDavid du Colombier fillstat(&r->d, "/", QTDIR, Qroot, 0555|DMDIR);
3519a747e4fSDavid du Colombier respond(r, nil);
3529a747e4fSDavid du Colombier return;
3539a747e4fSDavid du Colombier }
3549a747e4fSDavid du Colombier if(path == Qfactotum){
3559a747e4fSDavid du Colombier fillstat(&r->d, "factotum", QTDIR, Qfactotum, 0555|DMDIR);
3569a747e4fSDavid du Colombier respond(r, nil);
3579a747e4fSDavid du Colombier return;
3589a747e4fSDavid du Colombier }
3599a747e4fSDavid du Colombier for(i=0; i<nelem(dirtab); i++)
3609a747e4fSDavid du Colombier if(dirtab[i].qidpath == path){
3619a747e4fSDavid du Colombier fillstat(&r->d, dirtab[i].name, 0, dirtab[i].qidpath, dirtab[i].perm);
3629a747e4fSDavid du Colombier respond(r, nil);
3639a747e4fSDavid du Colombier return;
3649a747e4fSDavid du Colombier }
3659a747e4fSDavid du Colombier respond(r, "file not found");
3669a747e4fSDavid du Colombier }
3679a747e4fSDavid du Colombier
3689a747e4fSDavid du Colombier static void
fsopen(Req * r)3699a747e4fSDavid du Colombier fsopen(Req *r)
3709a747e4fSDavid du Colombier {
3719a747e4fSDavid du Colombier int i, *p, perm;
3729a747e4fSDavid du Colombier static int need[4] = {4, 2, 6, 1};
373d35914a8SDavid du Colombier int n;
3749a747e4fSDavid du Colombier Fsstate *fss;
3759a747e4fSDavid du Colombier
3769a747e4fSDavid du Colombier p = nil;
3779a747e4fSDavid du Colombier for(i=0; i<nelem(dirtab); i++)
3789a747e4fSDavid du Colombier if(dirtab[i].qidpath == r->fid->qid.path)
3799a747e4fSDavid du Colombier break;
3809a747e4fSDavid du Colombier if(i < nelem(dirtab)){
3819a747e4fSDavid du Colombier if(dirtab[i].perm & DMEXCL)
3829a747e4fSDavid du Colombier p = &inuse[i];
383fb7f0c93SDavid du Colombier if(strcmp(r->fid->uid, owner) == 0)
3849a747e4fSDavid du Colombier perm = dirtab[i].perm>>6;
3859a747e4fSDavid du Colombier else
3869a747e4fSDavid du Colombier perm = dirtab[i].perm;
3879a747e4fSDavid du Colombier }else
3889a747e4fSDavid du Colombier perm = 5;
3899a747e4fSDavid du Colombier
390d35914a8SDavid du Colombier n = need[r->ifcall.mode&3];
391d35914a8SDavid du Colombier if((r->ifcall.mode&~(3|OTRUNC)) || ((perm&n) != n)){
3929a747e4fSDavid du Colombier respond(r, "permission denied");
3939a747e4fSDavid du Colombier return;
3949a747e4fSDavid du Colombier }
3959a747e4fSDavid du Colombier if(p){
3969a747e4fSDavid du Colombier if(*p){
3979a747e4fSDavid du Colombier respond(r, "file in use");
3989a747e4fSDavid du Colombier return;
3999a747e4fSDavid du Colombier }
4009a747e4fSDavid du Colombier (*p)++;
4019a747e4fSDavid du Colombier }
4029a747e4fSDavid du Colombier
4039a747e4fSDavid du Colombier r->fid->aux = fss = emalloc(sizeof(Fsstate));
404d9306527SDavid du Colombier fss->phase = Notstarted;
4059a747e4fSDavid du Colombier fss->sysuser = r->fid->uid;
4069a747e4fSDavid du Colombier fss->attr = nil;
4079a747e4fSDavid du Colombier strcpy(fss->err, "factotum/fs.c no error");
4089a747e4fSDavid du Colombier respond(r, nil);
4099a747e4fSDavid du Colombier }
4109a747e4fSDavid du Colombier
4119a747e4fSDavid du Colombier static void
fsdestroyfid(Fid * fid)4129a747e4fSDavid du Colombier fsdestroyfid(Fid *fid)
4139a747e4fSDavid du Colombier {
4149a747e4fSDavid du Colombier int i;
4159a747e4fSDavid du Colombier Fsstate *fss;
4169a747e4fSDavid du Colombier
4179a747e4fSDavid du Colombier if(fid->omode != -1){
4189a747e4fSDavid du Colombier for(i=0; i<nelem(dirtab); i++)
4199a747e4fSDavid du Colombier if(dirtab[i].qidpath == fid->qid.path)
4209a747e4fSDavid du Colombier if(dirtab[i].perm&DMEXCL)
4219a747e4fSDavid du Colombier inuse[i] = 0;
4229a747e4fSDavid du Colombier }
4239a747e4fSDavid du Colombier
4249a747e4fSDavid du Colombier fss = fid->aux;
4259a747e4fSDavid du Colombier if(fss == nil)
4269a747e4fSDavid du Colombier return;
4279a747e4fSDavid du Colombier if(fss->ps)
4289a747e4fSDavid du Colombier (*fss->proto->close)(fss);
4299a747e4fSDavid du Colombier _freeattr(fss->attr);
4309a747e4fSDavid du Colombier free(fss);
4319a747e4fSDavid du Colombier }
4329a747e4fSDavid du Colombier
4339a747e4fSDavid du Colombier static int
readlist(int off,int (* gen)(int,char *,uint,Fsstate *),Req * r,Fsstate * fss)434fb7f0c93SDavid du Colombier readlist(int off, int (*gen)(int, char*, uint, Fsstate*), Req *r, Fsstate *fss)
4359a747e4fSDavid du Colombier {
4369a747e4fSDavid du Colombier char *a, *ea;
4379a747e4fSDavid du Colombier int n;
4389a747e4fSDavid du Colombier
4399a747e4fSDavid du Colombier a = r->ofcall.data;
4409a747e4fSDavid du Colombier ea = a+r->ifcall.count;
4419a747e4fSDavid du Colombier for(;;){
442fb7f0c93SDavid du Colombier n = (*gen)(off, a, ea-a, fss);
4439a747e4fSDavid du Colombier if(n == 0){
4449a747e4fSDavid du Colombier r->ofcall.count = a - (char*)r->ofcall.data;
4459a747e4fSDavid du Colombier return off;
4469a747e4fSDavid du Colombier }
4479a747e4fSDavid du Colombier a += n;
4489a747e4fSDavid du Colombier off++;
4499a747e4fSDavid du Colombier }
4509a747e4fSDavid du Colombier }
4519a747e4fSDavid du Colombier
452*3b86f2f8SDavid du Colombier enum { Nearend = 2, }; /* at least room for \n and NUL */
453*3b86f2f8SDavid du Colombier
454*3b86f2f8SDavid du Colombier /* result in `a', of `n' bytes maximum */
4559a747e4fSDavid du Colombier static int
keylist(int i,char * a,uint n,Fsstate * fss)456fb7f0c93SDavid du Colombier keylist(int i, char *a, uint n, Fsstate *fss)
4579a747e4fSDavid du Colombier {
458*3b86f2f8SDavid du Colombier int wb;
459260f7b65SDavid du Colombier Keyinfo ki;
4609a747e4fSDavid du Colombier Key *k;
461*3b86f2f8SDavid du Colombier static char zero[Nearend];
4629a747e4fSDavid du Colombier
463fb7f0c93SDavid du Colombier k = nil;
464260f7b65SDavid du Colombier mkkeyinfo(&ki, fss, nil);
465260f7b65SDavid du Colombier ki.attr = nil;
466260f7b65SDavid du Colombier ki.skip = i;
467260f7b65SDavid du Colombier ki.usedisabled = 1;
468260f7b65SDavid du Colombier if(findkey(&k, &ki, "") != RpcOk)
4699a747e4fSDavid du Colombier return 0;
470*3b86f2f8SDavid du Colombier
471*3b86f2f8SDavid du Colombier memset(a + n - Nearend, 0, Nearend);
472*3b86f2f8SDavid du Colombier wb = snprint(a, n, "key %A %N\n", k->attr, k->privattr);
473fb7f0c93SDavid du Colombier closekey(k);
474*3b86f2f8SDavid du Colombier if (wb >= n - 1 && a[n - 2] != '\n' && a[n - 2] != '\0') {
475*3b86f2f8SDavid du Colombier /* line won't fit in `a', so just truncate */
476*3b86f2f8SDavid du Colombier strcpy(a + n - 2, "\n");
4779a747e4fSDavid du Colombier return 0;
478*3b86f2f8SDavid du Colombier }
479*3b86f2f8SDavid du Colombier return wb;
4809a747e4fSDavid du Colombier }
4819a747e4fSDavid du Colombier
4829a747e4fSDavid du Colombier static int
protolist(int i,char * a,uint n,Fsstate * fss)483fb7f0c93SDavid du Colombier protolist(int i, char *a, uint n, Fsstate *fss)
4849a747e4fSDavid du Colombier {
485fb7f0c93SDavid du Colombier USED(fss);
486fb7f0c93SDavid du Colombier
4879a747e4fSDavid du Colombier if(i >= nelem(prototab)-1)
4889a747e4fSDavid du Colombier return 0;
4899a747e4fSDavid du Colombier if(strlen(prototab[i]->name)+1 > n)
4909a747e4fSDavid du Colombier return 0;
4919a747e4fSDavid du Colombier n = strlen(prototab[i]->name)+1;
4929a747e4fSDavid du Colombier memmove(a, prototab[i]->name, n-1);
4939a747e4fSDavid du Colombier a[n-1] = '\n';
4949a747e4fSDavid du Colombier return n;
4959a747e4fSDavid du Colombier }
4969a747e4fSDavid du Colombier
4979a747e4fSDavid du Colombier static void
fsread(Req * r)4989a747e4fSDavid du Colombier fsread(Req *r)
4999a747e4fSDavid du Colombier {
5009a747e4fSDavid du Colombier Fsstate *s;
5019a747e4fSDavid du Colombier
5029a747e4fSDavid du Colombier s = r->fid->aux;
5039a747e4fSDavid du Colombier switch((ulong)r->fid->qid.path){
5049a747e4fSDavid du Colombier default:
5059a747e4fSDavid du Colombier respond(r, "bug in fsread");
5069a747e4fSDavid du Colombier break;
5079a747e4fSDavid du Colombier case Qroot:
5089a747e4fSDavid du Colombier dirread9p(r, rootdirgen, nil);
5099a747e4fSDavid du Colombier respond(r, nil);
5109a747e4fSDavid du Colombier break;
5119a747e4fSDavid du Colombier case Qfactotum:
5129a747e4fSDavid du Colombier dirread9p(r, fsdirgen, nil);
5139a747e4fSDavid du Colombier respond(r, nil);
5149a747e4fSDavid du Colombier break;
5159a747e4fSDavid du Colombier case Qrpc:
5169a747e4fSDavid du Colombier rpcread(r);
5179a747e4fSDavid du Colombier break;
5189a747e4fSDavid du Colombier case Qneedkey:
5199a747e4fSDavid du Colombier needkeyread(r);
5209a747e4fSDavid du Colombier break;
5219a747e4fSDavid du Colombier case Qconfirm:
5229a747e4fSDavid du Colombier confirmread(r);
5239a747e4fSDavid du Colombier break;
5249a747e4fSDavid du Colombier case Qlog:
5259a747e4fSDavid du Colombier logread(r);
5269a747e4fSDavid du Colombier break;
5279a747e4fSDavid du Colombier case Qctl:
528fb7f0c93SDavid du Colombier s->listoff = readlist(s->listoff, keylist, r, s);
5299a747e4fSDavid du Colombier respond(r, nil);
5309a747e4fSDavid du Colombier break;
5319a747e4fSDavid du Colombier case Qprotolist:
532fb7f0c93SDavid du Colombier s->listoff = readlist(s->listoff, protolist, r, s);
5339a747e4fSDavid du Colombier respond(r, nil);
5349a747e4fSDavid du Colombier break;
5359a747e4fSDavid du Colombier }
5369a747e4fSDavid du Colombier }
5379a747e4fSDavid du Colombier
5389a747e4fSDavid du Colombier static void
fswrite(Req * r)5399a747e4fSDavid du Colombier fswrite(Req *r)
5409a747e4fSDavid du Colombier {
5419a747e4fSDavid du Colombier int ret;
5429a747e4fSDavid du Colombier char err[ERRMAX], *s;
5439a747e4fSDavid du Colombier
5449a747e4fSDavid du Colombier switch((ulong)r->fid->qid.path){
5459a747e4fSDavid du Colombier default:
5469a747e4fSDavid du Colombier respond(r, "bug in fswrite");
5479a747e4fSDavid du Colombier break;
5489a747e4fSDavid du Colombier case Qrpc:
5499a747e4fSDavid du Colombier rpcwrite(r);
5509a747e4fSDavid du Colombier break;
5519a747e4fSDavid du Colombier case Qneedkey:
5529a747e4fSDavid du Colombier case Qconfirm:
5539a747e4fSDavid du Colombier case Qctl:
5549a747e4fSDavid du Colombier s = emalloc(r->ifcall.count+1);
5559a747e4fSDavid du Colombier memmove(s, r->ifcall.data, r->ifcall.count);
5569a747e4fSDavid du Colombier s[r->ifcall.count] = '\0';
5579a747e4fSDavid du Colombier switch((ulong)r->fid->qid.path){
5589a747e4fSDavid du Colombier default:
5599a747e4fSDavid du Colombier abort();
5609a747e4fSDavid du Colombier case Qneedkey:
5619a747e4fSDavid du Colombier ret = needkeywrite(s);
5629a747e4fSDavid du Colombier break;
5639a747e4fSDavid du Colombier case Qconfirm:
5649a747e4fSDavid du Colombier ret = confirmwrite(s);
5659a747e4fSDavid du Colombier break;
5669a747e4fSDavid du Colombier case Qctl:
567260f7b65SDavid du Colombier ret = ctlwrite(s, 0);
5689a747e4fSDavid du Colombier break;
5699a747e4fSDavid du Colombier }
5709a747e4fSDavid du Colombier free(s);
5719a747e4fSDavid du Colombier if(ret < 0){
5729a747e4fSDavid du Colombier rerrstr(err, sizeof err);
5739a747e4fSDavid du Colombier respond(r, err);
5749a747e4fSDavid du Colombier }else{
5759a747e4fSDavid du Colombier r->ofcall.count = r->ifcall.count;
5769a747e4fSDavid du Colombier respond(r, nil);
5779a747e4fSDavid du Colombier }
5789a747e4fSDavid du Colombier break;
5799a747e4fSDavid du Colombier }
5809a747e4fSDavid du Colombier }
5819a747e4fSDavid du Colombier
5829a747e4fSDavid du Colombier static void
fsflush(Req * r)5839a747e4fSDavid du Colombier fsflush(Req *r)
5849a747e4fSDavid du Colombier {
5859a747e4fSDavid du Colombier confirmflush(r->oldreq);
5869a747e4fSDavid du Colombier needkeyflush(r->oldreq);
5879a747e4fSDavid du Colombier logflush(r->oldreq);
5889a747e4fSDavid du Colombier respond(r, nil);
5899a747e4fSDavid du Colombier }
5909a747e4fSDavid du Colombier
5919a747e4fSDavid du Colombier Srv fs = {
5929a747e4fSDavid du Colombier .attach= fsattach,
5939a747e4fSDavid du Colombier .walk1= fswalk1,
5949a747e4fSDavid du Colombier .open= fsopen,
5959a747e4fSDavid du Colombier .read= fsread,
5969a747e4fSDavid du Colombier .write= fswrite,
5979a747e4fSDavid du Colombier .stat= fsstat,
5989a747e4fSDavid du Colombier .flush= fsflush,
5999a747e4fSDavid du Colombier .destroyfid= fsdestroyfid,
6009a747e4fSDavid du Colombier };
6019a747e4fSDavid du Colombier
602