Add support for user-level 9P servers/clients and various bug fixes to go with them.
This commit is contained in:
parent
ac244f8d28
commit
32f69c36e0
60 changed files with 965 additions and 485 deletions
88
src/cmd/9p.c
88
src/cmd/9p.c
|
|
@ -11,7 +11,9 @@ usage(void)
|
|||
fprint(2, "usage: 9p [-a address] cmd args...\n");
|
||||
fprint(2, "possible cmds:\n");
|
||||
fprint(2, " read name\n");
|
||||
fprint(2, " readfd name\n");
|
||||
fprint(2, " write name\n");
|
||||
fprint(2, " writefd name\n");
|
||||
fprint(2, " stat name\n");
|
||||
// fprint(2, " ls name\n");
|
||||
fprint(2, "without -a, name elem/path means /path on server unix!$ns/elem\n");
|
||||
|
|
@ -20,6 +22,8 @@ usage(void)
|
|||
|
||||
void xread(int, char**);
|
||||
void xwrite(int, char**);
|
||||
void xreadfd(int, char**);
|
||||
void xwritefd(int, char**);
|
||||
void xstat(int, char**);
|
||||
void xls(int, char**);
|
||||
|
||||
|
|
@ -29,6 +33,8 @@ struct {
|
|||
} cmds[] = {
|
||||
"read", xread,
|
||||
"write", xwrite,
|
||||
"readfd", xreadfd,
|
||||
"writefd", xwritefd,
|
||||
"stat", xstat,
|
||||
// "ls", xls,
|
||||
};
|
||||
|
|
@ -64,7 +70,6 @@ Fsys*
|
|||
xparse(char *name, char **path)
|
||||
{
|
||||
int fd;
|
||||
char *ns;
|
||||
char *p;
|
||||
Fsys *fs;
|
||||
|
||||
|
|
@ -75,22 +80,17 @@ xparse(char *name, char **path)
|
|||
else
|
||||
*p++ = 0;
|
||||
*path = p;
|
||||
if(*name == 0)
|
||||
usage();
|
||||
ns = getenv("ns");
|
||||
if(ns == nil)
|
||||
sysfatal("ns not set");
|
||||
addr = smprint("unix!%s/%s", ns, name);
|
||||
if(addr == nil)
|
||||
sysfatal("out of memory");
|
||||
}else
|
||||
fs = nsmount(name, "");
|
||||
if(fs == nil)
|
||||
sysfatal("mount: %r");
|
||||
}else{
|
||||
*path = name;
|
||||
|
||||
fprint(2, "dial %s...", addr);
|
||||
if((fd = dial(addr, nil, nil, nil)) < 0)
|
||||
sysfatal("dial: %r");
|
||||
if((fs = fsmount(fd)) == nil)
|
||||
sysfatal("fsmount: %r");
|
||||
fprint(2, "dial %s...", addr);
|
||||
if((fd = dial(addr, nil, nil, nil)) < 0)
|
||||
sysfatal("dial: %r");
|
||||
if((fs = fsmount(fd, "")) == nil)
|
||||
sysfatal("fsmount: %r");
|
||||
}
|
||||
return fs;
|
||||
}
|
||||
|
||||
|
|
@ -120,6 +120,15 @@ xopen(char *name, int mode)
|
|||
return fid;
|
||||
}
|
||||
|
||||
int
|
||||
xopenfd(char *name, int mode)
|
||||
{
|
||||
Fsys *fs;
|
||||
|
||||
fs = xparse(name, &name);
|
||||
return fsopenfd(fs, name, mode);
|
||||
}
|
||||
|
||||
void
|
||||
xread(int argc, char **argv)
|
||||
{
|
||||
|
|
@ -143,6 +152,29 @@ xread(int argc, char **argv)
|
|||
exits(0);
|
||||
}
|
||||
|
||||
void
|
||||
xreadfd(int argc, char **argv)
|
||||
{
|
||||
char buf[1024];
|
||||
int n;
|
||||
int fd;
|
||||
|
||||
ARGBEGIN{
|
||||
default:
|
||||
usage();
|
||||
}ARGEND
|
||||
|
||||
if(argc != 1)
|
||||
usage();
|
||||
|
||||
fd = xopenfd(argv[0], OREAD);
|
||||
while((n = read(fd, buf, sizeof buf)) > 0)
|
||||
write(1, buf, n);
|
||||
if(n < 0)
|
||||
sysfatal("read error: %r");
|
||||
exits(0);
|
||||
}
|
||||
|
||||
void
|
||||
xwrite(int argc, char **argv)
|
||||
{
|
||||
|
|
@ -167,6 +199,30 @@ xwrite(int argc, char **argv)
|
|||
exits(0);
|
||||
}
|
||||
|
||||
void
|
||||
xwritefd(int argc, char **argv)
|
||||
{
|
||||
char buf[1024];
|
||||
int n;
|
||||
int fd;
|
||||
|
||||
ARGBEGIN{
|
||||
default:
|
||||
usage();
|
||||
}ARGEND
|
||||
|
||||
if(argc != 1)
|
||||
usage();
|
||||
|
||||
fd = xopenfd(argv[0], OWRITE|OTRUNC);
|
||||
while((n = read(0, buf, sizeof buf)) > 0)
|
||||
if(write(fd, buf, n) != n)
|
||||
sysfatal("write error: %r");
|
||||
if(n < 0)
|
||||
sysfatal("read error: %r");
|
||||
exits(0);
|
||||
}
|
||||
|
||||
void
|
||||
xstat(int argc, char **argv)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
#include <libc.h>
|
||||
#include <fcall.h>
|
||||
#include <thread.h>
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
@ -38,6 +40,7 @@ struct Msg
|
|||
int ref;
|
||||
int ctag;
|
||||
int tag;
|
||||
int isopenfd;
|
||||
Fcall tx;
|
||||
Fcall rx;
|
||||
Fid *fid;
|
||||
|
|
@ -52,6 +55,8 @@ struct Msg
|
|||
struct Conn
|
||||
{
|
||||
int fd;
|
||||
int fdmode;
|
||||
Fid *fdfid;
|
||||
int nmsg;
|
||||
int nfid;
|
||||
Channel *inc;
|
||||
|
|
@ -89,7 +94,7 @@ void *erealloc(void*, int);
|
|||
Queue *qalloc(void);
|
||||
int sendq(Queue*, void*);
|
||||
void *recvq(Queue*);
|
||||
void selectthread(void*);
|
||||
void pollthread(void*);
|
||||
void connthread(void*);
|
||||
void connoutthread(void*);
|
||||
void listenthread(void*);
|
||||
|
|
@ -100,6 +105,10 @@ int tlisten(char*, char*);
|
|||
int taccept(int, char*);
|
||||
int iolisten(Ioproc*, char*, char*);
|
||||
int ioaccept(Ioproc*, int, char*);
|
||||
int iorecvfd(Ioproc*, int);
|
||||
int iosendfd(Ioproc*, int, int);
|
||||
void mainproc(void*);
|
||||
int ignorepipe(void*, char*);
|
||||
|
||||
void
|
||||
usage(void)
|
||||
|
|
@ -110,14 +119,13 @@ usage(void)
|
|||
}
|
||||
|
||||
uchar vbuf[128];
|
||||
|
||||
extern int _threaddebuglevel;
|
||||
void
|
||||
threadmain(int argc, char **argv)
|
||||
{
|
||||
char *file;
|
||||
int n;
|
||||
Fcall f;
|
||||
|
||||
if(verbose) fprint(2, "9pserve running\n");
|
||||
ARGBEGIN{
|
||||
default:
|
||||
usage();
|
||||
|
|
@ -142,6 +150,20 @@ threadmain(int argc, char **argv)
|
|||
if((afd = announce(addr, adir)) < 0)
|
||||
sysfatal("announce %s: %r", addr);
|
||||
|
||||
proccreate(mainproc, nil, STACK);
|
||||
threadexits(0);
|
||||
}
|
||||
|
||||
void
|
||||
mainproc(void *v)
|
||||
{
|
||||
int n;
|
||||
Fcall f;
|
||||
USED(v);
|
||||
|
||||
yield(); /* let threadmain exit */
|
||||
|
||||
atnotify(ignorepipe, 1);
|
||||
fmtinstall('D', dirfmt);
|
||||
fmtinstall('M', dirmodefmt);
|
||||
fmtinstall('F', fcallfmt);
|
||||
|
|
@ -150,10 +172,6 @@ threadmain(int argc, char **argv)
|
|||
outq = qalloc();
|
||||
inq = qalloc();
|
||||
|
||||
// threadcreateidle(selectthread, nil, STACK);
|
||||
threadcreate(inputthread, nil, STACK);
|
||||
threadcreate(outputthread, nil, STACK);
|
||||
|
||||
f.type = Tversion;
|
||||
f.version = "9P2000";
|
||||
f.msize = 8192;
|
||||
|
|
@ -165,7 +183,22 @@ threadmain(int argc, char **argv)
|
|||
if(convM2S(vbuf, n, &f) != n)
|
||||
sysfatal("convM2S failure");
|
||||
if(verbose > 1) fprint(2, "* -> %F\n", &f);
|
||||
|
||||
threadcreate(inputthread, nil, STACK);
|
||||
threadcreate(outputthread, nil, STACK);
|
||||
threadcreate(listenthread, nil, STACK);
|
||||
threadcreateidle(pollthread, nil, STACK);
|
||||
threadexits(0);
|
||||
}
|
||||
|
||||
int
|
||||
ignorepipe(void *v, char *s)
|
||||
{
|
||||
USED(v);
|
||||
if(strcmp(s, "sys: write on closed pipe") == 0)
|
||||
return 1;
|
||||
fprint(2, "msg: %s\n", s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -178,10 +211,6 @@ listenthread(void *arg)
|
|||
USED(arg);
|
||||
for(;;){
|
||||
c = emalloc(sizeof(Conn));
|
||||
c->inc = chancreate(sizeof(void*), 0);
|
||||
c->internal = chancreate(sizeof(void*), 0);
|
||||
c->inq = qalloc();
|
||||
c->outq = qalloc();
|
||||
c->fd = iolisten(io, adir, c->dir);
|
||||
if(c->fd < 0){
|
||||
if(verbose) fprint(2, "listen: %r\n");
|
||||
|
|
@ -189,13 +218,17 @@ listenthread(void *arg)
|
|||
free(c);
|
||||
return;
|
||||
}
|
||||
c->inc = chancreate(sizeof(void*), 0);
|
||||
c->internal = chancreate(sizeof(void*), 0);
|
||||
c->inq = qalloc();
|
||||
c->outq = qalloc();
|
||||
if(verbose) fprint(2, "incoming call on %s\n", c->dir);
|
||||
threadcreate(connthread, c, STACK);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
sendmsg(Msg *m)
|
||||
send9pmsg(Msg *m)
|
||||
{
|
||||
int n, nn;
|
||||
|
||||
|
|
@ -226,7 +259,7 @@ err(Msg *m, char *ename)
|
|||
m->rx.type = Rerror;
|
||||
m->rx.ename = ename;
|
||||
m->rx.tag = m->tx.tag;
|
||||
sendmsg(m);
|
||||
send9pmsg(m);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -250,7 +283,7 @@ connthread(void *arg)
|
|||
c->fd = fd;
|
||||
threadcreate(connoutthread, c, STACK);
|
||||
while((m = mread9p(io, c->fd)) != nil){
|
||||
if(verbose > 1) fprint(2, "%s -> %F\n", c->dir, &m->tx);
|
||||
if(verbose > 1) fprint(2, "fd#%d -> %F\n", c->fd, &m->tx);
|
||||
m->c = c;
|
||||
m->ctag = m->tx.tag;
|
||||
c->nmsg++;
|
||||
|
|
@ -267,13 +300,13 @@ connthread(void *arg)
|
|||
m->rx.msize = 8192;
|
||||
m->rx.version = "9P2000";
|
||||
m->rx.type = Rversion;
|
||||
sendmsg(m);
|
||||
send9pmsg(m);
|
||||
continue;
|
||||
case Tflush:
|
||||
if((m->oldm = gethash(c->tag, m->tx.oldtag)) == nil){
|
||||
m->rx.tag = m->tx.tag;
|
||||
m->rx.type = Rflush;
|
||||
sendmsg(m);
|
||||
send9pmsg(m);
|
||||
continue;
|
||||
}
|
||||
m->oldm->ref++;
|
||||
|
|
@ -318,6 +351,15 @@ connthread(void *arg)
|
|||
}
|
||||
m->afid->ref++;
|
||||
break;
|
||||
case Topenfd:
|
||||
if(m->tx.mode != OREAD && (m->tx.mode&~OTRUNC) != OWRITE){
|
||||
err(m, "openfd mode must be OREAD or OWRITE");
|
||||
continue;
|
||||
}
|
||||
m->isopenfd = 1;
|
||||
m->tx.type = Topen;
|
||||
m->tpkt[4] = Topen;
|
||||
/* fall through */
|
||||
case Tcreate:
|
||||
case Topen:
|
||||
case Tclunk:
|
||||
|
|
@ -363,6 +405,7 @@ connthread(void *arg)
|
|||
m = msgnew();
|
||||
m->internal = 1;
|
||||
m->c = c;
|
||||
c->nmsg++;
|
||||
m->tx.type = Tflush;
|
||||
m->tx.tag = m->tag;
|
||||
m->tx.oldtag = om->tag;
|
||||
|
|
@ -371,7 +414,9 @@ connthread(void *arg)
|
|||
m->ref++; /* for outq */
|
||||
sendomsg(m);
|
||||
recvp(c->internal);
|
||||
msgput(m);
|
||||
msgput(m); /* got from recvp */
|
||||
msgput(m); /* got from msgnew */
|
||||
msgput(om); /* got from hash table */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -382,6 +427,7 @@ connthread(void *arg)
|
|||
m = msgnew();
|
||||
m->internal = 1;
|
||||
m->c = c;
|
||||
c->nmsg++;
|
||||
m->tx.type = Tclunk;
|
||||
m->tx.tag = m->tag;
|
||||
m->tx.fid = f->fid;
|
||||
|
|
@ -390,7 +436,9 @@ connthread(void *arg)
|
|||
m->ref++;
|
||||
sendomsg(m);
|
||||
recvp(c->internal);
|
||||
msgput(m);
|
||||
msgput(m); /* got from recvp */
|
||||
msgput(m); /* got from msgnew */
|
||||
fidput(f); /* got from hash table */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -398,9 +446,157 @@ out:
|
|||
assert(c->nmsg == 0);
|
||||
assert(c->nfid == 0);
|
||||
close(c->fd);
|
||||
chanfree(c->internal);
|
||||
c->internal = 0;
|
||||
chanfree(c->inc);
|
||||
c->inc = 0;
|
||||
free(c->inq);
|
||||
c->inq = 0;
|
||||
free(c->outq);
|
||||
c->outq = 0;
|
||||
free(c);
|
||||
}
|
||||
|
||||
static void
|
||||
openfdthread(void *v)
|
||||
{
|
||||
Conn *c;
|
||||
Fid *fid;
|
||||
Msg *m;
|
||||
int n;
|
||||
vlong tot;
|
||||
Ioproc *io;
|
||||
char buf[1024];
|
||||
|
||||
c = v;
|
||||
fid = c->fdfid;
|
||||
io = ioproc();
|
||||
|
||||
tot = 0;
|
||||
if(c->fdmode == OREAD){
|
||||
for(;;){
|
||||
if(verbose) fprint(2, "tread...");
|
||||
m = msgnew();
|
||||
m->internal = 1;
|
||||
m->c = c;
|
||||
m->tx.type = Tread;
|
||||
m->tx.count = 8192;
|
||||
m->tx.fid = fid->fid;
|
||||
m->tx.tag = m->tag;
|
||||
m->tx.offset = tot;
|
||||
m->fid = fid;
|
||||
fid->ref++;
|
||||
m->ref++;
|
||||
sendomsg(m);
|
||||
recvp(c->internal);
|
||||
if(m->rx.type == Rerror)
|
||||
break;
|
||||
if(m->rx.count == 0)
|
||||
break;
|
||||
tot += m->rx.count;
|
||||
if(iowrite(io, c->fd, m->rx.data, m->rx.count) != m->rx.count)
|
||||
break;
|
||||
msgput(m);
|
||||
msgput(m);
|
||||
}
|
||||
}else{
|
||||
for(;;){
|
||||
if(verbose) fprint(2, "twrite...");
|
||||
if((n=ioread(io, c->fd, buf, sizeof buf)) <= 0){
|
||||
m = nil;
|
||||
break;
|
||||
}
|
||||
m = msgnew();
|
||||
m->internal = 1;
|
||||
m->c = c;
|
||||
m->tx.type = Twrite;
|
||||
m->tx.fid = fid->fid;
|
||||
m->tx.data = buf;
|
||||
m->tx.count = n;
|
||||
m->tx.tag = m->tag;
|
||||
m->tx.offset = tot;
|
||||
m->fid = fid;
|
||||
fid->ref++;
|
||||
m->ref++;
|
||||
sendomsg(m);
|
||||
recvp(c->internal);
|
||||
if(m->rx.type == Rerror)
|
||||
break;
|
||||
tot = n;
|
||||
msgput(m);
|
||||
msgput(m);
|
||||
}
|
||||
}
|
||||
if(verbose) fprint(2, "eof on %d fid %d\n", c->fd, fid->fid);
|
||||
close(c->fd);
|
||||
closeioproc(io);
|
||||
if(m){
|
||||
msgput(m);
|
||||
msgput(m);
|
||||
}
|
||||
m = msgnew();
|
||||
m->internal = 1;
|
||||
m->c = c;
|
||||
m->tx.type = Tclunk;
|
||||
m->tx.fid = fid->fid;
|
||||
m->fid = fid;
|
||||
fid->ref++;
|
||||
m->ref++;
|
||||
sendomsg(m);
|
||||
recvp(c->internal);
|
||||
msgput(m);
|
||||
msgput(m);
|
||||
fidput(fid);
|
||||
c->fdfid = nil;
|
||||
chanfree(c->internal);
|
||||
c->internal = 0;
|
||||
free(c);
|
||||
}
|
||||
|
||||
int
|
||||
xopenfd(Msg *m)
|
||||
{
|
||||
char errs[ERRMAX];
|
||||
int n, p[2];
|
||||
Conn *nc;
|
||||
|
||||
if(pipe(p) < 0){
|
||||
rerrstr(errs, sizeof errs);
|
||||
err(m, errs);
|
||||
}
|
||||
if(verbose) fprint(2, "xopen pipe %d %d...", p[0], p[1]);
|
||||
|
||||
/* now we're committed. */
|
||||
|
||||
/* a new connection for this fid */
|
||||
nc = emalloc(sizeof(Conn));
|
||||
nc->internal = chancreate(sizeof(void*), 0);
|
||||
|
||||
/* a ref for us */
|
||||
nc->fdfid = m->fid;
|
||||
m->fid->ref++;
|
||||
nc->fdmode = m->tx.mode;
|
||||
nc->fd = p[0];
|
||||
|
||||
/* clunk fid from other connection */
|
||||
if(delhash(m->c->fid, m->fid->cfid, m->fid) == 0)
|
||||
fidput(m->fid);
|
||||
|
||||
/* a thread to tend the pipe */
|
||||
threadcreate(openfdthread, nc, STACK);
|
||||
|
||||
/* rewrite as Ropenfd */
|
||||
m->rx.type = Ropenfd;
|
||||
n = GBIT32(m->rpkt);
|
||||
m->rpkt = erealloc(m->rpkt, n+4);
|
||||
PBIT32(m->rpkt+n, p[1]);
|
||||
n += 4;
|
||||
PBIT32(m->rpkt, n);
|
||||
m->rpkt[4] = Ropenfd;
|
||||
m->rx.unixfd = p[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
connoutthread(void *arg)
|
||||
{
|
||||
|
|
@ -413,6 +609,9 @@ connoutthread(void *arg)
|
|||
io = ioproc();
|
||||
while((m = recvq(c->outq)) != nil){
|
||||
err = m->tx.type+1 != m->rx.type;
|
||||
if(!err && m->isopenfd)
|
||||
if(xopenfd(m) < 0)
|
||||
continue;
|
||||
switch(m->tx.type){
|
||||
case Tflush:
|
||||
om = m->oldm;
|
||||
|
|
@ -446,7 +645,7 @@ connoutthread(void *arg)
|
|||
}
|
||||
if(delhash(m->c->tag, m->ctag, m) == 0)
|
||||
msgput(m);
|
||||
if(verbose > 1) fprint(2, "%s <- %F\n", c->dir, &m->rx);
|
||||
if(verbose > 1) fprint(2, "fd#%d <- %F\n", c->fd, &m->rx);
|
||||
rewritehdr(&m->rx, m->rpkt);
|
||||
if(mwrite9p(io, c->fd, m->rpkt) < 0)
|
||||
if(verbose) fprint(2, "write error: %r\n");
|
||||
|
|
@ -473,6 +672,8 @@ outputthread(void *arg)
|
|||
msgput(m);
|
||||
}
|
||||
closeioproc(io);
|
||||
fprint(2, "output eof\n");
|
||||
threadexitsall(0);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -483,6 +684,7 @@ inputthread(void *arg)
|
|||
Msg *m;
|
||||
Ioproc *io;
|
||||
|
||||
if(verbose) fprint(2, "input thread\n");
|
||||
io = ioproc();
|
||||
USED(arg);
|
||||
while((pkt = read9ppkt(io, 0)) != nil){
|
||||
|
|
@ -514,6 +716,8 @@ inputthread(void *arg)
|
|||
sendq(m->c->outq, m);
|
||||
}
|
||||
closeioproc(io);
|
||||
fprint(2, "input eof\n");
|
||||
threadexitsall(0);
|
||||
}
|
||||
|
||||
void*
|
||||
|
|
@ -626,15 +830,20 @@ msgput(Msg *m)
|
|||
m->c->nmsg--;
|
||||
m->c = nil;
|
||||
fidput(m->fid);
|
||||
fidput(m->afid);
|
||||
fidput(m->newfid);
|
||||
free(m->tpkt);
|
||||
free(m->rpkt);
|
||||
m->fid = nil;
|
||||
fidput(m->afid);
|
||||
m->afid = nil;
|
||||
fidput(m->newfid);
|
||||
m->newfid = nil;
|
||||
free(m->tpkt);
|
||||
m->tpkt = nil;
|
||||
free(m->rpkt);
|
||||
m->rpkt = nil;
|
||||
if(m->rx.type == Ropenfd)
|
||||
close(m->rx.unixfd);
|
||||
m->rx.unixfd = -1;
|
||||
m->isopenfd = 0;
|
||||
m->internal = 0;
|
||||
m->next = freemsg;
|
||||
freemsg = m;
|
||||
}
|
||||
|
|
@ -649,6 +858,7 @@ msgget(int n)
|
|||
m = msgtab[n];
|
||||
if(m->ref == 0)
|
||||
return nil;
|
||||
if(verbose) fprint(2, "msgget %d = %p\n", n, m);
|
||||
m->ref++;
|
||||
return m;
|
||||
}
|
||||
|
|
@ -768,6 +978,12 @@ read9ppkt(Ioproc *io, int fd)
|
|||
free(pkt);
|
||||
return nil;
|
||||
}
|
||||
/* would do this if we ever got one of these, but we only generate them
|
||||
if(pkt[4] == Ropenfd){
|
||||
newfd = iorecvfd(io, fd);
|
||||
PBIT32(pkt+n-4, newfd);
|
||||
}
|
||||
*/
|
||||
return pkt;
|
||||
}
|
||||
|
||||
|
|
@ -795,7 +1011,7 @@ mread9p(Ioproc *io, int fd)
|
|||
int
|
||||
mwrite9p(Ioproc *io, int fd, uchar *pkt)
|
||||
{
|
||||
int n;
|
||||
int n, nfd;
|
||||
|
||||
n = GBIT32(pkt);
|
||||
if(verbose > 2) fprint(2, "write %d %d %.*H\n", fd, n, n, pkt);
|
||||
|
|
@ -803,6 +1019,13 @@ mwrite9p(Ioproc *io, int fd, uchar *pkt)
|
|||
fprint(2, "write error: %r\n");
|
||||
return -1;
|
||||
}
|
||||
if(pkt[4] == Ropenfd){
|
||||
nfd = GBIT32(pkt+n-4);
|
||||
if(iosendfd(io, fd, nfd) < 0){
|
||||
fprint(2, "send fd error: %r\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -871,42 +1094,212 @@ rewritehdr(Fcall *f, uchar *pkt)
|
|||
|
||||
#ifdef _LIB9_H_
|
||||
/* unix select-based polling */
|
||||
struct Ioproc
|
||||
{
|
||||
Channel *c;
|
||||
Ioproc *next;
|
||||
int index;
|
||||
};
|
||||
|
||||
static struct Ioproc **pio;
|
||||
static struct pollfd *pfd;
|
||||
static int npfd;
|
||||
static struct Ioproc *iofree;
|
||||
|
||||
Ioproc*
|
||||
ioproc(void)
|
||||
{
|
||||
return nil;
|
||||
Ioproc *io;
|
||||
|
||||
if(iofree == nil){
|
||||
pfd = erealloc(pfd, (npfd+1)*sizeof(pfd[0]));
|
||||
pfd[npfd].events = 0;
|
||||
pfd[npfd].fd = -1;
|
||||
iofree = emalloc(sizeof(Ioproc));
|
||||
iofree->index = npfd;
|
||||
iofree->c = chancreate(sizeof(ulong), 1);
|
||||
pio = erealloc(pio, (npfd+1)*sizeof(pio[0]));
|
||||
pio[npfd] = iofree;
|
||||
npfd++;
|
||||
}
|
||||
io = iofree;
|
||||
iofree = io->next;
|
||||
return io;
|
||||
}
|
||||
|
||||
void
|
||||
closeioproc(Ioproc *io)
|
||||
{
|
||||
io->next = iofree;
|
||||
iofree = io;
|
||||
}
|
||||
|
||||
void
|
||||
pollthread(void *v)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
for(;;){
|
||||
yield();
|
||||
for(i=0; i<npfd; i++)
|
||||
pfd[i].revents = 0;
|
||||
if(verbose){
|
||||
fprint(2, "poll:");
|
||||
for(i=0; i<npfd; i++)
|
||||
if(pfd[i].events)
|
||||
fprint(2, " %d%c", pfd[i].fd, pfd[i].events==POLLIN ? 'r' : pfd[i].events==POLLOUT ? 'w' : '?');
|
||||
fprint(2, "\n");
|
||||
}
|
||||
n = poll(pfd, npfd, -1);
|
||||
if(n <= 0)
|
||||
continue;
|
||||
for(i=0; i<npfd; i++)
|
||||
if(pfd[i].fd != -1 && pfd[i].revents){
|
||||
pfd[i].fd = -1;
|
||||
pfd[i].events = 0;
|
||||
pfd[i].revents = 0;
|
||||
nbsendul(pio[i]->c, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
noblock(int fd)
|
||||
{
|
||||
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK);
|
||||
}
|
||||
|
||||
static void
|
||||
xwait(Ioproc *io, int fd, int e)
|
||||
{
|
||||
if(verbose) fprint(2, "wait for %d%c\n", fd, e==POLLIN ? 'r' : 'w');
|
||||
pfd[io->index].fd = fd;
|
||||
pfd[io->index].events = e;
|
||||
recvul(io->c);
|
||||
if(verbose) fprint(2, "got %d\n", fd);
|
||||
}
|
||||
|
||||
static void
|
||||
rwait(Ioproc *io, int fd)
|
||||
{
|
||||
xwait(io, fd, POLLIN);
|
||||
}
|
||||
|
||||
static void
|
||||
wwait(Ioproc *io, int fd)
|
||||
{
|
||||
xwait(io, fd, POLLOUT);
|
||||
}
|
||||
|
||||
long
|
||||
ioread(Ioproc *io, int fd, void *v, long n)
|
||||
{
|
||||
long r;
|
||||
USED(io);
|
||||
|
||||
xxx;
|
||||
noblock(fd);
|
||||
while((r=read(fd, v, n)) < 0 && errno == EWOULDBLOCK)
|
||||
rwait(io, fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
long
|
||||
ioreadn(Ioproc *io, int fd, void *v, long n)
|
||||
{
|
||||
long tot, m;
|
||||
uchar *u;
|
||||
|
||||
u = v;
|
||||
for(tot=0; tot<n; tot+=m){
|
||||
m = ioread(io, fd, u+tot, n-tot);
|
||||
if(m <= 0){
|
||||
if(tot)
|
||||
break;
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return tot;
|
||||
}
|
||||
|
||||
int
|
||||
iorecvfd(Ioproc *io, int fd)
|
||||
{
|
||||
int r;
|
||||
|
||||
noblock(fd);
|
||||
while((r=recvfd(fd)) < 0 && errno == EWOULDBLOCK)
|
||||
rwait(io, fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
iosendfd(Ioproc *io, int s, int fd)
|
||||
{
|
||||
int r;
|
||||
|
||||
noblock(s);
|
||||
while((r=sendfd(s, fd)) < 0 && errno == EWOULDBLOCK)
|
||||
wwait(io, s);
|
||||
if(r < 0) fprint(2, "sent %d, %d\n", s, fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
static long
|
||||
_iowrite(Ioproc *io, int fd, void *v, long n)
|
||||
{
|
||||
long r;
|
||||
USED(io);
|
||||
|
||||
noblock(fd);
|
||||
while((r=write(fd, v, n)) < 0 && errno == EWOULDBLOCK)
|
||||
wwait(io, fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
long
|
||||
iowrite(Ioproc *io, int fd, void *v, long n)
|
||||
{
|
||||
USED(io);
|
||||
long tot, m;
|
||||
uchar *u;
|
||||
|
||||
xxx;
|
||||
u = v;
|
||||
for(tot=0; tot<n; tot+=m){
|
||||
m = _iowrite(io, fd, u+tot, n-tot);
|
||||
if(m <= 0){
|
||||
if(tot)
|
||||
break;
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return tot;
|
||||
}
|
||||
|
||||
int
|
||||
iolisten(Ioproc *io, char *a, char *b)
|
||||
iolisten(Ioproc *io, char *dir, char *ndir)
|
||||
{
|
||||
int fd;
|
||||
int r;
|
||||
extern int _p9netfd(char*);
|
||||
USED(io);
|
||||
|
||||
xxx;
|
||||
if((fd = _p9netfd(dir)) < 0)
|
||||
return -1;
|
||||
noblock(fd);
|
||||
while((r=listen(dir, ndir)) < 0 && errno == EWOULDBLOCK)
|
||||
rwait(io, fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
ioaccept(Ioproc *io, int fd, char *dir)
|
||||
{
|
||||
int r;
|
||||
USED(io);
|
||||
|
||||
xxx;
|
||||
noblock(fd);
|
||||
while((r=accept(fd, dir)) < 0 && errno == EWOULDBLOCK)
|
||||
rwait(io, fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -1212,7 +1212,6 @@ rcstart(int fd[2], int argc, char **argv)
|
|||
argv[1] = "-i";
|
||||
argv[2] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* fd0 is slave (tty), fd1 is master (pty)
|
||||
*/
|
||||
|
|
@ -1222,7 +1221,7 @@ rcstart(int fd[2], int argc, char **argv)
|
|||
|
||||
switch(pid = fork()) {
|
||||
case 0:
|
||||
putenv("TERM=9term");
|
||||
putenv("TERM", "9term");
|
||||
close(fd[1]);
|
||||
setsid();
|
||||
// tcsetpgrp(0, pid);
|
||||
|
|
@ -1238,6 +1237,7 @@ rcstart(int fd[2], int argc, char **argv)
|
|||
dup(sfd, 2);
|
||||
system("stty tabs -onlcr -echo");
|
||||
execvp(argv[0], argv);
|
||||
fprint(2, "exec %s failed: %r\n", argv[0]);
|
||||
_exits("oops");
|
||||
break;
|
||||
case -1:
|
||||
|
|
@ -1388,9 +1388,7 @@ scroll(int but)
|
|||
void
|
||||
plumbstart(void)
|
||||
{
|
||||
char buf[256];
|
||||
snprint(buf, sizeof buf, "%s/mnt/plumb", getenv("HOME"));
|
||||
if((plumbfd = plumbopen(buf, OWRITE)) < 0)
|
||||
if((plumbfd = plumbopen("send", OWRITE)) < 0)
|
||||
fatal("plumbopen");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,5 +9,5 @@ OFILES=\
|
|||
|
||||
<$PLAN9/src/mkone
|
||||
|
||||
LDFLAGS=-lframe -ldraw -lplumb -lthread -l9 -lfmt -lutf -L$X11/lib -lX11 -lutil
|
||||
LDFLAGS=-lframe -ldraw -lplumb -lfs -lmux -lthread -l9 -lfmt -lutf -L$X11/lib -lX11 -lutil
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ typedef void* pointer;
|
|||
#define NE 3
|
||||
#define length(p) ((p)->wt-(p)->beg)
|
||||
#define rewind(p) (p)->rd=(p)->beg
|
||||
#undef create
|
||||
#define create(p) (p)->rd = (p)->wt = (p)->beg
|
||||
#define fsfile(p) (p)->rd = (p)->wt
|
||||
#define truncate(p) (p)->wt = (p)->rd
|
||||
|
|
|
|||
|
|
@ -59,18 +59,13 @@ void
|
|||
main(int argc, char **argv)
|
||||
{
|
||||
int i, cmd, kflag;
|
||||
char *line, *p, *root;
|
||||
char *line, *p;
|
||||
|
||||
Binit(&binbuf, 0, OREAD);
|
||||
Binit(&boutbuf, 1, OWRITE);
|
||||
kflag = 0;
|
||||
line = 0;
|
||||
dict = 0;
|
||||
root = getenv("PLAN9");
|
||||
if(root == nil)
|
||||
root = "/usr/local/plan9";
|
||||
if(chdir(root) < 0)
|
||||
sysfatal("chdir %s: %r", root);
|
||||
|
||||
for(i=0; dicts[i].name; i++){
|
||||
if(access(dicts[i].path, 0)>=0 && access(dicts[i].indexpath, 0)>=0){
|
||||
|
|
@ -126,12 +121,12 @@ main(int argc, char **argv)
|
|||
}
|
||||
bdict = Bopen(dict->path, OREAD);
|
||||
if(!bdict) {
|
||||
err("can't open dictionary %s/%s", root, dict->path);
|
||||
err("can't open dictionary %s", dict->path);
|
||||
exits("nodict");
|
||||
}
|
||||
bindex = Bopen(dict->indexpath, OREAD);
|
||||
if(!bindex) {
|
||||
err("can't open index %s/%s", root, dict->indexpath);
|
||||
err("can't open index %s", dict->indexpath);
|
||||
exits("noindex");
|
||||
}
|
||||
indextop = Bseek(bindex, 0L, 2);
|
||||
|
|
|
|||
|
|
@ -5,160 +5,160 @@
|
|||
|
||||
Dict dicts[] = {
|
||||
{"oed", "Oxford English Dictionary, 2nd Ed.",
|
||||
"dict/oed2", "dict/oed2index",
|
||||
"#9/dict/oed2", "#9/dict/oed2index",
|
||||
oednextoff, oedprintentry, oedprintkey},
|
||||
{"ahd", "American Heritage Dictionary, 2nd College Ed.",
|
||||
"ahd/DICT.DB", "ahd/index",
|
||||
ahdnextoff, ahdprintentry, ahdprintkey},
|
||||
{"pgw", "Project Gutenberg Webster Dictionary",
|
||||
"dict/pgw", "dict/pgwindex",
|
||||
"#9/dict/pgw", "#9/dict/pgwindex",
|
||||
pgwnextoff, pgwprintentry, pgwprintkey},
|
||||
{"thesaurus", "Collins Thesaurus",
|
||||
"dict/thesaurus", "dict/thesindex",
|
||||
"#9/dict/thesaurus", "#9/dict/thesindex",
|
||||
thesnextoff, thesprintentry, thesprintkey},
|
||||
|
||||
{"ce", "Gendai Chinese->English",
|
||||
"dict/world/sansdata/sandic24.dat",
|
||||
"dict/world/sansdata/ceindex",
|
||||
"#9/dict/world/sansdata/sandic24.dat",
|
||||
"#9/dict/world/sansdata/ceindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
{"ceh", "Gendai Chinese->English (Hanzi index)",
|
||||
"dict/world/sansdata/sandic24.dat",
|
||||
"dict/world/sansdata/cehindex",
|
||||
"#9/dict/world/sansdata/sandic24.dat",
|
||||
"#9/dict/world/sansdata/cehindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
{"ec", "Gendai English->Chinese",
|
||||
"dict/world/sansdata/sandic24.dat",
|
||||
"dict/world/sansdata/ecindex",
|
||||
"#9/dict/world/sansdata/sandic24.dat",
|
||||
"#9/dict/world/sansdata/ecindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
|
||||
{"dae", "Gyldendal Danish->English",
|
||||
"dict/world/gylddata/sandic30.dat",
|
||||
"dict/world/gylddata/daeindex",
|
||||
"#9/dict/world/gylddata/sandic30.dat",
|
||||
"#9/dict/world/gylddata/daeindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
{"eda", "Gyldendal English->Danish",
|
||||
"dict/world/gylddata/sandic29.dat",
|
||||
"dict/world/gylddata/edaindex",
|
||||
"#9/dict/world/gylddata/sandic29.dat",
|
||||
"#9/dict/world/gylddata/edaindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
|
||||
{"due", "Wolters-Noordhoff Dutch->English",
|
||||
"dict/world/woltdata/sandic07.dat",
|
||||
"dict/world/woltdata/deindex",
|
||||
"#9/dict/world/woltdata/sandic07.dat",
|
||||
"#9/dict/world/woltdata/deindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
{"edu", "Wolters-Noordhoff English->Dutch",
|
||||
"dict/world/woltdata/sandic06.dat",
|
||||
"dict/world/woltdata/edindex",
|
||||
"#9/dict/world/woltdata/sandic06.dat",
|
||||
"#9/dict/world/woltdata/edindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
|
||||
{"fie", "WSOY Finnish->English",
|
||||
"dict/world/werndata/sandic32.dat",
|
||||
"dict/world/werndata/fieindex",
|
||||
"#9/dict/world/werndata/sandic32.dat",
|
||||
"#9/dict/world/werndata/fieindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
{"efi", "WSOY English->Finnish",
|
||||
"dict/world/werndata/sandic31.dat",
|
||||
"dict/world/werndata/efiindex",
|
||||
"#9/dict/world/werndata/sandic31.dat",
|
||||
"#9/dict/world/werndata/efiindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
|
||||
{"fe", "Collins French->English",
|
||||
"dict/fe", "dict/feindex",
|
||||
"#9/dict/fe", "#9/dict/feindex",
|
||||
pcollnextoff, pcollprintentry, pcollprintkey},
|
||||
{"ef", "Collins English->French",
|
||||
"dict/ef", "dict/efindex",
|
||||
"#9/dict/ef", "#9/dict/efindex",
|
||||
pcollnextoff, pcollprintentry, pcollprintkey},
|
||||
|
||||
{"ge", "Collins German->English",
|
||||
"dict/ge", "dict/geindex",
|
||||
"#9/dict/ge", "#9/dict/geindex",
|
||||
pcollgnextoff, pcollgprintentry, pcollgprintkey},
|
||||
{"eg", "Collins English->German",
|
||||
"dict/eg", "dict/egindex",
|
||||
"#9/dict/eg", "#9/dict/egindex",
|
||||
pcollgnextoff, pcollgprintentry, pcollgprintkey},
|
||||
|
||||
{"ie", "Collins Italian->English",
|
||||
"dict/ie", "dict/ieindex",
|
||||
"#9/dict/ie", "#9/dict/ieindex",
|
||||
pcollnextoff, pcollprintentry, pcollprintkey},
|
||||
{"ei", "Collins English->Italian",
|
||||
"dict/ei", "dict/eiindex",
|
||||
"#9/dict/ei", "#9/dict/eiindex",
|
||||
pcollnextoff, pcollprintentry, pcollprintkey},
|
||||
|
||||
{"je", "Sanshusha Japanese->English",
|
||||
"dict/world/sansdata/sandic18.dat",
|
||||
"dict/world/sansdata/jeindex",
|
||||
"#9/dict/world/sansdata/sandic18.dat",
|
||||
"#9/dict/world/sansdata/jeindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
{"jek", "Sanshusha Japanese->English (Kanji index)",
|
||||
"dict/world/sansdata/sandic18.dat",
|
||||
"dict/world/sansdata/jekindex",
|
||||
"#9/dict/world/sansdata/sandic18.dat",
|
||||
"#9/dict/world/sansdata/jekindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
{"ej", "Sanshusha English->Japanese",
|
||||
"dict/world/sansdata/sandic18.dat",
|
||||
"dict/world/sansdata/ejindex",
|
||||
"#9/dict/world/sansdata/sandic18.dat",
|
||||
"#9/dict/world/sansdata/ejindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
|
||||
{"tjeg", "Sanshusha technical Japanese->English,German",
|
||||
"dict/world/sansdata/sandic16.dat",
|
||||
"dict/world/sansdata/tjegindex",
|
||||
"#9/dict/world/sansdata/sandic16.dat",
|
||||
"#9/dict/world/sansdata/tjegindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
{"tjegk", "Sanshusha technical Japanese->English,German (Kanji index)",
|
||||
"dict/world/sansdata/sandic16.dat",
|
||||
"dict/world/sansdata/tjegkindex",
|
||||
"#9/dict/world/sansdata/sandic16.dat",
|
||||
"#9/dict/world/sansdata/tjegkindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
{"tegj", "Sanshusha technical English->German,Japanese",
|
||||
"dict/world/sansdata/sandic16.dat",
|
||||
"dict/world/sansdata/tegjindex",
|
||||
"#9/dict/world/sansdata/sandic16.dat",
|
||||
"#9/dict/world/sansdata/tegjindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
{"tgje", "Sanshusha technical German->Japanese,English",
|
||||
"dict/world/sansdata/sandic16.dat",
|
||||
"dict/world/sansdata/tgjeindex",
|
||||
"#9/dict/world/sansdata/sandic16.dat",
|
||||
"#9/dict/world/sansdata/tgjeindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
|
||||
{"ne", "Kunnskapforlaget Norwegian->English",
|
||||
"dict/world/kunndata/sandic28.dat",
|
||||
"dict/world/kunndata/neindex",
|
||||
"#9/dict/world/kunndata/sandic28.dat",
|
||||
"#9/dict/world/kunndata/neindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
{"en", "Kunnskapforlaget English->Norwegian",
|
||||
"dict/world/kunndata/sandic27.dat",
|
||||
"dict/world/kunndata/enindex",
|
||||
"#9/dict/world/kunndata/sandic27.dat",
|
||||
"#9/dict/world/kunndata/enindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
|
||||
{"re", "Leon Ungier Russian->English",
|
||||
"dict/re", "dict/reindex",
|
||||
"#9/dict/re", "#9/dict/reindex",
|
||||
simplenextoff, simpleprintentry, simpleprintkey},
|
||||
{"er", "Leon Ungier English->Russian",
|
||||
"dict/re", "dict/erindex",
|
||||
"#9/dict/re", "#9/dict/erindex",
|
||||
simplenextoff, simpleprintentry, simpleprintkey},
|
||||
|
||||
{"se", "Collins Spanish->English",
|
||||
"dict/se", "dict/seindex",
|
||||
"#9/dict/se", "#9/dict/seindex",
|
||||
pcollnextoff, pcollprintentry, pcollprintkey},
|
||||
{"es", "Collins English->Spanish",
|
||||
"dict/es", "dict/esindex",
|
||||
"#9/dict/es", "#9/dict/esindex",
|
||||
pcollnextoff, pcollprintentry, pcollprintkey},
|
||||
|
||||
{"swe", "Esselte Studium Swedish->English",
|
||||
"dict/world/essedata/sandic34.dat",
|
||||
"dict/world/essedata/sweindex",
|
||||
"#9/dict/world/essedata/sandic34.dat",
|
||||
"#9/dict/world/essedata/sweindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
{"esw", "Esselte Studium English->Swedish",
|
||||
"dict/world/essedata/sandic33.dat",
|
||||
"dict/world/essedata/eswindex",
|
||||
"#9/dict/world/essedata/sandic33.dat",
|
||||
"#9/dict/world/essedata/eswindex",
|
||||
worldnextoff, worldprintentry, worldprintkey},
|
||||
|
||||
{"movie", "Movies -- by title",
|
||||
"movie/data", "dict/movtindex",
|
||||
"movie/data", "#9/dict/movtindex",
|
||||
movienextoff, movieprintentry, movieprintkey},
|
||||
{"moviea", "Movies -- by actor",
|
||||
"movie/data", "dict/movaindex",
|
||||
"movie/data", "#9/dict/movaindex",
|
||||
movienextoff, movieprintentry, movieprintkey},
|
||||
{"movied", "Movies -- by director",
|
||||
"movie/data", "dict/movdindex",
|
||||
"movie/data", "#9/dict/movdindex",
|
||||
movienextoff, movieprintentry, movieprintkey},
|
||||
|
||||
{"slang", "English Slang",
|
||||
"dict/slang", "dict/slangindex",
|
||||
"#9/dict/slang", "#9/dict/slangindex",
|
||||
slangnextoff, slangprintentry, slangprintkey},
|
||||
|
||||
{"robert", "Robert Électronique",
|
||||
"dict/robert/_pointers", "dict/robert/_index",
|
||||
"#9/dict/robert/_pointers", "#9/dict/robert/_index",
|
||||
robertnextoff, robertindexentry, robertprintkey},
|
||||
{"robertv", "Robert Électronique - formes des verbes",
|
||||
"dict/robert/flex.rob", "dict/robert/_flexindex",
|
||||
"#9/dict/robert/flex.rob", "#9/dict/robert/_flexindex",
|
||||
robertnextflex, robertflexentry, robertprintkey},
|
||||
|
||||
{0, 0, 0, 0, 0}
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ PLAN9=../..
|
|||
<$PLAN9/src/mkhdr
|
||||
|
||||
TARG=`ls *.c | sed 's/\.c//'`
|
||||
LDFLAGS=$LDFLAGS -lthread -lsec -lfs -lmux -lregexp9 -l9 -lbio -lfmt -lutf
|
||||
LDFLAGS=$LDFLAGS -lthread -lsec -lfs -lmux -lregexp9 -lbio -l9 -lfmt -lutf
|
||||
|
||||
<$PLAN9/src/mkmany
|
||||
|
||||
BUGGERED='CVS|oplumb|plumb|plumb2|mk|vac|9term|venti|htmlfmt'
|
||||
BUGGERED='CVS|oplumb|plumb2|mk|vac|9term|venti|htmlfmt'
|
||||
DIRS=`ls -l |sed -n 's/^d.* //p' |egrep -v "$BUGGERED"`
|
||||
|
||||
<$PLAN9/src/mkdirs
|
||||
|
|
|
|||
|
|
@ -3,14 +3,13 @@
|
|||
#include <bio.h>
|
||||
#include <regexp.h>
|
||||
#include <thread.h>
|
||||
#include <auth.h>
|
||||
#include <fcall.h>
|
||||
#include <plumb.h>
|
||||
#include "plumber.h"
|
||||
|
||||
enum
|
||||
{
|
||||
Stack = 8*1024
|
||||
Stack = 32*1024
|
||||
};
|
||||
|
||||
typedef struct Dirtab Dirtab;
|
||||
|
|
@ -73,13 +72,12 @@ struct Holdq
|
|||
|
||||
struct /* needed because incref() doesn't return value */
|
||||
{
|
||||
Lock;
|
||||
int ref;
|
||||
Lock lk;
|
||||
int ref;
|
||||
} rulesref;
|
||||
|
||||
enum
|
||||
{
|
||||
DEBUG = 0,
|
||||
NDIR = 50,
|
||||
Nhash = 16,
|
||||
|
||||
|
|
@ -99,13 +97,10 @@ static Dirtab dir[NDIR] =
|
|||
static int ndir = NQID;
|
||||
|
||||
static int srvfd;
|
||||
static int srvclosefd; /* rock for end of pipe to close */
|
||||
static int clockfd;
|
||||
static int clock;
|
||||
static Fid *fids[Nhash];
|
||||
static QLock readlock;
|
||||
static QLock queue;
|
||||
static char srvfile[128];
|
||||
static int messagesize = 8192+IOHDRSZ; /* good start */
|
||||
|
||||
static void fsysproc(void*);
|
||||
|
|
@ -183,54 +178,35 @@ addport(char *port)
|
|||
static ulong
|
||||
getclock(void)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
seek(clockfd, 0, 0);
|
||||
read(clockfd, buf, sizeof buf);
|
||||
return atoi(buf);
|
||||
return time(0);
|
||||
}
|
||||
|
||||
void
|
||||
startfsys(void)
|
||||
{
|
||||
int p[2], fd;
|
||||
int p[2];
|
||||
|
||||
fmtinstall('F', fcallfmt);
|
||||
clockfd = open("/dev/time", OREAD|OCEXEC);
|
||||
clock = getclock();
|
||||
if(pipe(p) < 0)
|
||||
error("can't create pipe: %r");
|
||||
/* 0 will be server end, 1 will be client end */
|
||||
srvfd = p[0];
|
||||
srvclosefd = p[1];
|
||||
sprint(srvfile, "/srv/plumb.%s.%d", user, getpid());
|
||||
if(putenv("plumbsrv", srvfile) < 0)
|
||||
error("can't write $plumbsrv: %r");
|
||||
fd = create(srvfile, OWRITE|OCEXEC|ORCLOSE, 0600);
|
||||
if(fd < 0)
|
||||
error("can't create /srv file: %r");
|
||||
if(fprint(fd, "%d", p[1]) <= 0)
|
||||
error("can't write /srv/file: %r");
|
||||
/* leave fd open; ORCLOSE will take care of it */
|
||||
|
||||
procrfork(fsysproc, nil, Stack, RFFDG);
|
||||
|
||||
close(p[0]);
|
||||
if(mount(p[1], -1, "/mnt/plumb", MREPL, "") < 0)
|
||||
error("can't mount /mnt/plumb: %r");
|
||||
if(post9pservice(p[1], "plumb") < 0)
|
||||
sysfatal("post9pservice plumb: %r");
|
||||
close(p[1]);
|
||||
proccreate(fsysproc, nil, Stack);
|
||||
}
|
||||
|
||||
static void
|
||||
fsysproc(void*)
|
||||
fsysproc(void *v)
|
||||
{
|
||||
int n;
|
||||
Fcall *t;
|
||||
Fid *f;
|
||||
uchar *buf;
|
||||
|
||||
close(srvclosefd);
|
||||
srvclosefd = -1;
|
||||
USED(v);
|
||||
t = nil;
|
||||
for(;;){
|
||||
buf = malloc(messagesize); /* avoid memset of emalloc */
|
||||
|
|
@ -250,7 +226,7 @@ fsysproc(void*)
|
|||
t = emalloc(sizeof(Fcall));
|
||||
if(convM2S(buf, n, t) != n)
|
||||
error("convert error in convM2S");
|
||||
if(DEBUG)
|
||||
if(debug)
|
||||
fprint(2, "<= %F\n", t);
|
||||
if(fcall[t->type] == nil)
|
||||
fsysrespond(t, buf, Ebadfcall);
|
||||
|
|
@ -281,7 +257,7 @@ fsysrespond(Fcall *t, uchar *buf, char *err)
|
|||
error("convert error in convS2M");
|
||||
if(write(srvfd, buf, n) != n)
|
||||
error("write error in respond");
|
||||
if(DEBUG)
|
||||
if(debug)
|
||||
fprint(2, "=> %F\n", t);
|
||||
free(buf);
|
||||
}
|
||||
|
|
@ -555,8 +531,10 @@ dispose(Fcall *t, uchar *buf, Plumbmsg *m, Ruleset *rs, Exec *e)
|
|||
}
|
||||
|
||||
static Fcall*
|
||||
fsysversion(Fcall *t, uchar *buf, Fid*)
|
||||
fsysversion(Fcall *t, uchar *buf, Fid *fid)
|
||||
{
|
||||
USED(fid);
|
||||
|
||||
if(t->msize < 256){
|
||||
fsysrespond(t, buf, "version: message size too small");
|
||||
return t;
|
||||
|
|
@ -574,8 +552,9 @@ fsysversion(Fcall *t, uchar *buf, Fid*)
|
|||
}
|
||||
|
||||
static Fcall*
|
||||
fsysauth(Fcall *t, uchar *buf, Fid*)
|
||||
fsysauth(Fcall *t, uchar *buf, Fid *fid)
|
||||
{
|
||||
USED(fid);
|
||||
fsysrespond(t, buf, "plumber: authentication not required");
|
||||
return t;
|
||||
}
|
||||
|
|
@ -605,10 +584,11 @@ fsysattach(Fcall *t, uchar *buf, Fid *f)
|
|||
}
|
||||
|
||||
static Fcall*
|
||||
fsysflush(Fcall *t, uchar *buf, Fid*)
|
||||
fsysflush(Fcall *t, uchar *buf, Fid *fid)
|
||||
{
|
||||
int i;
|
||||
|
||||
USED(fid);
|
||||
qlock(&queue);
|
||||
for(i=NQID; i<ndir; i++)
|
||||
flushqueue(&dir[i], t->oldtag);
|
||||
|
|
@ -729,14 +709,14 @@ fsysopen(Fcall *t, uchar *buf, Fid *f)
|
|||
if(((f->dir->perm&~(DMDIR|DMAPPEND))&m) != m)
|
||||
goto Deny;
|
||||
if(f->qid.path==Qrules && (mode==OWRITE || mode==ORDWR)){
|
||||
lock(&rulesref);
|
||||
lock(&rulesref.lk);
|
||||
if(rulesref.ref++ != 0){
|
||||
rulesref.ref--;
|
||||
unlock(&rulesref);
|
||||
unlock(&rulesref.lk);
|
||||
fsysrespond(t, buf, Einuse);
|
||||
return t;
|
||||
}
|
||||
unlock(&rulesref);
|
||||
unlock(&rulesref.lk);
|
||||
}
|
||||
if(clearrules){
|
||||
writerules(nil, 0);
|
||||
|
|
@ -761,8 +741,9 @@ fsysopen(Fcall *t, uchar *buf, Fid *f)
|
|||
}
|
||||
|
||||
static Fcall*
|
||||
fsyscreate(Fcall *t, uchar *buf, Fid*)
|
||||
fsyscreate(Fcall *t, uchar *buf, Fid *fid)
|
||||
{
|
||||
USED(fid);
|
||||
fsysrespond(t, buf, Eperm);
|
||||
return t;
|
||||
}
|
||||
|
|
@ -916,15 +897,17 @@ fsysstat(Fcall *t, uchar *buf, Fid *f)
|
|||
}
|
||||
|
||||
static Fcall*
|
||||
fsyswstat(Fcall *t, uchar *buf, Fid*)
|
||||
fsyswstat(Fcall *t, uchar *buf, Fid *fid)
|
||||
{
|
||||
USED(fid);
|
||||
fsysrespond(t, buf, Eperm);
|
||||
return t;
|
||||
}
|
||||
|
||||
static Fcall*
|
||||
fsysremove(Fcall *t, uchar *buf, Fid*)
|
||||
fsysremove(Fcall *t, uchar *buf, Fid *fid)
|
||||
{
|
||||
USED(fid);
|
||||
fsysrespond(t, buf, Eperm);
|
||||
return t;
|
||||
}
|
||||
|
|
@ -945,9 +928,9 @@ fsysclunk(Fcall *t, uchar *buf, Fid *f)
|
|||
* unless last write ended with a blank line
|
||||
*/
|
||||
writerules(nil, 0);
|
||||
lock(&rulesref);
|
||||
lock(&rulesref.lk);
|
||||
rulesref.ref--;
|
||||
unlock(&rulesref);
|
||||
unlock(&rulesref.lk);
|
||||
}
|
||||
prev = nil;
|
||||
for(p=d->fopen; p; p=p->nextopen){
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <plumb.h>
|
||||
#include "plumber.h"
|
||||
|
||||
/*
|
||||
static char*
|
||||
nonnil(char *s)
|
||||
{
|
||||
|
|
@ -13,6 +14,7 @@ nonnil(char *s)
|
|||
return "";
|
||||
return s;
|
||||
}
|
||||
*/
|
||||
|
||||
int
|
||||
verbis(int obj, Plumbmsg *m, Rule *r)
|
||||
|
|
@ -44,10 +46,10 @@ setvar(Resub rs[10], char *match[10])
|
|||
free(match[i]);
|
||||
match[i] = nil;
|
||||
}
|
||||
for(i=0; i<10 && rs[i].sp!=nil; i++){
|
||||
n = rs[i].ep-rs[i].sp;
|
||||
for(i=0; i<10 && rs[i].s.sp!=nil; i++){
|
||||
n = rs[i].e.ep-rs[i].s.sp;
|
||||
match[i] = emalloc(n+1);
|
||||
memmove(match[i], rs[i].sp, n);
|
||||
memmove(match[i], rs[i].s.sp, n);
|
||||
match[i][n] = '\0';
|
||||
}
|
||||
}
|
||||
|
|
@ -66,7 +68,7 @@ clickmatch(Reprog *re, char *text, Resub rs[10], int click)
|
|||
for(i=0; i<=click; i++){
|
||||
memset(rs, 0, 10*sizeof(Resub));
|
||||
if(regexec(re, text+i, rs, 10))
|
||||
if(rs[0].sp<=clickp && clickp<=rs[0].ep)
|
||||
if(rs[0].s.sp<=clickp && clickp<=rs[0].e.ep)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -94,8 +96,8 @@ verbmatches(int obj, Plumbmsg *m, Rule *r, Exec *e)
|
|||
}
|
||||
if(!clickmatch(r->regex, m->data, rs, atoi(clickval)))
|
||||
break;
|
||||
p0 = rs[0].sp - m->data;
|
||||
p1 = rs[0].ep - m->data;
|
||||
p0 = rs[0].s.sp - m->data;
|
||||
p1 = rs[0].e.ep - m->data;
|
||||
if(e->p0 >=0 && !(p0==e->p0 && p1==e->p1))
|
||||
break;
|
||||
e->clearclick = 1;
|
||||
|
|
@ -120,7 +122,7 @@ verbmatches(int obj, Plumbmsg *m, Rule *r, Exec *e)
|
|||
/* must match full text */
|
||||
if(ntext < 0)
|
||||
ntext = strlen(alltext);
|
||||
if(!regexec(r->regex, alltext, rs, 10) || rs[0].sp!=alltext || rs[0].ep!=alltext+ntext)
|
||||
if(!regexec(r->regex, alltext, rs, 10) || rs[0].s.sp!=alltext || rs[0].e.ep!=alltext+ntext)
|
||||
break;
|
||||
setvar(rs, e->match);
|
||||
return 1;
|
||||
|
|
@ -389,7 +391,7 @@ enum
|
|||
{
|
||||
NARGS = 100,
|
||||
NARGCHAR = 8*1024,
|
||||
EXECSTACK = 4096+(NARGS+1)*sizeof(char*)+NARGCHAR
|
||||
EXECSTACK = 32*1024+(NARGS+1)*sizeof(char*)+NARGCHAR
|
||||
};
|
||||
|
||||
/* copy argv to stack and free the incoming strings, so we don't leak argument vectors */
|
||||
|
|
@ -419,19 +421,17 @@ stackargv(char **inargv, char *argv[NARGS+1], char args[NARGCHAR])
|
|||
void
|
||||
execproc(void *v)
|
||||
{
|
||||
int fd[3];
|
||||
char **av;
|
||||
char buf[1024], *args[NARGS+1], argc[NARGCHAR];
|
||||
char *args[NARGS+1], argc[NARGCHAR];
|
||||
|
||||
rfork(RFFDG);
|
||||
close(0);
|
||||
open("/dev/null", OREAD);
|
||||
fd[0] = open("/dev/null", OREAD);
|
||||
fd[1] = dup(1, -1);
|
||||
fd[2] = dup(2, -1);
|
||||
av = v;
|
||||
stackargv(av, args, argc);
|
||||
free(av);
|
||||
procexec(nil, args[0], args);
|
||||
if(args[0][0]!='/' && strncmp(args[0], "./", 2)!=0 && strncmp(args[0], "../", 3)!=0)
|
||||
snprint(buf, sizeof buf, "/bin/%s", args[0]);
|
||||
procexec(nil, buf, args);
|
||||
procexec(nil, fd, args[0], args);
|
||||
threadexits("can't exec");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
</$objtype/mkfile
|
||||
PLAN9=../../..
|
||||
<$PLAN9/src/mkhdr
|
||||
|
||||
TARG=plumber plumb
|
||||
|
||||
|
||||
BIN=/$objtype/bin
|
||||
</sys/src/cmd/mkmany
|
||||
<$PLAN9/src/mkmany
|
||||
|
||||
PLUMBER=plumber.$O fsys.$O match.$O rules.$O
|
||||
PLUMB=plumb.$O
|
||||
|
|
@ -15,6 +14,4 @@ $PLUMB: $HFILES
|
|||
$O.plumb: $PLUMB
|
||||
$O.plumber: $PLUMBER
|
||||
|
||||
syms:V:
|
||||
8c -a plumber.c >syms
|
||||
8c -aa fsys.c match.c rules.c >>syms
|
||||
LDFLAGS=$LDFLAGS -lplumb -lfs -lmux -lthread -lregexp9 -l9 -lbio -lfmt -lutf
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
#include <regexp.h>
|
||||
#include <thread.h>
|
||||
#include <plumb.h>
|
||||
#include <auth.h>
|
||||
#include <fcall.h>
|
||||
#include "plumber.h"
|
||||
|
||||
int debug;
|
||||
char *plumbfile;
|
||||
char *user;
|
||||
char *home;
|
||||
|
|
@ -47,13 +47,18 @@ threadmain(int argc, char *argv[])
|
|||
progname = "plumber";
|
||||
|
||||
ARGBEGIN{
|
||||
case 'd':
|
||||
debug = 1;
|
||||
break;
|
||||
case 'p':
|
||||
plumbfile = ARGF();
|
||||
break;
|
||||
}ARGEND
|
||||
|
||||
user = getenv("user");
|
||||
user = getuser();
|
||||
home = getenv("home");
|
||||
if(home == nil)
|
||||
home = getenv("HOME");
|
||||
if(user==nil || home==nil)
|
||||
error("can't initialize $user or $home: %r");
|
||||
if(plumbfile == nil){
|
||||
|
|
|
|||
|
|
@ -91,3 +91,4 @@ jmp_buf parsejmp;
|
|||
char *lasterror;
|
||||
char **ports;
|
||||
int nports;
|
||||
int debug;
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ char*
|
|||
getline(void)
|
||||
{
|
||||
static int n = 0;
|
||||
static char *s, *incl;
|
||||
static char *s /*, *incl*/;
|
||||
int c, i;
|
||||
|
||||
i = 0;
|
||||
|
|
@ -414,7 +414,7 @@ include(char *s)
|
|||
t = args[1];
|
||||
fd = open(t, OREAD);
|
||||
if(fd<0 && t[0]!='/' && strncmp(t, "./", 2)!=0 && strncmp(t, "../", 3)!=0){
|
||||
snprint(buf, sizeof buf, "/sys/lib/plumb/%s", t);
|
||||
snprint(buf, sizeof buf, "#9/plumb/%s", t);
|
||||
t = buf;
|
||||
fd = open(t, OREAD);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ char *syssigname[]={
|
|||
char*
|
||||
Rcmain(void)
|
||||
{
|
||||
return "#9/rcmain";
|
||||
/*
|
||||
static char buf[256];
|
||||
char *root;
|
||||
|
||||
|
|
@ -35,9 +37,10 @@ Rcmain(void)
|
|||
root = "/usr/local/plan9";
|
||||
snprint(buf, sizeof buf, "%s/rcmain", root);
|
||||
return buf;
|
||||
*/
|
||||
}
|
||||
|
||||
char Fdprefix[]="/dev/fd/";
|
||||
char Fdprefix[]="#d/";
|
||||
void execfinit(void);
|
||||
void execbind(void);
|
||||
void execmount(void);
|
||||
|
|
|
|||
|
|
@ -214,92 +214,4 @@ erealloc(void *p, ulong n)
|
|||
return p;
|
||||
}
|
||||
|
||||
#if 0
|
||||
char *
|
||||
strdup(const char *s)
|
||||
{
|
||||
return strcpy(emalloc(strlen(s)), s);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
void exits(const char *s)
|
||||
{
|
||||
if (s) fprint(2, "exit: %s\n", s);
|
||||
exit(s != 0);
|
||||
}
|
||||
|
||||
void
|
||||
_exits(const char *s)
|
||||
{
|
||||
if (s) fprint(2, "exit: %s\n", s);
|
||||
_exit(s != 0);
|
||||
}
|
||||
|
||||
int errstr(char *buf, int size)
|
||||
{
|
||||
extern int errno;
|
||||
|
||||
snprint(buf, size, "%s", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
|
||||
int
|
||||
create(char *name, int omode, ulong perm)
|
||||
{
|
||||
int mode;
|
||||
int fd;
|
||||
|
||||
if (omode & OWRITE) mode = O_WRONLY;
|
||||
else if (omode & OREAD) mode = O_RDONLY;
|
||||
else mode = O_RDWR;
|
||||
|
||||
if ((fd = open(name, mode|O_CREAT|O_TRUNC, perm)) < 0)
|
||||
return fd;
|
||||
|
||||
if (omode & OCEXEC)
|
||||
fcntl(fd, F_SETFD, fcntl(fd,F_GETFD,0) | FD_CLOEXEC);
|
||||
|
||||
/* SES - not exactly right, but hopefully good enough. */
|
||||
if (omode & ORCLOSE)
|
||||
remove(name);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* SHOULD BE ELSEWHERE */
|
||||
#if 0 /* needed on old __APPLE__ */
|
||||
#include <lib9.h>
|
||||
|
||||
Lock plk;
|
||||
|
||||
ulong
|
||||
pread(int fd, void *buf, ulong n, ulong off)
|
||||
{
|
||||
ulong rv;
|
||||
|
||||
lock(&plk);
|
||||
if (lseek(fd, off, 0) != off)
|
||||
return -1;
|
||||
rv = read(fd, buf, n);
|
||||
unlock(&plk);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
ulong
|
||||
pwrite(int fd, void *buf, ulong n, ulong off)
|
||||
{
|
||||
ulong rv;
|
||||
|
||||
lock(&plk);
|
||||
if (lseek(fd, off, 0) != off)
|
||||
return -1;
|
||||
rv = write(fd, buf, n);
|
||||
unlock(&plk);
|
||||
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@
|
|||
#define SETBIT(a,i) ((a)[(i)>>5] |= (1<<((i)&037)))
|
||||
#define NWORDS(n) (((n)+32)/32)
|
||||
|
||||
#define PARSER "lib/yaccpar"
|
||||
#define PARSERS "lib/yaccpars"
|
||||
#define PARSER "#9/lib/yaccpar"
|
||||
#define PARSERS "#9/lib/yaccpars"
|
||||
#define TEMPNAME "y.tmp.XXXXXX"
|
||||
#define ACTNAME "y.acts.XXXXXX"
|
||||
#define OFILE "tab.c"
|
||||
|
|
@ -398,19 +398,10 @@ void
|
|||
others(void)
|
||||
{
|
||||
int c, i, j;
|
||||
char *s, *root;
|
||||
|
||||
root = getenv("PLAN9");
|
||||
if(root == nil)
|
||||
root = "/usr/local/plan9";
|
||||
s = malloc(strlen(root)+1+strlen(parser)+1);
|
||||
strcpy(s, root);
|
||||
strcat(s, "/");
|
||||
strcat(s, parser);
|
||||
finput = Bopen(s, OREAD);
|
||||
finput = Bopen(parser, OREAD);
|
||||
if(finput == 0)
|
||||
error("cannot find parser %s", s);
|
||||
free(s);
|
||||
error("cannot find parser %s", parser);
|
||||
warray("yyr1", levprd, nprod);
|
||||
aryfil(temp1, nprod, 0);
|
||||
PLOOP(1, i)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue