Commit Diff


commit - 169aba14a4766b3d15695ef27681d0f1d04f8521
commit + 3d7e9092a436b707f2160fb869ab68e2a222bc4e
blob - /dev/null
blob + abc56d085b57766e154e8061cdc6fd0f73858317 (mode 644)
--- /dev/null
+++ include/plumb.h
@@ -0,0 +1,48 @@
+#pragma	lib	"libplumb.a"
+#pragma	src	"/sys/src/libplumb"
+
+/*
+ * Message format:
+ *	source application\n
+ *	destination port\n
+ *	working directory\n
+ *	type\n
+ *	attributes\n
+ *	nbytes\n
+ *	n bytes of data
+ */
+
+typedef struct Plumbattr Plumbattr;
+typedef struct Plumbmsg Plumbmsg;
+
+struct Plumbmsg
+{
+	char		*src;
+	char		*dst;
+	char		*wdir;
+	char		*type;
+	Plumbattr	*attr;
+	int		ndata;
+	char		*data;
+};
+
+struct Plumbattr
+{
+	char		*name;
+	char		*value;
+	Plumbattr	*next;
+};
+
+int			plumbsend(int, Plumbmsg*);
+Plumbmsg*	plumbrecv(int);
+char*		plumbpack(Plumbmsg*, int*);
+Plumbmsg*	plumbunpack(char*, int);
+Plumbmsg*	plumbunpackpartial(char*, int, int*);
+char*		plumbpackattr(Plumbattr*);
+Plumbattr*	plumbunpackattr(char*);
+Plumbattr*	plumbaddattr(Plumbattr*, Plumbattr*);
+Plumbattr*	plumbdelattr(Plumbattr*, char*);
+void			plumbfree(Plumbmsg*);
+char*		plumblookup(Plumbattr*, char*);
+int			plumbopen(char*, int);
+int			eplumb(int, char*);
blob - /dev/null
blob + df3c8bed7565e93ce43629a55a5cd1166a6e078f (mode 644)
--- /dev/null
+++ src/cmd/plumb/Makefile
@@ -0,0 +1,16 @@
+
+CFLAGS=-I../../../include
+LDLIBS=-L../../../lib -lplumb -lbio -lregexp9 -lfmt -l9 -lutf 
+all:	plumb plumber
+
+plumb: plumb.o
+	cc -o $@ plumb.o $(LDLIBS)
+
+plumber: match.o rules.o plumber.o
+	cc -o $@ match.o rules.o plumber.o $(LDLIBS)
+
+clean:
+	rm -f *.o
+
+install: plumb plumber
+	cp plumb plumber ../../../bin
blob - f702a5c514e73a0a8d5fac2e17d0512b07a03c57
blob + 5411bd92a4793484300a147ef031cf9fc5f8ba46
--- src/lib9/Makefile
+++ src/lib9/Makefile
@@ -7,6 +7,8 @@ OFILES=\
 	_exits.$O\
 	argv0.$O\
 	await.$O\
+	cleanname.$O\
+	dirstat.$O\
 	encodefmt.$O\
 	errstr.$O\
 	exits.$O\
@@ -16,12 +18,10 @@ OFILES=\
 	lock.$O\
 	malloctag.$O\
 	mallocz.$O\
-	netmkaddr.$O\
 	nrand.$O\
 	qlock.$O\
 	readn.$O\
 	rendez-$(SYSNAME).$O\
-	sleep.$O\
 	strecpy.$O\
 	sysfatal.$O\
 	tas-$(OBJTYPE).$O\
