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 int
11 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;
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;
132 static int
133 plumbline(char **linep, char *buf, int i, int n, int *bad)
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';
153 *linep = p;
154 i++;
156 return i;
159 void
160 plumbfree(Plumbmsg *m)
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);
174 free(m->data);
175 free(m);
178 Plumbattr*
179 plumbunpackattr(char *p)
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;
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;
223 }else{
224 if(c==' ' || c=='\t')
225 break;
226 if(c == '\''){
227 quoting = 1;
228 continue;
231 *v++ = c;
233 a->value = malloc(v-attrbuf+1);
234 if(a->value == nil){
235 free(a->name);
236 free(a);
237 break;
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;
249 return attr;
252 Plumbattr*
253 plumbaddattr(Plumbattr *attr, Plumbattr *new)
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;
266 Plumbattr*
267 plumbdelattr(Plumbattr *attr, char *name)
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;
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;
289 Plumbmsg*
290 plumbunpackpartial(char *buf, int n, int *morep)
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);
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';
329 if(bad){
330 plumbfree(m);
331 m = nil;
333 return m;
336 Plumbmsg*
337 plumbunpack(char *buf, int n)
339 return plumbunpackpartial(buf, n, nil);