xref: /plan9/sys/src/libplumb/mesg.c (revision 9c06fe1d54c51a5e47f19e590a2bc12b07b5d99e)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include "plumb.h"
47dd7cddfSDavid du Colombier 
57dd7cddfSDavid du Colombier static char attrbuf[4096];
67dd7cddfSDavid du Colombier 
77dd7cddfSDavid du Colombier int
87dd7cddfSDavid du Colombier plumbopen(char *name, int omode)
97dd7cddfSDavid du Colombier {
107dd7cddfSDavid du Colombier 	int fd, f;
11*9c06fe1dSDavid du Colombier 	char *s, *plumber;
12*9c06fe1dSDavid du Colombier 	char buf[128], err[ERRMAX];
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier 	if(name[0] == '/')
157dd7cddfSDavid du Colombier 		return open(name, omode);
16*9c06fe1dSDavid du Colombier 
17*9c06fe1dSDavid du Colombier 	/* find elusive plumber */
18*9c06fe1dSDavid du Colombier 	if(access("/mnt/plumb/send", OWRITE) >= 0)
19*9c06fe1dSDavid du Colombier 		plumber = "/mnt/plumb";
20*9c06fe1dSDavid du Colombier 	else if(access("/mnt/term/mnt/plumb/send", OWRITE) >= 0)
21*9c06fe1dSDavid du Colombier 		plumber = "/mnt/term/mnt/plumb";
22*9c06fe1dSDavid du Colombier 	else{
23*9c06fe1dSDavid du Colombier 		/* last resort: try mounting service */
24*9c06fe1dSDavid du Colombier 		plumber = "/mnt/plumb";
257dd7cddfSDavid du Colombier 		s = getenv("plumbsrv");
267dd7cddfSDavid du Colombier 		if(s == nil)
277dd7cddfSDavid du Colombier 			return -1;
287dd7cddfSDavid du Colombier 		f = open(s, ORDWR);
297dd7cddfSDavid du Colombier 		if(f < 0)
307dd7cddfSDavid du Colombier 			return -1;
31*9c06fe1dSDavid du Colombier 		if(mount(f, -1, "/mnt/plumb", MREPL, "") < 0){
32*9c06fe1dSDavid du Colombier 			close(f);
337dd7cddfSDavid du Colombier 			return -1;
34*9c06fe1dSDavid du Colombier 		}
35*9c06fe1dSDavid du Colombier 		if(access("/mnt/plumb/send", OWRITE) < 0)
36*9c06fe1dSDavid du Colombier 			return -1;
37*9c06fe1dSDavid du Colombier 	}
38*9c06fe1dSDavid du Colombier 
39*9c06fe1dSDavid du Colombier 	snprint(buf, sizeof buf, "%s/%s", plumber, name);
40*9c06fe1dSDavid du Colombier 	fd = open(buf, omode);
41*9c06fe1dSDavid du Colombier 	if(fd >= 0)
42*9c06fe1dSDavid du Colombier 		return fd;
43*9c06fe1dSDavid du Colombier 
44*9c06fe1dSDavid du Colombier 	/* try creating port; used by non-standard plumb implementations */
45*9c06fe1dSDavid du Colombier 	rerrstr(err, sizeof err);
46*9c06fe1dSDavid du Colombier 	fd = create(buf, omode, 0600);
47*9c06fe1dSDavid du Colombier 	if(fd >= 0)
48*9c06fe1dSDavid du Colombier 		return fd;
49*9c06fe1dSDavid du Colombier 	errstr(err, sizeof err);
50*9c06fe1dSDavid du Colombier 
51*9c06fe1dSDavid du Colombier 	return -1;
527dd7cddfSDavid du Colombier }
537dd7cddfSDavid du Colombier 
547dd7cddfSDavid du Colombier static int
557dd7cddfSDavid du Colombier Strlen(char *s)
567dd7cddfSDavid du Colombier {
577dd7cddfSDavid du Colombier 	if(s == nil)
587dd7cddfSDavid du Colombier 		return 0;
597dd7cddfSDavid du Colombier 	return strlen(s);
607dd7cddfSDavid du Colombier }
617dd7cddfSDavid du Colombier 
627dd7cddfSDavid du Colombier static char*
637dd7cddfSDavid du Colombier Strcpy(char *s, char *t)
647dd7cddfSDavid du Colombier {
657dd7cddfSDavid du Colombier 	if(t == nil)
667dd7cddfSDavid du Colombier 		return s;
677dd7cddfSDavid du Colombier 	return strcpy(s, t) + strlen(t);
687dd7cddfSDavid du Colombier }
697dd7cddfSDavid du Colombier 
707dd7cddfSDavid du Colombier /* quote attribute value, if necessary */
717dd7cddfSDavid du Colombier static char*
727dd7cddfSDavid du Colombier quote(char *s)
737dd7cddfSDavid du Colombier {
747dd7cddfSDavid du Colombier 	char *t;
757dd7cddfSDavid du Colombier 	int c;
767dd7cddfSDavid du Colombier 
777dd7cddfSDavid du Colombier 	if(s == nil){
787dd7cddfSDavid du Colombier 		attrbuf[0] = '\0';
797dd7cddfSDavid du Colombier 		return attrbuf;
807dd7cddfSDavid du Colombier 	}
817dd7cddfSDavid du Colombier 	if(strpbrk(s, " '=\t") == nil)
827dd7cddfSDavid du Colombier 		return s;
837dd7cddfSDavid du Colombier 	t = attrbuf;
847dd7cddfSDavid du Colombier 	*t++ = '\'';
857dd7cddfSDavid du Colombier 	while(t < attrbuf+sizeof attrbuf-2){
867dd7cddfSDavid du Colombier 		c = *s++;
877dd7cddfSDavid du Colombier 		if(c == '\0')
887dd7cddfSDavid du Colombier 			break;
897dd7cddfSDavid du Colombier 		*t++ = c;
907dd7cddfSDavid du Colombier 		if(c == '\'')
917dd7cddfSDavid du Colombier 			*t++ = c;
927dd7cddfSDavid du Colombier 	}
937dd7cddfSDavid du Colombier 	*t++ = '\'';
947dd7cddfSDavid du Colombier 	*t = '\0';
957dd7cddfSDavid du Colombier 	return attrbuf;
967dd7cddfSDavid du Colombier }
977dd7cddfSDavid du Colombier 
987dd7cddfSDavid du Colombier char*
997dd7cddfSDavid du Colombier plumbpackattr(Plumbattr *attr)
1007dd7cddfSDavid du Colombier {
1017dd7cddfSDavid du Colombier 	int n;
1027dd7cddfSDavid du Colombier 	Plumbattr *a;
1037dd7cddfSDavid du Colombier 	char *s, *t;
1047dd7cddfSDavid du Colombier 
1057dd7cddfSDavid du Colombier 	if(attr == nil)
1067dd7cddfSDavid du Colombier 		return nil;
1077dd7cddfSDavid du Colombier 	n = 0;
1087dd7cddfSDavid du Colombier 	for(a=attr; a!=nil; a=a->next)
1097dd7cddfSDavid du Colombier 		n += Strlen(a->name) + 1 + Strlen(quote(a->value)) + 1;
1107dd7cddfSDavid du Colombier 	s = malloc(n);
1117dd7cddfSDavid du Colombier 	if(s == nil)
1127dd7cddfSDavid du Colombier 		return nil;
1137dd7cddfSDavid du Colombier 	t = s;
1147dd7cddfSDavid du Colombier 	*t = '\0';
1157dd7cddfSDavid du Colombier 	for(a=attr; a!=nil; a=a->next){
1167dd7cddfSDavid du Colombier 		if(t != s)
1177dd7cddfSDavid du Colombier 			*t++ = ' ';
1187dd7cddfSDavid du Colombier 		strcpy(t, a->name);
1197dd7cddfSDavid du Colombier 		strcat(t, "=");
1207dd7cddfSDavid du Colombier 		strcat(t, quote(a->value));
1217dd7cddfSDavid du Colombier 		t += strlen(t);
1227dd7cddfSDavid du Colombier 	}
1237dd7cddfSDavid du Colombier 	if(t > s+n)
1247dd7cddfSDavid du Colombier 		abort();
1257dd7cddfSDavid du Colombier 	return s;
1267dd7cddfSDavid du Colombier }
1277dd7cddfSDavid du Colombier 
1287dd7cddfSDavid du Colombier char*
1297dd7cddfSDavid du Colombier plumblookup(Plumbattr *attr, char *name)
1307dd7cddfSDavid du Colombier {
1317dd7cddfSDavid du Colombier 	while(attr){
1327dd7cddfSDavid du Colombier 		if(strcmp(attr->name, name) == 0)
1337dd7cddfSDavid du Colombier 			return attr->value;
1347dd7cddfSDavid du Colombier 		attr = attr->next;
1357dd7cddfSDavid du Colombier 	}
1367dd7cddfSDavid du Colombier 	return nil;
1377dd7cddfSDavid du Colombier }
1387dd7cddfSDavid du Colombier 
1397dd7cddfSDavid du Colombier char*
1407dd7cddfSDavid du Colombier plumbpack(Plumbmsg *m, int *np)
1417dd7cddfSDavid du Colombier {
1427dd7cddfSDavid du Colombier 	int n, ndata;
1437dd7cddfSDavid du Colombier 	char *buf, *p, *attr;
1447dd7cddfSDavid du Colombier 
1457dd7cddfSDavid du Colombier 	ndata = m->ndata;
1467dd7cddfSDavid du Colombier 	if(ndata < 0)
1477dd7cddfSDavid du Colombier 		ndata = Strlen(m->data);
1487dd7cddfSDavid du Colombier 	attr = plumbpackattr(m->attr);
1497dd7cddfSDavid du Colombier 	n = Strlen(m->src)+1 + Strlen(m->dst)+1 + Strlen(m->wdir)+1 +
1507dd7cddfSDavid du Colombier 		Strlen(m->type)+1 + Strlen(attr)+1 + 16 + ndata;
1517dd7cddfSDavid du Colombier 	buf = malloc(n+1);	/* +1 for '\0' */
1527dd7cddfSDavid du Colombier 	if(buf == nil){
1537dd7cddfSDavid du Colombier 		free(attr);
1547dd7cddfSDavid du Colombier 		return nil;
1557dd7cddfSDavid du Colombier 	}
1567dd7cddfSDavid du Colombier 	p = Strcpy(buf, m->src);
1577dd7cddfSDavid du Colombier 	*p++ = '\n';
1587dd7cddfSDavid du Colombier 	p = Strcpy(p, m->dst);
1597dd7cddfSDavid du Colombier 	*p++ = '\n';
1607dd7cddfSDavid du Colombier 	p = Strcpy(p, m->wdir);
1617dd7cddfSDavid du Colombier 	*p++ = '\n';
1627dd7cddfSDavid du Colombier 	p = Strcpy(p, m->type);
1637dd7cddfSDavid du Colombier 	*p++ = '\n';
1647dd7cddfSDavid du Colombier 	p = Strcpy(p, attr);
1657dd7cddfSDavid du Colombier 	*p++ = '\n';
1667dd7cddfSDavid du Colombier 	p += sprint(p, "%d\n", ndata);
1677dd7cddfSDavid du Colombier 	memmove(p, m->data, ndata);
1687dd7cddfSDavid du Colombier 	*np = (p-buf)+ndata;
1697dd7cddfSDavid du Colombier 	buf[*np] = '\0';	/* null terminate just in case */
1707dd7cddfSDavid du Colombier 	if(*np >= n+1)
1717dd7cddfSDavid du Colombier 		abort();
1727dd7cddfSDavid du Colombier 	free(attr);
1737dd7cddfSDavid du Colombier 	return buf;
1747dd7cddfSDavid du Colombier }
1757dd7cddfSDavid du Colombier 
1767dd7cddfSDavid du Colombier int
1777dd7cddfSDavid du Colombier plumbsend(int fd, Plumbmsg *m)
1787dd7cddfSDavid du Colombier {
1797dd7cddfSDavid du Colombier 	char *buf;
1807dd7cddfSDavid du Colombier 	int n;
1817dd7cddfSDavid du Colombier 
1827dd7cddfSDavid du Colombier 	buf = plumbpack(m, &n);
1837dd7cddfSDavid du Colombier 	if(buf == nil)
1847dd7cddfSDavid du Colombier 		return -1;
1857dd7cddfSDavid du Colombier 	n = write(fd, buf, n);
1867dd7cddfSDavid du Colombier 	free(buf);
1877dd7cddfSDavid du Colombier 	return n;
1887dd7cddfSDavid du Colombier }
1897dd7cddfSDavid du Colombier 
1907dd7cddfSDavid du Colombier static int
1917dd7cddfSDavid du Colombier plumbline(char **linep, char *buf, int i, int n, int *bad)
1927dd7cddfSDavid du Colombier {
1937dd7cddfSDavid du Colombier 	int starti;
1947dd7cddfSDavid du Colombier 	char *p;
1957dd7cddfSDavid du Colombier 
1967dd7cddfSDavid du Colombier 	starti = i;
1977dd7cddfSDavid du Colombier 	while(i<n && buf[i]!='\n')
1987dd7cddfSDavid du Colombier 		i++;
1997dd7cddfSDavid du Colombier 	if(i == n)
2007dd7cddfSDavid du Colombier 		*bad = 1;
2017dd7cddfSDavid du Colombier 	else{
2027dd7cddfSDavid du Colombier 		p = malloc((i-starti) + 1);
2037dd7cddfSDavid du Colombier 		if(p == nil)
2047dd7cddfSDavid du Colombier 			*bad = 1;
2057dd7cddfSDavid du Colombier 		else{
2067dd7cddfSDavid du Colombier 			memmove(p, buf+starti, i-starti);
2077dd7cddfSDavid du Colombier 			p[i-starti] = '\0';
2087dd7cddfSDavid du Colombier 		}
2097dd7cddfSDavid du Colombier 		*linep = p;
2107dd7cddfSDavid du Colombier 		i++;
2117dd7cddfSDavid du Colombier 	}
2127dd7cddfSDavid du Colombier 	return i;
2137dd7cddfSDavid du Colombier }
2147dd7cddfSDavid du Colombier 
2157dd7cddfSDavid du Colombier void
2167dd7cddfSDavid du Colombier plumbfree(Plumbmsg *m)
2177dd7cddfSDavid du Colombier {
2187dd7cddfSDavid du Colombier 	Plumbattr *a, *next;
2197dd7cddfSDavid du Colombier 
2207dd7cddfSDavid du Colombier 	free(m->src);
2217dd7cddfSDavid du Colombier 	free(m->dst);
2227dd7cddfSDavid du Colombier 	free(m->wdir);
2237dd7cddfSDavid du Colombier 	free(m->type);
2247dd7cddfSDavid du Colombier 	for(a=m->attr; a!=nil; a=next){
2257dd7cddfSDavid du Colombier 		next = a->next;
2267dd7cddfSDavid du Colombier 		free(a->name);
2277dd7cddfSDavid du Colombier 		free(a->value);
2287dd7cddfSDavid du Colombier 		free(a);
2297dd7cddfSDavid du Colombier 	}
2307dd7cddfSDavid du Colombier 	free(m->data);
2317dd7cddfSDavid du Colombier 	free(m);
2327dd7cddfSDavid du Colombier }
2337dd7cddfSDavid du Colombier 
2347dd7cddfSDavid du Colombier Plumbattr*
2357dd7cddfSDavid du Colombier plumbunpackattr(char *p)
2367dd7cddfSDavid du Colombier {
2377dd7cddfSDavid du Colombier 	Plumbattr *attr, *prev, *a;
2387dd7cddfSDavid du Colombier 	char *q, *v;
2397dd7cddfSDavid du Colombier 	int c, quoting;
2407dd7cddfSDavid du Colombier 
2417dd7cddfSDavid du Colombier 	attr = prev = nil;
2427dd7cddfSDavid du Colombier 	while(*p!='\0' && *p!='\n'){
2437dd7cddfSDavid du Colombier 		while(*p==' ' || *p=='\t')
2447dd7cddfSDavid du Colombier 			p++;
2457dd7cddfSDavid du Colombier 		if(*p == '\0')
2467dd7cddfSDavid du Colombier 			break;
2477dd7cddfSDavid du Colombier 		for(q=p; *q!='\0' && *q!='\n' && *q!=' ' && *q!='\t'; q++)
2487dd7cddfSDavid du Colombier 			if(*q == '=')
2497dd7cddfSDavid du Colombier 				break;
2507dd7cddfSDavid du Colombier 		if(*q != '=')
2517dd7cddfSDavid du Colombier 			break;	/* malformed attribute */
2527dd7cddfSDavid du Colombier 		a = malloc(sizeof(Plumbattr));
2537dd7cddfSDavid du Colombier 		if(a == nil)
2547dd7cddfSDavid du Colombier 			break;
2557dd7cddfSDavid du Colombier 		a->name = malloc(q-p+1);
2567dd7cddfSDavid du Colombier 		if(a->name == nil){
2577dd7cddfSDavid du Colombier 			free(a);
2587dd7cddfSDavid du Colombier 			break;
2597dd7cddfSDavid du Colombier 		}
2607dd7cddfSDavid du Colombier 		memmove(a->name, p, q-p);
2617dd7cddfSDavid du Colombier 		a->name[q-p] = '\0';
2627dd7cddfSDavid du Colombier 		/* process quotes in value */
2637dd7cddfSDavid du Colombier 		q++;	/* skip '=' */
2647dd7cddfSDavid du Colombier 		v = attrbuf;
2657dd7cddfSDavid du Colombier 		quoting = 0;
2667dd7cddfSDavid du Colombier 		while(*q!='\0' && *q!='\n'){
2677dd7cddfSDavid du Colombier 			if(v >= attrbuf+sizeof attrbuf)
2687dd7cddfSDavid du Colombier 				break;
2697dd7cddfSDavid du Colombier 			c = *q++;
2707dd7cddfSDavid du Colombier 			if(quoting){
2717dd7cddfSDavid du Colombier 				if(c == '\''){
2727dd7cddfSDavid du Colombier 					if(*q == '\'')
2737dd7cddfSDavid du Colombier 						q++;
2747dd7cddfSDavid du Colombier 					else{
2757dd7cddfSDavid du Colombier 						quoting = 0;
2767dd7cddfSDavid du Colombier 						continue;
2777dd7cddfSDavid du Colombier 					}
2787dd7cddfSDavid du Colombier 				}
2797dd7cddfSDavid du Colombier 			}else{
2807dd7cddfSDavid du Colombier 				if(c==' ' || c=='\t')
2817dd7cddfSDavid du Colombier 					break;
2827dd7cddfSDavid du Colombier 				if(c == '\''){
2837dd7cddfSDavid du Colombier 					quoting = 1;
2847dd7cddfSDavid du Colombier 					continue;
2857dd7cddfSDavid du Colombier 				}
2867dd7cddfSDavid du Colombier 			}
2877dd7cddfSDavid du Colombier 			*v++ = c;
2887dd7cddfSDavid du Colombier 		}
2897dd7cddfSDavid du Colombier 		a->value = malloc(v-attrbuf+1);
2907dd7cddfSDavid du Colombier 		if(a->value == nil){
2917dd7cddfSDavid du Colombier 			free(a->name);
2927dd7cddfSDavid du Colombier 			free(a);
2937dd7cddfSDavid du Colombier 			break;
2947dd7cddfSDavid du Colombier 		}
2957dd7cddfSDavid du Colombier 		memmove(a->value, attrbuf, v-attrbuf);
2967dd7cddfSDavid du Colombier 		a->value[v-attrbuf] = '\0';
2977dd7cddfSDavid du Colombier 		a->next = nil;
2987dd7cddfSDavid du Colombier 		if(prev == nil)
2997dd7cddfSDavid du Colombier 			attr = a;
3007dd7cddfSDavid du Colombier 		else
3017dd7cddfSDavid du Colombier 			prev->next = a;
3027dd7cddfSDavid du Colombier 		prev = a;
3037dd7cddfSDavid du Colombier 		p = q;
3047dd7cddfSDavid du Colombier 	}
3057dd7cddfSDavid du Colombier 	return attr;
3067dd7cddfSDavid du Colombier }
3077dd7cddfSDavid du Colombier 
3087dd7cddfSDavid du Colombier Plumbattr*
3097dd7cddfSDavid du Colombier plumbaddattr(Plumbattr *attr, Plumbattr *new)
3107dd7cddfSDavid du Colombier {
3117dd7cddfSDavid du Colombier 	Plumbattr *l;
3127dd7cddfSDavid du Colombier 
3137dd7cddfSDavid du Colombier 	l = attr;
3147dd7cddfSDavid du Colombier 	if(l == nil)
3157dd7cddfSDavid du Colombier 		return new;
3167dd7cddfSDavid du Colombier 	while(l->next != nil)
3177dd7cddfSDavid du Colombier 		l = l->next;
3187dd7cddfSDavid du Colombier 	l->next = new;
3197dd7cddfSDavid du Colombier 	return attr;
3207dd7cddfSDavid du Colombier }
3217dd7cddfSDavid du Colombier 
3227dd7cddfSDavid du Colombier Plumbattr*
3237dd7cddfSDavid du Colombier plumbdelattr(Plumbattr *attr, char *name)
3247dd7cddfSDavid du Colombier {
3257dd7cddfSDavid du Colombier 	Plumbattr *l, *prev;
3267dd7cddfSDavid du Colombier 
3277dd7cddfSDavid du Colombier 	prev = nil;
3287dd7cddfSDavid du Colombier 	for(l=attr; l!=nil; l=l->next){
3297dd7cddfSDavid du Colombier 		if(strcmp(name, l->name) == 0)
3307dd7cddfSDavid du Colombier 			break;
3317dd7cddfSDavid du Colombier 		prev = l;
3327dd7cddfSDavid du Colombier 	}
3337dd7cddfSDavid du Colombier 	if(l == nil)
3347dd7cddfSDavid du Colombier 		return nil;
3357dd7cddfSDavid du Colombier 	if(prev)
3367dd7cddfSDavid du Colombier 		prev->next = l->next;
3377dd7cddfSDavid du Colombier 	else
3387dd7cddfSDavid du Colombier 		attr = l->next;
3397dd7cddfSDavid du Colombier 	free(l->name);
3407dd7cddfSDavid du Colombier 	free(l->value);
3417dd7cddfSDavid du Colombier 	free(l);
3427dd7cddfSDavid du Colombier 	return attr;
3437dd7cddfSDavid du Colombier }
3447dd7cddfSDavid du Colombier 
3457dd7cddfSDavid du Colombier Plumbmsg*
3467dd7cddfSDavid du Colombier plumbunpackpartial(char *buf, int n, int *morep)
3477dd7cddfSDavid du Colombier {
3487dd7cddfSDavid du Colombier 	Plumbmsg *m;
3497dd7cddfSDavid du Colombier 	int i, bad;
3507dd7cddfSDavid du Colombier 	char *ntext, *attr;
3517dd7cddfSDavid du Colombier 
3527dd7cddfSDavid du Colombier 	m = malloc(sizeof(Plumbmsg));
3537dd7cddfSDavid du Colombier 	if(m == nil)
3547dd7cddfSDavid du Colombier 		return nil;
3557dd7cddfSDavid du Colombier 	memset(m, 0, sizeof(Plumbmsg));
3567dd7cddfSDavid du Colombier 	if(morep != nil)
3577dd7cddfSDavid du Colombier 		*morep = 0;
3587dd7cddfSDavid du Colombier 	bad = 0;
3597dd7cddfSDavid du Colombier 	i = plumbline(&m->src, buf, 0, n, &bad);
3607dd7cddfSDavid du Colombier 	i = plumbline(&m->dst, buf, i, n, &bad);
3617dd7cddfSDavid du Colombier 	i = plumbline(&m->wdir, buf, i, n, &bad);
3627dd7cddfSDavid du Colombier 	i = plumbline(&m->type, buf, i, n, &bad);
3637dd7cddfSDavid du Colombier 	i = plumbline(&attr, buf, i, n, &bad);
36459cc4ca5SDavid du Colombier 	i = plumbline(&ntext, buf, i, n, &bad);
36559cc4ca5SDavid du Colombier 	if(bad){
36659cc4ca5SDavid du Colombier 		plumbfree(m);
36759cc4ca5SDavid du Colombier 		return nil;
36859cc4ca5SDavid du Colombier 	}
3697dd7cddfSDavid du Colombier 	m->attr = plumbunpackattr(attr);
3707dd7cddfSDavid du Colombier 	free(attr);
3717dd7cddfSDavid du Colombier 	m->ndata = atoi(ntext);
3727dd7cddfSDavid du Colombier 	if(m->ndata != n-i){
3737dd7cddfSDavid du Colombier 		bad = 1;
3747dd7cddfSDavid du Colombier 		if(morep!=nil && m->ndata>n-i)
3757dd7cddfSDavid du Colombier 			*morep = m->ndata - (n-i);
3767dd7cddfSDavid du Colombier 	}
3777dd7cddfSDavid du Colombier 	free(ntext);
3787dd7cddfSDavid du Colombier 	if(!bad){
3797dd7cddfSDavid du Colombier 		m->data = malloc(n-i+1);	/* +1 for '\0' */
3807dd7cddfSDavid du Colombier 		if(m->data == nil)
3817dd7cddfSDavid du Colombier 			bad = 1;
3827dd7cddfSDavid du Colombier 		else{
3837dd7cddfSDavid du Colombier 			memmove(m->data, buf+i, m->ndata);
3847dd7cddfSDavid du Colombier 			m->ndata = n-i;
3857dd7cddfSDavid du Colombier 			/* null-terminate in case it's text */
3867dd7cddfSDavid du Colombier 			m->data[m->ndata] = '\0';
3877dd7cddfSDavid du Colombier 		}
3887dd7cddfSDavid du Colombier 	}
3897dd7cddfSDavid du Colombier 	if(bad){
3907dd7cddfSDavid du Colombier 		plumbfree(m);
3917dd7cddfSDavid du Colombier 		m = nil;
3927dd7cddfSDavid du Colombier 	}
3937dd7cddfSDavid du Colombier 	return m;
3947dd7cddfSDavid du Colombier }
3957dd7cddfSDavid du Colombier 
3967dd7cddfSDavid du Colombier Plumbmsg*
3977dd7cddfSDavid du Colombier plumbunpack(char *buf, int n)
3987dd7cddfSDavid du Colombier {
3997dd7cddfSDavid du Colombier 	return plumbunpackpartial(buf, n, nil);
4007dd7cddfSDavid du Colombier }
4017dd7cddfSDavid du Colombier 
4027dd7cddfSDavid du Colombier Plumbmsg*
4037dd7cddfSDavid du Colombier plumbrecv(int fd)
4047dd7cddfSDavid du Colombier {
4057dd7cddfSDavid du Colombier 	char *buf;
4067dd7cddfSDavid du Colombier 	Plumbmsg *m;
4077dd7cddfSDavid du Colombier 	int n, more;
4087dd7cddfSDavid du Colombier 
4097dd7cddfSDavid du Colombier 	buf = malloc(8192);
4107dd7cddfSDavid du Colombier 	if(buf == nil)
4117dd7cddfSDavid du Colombier 		return nil;
4127dd7cddfSDavid du Colombier 	n = read(fd, buf, 8192);
4137dd7cddfSDavid du Colombier 	m = nil;
4147dd7cddfSDavid du Colombier 	if(n > 0){
4157dd7cddfSDavid du Colombier 		m = plumbunpackpartial(buf, n, &more);
4167dd7cddfSDavid du Colombier 		if(m==nil && more>0){
4177dd7cddfSDavid du Colombier 			/* we now know how many more bytes to read for complete message */
4187dd7cddfSDavid du Colombier 			buf = realloc(buf, n+more);
4197dd7cddfSDavid du Colombier 			if(buf == nil)
4207dd7cddfSDavid du Colombier 				return nil;
4217dd7cddfSDavid du Colombier 			if(readn(fd, buf+n, more) == more)
4227dd7cddfSDavid du Colombier 				m = plumbunpackpartial(buf, n+more, nil);
4237dd7cddfSDavid du Colombier 		}
4247dd7cddfSDavid du Colombier 	}
4257dd7cddfSDavid du Colombier 	free(buf);
4267dd7cddfSDavid du Colombier 	return m;
4277dd7cddfSDavid du Colombier }
428