7 typedef struct Queue Queue;
21 Queue* kbdq; /* unprocessed console input */
22 Queue* lineq; /* processed console input */
30 int raw; /* true if we shouldn't process input */
31 int ctl; /* number of opens to the control file */
32 int x; /* index into line */
33 char line[1024]; /* current input line */
37 * cheapo fixed-length queues
40 qwrite(Queue *q, void *v, int n)
47 for(i = 0; i < n; i++){
58 rendwakeup(&q->rwait);
75 qread(Queue *q, void *v, int n)
87 while(nn < n && q->r != q->w){
93 notempty = q->notempty;
94 q->notempty = q->r != q->w;
100 * wait for something to show up in the kbd buffer.
107 rendsleep(&q->rwait, qcanread, q);
119 q = smalloc(sizeof(Queue));
122 q->e = &q->buf[sizeof q->buf];
128 echoscreen(char *buf, int n)
135 e = ebuf + sizeof(ebuf) - 4;
138 screenputs(ebuf, p - ebuf);
150 screenputs(ebuf, p - ebuf);
154 * Put character, possibly a rune, into read queue at interrupt time.
155 * Called at interrupt time to process a character.
165 n = runetochar(buf, &r);
166 qwrite(kbdq, buf, n);
189 static Dirtab consdir[]={
190 ".", {Qdir, 0, QTDIR}, 0, DMDIR|0555,
191 "cons", {Qcons}, 0, 0660,
192 "consctl", {Qconsctl}, 0, 0220,
193 "snarf", {Qsnarf}, 0, 0600,
194 "winname", {Qwinname}, 0, 0000,
204 consattach(char *spec)
206 return devattach('c', spec);
210 conswalk(Chan *c, Chan *nc, char **name, int nname)
212 return devwalk(c, nc, name,nname, consdir, nelem(consdir), devgen);
216 consstat(Chan *c, uchar *dp, int n)
218 return devstat(c, dp, n, consdir, nelem(consdir), devgen);
222 consopen(Chan *c, int omode)
225 c = devopen(c, omode, consdir, nelem(consdir), devgen);
226 switch((ulong)c->qid.path){
233 if((c->mode&3) == OWRITE || (c->mode&3) == ORDWR)
234 c->aux = smalloc(sizeof(Snarf));
241 setsnarf(char *buf, int n, int *vers)
249 for(i = 0; i < nelem(consdir); i++){
250 if(consdir[i].qid.type == Qsnarf){
251 consdir[i].qid.vers = snarf.vers;
266 switch((ulong)c->qid.path){
267 /* last close of control file turns off raw */
276 /* odd behavior but really ok: replace snarf buffer when /dev/snarf is closed */
281 setsnarf(t->buf, t->n, 0);
282 t->buf = nil; /* setsnarf took it */
290 consread(Chan *c, void *buf, long n, vlong off)
297 switch((ulong)c->qid.path){
301 if(off + n > snarf.n)
303 memmove(buf, snarf.buf+off, n);
310 return devdirread(c, buf, n, consdir, nelem(consdir), devgen);
318 while(!qcanread(lineq)){
322 /* flush output on rawoff -> rawon */
324 send = !qcanread(kbdq);
326 kbd.line[kbd.x++] = ch;
327 send = !qcanread(kbdq);
342 kbd.line[kbd.x++] = ch;
346 if(send || kbd.x == sizeof kbd.line){
347 qwrite(lineq, kbd.line, kbd.x);
351 n = qread(lineq, buf, n);
357 print("consread 0x%llux\n", c->qid.path);
360 return -1; /* never reached */
364 conswrite(Chan *c, void *va, long n, vlong)
370 switch((ulong)c->qid.path){
381 if(strncmp(a, "rawon", 5) == 0){
383 /* clumsy hack - wake up reader */
385 qwrite(kbdq, &ch, 1);
386 } else if(strncmp(a, "rawoff", 6) == 0){
389 if(a = strchr(a, ' '))
396 /* always append only */
397 if(t->n > MAXSNARF) /* avoid thrashing when people cut huge text */
398 error("snarf buffer too big");
399 a = realloc(t->buf, t->n + n + 1);
401 error("snarf buffer too big");
403 memmove(t->buf+t->n, va, n);
408 print("conswrite: 0x%llux\n", c->qid.path);