URI:
       tacme.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tacme.c (8924B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <thread.h>
            4 #include <9pclient.h>
            5 #include <acme.h>
            6 
            7 static CFsys *acmefs;
            8 static Win *windows;
            9 static Win *last;
           10 
           11 static void
           12 mountacme(void)
           13 {
           14         if(acmefs == nil){
           15                 acmefs = nsmount("acme", nil);
           16                 if(acmefs == nil)
           17                         sysfatal("cannot mount acme: %r");
           18         }
           19 }
           20 
           21 Win*
           22 newwin(void)
           23 {
           24         CFid *fid;
           25         char buf[100];
           26         int id, n;
           27 
           28         mountacme();
           29         fid = fsopen(acmefs, "new/ctl", ORDWR);
           30         if(fid == nil)
           31                 sysfatal("open new/ctl: %r");
           32         n = fsread(fid, buf, sizeof buf-1);
           33         if(n <= 0)
           34                 sysfatal("read new/ctl: %r");
           35         buf[n] = 0;
           36         id = atoi(buf);
           37         if(id == 0)
           38                 sysfatal("read new/ctl: malformed message: %s", buf);
           39 
           40         return openwin(id, fid);
           41 }
           42 
           43 Win*
           44 openwin(int id, CFid *ctl)
           45 {
           46         char buf[100];
           47         Win *w;
           48 
           49         mountacme();
           50         if(ctl == nil){
           51                 snprint(buf, sizeof buf, "%d/ctl", id);
           52                 if((ctl = fsopen(acmefs, buf, ORDWR)) == nil)
           53                         sysfatal("open %s: %r", buf);
           54         }
           55         w = emalloc(sizeof *w);
           56         w->id = id;
           57         w->ctl = ctl;
           58         w->next = nil;
           59         w->prev = last;
           60         if(last)
           61                 last->next = w;
           62         else
           63                 windows = w;
           64         last = w;
           65         return w;
           66 }
           67 
           68 void
           69 winclosefiles(Win *w)
           70 {
           71         if(w->ctl){
           72                 fsclose(w->ctl);
           73                 w->ctl = nil;
           74         }
           75         if(w->body){
           76                 fsclose(w->body);
           77                 w->body = nil;
           78         }
           79         if(w->addr){
           80                 fsclose(w->addr);
           81                 w->addr = nil;
           82         }
           83         if(w->tag){
           84                 fsclose(w->tag);
           85                 w->tag = nil;
           86         }
           87         if(w->event){
           88                 fsclose(w->event);
           89                 w->event = nil;
           90         }
           91         if(w->data){
           92                 fsclose(w->data);
           93                 w->data = nil;
           94         }
           95         if(w->xdata){
           96                 fsclose(w->xdata);
           97                 w->xdata = nil;
           98         }
           99 }
          100 
          101 void
          102 winfree(Win *w)
          103 {
          104         winclosefiles(w);
          105         if(w->c){
          106                 chanfree(w->c);
          107                 w->c = nil;
          108         }
          109         if(w->next)
          110                 w->next->prev = w->prev;
          111         else
          112                 last = w->prev;
          113         if(w->prev)
          114                 w->prev->next = w->next;
          115         else
          116                 windows = w->next;
          117         free(w);
          118 }
          119 
          120 void
          121 windeleteall(void)
          122 {
          123         Win *w, *next;
          124 
          125         for(w=windows; w; w=next){
          126                 next = w->next;
          127                 winctl(w, "delete");
          128         }
          129 }
          130 
          131 static CFid*
          132 wfid(Win *w, char *name)
          133 {
          134         char buf[100];
          135         CFid **fid;
          136 
          137         if(strcmp(name, "ctl") == 0)
          138                 fid = &w->ctl;
          139         else if(strcmp(name, "body") == 0)
          140                 fid = &w->body;
          141         else if(strcmp(name, "addr") == 0)
          142                 fid = &w->addr;
          143         else if(strcmp(name, "tag") == 0)
          144                 fid = &w->tag;
          145         else if(strcmp(name, "event") == 0)
          146                 fid = &w->event;
          147         else if(strcmp(name, "data") == 0)
          148                 fid = &w->data;
          149         else if(strcmp(name, "xdata") == 0)
          150                 fid = &w->xdata;
          151         else{
          152                 fid = 0;
          153                 sysfatal("bad window file name %s", name);
          154         }
          155 
          156         if(*fid == nil){
          157                 snprint(buf, sizeof buf, "acme/%d/%s", w->id, name);
          158                 *fid = fsopen(acmefs, buf, ORDWR);
          159                 if(*fid == nil)
          160                         sysfatal("open %s: %r", buf);
          161         }
          162         return *fid;
          163 }
          164 
          165 int
          166 winopenfd(Win *w, char *name, int mode)
          167 {
          168         char buf[100];
          169 
          170         snprint(buf, sizeof buf, "%d/%s", w->id, name);
          171         return fsopenfd(acmefs, buf, mode);
          172 }
          173 
          174 int
          175 winctl(Win *w, char *fmt, ...)
          176 {
          177         char *s;
          178         va_list arg;
          179         CFid *fid;
          180         int n;
          181 
          182         va_start(arg, fmt);
          183         s = evsmprint(fmt, arg);
          184         va_end(arg);
          185 
          186         fid = wfid(w, "ctl");
          187         n = fspwrite(fid, s, strlen(s), 0);
          188         free(s);
          189         return n;
          190 }
          191 
          192 int
          193 winname(Win *w, char *fmt, ...)
          194 {
          195         char *s;
          196         va_list arg;
          197         int n;
          198 
          199         va_start(arg, fmt);
          200         s = evsmprint(fmt, arg);
          201         va_end(arg);
          202 
          203         n = winctl(w, "name %s\n", s);
          204         free(s);
          205         return n;
          206 }
          207 
          208 int
          209 winprint(Win *w, char *name, char *fmt, ...)
          210 {
          211         char *s;
          212         va_list arg;
          213         int n;
          214 
          215         va_start(arg, fmt);
          216         s = evsmprint(fmt, arg);
          217         va_end(arg);
          218 
          219         n = fswrite(wfid(w, name), s, strlen(s));
          220         free(s);
          221         return n;
          222 }
          223 
          224 int
          225 winaddr(Win *w, char *fmt, ...)
          226 {
          227         char *s;
          228         va_list arg;
          229         int n;
          230 
          231         va_start(arg, fmt);
          232         s = evsmprint(fmt, arg);
          233         va_end(arg);
          234 
          235         n = fswrite(wfid(w, "addr"), s, strlen(s));
          236         free(s);
          237         return n;
          238 }
          239 
          240 int
          241 winreadaddr(Win *w, uint *q1)
          242 {
          243         char buf[40], *p;
          244         uint q0;
          245         int n;
          246 
          247         n = fspread(wfid(w, "addr"), buf, sizeof buf-1, 0);
          248         if(n <= 0)
          249                 return -1;
          250         buf[n] = 0;
          251         q0 = strtoul(buf, &p, 10);
          252         if(q1)
          253                 *q1 = strtoul(p, nil, 10);
          254         return q0;
          255 }
          256 
          257 int
          258 winread(Win *w, char *file, void *a, int n)
          259 {
          260         return fsread(wfid(w, file), a, n);
          261 }
          262 
          263 int
          264 winwrite(Win *w, char *file, void *a, int n)
          265 {
          266         return fswrite(wfid(w, file), a, n);
          267 }
          268 
          269 char*
          270 winmread(Win *w, char *file)
          271 {
          272         char *buf;
          273         int n, tot, m;
          274 
          275         m = 128;
          276         buf = emalloc(m+1);
          277         tot = 0;
          278         while((n = fsread(wfid(w, file), buf+tot, m-tot)) > 0){
          279                 tot += n;
          280                 if(tot >= m){
          281                         m += 128;
          282                         buf = erealloc(buf, m+1);
          283                 }
          284         }
          285         if(n < 0){
          286                 free(buf);
          287                 return nil;
          288         }
          289         buf[tot] = 0;
          290         return buf;
          291 }
          292 
          293 int
          294 winseek(Win *w, char *file, int n, int off)
          295 {
          296         return fsseek(wfid(w, file), n, off);
          297 }
          298 
          299 int
          300 winwriteevent(Win *w, Event *e)
          301 {
          302         char buf[100];
          303 
          304         snprint(buf, sizeof buf, "%c%c%d %d \n", e->c1, e->c2, e->q0, e->q1);
          305         return fswrite(wfid(w, "event"), buf, strlen(buf));
          306 }
          307 
          308 int
          309 windel(Win *w, int sure)
          310 {
          311         return winctl(w, sure ? "delete" : "del");
          312 }
          313 
          314 int
          315 winfd(Win *w, char *name, int mode)
          316 {
          317         char buf[100];
          318 
          319         snprint(buf, sizeof buf, "acme/%d/%s", w->id, name);
          320         return fsopenfd(acmefs, buf, mode);
          321 }
          322 
          323 static void
          324 error(Win *w, char *msg)
          325 {
          326         if(msg == nil)
          327                 longjmp(w->jmp, 1);
          328         fprint(2, "%s: win%d: %s\n", argv0, w->id, msg);
          329         longjmp(w->jmp, 2);
          330 }
          331 
          332 static int
          333 getec(Win *w, CFid *efd)
          334 {
          335         if(w->nbuf <= 0){
          336                 w->nbuf = fsread(efd, w->buf, sizeof w->buf);
          337                 if(w->nbuf <= 0)
          338                         error(w, nil);
          339                 w->bufp = w->buf;
          340         }
          341         --w->nbuf;
          342         return *w->bufp++;
          343 }
          344 
          345 static int
          346 geten(Win *w, CFid *efd)
          347 {
          348         int n, c;
          349 
          350         n = 0;
          351         while('0'<=(c=getec(w,efd)) && c<='9')
          352                 n = n*10+(c-'0');
          353         if(c != ' ')
          354                 error(w, "event number syntax");
          355         return n;
          356 }
          357 
          358 static int
          359 geter(Win *w, CFid *efd, char *buf, int *nb)
          360 {
          361         Rune r;
          362         int n;
          363 
          364         r = getec(w, efd);
          365         buf[0] = r;
          366         n = 1;
          367         if(r < Runeself)
          368                 goto Return;
          369         while(!fullrune(buf, n))
          370                 buf[n++] = getec(w, efd);
          371         chartorune(&r, buf);
          372     Return:
          373         *nb = n;
          374         return r;
          375 }
          376 
          377 static void
          378 gete(Win *w, CFid *efd, Event *e)
          379 {
          380         int i, nb;
          381 
          382         e->c1 = getec(w, efd);
          383         e->c2 = getec(w, efd);
          384         e->q0 = geten(w, efd);
          385         e->q1 = geten(w, efd);
          386         e->flag = geten(w, efd);
          387         e->nr = geten(w, efd);
          388         if(e->nr > EVENTSIZE)
          389                 error(w, "event string too long");
          390         e->nb = 0;
          391         for(i=0; i<e->nr; i++){
          392                 /* e->r[i] = */ geter(w, efd, e->text+e->nb, &nb);
          393                 e->nb += nb;
          394         }
          395 /*         e->r[e->nr] = 0; */
          396         e->text[e->nb] = 0;
          397         if(getec(w, efd) != '\n')
          398                 error(w, "event syntax 2");
          399 }
          400 
          401 int
          402 winreadevent(Win *w, Event *e)
          403 {
          404         CFid *efd;
          405         int r;
          406 
          407         if((r = setjmp(w->jmp)) != 0){
          408                 if(r == 1)
          409                         return 0;
          410                 return -1;
          411         }
          412         efd = wfid(w, "event");
          413         gete(w, efd, e);
          414         e->oq0 = e->q0;
          415         e->oq1 = e->q1;
          416 
          417         /* expansion */
          418         if(e->flag&2){
          419                 gete(w, efd, &w->e2);
          420                 if(e->q0==e->q1){
          421                         w->e2.oq0 = e->q0;
          422                         w->e2.oq1 = e->q1;
          423                         w->e2.flag = e->flag;
          424                         *e = w->e2;
          425                 }
          426         }
          427 
          428         /* chorded argument */
          429         if(e->flag&8){
          430                 gete(w, efd, &w->e3);        /* arg */
          431                 gete(w, efd, &w->e4);        /* location */
          432                 strcpy(e->arg, w->e3.text);
          433                 strcpy(e->loc, w->e4.text);
          434         }
          435 
          436         return 1;
          437 }
          438 
          439 int
          440 eventfmt(Fmt *fmt)
          441 {
          442         Event *e;
          443 
          444         e = va_arg(fmt->args, Event*);
          445         return fmtprint(fmt, "%c%c %d %d %d %d %q", e->c1, e->c2, e->q0, e->q1, e->flag, e->nr, e->text);
          446 }
          447 
          448 void*
          449 emalloc(uint n)
          450 {
          451         void *v;
          452 
          453         v = mallocz(n, 1);
          454         if(v == nil)
          455                 sysfatal("out of memory");
          456         return v;
          457 }
          458 
          459 void*
          460 erealloc(void *v, uint n)
          461 {
          462         v = realloc(v, n);
          463         if(v == nil)
          464                 sysfatal("out of memory");
          465         return v;
          466 }
          467 
          468 char*
          469 estrdup(char *s)
          470 {
          471         s = strdup(s);
          472         if(s == nil)
          473                 sysfatal("out of memory");
          474         return s;
          475 }
          476 
          477 char*
          478 evsmprint(char *s, va_list v)
          479 {
          480         s = vsmprint(s, v);
          481         if(s == nil)
          482                 sysfatal("out of memory");
          483         return s;
          484 }
          485 
          486 int
          487 pipewinto(Win *w, char *name, int errto, char *cmd, ...)
          488 {
          489         va_list arg;
          490         char *p;
          491         int fd[3], pid;
          492 
          493         va_start(arg, cmd);
          494         p = evsmprint(cmd, arg);
          495         va_end(arg);
          496         fd[0] = winfd(w, name, OREAD);
          497         fd[1] = dup(errto, -1);
          498         fd[2] = dup(errto, -1);
          499         pid = threadspawnl(fd, "rc", "rc", "-c", p, 0);
          500         free(p);
          501         return pid;
          502 }
          503 
          504 int
          505 pipetowin(Win *w, char *name, int errto, char *cmd, ...)
          506 {
          507         va_list arg;
          508         char *p;
          509         int fd[3], pid;
          510 
          511         va_start(arg, cmd);
          512         p = evsmprint(cmd, arg);
          513         va_end(arg);
          514         fd[0] = open("/dev/null", OREAD);
          515         fd[1] = winfd(w, name, OWRITE);
          516         if(errto == 0)
          517                 fd[2] = dup(fd[1], -1);
          518         else
          519                 fd[2] = dup(errto, -1);
          520         pid = threadspawnl(fd, "rc", "rc", "-c", p, 0);
          521         free(p);
          522         return pid;
          523 }
          524 
          525 char*
          526 sysrun(char *fmt, ...)
          527 {
          528         static char buf[1025];
          529         char *cmd;
          530         va_list arg;
          531         int n, fd[3], p[2], tot;
          532 
          533 #undef pipe
          534         if(pipe(p) < 0)
          535                 sysfatal("pipe: %r");
          536         fd[0] = open("/dev/null", OREAD);
          537         fd[1] = p[1];
          538         fd[2] = dup(p[1], -1);
          539 
          540         va_start(arg, fmt);
          541         cmd = evsmprint(fmt, arg);
          542         va_end(arg);
          543         threadspawnl(fd, "rc", "rc", "-Ic", cmd, 0);
          544 
          545         tot = 0;
          546         while((n = read(p[0], buf+tot, sizeof buf-tot)) > 0)
          547                 tot += n;
          548         close(p[0]);
          549         if(n < 0)
          550                 return nil;
          551         free(cmd);
          552         if(tot == sizeof buf)
          553                 tot--;
          554         buf[tot] = 0;
          555         while(tot > 0 && isspace(buf[tot-1]))
          556                 tot--;
          557         buf[tot] = 0;
          558         if(tot == 0){
          559                 werrstr("no output");
          560                 return nil;
          561         }
          562         return buf;
          563 }
          564 
          565 static void
          566 eventreader(void *v)
          567 {
          568         Event e[2];
          569         Win *w;
          570         int i;
          571 
          572         w = v;
          573         i = 0;
          574         for(;;){
          575                 if(winreadevent(w, &e[i]) <= 0)
          576                         break;
          577                 sendp(w->c, &e[i]);
          578                 i = 1-i;        /* toggle */
          579         }
          580         sendp(w->c, nil);
          581         threadexits(nil);
          582 }
          583 
          584 Channel*
          585 wineventchan(Win *w)
          586 {
          587         if(w->c == nil){
          588                 w->c = chancreate(sizeof(Event*), 0);
          589                 threadcreate(eventreader, w, 32*1024);
          590         }
          591         return w->c;
          592 }