6 plumbopen(char *name, int omode)
9 char buf[128], err[ERRMAX];
12 return open(name, omode);
14 if(access("/mnt/plumb/send", AWRITE) < 0)
17 snprint(buf, sizeof buf, "/mnt/plumb/%s", name);
18 fd = open(buf, omode);
22 /* try creating port; used by non-standard plumb implementations */
23 rerrstr(err, sizeof err);
24 fd = create(buf, omode, 0600);
27 errstr(err, sizeof err);
41 Strcpy(char *s, char *t)
45 return strcpy(s, t) + strlen(t);
48 /* quote attribute value, if necessary */
50 quote(char *s, char *buf, char *bufe)
59 if(strpbrk(s, " '=\t") == nil)
77 plumbpackattr(Plumbattr *attr)
81 char *s, *t, *buf, *bufe;
85 if((buf = malloc(4096)) == nil)
89 for(a=attr; a!=nil; a=a->next)
90 n += Strlen(a->name) + 1 + Strlen(quote(a->value, buf, bufe)) + 1;
96 for(a=attr; a!=nil; a=a->next){
101 strcat(t, quote(a->value, buf, bufe));
112 plumblookup(Plumbattr *attr, char *name)
115 if(strcmp(attr->name, name) == 0)
123 plumbpack(Plumbmsg *m, int *np)
126 char *buf, *p, *attr;
130 ndata = Strlen(m->data);
131 attr = plumbpackattr(m->attr);
132 n = Strlen(m->src)+1 + Strlen(m->dst)+1 + Strlen(m->wdir)+1 +
133 Strlen(m->type)+1 + Strlen(attr)+1 + 16 + ndata;
134 buf = malloc(n+1); /* +1 for '\0' */
139 p = Strcpy(buf, m->src);
141 p = Strcpy(p, m->dst);
143 p = Strcpy(p, m->wdir);
145 p = Strcpy(p, m->type);
149 p += sprint(p, "%d\n", ndata);
150 memmove(p, m->data, ndata);
152 buf[*np] = '\0'; /* null terminate just in case */
160 plumbsend(int fd, Plumbmsg *m)
165 buf = plumbpack(m, &n);
168 n = write(fd, buf, n);
174 plumbline(char **linep, char *buf, int i, int n, int *bad)
180 while(i<n && buf[i]!='\n')
185 p = malloc((i-starti) + 1);
189 memmove(p, buf+starti, i-starti);
199 plumbfree(Plumbmsg *m)
207 for(a=m->attr; a!=nil; a=next){
218 plumbunpackattr(char *p)
220 Plumbattr *attr, *prev, *a;
221 char *q, *v, *buf, *bufe;
224 if((buf = malloc(4096)) == nil)
228 while(*p!='\0' && *p!='\n'){
229 while(*p==' ' || *p=='\t')
233 for(q=p; *q!='\0' && *q!='\n' && *q!=' ' && *q!='\t'; q++)
237 break; /* malformed attribute */
238 a = malloc(sizeof(Plumbattr));
241 a->name = malloc(q-p+1);
246 memmove(a->name, p, q-p);
248 /* process quotes in value */
252 while(*q!='\0' && *q!='\n'){
266 if(c==' ' || c=='\t')
275 a->value = malloc(v-buf+1);
281 memmove(a->value, buf, v-buf);
282 a->value[v-buf] = '\0';
297 plumbaddattr(Plumbattr *attr, Plumbattr *new)
304 while(l->next != nil)
311 plumbdelattr(Plumbattr *attr, char *name)
316 for(l=attr; l!=nil; l=l->next){
317 if(strcmp(name, l->name) == 0)
324 prev->next = l->next;
334 plumbunpackpartial(char *buf, int n, int *morep)
340 m = malloc(sizeof(Plumbmsg));
343 memset(m, 0, sizeof(Plumbmsg));
347 i = plumbline(&m->src, buf, 0, n, &bad);
348 i = plumbline(&m->dst, buf, i, n, &bad);
349 i = plumbline(&m->wdir, buf, i, n, &bad);
350 i = plumbline(&m->type, buf, i, n, &bad);
351 i = plumbline(&attr, buf, i, n, &bad);
352 i = plumbline(&ntext, buf, i, n, &bad);
357 m->attr = plumbunpackattr(attr);
359 m->ndata = atoi(ntext);
362 if(morep!=nil && m->ndata>n-i)
363 *morep = m->ndata - (n-i);
367 m->data = malloc(n-i+1); /* +1 for '\0' */
371 memmove(m->data, buf+i, m->ndata);
373 /* null-terminate in case it's text */
374 m->data[m->ndata] = '\0';
385 plumbunpack(char *buf, int n)
387 return plumbunpackpartial(buf, n, nil);
400 n = read(fd, buf, 8192);
403 m = plumbunpackpartial(buf, n, &more);
404 if(m==nil && more>0){
405 /* we now know how many more bytes to read for complete message */
406 buf = realloc(old = buf, n+more);
411 if(readn(fd, buf+n, more) == more)
412 m = plumbunpackpartial(buf, n+more, nil);