Blob
1 #include <u.h>2 #include <libc.h>3 #include "plumb.h"5 static char attrbuf[4096];7 char *home;9 int10 plumbopen(char *name, int omode)11 {12 #if 013 int fd, f;14 char *s;15 #endif16 char buf[256];18 if(name[0] == '/')19 return open(name, omode);20 if(home == nil){21 home = getenv("HOME");22 if(home == nil)23 return -1;24 }25 snprint(buf, sizeof buf, "%s/mnt/plumb", home);26 #if 027 fd = open(buf, omode);28 if(fd >= 0)29 return fd;30 snprint(buf, sizeof buf, "/mnt/term/mnt/plumb/%s", name);31 fd = open(buf, omode);32 if(fd >= 0)33 return fd;34 /* try mounting service */35 s = getenv("plumbsrv");36 if(s == nil)37 return -1;38 snprint(buf, sizeof buf, "/mnt/plumb/%s", name);39 #endif40 return open(buf, omode);41 }43 static int44 Strlen(char *s)45 {46 if(s == nil)47 return 0;48 return strlen(s);49 }51 static char*52 Strcpy(char *s, char *t)53 {54 if(t == nil)55 return s;56 return strcpy(s, t) + strlen(t);57 }59 /* quote attribute value, if necessary */60 static char*61 quote(char *s)62 {63 char *t;64 int c;66 if(s == nil){67 attrbuf[0] = '\0';68 return attrbuf;69 }70 if(strpbrk(s, " '=\t") == nil)71 return s;72 t = attrbuf;73 *t++ = '\'';74 while(t < attrbuf+sizeof attrbuf-2){75 c = *s++;76 if(c == '\0')77 break;78 *t++ = c;79 if(c == '\'')80 *t++ = c;81 }82 *t++ = '\'';83 *t = '\0';84 return attrbuf;85 }87 char*88 plumbpackattr(Plumbattr *attr)89 {90 int n;91 Plumbattr *a;92 char *s, *t;94 if(attr == nil)95 return nil;96 n = 0;97 for(a=attr; a!=nil; a=a->next)98 n += Strlen(a->name) + 1 + Strlen(quote(a->value)) + 1;99 s = malloc(n);100 if(s == nil)101 return nil;102 t = s;103 *t = '\0';104 for(a=attr; a!=nil; a=a->next){105 if(t != s)106 *t++ = ' ';107 strcpy(t, a->name);108 strcat(t, "=");109 strcat(t, quote(a->value));110 t += strlen(t);111 }112 if(t > s+n)113 abort();114 return s;115 }117 char*118 plumblookup(Plumbattr *attr, char *name)119 {120 while(attr){121 if(strcmp(attr->name, name) == 0)122 return attr->value;123 attr = attr->next;124 }125 return nil;126 }128 char*129 plumbpack(Plumbmsg *m, int *np)130 {131 int n, ndata;132 char *buf, *p, *attr;134 ndata = m->ndata;135 if(ndata < 0)136 ndata = Strlen(m->data);137 attr = plumbpackattr(m->attr);138 n = Strlen(m->src)+1 + Strlen(m->dst)+1 + Strlen(m->wdir)+1 +139 Strlen(m->type)+1 + Strlen(attr)+1 + 16 + ndata;140 buf = malloc(n+1); /* +1 for '\0' */141 if(buf == nil){142 free(attr);143 return nil;144 }145 p = Strcpy(buf, m->src);146 *p++ = '\n';147 p = Strcpy(p, m->dst);148 *p++ = '\n';149 p = Strcpy(p, m->wdir);150 *p++ = '\n';151 p = Strcpy(p, m->type);152 *p++ = '\n';153 p = Strcpy(p, attr);154 *p++ = '\n';155 p += sprint(p, "%d\n", ndata);156 memmove(p, m->data, ndata);157 *np = (p-buf)+ndata;158 buf[*np] = '\0'; /* null terminate just in case */159 if(*np >= n+1)160 abort();161 free(attr);162 return buf;163 }165 int166 plumbsend(int fd, Plumbmsg *m)167 {168 char *buf;169 int n;171 buf = plumbpack(m, &n);172 if(buf == nil)173 return -1;174 n = write(fd, buf, n);175 free(buf);176 return n;177 }179 static int180 plumbline(char **linep, char *buf, int i, int n, int *bad)181 {182 int starti;183 char *p;185 if(*bad)186 return i;187 starti = i;188 while(i<n && buf[i]!='\n')189 i++;190 if(i == n)191 *bad = 1;192 else{193 p = malloc((i-starti) + 1);194 if(p == nil)195 *bad = 1;196 else{197 memmove(p, buf+starti, i-starti);198 p[i-starti] = '\0';199 }200 *linep = p;201 i++;202 }203 return i;204 }206 void207 plumbfree(Plumbmsg *m)208 {209 Plumbattr *a, *next;211 free(m->src);212 free(m->dst);213 free(m->wdir);214 free(m->type);215 for(a=m->attr; a!=nil; a=next){216 next = a->next;217 free(a->name);218 free(a->value);219 free(a);220 }221 free(m->data);222 free(m);223 }225 Plumbattr*226 plumbunpackattr(char *p)227 {228 Plumbattr *attr, *prev, *a;229 char *q, *v;230 int c, quoting;232 attr = prev = nil;233 while(*p!='\0' && *p!='\n'){234 while(*p==' ' || *p=='\t')235 p++;236 if(*p == '\0')237 break;238 for(q=p; *q!='\0' && *q!='\n' && *q!=' ' && *q!='\t'; q++)239 if(*q == '=')240 break;241 if(*q != '=')242 break; /* malformed attribute */243 a = malloc(sizeof(Plumbattr));244 if(a == nil)245 break;246 a->name = malloc(q-p+1);247 if(a->name == nil){248 free(a);249 break;250 }251 memmove(a->name, p, q-p);252 a->name[q-p] = '\0';253 /* process quotes in value */254 q++; /* skip '=' */255 v = attrbuf;256 quoting = 0;257 while(*q!='\0' && *q!='\n'){258 if(v >= attrbuf+sizeof attrbuf)259 break;260 c = *q++;261 if(quoting){262 if(c == '\''){263 if(*q == '\'')264 q++;265 else{266 quoting = 0;267 continue;268 }269 }270 }else{271 if(c==' ' || c=='\t')272 break;273 if(c == '\''){274 quoting = 1;275 continue;276 }277 }278 *v++ = c;279 }280 a->value = malloc(v-attrbuf+1);281 if(a->value == nil){282 free(a->name);283 free(a);284 break;285 }286 memmove(a->value, attrbuf, v-attrbuf);287 a->value[v-attrbuf] = '\0';288 a->next = nil;289 if(prev == nil)290 attr = a;291 else292 prev->next = a;293 prev = a;294 p = q;295 }296 return attr;297 }299 Plumbattr*300 plumbaddattr(Plumbattr *attr, Plumbattr *new)301 {302 Plumbattr *l;304 l = attr;305 if(l == nil)306 return new;307 while(l->next != nil)308 l = l->next;309 l->next = new;310 return attr;311 }313 Plumbattr*314 plumbdelattr(Plumbattr *attr, char *name)315 {316 Plumbattr *l, *prev;318 prev = nil;319 for(l=attr; l!=nil; l=l->next){320 if(strcmp(name, l->name) == 0)321 break;322 prev = l;323 }324 if(l == nil)325 return nil;326 if(prev)327 prev->next = l->next;328 else329 attr = l->next;330 free(l->name);331 free(l->value);332 free(l);333 return attr;334 }336 Plumbmsg*337 plumbunpackpartial(char *buf, int n, int *morep)338 {339 Plumbmsg *m;340 int i, bad;341 char *ntext, *attr;343 m = malloc(sizeof(Plumbmsg));344 if(m == nil)345 return nil;346 memset(m, 0, sizeof(Plumbmsg));347 if(morep != nil)348 *morep = 0;349 bad = 0;350 i = plumbline(&m->src, buf, 0, n, &bad);351 i = plumbline(&m->dst, buf, i, n, &bad);352 i = plumbline(&m->wdir, buf, i, n, &bad);353 i = plumbline(&m->type, buf, i, n, &bad);354 i = plumbline(&attr, buf, i, n, &bad);355 m->attr = plumbunpackattr(attr);356 free(attr);357 i = plumbline(&ntext, buf, i, n, &bad);358 m->ndata = atoi(ntext);359 if(m->ndata != n-i){360 bad = 1;361 if(morep!=nil && m->ndata>n-i)362 *morep = m->ndata - (n-i);363 }364 free(ntext);365 if(!bad){366 m->data = malloc(n-i+1); /* +1 for '\0' */367 if(m->data == nil)368 bad = 1;369 else{370 memmove(m->data, buf+i, m->ndata);371 m->ndata = n-i;372 /* null-terminate in case it's text */373 m->data[m->ndata] = '\0';374 }375 }376 if(bad){377 plumbfree(m);378 m = nil;379 }380 return m;381 }383 Plumbmsg*384 plumbunpack(char *buf, int n)385 {386 return plumbunpackpartial(buf, n, nil);387 }389 Plumbmsg*390 plumbrecv(int fd)391 {392 char *buf;393 Plumbmsg *m;394 int n, more;396 buf = malloc(8192);397 if(buf == nil)398 return nil;399 n = read(fd, buf, 8192);400 m = nil;401 if(n > 0){402 m = plumbunpackpartial(buf, n, &more);403 if(m==nil && more>0){404 /* we now know how many more bytes to read for complete message */405 buf = realloc(buf, n+more);406 if(buf == nil)407 return nil;408 if(readn(fd, buf+n, more) == more)409 m = plumbunpackpartial(buf, n+more, nil);410 }411 }412 free(buf);413 return m;414 }