diff options
author | rsc <devnull@localhost> | 2006-05-25 06:25:28 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2006-05-25 06:25:28 +0000 |
commit | f3b8bf7f4ee326d9de31947584c6e9dbbfa75ce6 (patch) | |
tree | da260702524241156de68695021820397e83f1ac /src/libacme | |
parent | 603d6d896f9932b125b240fe4da82f7a41012a62 (diff) | |
download | plan9port-f3b8bf7f4ee326d9de31947584c6e9dbbfa75ce6.tar.gz plan9port-f3b8bf7f4ee326d9de31947584c6e9dbbfa75ce6.tar.bz2 plan9port-f3b8bf7f4ee326d9de31947584c6e9dbbfa75ce6.zip |
new libacme
Diffstat (limited to 'src/libacme')
-rw-r--r-- | src/libacme/acme.c | 588 | ||||
-rw-r--r-- | src/libacme/mkfile | 13 |
2 files changed, 601 insertions, 0 deletions
diff --git a/src/libacme/acme.c b/src/libacme/acme.c new file mode 100644 index 00000000..35d222d5 --- /dev/null +++ b/src/libacme/acme.c @@ -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; +} diff --git a/src/libacme/mkfile b/src/libacme/mkfile new file mode 100644 index 00000000..4b576c60 --- /dev/null +++ b/src/libacme/mkfile @@ -0,0 +1,13 @@ +<$PLAN9/src/mkhdr + +LIB=libacme.a + +OFILES=\ + acme.$O\ + +HFILES=\ + $PLAN9/include/acme.h\ + +<$PLAN9/src/mksyslib + + |