diff options
author | David du Colombier <0intro@gmail.com> | 2013-09-23 23:00:39 +0200 |
---|---|---|
committer | David du Colombier <0intro@gmail.com> | 2013-09-23 23:00:39 +0200 |
commit | 6f4d00ee45693290fae042b27536b54f77b96acd (patch) | |
tree | 60ad31bf16ed2000661c02345dd2a63851588a5d /src/cmd/fossil/Ccmd.c | |
parent | fea86f063930ea187f1c77e93207ac8d39125520 (diff) | |
download | plan9port-6f4d00ee45693290fae042b27536b54f77b96acd.tar.gz plan9port-6f4d00ee45693290fae042b27536b54f77b96acd.tar.bz2 plan9port-6f4d00ee45693290fae042b27536b54f77b96acd.zip |
fossil: import from plan 9
R=rsc
https://codereview.appspot.com/7988047
Diffstat (limited to 'src/cmd/fossil/Ccmd.c')
-rw-r--r-- | src/cmd/fossil/Ccmd.c | 459 |
1 files changed, 459 insertions, 0 deletions
diff --git a/src/cmd/fossil/Ccmd.c b/src/cmd/fossil/Ccmd.c new file mode 100644 index 00000000..806c62ff --- /dev/null +++ b/src/cmd/fossil/Ccmd.c @@ -0,0 +1,459 @@ +#include "stdinc.h" + +#include "9.h" + +static struct { + VtLock* lock; + + Con* con; + int confd[2]; + ushort tag; +} cbox; + +static ulong +cmd9pStrtoul(char* s) +{ + if(strcmp(s, "~0") == 0) + return ~0UL; + return strtoul(s, 0, 0); +} + +static uvlong +cmd9pStrtoull(char* s) +{ + if(strcmp(s, "~0") == 0) + return ~0ULL; + return strtoull(s, 0, 0); +} + +static int +cmd9pTag(Fcall*, int, char **argv) +{ + cbox.tag = strtoul(argv[0], 0, 0)-1; + + return 1; +} + +static int +cmd9pTwstat(Fcall* f, int, char **argv) +{ + Dir d; + static uchar buf[DIRMAX]; + + memset(&d, 0, sizeof d); + nulldir(&d); + d.name = argv[1]; + d.uid = argv[2]; + d.gid = argv[3]; + d.mode = cmd9pStrtoul(argv[4]); + d.mtime = cmd9pStrtoul(argv[5]); + d.length = cmd9pStrtoull(argv[6]); + + f->fid = strtol(argv[0], 0, 0); + f->stat = buf; + f->nstat = convD2M(&d, buf, sizeof buf); + if(f->nstat < BIT16SZ){ + vtSetError("Twstat: convD2M failed (internal error)"); + return 0; + } + + return 1; +} + +static int +cmd9pTstat(Fcall* f, int, char** argv) +{ + f->fid = strtol(argv[0], 0, 0); + + return 1; +} + +static int +cmd9pTremove(Fcall* f, int, char** argv) +{ + f->fid = strtol(argv[0], 0, 0); + + return 1; +} + +static int +cmd9pTclunk(Fcall* f, int, char** argv) +{ + f->fid = strtol(argv[0], 0, 0); + + return 1; +} + +static int +cmd9pTwrite(Fcall* f, int, char** argv) +{ + f->fid = strtol(argv[0], 0, 0); + f->offset = strtoll(argv[1], 0, 0); + f->data = argv[2]; + f->count = strlen(argv[2]); + + return 1; +} + +static int +cmd9pTread(Fcall* f, int, char** argv) +{ + f->fid = strtol(argv[0], 0, 0); + f->offset = strtoll(argv[1], 0, 0); + f->count = strtol(argv[2], 0, 0); + + return 1; +} + +static int +cmd9pTcreate(Fcall* f, int, char** argv) +{ + f->fid = strtol(argv[0], 0, 0); + f->name = argv[1]; + f->perm = strtol(argv[2], 0, 8); + f->mode = strtol(argv[3], 0, 0); + + return 1; +} + +static int +cmd9pTopen(Fcall* f, int, char** argv) +{ + f->fid = strtol(argv[0], 0, 0); + f->mode = strtol(argv[1], 0, 0); + + return 1; +} + +static int +cmd9pTwalk(Fcall* f, int argc, char** argv) +{ + int i; + + if(argc < 2){ + vtSetError("usage: Twalk tag fid newfid [name...]"); + return 0; + } + f->fid = strtol(argv[0], 0, 0); + f->newfid = strtol(argv[1], 0, 0); + f->nwname = argc-2; + if(f->nwname > MAXWELEM){ + vtSetError("Twalk: too many names"); + return 0; + } + for(i = 0; i < argc-2; i++) + f->wname[i] = argv[2+i]; + + return 1; +} + +static int +cmd9pTflush(Fcall* f, int, char** argv) +{ + f->oldtag = strtol(argv[0], 0, 0); + + return 1; +} + +static int +cmd9pTattach(Fcall* f, int, char** argv) +{ + f->fid = strtol(argv[0], 0, 0); + f->afid = strtol(argv[1], 0, 0); + f->uname = argv[2]; + f->aname = argv[3]; + + return 1; +} + +static int +cmd9pTauth(Fcall* f, int, char** argv) +{ + f->afid = strtol(argv[0], 0, 0); + f->uname = argv[1]; + f->aname = argv[2]; + + return 1; +} + +static int +cmd9pTversion(Fcall* f, int, char** argv) +{ + f->msize = strtoul(argv[0], 0, 0); + if(f->msize > cbox.con->msize){ + vtSetError("msize too big"); + return 0; + } + f->version = argv[1]; + + return 1; +} + +typedef struct Cmd9p Cmd9p; +struct Cmd9p { + char* name; + int type; + int argc; + char* usage; + int (*f)(Fcall*, int, char**); +}; + +static Cmd9p cmd9pTmsg[] = { + "Tversion", Tversion, 2, "msize version", cmd9pTversion, + "Tauth", Tauth, 3, "afid uname aname", cmd9pTauth, + "Tflush", Tflush, 1, "oldtag", cmd9pTflush, + "Tattach", Tattach, 4, "fid afid uname aname", cmd9pTattach, + "Twalk", Twalk, 0, "fid newfid [name...]", cmd9pTwalk, + "Topen", Topen, 2, "fid mode", cmd9pTopen, + "Tcreate", Tcreate, 4, "fid name perm mode", cmd9pTcreate, + "Tread", Tread, 3, "fid offset count", cmd9pTread, + "Twrite", Twrite, 3, "fid offset data", cmd9pTwrite, + "Tclunk", Tclunk, 1, "fid", cmd9pTclunk, + "Tremove", Tremove, 1, "fid", cmd9pTremove, + "Tstat", Tstat, 1, "fid", cmd9pTstat, + "Twstat", Twstat, 7, "fid name uid gid mode mtime length", cmd9pTwstat, + "nexttag", 0, 0, "", cmd9pTag, +}; + +static int +cmd9p(int argc, char* argv[]) +{ + int i, n; + Fcall f, t; + uchar *buf; + char *usage; + u32int msize; + + usage = "usage: 9p T-message ..."; + + ARGBEGIN{ + default: + return cliError(usage); + }ARGEND + if(argc < 1) + return cliError(usage); + + for(i = 0; i < nelem(cmd9pTmsg); i++){ + if(strcmp(cmd9pTmsg[i].name, argv[0]) == 0) + break; + } + if(i == nelem(cmd9pTmsg)) + return cliError(usage); + argc--; + argv++; + if(cmd9pTmsg[i].argc && argc != cmd9pTmsg[i].argc){ + vtSetError("usage: %s %s", + cmd9pTmsg[i].name, cmd9pTmsg[i].usage); + return 0; + } + + memset(&t, 0, sizeof(t)); + t.type = cmd9pTmsg[i].type; + if(t.type == Tversion) + t.tag = NOTAG; + else + t.tag = ++cbox.tag; + msize = cbox.con->msize; + if(!cmd9pTmsg[i].f(&t, argc, argv)) + return 0; + buf = vtMemAlloc(msize); + n = convS2M(&t, buf, msize); + if(n <= BIT16SZ){ + vtSetError("%s: convS2M error", cmd9pTmsg[i].name); + vtMemFree(buf); + return 0; + } + if(write(cbox.confd[0], buf, n) != n){ + vtSetError("%s: write error: %r", cmd9pTmsg[i].name); + vtMemFree(buf); + return 0; + } + consPrint("\t-> %F\n", &t); + + if((n = read9pmsg(cbox.confd[0], buf, msize)) <= 0){ + vtSetError("%s: read error: %r", cmd9pTmsg[i].name); + vtMemFree(buf); + return 0; + } + if(convM2S(buf, n, &f) == 0){ + vtSetError("%s: convM2S error", cmd9pTmsg[i].name); + vtMemFree(buf); + return 0; + } + consPrint("\t<- %F\n", &f); + + vtMemFree(buf); + return 1; +} + +static int +cmdDot(int argc, char* argv[]) +{ + long l; + Dir *dir; + int fd, r; + vlong length; + char *f, *p, *s, *usage; + + usage = "usage: . file"; + + ARGBEGIN{ + default: + return cliError(usage); + }ARGEND + if(argc != 1) + return cliError(usage); + + if((dir = dirstat(argv[0])) == nil) + return cliError(". dirstat %s: %r", argv[0]); + length = dir->length; + free(dir); + + r = 1; + if(length != 0){ + /* + * Read the whole file in. + */ + if((fd = open(argv[0], OREAD)) < 0) + return cliError(". open %s: %r", argv[0]); + f = vtMemAlloc(dir->length+1); + if((l = read(fd, f, length)) < 0){ + vtMemFree(f); + close(fd); + return cliError(". read %s: %r", argv[0]); + } + close(fd); + f[l] = '\0'; + + /* + * Call cliExec() for each line. + */ + for(p = s = f; *p != '\0'; p++){ + if(*p == '\n'){ + *p = '\0'; + if(cliExec(s) == 0){ + r = 0; + consPrint("%s: %R\n", s); + } + s = p+1; + } + } + vtMemFree(f); + } + + if(r == 0) + vtSetError("errors in . %#q", argv[0]); + return r; +} + +static int +cmdDflag(int argc, char* argv[]) +{ + char *usage; + + usage = "usage: dflag"; + + ARGBEGIN{ + default: + return cliError(usage); + }ARGEND + if(argc) + return cliError(usage); + + Dflag ^= 1; + consPrint("dflag %d\n", Dflag); + + return 1; +} + +static int +cmdEcho(int argc, char* argv[]) +{ + char *usage; + int i, nflag; + + nflag = 0; + usage = "usage: echo [-n] ..."; + + ARGBEGIN{ + default: + return cliError(usage); + case 'n': + nflag = 1; + break; + }ARGEND + + for(i = 0; i < argc; i++){ + if(i != 0) + consPrint(" %s", argv[i]); + else + consPrint(argv[i]); + } + if(!nflag) + consPrint("\n"); + + return 1; +} + +static int +cmdBind(int argc, char* argv[]) +{ + ulong flag = 0; + char *usage; + + usage = "usage: bind [-b|-a|-c|-bc|-ac] new old"; + + ARGBEGIN{ + case 'a': + flag |= MAFTER; + break; + case 'b': + flag |= MBEFORE; + break; + case 'c': + flag |= MCREATE; + break; + default: + return cliError(usage); + }ARGEND + + if(argc != 2 || (flag&MAFTER)&&(flag&MBEFORE)) + return cliError(usage); + + if(bind(argv[0], argv[1], flag) < 0){ + /* try to give a less confusing error than the default */ + if(access(argv[0], 0) < 0) + return cliError("bind: %s: %r", argv[0]); + else if(access(argv[1], 0) < 0) + return cliError("bind: %s: %r", argv[1]); + else + return cliError("bind %s %s: %r", argv[0], argv[1]); + } + return 1; +} + +int +cmdInit(void) +{ + cbox.lock = vtLockAlloc(); + cbox.confd[0] = cbox.confd[1] = -1; + + cliAddCmd(".", cmdDot); + cliAddCmd("9p", cmd9p); + cliAddCmd("dflag", cmdDflag); + cliAddCmd("echo", cmdEcho); + cliAddCmd("bind", cmdBind); + + if(pipe(cbox.confd) < 0) + return 0; + if((cbox.con = conAlloc(cbox.confd[1], "console", 0)) == nil){ + close(cbox.confd[0]); + close(cbox.confd[1]); + cbox.confd[0] = cbox.confd[1] = -1; + return 0; + + } + cbox.con->isconsole = 1; + + return 1; +} |