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 int
12 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;
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;
133 static int
134 plumbline(char **linep, char *buf, int i, int n, int *bad)
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';
154 *linep = p;
155 i++;
157 return i;
160 void
161 plumbfree(Plumbmsg *m)
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);
175 free(m->data);
176 free(m);
179 Plumbattr*
180 plumbunpackattr(char *p)
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;
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;
224 }else{
225 if(c==' ' || c=='\t')
226 break;
227 if(c == '\''){
228 quoting = 1;
229 continue;
232 *v++ = c;
234 a->value = malloc(v-attrbuf+1);
235 if(a->value == nil){
236 free(a->name);
237 free(a);
238 break;
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 else
246 prev->next = a;
247 prev = a;
248 p = q;
250 return attr;
253 Plumbattr*
254 plumbaddattr(Plumbattr *attr, Plumbattr *new)
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;
267 Plumbattr*
268 plumbdelattr(Plumbattr *attr, char *name)
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;
278 if(l == nil)
279 return nil;
280 if(prev)
281 prev->next = l->next;
282 else
283 attr = l->next;
284 free(l->name);
285 free(l->value);
286 free(l);
287 return attr;
290 Plumbmsg*
291 plumbunpackpartial(char *buf, int n, int *morep)
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);
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';
330 if(bad){
331 plumbfree(m);
332 m = nil;
334 return m;
337 Plumbmsg*
338 plumbunpack(char *buf, int n)
340 return plumbunpackpartial(buf, n, nil);