Blob
1 #include <u.h>2 #include <libc.h>3 #include <fcall.h>4 #include "plumb.h"6 static char attrbuf[4096];8 char *home;10 static int11 Strlen(char *s)12 {13 if(s == nil)14 return 0;15 return strlen(s);16 }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 }26 /* quote attribute value, if necessary */27 static char*28 quote(char *s)29 {30 char *t;31 int c;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 }54 char*55 plumbpackattr(Plumbattr *attr)56 {57 int n;58 Plumbattr *a;59 char *s, *t;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 }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 }95 char*96 plumbpack(Plumbmsg *m, int *np)97 {98 int n, ndata;99 char *buf, *p, *attr;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 }132 static int133 plumbline(char **linep, char *buf, int i, int n, int *bad)134 {135 int starti;136 char *p;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 }159 void160 plumbfree(Plumbmsg *m)161 {162 Plumbattr *a, *next;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 }178 Plumbattr*179 plumbunpackattr(char *p)180 {181 Plumbattr *attr, *prev, *a;182 char *q, *v;183 int c, quoting;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 else245 prev->next = a;246 prev = a;247 p = q;248 }249 return attr;250 }252 Plumbattr*253 plumbaddattr(Plumbattr *attr, Plumbattr *new)254 {255 Plumbattr *l;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 }266 Plumbattr*267 plumbdelattr(Plumbattr *attr, char *name)268 {269 Plumbattr *l, *prev;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 else282 attr = l->next;283 free(l->name);284 free(l->value);285 free(l);286 return attr;287 }289 Plumbmsg*290 plumbunpackpartial(char *buf, int n, int *morep)291 {292 Plumbmsg *m;293 int i, bad;294 char *ntext, *attr;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 }336 Plumbmsg*337 plumbunpack(char *buf, int n)338 {339 return plumbunpackpartial(buf, n, nil);340 }