blob - /dev/null
blob + cfcb4822afed0e47944ab8a7c90b529003a9daed (mode 644)
--- /dev/null
+++ src/lib9/cleanname.c
@@ -0,0 +1,52 @@
+#include <u.h>
+#include <libc.h>
+
+/*
+ * In place, rewrite name to compress multiple /, eliminate ., and process ..
+ */
+#define SEP(x)	((x)=='/' || (x) == 0)
+char*
+cleanname(char *name)
+{
+	char *p, *q, *dotdot;
+	int rooted;
+
+	rooted = name[0] == '/';
+
+	/*
+	 * invariants:
+	 *	p points at beginning of path element we're considering.
+	 *	q points just past the last path element we wrote (no slash).
+	 *	dotdot points just past the point where .. cannot backtrack
+	 *		any further (no slash).
+	 */
+	p = q = dotdot = name+rooted;
+	while(*p) {
+		if(p[0] == '/')	/* null element */
+			p++;
+		else if(p[0] == '.' && SEP(p[1]))
+			p += 1;	/* don't count the separator in case it is nul */
+		else if(p[0] == '.' && p[1] == '.' && SEP(p[2])) {
+			p += 2;
+			if(q > dotdot) {	/* can backtrack */
+				while(--q > dotdot && *q != '/')
+					;
+			} else if(!rooted) {	/* /.. is / but ./../ is .. */
+				if(q != name)
+					*q++ = '/';
+				*q++ = '.';
+				*q++ = '.';
+				dotdot = q;
+			}
+		} else {	/* real path element */
+			if(q != name+rooted)
+				*q++ = '/';
+			while((*q = *p) != '/' && *q != 0)
+				p++, q++;
+		}
+	}
+	if(q == name)	/* empty string is really ``.'' */
+		*q++ = '.';
+	*q = '\0';
+	return name;
+}
blob - /dev/null
blob + fb9cd0acdc83b7d9cb2ae99e49094eb74c458f98 (mode 644)
--- /dev/null
+++ src/lib9/dirstat.c
@@ -0,0 +1,83 @@
+#include "u.h"
+#include "libc.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <pwd.h>
+#include <grp.h>
+
+static void
+statconv(Dir *dir, struct stat *s)
+{
+	struct passwd *p;
+	struct group *g;
+	ulong q;
+
+	p = getpwuid(s->st_uid);
+	if (p)
+		strncpy(dir->uid, p->pw_name, NAMELEN);
+	g = getgrgid(s->st_gid);
+	if (g)
+		strncpy(dir->gid, g->gr_name, NAMELEN);
+	q = 0;
+	if(S_ISDIR(s->st_mode))
+		q = CHDIR;
+	q |= s->st_ino & 0x00FFFFFFUL;
+	dir->qid.path = q;
+	dir->qid.vers = s->st_mtime;
+	dir->mode = (dir->qid.path&CHDIR)|(s->st_mode&0777);
+	dir->atime = s->st_atime;
+	dir->mtime = s->st_mtime;
+	dir->length = s->st_size;
+	dir->dev = s->st_dev;
+	dir->type = 'M';
+	if(S_ISFIFO(s->st_mode))
+		dir->type = '|';
+}
+
+int
+dirfstat(int fd, Dir *d)
+{
+	struct stat sbuf;
+
+	if(fstat(fd, &sbuf) < 0)
+		return -1;
+	statconv(d, &sbuf);
+	return 0;
+}
+
+static char *
+lelem(char *path)
+{	
+	char *pr;
+
+	pr = utfrrune(path, '/');
+	if(pr)
+		pr++;
+	else
+		pr = path;
+	return pr;
+}
+
+int
+dirstat(char *f, Dir *d)
+{
+	struct stat sbuf;
+
+	if(stat(f, &sbuf) < 0)
+		return -1;
+	statconv(d, &sbuf);
+	strncpy(d->name, lelem(f), NAMELEN);
+	return 0;
+}
+
+int
+dirfwstat(int fd, Dir *d)
+{
+	return -1;
+}
+
+int
+dirwstat(char *name, Dir *d)
+{
+	return -1;
+}
blob - /dev/null
blob + e9d07a6658c8d8e0c914cbecb4c779b97dfc4ce6 (mode 755)
--- /dev/null
+++ src/libplumb/Makefile
@@ -0,0 +1,19 @@
+
+LIB=../../lib/libplumb.a
+OFILES=\
+	mesg.o\
+
+HFILES=../../include/plumb.h
+
+INCLUDES=-I../../include
+
+CFLAGS += $(INCLUDES) -D_POSIX_SOURCE
+
+CC=cc
+
+$(LIB): $(OFILES)
+	ar r $(LIB) $(OFILES)
+
+clean:
+	rm -rf $(TARG) $(OFILES)
+
blob - /dev/null
blob + 36a95d687f882f4cac738da882a22788bde65f01 (mode 755)
--- /dev/null
+++ src/libplumb/event.c
@@ -0,0 +1,108 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <event.h>
+#include "plumb.h"
+
+typedef struct EQueue EQueue;
+
+struct EQueue
+{
+	int		id;
+	char		*buf;
+	int		nbuf;
+	EQueue	*next;
+};
+
+static	EQueue	*equeue;
+static	Lock		eqlock;
+
+static
+int
+partial(int id, Event *e, uchar *b, int n)
+{
+	EQueue *eq, *p;
+	int nmore;
+
+	lock(&eqlock);
+	for(eq = equeue; eq != nil; eq = eq->next)
+		if(eq->id == id)
+			break;
+	unlock(&eqlock);
+	if(eq == nil)
+		return 0;
+	/* partial message exists for this id */
+	eq->buf = realloc(eq->buf, eq->nbuf+n);
+	if(eq->buf == nil)
+		drawerror(display, "eplumb: cannot allocate buffer");
+	memmove(eq->buf+eq->nbuf, b, n);
+	eq->nbuf += n;
+	e->v = plumbunpackpartial((char*)eq->buf, eq->nbuf, &nmore);
+	if(nmore == 0){	/* no more to read in this message */
+		lock(&eqlock);
+		if(eq == equeue)
+			equeue = eq->next;
+		else{
+			for(p = equeue; p!=nil && p->next!=eq; p = p->next)
+				;
+			if(p == nil)
+				drawerror(display, "eplumb: bad event queue");
+			p->next = eq->next;
+		}
+		unlock(&eqlock);
+		free(eq->buf);
+		free(eq);
+	}
+	return 1;
+}
+
+static
+void
+addpartial(int id, char *b, int n)
+{
+	EQueue *eq;
+
+	eq = malloc(sizeof(EQueue));
+	if(eq == nil)
+		return;
+	eq->id = id;
+	eq->nbuf = n;
+	eq->buf = malloc(n);
+	if(eq->buf == nil){
+		free(eq);
+		return;
+	}
+	memmove(eq->buf, b, n);
+	lock(&eqlock);
+	eq->next = equeue;
+	equeue = eq;
+	unlock(&eqlock);
+}
+
+static
+int
+plumbevent(int id, Event *e, uchar *b, int n)
+{
+	int nmore;
+
+	if(partial(id, e, b, n) == 0){
+		/* no partial message already waiting for this id */
+		e->v = plumbunpackpartial((char*)b, n, &nmore);
+		if(nmore > 0)	/* incomplete message */
+			addpartial(id, (char*)b, n);
+	}
+	if(e->v == nil)
+		return 0;
+	return id;
+}
+
+int
+eplumb(int key, char *port)
+{
+	int fd;
+
+	fd = plumbopen(port, OREAD|OCEXEC);
+	if(fd < 0)
+		return -1;
+	return estartfn(key, fd, 8192, plumbevent);
+}
blob - /dev/null
blob + 93ab03f68ca7ba83140e658c15736166ddec28c3 (mode 755)
--- /dev/null
+++ src/libplumb/mesg.c
@@ -0,0 +1,403 @@
+#include <u.h>
+#include <libc.h>
+#include "plumb.h"
+
+static char attrbuf[4096];
+
+int
+plumbopen(char *name, int omode)
+{
+	int fd, f;
+	char *s;
+	char buf[128];
+
+	if(name[0] == '/')
+		return open(name, omode);
+	snprint(buf, sizeof buf, "/mnt/plumb/%s", name);
+	fd = open(buf, omode);
+	if(fd >= 0)
+		return fd;
+	snprint(buf, sizeof buf, "/mnt/term/mnt/plumb/%s", name);
+	fd = open(buf, omode);
+	if(fd >= 0)
+		return fd;
+	/* try mounting service */
+	s = getenv("plumbsrv");
+	if(s == nil)
+		return -1;
+	snprint(buf, sizeof buf, "/mnt/plumb/%s", name);
+	return open(buf, omode);
+}
+
+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;
+
+	if(*bad)
+		return i;
+	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);
+	m->attr = plumbunpackattr(attr);
+	free(attr);
+	i = plumbline(&ntext, buf, i, n, &bad);
+	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;
+}