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