new libacme
This commit is contained in:
parent
603d6d896f
commit
f3b8bf7f4e
3 changed files with 677 additions and 0 deletions
76
include/acme.h
Normal file
76
include/acme.h
Normal file
|
|
@ -0,0 +1,76 @@
|
||||||
|
AUTOLIB(acme);
|
||||||
|
|
||||||
|
typedef struct Event Event;
|
||||||
|
typedef struct Win Win;
|
||||||
|
|
||||||
|
#define EVENTSIZE 256
|
||||||
|
struct Event
|
||||||
|
{
|
||||||
|
int c1;
|
||||||
|
int c2;
|
||||||
|
int oq0;
|
||||||
|
int oq1;
|
||||||
|
int q0;
|
||||||
|
int q1;
|
||||||
|
int flag;
|
||||||
|
int nb;
|
||||||
|
int nr;
|
||||||
|
char text[EVENTSIZE*UTFmax+1];
|
||||||
|
char arg[EVENTSIZE*UTFmax+1];
|
||||||
|
char loc[EVENTSIZE*UTFmax+1];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Win
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
CFid *ctl;
|
||||||
|
CFid *tag;
|
||||||
|
CFid *body;
|
||||||
|
CFid *addr;
|
||||||
|
CFid *event;
|
||||||
|
CFid *data;
|
||||||
|
CFid *xdata;
|
||||||
|
Channel *c; /* chan(Event) */
|
||||||
|
Win *next;
|
||||||
|
Win *prev;
|
||||||
|
|
||||||
|
/* events */
|
||||||
|
int nbuf;
|
||||||
|
char buf[1024];
|
||||||
|
char *bufp;
|
||||||
|
jmp_buf jmp;
|
||||||
|
Event e2;
|
||||||
|
Event e3;
|
||||||
|
Event e4;
|
||||||
|
};
|
||||||
|
|
||||||
|
Win *newwin(void);
|
||||||
|
Win *openwin(int, CFid*);
|
||||||
|
|
||||||
|
int eventfmt(Fmt*);
|
||||||
|
int pipewinto(Win *w, char *name, int, char *fmt, ...);
|
||||||
|
int pipetowin(Win *w, char *name, int, char *fmt, ...);
|
||||||
|
char *sysrun(char*, ...);
|
||||||
|
int winaddr(Win *w, char *fmt, ...);
|
||||||
|
int winctl(Win *w, char *fmt, ...);
|
||||||
|
int windel(Win *w, int sure);
|
||||||
|
int winfd(Win *w, char *name, int);
|
||||||
|
char *winmread(Win *w, char *file);
|
||||||
|
int winname(Win *w, char *fmt, ...);
|
||||||
|
int winprint(Win *w, char *name, char *fmt, ...);
|
||||||
|
int winread(Win *w, char *file, void *a, int n);
|
||||||
|
int winseek(Win *w, char *file, int n, int off);
|
||||||
|
int winreadaddr(Win *w, uint*);
|
||||||
|
int winreadevent(Win *w, Event *e);
|
||||||
|
int winwrite(Win *w, char *file, void *a, int n);
|
||||||
|
int winwriteevent(Win *w, Event *e);
|
||||||
|
int winopenfd(Win *w, char *name, int mode);
|
||||||
|
void windeleteall(void);
|
||||||
|
void winfree(Win *w);
|
||||||
|
void winclosefiles(Win *w);
|
||||||
|
Channel *wineventchan(Win *w);
|
||||||
|
|
||||||
|
void *erealloc(void*, uint);
|
||||||
|
void *emalloc(uint);
|
||||||
|
char *estrdup(char*);
|
||||||
|
char *evsmprint(char*, va_list);
|
||||||
588
src/libacme/acme.c
Normal file
588
src/libacme/acme.c
Normal file
|
|
@ -0,0 +1,588 @@
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <thread.h>
|
||||||
|
#include <9pclient.h>
|
||||||
|
#include <acme.h>
|
||||||
|
|
||||||
|
static CFsys *acmefs;
|
||||||
|
static Win *windows;
|
||||||
|
static Win *last;
|
||||||
|
|
||||||
|
static void
|
||||||
|
mountacme(void)
|
||||||
|
{
|
||||||
|
if(acmefs == nil){
|
||||||
|
acmefs = nsmount("acme", nil);
|
||||||
|
if(acmefs == nil)
|
||||||
|
sysfatal("cannot mount acme: %r");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Win*
|
||||||
|
newwin(void)
|
||||||
|
{
|
||||||
|
CFid *fid;
|
||||||
|
char buf[100];
|
||||||
|
int id, n;
|
||||||
|
|
||||||
|
mountacme();
|
||||||
|
fid = fsopen(acmefs, "new/ctl", ORDWR);
|
||||||
|
if(fid == nil)
|
||||||
|
sysfatal("open new/ctl: %r");
|
||||||
|
n = fsread(fid, buf, sizeof buf-1);
|
||||||
|
if(n <= 0)
|
||||||
|
sysfatal("read new/ctl: %r");
|
||||||
|
buf[n] = 0;
|
||||||
|
id = atoi(buf);
|
||||||
|
if(id == 0)
|
||||||
|
sysfatal("read new/ctl: malformed message: %s", buf);
|
||||||
|
|
||||||
|
return openwin(id, fid);
|
||||||
|
}
|
||||||
|
|
||||||
|
Win*
|
||||||
|
openwin(int id, CFid *ctl)
|
||||||
|
{
|
||||||
|
char buf[100];
|
||||||
|
Win *w;
|
||||||
|
|
||||||
|
mountacme();
|
||||||
|
if(ctl == nil){
|
||||||
|
snprint(buf, sizeof buf, "%d/ctl", id);
|
||||||
|
if((ctl = fsopen(acmefs, buf, ORDWR)) == nil)
|
||||||
|
sysfatal("open %s: %r", buf);
|
||||||
|
}
|
||||||
|
w = emalloc(sizeof *w);
|
||||||
|
w->id = id;
|
||||||
|
w->ctl = ctl;
|
||||||
|
w->next = nil;
|
||||||
|
w->prev = last;
|
||||||
|
if(last)
|
||||||
|
last->next = w;
|
||||||
|
else
|
||||||
|
windows = w;
|
||||||
|
last = w;
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
winclosefiles(Win *w)
|
||||||
|
{
|
||||||
|
if(w->ctl){
|
||||||
|
fsclose(w->ctl);
|
||||||
|
w->ctl = nil;
|
||||||
|
}
|
||||||
|
if(w->body){
|
||||||
|
fsclose(w->body);
|
||||||
|
w->body = nil;
|
||||||
|
}
|
||||||
|
if(w->addr){
|
||||||
|
fsclose(w->addr);
|
||||||
|
w->addr = nil;
|
||||||
|
}
|
||||||
|
if(w->tag){
|
||||||
|
fsclose(w->tag);
|
||||||
|
w->tag = nil;
|
||||||
|
}
|
||||||
|
if(w->event){
|
||||||
|
fsclose(w->event);
|
||||||
|
w->event = nil;
|
||||||
|
}
|
||||||
|
if(w->data){
|
||||||
|
fsclose(w->data);
|
||||||
|
w->data = nil;
|
||||||
|
}
|
||||||
|
if(w->xdata){
|
||||||
|
fsclose(w->xdata);
|
||||||
|
w->xdata = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
winfree(Win *w)
|
||||||
|
{
|
||||||
|
winclosefiles(w);
|
||||||
|
if(w->c){
|
||||||
|
chanfree(w->c);
|
||||||
|
w->c = nil;
|
||||||
|
}
|
||||||
|
if(w->next)
|
||||||
|
w->next->prev = w->prev;
|
||||||
|
else
|
||||||
|
last = w->prev;
|
||||||
|
if(w->prev)
|
||||||
|
w->prev->next = w->next;
|
||||||
|
else
|
||||||
|
windows = w->next;
|
||||||
|
free(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
windeleteall(void)
|
||||||
|
{
|
||||||
|
Win *w, *next;
|
||||||
|
|
||||||
|
for(w=windows; w; w=next){
|
||||||
|
next = w->next;
|
||||||
|
winctl(w, "delete");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static CFid*
|
||||||
|
wfid(Win *w, char *name)
|
||||||
|
{
|
||||||
|
char buf[100];
|
||||||
|
CFid **fid;
|
||||||
|
|
||||||
|
if(strcmp(name, "ctl") == 0)
|
||||||
|
fid = &w->ctl;
|
||||||
|
else if(strcmp(name, "body") == 0)
|
||||||
|
fid = &w->body;
|
||||||
|
else if(strcmp(name, "addr") == 0)
|
||||||
|
fid = &w->addr;
|
||||||
|
else if(strcmp(name, "tag") == 0)
|
||||||
|
fid = &w->tag;
|
||||||
|
else if(strcmp(name, "event") == 0)
|
||||||
|
fid = &w->event;
|
||||||
|
else if(strcmp(name, "data") == 0)
|
||||||
|
fid = &w->data;
|
||||||
|
else if(strcmp(name, "xdata") == 0)
|
||||||
|
fid = &w->xdata;
|
||||||
|
else{
|
||||||
|
fid = 0;
|
||||||
|
sysfatal("bad window file name %s", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*fid == nil){
|
||||||
|
snprint(buf, sizeof buf, "acme/%d/%s", w->id, name);
|
||||||
|
*fid = fsopen(acmefs, buf, ORDWR);
|
||||||
|
if(*fid == nil)
|
||||||
|
sysfatal("open %s: %r", buf);
|
||||||
|
}
|
||||||
|
return *fid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
winopenfd(Win *w, char *name, int mode)
|
||||||
|
{
|
||||||
|
char buf[100];
|
||||||
|
|
||||||
|
snprint(buf, sizeof buf, "%d/%s", w->id, name);
|
||||||
|
return fsopenfd(acmefs, buf, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
winctl(Win *w, char *fmt, ...)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
va_list arg;
|
||||||
|
CFid *fid;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
va_start(arg, fmt);
|
||||||
|
s = evsmprint(fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
fid = wfid(w, "ctl");
|
||||||
|
n = fspwrite(fid, s, strlen(s), 0);
|
||||||
|
free(s);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
winname(Win *w, char *fmt, ...)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
va_list arg;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
va_start(arg, fmt);
|
||||||
|
s = evsmprint(fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
n = winctl(w, "name %s\n", s);
|
||||||
|
free(s);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
winprint(Win *w, char *name, char *fmt, ...)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
va_list arg;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
va_start(arg, fmt);
|
||||||
|
s = evsmprint(fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
n = fswrite(wfid(w, name), s, strlen(s));
|
||||||
|
free(s);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
winaddr(Win *w, char *fmt, ...)
|
||||||
|
{
|
||||||
|
char *s;
|
||||||
|
va_list arg;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
va_start(arg, fmt);
|
||||||
|
s = evsmprint(fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
|
||||||
|
n = fswrite(wfid(w, "addr"), s, strlen(s));
|
||||||
|
free(s);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
winreadaddr(Win *w, uint *q1)
|
||||||
|
{
|
||||||
|
char buf[40], *p;
|
||||||
|
uint q0;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = fspread(wfid(w, "addr"), buf, sizeof buf-1, 0);
|
||||||
|
if(n <= 0)
|
||||||
|
return -1;
|
||||||
|
buf[n] = 0;
|
||||||
|
q0 = strtoul(buf, &p, 10);
|
||||||
|
if(q1)
|
||||||
|
*q1 = strtoul(p, nil, 10);
|
||||||
|
return q0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
winread(Win *w, char *file, void *a, int n)
|
||||||
|
{
|
||||||
|
return fsread(wfid(w, file), a, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
winwrite(Win *w, char *file, void *a, int n)
|
||||||
|
{
|
||||||
|
return fswrite(wfid(w, file), a, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
winmread(Win *w, char *file)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
int n, tot, m;
|
||||||
|
|
||||||
|
m = 128;
|
||||||
|
buf = emalloc(m+1);
|
||||||
|
tot = 0;
|
||||||
|
while((n = fsread(wfid(w, file), buf+tot, m-tot)) > 0){
|
||||||
|
tot += n;
|
||||||
|
if(tot >= m){
|
||||||
|
m += 128;
|
||||||
|
buf = erealloc(buf, m+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(n < 0){
|
||||||
|
free(buf);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
buf[tot] = 0;
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
winseek(Win *w, char *file, int n, int off)
|
||||||
|
{
|
||||||
|
return fsseek(wfid(w, file), n, off);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
winwriteevent(Win *w, Event *e)
|
||||||
|
{
|
||||||
|
char buf[100];
|
||||||
|
|
||||||
|
snprint(buf, sizeof buf, "%c%c%d %d \n", e->c1, e->c2, e->q0, e->q1);
|
||||||
|
return fswrite(wfid(w, "event"), buf, strlen(buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
windel(Win *w, int sure)
|
||||||
|
{
|
||||||
|
return winctl(w, sure ? "delete" : "del");
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
winfd(Win *w, char *name, int mode)
|
||||||
|
{
|
||||||
|
char buf[100];
|
||||||
|
|
||||||
|
snprint(buf, sizeof buf, "acme/%d/%s", w->id, name);
|
||||||
|
return fsopenfd(acmefs, buf, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
error(Win *w, char *msg)
|
||||||
|
{
|
||||||
|
if(msg == nil)
|
||||||
|
longjmp(w->jmp, 1);
|
||||||
|
fprint(2, "%s: win%d: %s\n", argv0, w->id, msg);
|
||||||
|
longjmp(w->jmp, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
getec(Win *w, CFid *efd)
|
||||||
|
{
|
||||||
|
if(w->nbuf <= 0){
|
||||||
|
w->nbuf = fsread(efd, w->buf, sizeof w->buf);
|
||||||
|
if(w->nbuf <= 0)
|
||||||
|
error(w, nil);
|
||||||
|
w->bufp = w->buf;
|
||||||
|
}
|
||||||
|
--w->nbuf;
|
||||||
|
return *w->bufp++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
geten(Win *w, CFid *efd)
|
||||||
|
{
|
||||||
|
int n, c;
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
while('0'<=(c=getec(w,efd)) && c<='9')
|
||||||
|
n = n*10+(c-'0');
|
||||||
|
if(c != ' ')
|
||||||
|
error(w, "event number syntax");
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
geter(Win *w, CFid *efd, char *buf, int *nb)
|
||||||
|
{
|
||||||
|
Rune r;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
r = getec(w, efd);
|
||||||
|
buf[0] = r;
|
||||||
|
n = 1;
|
||||||
|
if(r < Runeself)
|
||||||
|
goto Return;
|
||||||
|
while(!fullrune(buf, n))
|
||||||
|
buf[n++] = getec(w, efd);
|
||||||
|
chartorune(&r, buf);
|
||||||
|
Return:
|
||||||
|
*nb = n;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gete(Win *w, CFid *efd, Event *e)
|
||||||
|
{
|
||||||
|
int i, nb;
|
||||||
|
|
||||||
|
e->c1 = getec(w, efd);
|
||||||
|
e->c2 = getec(w, efd);
|
||||||
|
e->q0 = geten(w, efd);
|
||||||
|
e->q1 = geten(w, efd);
|
||||||
|
e->flag = geten(w, efd);
|
||||||
|
e->nr = geten(w, efd);
|
||||||
|
if(e->nr > EVENTSIZE)
|
||||||
|
error(w, "event string too long");
|
||||||
|
e->nb = 0;
|
||||||
|
for(i=0; i<e->nr; i++){
|
||||||
|
/* e->r[i] = */ geter(w, efd, e->text+e->nb, &nb);
|
||||||
|
e->nb += nb;
|
||||||
|
}
|
||||||
|
/* e->r[e->nr] = 0; */
|
||||||
|
e->text[e->nb] = 0;
|
||||||
|
if(getec(w, efd) != '\n')
|
||||||
|
error(w, "event syntax 2");
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
winreadevent(Win *w, Event *e)
|
||||||
|
{
|
||||||
|
CFid *efd;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if((r = setjmp(w->jmp)) != 0){
|
||||||
|
if(r == 1)
|
||||||
|
return 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
efd = wfid(w, "event");
|
||||||
|
gete(w, efd, e);
|
||||||
|
|
||||||
|
/* expansion */
|
||||||
|
if(e->flag&2){
|
||||||
|
gete(w, efd, &w->e2);
|
||||||
|
if(e->q0==e->q1){
|
||||||
|
w->e2.flag = e->flag;
|
||||||
|
*e = w->e2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* chorded argument */
|
||||||
|
if(e->flag&8){
|
||||||
|
gete(w, efd, &w->e3); /* arg */
|
||||||
|
gete(w, efd, &w->e4); /* location */
|
||||||
|
strcpy(e->arg, w->e3.text);
|
||||||
|
strcpy(e->loc, w->e4.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
eventfmt(Fmt *fmt)
|
||||||
|
{
|
||||||
|
Event *e;
|
||||||
|
|
||||||
|
e = va_arg(fmt->args, Event*);
|
||||||
|
return fmtprint(fmt, "%c%c %d %d %d %d %q", e->c1, e->c2, e->q0, e->q1, e->flag, e->nr, e->text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
emalloc(uint n)
|
||||||
|
{
|
||||||
|
void *v;
|
||||||
|
|
||||||
|
v = mallocz(n, 1);
|
||||||
|
if(v == nil)
|
||||||
|
sysfatal("out of memory");
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
erealloc(void *v, uint n)
|
||||||
|
{
|
||||||
|
v = realloc(v, n);
|
||||||
|
if(v == nil)
|
||||||
|
sysfatal("out of memory");
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
estrdup(char *s)
|
||||||
|
{
|
||||||
|
s = strdup(s);
|
||||||
|
if(s == nil)
|
||||||
|
sysfatal("out of memory");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
evsmprint(char *s, va_list v)
|
||||||
|
{
|
||||||
|
s = vsmprint(s, v);
|
||||||
|
if(s == nil)
|
||||||
|
sysfatal("out of memory");
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pipewinto(Win *w, char *name, int errto, char *cmd, ...)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
char *p;
|
||||||
|
int fd[3], pid;
|
||||||
|
|
||||||
|
va_start(arg, cmd);
|
||||||
|
p = evsmprint(cmd, arg);
|
||||||
|
va_end(arg);
|
||||||
|
fd[0] = winfd(w, name, OREAD);
|
||||||
|
fd[1] = dup(errto, -1);
|
||||||
|
fd[2] = dup(errto, -1);
|
||||||
|
pid = threadspawnl(fd, "rc", "rc", "-c", p, 0);
|
||||||
|
free(p);
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pipetowin(Win *w, char *name, int errto, char *cmd, ...)
|
||||||
|
{
|
||||||
|
va_list arg;
|
||||||
|
char *p;
|
||||||
|
int fd[3], pid;
|
||||||
|
|
||||||
|
va_start(arg, cmd);
|
||||||
|
p = evsmprint(cmd, arg);
|
||||||
|
va_end(arg);
|
||||||
|
fd[0] = open("/dev/null", OREAD);
|
||||||
|
fd[1] = winfd(w, name, OWRITE);
|
||||||
|
if(errto == 0)
|
||||||
|
fd[2] = dup(fd[1], -1);
|
||||||
|
else
|
||||||
|
fd[2] = dup(errto, -1);
|
||||||
|
pid = threadspawnl(fd, "rc", "rc", "-c", p, 0);
|
||||||
|
free(p);
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
sysrun(char *fmt, ...)
|
||||||
|
{
|
||||||
|
static char buf[1024];
|
||||||
|
char *cmd;
|
||||||
|
va_list arg;
|
||||||
|
int n, fd[3], p[2], tot;
|
||||||
|
|
||||||
|
#undef pipe
|
||||||
|
if(pipe(p) < 0)
|
||||||
|
sysfatal("pipe: %r");
|
||||||
|
fd[0] = open("/dev/null", OREAD);
|
||||||
|
fd[1] = p[1];
|
||||||
|
fd[2] = dup(p[1], -1);
|
||||||
|
|
||||||
|
va_start(arg, fmt);
|
||||||
|
cmd = evsmprint(fmt, arg);
|
||||||
|
va_end(arg);
|
||||||
|
threadspawnl(fd, "rc", "rc", "-Ic", cmd, 0);
|
||||||
|
|
||||||
|
tot = 0;
|
||||||
|
while((n = read(p[0], buf+tot, sizeof buf-tot)) > 0)
|
||||||
|
tot += n;
|
||||||
|
close(p[0]);
|
||||||
|
if(n < 0)
|
||||||
|
return nil;
|
||||||
|
free(cmd);
|
||||||
|
if(tot == sizeof buf)
|
||||||
|
tot--;
|
||||||
|
buf[tot] = 0;
|
||||||
|
while(tot > 0 && isspace(buf[tot-1]))
|
||||||
|
tot--;
|
||||||
|
buf[tot] = 0;
|
||||||
|
if(tot == 0){
|
||||||
|
werrstr("no output");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
eventreader(void *v)
|
||||||
|
{
|
||||||
|
Event e[2];
|
||||||
|
Win *w;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
w = v;
|
||||||
|
i = 0;
|
||||||
|
for(;;){
|
||||||
|
if(winreadevent(w, &e[i]) <= 0)
|
||||||
|
break;
|
||||||
|
sendp(w->c, &e[i]);
|
||||||
|
i = 1-i; /* toggle */
|
||||||
|
}
|
||||||
|
sendp(w->c, nil);
|
||||||
|
threadexits(nil);
|
||||||
|
}
|
||||||
|
|
||||||
|
Channel*
|
||||||
|
wineventchan(Win *w)
|
||||||
|
{
|
||||||
|
if(w->c == nil){
|
||||||
|
w->c = chancreate(sizeof(Event*), 0);
|
||||||
|
threadcreate(eventreader, w, 32*1024);
|
||||||
|
}
|
||||||
|
return w->c;
|
||||||
|
}
|
||||||
13
src/libacme/mkfile
Normal file
13
src/libacme/mkfile
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
<$PLAN9/src/mkhdr
|
||||||
|
|
||||||
|
LIB=libacme.a
|
||||||
|
|
||||||
|
OFILES=\
|
||||||
|
acme.$O\
|
||||||
|
|
||||||
|
HFILES=\
|
||||||
|
$PLAN9/include/acme.h\
|
||||||
|
|
||||||
|
<$PLAN9/src/mksyslib
|
||||||
|
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue