xref: /plan9/sys/src/libplumb/mesg.c (revision 9b7bf7df4595c26f1e9b67beb0c6e44c9876fb05)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include "plumb.h"
47dd7cddfSDavid du Colombier 
57dd7cddfSDavid du Colombier int
plumbopen(char * name,int omode)67dd7cddfSDavid du Colombier plumbopen(char *name, int omode)
77dd7cddfSDavid du Colombier {
87dd7cddfSDavid du Colombier 	int fd, f;
99c06fe1dSDavid du Colombier 	char *s, *plumber;
109c06fe1dSDavid du Colombier 	char buf[128], err[ERRMAX];
117dd7cddfSDavid du Colombier 
127dd7cddfSDavid du Colombier 	if(name[0] == '/')
137dd7cddfSDavid du Colombier 		return open(name, omode);
149c06fe1dSDavid du Colombier 
159c06fe1dSDavid du Colombier 	/* find elusive plumber */
16debe080aSDavid du Colombier 	if(access("/mnt/plumb/send", AWRITE) >= 0)
179c06fe1dSDavid du Colombier 		plumber = "/mnt/plumb";
18debe080aSDavid du Colombier 	else if(access("/mnt/term/mnt/plumb/send", AWRITE) >= 0)
199c06fe1dSDavid du Colombier 		plumber = "/mnt/term/mnt/plumb";
209c06fe1dSDavid du Colombier 	else{
219c06fe1dSDavid du Colombier 		/* last resort: try mounting service */
229c06fe1dSDavid du Colombier 		plumber = "/mnt/plumb";
237dd7cddfSDavid du Colombier 		s = getenv("plumbsrv");
247dd7cddfSDavid du Colombier 		if(s == nil)
257dd7cddfSDavid du Colombier 			return -1;
267dd7cddfSDavid du Colombier 		f = open(s, ORDWR);
27fed0fa9eSDavid du Colombier 		free(s);
287dd7cddfSDavid du Colombier 		if(f < 0)
297dd7cddfSDavid du Colombier 			return -1;
309c06fe1dSDavid du Colombier 		if(mount(f, -1, "/mnt/plumb", MREPL, "") < 0){
319c06fe1dSDavid du Colombier 			close(f);
327dd7cddfSDavid du Colombier 			return -1;
339c06fe1dSDavid du Colombier 		}
34debe080aSDavid du Colombier 		if(access("/mnt/plumb/send", AWRITE) < 0)
359c06fe1dSDavid du Colombier 			return -1;
369c06fe1dSDavid du Colombier 	}
379c06fe1dSDavid du Colombier 
389c06fe1dSDavid du Colombier 	snprint(buf, sizeof buf, "%s/%s", plumber, name);
399c06fe1dSDavid du Colombier 	fd = open(buf, omode);
409c06fe1dSDavid du Colombier 	if(fd >= 0)
419c06fe1dSDavid du Colombier 		return fd;
429c06fe1dSDavid du Colombier 
439c06fe1dSDavid du Colombier 	/* try creating port; used by non-standard plumb implementations */
449c06fe1dSDavid du Colombier 	rerrstr(err, sizeof err);
459c06fe1dSDavid du Colombier 	fd = create(buf, omode, 0600);
469c06fe1dSDavid du Colombier 	if(fd >= 0)
479c06fe1dSDavid du Colombier 		return fd;
489c06fe1dSDavid du Colombier 	errstr(err, sizeof err);
499c06fe1dSDavid du Colombier 
509c06fe1dSDavid du Colombier 	return -1;
517dd7cddfSDavid du Colombier }
527dd7cddfSDavid du Colombier 
537dd7cddfSDavid du Colombier static int
Strlen(char * s)547dd7cddfSDavid du Colombier Strlen(char *s)
557dd7cddfSDavid du Colombier {
567dd7cddfSDavid du Colombier 	if(s == nil)
577dd7cddfSDavid du Colombier 		return 0;
587dd7cddfSDavid du Colombier 	return strlen(s);
597dd7cddfSDavid du Colombier }
607dd7cddfSDavid du Colombier 
617dd7cddfSDavid du Colombier static char*
Strcpy(char * s,char * t)627dd7cddfSDavid du Colombier Strcpy(char *s, char *t)
637dd7cddfSDavid du Colombier {
647dd7cddfSDavid du Colombier 	if(t == nil)
657dd7cddfSDavid du Colombier 		return s;
667dd7cddfSDavid du Colombier 	return strcpy(s, t) + strlen(t);
677dd7cddfSDavid du Colombier }
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier /* quote attribute value, if necessary */
707dd7cddfSDavid du Colombier static char*
quote(char * s,char * buf,char * bufe)71*9b7bf7dfSDavid du Colombier quote(char *s, char *buf, char *bufe)
727dd7cddfSDavid du Colombier {
737dd7cddfSDavid du Colombier 	char *t;
747dd7cddfSDavid du Colombier 	int c;
757dd7cddfSDavid du Colombier 
767dd7cddfSDavid du Colombier 	if(s == nil){
77*9b7bf7dfSDavid du Colombier 		buf[0] = '\0';
78*9b7bf7dfSDavid du Colombier 		return buf;
797dd7cddfSDavid du Colombier 	}
807dd7cddfSDavid du Colombier 	if(strpbrk(s, " '=\t") == nil)
817dd7cddfSDavid du Colombier 		return s;
82*9b7bf7dfSDavid du Colombier 	t = buf;
837dd7cddfSDavid du Colombier 	*t++ = '\'';
84*9b7bf7dfSDavid du Colombier 	while(t < bufe-2){
857dd7cddfSDavid du Colombier 		c = *s++;
867dd7cddfSDavid du Colombier 		if(c == '\0')
877dd7cddfSDavid du Colombier 			break;
887dd7cddfSDavid du Colombier 		*t++ = c;
897dd7cddfSDavid du Colombier 		if(c == '\'')
907dd7cddfSDavid du Colombier 			*t++ = c;
917dd7cddfSDavid du Colombier 	}
927dd7cddfSDavid du Colombier 	*t++ = '\'';
937dd7cddfSDavid du Colombier 	*t = '\0';
94*9b7bf7dfSDavid du Colombier 	return buf;
957dd7cddfSDavid du Colombier }
967dd7cddfSDavid du Colombier 
977dd7cddfSDavid du Colombier char*
plumbpackattr(Plumbattr * attr)987dd7cddfSDavid du Colombier plumbpackattr(Plumbattr *attr)
997dd7cddfSDavid du Colombier {
1007dd7cddfSDavid du Colombier 	int n;
1017dd7cddfSDavid du Colombier 	Plumbattr *a;
102*9b7bf7dfSDavid du Colombier 	char *s, *t, *buf, *bufe;
1037dd7cddfSDavid du Colombier 
1047dd7cddfSDavid du Colombier 	if(attr == nil)
1057dd7cddfSDavid du Colombier 		return nil;
106*9b7bf7dfSDavid du Colombier 	if((buf = malloc(4096)) == nil)
107*9b7bf7dfSDavid du Colombier 		return nil;
108*9b7bf7dfSDavid du Colombier 	bufe = buf + 4096;
1097dd7cddfSDavid du Colombier 	n = 0;
1107dd7cddfSDavid du Colombier 	for(a=attr; a!=nil; a=a->next)
111*9b7bf7dfSDavid du Colombier 		n += Strlen(a->name) + 1 + Strlen(quote(a->value, buf, bufe)) + 1;
1127dd7cddfSDavid du Colombier 	s = malloc(n);
113*9b7bf7dfSDavid du Colombier 	if(s == nil) {
114*9b7bf7dfSDavid du Colombier 		free(buf);
1157dd7cddfSDavid du Colombier 		return nil;
116*9b7bf7dfSDavid du Colombier 	}
1177dd7cddfSDavid du Colombier 	t = s;
1187dd7cddfSDavid du Colombier 	*t = '\0';
1197dd7cddfSDavid du Colombier 	for(a=attr; a!=nil; a=a->next){
1207dd7cddfSDavid du Colombier 		if(t != s)
1217dd7cddfSDavid du Colombier 			*t++ = ' ';
1227dd7cddfSDavid du Colombier 		strcpy(t, a->name);
1237dd7cddfSDavid du Colombier 		strcat(t, "=");
124*9b7bf7dfSDavid du Colombier 		strcat(t, quote(a->value, buf, bufe));
1257dd7cddfSDavid du Colombier 		t += strlen(t);
1267dd7cddfSDavid du Colombier 	}
1277dd7cddfSDavid du Colombier 	if(t > s+n)
1287dd7cddfSDavid du Colombier 		abort();
129*9b7bf7dfSDavid du Colombier 	free(buf);
1307dd7cddfSDavid du Colombier 	return s;
1317dd7cddfSDavid du Colombier }
1327dd7cddfSDavid du Colombier 
1337dd7cddfSDavid du Colombier char*
plumblookup(Plumbattr * attr,char * name)1347dd7cddfSDavid du Colombier plumblookup(Plumbattr *attr, char *name)
1357dd7cddfSDavid du Colombier {
1367dd7cddfSDavid du Colombier 	while(attr){
1377dd7cddfSDavid du Colombier 		if(strcmp(attr->name, name) == 0)
1387dd7cddfSDavid du Colombier 			return attr->value;
1397dd7cddfSDavid du Colombier 		attr = attr->next;
1407dd7cddfSDavid du Colombier 	}
1417dd7cddfSDavid du Colombier 	return nil;
1427dd7cddfSDavid du Colombier }
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier char*
plumbpack(Plumbmsg * m,int * np)1457dd7cddfSDavid du Colombier plumbpack(Plumbmsg *m, int *np)
1467dd7cddfSDavid du Colombier {
1477dd7cddfSDavid du Colombier 	int n, ndata;
1487dd7cddfSDavid du Colombier 	char *buf, *p, *attr;
1497dd7cddfSDavid du Colombier 
1507dd7cddfSDavid du Colombier 	ndata = m->ndata;
1517dd7cddfSDavid du Colombier 	if(ndata < 0)
1527dd7cddfSDavid du Colombier 		ndata = Strlen(m->data);
1537dd7cddfSDavid du Colombier 	attr = plumbpackattr(m->attr);
1547dd7cddfSDavid du Colombier 	n = Strlen(m->src)+1 + Strlen(m->dst)+1 + Strlen(m->wdir)+1 +
1557dd7cddfSDavid du Colombier 		Strlen(m->type)+1 + Strlen(attr)+1 + 16 + ndata;
1567dd7cddfSDavid du Colombier 	buf = malloc(n+1);	/* +1 for '\0' */
1577dd7cddfSDavid du Colombier 	if(buf == nil){
1587dd7cddfSDavid du Colombier 		free(attr);
1597dd7cddfSDavid du Colombier 		return nil;
1607dd7cddfSDavid du Colombier 	}
1617dd7cddfSDavid du Colombier 	p = Strcpy(buf, m->src);
1627dd7cddfSDavid du Colombier 	*p++ = '\n';
1637dd7cddfSDavid du Colombier 	p = Strcpy(p, m->dst);
1647dd7cddfSDavid du Colombier 	*p++ = '\n';
1657dd7cddfSDavid du Colombier 	p = Strcpy(p, m->wdir);
1667dd7cddfSDavid du Colombier 	*p++ = '\n';
1677dd7cddfSDavid du Colombier 	p = Strcpy(p, m->type);
1687dd7cddfSDavid du Colombier 	*p++ = '\n';
1697dd7cddfSDavid du Colombier 	p = Strcpy(p, attr);
1707dd7cddfSDavid du Colombier 	*p++ = '\n';
1717dd7cddfSDavid du Colombier 	p += sprint(p, "%d\n", ndata);
1727dd7cddfSDavid du Colombier 	memmove(p, m->data, ndata);
1737dd7cddfSDavid du Colombier 	*np = (p-buf)+ndata;
1747dd7cddfSDavid du Colombier 	buf[*np] = '\0';	/* null terminate just in case */
1757dd7cddfSDavid du Colombier 	if(*np >= n+1)
1767dd7cddfSDavid du Colombier 		abort();
1777dd7cddfSDavid du Colombier 	free(attr);
1787dd7cddfSDavid du Colombier 	return buf;
1797dd7cddfSDavid du Colombier }
1807dd7cddfSDavid du Colombier 
1817dd7cddfSDavid du Colombier int
plumbsend(int fd,Plumbmsg * m)1827dd7cddfSDavid du Colombier plumbsend(int fd, Plumbmsg *m)
1837dd7cddfSDavid du Colombier {
1847dd7cddfSDavid du Colombier 	char *buf;
1857dd7cddfSDavid du Colombier 	int n;
1867dd7cddfSDavid du Colombier 
1877dd7cddfSDavid du Colombier 	buf = plumbpack(m, &n);
1887dd7cddfSDavid du Colombier 	if(buf == nil)
1897dd7cddfSDavid du Colombier 		return -1;
1907dd7cddfSDavid du Colombier 	n = write(fd, buf, n);
1917dd7cddfSDavid du Colombier 	free(buf);
1927dd7cddfSDavid du Colombier 	return n;
1937dd7cddfSDavid du Colombier }
1947dd7cddfSDavid du Colombier 
1957dd7cddfSDavid du Colombier static int
plumbline(char ** linep,char * buf,int i,int n,int * bad)1967dd7cddfSDavid du Colombier plumbline(char **linep, char *buf, int i, int n, int *bad)
1977dd7cddfSDavid du Colombier {
1987dd7cddfSDavid du Colombier 	int starti;
1997dd7cddfSDavid du Colombier 	char *p;
2007dd7cddfSDavid du Colombier 
2017dd7cddfSDavid du Colombier 	starti = i;
2027dd7cddfSDavid du Colombier 	while(i<n && buf[i]!='\n')
2037dd7cddfSDavid du Colombier 		i++;
2047dd7cddfSDavid du Colombier 	if(i == n)
2057dd7cddfSDavid du Colombier 		*bad = 1;
2067dd7cddfSDavid du Colombier 	else{
2077dd7cddfSDavid du Colombier 		p = malloc((i-starti) + 1);
2087dd7cddfSDavid du Colombier 		if(p == nil)
2097dd7cddfSDavid du Colombier 			*bad = 1;
2107dd7cddfSDavid du Colombier 		else{
2117dd7cddfSDavid du Colombier 			memmove(p, buf+starti, i-starti);
2127dd7cddfSDavid du Colombier 			p[i-starti] = '\0';
2137dd7cddfSDavid du Colombier 		}
2147dd7cddfSDavid du Colombier 		*linep = p;
2157dd7cddfSDavid du Colombier 		i++;
2167dd7cddfSDavid du Colombier 	}
2177dd7cddfSDavid du Colombier 	return i;
2187dd7cddfSDavid du Colombier }
2197dd7cddfSDavid du Colombier 
2207dd7cddfSDavid du Colombier void
plumbfree(Plumbmsg * m)2217dd7cddfSDavid du Colombier plumbfree(Plumbmsg *m)
2227dd7cddfSDavid du Colombier {
2237dd7cddfSDavid du Colombier 	Plumbattr *a, *next;
2247dd7cddfSDavid du Colombier 
2257dd7cddfSDavid du Colombier 	free(m->src);
2267dd7cddfSDavid du Colombier 	free(m->dst);
2277dd7cddfSDavid du Colombier 	free(m->wdir);
2287dd7cddfSDavid du Colombier 	free(m->type);
2297dd7cddfSDavid du Colombier 	for(a=m->attr; a!=nil; a=next){
2307dd7cddfSDavid du Colombier 		next = a->next;
2317dd7cddfSDavid du Colombier 		free(a->name);
2327dd7cddfSDavid du Colombier 		free(a->value);
2337dd7cddfSDavid du Colombier 		free(a);
2347dd7cddfSDavid du Colombier 	}
2357dd7cddfSDavid du Colombier 	free(m->data);
2367dd7cddfSDavid du Colombier 	free(m);
2377dd7cddfSDavid du Colombier }
2387dd7cddfSDavid du Colombier 
2397dd7cddfSDavid du Colombier Plumbattr*
plumbunpackattr(char * p)2407dd7cddfSDavid du Colombier plumbunpackattr(char *p)
2417dd7cddfSDavid du Colombier {
2427dd7cddfSDavid du Colombier 	Plumbattr *attr, *prev, *a;
243*9b7bf7dfSDavid du Colombier 	char *q, *v, *buf, *bufe;
2447dd7cddfSDavid du Colombier 	int c, quoting;
2457dd7cddfSDavid du Colombier 
246*9b7bf7dfSDavid du Colombier 	buf = malloc(4096);
247*9b7bf7dfSDavid du Colombier 	if(buf == nil)
248*9b7bf7dfSDavid du Colombier 		return nil;
249*9b7bf7dfSDavid du Colombier 	bufe = buf + 4096;
2507dd7cddfSDavid du Colombier 	attr = prev = nil;
2517dd7cddfSDavid du Colombier 	while(*p!='\0' && *p!='\n'){
2527dd7cddfSDavid du Colombier 		while(*p==' ' || *p=='\t')
2537dd7cddfSDavid du Colombier 			p++;
2547dd7cddfSDavid du Colombier 		if(*p == '\0')
2557dd7cddfSDavid du Colombier 			break;
2567dd7cddfSDavid du Colombier 		for(q=p; *q!='\0' && *q!='\n' && *q!=' ' && *q!='\t'; q++)
2577dd7cddfSDavid du Colombier 			if(*q == '=')
2587dd7cddfSDavid du Colombier 				break;
2597dd7cddfSDavid du Colombier 		if(*q != '=')
2607dd7cddfSDavid du Colombier 			break;	/* malformed attribute */
2617dd7cddfSDavid du Colombier 		a = malloc(sizeof(Plumbattr));
2627dd7cddfSDavid du Colombier 		if(a == nil)
2637dd7cddfSDavid du Colombier 			break;
2647dd7cddfSDavid du Colombier 		a->name = malloc(q-p+1);
2657dd7cddfSDavid du Colombier 		if(a->name == nil){
2667dd7cddfSDavid du Colombier 			free(a);
2677dd7cddfSDavid du Colombier 			break;
2687dd7cddfSDavid du Colombier 		}
2697dd7cddfSDavid du Colombier 		memmove(a->name, p, q-p);
2707dd7cddfSDavid du Colombier 		a->name[q-p] = '\0';
2717dd7cddfSDavid du Colombier 		/* process quotes in value */
2727dd7cddfSDavid du Colombier 		q++;	/* skip '=' */
273*9b7bf7dfSDavid du Colombier 		v = buf;
2747dd7cddfSDavid du Colombier 		quoting = 0;
2757dd7cddfSDavid du Colombier 		while(*q!='\0' && *q!='\n'){
276*9b7bf7dfSDavid du Colombier 			if(v >= bufe)
2777dd7cddfSDavid du Colombier 				break;
2787dd7cddfSDavid du Colombier 			c = *q++;
2797dd7cddfSDavid du Colombier 			if(quoting){
2807dd7cddfSDavid du Colombier 				if(c == '\''){
2817dd7cddfSDavid du Colombier 					if(*q == '\'')
2827dd7cddfSDavid du Colombier 						q++;
2837dd7cddfSDavid du Colombier 					else{
2847dd7cddfSDavid du Colombier 						quoting = 0;
2857dd7cddfSDavid du Colombier 						continue;
2867dd7cddfSDavid du Colombier 					}
2877dd7cddfSDavid du Colombier 				}
2887dd7cddfSDavid du Colombier 			}else{
2897dd7cddfSDavid du Colombier 				if(c==' ' || c=='\t')
2907dd7cddfSDavid du Colombier 					break;
2917dd7cddfSDavid du Colombier 				if(c == '\''){
2927dd7cddfSDavid du Colombier 					quoting = 1;
2937dd7cddfSDavid du Colombier 					continue;
2947dd7cddfSDavid du Colombier 				}
2957dd7cddfSDavid du Colombier 			}
2967dd7cddfSDavid du Colombier 			*v++ = c;
2977dd7cddfSDavid du Colombier 		}
298*9b7bf7dfSDavid du Colombier 		a->value = malloc(v-buf+1);
2997dd7cddfSDavid du Colombier 		if(a->value == nil){
3007dd7cddfSDavid du Colombier 			free(a->name);
3017dd7cddfSDavid du Colombier 			free(a);
3027dd7cddfSDavid du Colombier 			break;
3037dd7cddfSDavid du Colombier 		}
304*9b7bf7dfSDavid du Colombier 		memmove(a->value, buf, v-buf);
305*9b7bf7dfSDavid du Colombier 		a->value[v-buf] = '\0';
3067dd7cddfSDavid du Colombier 		a->next = nil;
3077dd7cddfSDavid du Colombier 		if(prev == nil)
3087dd7cddfSDavid du Colombier 			attr = a;
3097dd7cddfSDavid du Colombier 		else
3107dd7cddfSDavid du Colombier 			prev->next = a;
3117dd7cddfSDavid du Colombier 		prev = a;
3127dd7cddfSDavid du Colombier 		p = q;
3137dd7cddfSDavid du Colombier 	}
314*9b7bf7dfSDavid du Colombier 	free(buf);
3157dd7cddfSDavid du Colombier 	return attr;
3167dd7cddfSDavid du Colombier }
3177dd7cddfSDavid du Colombier 
3187dd7cddfSDavid du Colombier Plumbattr*
plumbaddattr(Plumbattr * attr,Plumbattr * new)3197dd7cddfSDavid du Colombier plumbaddattr(Plumbattr *attr, Plumbattr *new)
3207dd7cddfSDavid du Colombier {
3217dd7cddfSDavid du Colombier 	Plumbattr *l;
3227dd7cddfSDavid du Colombier 
3237dd7cddfSDavid du Colombier 	l = attr;
3247dd7cddfSDavid du Colombier 	if(l == nil)
3257dd7cddfSDavid du Colombier 		return new;
3267dd7cddfSDavid du Colombier 	while(l->next != nil)
3277dd7cddfSDavid du Colombier 		l = l->next;
3287dd7cddfSDavid du Colombier 	l->next = new;
3297dd7cddfSDavid du Colombier 	return attr;
3307dd7cddfSDavid du Colombier }
3317dd7cddfSDavid du Colombier 
3327dd7cddfSDavid du Colombier Plumbattr*
plumbdelattr(Plumbattr * attr,char * name)3337dd7cddfSDavid du Colombier plumbdelattr(Plumbattr *attr, char *name)
3347dd7cddfSDavid du Colombier {
3357dd7cddfSDavid du Colombier 	Plumbattr *l, *prev;
3367dd7cddfSDavid du Colombier 
3377dd7cddfSDavid du Colombier 	prev = nil;
3387dd7cddfSDavid du Colombier 	for(l=attr; l!=nil; l=l->next){
3397dd7cddfSDavid du Colombier 		if(strcmp(name, l->name) == 0)
3407dd7cddfSDavid du Colombier 			break;
3417dd7cddfSDavid du Colombier 		prev = l;
3427dd7cddfSDavid du Colombier 	}
3437dd7cddfSDavid du Colombier 	if(l == nil)
3447dd7cddfSDavid du Colombier 		return nil;
3457dd7cddfSDavid du Colombier 	if(prev)
3467dd7cddfSDavid du Colombier 		prev->next = l->next;
3477dd7cddfSDavid du Colombier 	else
3487dd7cddfSDavid du Colombier 		attr = l->next;
3497dd7cddfSDavid du Colombier 	free(l->name);
3507dd7cddfSDavid du Colombier 	free(l->value);
3517dd7cddfSDavid du Colombier 	free(l);
3527dd7cddfSDavid du Colombier 	return attr;
3537dd7cddfSDavid du Colombier }
3547dd7cddfSDavid du Colombier 
3557dd7cddfSDavid du Colombier Plumbmsg*
plumbunpackpartial(char * buf,int n,int * morep)3567dd7cddfSDavid du Colombier plumbunpackpartial(char *buf, int n, int *morep)
3577dd7cddfSDavid du Colombier {
3587dd7cddfSDavid du Colombier 	Plumbmsg *m;
3597dd7cddfSDavid du Colombier 	int i, bad;
3607dd7cddfSDavid du Colombier 	char *ntext, *attr;
3617dd7cddfSDavid du Colombier 
3627dd7cddfSDavid du Colombier 	m = malloc(sizeof(Plumbmsg));
3637dd7cddfSDavid du Colombier 	if(m == nil)
3647dd7cddfSDavid du Colombier 		return nil;
3657dd7cddfSDavid du Colombier 	memset(m, 0, sizeof(Plumbmsg));
3667dd7cddfSDavid du Colombier 	if(morep != nil)
3677dd7cddfSDavid du Colombier 		*morep = 0;
3687dd7cddfSDavid du Colombier 	bad = 0;
3697dd7cddfSDavid du Colombier 	i = plumbline(&m->src, buf, 0, n, &bad);
3707dd7cddfSDavid du Colombier 	i = plumbline(&m->dst, buf, i, n, &bad);
3717dd7cddfSDavid du Colombier 	i = plumbline(&m->wdir, buf, i, n, &bad);
3727dd7cddfSDavid du Colombier 	i = plumbline(&m->type, buf, i, n, &bad);
3737dd7cddfSDavid du Colombier 	i = plumbline(&attr, buf, i, n, &bad);
37459cc4ca5SDavid du Colombier 	i = plumbline(&ntext, buf, i, n, &bad);
37559cc4ca5SDavid du Colombier 	if(bad){
37659cc4ca5SDavid du Colombier 		plumbfree(m);
37759cc4ca5SDavid du Colombier 		return nil;
37859cc4ca5SDavid du Colombier 	}
3797dd7cddfSDavid du Colombier 	m->attr = plumbunpackattr(attr);
3807dd7cddfSDavid du Colombier 	free(attr);
3817dd7cddfSDavid du Colombier 	m->ndata = atoi(ntext);
3827dd7cddfSDavid du Colombier 	if(m->ndata != n-i){
3837dd7cddfSDavid du Colombier 		bad = 1;
3847dd7cddfSDavid du Colombier 		if(morep!=nil && m->ndata>n-i)
3857dd7cddfSDavid du Colombier 			*morep = m->ndata - (n-i);
3867dd7cddfSDavid du Colombier 	}
3877dd7cddfSDavid du Colombier 	free(ntext);
3887dd7cddfSDavid du Colombier 	if(!bad){
3897dd7cddfSDavid du Colombier 		m->data = malloc(n-i+1);	/* +1 for '\0' */
3907dd7cddfSDavid du Colombier 		if(m->data == nil)
3917dd7cddfSDavid du Colombier 			bad = 1;
3927dd7cddfSDavid du Colombier 		else{
3937dd7cddfSDavid du Colombier 			memmove(m->data, buf+i, m->ndata);
3947dd7cddfSDavid du Colombier 			m->ndata = n-i;
3957dd7cddfSDavid du Colombier 			/* null-terminate in case it's text */
3967dd7cddfSDavid du Colombier 			m->data[m->ndata] = '\0';
3977dd7cddfSDavid du Colombier 		}
3987dd7cddfSDavid du Colombier 	}
3997dd7cddfSDavid du Colombier 	if(bad){
4007dd7cddfSDavid du Colombier 		plumbfree(m);
4017dd7cddfSDavid du Colombier 		m = nil;
4027dd7cddfSDavid du Colombier 	}
4037dd7cddfSDavid du Colombier 	return m;
4047dd7cddfSDavid du Colombier }
4057dd7cddfSDavid du Colombier 
4067dd7cddfSDavid du Colombier Plumbmsg*
plumbunpack(char * buf,int n)4077dd7cddfSDavid du Colombier plumbunpack(char *buf, int n)
4087dd7cddfSDavid du Colombier {
4097dd7cddfSDavid du Colombier 	return plumbunpackpartial(buf, n, nil);
4107dd7cddfSDavid du Colombier }
4117dd7cddfSDavid du Colombier 
4127dd7cddfSDavid du Colombier Plumbmsg*
plumbrecv(int fd)4137dd7cddfSDavid du Colombier plumbrecv(int fd)
4147dd7cddfSDavid du Colombier {
4157dd7cddfSDavid du Colombier 	char *buf;
4167dd7cddfSDavid du Colombier 	Plumbmsg *m;
4177dd7cddfSDavid du Colombier 	int n, more;
4187dd7cddfSDavid du Colombier 
4197dd7cddfSDavid du Colombier 	buf = malloc(8192);
4207dd7cddfSDavid du Colombier 	if(buf == nil)
4217dd7cddfSDavid du Colombier 		return nil;
4227dd7cddfSDavid du Colombier 	n = read(fd, buf, 8192);
4237dd7cddfSDavid du Colombier 	m = nil;
4247dd7cddfSDavid du Colombier 	if(n > 0){
4257dd7cddfSDavid du Colombier 		m = plumbunpackpartial(buf, n, &more);
4267dd7cddfSDavid du Colombier 		if(m==nil && more>0){
4277dd7cddfSDavid du Colombier 			/* we now know how many more bytes to read for complete message */
4287dd7cddfSDavid du Colombier 			buf = realloc(buf, n+more);
4297dd7cddfSDavid du Colombier 			if(buf == nil)
4307dd7cddfSDavid du Colombier 				return nil;
4317dd7cddfSDavid du Colombier 			if(readn(fd, buf+n, more) == more)
4327dd7cddfSDavid du Colombier 				m = plumbunpackpartial(buf, n+more, nil);
4337dd7cddfSDavid du Colombier 		}
4347dd7cddfSDavid du Colombier 	}
4357dd7cddfSDavid du Colombier 	free(buf);
4367dd7cddfSDavid du Colombier 	return m;
4377dd7cddfSDavid du Colombier }
438