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 }