1 #include "u.h" 2 #include "../port/lib.h" 3 #include "mem.h" 4 #include "dat.h" 5 #include "fns.h" 6 #include "../port/error.h" 7 8 #include <interp.h> 9 10 #include "draw.h" 11 12 enum{ 13 Qdir, 14 Qtkevents 15 }; 16 17 static 18 Dirtab tkdirtab[]={ 19 {".", {Qdir,0,QTDIR}, 0, 0500}, 20 {"tkevents", {Qtkevents, 0}, 0, 0600}, 21 }; 22 23 static struct { 24 QLock l; 25 Queue* eq; 26 Ref inuse; 27 } tkevents; 28 29 static void 30 tkwiretapper(void *top, char *cmd, char *result, void *image, Rectangle *rp) 31 { 32 Block *b; 33 int n; 34 char *s, *e; 35 36 n = 12; 37 if(cmd != nil) 38 n += strlen(cmd)+2+1; 39 if(result != nil) 40 n += strlen(result)+2+1; 41 if(image != nil) 42 n += 12; 43 if(rp != nil) 44 n += 4*20; 45 n++; 46 b = allocb(n); 47 if(b != nil){ 48 s = (char*)b->wp; 49 e = s+n; 50 s += snprint(s, e-s, "%p", top); 51 if(cmd != nil){ 52 *s++ = ' '; 53 *s++ = '['; 54 n = strlen(cmd); 55 memmove(s, cmd, n); 56 s += n; 57 *s++ = ']'; 58 } 59 /* ignore result for now */ 60 if(image != nil) 61 s += snprint(s, e-s, " %p", image); 62 if(rp != nil) 63 s += snprint(s, e-s, " %d %d %d %d", rp->min.x, rp->min.y, rp->max.x, rp->max.y); 64 *s++ = '\n'; 65 b->wp = (uchar*)s; 66 release(); 67 qlock(&tkevents.l); 68 if(waserror()){ 69 qunlock(&tkevents.l); 70 acquire(); 71 return; 72 } 73 if(tkevents.eq != nil) 74 qbwrite(tkevents.eq, b); 75 poperror(); 76 qunlock(&tkevents.l); 77 acquire(); 78 } 79 } 80 81 void (*tkwiretap)(void*, char*, char*, void*, Rectangle*); 82 83 static Chan* 84 tkattach(char* spec) 85 { 86 return devattach(L'τ', spec); 87 } 88 89 static Walkqid* 90 tkwalk(Chan *c, Chan *nc, char **name, int nname) 91 { 92 return devwalk(c, nc, name, nname, tkdirtab, nelem(tkdirtab), devgen); 93 } 94 95 static int 96 tkstat(Chan *c, uchar *db, int n) 97 { 98 return devstat(c, db, n, tkdirtab, nelem(tkdirtab), devgen); 99 } 100 101 static Chan* 102 tkopen(Chan* c, int omode) 103 { 104 if(c->qid.type & QTDIR) 105 return devopen(c, omode, tkdirtab, nelem(tkdirtab), devgen); 106 switch((ulong)c->qid.path){ 107 case Qtkevents: 108 c = devopen(c, omode, tkdirtab, nelem(tkdirtab), devgen); 109 qlock(&tkevents.l); 110 if(incref(&tkevents.inuse) != 1){ 111 qunlock(&tkevents.l); 112 error(Einuse); 113 } 114 if(tkevents.eq == nil) 115 tkevents.eq = qopen(256*1024, 0, nil, nil); 116 else 117 qreopen(tkevents.eq); 118 tkwiretap = tkwiretapper; 119 qunlock(&tkevents.l); 120 break; 121 } 122 return c; 123 } 124 125 static void 126 tkclose(Chan* c) 127 { 128 if(c->qid.type & QTDIR || (c->flag & COPEN) == 0) 129 return; 130 qlock(&tkevents.l); 131 if(decref(&tkevents.inuse) == 0){ 132 tkwiretap = nil; 133 qclose(tkevents.eq); 134 } 135 qunlock(&tkevents.l); 136 } 137 138 static long 139 tkread(Chan* c, void* a, long n, vlong offset) 140 { 141 USED(offset); 142 switch((ulong)c->qid.path){ 143 case Qdir: 144 return devdirread(c, a, n, tkdirtab, nelem(tkdirtab), devgen); 145 case Qtkevents: 146 return qread(tkevents.eq, a, n); 147 default: 148 n=0; 149 break; 150 } 151 return n; 152 } 153 154 static long 155 tkwrite(Chan*, void*, long, vlong) 156 { 157 error(Ebadusefd); 158 return 0; 159 } 160 161 Dev tkdevtab = { 162 L'τ', 163 "tk", 164 165 devreset, 166 devinit, 167 devshutdown, 168 tkattach, 169 tkwalk, 170 tkstat, 171 tkopen, 172 devcreate, 173 tkclose, 174 tkread, 175 devbread, 176 tkwrite, 177 devbwrite, 178 devremove, 179 devwstat, 180 }; 181