1*3ff48bf5SDavid du Colombier #include <u.h> 2*3ff48bf5SDavid du Colombier #include <libc.h> 3*3ff48bf5SDavid du Colombier #include <fcall.h> 4*3ff48bf5SDavid du Colombier #include <thread.h> 5*3ff48bf5SDavid du Colombier #include <9p.h> 6*3ff48bf5SDavid du Colombier 7*3ff48bf5SDavid du Colombier /* 8*3ff48bf5SDavid du Colombier * Generous estimate of number of fields, including terminal nil pointer 9*3ff48bf5SDavid du Colombier */ 10*3ff48bf5SDavid du Colombier static int 11*3ff48bf5SDavid du Colombier ncmdfield(char *p, int n) 12*3ff48bf5SDavid du Colombier { 13*3ff48bf5SDavid du Colombier int white, nwhite; 14*3ff48bf5SDavid du Colombier char *ep; 15*3ff48bf5SDavid du Colombier int nf; 16*3ff48bf5SDavid du Colombier 17*3ff48bf5SDavid du Colombier if(p == nil) 18*3ff48bf5SDavid du Colombier return 1; 19*3ff48bf5SDavid du Colombier 20*3ff48bf5SDavid du Colombier nf = 0; 21*3ff48bf5SDavid du Colombier ep = p+n; 22*3ff48bf5SDavid du Colombier white = 1; /* first text will start field */ 23*3ff48bf5SDavid du Colombier while(p < ep){ 24*3ff48bf5SDavid du Colombier nwhite = (strchr(" \t\r\n", *p++ & 0xFF) != 0); /* UTF is irrelevant */ 25*3ff48bf5SDavid du Colombier if(white && !nwhite) /* beginning of field */ 26*3ff48bf5SDavid du Colombier nf++; 27*3ff48bf5SDavid du Colombier white = nwhite; 28*3ff48bf5SDavid du Colombier } 29*3ff48bf5SDavid du Colombier return nf+1; /* +1 for nil */ 30*3ff48bf5SDavid du Colombier } 31*3ff48bf5SDavid du Colombier 32*3ff48bf5SDavid du Colombier /* 33*3ff48bf5SDavid du Colombier * parse a command written to a device 34*3ff48bf5SDavid du Colombier */ 35*3ff48bf5SDavid du Colombier Cmdbuf* 36*3ff48bf5SDavid du Colombier parsecmd(char *p, int n) 37*3ff48bf5SDavid du Colombier { 38*3ff48bf5SDavid du Colombier Cmdbuf *cb; 39*3ff48bf5SDavid du Colombier int nf; 40*3ff48bf5SDavid du Colombier char *sp; 41*3ff48bf5SDavid du Colombier 42*3ff48bf5SDavid du Colombier nf = ncmdfield(p, n); 43*3ff48bf5SDavid du Colombier 44*3ff48bf5SDavid du Colombier /* allocate Cmdbuf plus string pointers plus copy of string including \0 */ 45*3ff48bf5SDavid du Colombier sp = emalloc9p(sizeof(*cb) + nf * sizeof(char*) + n + 1); 46*3ff48bf5SDavid du Colombier cb = (Cmdbuf*)sp; 47*3ff48bf5SDavid du Colombier cb->f = (char**)(&cb[1]); 48*3ff48bf5SDavid du Colombier cb->buf = (char*)(&cb->f[nf]); 49*3ff48bf5SDavid du Colombier 50*3ff48bf5SDavid du Colombier memmove(cb->buf, p, n); 51*3ff48bf5SDavid du Colombier 52*3ff48bf5SDavid du Colombier /* dump new line and null terminate */ 53*3ff48bf5SDavid du Colombier if(n > 0 && cb->buf[n-1] == '\n') 54*3ff48bf5SDavid du Colombier n--; 55*3ff48bf5SDavid du Colombier cb->buf[n] = '\0'; 56*3ff48bf5SDavid du Colombier 57*3ff48bf5SDavid du Colombier cb->nf = tokenize(cb->buf, cb->f, nf-1); 58*3ff48bf5SDavid du Colombier cb->f[cb->nf] = nil; 59*3ff48bf5SDavid du Colombier 60*3ff48bf5SDavid du Colombier return cb; 61*3ff48bf5SDavid du Colombier } 62*3ff48bf5SDavid du Colombier 63*3ff48bf5SDavid du Colombier /* 64*3ff48bf5SDavid du Colombier * Reconstruct original message, for error diagnostic 65*3ff48bf5SDavid du Colombier */ 66*3ff48bf5SDavid du Colombier void 67*3ff48bf5SDavid du Colombier respondcmderror(Req *r, Cmdbuf *cb, char *fmt, ...) 68*3ff48bf5SDavid du Colombier { 69*3ff48bf5SDavid du Colombier int i; 70*3ff48bf5SDavid du Colombier va_list arg; 71*3ff48bf5SDavid du Colombier char *p, *e; 72*3ff48bf5SDavid du Colombier char err[ERRMAX]; 73*3ff48bf5SDavid du Colombier 74*3ff48bf5SDavid du Colombier e = err+ERRMAX-10; 75*3ff48bf5SDavid du Colombier va_start(arg, fmt); 76*3ff48bf5SDavid du Colombier p = vseprint(err, e, fmt, arg); 77*3ff48bf5SDavid du Colombier va_end(arg); 78*3ff48bf5SDavid du Colombier p = seprint(p, e, ": \""); 79*3ff48bf5SDavid du Colombier for(i=0; i<cb->nf; i++){ 80*3ff48bf5SDavid du Colombier if(i > 0) 81*3ff48bf5SDavid du Colombier p = seprint(p, e, " "); 82*3ff48bf5SDavid du Colombier p = seprint(p, e, "%q", cb->f[i]); 83*3ff48bf5SDavid du Colombier } 84*3ff48bf5SDavid du Colombier strcpy(p, "\""); 85*3ff48bf5SDavid du Colombier respond(r, err); 86*3ff48bf5SDavid du Colombier } 87*3ff48bf5SDavid du Colombier 88*3ff48bf5SDavid du Colombier /* 89*3ff48bf5SDavid du Colombier * Look up entry in table 90*3ff48bf5SDavid du Colombier */ 91*3ff48bf5SDavid du Colombier Cmdtab* 92*3ff48bf5SDavid du Colombier lookupcmd(Cmdbuf *cb, Cmdtab *ctab, int nctab) 93*3ff48bf5SDavid du Colombier { 94*3ff48bf5SDavid du Colombier int i; 95*3ff48bf5SDavid du Colombier Cmdtab *ct; 96*3ff48bf5SDavid du Colombier 97*3ff48bf5SDavid du Colombier if(cb->nf == 0){ 98*3ff48bf5SDavid du Colombier werrstr("empty control message"); 99*3ff48bf5SDavid du Colombier return nil; 100*3ff48bf5SDavid du Colombier } 101*3ff48bf5SDavid du Colombier 102*3ff48bf5SDavid du Colombier for(ct = ctab, i=0; i<nctab; i++, ct++){ 103*3ff48bf5SDavid du Colombier if(strcmp(ct->cmd, "*") !=0) /* wildcard always matches */ 104*3ff48bf5SDavid du Colombier if(strcmp(ct->cmd, cb->f[0]) != 0) 105*3ff48bf5SDavid du Colombier continue; 106*3ff48bf5SDavid du Colombier if(ct->narg != 0 && ct->narg != cb->nf){ 107*3ff48bf5SDavid du Colombier werrstr("bad # args to command"); 108*3ff48bf5SDavid du Colombier return nil; 109*3ff48bf5SDavid du Colombier } 110*3ff48bf5SDavid du Colombier return ct; 111*3ff48bf5SDavid du Colombier } 112*3ff48bf5SDavid du Colombier 113*3ff48bf5SDavid du Colombier werrstr("unknown control message"); 114*3ff48bf5SDavid du Colombier return nil; 115*3ff48bf5SDavid du Colombier } 116