123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427 |
- #include <u.h>
- #include <libc.h>
- #include "plumb.h"
- static char attrbuf[4096];
- int
- plumbopen(char *name, int omode)
- {
- int fd, f;
- char *s, *plumber;
- char buf[128], err[ERRMAX];
- if(name[0] == '/')
- return open(name, omode);
-
- /* find elusive plumber */
- if(access("/mnt/plumb/send", AWRITE) >= 0)
- plumber = "/mnt/plumb";
- else if(access("/mnt/term/mnt/plumb/send", AWRITE) >= 0)
- plumber = "/mnt/term/mnt/plumb";
- else{
- /* last resort: try mounting service */
- plumber = "/mnt/plumb";
- s = getenv("plumbsrv");
- if(s == nil)
- return -1;
- f = open(s, ORDWR);
- if(f < 0)
- return -1;
- if(mount(f, -1, "/mnt/plumb", MREPL, "") < 0){
- close(f);
- return -1;
- }
- if(access("/mnt/plumb/send", AWRITE) < 0)
- return -1;
- }
- snprint(buf, sizeof buf, "%s/%s", plumber, name);
- fd = open(buf, omode);
- if(fd >= 0)
- return fd;
- /* try creating port; used by non-standard plumb implementations */
- rerrstr(err, sizeof err);
- fd = create(buf, omode, 0600);
- if(fd >= 0)
- return fd;
- errstr(err, sizeof err);
- return -1;
- }
- static int
- Strlen(char *s)
- {
- if(s == nil)
- return 0;
- return strlen(s);
- }
- static char*
- Strcpy(char *s, char *t)
- {
- if(t == nil)
- return s;
- return strcpy(s, t) + strlen(t);
- }
- /* quote attribute value, if necessary */
- static char*
- quote(char *s)
- {
- char *t;
- int c;
- if(s == nil){
- attrbuf[0] = '\0';
- return attrbuf;
- }
- if(strpbrk(s, " '=\t") == nil)
- return s;
- t = attrbuf;
- *t++ = '\'';
- while(t < attrbuf+sizeof attrbuf-2){
- c = *s++;
- if(c == '\0')
- break;
- *t++ = c;
- if(c == '\'')
- *t++ = c;
- }
- *t++ = '\'';
- *t = '\0';
- return attrbuf;
- }
- char*
- plumbpackattr(Plumbattr *attr)
- {
- int n;
- Plumbattr *a;
- char *s, *t;
- if(attr == nil)
- return nil;
- n = 0;
- for(a=attr; a!=nil; a=a->next)
- n += Strlen(a->name) + 1 + Strlen(quote(a->value)) + 1;
- s = malloc(n);
- if(s == nil)
- return nil;
- t = s;
- *t = '\0';
- for(a=attr; a!=nil; a=a->next){
- if(t != s)
- *t++ = ' ';
- strcpy(t, a->name);
- strcat(t, "=");
- strcat(t, quote(a->value));
- t += strlen(t);
- }
- if(t > s+n)
- abort();
- return s;
- }
- char*
- plumblookup(Plumbattr *attr, char *name)
- {
- while(attr){
- if(strcmp(attr->name, name) == 0)
- return attr->value;
- attr = attr->next;
- }
- return nil;
- }
- char*
- plumbpack(Plumbmsg *m, int *np)
- {
- int n, ndata;
- char *buf, *p, *attr;
- ndata = m->ndata;
- if(ndata < 0)
- ndata = Strlen(m->data);
- attr = plumbpackattr(m->attr);
- n = Strlen(m->src)+1 + Strlen(m->dst)+1 + Strlen(m->wdir)+1 +
- Strlen(m->type)+1 + Strlen(attr)+1 + 16 + ndata;
- buf = malloc(n+1); /* +1 for '\0' */
- if(buf == nil){
- free(attr);
- return nil;
- }
- p = Strcpy(buf, m->src);
- *p++ = '\n';
- p = Strcpy(p, m->dst);
- *p++ = '\n';
- p = Strcpy(p, m->wdir);
- *p++ = '\n';
- p = Strcpy(p, m->type);
- *p++ = '\n';
- p = Strcpy(p, attr);
- *p++ = '\n';
- p += sprint(p, "%d\n", ndata);
- memmove(p, m->data, ndata);
- *np = (p-buf)+ndata;
- buf[*np] = '\0'; /* null terminate just in case */
- if(*np >= n+1)
- abort();
- free(attr);
- return buf;
- }
- int
- plumbsend(int fd, Plumbmsg *m)
- {
- char *buf;
- int n;
- buf = plumbpack(m, &n);
- if(buf == nil)
- return -1;
- n = write(fd, buf, n);
- free(buf);
- return n;
- }
- static int
- plumbline(char **linep, char *buf, int i, int n, int *bad)
- {
- int starti;
- char *p;
- starti = i;
- while(i<n && buf[i]!='\n')
- i++;
- if(i == n)
- *bad = 1;
- else{
- p = malloc((i-starti) + 1);
- if(p == nil)
- *bad = 1;
- else{
- memmove(p, buf+starti, i-starti);
- p[i-starti] = '\0';
- }
- *linep = p;
- i++;
- }
- return i;
- }
- void
- plumbfree(Plumbmsg *m)
- {
- Plumbattr *a, *next;
- free(m->src);
- free(m->dst);
- free(m->wdir);
- free(m->type);
- for(a=m->attr; a!=nil; a=next){
- next = a->next;
- free(a->name);
- free(a->value);
- free(a);
- }
- free(m->data);
- free(m);
- }
- Plumbattr*
- plumbunpackattr(char *p)
- {
- Plumbattr *attr, *prev, *a;
- char *q, *v;
- int c, quoting;
- attr = prev = nil;
- while(*p!='\0' && *p!='\n'){
- while(*p==' ' || *p=='\t')
- p++;
- if(*p == '\0')
- break;
- for(q=p; *q!='\0' && *q!='\n' && *q!=' ' && *q!='\t'; q++)
- if(*q == '=')
- break;
- if(*q != '=')
- break; /* malformed attribute */
- a = malloc(sizeof(Plumbattr));
- if(a == nil)
- break;
- a->name = malloc(q-p+1);
- if(a->name == nil){
- free(a);
- break;
- }
- memmove(a->name, p, q-p);
- a->name[q-p] = '\0';
- /* process quotes in value */
- q++; /* skip '=' */
- v = attrbuf;
- quoting = 0;
- while(*q!='\0' && *q!='\n'){
- if(v >= attrbuf+sizeof attrbuf)
- break;
- c = *q++;
- if(quoting){
- if(c == '\''){
- if(*q == '\'')
- q++;
- else{
- quoting = 0;
- continue;
- }
- }
- }else{
- if(c==' ' || c=='\t')
- break;
- if(c == '\''){
- quoting = 1;
- continue;
- }
- }
- *v++ = c;
- }
- a->value = malloc(v-attrbuf+1);
- if(a->value == nil){
- free(a->name);
- free(a);
- break;
- }
- memmove(a->value, attrbuf, v-attrbuf);
- a->value[v-attrbuf] = '\0';
- a->next = nil;
- if(prev == nil)
- attr = a;
- else
- prev->next = a;
- prev = a;
- p = q;
- }
- return attr;
- }
- Plumbattr*
- plumbaddattr(Plumbattr *attr, Plumbattr *new)
- {
- Plumbattr *l;
- l = attr;
- if(l == nil)
- return new;
- while(l->next != nil)
- l = l->next;
- l->next = new;
- return attr;
- }
- Plumbattr*
- plumbdelattr(Plumbattr *attr, char *name)
- {
- Plumbattr *l, *prev;
- prev = nil;
- for(l=attr; l!=nil; l=l->next){
- if(strcmp(name, l->name) == 0)
- break;
- prev = l;
- }
- if(l == nil)
- return nil;
- if(prev)
- prev->next = l->next;
- else
- attr = l->next;
- free(l->name);
- free(l->value);
- free(l);
- return attr;
- }
- Plumbmsg*
- plumbunpackpartial(char *buf, int n, int *morep)
- {
- Plumbmsg *m;
- int i, bad;
- char *ntext, *attr;
- m = malloc(sizeof(Plumbmsg));
- if(m == nil)
- return nil;
- memset(m, 0, sizeof(Plumbmsg));
- if(morep != nil)
- *morep = 0;
- bad = 0;
- i = plumbline(&m->src, buf, 0, n, &bad);
- i = plumbline(&m->dst, buf, i, n, &bad);
- i = plumbline(&m->wdir, buf, i, n, &bad);
- i = plumbline(&m->type, buf, i, n, &bad);
- i = plumbline(&attr, buf, i, n, &bad);
- i = plumbline(&ntext, buf, i, n, &bad);
- if(bad){
- plumbfree(m);
- return nil;
- }
- m->attr = plumbunpackattr(attr);
- free(attr);
- m->ndata = atoi(ntext);
- if(m->ndata != n-i){
- bad = 1;
- if(morep!=nil && m->ndata>n-i)
- *morep = m->ndata - (n-i);
- }
- free(ntext);
- if(!bad){
- m->data = malloc(n-i+1); /* +1 for '\0' */
- if(m->data == nil)
- bad = 1;
- else{
- memmove(m->data, buf+i, m->ndata);
- m->ndata = n-i;
- /* null-terminate in case it's text */
- m->data[m->ndata] = '\0';
- }
- }
- if(bad){
- plumbfree(m);
- m = nil;
- }
- return m;
- }
- Plumbmsg*
- plumbunpack(char *buf, int n)
- {
- return plumbunpackpartial(buf, n, nil);
- }
- Plumbmsg*
- plumbrecv(int fd)
- {
- char *buf;
- Plumbmsg *m;
- int n, more;
- buf = malloc(8192);
- if(buf == nil)
- return nil;
- n = read(fd, buf, 8192);
- m = nil;
- if(n > 0){
- m = plumbunpackpartial(buf, n, &more);
- if(m==nil && more>0){
- /* we now know how many more bytes to read for complete message */
- buf = realloc(buf, n+more);
- if(buf == nil)
- return nil;
- if(readn(fd, buf+n, more) == more)
- m = plumbunpackpartial(buf, n+more, nil);
- }
- }
- free(buf);
- return m;
- }
|