blob: c9379307c7d79b807ec2985b9d3966968729492b [file] [log] [blame]
rsc3d7e9092003-10-14 02:35:00 +00001#include <u.h>
2#include <libc.h>
rsc32f69c32003-12-11 17:48:38 +00003#include <fcall.h>
rsc3d7e9092003-10-14 02:35:00 +00004#include "plumb.h"
5
6static char attrbuf[4096];
7
rscb7e6f412003-11-23 18:16:51 +00008char *home;
rsc49588d52003-12-17 04:34:52 +00009
rsc3d7e9092003-10-14 02:35:00 +000010static int
11Strlen(char *s)
12{
13 if(s == nil)
14 return 0;
15 return strlen(s);
16}
17
18static char*
19Strcpy(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 */
27static char*
28quote(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
54char*
55plumbpackattr(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
84char*
85plumblookup(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
95char*
96plumbpack(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
rsc3d7e9092003-10-14 02:35:00 +0000132static int
133plumbline(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
159void
160plumbfree(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
178Plumbattr*
179plumbunpackattr(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
252Plumbattr*
253plumbaddattr(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
266Plumbattr*
267plumbdelattr(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
289Plumbmsg*
290plumbunpackpartial(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
336Plumbmsg*
337plumbunpack(char *buf, int n)
338{
339 return plumbunpackpartial(buf, n, nil);
340}
341