<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"
http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv=Content-Type content="text/html; charset=utf8">
<title>/usr/web/sources/contrib/rsc/9pfilt.c - Plan 9 from Bell Labs</title>
<!-- THIS FILE IS AUTOMATICALLY GENERATED. -->
<!-- EDIT sources.tr INSTEAD. -->
</meta>
</head>
<body>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"><a href="/plan9/">Plan 9 from Bell Labs</a>’s /usr/web/sources/contrib/rsc/9pfilt.c</span></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
Copyright © 2009 Alcatel-Lucent.<br />
Distributed under the
<a href="/plan9/license.html">Lucent Public License version 1.02</a>.
<br />
<a href="/plan9/download.html">Download the Plan 9 distribution.</a>
</font>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<table width="100%" cellspacing=0 border=0><tr><td align="center">
<table cellspacing=0 cellpadding=5 bgcolor="#eeeeff"><tr><td align="left">
<pre>
<!-- END HEADER -->
#include <u.h>
#include <libc.h>
#include <auth.h>
#include <fcall.h>
#include <thread.h>
#include <ctype.h>
void
usage(void)
{
threadprint(2, "9pfilt [-abc] oldsrvfile newsrvname\n");
exits("usage");
}
void postfd(char*, int);
typedef struct Win Win;
typedef struct Req Req;
struct Win {
char *name;
QLock;
int passing;
int numgen;
int id;
int ctlfd;
int addrfd;
int bodyfd;
int datafd;
int tagfd;
int eventfd;
int msgfd; /* where messages come from */
Channel *rx; /* channel to receive messages */
Channel *tx; /* channel to send messages on */
Req *reqlist; /* actual messages */
Req **elist;
};
struct Req {
Fcall f;
char buf[MAXFDATA+MAXMSG];
long n;
int num;
int passed;
Req *link;
};
/* read messages from fromfd and send them to rx channel */
void
filterproc(void *a)
{
Win *w;
Req *r;
w = a;
for(;;){
r = mallocz(sizeof *r, 1);
assert(r != nil);
r->n = sizeof r->buf;
if(getS(w->msgfd, r->buf, &r->f, &r->n))
break;
sendp(w->rx, r);
}
threadexitsall("read failed");
}
void
newwin(Win *w, char *name, int msgfd, Channel *rx, Channel *tx)
{
int fd;
char buf[30], *p;
w->name = name;
w->msgfd = msgfd;
fd = open("/dev/new/ctl", ORDWR);
if(fd < 0)
sysfatal("open /dev/new/ctl: %r");
if(read(fd, buf, 12) != 12)
sysfatal("read id");
w->ctlfd = fd;
w->id = atoi(buf);
sprint(buf, "/dev/%d/", w->id);
p = buf+strlen(buf);
strcpy(p, "addr");
w->addrfd = open(buf, ORDWR);
if(w->addrfd < 0)
sysfatal("addr %s: %r", buf);
strcpy(p, "body");
w->bodyfd = open(buf, OWRITE);
if(w->bodyfd < 0)
sysfatal("body %s: %r", buf);
strcpy(p, "data");
w->datafd = open(buf, ORDWR);
if(w->datafd < 0)
sysfatal("body %s: %r", buf);
strcpy(p, "tag");
w->tagfd = open(buf, ORDWR);
if(w->tagfd < 0)
sysfatal("tag %s: %r", buf);
strcpy(p, "event");
w->eventfd = open(buf, OREAD);
if(w->eventfd < 0)
sysfatal("event %s: %r", buf);
w->rx = rx;
w->tx = tx;
w->elist = &w->reqlist;
}
Req*
copy(Req *r)
{
Req *n;
n = mallocz(sizeof *n, 1);
assert(n != nil);
*n = *r;
n->link = nil;
return n;
}
void
tag(Win *w, char *name)
{
threadprint(w->ctlfd, "cleartag\n");
threadprint(w->tagfd, "Look %s", name);
}
int
gettext(Win *w, char *buf, long a, long b)
{
int n;
threadprint(w->addrfd, "#%ld,#%ld", a, b);
seek(w->datafd, 0, 0);
if((n=read(w->datafd, buf, b-a)) != b-a)
threadprint(2, "warning: read %ld ret %d\n", b-a, n);
return n;
}
void
settext(Win *w, char *buf, long a, long b)
{
threadprint(w->addrfd, "#%ld,#%ld", a, b);
seek(w->datafd, 0, 0);
write(w->datafd, buf, strlen(buf));
}
void
refreshwin(Win *w)
{
// threadprint(w->addrfd, ",");
// threadprint(w->datafd, "");
}
void
acmewin(void *a)
{
Win *w;
char buf[128];
int n;
long num[4];
char *p;
Req *r;
w = a;
threadprint(w->ctlfd, "name /9p/%s\n", w->name);
tag(w, "Pass");
while((n=read(w->eventfd, buf, sizeof buf-1)) > 0){
Cont:
buf[n] = 0;
num[0] = strtol(buf+2, &p, 10);
assert(p != nil);
num[1] = strtol(p, &p, 10);
assert(p != nil);
num[2] = strtol(p, &p, 10);
assert(p != nil);
num[3] = strtol(p, &p, 10);
assert(p != nil);
p++;
p[num[3]] = 0;
if(num[2] & 2){
memmove(buf, p+num[3]+1, n = n - (p-buf) - num[3] - 1);
goto Cont;
}
switch(buf[0]){
case 'E': /* write to body or tag file */
case 'F': /* other file write */
case 'K': /* keyboard */
case 'M':; /* mouse */
}
switch(buf[1]){
case 'x':
if(strcmp(p, "Pass")==0){
w->passing = 1;
tag(w, "Nopass");
}
if(strcmp(p, "Nopass")==0){
w->passing = 0;
tag(w, "Pass");
}
if(strcmp(p, "Get")==0){
refreshwin(w);
}
break;
case 'X':
if(num[1] - num[0] > 30)
break;
if(isdigit(p[0])){
n = atoi(p);
for(r=w->reqlist; r; r=r->link)
if(r->num == n)
break;
if(r == nil)
break;
if(r->passed)
break;
r->passed = 1;
sendp(w->tx, copy(r));
num[0]--;
num[1]++;
gettext(w, buf, num[0], num[1]);
threadprint(1, "get %ld %ld %.*s\n", num[1], num[0], (int)num[1]-num[0], buf);
if(buf[0] == '[' && buf[num[1]-num[0]-1] == ']'){
buf[num[1]-num[0]-1] = 0;
settext(w, buf+1, num[0], num[1]);
}
}
break;
}
}
}
void
reqproc(void *a)
{
Win *w;
Req *r;
w = a;
while(r = recvp(w->rx)){
if(r->passed){
write(w->msgfd, r->buf, r->n);
}
else if(w->passing){
r->passed = 1;
sendp(w->tx, copy(r));
}
qlock(w);
*w->elist = r;
w->elist = &r->link;
r->num = w->numgen++;
threadprint(w->bodyfd, r->passed ? "%d/ %F\n" :
"[%d]/ %F\n", r->num, &r->f);
qunlock(w);
}
}
Win srv, ker;
void
threadmain(int argc, char **argv)
{
int flag;
int fd;
int pfd[2];
Channel *k, *s;
rfork(RFNOTEG);
flag = 0;
ARGBEGIN{
case 'a':
flag |= MAFTER;
break;
case 'b':
flag |= MBEFORE;
break;
case 'c':
flag |= MCREATE;
break;
default:
usage();
}ARGEND
if(argc != 2)
usage();
fmtinstall('F', fcallconv);
fmtinstall('D', dirconv);
if((fd = open(argv[0], ORDWR)) < 0)
sysfatal("cannot open %s: %r", argv[0]);
if(pipe(pfd)<0)
sysfatal("pipe: %r");
postfd(argv[1], pfd[1]);
k = chancreate(sizeof(Req*), 32);
s = chancreate(sizeof(Req*), 32);
newwin(&srv, "server", fd, k, s);
newwin(&ker, "kernel", pfd[0], s, k);
proccreate(filterproc, &ker, 8192);
proccreate(filterproc, &srv, 8192);
proccreate(acmewin, &ker, 8192);
proccreate(acmewin, &srv, 8192);
proccreate(reqproc, &ker, 8192);
proccreate(reqproc, &srv, 8192);
threadexits(0);
}
/*
* read a message from fd and convert it.
* ignore 0-length messages.
*/
char *
getS(int fd, char *buf, Fcall *f, long *lp)
{
long m, n;
int i;
char *errstr;
errstr = "EOF";
n = 0;
for(i = 0; i < 3; i++){
n = read(fd, buf, *lp);
if(n == 0){
continue;
}
if(n < 0)
return "read error";
m = convM2S(buf, f, n);
if(m == 0){
errstr = "bad type";
continue;
}
*lp = m;
return 0;
}
*lp = n;
return errstr;
}
void
sysfatal(char *fmt, ...)
{
char buf[128];
va_list arg;
va_start(arg, fmt);
doprint(buf, buf+sizeof(buf), fmt, arg);
va_end(arg);
if(argv0)
threadprint(2, "%s: %s\n", argv0, buf);
else
threadprint(2, "%s\n", buf);
threadexitsall(buf);
}
void
postfd(char *name, int pfd)
{
char buf[2*NAMELEN];
int fd;
snprint(buf, sizeof buf, "/srv/%s", name);
fd = create(buf, OWRITE, 0666);
if(fd == -1)
sysfatal("postsrv %s", buf);
fprint(fd, "%d", pfd);
close(fd);
}
<!-- BEGIN TAIL -->
</pre>
</td></tr></table>
</td></tr></table>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<p style="line-height: 1.2em; margin-left: 1.00in; text-indent: 0.00in; margin-right: 1.00in; margin-top: 0; margin-bottom: 0; text-align: center;">
<span style="font-size: 10pt"></span></p>
<p style="margin-top: 0; margin-bottom: 0.50in"></p>
<p style="margin-top: 0; margin-bottom: 0.33in"></p>
<center><table border="0"><tr>
<td valign="middle"><a href="
http://www.alcatel-lucent.com/"><img border="0" src="/plan9/img/logo_ft.gif" alt="Bell Labs" />
</a></td>
<td valign="middle"><a href="
http://www.opensource.org"><img border="0" alt="OSI certified" src="/plan9/img/osi-certified-60x50.gif" />
</a></td>
<td><img style="padding-right: 45px;" alt="Powered by Plan 9" src="/plan9/img/power36.gif" />
</td>
</tr></table></center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center>
<span style="font-size: 10pt">(<a href="/plan9/">Return to Plan 9 Home Page</a>)</span>
</center>
<p style="margin-top: 0; margin-bottom: 0.17in"></p>
<center><font size=-1>
<span style="font-size: 10pt"><a href="
http://www.lucent.com/copyright.html">Copyright</a></span>
<span style="font-size: 10pt">© 2009 Alcatel-Lucent.</span>
<span style="font-size: 10pt">All Rights Reserved.</span>
<br />
<span style="font-size: 10pt">Comments to</span>
<span style="font-size: 10pt"><a href="mailto:
[email protected]">
[email protected]</a>.</span>
</font></center>
</body>
</html>