#include #include #include #include #include "dat.h" #include "fns.h" enum { MAXARGS = 16 }; typedef struct Cmd Cmd; static int echo; extern Fs *fsmain; struct Cmd { char *name; int args; int (*f)(int, char **); }; static int walkpath(Chan *ch, char *path, char **cr) { char buf[NAMELEN], *p, *fp; fp = path; if(*path != '/'){ noent: werrstr("%s: %s", fp, Enoent); return -1; } path++; for(;;){ p = strchr(path, '/'); if(p == nil){ if(cr != nil){ if(*path == 0){ werrstr("%s: trailing slash", fp); return -1; } *cr = path; break; } p = path + strlen(path); } if(*path == '/'){ path++; continue; } if(*path == 0) break; if(p - path >= NAMELEN) goto noent; memset(buf, 0, sizeof buf); memcpy(buf, path, p - path); if(chanwalk(ch, buf) <= 0){ werrstr("%s: %r", fp); return -1; } if(*p == 0) break; path = p + 1; } return 1; } int cmdhalt(int, char **) { shutdown(); return 0; } int cmddump(int, char **) { fsdump(fsmain); dprint("hjfs: dumped\n"); return 0; } int cmdallow(int, char **) { fsmain->flags |= FSNOPERM | FSCHOWN; dprint("hjfs: allow\n"); return 0; } int cmdchatty(int, char **) { extern int chatty9p; chatty9p = !chatty9p; return 0; } int cmddisallow(int, char **) { fsmain->flags &= ~(FSNOPERM | FSCHOWN); dprint("hjfs: disallow\n"); return 0; } int cmdnoauth(int, char **) { fsmain->flags ^= FSNOAUTH; if((fsmain->flags & FSNOAUTH) == 0) dprint("hjfs: auth enabled\n"); else dprint("hjfs: auth disabled\n"); return 1; } int cmdcreate(int argc, char **argv) { Chan *ch; char *n; short uid, gid; ulong perm; Dir di; if(argc != 5 && argc != 6) return -9001; perm = strtol(argv[4], &n, 8) & 0777; if(*n != 0) return -9001; if(argc == 6) for(n = argv[5]; *n != 0; n++) switch(*n){ case 'l': perm |= DMEXCL; break; case 'd': perm |= DMDIR; break; case 'a': perm |= DMAPPEND; break; default: return -9001; } if(name2uid(fsmain, argv[2], &uid) < 0) return -1; if(name2uid(fsmain, argv[3], &gid) < 0) return -1; ch = chanattach(fsmain, 0); if(ch == nil) return -1; ch->uid = uid; if(walkpath(ch, argv[1], &n) < 0){ chanclunk(ch); return -1; } if(chancreat(ch, n, perm, OREAD) < 0){ chanclunk(ch); return -1; } nulldir(&di); di.gid = argv[3]; chanwstat(ch, &di); chanclunk(ch); return 1; } int cmdecho(int, char **argv) { echo = strcmp(argv[1], "on") == 0; return 1; } extern int cmdnewuser(int, char **); Cmd cmds[] = { {"allow", 1, cmdallow}, {"noauth", 1, cmdnoauth}, {"chatty", 1, cmdchatty}, {"create", 0, cmdcreate}, {"disallow", 1, cmddisallow}, {"dump", 1, cmddump}, {"halt", 1, cmdhalt}, {"newuser", 0, cmdnewuser}, {"echo", 2, cmdecho}, }; static void consproc(void *v) { Biobuf *in; Cmd *c; char *s; char *args[MAXARGS]; int rc; in = (Biobuf *) v; for(;;){ s = Brdstr(in, '\n', 1); if(s == nil) continue; if(echo) dprint("hjfs: >%s\n", s); rc = tokenize(s, args, MAXARGS); if(rc == 0) goto syntax; for(c = cmds; c < cmds + nelem(cmds); c++) if(strcmp(c->name, args[0]) == 0){ if(c->args != 0 && c->args != rc) goto syntax; if(c->f != nil){ rc = c->f(rc, args); if(rc == -9001) goto syntax; if(rc < 0) dprint("hjfs: %r\n"); goto done; } } syntax: dprint("hjfs: syntax error\n"); done: free(s); } } void initcons(char *service) { int fd, pfd[2]; static Biobuf bio; char buf[512]; snprint(buf, sizeof(buf), "/srv/%s.cmd", service); fd = create(buf, OWRITE|ORCLOSE, 0600); if(fd < 0) return; pipe(pfd); fprint(fd, "%d", pfd[1]); Binit(&bio, pfd[0], OREAD); proccreate(consproc, &bio, mainstacksize); }