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