5 static char attrbuf[4096];
8 plumbopen(char *name, int omode)
12 char buf[128], err[ERRMAX];
15 return open(name, omode);
17 /* find elusive plumber */
18 if(access("/mnt/plumb/send", AWRITE) >= 0)
19 plumber = "/mnt/plumb";
20 else if(access("/mnt/term/mnt/plumb/send", AWRITE) >= 0)
21 plumber = "/mnt/term/mnt/plumb";
23 /* last resort: try mounting service */
24 plumber = "/mnt/plumb";
25 s = getenv("plumbsrv");
32 if(mount(f, -1, "/mnt/plumb", MREPL, "") < 0){
36 if(access("/mnt/plumb/send", AWRITE) < 0)
40 snprint(buf, sizeof buf, "%s/%s", plumber, name);
41 fd = open(buf, omode);
45 /* try creating port; used by non-standard plumb implementations */
46 rerrstr(err, sizeof err);
47 fd = create(buf, omode, 0600);
50 errstr(err, sizeof err);
64 Strcpy(char *s, char *t)
68 return strcpy(s, t) + strlen(t);
71 /* quote attribute value, if necessary */
82 if(strpbrk(s, " '=\t") == nil)
86 while(t < attrbuf+sizeof attrbuf-2){
100 plumbpackattr(Plumbattr *attr)
109 for(a=attr; a!=nil; a=a->next)
110 n += Strlen(a->name) + 1 + Strlen(quote(a->value)) + 1;
116 for(a=attr; a!=nil; a=a->next){
121 strcat(t, quote(a->value));
130 plumblookup(Plumbattr *attr, char *name)
133 if(strcmp(attr->name, name) == 0)
141 plumbpack(Plumbmsg *m, int *np)
144 char *buf, *p, *attr;
148 ndata = Strlen(m->data);
149 attr = plumbpackattr(m->attr);
150 n = Strlen(m->src)+1 + Strlen(m->dst)+1 + Strlen(m->wdir)+1 +
151 Strlen(m->type)+1 + Strlen(attr)+1 + 16 + ndata;
152 buf = malloc(n+1); /* +1 for '\0' */
157 p = Strcpy(buf, m->src);
159 p = Strcpy(p, m->dst);
161 p = Strcpy(p, m->wdir);
163 p = Strcpy(p, m->type);
167 p += sprint(p, "%d\n", ndata);
168 memmove(p, m->data, ndata);
170 buf[*np] = '\0'; /* null terminate just in case */
178 plumbsend(int fd, Plumbmsg *m)
183 buf = plumbpack(m, &n);
186 n = write(fd, buf, n);
192 plumbline(char **linep, char *buf, int i, int n, int *bad)
198 while(i<n && buf[i]!='\n')
203 p = malloc((i-starti) + 1);
207 memmove(p, buf+starti, i-starti);
217 plumbfree(Plumbmsg *m)
225 for(a=m->attr; a!=nil; a=next){
236 plumbunpackattr(char *p)
238 Plumbattr *attr, *prev, *a;
243 while(*p!='\0' && *p!='\n'){
244 while(*p==' ' || *p=='\t')
248 for(q=p; *q!='\0' && *q!='\n' && *q!=' ' && *q!='\t'; q++)
252 break; /* malformed attribute */
253 a = malloc(sizeof(Plumbattr));
256 a->name = malloc(q-p+1);
261 memmove(a->name, p, q-p);
263 /* process quotes in value */
267 while(*q!='\0' && *q!='\n'){
268 if(v >= attrbuf+sizeof attrbuf)
281 if(c==' ' || c=='\t')
290 a->value = malloc(v-attrbuf+1);
296 memmove(a->value, attrbuf, v-attrbuf);
297 a->value[v-attrbuf] = '\0';
310 plumbaddattr(Plumbattr *attr, Plumbattr *new)
317 while(l->next != nil)
324 plumbdelattr(Plumbattr *attr, char *name)
329 for(l=attr; l!=nil; l=l->next){
330 if(strcmp(name, l->name) == 0)
337 prev->next = l->next;
347 plumbunpackpartial(char *buf, int n, int *morep)
353 m = malloc(sizeof(Plumbmsg));
356 memset(m, 0, sizeof(Plumbmsg));
360 i = plumbline(&m->src, buf, 0, n, &bad);
361 i = plumbline(&m->dst, buf, i, n, &bad);
362 i = plumbline(&m->wdir, buf, i, n, &bad);
363 i = plumbline(&m->type, buf, i, n, &bad);
364 i = plumbline(&attr, buf, i, n, &bad);
365 i = plumbline(&ntext, buf, i, n, &bad);
370 m->attr = plumbunpackattr(attr);
372 m->ndata = atoi(ntext);
375 if(morep!=nil && m->ndata>n-i)
376 *morep = m->ndata - (n-i);
380 m->data = malloc(n-i+1); /* +1 for '\0' */
384 memmove(m->data, buf+i, m->ndata);
386 /* null-terminate in case it's text */
387 m->data[m->ndata] = '\0';
398 plumbunpack(char *buf, int n)
400 return plumbunpackpartial(buf, n, nil);
413 n = read(fd, buf, 8192);
416 m = plumbunpackpartial(buf, n, &more);
417 if(m==nil && more>0){
418 /* we now know how many more bytes to read for complete message */
419 buf = realloc(buf, n+more);
422 if(readn(fd, buf+n, more) == more)
423 m = plumbunpackpartial(buf, n+more, nil);