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