tCcmd.c - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       tCcmd.c (8093B)
       ---
            1 #include "stdinc.h"
            2 
            3 #include "9.h"
            4 
            5 static struct {
            6         QLock        lock;
            7 
            8         Con*        con;
            9         int        confd[2];
           10         ushort        tag;
           11 } cbox;
           12 
           13 static ulong
           14 cmd9pStrtoul(char* s)
           15 {
           16         if(strcmp(s, "~0") == 0)
           17                 return ~0UL;
           18         return strtoul(s, 0, 0);
           19 }
           20 
           21 static uvlong
           22 cmd9pStrtoull(char* s)
           23 {
           24         if(strcmp(s, "~0") == 0)
           25                 return ~0ULL;
           26         return strtoull(s, 0, 0);
           27 }
           28 
           29 static int
           30 cmd9pTag(Fcall* f, int i, char **argv)
           31 {
           32         USED(f);
           33         USED(i);
           34         cbox.tag = strtoul(argv[0], 0, 0)-1;
           35 
           36         return 1;
           37 }
           38 
           39 static int
           40 cmd9pTwstat(Fcall* f, int i, char **argv)
           41 {
           42         Dir d;
           43         static uchar buf[DIRMAX];
           44 
           45         USED(i);
           46         memset(&d, 0, sizeof d);
           47         nulldir(&d);
           48         d.name = argv[1];
           49         d.uid = argv[2];
           50         d.gid = argv[3];
           51         d.mode = cmd9pStrtoul(argv[4]);
           52         d.mtime = cmd9pStrtoul(argv[5]);
           53         d.length = cmd9pStrtoull(argv[6]);
           54 
           55         f->fid = strtol(argv[0], 0, 0);
           56         f->stat = buf;
           57         f->nstat = convD2M(&d, buf, sizeof buf);
           58         if(f->nstat < BIT16SZ){
           59                 werrstr("Twstat: convD2M failed (internal error)");
           60                 return 0;
           61         }
           62 
           63         return 1;
           64 }
           65 
           66 static int
           67 cmd9pTstat(Fcall* f, int i, char** argv)
           68 {
           69         USED(i);
           70         f->fid = strtol(argv[0], 0, 0);
           71 
           72         return 1;
           73 }
           74 
           75 static int
           76 cmd9pTremove(Fcall* f, int i, char** argv)
           77 {
           78         USED(i);
           79         f->fid = strtol(argv[0], 0, 0);
           80 
           81         return 1;
           82 }
           83 
           84 static int
           85 cmd9pTclunk(Fcall* f, int i, char** argv)
           86 {
           87         USED(i);
           88         f->fid = strtol(argv[0], 0, 0);
           89 
           90         return 1;
           91 }
           92 
           93 static int
           94 cmd9pTwrite(Fcall* f, int i, char** argv)
           95 {
           96         USED(i);
           97         f->fid = strtol(argv[0], 0, 0);
           98         f->offset = strtoll(argv[1], 0, 0);
           99         f->data = argv[2];
          100         f->count = strlen(argv[2]);
          101 
          102         return 1;
          103 }
          104 
          105 static int
          106 cmd9pTread(Fcall* f, int i, char** argv)
          107 {
          108         USED(i);
          109         f->fid = strtol(argv[0], 0, 0);
          110         f->offset = strtoll(argv[1], 0, 0);
          111         f->count = strtol(argv[2], 0, 0);
          112 
          113         return 1;
          114 }
          115 
          116 static int
          117 cmd9pTcreate(Fcall* f, int i, char** argv)
          118 {
          119         USED(i);
          120         f->fid = strtol(argv[0], 0, 0);
          121         f->name = argv[1];
          122         f->perm = strtol(argv[2], 0, 8);
          123         f->mode = strtol(argv[3], 0, 0);
          124 
          125         return 1;
          126 }
          127 
          128 static int
          129 cmd9pTopen(Fcall* f, int i, char** argv)
          130 {
          131         USED(i);
          132         f->fid = strtol(argv[0], 0, 0);
          133         f->mode = strtol(argv[1], 0, 0);
          134 
          135         return 1;
          136 }
          137 
          138 static int
          139 cmd9pTwalk(Fcall* f, int argc, char** argv)
          140 {
          141         int i;
          142 
          143         if(argc < 2){
          144                 werrstr("usage: Twalk tag fid newfid [name...]");
          145                 return 0;
          146         }
          147         f->fid = strtol(argv[0], 0, 0);
          148         f->newfid = strtol(argv[1], 0, 0);
          149         f->nwname = argc-2;
          150         if(f->nwname > MAXWELEM){
          151                 werrstr("Twalk: too many names");
          152                 return 0;
          153         }
          154         for(i = 0; i < argc-2; i++)
          155                 f->wname[i] = argv[2+i];
          156 
          157         return 1;
          158 }
          159 
          160 static int
          161 cmd9pTflush(Fcall* f, int i, char** argv)
          162 {
          163         USED(i);
          164         f->oldtag = strtol(argv[0], 0, 0);
          165 
          166         return 1;
          167 }
          168 
          169 static int
          170 cmd9pTattach(Fcall* f, int i, char** argv)
          171 {
          172         USED(i);
          173         f->fid = strtol(argv[0], 0, 0);
          174         f->afid = strtol(argv[1], 0, 0);
          175         f->uname = argv[2];
          176         f->aname = argv[3];
          177 
          178         return 1;
          179 }
          180 
          181 static int
          182 cmd9pTauth(Fcall* f, int i, char** argv)
          183 {
          184         USED(i);
          185         f->afid = strtol(argv[0], 0, 0);
          186         f->uname = argv[1];
          187         f->aname = argv[2];
          188 
          189         return 1;
          190 }
          191 
          192 static int
          193 cmd9pTversion(Fcall* f, int i, char** argv)
          194 {
          195         USED(i);
          196         f->msize = strtoul(argv[0], 0, 0);
          197         if(f->msize > cbox.con->msize){
          198                 werrstr("msize too big");
          199                 return 0;
          200         }
          201         f->version = argv[1];
          202 
          203         return 1;
          204 }
          205 
          206 typedef struct Cmd9p Cmd9p;
          207 struct Cmd9p {
          208         char*        name;
          209         int        type;
          210         int        argc;
          211         char*        usage;
          212         int        (*f)(Fcall*, int, char**);
          213 };
          214 
          215 static Cmd9p cmd9pTmsg[] = {
          216         "Tversion", Tversion, 2, "msize version", cmd9pTversion,
          217         "Tauth", Tauth, 3, "afid uname aname", cmd9pTauth,
          218         "Tflush", Tflush, 1, "oldtag", cmd9pTflush,
          219         "Tattach", Tattach, 4, "fid afid uname aname", cmd9pTattach,
          220         "Twalk", Twalk, 0, "fid newfid [name...]", cmd9pTwalk,
          221         "Topen", Topen, 2, "fid mode", cmd9pTopen,
          222         "Tcreate", Tcreate, 4, "fid name perm mode", cmd9pTcreate,
          223         "Tread", Tread, 3, "fid offset count", cmd9pTread,
          224         "Twrite", Twrite, 3, "fid offset data", cmd9pTwrite,
          225         "Tclunk", Tclunk, 1, "fid", cmd9pTclunk,
          226         "Tremove", Tremove, 1, "fid", cmd9pTremove,
          227         "Tstat", Tstat, 1, "fid", cmd9pTstat,
          228         "Twstat", Twstat, 7, "fid name uid gid mode mtime length", cmd9pTwstat,
          229         "nexttag", 0, 0, "", cmd9pTag,
          230 };
          231 
          232 static int
          233 cmd9p(int argc, char* argv[])
          234 {
          235         int i, n;
          236         Fcall f, t;
          237         uchar *buf;
          238         char *usage;
          239         u32int msize;
          240 
          241         usage = "usage: 9p T-message ...";
          242 
          243         ARGBEGIN{
          244         default:
          245                 return cliError(usage);
          246         }ARGEND
          247         if(argc < 1)
          248                 return cliError(usage);
          249 
          250         for(i = 0; i < nelem(cmd9pTmsg); i++){
          251                 if(strcmp(cmd9pTmsg[i].name, argv[0]) == 0)
          252                         break;
          253         }
          254         if(i == nelem(cmd9pTmsg))
          255                 return cliError(usage);
          256         argc--;
          257         argv++;
          258         if(cmd9pTmsg[i].argc && argc != cmd9pTmsg[i].argc){
          259                 werrstr("usage: %s %s",
          260                         cmd9pTmsg[i].name, cmd9pTmsg[i].usage);
          261                 return 0;
          262         }
          263 
          264         memset(&t, 0, sizeof(t));
          265         t.type = cmd9pTmsg[i].type;
          266         if(t.type == Tversion)
          267                 t.tag = NOTAG;
          268         else
          269                 t.tag = ++cbox.tag;
          270         msize = cbox.con->msize;
          271         if(!cmd9pTmsg[i].f(&t, argc, argv))
          272                 return 0;
          273         buf = vtmalloc(msize);
          274         n = convS2M(&t, buf, msize);
          275         if(n <= BIT16SZ){
          276                 werrstr("%s: convS2M error", cmd9pTmsg[i].name);
          277                 vtfree(buf);
          278                 return 0;
          279         }
          280         if(write(cbox.confd[0], buf, n) != n){
          281                 werrstr("%s: write error: %r", cmd9pTmsg[i].name);
          282                 vtfree(buf);
          283                 return 0;
          284         }
          285         consPrint("\t-> %F\n", &t);
          286 
          287         if((n = read9pmsg(cbox.confd[0], buf, msize)) <= 0){
          288                 werrstr("%s: read error: %r", cmd9pTmsg[i].name);
          289                 vtfree(buf);
          290                 return 0;
          291         }
          292         if(convM2S(buf, n, &f) == 0){
          293                 werrstr("%s: convM2S error", cmd9pTmsg[i].name);
          294                 vtfree(buf);
          295                 return 0;
          296         }
          297         consPrint("\t<- %F\n", &f);
          298 
          299         vtfree(buf);
          300         return 1;
          301 }
          302 
          303 static int
          304 cmdDot(int argc, char* argv[])
          305 {
          306         long l;
          307         Dir *dir;
          308         int fd, r;
          309         vlong length;
          310         char *f, *p, *s, *usage;
          311 
          312         usage = "usage: . file";
          313 
          314         ARGBEGIN{
          315         default:
          316                 return cliError(usage);
          317         }ARGEND
          318         if(argc != 1)
          319                 return cliError(usage);
          320 
          321         if((dir = dirstat(argv[0])) == nil)
          322                 return cliError(". dirstat %s: %r", argv[0]);
          323         length = dir->length;
          324         free(dir);
          325 
          326         r = 1;
          327         if(length != 0){
          328                 /*
          329                  * Read the whole file in.
          330                  */
          331                 if((fd = open(argv[0], OREAD)) < 0)
          332                         return cliError(". open %s: %r", argv[0]);
          333                 f = vtmalloc(dir->length+1);
          334                 if((l = read(fd, f, length)) < 0){
          335                         vtfree(f);
          336                         close(fd);
          337                         return cliError(". read %s: %r", argv[0]);
          338                 }
          339                 close(fd);
          340                 f[l] = '\0';
          341 
          342                 /*
          343                  * Call cliExec() for each line.
          344                  */
          345                 for(p = s = f; *p != '\0'; p++){
          346                         if(*p == '\n'){
          347                                 *p = '\0';
          348                                 if(cliExec(s) == 0){
          349                                         r = 0;
          350                                         consPrint("%s: %r\n", s);
          351                                 }
          352                                 s = p+1;
          353                         }
          354                 }
          355                 vtfree(f);
          356         }
          357 
          358         if(r == 0)
          359                 werrstr("errors in . %#q", argv[0]);
          360         return r;
          361 }
          362 
          363 static int
          364 cmdDflag(int argc, char* argv[])
          365 {
          366         char *usage;
          367 
          368         usage = "usage: dflag";
          369 
          370         ARGBEGIN{
          371         default:
          372                 return cliError(usage);
          373         }ARGEND
          374         if(argc)
          375                 return cliError(usage);
          376 
          377         Dflag ^= 1;
          378         consPrint("dflag %d\n", Dflag);
          379 
          380         return 1;
          381 }
          382 
          383 static int
          384 cmdEcho(int argc, char* argv[])
          385 {
          386         char *usage;
          387         int i, nflag;
          388 
          389         nflag = 0;
          390         usage = "usage: echo [-n] ...";
          391 
          392         ARGBEGIN{
          393         default:
          394                 return cliError(usage);
          395         case 'n':
          396                 nflag = 1;
          397                 break;
          398         }ARGEND
          399 
          400         for(i = 0; i < argc; i++){
          401                 if(i != 0)
          402                         consPrint(" %s", argv[i]);
          403                 else
          404                         consPrint(argv[i]);
          405         }
          406         if(!nflag)
          407                 consPrint("\n");
          408 
          409         return 1;
          410 }
          411 
          412 static int
          413 cmdBind(int argc, char* argv[])
          414 {
          415         ulong flag = 0;
          416         char *usage;
          417 
          418         usage = "usage: bind [-b|-a|-c|-bc|-ac] new old";
          419 
          420         ARGBEGIN{
          421         case 'a':
          422                 flag |= MAFTER;
          423                 break;
          424         case 'b':
          425                 flag |= MBEFORE;
          426                 break;
          427         case 'c':
          428                 flag |= MCREATE;
          429                 break;
          430         default:
          431                 return cliError(usage);
          432         }ARGEND
          433 
          434         if(argc != 2 || (flag&MAFTER)&&(flag&MBEFORE))
          435                 return cliError(usage);
          436 
          437 #ifndef PLAN9PORT
          438         if(bind(argv[0], argv[1], flag) < 0){
          439                 /* try to give a less confusing error than the default */
          440                 if(access(argv[0], 0) < 0)
          441                         return cliError("bind: %s: %r", argv[0]);
          442                 else if(access(argv[1], 0) < 0)
          443                         return cliError("bind: %s: %r", argv[1]);
          444                 else
          445                         return cliError("bind %s %s: %r", argv[0], argv[1]);
          446         }
          447 #endif
          448         return 1;
          449 }
          450 
          451 int
          452 cmdInit(void)
          453 {
          454         cbox.confd[0] = cbox.confd[1] = -1;
          455 
          456         cliAddCmd(".", cmdDot);
          457         cliAddCmd("9p", cmd9p);
          458         cliAddCmd("dflag", cmdDflag);
          459         cliAddCmd("echo", cmdEcho);
          460         cliAddCmd("bind", cmdBind);
          461 
          462         if(pipe(cbox.confd) < 0)
          463                 return 0;
          464         if((cbox.con = conAlloc(cbox.confd[1], "console", 0)) == nil){
          465                 close(cbox.confd[0]);
          466                 close(cbox.confd[1]);
          467                 cbox.confd[0] = cbox.confd[1] = -1;
          468                 return 0;
          469 
          470         }
          471         cbox.con->isconsole = 1;
          472 
          473         return 1;
          474 }