URI: 
       tmesg.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tmesg.c (5481B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <fcall.h>
            4 #include "plumb.h"
            5 
            6 static char attrbuf[4096];
            7 
            8 char *home;
            9 
           10 static int
           11 Strlen(char *s)
           12 {
           13         if(s == nil)
           14                 return 0;
           15         return strlen(s);
           16 }
           17 
           18 static char*
           19 Strcpy(char *s, char *t)
           20 {
           21         if(t == nil)
           22                 return s;
           23         return strcpy(s, t) + strlen(t);
           24 }
           25 
           26 /* quote attribute value, if necessary */
           27 static char*
           28 quote(char *s)
           29 {
           30         char *t;
           31         int c;
           32 
           33         if(s == nil){
           34                 attrbuf[0] = '\0';
           35                 return attrbuf;
           36         }
           37         if(strpbrk(s, " '=\t") == nil)
           38                 return s;
           39         t = attrbuf;
           40         *t++ = '\'';
           41         while(t < attrbuf+sizeof attrbuf-2){
           42                 c = *s++;
           43                 if(c == '\0')
           44                         break;
           45                 *t++ = c;
           46                 if(c == '\'')
           47                         *t++ = c;
           48         }
           49         *t++ = '\'';
           50         *t = '\0';
           51         return attrbuf;
           52 }
           53 
           54 char*
           55 plumbpackattr(Plumbattr *attr)
           56 {
           57         int n;
           58         Plumbattr *a;
           59         char *s, *t;
           60 
           61         if(attr == nil)
           62                 return nil;
           63         n = 0;
           64         for(a=attr; a!=nil; a=a->next)
           65                 n += Strlen(a->name) + 1 + Strlen(quote(a->value)) + 1;
           66         s = malloc(n);
           67         if(s == nil)
           68                 return nil;
           69         t = s;
           70         *t = '\0';
           71         for(a=attr; a!=nil; a=a->next){
           72                 if(t != s)
           73                         *t++ = ' ';
           74                 strcpy(t, a->name);
           75                 strcat(t, "=");
           76                 strcat(t, quote(a->value));
           77                 t += strlen(t);
           78         }
           79         if(t > s+n)
           80                 abort();
           81         return s;
           82 }
           83 
           84 char*
           85 plumblookup(Plumbattr *attr, char *name)
           86 {
           87         while(attr){
           88                 if(strcmp(attr->name, name) == 0)
           89                         return attr->value;
           90                 attr = attr->next;
           91         }
           92         return nil;
           93 }
           94 
           95 char*
           96 plumbpack(Plumbmsg *m, int *np)
           97 {
           98         int n, ndata;
           99         char *buf, *p, *attr;
          100 
          101         ndata = m->ndata;
          102         if(ndata < 0)
          103                 ndata = Strlen(m->data);
          104         attr = plumbpackattr(m->attr);
          105         n = Strlen(m->src)+1 + Strlen(m->dst)+1 + Strlen(m->wdir)+1 +
          106                 Strlen(m->type)+1 + Strlen(attr)+1 + 16 + ndata;
          107         buf = malloc(n+1);        /* +1 for '\0' */
          108         if(buf == nil){
          109                 free(attr);
          110                 return nil;
          111         }
          112         p = Strcpy(buf, m->src);
          113         *p++ = '\n';
          114         p = Strcpy(p, m->dst);
          115         *p++ = '\n';
          116         p = Strcpy(p, m->wdir);
          117         *p++ = '\n';
          118         p = Strcpy(p, m->type);
          119         *p++ = '\n';
          120         p = Strcpy(p, attr);
          121         *p++ = '\n';
          122         p += sprint(p, "%d\n", ndata);
          123         memmove(p, m->data, ndata);
          124         *np = (p-buf)+ndata;
          125         buf[*np] = '\0';        /* null terminate just in case */
          126         if(*np >= n+1)
          127                 abort();
          128         free(attr);
          129         return buf;
          130 }
          131 
          132 static int
          133 plumbline(char **linep, char *buf, int i, int n, int *bad)
          134 {
          135         int starti;
          136         char *p;
          137 
          138         if(*bad)
          139                 return i;
          140         starti = i;
          141         while(i<n && buf[i]!='\n')
          142                 i++;
          143         if(i == n)
          144                 *bad = 1;
          145         else{
          146                 p = malloc((i-starti) + 1);
          147                 if(p == nil)
          148                         *bad = 1;
          149                 else{
          150                         memmove(p, buf+starti, i-starti);
          151                         p[i-starti] = '\0';
          152                 }
          153                 *linep = p;
          154                 i++;
          155         }
          156         return i;
          157 }
          158 
          159 void
          160 plumbfree(Plumbmsg *m)
          161 {
          162         Plumbattr *a, *next;
          163 
          164         free(m->src);
          165         free(m->dst);
          166         free(m->wdir);
          167         free(m->type);
          168         for(a=m->attr; a!=nil; a=next){
          169                 next = a->next;
          170                 free(a->name);
          171                 free(a->value);
          172                 free(a);
          173         }
          174         free(m->data);
          175         free(m);
          176 }
          177 
          178 Plumbattr*
          179 plumbunpackattr(char *p)
          180 {
          181         Plumbattr *attr, *prev, *a;
          182         char *q, *v;
          183         int c, quoting;
          184 
          185         attr = prev = nil;
          186         while(*p!='\0' && *p!='\n'){
          187                 while(*p==' ' || *p=='\t')
          188                         p++;
          189                 if(*p == '\0')
          190                         break;
          191                 for(q=p; *q!='\0' && *q!='\n' && *q!=' ' && *q!='\t'; q++)
          192                         if(*q == '=')
          193                                 break;
          194                 if(*q != '=')
          195                         break;        /* malformed attribute */
          196                 a = malloc(sizeof(Plumbattr));
          197                 if(a == nil)
          198                         break;
          199                 a->name = malloc(q-p+1);
          200                 if(a->name == nil){
          201                         free(a);
          202                         break;
          203                 }
          204                 memmove(a->name, p, q-p);
          205                 a->name[q-p] = '\0';
          206                 /* process quotes in value */
          207                 q++;        /* skip '=' */
          208                 v = attrbuf;
          209                 quoting = 0;
          210                 while(*q!='\0' && *q!='\n'){
          211                         if(v >= attrbuf+sizeof attrbuf)
          212                                 break;
          213                         c = *q++;
          214                         if(quoting){
          215                                 if(c == '\''){
          216                                         if(*q == '\'')
          217                                                 q++;
          218                                         else{
          219                                                 quoting = 0;
          220                                                 continue;
          221                                         }
          222                                 }
          223                         }else{
          224                                 if(c==' ' || c=='\t')
          225                                         break;
          226                                 if(c == '\''){
          227                                         quoting = 1;
          228                                         continue;
          229                                 }
          230                         }
          231                         *v++ = c;
          232                 }
          233                 a->value = malloc(v-attrbuf+1);
          234                 if(a->value == nil){
          235                         free(a->name);
          236                         free(a);
          237                         break;
          238                 }
          239                 memmove(a->value, attrbuf, v-attrbuf);
          240                 a->value[v-attrbuf] = '\0';
          241                 a->next = nil;
          242                 if(prev == nil)
          243                         attr = a;
          244                 else
          245                         prev->next = a;
          246                 prev = a;
          247                 p = q;
          248         }
          249         return attr;
          250 }
          251 
          252 Plumbattr*
          253 plumbaddattr(Plumbattr *attr, Plumbattr *new)
          254 {
          255         Plumbattr *l;
          256 
          257         l = attr;
          258         if(l == nil)
          259                 return new;
          260         while(l->next != nil)
          261                 l = l->next;
          262         l->next = new;
          263         return attr;
          264 }
          265 
          266 Plumbattr*
          267 plumbdelattr(Plumbattr *attr, char *name)
          268 {
          269         Plumbattr *l, *prev;
          270 
          271         prev = nil;
          272         for(l=attr; l!=nil; l=l->next){
          273                 if(strcmp(name, l->name) == 0)
          274                         break;
          275                 prev = l;
          276         }
          277         if(l == nil)
          278                 return nil;
          279         if(prev)
          280                 prev->next = l->next;
          281         else
          282                 attr = l->next;
          283         free(l->name);
          284         free(l->value);
          285         free(l);
          286         return attr;
          287 }
          288 
          289 Plumbmsg*
          290 plumbunpackpartial(char *buf, int n, int *morep)
          291 {
          292         Plumbmsg *m;
          293         int i, bad;
          294         char *ntext, *attr;
          295 
          296         m = malloc(sizeof(Plumbmsg));
          297         if(m == nil)
          298                 return nil;
          299         memset(m, 0, sizeof(Plumbmsg));
          300         if(morep != nil)
          301                 *morep = 0;
          302         bad = 0;
          303         i = plumbline(&m->src, buf, 0, n, &bad);
          304         i = plumbline(&m->dst, buf, i, n, &bad);
          305         i = plumbline(&m->wdir, buf, i, n, &bad);
          306         i = plumbline(&m->type, buf, i, n, &bad);
          307         i = plumbline(&attr, buf, i, n, &bad);
          308         m->attr = plumbunpackattr(attr);
          309         free(attr);
          310         i = plumbline(&ntext, buf, i, n, &bad);
          311         m->ndata = atoi(ntext);
          312         if(m->ndata != n-i){
          313                 bad = 1;
          314                 if(morep!=nil && m->ndata>n-i)
          315                         *morep = m->ndata - (n-i);
          316         }
          317         free(ntext);
          318         if(!bad){
          319                 m->data = malloc(n-i+1);        /* +1 for '\0' */
          320                 if(m->data == nil)
          321                         bad = 1;
          322                 else{
          323                         memmove(m->data, buf+i, m->ndata);
          324                         m->ndata = n-i;
          325                         /* null-terminate in case it's text */
          326                         m->data[m->ndata] = '\0';
          327                 }
          328         }
          329         if(bad){
          330                 plumbfree(m);
          331                 m = nil;
          332         }
          333         return m;
          334 }
          335 
          336 Plumbmsg*
          337 plumbunpack(char *buf, int n)
          338 {
          339         return plumbunpackpartial(buf, n, nil);
          340 }