Blob


1 #include <u.h>
2 #include <libc.h>
3 #include "plumb.h"
5 static char attrbuf[4096];
7 char *home;
9 int
10 plumbopen(char *name, int omode)
11 {
12 #if 0
13 int fd, f;
14 char *s;
15 #endif
16 char buf[256];
18 if(name[0] == '/')
19 return open(name, omode);
20 if(home == nil){
21 home = getenv("HOME");
22 if(home == nil)
23 return -1;
24 }
25 snprint(buf, sizeof buf, "%s/mnt/plumb", home);
26 #if 0
27 fd = open(buf, omode);
28 if(fd >= 0)
29 return fd;
30 snprint(buf, sizeof buf, "/mnt/term/mnt/plumb/%s", name);
31 fd = open(buf, omode);
32 if(fd >= 0)
33 return fd;
34 /* try mounting service */
35 s = getenv("plumbsrv");
36 if(s == nil)
37 return -1;
38 snprint(buf, sizeof buf, "/mnt/plumb/%s", name);
39 #endif
40 return open(buf, omode);
41 }
43 static int
44 Strlen(char *s)
45 {
46 if(s == nil)
47 return 0;
48 return strlen(s);
49 }
51 static char*
52 Strcpy(char *s, char *t)
53 {
54 if(t == nil)
55 return s;
56 return strcpy(s, t) + strlen(t);
57 }
59 /* quote attribute value, if necessary */
60 static char*
61 quote(char *s)
62 {
63 char *t;
64 int c;
66 if(s == nil){
67 attrbuf[0] = '\0';
68 return attrbuf;
69 }
70 if(strpbrk(s, " '=\t") == nil)
71 return s;
72 t = attrbuf;
73 *t++ = '\'';
74 while(t < attrbuf+sizeof attrbuf-2){
75 c = *s++;
76 if(c == '\0')
77 break;
78 *t++ = c;
79 if(c == '\'')
80 *t++ = c;
81 }
82 *t++ = '\'';
83 *t = '\0';
84 return attrbuf;
85 }
87 char*
88 plumbpackattr(Plumbattr *attr)
89 {
90 int n;
91 Plumbattr *a;
92 char *s, *t;
94 if(attr == nil)
95 return nil;
96 n = 0;
97 for(a=attr; a!=nil; a=a->next)
98 n += Strlen(a->name) + 1 + Strlen(quote(a->value)) + 1;
99 s = malloc(n);
100 if(s == nil)
101 return nil;
102 t = s;
103 *t = '\0';
104 for(a=attr; a!=nil; a=a->next){
105 if(t != s)
106 *t++ = ' ';
107 strcpy(t, a->name);
108 strcat(t, "=");
109 strcat(t, quote(a->value));
110 t += strlen(t);
112 if(t > s+n)
113 abort();
114 return s;
117 char*
118 plumblookup(Plumbattr *attr, char *name)
120 while(attr){
121 if(strcmp(attr->name, name) == 0)
122 return attr->value;
123 attr = attr->next;
125 return nil;
128 char*
129 plumbpack(Plumbmsg *m, int *np)
131 int n, ndata;
132 char *buf, *p, *attr;
134 ndata = m->ndata;
135 if(ndata < 0)
136 ndata = Strlen(m->data);
137 attr = plumbpackattr(m->attr);
138 n = Strlen(m->src)+1 + Strlen(m->dst)+1 + Strlen(m->wdir)+1 +
139 Strlen(m->type)+1 + Strlen(attr)+1 + 16 + ndata;
140 buf = malloc(n+1); /* +1 for '\0' */
141 if(buf == nil){
142 free(attr);
143 return nil;
145 p = Strcpy(buf, m->src);
146 *p++ = '\n';
147 p = Strcpy(p, m->dst);
148 *p++ = '\n';
149 p = Strcpy(p, m->wdir);
150 *p++ = '\n';
151 p = Strcpy(p, m->type);
152 *p++ = '\n';
153 p = Strcpy(p, attr);
154 *p++ = '\n';
155 p += sprint(p, "%d\n", ndata);
156 memmove(p, m->data, ndata);
157 *np = (p-buf)+ndata;
158 buf[*np] = '\0'; /* null terminate just in case */
159 if(*np >= n+1)
160 abort();
161 free(attr);
162 return buf;
165 int
166 plumbsend(int fd, Plumbmsg *m)
168 char *buf;
169 int n;
171 buf = plumbpack(m, &n);
172 if(buf == nil)
173 return -1;
174 n = write(fd, buf, n);
175 free(buf);
176 return n;
179 static int
180 plumbline(char **linep, char *buf, int i, int n, int *bad)
182 int starti;
183 char *p;
185 if(*bad)
186 return i;
187 starti = i;
188 while(i<n && buf[i]!='\n')
189 i++;
190 if(i == n)
191 *bad = 1;
192 else{
193 p = malloc((i-starti) + 1);
194 if(p == nil)
195 *bad = 1;
196 else{
197 memmove(p, buf+starti, i-starti);
198 p[i-starti] = '\0';
200 *linep = p;
201 i++;
203 return i;
206 void
207 plumbfree(Plumbmsg *m)
209 Plumbattr *a, *next;
211 free(m->src);
212 free(m->dst);
213 free(m->wdir);
214 free(m->type);
215 for(a=m->attr; a!=nil; a=next){
216 next = a->next;
217 free(a->name);
218 free(a->value);
219 free(a);
221 free(m->data);
222 free(m);
225 Plumbattr*
226 plumbunpackattr(char *p)
228 Plumbattr *attr, *prev, *a;
229 char *q, *v;
230 int c, quoting;
232 attr = prev = nil;
233 while(*p!='\0' && *p!='\n'){
234 while(*p==' ' || *p=='\t')
235 p++;
236 if(*p == '\0')
237 break;
238 for(q=p; *q!='\0' && *q!='\n' && *q!=' ' && *q!='\t'; q++)
239 if(*q == '=')
240 break;
241 if(*q != '=')
242 break; /* malformed attribute */
243 a = malloc(sizeof(Plumbattr));
244 if(a == nil)
245 break;
246 a->name = malloc(q-p+1);
247 if(a->name == nil){
248 free(a);
249 break;
251 memmove(a->name, p, q-p);
252 a->name[q-p] = '\0';
253 /* process quotes in value */
254 q++; /* skip '=' */
255 v = attrbuf;
256 quoting = 0;
257 while(*q!='\0' && *q!='\n'){
258 if(v >= attrbuf+sizeof attrbuf)
259 break;
260 c = *q++;
261 if(quoting){
262 if(c == '\''){
263 if(*q == '\'')
264 q++;
265 else{
266 quoting = 0;
267 continue;
270 }else{
271 if(c==' ' || c=='\t')
272 break;
273 if(c == '\''){
274 quoting = 1;
275 continue;
278 *v++ = c;
280 a->value = malloc(v-attrbuf+1);
281 if(a->value == nil){
282 free(a->name);
283 free(a);
284 break;
286 memmove(a->value, attrbuf, v-attrbuf);
287 a->value[v-attrbuf] = '\0';
288 a->next = nil;
289 if(prev == nil)
290 attr = a;
291 else
292 prev->next = a;
293 prev = a;
294 p = q;
296 return attr;
299 Plumbattr*
300 plumbaddattr(Plumbattr *attr, Plumbattr *new)
302 Plumbattr *l;
304 l = attr;
305 if(l == nil)
306 return new;
307 while(l->next != nil)
308 l = l->next;
309 l->next = new;
310 return attr;
313 Plumbattr*
314 plumbdelattr(Plumbattr *attr, char *name)
316 Plumbattr *l, *prev;
318 prev = nil;
319 for(l=attr; l!=nil; l=l->next){
320 if(strcmp(name, l->name) == 0)
321 break;
322 prev = l;
324 if(l == nil)
325 return nil;
326 if(prev)
327 prev->next = l->next;
328 else
329 attr = l->next;
330 free(l->name);
331 free(l->value);
332 free(l);
333 return attr;
336 Plumbmsg*
337 plumbunpackpartial(char *buf, int n, int *morep)
339 Plumbmsg *m;
340 int i, bad;
341 char *ntext, *attr;
343 m = malloc(sizeof(Plumbmsg));
344 if(m == nil)
345 return nil;
346 memset(m, 0, sizeof(Plumbmsg));
347 if(morep != nil)
348 *morep = 0;
349 bad = 0;
350 i = plumbline(&m->src, buf, 0, n, &bad);
351 i = plumbline(&m->dst, buf, i, n, &bad);
352 i = plumbline(&m->wdir, buf, i, n, &bad);
353 i = plumbline(&m->type, buf, i, n, &bad);
354 i = plumbline(&attr, buf, i, n, &bad);
355 m->attr = plumbunpackattr(attr);
356 free(attr);
357 i = plumbline(&ntext, buf, i, n, &bad);
358 m->ndata = atoi(ntext);
359 if(m->ndata != n-i){
360 bad = 1;
361 if(morep!=nil && m->ndata>n-i)
362 *morep = m->ndata - (n-i);
364 free(ntext);
365 if(!bad){
366 m->data = malloc(n-i+1); /* +1 for '\0' */
367 if(m->data == nil)
368 bad = 1;
369 else{
370 memmove(m->data, buf+i, m->ndata);
371 m->ndata = n-i;
372 /* null-terminate in case it's text */
373 m->data[m->ndata] = '\0';
376 if(bad){
377 plumbfree(m);
378 m = nil;
380 return m;
383 Plumbmsg*
384 plumbunpack(char *buf, int n)
386 return plumbunpackpartial(buf, n, nil);
389 Plumbmsg*
390 plumbrecv(int fd)
392 char *buf;
393 Plumbmsg *m;
394 int n, more;
396 buf = malloc(8192);
397 if(buf == nil)
398 return nil;
399 n = read(fd, buf, 8192);
400 m = nil;
401 if(n > 0){
402 m = plumbunpackpartial(buf, n, &more);
403 if(m==nil && more>0){
404 /* we now know how many more bytes to read for complete message */
405 buf = realloc(buf, n+more);
406 if(buf == nil)
407 return nil;
408 if(readn(fd, buf+n, more) == more)
409 m = plumbunpackpartial(buf, n+more, nil);
412 free(buf);
413 return m;