plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

mesg.c (5481B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <fcall.h>
      4 #include "plumb.h"
      5 
      6 static char attrbuf[4096];
      7 
      8 char *home;
      9 
     10 static int
     11 Strlen(char *s)
     12 {
     13 	if(s == nil)
     14 		return 0;
     15 	return strlen(s);
     16 }
     17 
     18 static char*
     19 Strcpy(char *s, char *t)
     20 {
     21 	if(t == nil)
     22 		return s;
     23 	return strcpy(s, t) + strlen(t);
     24 }
     25 
     26 /* quote attribute value, if necessary */
     27 static char*
     28 quote(char *s)
     29 {
     30 	char *t;
     31 	int c;
     32 
     33 	if(s == nil){
     34 		attrbuf[0] = '\0';
     35 		return attrbuf;
     36 	}
     37 	if(strpbrk(s, " '=\t") == nil)
     38 		return s;
     39 	t = attrbuf;
     40 	*t++ = '\'';
     41 	while(t < attrbuf+sizeof attrbuf-2){
     42 		c = *s++;
     43 		if(c == '\0')
     44 			break;
     45 		*t++ = c;
     46 		if(c == '\'')
     47 			*t++ = c;
     48 	}
     49 	*t++ = '\'';
     50 	*t = '\0';
     51 	return attrbuf;
     52 }
     53 
     54 char*
     55 plumbpackattr(Plumbattr *attr)
     56 {
     57 	int n;
     58 	Plumbattr *a;
     59 	char *s, *t;
     60 
     61 	if(attr == nil)
     62 		return nil;
     63 	n = 0;
     64 	for(a=attr; a!=nil; a=a->next)
     65 		n += Strlen(a->name) + 1 + Strlen(quote(a->value)) + 1;
     66 	s = malloc(n);
     67 	if(s == nil)
     68 		return nil;
     69 	t = s;
     70 	*t = '\0';
     71 	for(a=attr; a!=nil; a=a->next){
     72 		if(t != s)
     73 			*t++ = ' ';
     74 		strcpy(t, a->name);
     75 		strcat(t, "=");
     76 		strcat(t, quote(a->value));
     77 		t += strlen(t);
     78 	}
     79 	if(t > s+n)
     80 		abort();
     81 	return s;
     82 }
     83 
     84 char*
     85 plumblookup(Plumbattr *attr, char *name)
     86 {
     87 	while(attr){
     88 		if(strcmp(attr->name, name) == 0)
     89 			return attr->value;
     90 		attr = attr->next;
     91 	}
     92 	return nil;
     93 }
     94 
     95 char*
     96 plumbpack(Plumbmsg *m, int *np)
     97 {
     98 	int n, ndata;
     99 	char *buf, *p, *attr;
    100 
    101 	ndata = m->ndata;
    102 	if(ndata < 0)
    103 		ndata = Strlen(m->data);
    104 	attr = plumbpackattr(m->attr);
    105 	n = Strlen(m->src)+1 + Strlen(m->dst)+1 + Strlen(m->wdir)+1 +
    106 		Strlen(m->type)+1 + Strlen(attr)+1 + 16 + ndata;
    107 	buf = malloc(n+1);	/* +1 for '\0' */
    108 	if(buf == nil){
    109 		free(attr);
    110 		return nil;
    111 	}
    112 	p = Strcpy(buf, m->src);
    113 	*p++ = '\n';
    114 	p = Strcpy(p, m->dst);
    115 	*p++ = '\n';
    116 	p = Strcpy(p, m->wdir);
    117 	*p++ = '\n';
    118 	p = Strcpy(p, m->type);
    119 	*p++ = '\n';
    120 	p = Strcpy(p, attr);
    121 	*p++ = '\n';
    122 	p += sprint(p, "%d\n", ndata);
    123 	memmove(p, m->data, ndata);
    124 	*np = (p-buf)+ndata;
    125 	buf[*np] = '\0';	/* null terminate just in case */
    126 	if(*np >= n+1)
    127 		abort();
    128 	free(attr);
    129 	return buf;
    130 }
    131 
    132 static int
    133 plumbline(char **linep, char *buf, int i, int n, int *bad)
    134 {
    135 	int starti;
    136 	char *p;
    137 
    138 	if(*bad)
    139 		return i;
    140 	starti = i;
    141 	while(i<n && buf[i]!='\n')
    142 		i++;
    143 	if(i == n)
    144 		*bad = 1;
    145 	else{
    146 		p = malloc((i-starti) + 1);
    147 		if(p == nil)
    148 			*bad = 1;
    149 		else{
    150 			memmove(p, buf+starti, i-starti);
    151 			p[i-starti] = '\0';
    152 		}
    153 		*linep = p;
    154 		i++;
    155 	}
    156 	return i;
    157 }
    158 
    159 void
    160 plumbfree(Plumbmsg *m)
    161 {
    162 	Plumbattr *a, *next;
    163 
    164 	free(m->src);
    165 	free(m->dst);
    166 	free(m->wdir);
    167 	free(m->type);
    168 	for(a=m->attr; a!=nil; a=next){
    169 		next = a->next;
    170 		free(a->name);
    171 		free(a->value);
    172 		free(a);
    173 	}
    174 	free(m->data);
    175 	free(m);
    176 }
    177 
    178 Plumbattr*
    179 plumbunpackattr(char *p)
    180 {
    181 	Plumbattr *attr, *prev, *a;
    182 	char *q, *v;
    183 	int c, quoting;
    184 
    185 	attr = prev = nil;
    186 	while(*p!='\0' && *p!='\n'){
    187 		while(*p==' ' || *p=='\t')
    188 			p++;
    189 		if(*p == '\0')
    190 			break;
    191 		for(q=p; *q!='\0' && *q!='\n' && *q!=' ' && *q!='\t'; q++)
    192 			if(*q == '=')
    193 				break;
    194 		if(*q != '=')
    195 			break;	/* malformed attribute */
    196 		a = malloc(sizeof(Plumbattr));
    197 		if(a == nil)
    198 			break;
    199 		a->name = malloc(q-p+1);
    200 		if(a->name == nil){
    201 			free(a);
    202 			break;
    203 		}
    204 		memmove(a->name, p, q-p);
    205 		a->name[q-p] = '\0';
    206 		/* process quotes in value */
    207 		q++;	/* skip '=' */
    208 		v = attrbuf;
    209 		quoting = 0;
    210 		while(*q!='\0' && *q!='\n'){
    211 			if(v >= attrbuf+sizeof attrbuf)
    212 				break;
    213 			c = *q++;
    214 			if(quoting){
    215 				if(c == '\''){
    216 					if(*q == '\'')
    217 						q++;
    218 					else{
    219 						quoting = 0;
    220 						continue;
    221 					}
    222 				}
    223 			}else{
    224 				if(c==' ' || c=='\t')
    225 					break;
    226 				if(c == '\''){
    227 					quoting = 1;
    228 					continue;
    229 				}
    230 			}
    231 			*v++ = c;
    232 		}
    233 		a->value = malloc(v-attrbuf+1);
    234 		if(a->value == nil){
    235 			free(a->name);
    236 			free(a);
    237 			break;
    238 		}
    239 		memmove(a->value, attrbuf, v-attrbuf);
    240 		a->value[v-attrbuf] = '\0';
    241 		a->next = nil;
    242 		if(prev == nil)
    243 			attr = a;
    244 		else
    245 			prev->next = a;
    246 		prev = a;
    247 		p = q;
    248 	}
    249 	return attr;
    250 }
    251 
    252 Plumbattr*
    253 plumbaddattr(Plumbattr *attr, Plumbattr *new)
    254 {
    255 	Plumbattr *l;
    256 
    257 	l = attr;
    258 	if(l == nil)
    259 		return new;
    260 	while(l->next != nil)
    261 		l = l->next;
    262 	l->next = new;
    263 	return attr;
    264 }
    265 
    266 Plumbattr*
    267 plumbdelattr(Plumbattr *attr, char *name)
    268 {
    269 	Plumbattr *l, *prev;
    270 
    271 	prev = nil;
    272 	for(l=attr; l!=nil; l=l->next){
    273 		if(strcmp(name, l->name) == 0)
    274 			break;
    275 		prev = l;
    276 	}
    277 	if(l == nil)
    278 		return nil;
    279 	if(prev)
    280 		prev->next = l->next;
    281 	else
    282 		attr = l->next;
    283 	free(l->name);
    284 	free(l->value);
    285 	free(l);
    286 	return attr;
    287 }
    288 
    289 Plumbmsg*
    290 plumbunpackpartial(char *buf, int n, int *morep)
    291 {
    292 	Plumbmsg *m;
    293 	int i, bad;
    294 	char *ntext, *attr;
    295 
    296 	m = malloc(sizeof(Plumbmsg));
    297 	if(m == nil)
    298 		return nil;
    299 	memset(m, 0, sizeof(Plumbmsg));
    300 	if(morep != nil)
    301 		*morep = 0;
    302 	bad = 0;
    303 	i = plumbline(&m->src, buf, 0, n, &bad);
    304 	i = plumbline(&m->dst, buf, i, n, &bad);
    305 	i = plumbline(&m->wdir, buf, i, n, &bad);
    306 	i = plumbline(&m->type, buf, i, n, &bad);
    307 	i = plumbline(&attr, buf, i, n, &bad);
    308 	m->attr = plumbunpackattr(attr);
    309 	free(attr);
    310 	i = plumbline(&ntext, buf, i, n, &bad);
    311 	m->ndata = atoi(ntext);
    312 	if(m->ndata != n-i){
    313 		bad = 1;
    314 		if(morep!=nil && m->ndata>n-i)
    315 			*morep = m->ndata - (n-i);
    316 	}
    317 	free(ntext);
    318 	if(!bad){
    319 		m->data = malloc(n-i+1);	/* +1 for '\0' */
    320 		if(m->data == nil)
    321 			bad = 1;
    322 		else{
    323 			memmove(m->data, buf+i, m->ndata);
    324 			m->ndata = n-i;
    325 			/* null-terminate in case it's text */
    326 			m->data[m->ndata] = '\0';
    327 		}
    328 	}
    329 	if(bad){
    330 		plumbfree(m);
    331 		m = nil;
    332 	}
    333 	return m;
    334 }
    335 
    336 Plumbmsg*
    337 plumbunpack(char *buf, int n)
    338 {
    339 	return plumbunpackpartial(buf, n, nil);
    340 }