]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/aux/kbdfs/kbdfs.c
kbdfs: allow to escape ctlr-alt-del with shift for vmx and vnc.
[plan9front.git] / sys / src / cmd / aux / kbdfs / kbdfs.c
1 #include <u.h>
2 #include <libc.h>
3 #include <auth.h>
4 #include <fcall.h>
5 #include <thread.h>
6 #include <keyboard.h>
7 #include <9p.h>
8
9 enum {
10         Nscan=  128,
11
12         Qroot=  0,
13         Qkbd,
14         Qkbdin,
15         Qkbin,
16         Qkbmap,
17         Qcons,
18         Qconsctl,
19         Nqid,
20
21         Rawon=  0,
22         Rawoff,
23
24         STACK = 8*1024,
25 };
26
27 typedef struct Key Key;
28 typedef struct Scan Scan;
29
30 struct Key {
31         int     down;
32         Rune    b;      /* button, unshifted key */
33         Rune    r;      /* rune, shifted key */
34 };
35
36 struct Scan {
37         int     esc1;
38         int     esc2;
39         int     caps;
40         int     num;
41         int     shift;
42         int     ctl;
43         int     alt;
44         int     altgr;
45         int     mod4;
46         int     leds;
47 };
48
49 struct Qtab {
50         char *name;
51         int mode;
52         int type;
53 } qtab[Nqid] = {
54         "/",
55                 DMDIR|0500,
56                 QTDIR,
57
58         "kbd",
59                 0600,
60                 0,
61
62         "kbdin",
63                 0200,
64                 0,
65
66         "kbin",
67                 0200,   
68                 0,
69
70         "kbmap",
71                 0600,   
72                 0,
73
74         "cons",
75                 0600,   
76                 0,
77
78         "consctl",
79                 0600,
80                 0,
81 };
82
83 char Eshort[] = "read count too small";
84 char Ebadarg[] = "invalid argument";
85 char Eperm[] = "permission denied";
86 char Einuse[] = "file in use";
87 char Enonexist[] = "file does not exist";
88 char Ebadspec[] = "bad attach specifier";
89 char Ewalk[] = "walk in non directory";
90 char Ephase[] = "the front fell off";
91 char Eintr[] = "interrupted";
92
93 int kbdifd = -1;
94 int scanfd = -1;
95 int ledsfd = -1;
96 int consfd = -1;
97 int mctlfd = -1;
98 int msinfd = -1;
99 int notefd = -1;
100 int killfd = -1;
101
102 int kbdopen;
103 int consctlopen;
104 int quiet = 0;
105 char *sname = nil;
106 char *mntpt = "/dev";
107 char *user;
108
109 int debug;
110
111 Channel *keychan;       /* chan(Key) */
112 Channel *mctlchan;      /* chan(Key) */
113
114 Channel *kbdreqchan;    /* chan(Req*) */
115 Channel *consreqchan;   /* chan(Req*) */
116
117 Channel *ctlchan;       /* chan(int) */
118
119 Channel *rawchan;       /* chan(Rune) */
120 Channel *runechan;      /* chan(Rune) */
121
122 Channel *conschan;      /* chan(char*) */
123 Channel *kbdchan;       /* chan(char*) */
124 Channel *intchan;       /* chan(int) */
125
126 /*
127  * The codes at 0x79 and 0x7b are produced by the PFU Happy Hacking keyboard.
128  * A 'standard' keyboard doesn't produce anything above 0x58.
129  */
130 Rune kbtab[Nscan] = 
131 {
132 [0x00]  0,      0x1b,   '1',    '2',    '3',    '4',    '5',    '6',
133 [0x08]  '7',    '8',    '9',    '0',    '-',    '=',    '\b',   '\t',
134 [0x10]  'q',    'w',    'e',    'r',    't',    'y',    'u',    'i',
135 [0x18]  'o',    'p',    '[',    ']',    '\n',   Kctl,   'a',    's',
136 [0x20]  'd',    'f',    'g',    'h',    'j',    'k',    'l',    ';',
137 [0x28]  '\'',   '`',    Kshift, '\\',   'z',    'x',    'c',    'v',
138 [0x30]  'b',    'n',    'm',    ',',    '.',    '/',    Kshift, '*',
139 [0x38]  Kalt,   ' ',    Kctl,   KF|1,   KF|2,   KF|3,   KF|4,   KF|5,
140 [0x40]  KF|6,   KF|7,   KF|8,   KF|9,   KF|10,  Knum,   Kscroll,'7',
141 [0x48]  '8',    '9',    '-',    '4',    '5',    '6',    '+',    '1',
142 [0x50]  '2',    '3',    '0',    '.',    0,      0,      0,      KF|11,
143 [0x58]  KF|12,  0,      0,      0,      0,      0,      0,      0,
144 [0x60]  0,      0,      0,      0,      0,      0,      0,      0,
145 [0x68]  0,      0,      0,      0,      0,      0,      0,      0,
146 [0x70]  0,      0,      0,      0,      0,      0,      0,      0,
147 [0x78]  0,      Kdown,  0,      Kup,    0,      0,      0,      0,
148 };
149
150 Rune kbtabshift[Nscan] =
151 {
152 [0x00]  0,      0x1b,   '!',    '@',    '#',    '$',    '%',    '^',
153 [0x08]  '&',    '*',    '(',    ')',    '_',    '+',    '\b',   '\t',
154 [0x10]  'Q',    'W',    'E',    'R',    'T',    'Y',    'U',    'I',
155 [0x18]  'O',    'P',    '{',    '}',    '\n',   Kctl,   'A',    'S',
156 [0x20]  'D',    'F',    'G',    'H',    'J',    'K',    'L',    ':',
157 [0x28]  '"',    '~',    Kshift, '|',    'Z',    'X',    'C',    'V',
158 [0x30]  'B',    'N',    'M',    '<',    '>',    '?',    Kshift, '*',
159 [0x38]  Kalt,   ' ',    Kctl,   KF|1,   KF|2,   KF|3,   KF|4,   KF|5,
160 [0x40]  KF|6,   KF|7,   KF|8,   KF|9,   KF|10,  Knum,   Kscroll,'7',
161 [0x48]  '8',    '9',    '-',    '4',    '5',    '6',    '+',    '1',
162 [0x50]  '2',    '3',    '0',    '.',    0,      0,      0,      KF|11,
163 [0x58]  KF|12,  0,      0,      0,      0,      0,      0,      0,
164 [0x60]  0,      0,      0,      0,      0,      0,      0,      0,
165 [0x68]  0,      0,      0,      0,      0,      0,      0,      0,
166 [0x70]  0,      0,      0,      0,      0,      0,      0,      0,
167 [0x78]  0,      Kdown,  0,      Kup,    0,      0,      0,      0,
168 };
169
170 Rune kbtabesc1[Nscan] =
171 {
172 [0x00]  0,      0,      0,      0,      0,      0,      0,      0,
173 [0x08]  0,      0,      0,      0,      0,      0,      0,      0,
174 [0x10]  0,      0,      0,      0,      0,      0,      0,      0,
175 [0x18]  0,      0,      0,      0,      '\n',   Kctl,   0,      0,
176 [0x20]  0,      0,      0,      0,      0,      0,      0,      0,
177 [0x28]  0,      0,      0,      0,      0,      0,      0,      0,
178 [0x30]  0,      0,      0,      0,      0,      '/',    0,      Kprint,
179 [0x38]  Kaltgr, 0,      0,      0,      0,      0,      0,      0,
180 [0x40]  0,      0,      0,      0,      0,      0,      Kbreak, Khome,
181 [0x48]  Kup,    Kpgup,  0,      Kleft,  0,      Kright, 0,      Kend,
182 [0x50]  Kdown,  Kpgdown,Kins,   Kdel,   0,      0,      0,      0,
183 [0x58]  0,      0,      0,      Kmod4,  0,      0,      0,      0,
184 [0x60]  0,      0,      0,      0,      0,      0,      0,      0,
185 [0x68]  0,      0,      0,      0,      0,      0,      0,      0,
186 [0x70]  0,      0,      0,      0,      0,      0,      0,      0,
187 [0x78]  0,      Kup,    0,      0,      0,      0,      0,      0,
188 };
189
190 Rune kbtabshiftesc1[Nscan] =
191 {
192 [0x00]  0,      0,      0,      0,      0,      0,      0,      0,
193 [0x08]  0,      0,      0,      0,      0,      0,      0,      0,
194 [0x10]  0,      0,      0,      0,      0,      0,      0,      0,
195 [0x18]  0,      0,      0,      0,      0,      0,      0,      0,
196 [0x20]  0,      0,      0,      0,      0,      0,      0,      0,
197 [0x28]  0,      0,      0,      0,      0,      0,      0,      0,
198 [0x30]  0,      0,      0,      0,      0,      0,      0,      0,
199 [0x38]  0,      0,      0,      0,      0,      0,      0,      0,
200 [0x40]  0,      0,      0,      0,      0,      0,      0,      0,
201 [0x48]  Kup,    0,      0,      0,      0,      0,      0,      0,
202 [0x50]  0,      0,      0,      0,      0,      0,      0,      0,
203 [0x58]  0,      0,      0,      0,      0,      0,      0,      0,
204 [0x60]  0,      0,      0,      0,      0,      0,      0,      0,
205 [0x68]  0,      0,      0,      0,      0,      0,      0,      0,
206 [0x70]  0,      0,      0,      0,      0,      0,      0,      0,
207 [0x78]  0,      Kup,    0,      0,      0,      0,      0,      0,
208 };
209
210 Rune kbtabctrlesc1[Nscan] =
211 {
212 [0x00]  0,      0,      0,      0,      0,      0,      0,      0,
213 [0x08]  0,      0,      0,      0,      0,      0,      0,      0,
214 [0x10]  0,      0,      0,      0,      0,      0,      0,      0,
215 [0x18]  0,      0,      0,      0,      0,      0,      0,      0,
216 [0x20]  0,      0,      0,      0,      0,      0,      0,      0,
217 [0x28]  0,      0,      0,      0,      0,      0,      0,      0,
218 [0x30]  0,      0,      0,      0,      0,      0,      0,      0,
219 [0x38]  0,      0,      0,      0,      0,      0,      0,      0,
220 [0x40]  0,      0,      0,      0,      0,      0,      0,      0,
221 [0x48]  Kup,    0,      0,      0,      0,      0,      0,      0,
222 [0x50]  0,      0,      0,      0,      0,      0,      0,      0,
223 [0x58]  0,      0,      0,      0,      0,      0,      0,      0,
224 [0x60]  0,      0,      0,      0,      0,      0,      0,      0,
225 [0x68]  0,      0,      0,      0,      0,      0,      0,      0,
226 [0x70]  0,      0,      0,      0,      0,      0,      0,      0,
227 [0x78]  0,      Kup,    0,      0,      0,      0,      0,      0,
228 };
229
230 Rune kbtabaltgr[Nscan] =
231 {
232 [0x00]  0,      0,      0,      0,      0,      0,      0,      0,
233 [0x08]  0,      0,      0,      0,      0,      0,      0,      0,
234 [0x10]  0,      0,      0,      0,      0,      0,      0,      0,
235 [0x18]  0,      0,      0,      0,      '\n',   Kctl,   0,      0,
236 [0x20]  0,      0,      0,      0,      0,      0,      0,      0,
237 [0x28]  0,      0,      Kshift, 0,      0,      0,      0,      0,
238 [0x30]  0,      0,      0,      0,      0,      '/',    0,      Kprint,
239 [0x38]  Kaltgr, 0,      0,      0,      0,      0,      0,      0,
240 [0x40]  0,      0,      0,      0,      0,      0,      Kbreak, Khome,
241 [0x48]  Kup,    Kpgup,  0,      Kleft,  0,      Kright, 0,      Kend,
242 [0x50]  Kdown,  Kpgdown,Kins,   Kdel,   0,      0,      0,      0,
243 [0x58]  0,      0,      0,      0,      0,      0,      0,      0,
244 [0x60]  0,      0,      0,      0,      0,      0,      0,      0,
245 [0x68]  0,      0,      0,      0,      0,      0,      0,      0,
246 [0x70]  0,      0,      0,      0,      0,      0,      0,      0,
247 [0x78]  0,      Kup,    0,      0,      0,      0,      0,      0,
248 };
249
250 Rune kbtabctl[Nscan] =
251 {
252 [0x00]  0,      '\e',    '\11',    '\12',    '\13',    '\14',    '\15',    '\16', 
253 [0x08]  '\17',    '\18',    '\19',    '\10',    '\r',    '\1d',    '\b',   '\t',
254 [0x10]  '\11',    '\17',    '\ 5',    '\12',    '\14',    '\19',    '\15',    '\t',
255 [0x18]  '\ f',    '\10',    '\e',    '\1d',    '\n',   Kctl,   '\ 1',    '\13', 
256 [0x20]  '\ 4',    '\ 6',    '\a',    '\b',   '\n',   '\v',    '\f',    '\e', 
257 [0x28]  '\a',    0,      Kshift, '\1c',    '\1a',    '\18',    '\ 3',    '\16', 
258 [0x30]  '\ 2',    '\ e',    '\r',    '\f',    '\ e',    '\ f',    Kshift, '\n',
259 [0x38]  Kalt,   0,      Kctl,   '\ 5',    '\ 6',    '\a',    '\ 4',    '\ 5', 
260 [0x40]  '\ 6',    '\a',    '\f',    '\r',    '\ e',    '\ 5',    '\ 6',    '\17', 
261 [0x48]  '\18',    '\19',    '\r',    '\14',    '\15',    '\16',    '\v',    '\11', 
262 [0x50]  '\12',    '\13',    '\10',    '\ e',    0,      0,      0,      '\ f', 
263 [0x58]  '\f',    0,      0,      0,      0,      0,      0,      0,
264 [0x60]  0,      0,      0,      0,      0,      0,      0,      0,
265 [0x68]  0,      0,      0,      0,      0,      0,      0,      0,
266 [0x70]  0,      0,      0,      0,      0,      0,      0,      0,
267 [0x78]  0,      '\a',    0,      '\b',   0,      0,      0,      0,
268 };
269
270 Rune kbtabshiftaltgr[Nscan] =
271 {
272 [0x00]  0,      0,      0,      0,      0,      0,      0,      0,
273 [0x08]  0,      0,      0,      0,      0,      0,      0,      0,
274 [0x10]  0,      0,      0,      0,      0,      0,      0,      0,
275 [0x18]  0,      0,      0,      0,      0,      0,      0,      0,
276 [0x20]  0,      0,      0,      0,      0,      0,      0,      0,
277 [0x28]  0,      0,      0,      0,      0,      0,      0,      0,
278 [0x30]  0,      0,      0,      0,      0,      0,      0,      0,
279 [0x38]  0,      0,      0,      0,      0,      0,      0,      0,
280 [0x40]  0,      0,      0,      0,      0,      0,      0,      0,
281 [0x48]  0,      0,      0,      0,      0,      0,      0,      0,
282 [0x50]  0,      0,      0,      0,      0,      0,      0,      0,
283 [0x58]  0,      0,      0,      0,      0,      0,      0,      0,
284 [0x60]  0,      0,      0,      0,      0,      0,      0,      0,
285 [0x68]  0,      0,      0,      0,      0,      0,      0,      0,
286 [0x70]  0,      0,      0,      0,      0,      0,      0,      0,
287 [0x78]  0,      0,      0,      0,      0,      0,      0,      0,
288 };
289
290 Rune kbtabmod4[Nscan] =
291 {
292 [0x00]  0,      0,      0,      0,      0,      0,      0,      0,
293 [0x08]  0,      0,      0,      0,      0,      0,      0,      0,
294 [0x10]  0,      0,      0,      0,      0,      0,      0,      0,
295 [0x18]  0,      0,      0,      0,      0,      0,      0,      0,
296 [0x20]  0,      0,      0,      0,      0,      0,      0,      0,
297 [0x28]  0,      0,      0,      0,      0,      0,      0,      0,
298 [0x30]  0,      0,      0,      0,      0,      0,      0,      0,
299 [0x38]  0,      0,      0,      0,      0,      0,      0,      0,
300 [0x40]  0,      0,      0,      0,      0,      0,      0,      0,
301 [0x48]  0,      0,      0,      0,      0,      0,      0,      0,
302 [0x50]  0,      0,      0,      0,      0,      0,      0,      0,
303 [0x58]  0,      0,      0,      0,      0,      0,      0,      0,
304 [0x60]  0,      0,      0,      0,      0,      0,      0,      0,
305 [0x68]  0,      0,      0,      0,      0,      0,      0,      0,
306 [0x70]  0,      0,      0,      0,      0,      0,      0,      0,
307 [0x78]  0,      0,      0,      0,      0,      0,      0,      0,
308 };
309
310 Rune kbtabaltgrmod4[Nscan] =
311 {
312 [0x00]  0,      0,      0,      0,      0,      0,      0,      0,
313 [0x08]  0,      0,      0,      0,      0,      0,      0,      0,
314 [0x10]  0,      0,      0,      0,      0,      0,      0,      0,
315 [0x18]  0,      0,      0,      0,      0,      0,      0,      0,
316 [0x20]  0,      0,      0,      0,      0,      0,      0,      0,
317 [0x28]  0,      0,      0,      0,      0,      0,      0,      0,
318 [0x30]  0,      0,      0,      0,      0,      0,      0,      0,
319 [0x38]  0,      0,      0,      0,      0,      0,      0,      0,
320 [0x40]  0,      0,      0,      0,      0,      0,      0,      0,
321 [0x48]  0,      0,      0,      0,      0,      0,      0,      0,
322 [0x50]  0,      0,      0,      0,      0,      0,      0,      0,
323 [0x58]  0,      0,      0,      0,      0,      0,      0,      0,
324 [0x60]  0,      0,      0,      0,      0,      0,      0,      0,
325 [0x68]  0,      0,      0,      0,      0,      0,      0,      0,
326 [0x70]  0,      0,      0,      0,      0,      0,      0,      0,
327 [0x78]  0,      0,      0,      0,      0,      0,      0,      0,
328 };
329
330 char*
331 dev(char *file)
332 {
333         static char *buf = nil;
334         free(buf);
335         buf = smprint("%s/%s", mntpt, file);
336         return buf;
337 }
338
339 int
340 eopen(char *name, int mode)
341 {
342         int fd;
343
344         fd = open(name, mode);
345         if(fd < 0 && !quiet)
346                 fprint(2, "%s: warning: can't open %s: %r\n", argv0, name);
347         return fd;
348 }
349
350 void
351 reboot(void)
352 {
353         int fd;
354
355         if(debug)
356                 return;
357
358         if((fd = eopen(dev("reboot"), OWRITE)) < 0)
359                 return;
360         fprint(fd, "reboot\n");
361         close(fd);
362 }
363
364 void
365 shutdown(void)
366 {
367         if(notefd >= 0)
368                 write(notefd, "hangup", 6);
369         if(killfd >= 0)
370                 write(killfd, "hangup", 6);
371         threadexitsall(nil);
372 }
373
374 void
375 shiftup(void)
376 {
377         Key key = { .down = 0, .r = Kshift, .b = Kshift };
378         send(keychan, &key);
379 }
380
381 /*
382  * Scan code processing
383  */
384 void
385 kbdputsc(Scan *scan, int c)
386 {
387         Key key;
388
389         /*
390          *  e0's is the first of a 2 character sequence, e1 and e2 the first
391          *  of a 3 character sequence (on the safari)
392          */
393         if(scan->esc2){
394                 scan->esc2--;
395                 return;
396         } else if(c == 0xe1 || c == 0xe2){
397                 scan->esc2 = 2;
398                 return;
399         } else if(c == 0xe0){
400                 scan->esc1 = 1;
401                 return;
402         }
403
404         key.down = (c & 0x80) == 0;
405         c &= 0x7f;
406
407         if(c >= Nscan)
408                 return;
409
410         /* qemu workarround: emulate e0 for numpad */
411         if(c != 0 && strchr("GHIKMOPQRS", c) != nil)
412                 scan->esc1 |= !scan->num;
413
414         if(scan->esc1 && scan->ctl && kbtabctrlesc1[c] != 0)
415                 key.r = kbtabctrlesc1[c];
416         else if(scan->esc1 && scan->shift && kbtabshiftesc1[c] != 0)
417                 key.r = kbtabshiftesc1[c];
418         else if(scan->esc1)
419                 key.r = kbtabesc1[c];
420         else if(scan->altgr && scan->mod4 && kbtabaltgrmod4[c] != 0)
421                 key.r = kbtabaltgrmod4[c];
422         else if(scan->mod4 && kbtabmod4[c] != 0)
423                 key.r = kbtabmod4[c];
424         else if(scan->shift && scan->altgr && kbtabshiftaltgr[c] != 0)
425                 key.r = kbtabshiftaltgr[c];
426         else if(scan->shift)
427                 key.r = kbtabshift[c];
428         else if(scan->altgr)
429                 key.r = kbtabaltgr[c];
430         else if(scan->ctl)
431                 key.r = kbtabctl[c];
432         else
433                 key.r = kbtab[c];
434
435         if(scan->esc1 || kbtab[c] == 0)
436                 key.b = key.r;
437         else
438                 key.b = kbtab[c];
439
440         if(scan->caps && key.r<='z' && key.r>='a')
441                 key.r += 'A' - 'a';
442
443         if(scan->ctl && scan->alt && key.r == Kdel){
444                 if(scan->shift)
445                         shiftup();
446                 else
447                         reboot();
448         }
449
450         if(key.b)
451                 send(keychan, &key);
452
453         switch(key.r){
454         case Kshift:
455                 scan->shift = key.down;
456                 break;
457         case Kctl:
458                 scan->ctl = key.down;
459                 break;
460         case Kaltgr:
461                 scan->altgr = key.down;
462                 break;
463         case Kmod4:
464                 scan->mod4 = key.down;
465                 break;
466         case Kalt:
467                 scan->alt = key.down;
468                 break;
469         case Knum:
470                 scan->num ^= key.down;
471                 break;
472         case Kcaps:
473                 scan->caps ^= key.down;
474                 break;
475         }
476         scan->esc1 = 0;
477 }
478
479 static void
480 kbdin(Scan *a, char *p, int n)
481 {
482         char *s;
483         Key k;
484         int i;
485
486         if(n > 0 && p[n-1] != 0){
487                 /*
488                  * old format as used by bitsy keyboard:
489                  * just a string of characters, no keyup
490                  * information.
491                  */
492                 s = emalloc9p(n+1);
493                 memmove(s, p, n);
494                 s[n] = 0;
495                 p = s;
496                 while(*p){
497                         p += chartorune(&k.r, p);
498                         if(k.r)
499                                 send(rawchan, &k.r);
500                 }
501                 free(s);
502                 return;
503         }
504 Nextmsg:
505         if(n < 2)
506                 return;
507         switch(p[0]){
508         case 'R':
509         case 'r':
510                 /* rune up/down */
511                 chartorune(&k.r, p+1);
512                 if(k.r == 0)
513                         break;
514                 k.b = 0;
515                 k.down = (p[0] == 'r');
516                 for(i=0; i<Nscan; i++){
517                         if(kbtab[i] == k.r || kbtabshift[i] == k.r || (i >= 16 && kbtabctl[i] == k.r)){
518                                 /* assign button from kbtab */
519                                 k.b = kbtab[i];
520                                 /* handle ^X forms */
521                                 if(k.r == kbtab[i] && kbtabctl[i] && !a->shift && !a->altgr && a->ctl)
522                                         k.r = kbtabctl[i];
523                                 break;
524                         }
525                 }
526                 /* button unknown to kbtab, use rune if no modifier keys are active */
527                 if(k.b == 0 && !a->shift && !a->altgr && !a->ctl)
528                         k.b = k.r;
529                 if(k.r == Kshift)
530                         a->shift = k.down;
531                 else if(k.r == Kaltgr)
532                         a->altgr = k.down;
533                 else if(k.r == Kmod4)
534                         a->mod4 = k.down;
535                 else if(k.r == Kctl)
536                         a->ctl = k.down;
537                 send(keychan, &k);
538                 break;
539
540         case 'c':
541                 chartorune(&k.r, p+1);
542                 nbsend(runechan, &k.r);
543                 break;
544
545         default:
546                 if(!kbdopen)
547                         break;
548                 i = strlen(p)+1;
549                 s = emalloc9p(i);
550                 memmove(s, p, i);
551                 if(nbsendp(kbdchan, s) <= 0)
552                         free(s);
553         }
554         i = strlen(p)+1;
555         n -= i, p += i;
556         goto Nextmsg;
557 }
558
559 void
560 setleds(Scan *scan, int leds)
561 {
562         char buf[8];
563
564         if(ledsfd < 0 || scan->leds == leds)
565                 return;
566         leds &= 7;
567         snprint(buf, sizeof(buf), "%d", leds);
568         pwrite(ledsfd, buf, strlen(buf), 0);
569         scan->leds = leds;
570 }
571
572 /*
573  * Read scan codes from scanfd
574  */ 
575 void
576 scanproc(void *)
577 {
578         uchar buf[64];
579         Scan scan;
580         int i, n;
581
582         threadsetname("scanproc");
583
584         memset(&scan, 0, sizeof scan);
585         while((n = read(scanfd, buf, sizeof buf)) > 0){
586                 for(i=0; i<n; i++)
587                         kbdputsc(&scan, buf[i]);
588                 setleds(&scan, (scan.num<<1) | (scan.caps<<2));
589         }
590
591         shutdown();
592 }
593
594 void
595 kbdiproc(void *)
596 {
597         char buf[1024];
598         Scan a;
599         int n;
600
601         threadsetname("kbdiproc");
602
603         memset(&a, 0, sizeof(a));
604         while((n = read(kbdifd, buf, sizeof buf)) > 0)
605                 kbdin(&a, buf, n);
606
607         shutdown();
608 }
609
610 char*
611 utfconv(Rune *r, int n)
612 {
613         char *s, *p;
614         int l;
615
616         l = runenlen(r, n) + 1;
617         s = emalloc9p(l);
618         for(p = s; n > 0; r++, n--)
619                 p += runetochar(p, r);
620         *p = 0;
621         return s;
622 }
623
624 /*
625  * Read key events from keychan and produce characters to
626  * rawchan and keystate in kbdchan.
627  */
628 void
629 keyproc(void *)
630 {
631         Rune rb[Nscan+1];
632         Key key;
633         int i, nb;
634         char *s;
635
636         threadsetname("keyproc");
637
638         nb = 0;
639         while(recv(keychan, &key) > 0){
640                 if(key.r >= Kmouse+1 && key.r <= Kmouse+5){
641                         if(msinfd >= 0)
642                                 send(mctlchan, &key);
643                         continue;
644                 }
645                 rb[0] = 0;
646                 if(key.b){
647                         for(i=0; i<nb && rb[i+1] != key.b; i++)
648                                 ;
649                         if(!key.down){
650                                 while(i < nb && rb[i+1] == key.b){
651                                         memmove(rb+i+1, rb+i+2, (nb-i+1) * sizeof(rb[0]));
652                                         nb--;
653                                         rb[0] = 'K';
654                                 }
655                         } else if(i == nb && nb < nelem(rb)-1 && key.b){
656                                 rb[++nb] = key.b;
657                                 rb[0] = 'k';
658                         }
659                 }
660                 if(rb[0]){
661                         if(kbdopen){
662                                 s = utfconv(rb, nb+1);
663                                 if(nbsendp(kbdchan, s) <= 0)
664                                         free(s);
665                         }
666                         if(mctlfd >= 0)
667                                 send(mctlchan, &key);
668                 }
669                 if(key.down && key.r)
670                         send(rawchan, &key.r);
671         }
672 }
673
674 /*
675  * Read characters from consfd (serial console)
676  */ 
677 void
678 consproc(void *)
679 {
680         char *p, *e, *x, buf[64];
681         int n, cr;
682         Rune r;
683
684         threadsetname("consproc");
685
686         cr = 0;
687         p = buf;
688         e = buf + sizeof(buf);
689         while((n = read(consfd, p, e - p)) > 0){
690                 x = p + n;
691                 p = buf;
692                 while((n = x - p) > 0){
693                         if(!fullrune(p, n)){
694                                 memmove(buf, p, n);
695                                 break;
696                         }
697                         p += chartorune(&r, p);
698                         if(r == 021 || r == 023)        /* XON/XOFF */
699                                 continue;
700                         if(r == 0 || r == Runeerror){
701                                 cr = 0;
702                                 continue;
703                         }
704                         if(r == '\n' && cr){
705                                 cr = 0;
706                                 continue;
707                         }
708                         if(cr = (r == '\r'))
709                                 r = '\n';
710                         send(runechan, &r);
711                 }
712                 if(n < 0) n = 0;
713                 p = buf + n;
714         }
715
716         shutdown();
717 }
718
719 static int
720 nextrune(Channel *ch, Rune *r)
721 {
722         while(recv(ch, r) > 0){
723                 switch(*r){
724                 case 0:
725                 case Kcaps:
726                 case Knum:
727                 case Kshift:
728                 case Kaltgr:
729                 case Kmod4:
730                         /* ignore modifiers */
731                         continue;
732
733                 case Kctl:
734                 case Kalt:
735                         /* composing escapes */
736                         return 1;
737                 }
738                 return 0;
739         }
740         return -1;
741 }
742
743 /*
744  * Read runes from rawchan, possibly compose special characters
745  * and output the new runes to runechan
746  */
747 void
748 runeproc(void *)
749 {
750         static struct {
751                 char    *ld;    /* must be seen before using this conversion */
752                 char    *si;    /* options for last input characters */
753                 Rune    *so;    /* the corresponding Rune for each si entry */
754         } tab[] = {
755 #include "latin1.h"
756         };
757         Rune r, rr;
758         int i, j;
759         int ctl;
760
761         threadsetname("runeproc");
762
763         ctl = 0;
764         while((i = nextrune(rawchan, &r)) >= 0){
765                 if(i == 0){
766                         ctl = 0;
767 Forward:
768                         send(runechan, &r);
769                         continue;
770                 }
771
772                 if(r == Kctl){
773                         ctl = 1;
774                         continue;
775                 }
776
777                 /*
778                  * emulators like qemu and vmware use Ctrl+Alt to lock
779                  * keyboard input so dont confuse them for a compose
780                  * sequence.
781                  */
782                 if(r != Kalt || ctl)
783                         continue;
784
785                 if(nextrune(rawchan, &r))
786                         continue;
787
788                 if(r == 'x' || r == 'X'){
789                         i = (r == 'X') ? 4 : 6;
790                         r = 0;
791                         do {
792                                 if(nextrune(rawchan, &rr))
793                                         break;
794                                 if(rr >= '0' && rr <= '9')
795                                         r = (r << 4) | (rr - '0');
796                                 else if(rr >= 'a' && rr <= 'f')
797                                         r = (r << 4) | (10 + (rr - 'a'));
798                                 else if(rr >= 'A' && rr <= 'F')
799                                         r = (r << 4) | (10 + (rr - 'A'));
800                                 else
801                                         break;
802                         } while(--i > 0);
803                         if((i == 0 || rr == ';') && r != 0 && r <= Runemax)
804                                 goto Forward;
805                 } else {
806                         if(nextrune(rawchan, &rr))
807                                 continue;
808                         for(i = 0; i<nelem(tab); i++){
809                                 if(tab[i].ld[0] != r)
810                                         continue;
811                                 if(tab[i].ld[1] == 0)
812                                         break;  
813                                 if(tab[i].ld[1] == rr){
814                                         nextrune(rawchan, &rr);
815                                         break;
816                                 }
817                         }
818                         if(i == nelem(tab) || rr == 0)
819                                 continue;
820                         for(j = 0; tab[i].si[j]; j++){
821                                 if(tab[i].si[j] != rr)
822                                         continue;
823                                 r = tab[i].so[j];
824                                 goto Forward;
825                         }
826                 }
827         }
828 }
829
830 /*
831  * Need to do this in a separate proc because if process we're interrupting
832  * is dying and trying to print tombstone, kernel is blocked holding p->debug lock.
833  */
834 void
835 intrproc(void *)
836 {
837         threadsetname("intrproc");
838
839         while(recv(intchan, nil) > 0)
840                 write(notefd, "interrupt", 9);
841 }
842
843 /*
844  * Process Kmouse keys and mouse button swap on shift,
845  * unblank screen by twiching.
846  */
847 void
848 mctlproc(void *)
849 {
850         Key key;
851         int i, mouseb = 0;
852
853         threadsetname("mctlproc");
854
855         for(;;){
856                 if(nbrecv(mctlchan, &key) <= 0){
857                         if(mctlfd >= 0)
858                                 fprint(mctlfd, "twitch");
859                         if(recv(mctlchan, &key) <= 0)
860                                 break;
861                 }
862
863                 if(mctlfd >= 0 && key.r == Kshift){
864                         if(key.down){
865                                 fprint(mctlfd, "buttonmap 132");
866                         } else {
867                                 fprint(mctlfd, "swap");
868                                 fprint(mctlfd, "swap");
869                         }
870                         continue;
871                 }
872
873                 if(msinfd >= 0 && key.r >= Kmouse+1 && key.r <= Kmouse+5){
874                         i = 1<<(key.r-(Kmouse+1));
875                         if(key.down)
876                                 mouseb |= i;
877                         else
878                                 mouseb &= ~i;
879                         fprint(msinfd, "m%11d %11d %11d", 0, 0, mouseb);
880                         continue;
881                 }
882         }
883 }
884
885 /*
886  * Cook lines for cons
887  */
888 void
889 lineproc(void *aux)
890 {
891         Rune rb[256], r;
892         Channel *cook;
893         int nr, done;
894         char *s;
895
896         cook = aux;
897
898         threadsetname("lineproc");
899
900         for(;;){
901                 nr = 0;
902                 done = 0;
903                 do {
904                         recv(cook, &r);
905                         switch(r){
906                         case Kdel:
907                                 if(nbsend(intchan, &notefd) <= 0)
908                                         continue;
909                                 /* no break */
910                         case '\0':      /* flush */
911                                 nr = 0;
912                                 continue;
913                         case Kbs:       /* ^H: erase character */
914                         case Knack:     /* ^U: erase line */
915                         case Ketb:      /* ^W: erase word */
916                                 while(nr > 0){
917                                         nr--;
918                                         fprint(1, "\b");
919                                         if(r == Kbs)
920                                                 break;
921                                         if(r == Ketb && utfrune(" \t", rb[nr]))
922                                                 break;
923                                 }
924                                 continue;
925                         case Keof:      /* ^D: eof */
926                                 done = 1;
927                                 break;
928                         case '\n':
929                                 done = 1;
930                                 /* no break */
931                         default:
932                                 rb[nr++] = r;
933                                 fprint(1, "%C", r);
934                         }
935                 } while(!done && nr < nelem(rb));
936                 s = utfconv(rb, nr);
937                 if(nbsendp(conschan, s) <= 0)
938                         free(s);
939         }
940 }
941
942 /*
943  * Reads Tread and Tflush requests from reqchan and responds
944  * to them with data received on the string channel.
945  */
946 void
947 reqproc(void *aux)
948 {
949         enum { AREQ, ASTR, AEND };
950         Alt a[AEND+1];
951         Channel **ac;
952         Req *r, *q, **qq;
953         char *s, *p, *e;
954         int n, m;
955
956         threadsetname("reqproc");
957
958         e = nil;
959         s = nil;
960         p = nil;
961
962         q = nil;
963         qq = &q;
964
965         ac = aux;
966         a[AREQ].op = CHANRCV;
967         a[AREQ].c = ac[0];      /* chan(Req*) */
968         a[AREQ].v = &r;
969
970         a[ASTR].c = ac[1];      /* chan(char*) */
971         a[ASTR].v = &s;
972
973         a[AEND].op = CHANEND;
974
975         for(;;){
976                 a[ASTR].op = s != nil ? CHANNOP : CHANRCV;
977
978                 switch(alt(a)){
979                 case AREQ:
980                         if(r->ifcall.type == Tflush){
981                                 Req **rr, **xx;
982
983                                 for(rr = &q; *rr; rr=xx){
984                                         xx = &((*rr)->aux);
985                                         if(*rr == r->oldreq){
986                                                 if((*rr = *xx) == nil)
987                                                         qq = rr;
988                                                 respond(r->oldreq, Eintr);
989                                                 break;
990                                         }
991                                 }
992                                 respond(r, nil);
993                                 continue;
994                         } else if(r->ifcall.type != Tread){
995                                 respond(r, Ephase);
996                                 continue;
997                         }
998                         r->aux = nil;
999                         *qq = r;
1000                         qq = &r->aux;
1001
1002                         if(0){
1003                 case ASTR:
1004                                 p = s;
1005                         }
1006
1007                         while(s != nil && q != nil){
1008                                 r = q;
1009                                 if((q = q->aux) == nil)
1010                                         qq = &q;
1011                                 r->ofcall.count = 0;
1012                                 if(s == p){
1013                                 More:
1014                                         e = s + strlen(s);
1015                                         if(r->fid->qid.path == Qkbd)
1016                                                 e++; /* send terminating \0 if its kbd file */
1017                                 }
1018                                 n = e - p;
1019                                 m = r->ifcall.count - r->ofcall.count;
1020                                 if(n > m){
1021                                         if(r->ofcall.count > 0){
1022                                                 respond(r, nil);
1023                                                 continue;
1024                                         }
1025                                         n = m;
1026                                 }
1027                                 memmove((char*)r->ofcall.data + r->ofcall.count, p, n);
1028                                 r->ofcall.count += n;
1029                                 p += n;
1030                                 if(p >= e){
1031                                         free(s);
1032                                         s = nbrecvp(a[ASTR].c);
1033                                         if(s != nil){
1034                                                 p = s;
1035                                                 goto More;
1036                                         }
1037                                 }
1038                                 respond(r, nil);
1039                         }
1040                 }
1041         }
1042 }
1043
1044 /*
1045  * Keep track of rawing state and distribute the runes from
1046  * runechan to the right channels depending on the state.
1047  */
1048 void
1049 ctlproc(void *)
1050 {
1051         Channel *cook, *aconsr[2], *akbdr[2];
1052         enum { ACTL, ARUNE, AEND };
1053         Alt a[AEND+1];
1054         Rune r;
1055         int c, raw;
1056         char *s;
1057
1058         threadsetname("ctlproc");
1059
1060         if(kbdifd >= 0)
1061                 proccreate(kbdiproc, nil, STACK);       /* kbdifd -> kbdin() */
1062         if(mctlfd >= 0 || msinfd >= 0)
1063                 proccreate(mctlproc, nil, STACK);       /* mctlchan -> mctlfd, msinfd */
1064         if(scanfd >= 0)
1065                 proccreate(scanproc, nil, STACK);       /* scanfd -> keychan */
1066         if(consfd >= 0)
1067                 proccreate(consproc, nil, STACK);       /* consfd -> runechan */
1068         if(notefd >= 0)
1069                 proccreate(intrproc, nil, STACK);       /* intchan -> notefd */
1070
1071         threadcreate(keyproc, nil, STACK);              /* keychan -> mctlchan, rawchan, kbdchan */
1072         threadcreate(runeproc, nil, STACK);             /* rawchan -> runechan */
1073
1074         aconsr[0] = consreqchan;
1075         aconsr[1] = conschan;
1076         threadcreate(reqproc, aconsr, STACK);           /* consreqchan,conschan -> respond */
1077
1078         akbdr[0] = kbdreqchan;
1079         akbdr[1] = kbdchan;
1080         threadcreate(reqproc, akbdr, STACK);            /* kbdreqchan,kbdchan -> respond */
1081
1082         cook = chancreate(sizeof(Rune), 0);
1083         threadcreate(lineproc, cook, STACK);            /* cook -> conschan */
1084
1085         raw = 0;
1086
1087         a[ACTL].c = ctlchan;
1088         a[ACTL].v = &c;
1089         a[ACTL].op = CHANRCV;
1090
1091         a[ARUNE].c = runechan;
1092         a[ARUNE].v = &r;
1093         a[ARUNE].op = CHANRCV;
1094
1095         a[AEND].op = CHANEND;
1096
1097         for(;;){
1098                 switch(alt(a)){
1099                 case ACTL:
1100                         switch(c){
1101                         case Rawoff:
1102                         case Rawon:
1103                                 if(raw = (c == Rawon)){
1104                                         r = 0;
1105                                         nbsend(cook, &r);
1106                                 }
1107                         }
1108                         break;
1109                 case ARUNE:
1110                         if(kbdopen){
1111                                 s = emalloc9p(UTFmax+2);
1112                                 s[0] = 'c';
1113                                 s[1+runetochar(s+1, &r)] = 0;
1114                                 if(nbsendp(kbdchan, s) <= 0)
1115                                         free(s);
1116                                 break;
1117                         }
1118                         if(raw){
1119                                 s = emalloc9p(UTFmax+1);
1120                                 s[runetochar(s, &r)] = 0;
1121                                 if(nbsendp(conschan, s) <= 0)
1122                                         free(s);
1123                                 break;
1124                         }
1125                         nbsend(cook, &r);
1126                         break;
1127                 }
1128         }
1129 }
1130
1131 /*
1132  * Keyboard layout maps
1133  */
1134
1135 Rune*
1136 kbmapent(int t, int sc)
1137 {
1138         static Rune *tabs[] = { 
1139         /* 0 */ kbtab,
1140         /* 1 */ kbtabshift,
1141         /* 2 */ kbtabesc1,
1142         /* 3 */ kbtabaltgr,
1143         /* 4 */ kbtabctl,
1144         /* 5 */ kbtabctrlesc1,
1145         /* 6 */ kbtabshiftesc1,
1146         /* 7 */ kbtabshiftaltgr,
1147         /* 8 */ kbtabmod4,
1148         /* 9 */ kbtabaltgrmod4,
1149         };
1150         if(t >= 0 && t < nelem(tabs) && sc >= 0 && sc < Nscan)
1151                 return &tabs[t][sc];
1152         return nil;
1153 }
1154
1155 void
1156 kbmapread(Req *req)
1157 {
1158         char tmp[3*12+1];
1159         int t, sc, soff, off, n;
1160         Rune *rp;
1161
1162         off = req->ifcall.offset/(sizeof(tmp)-1);
1163         soff = req->ifcall.offset%(sizeof(tmp)-1);
1164         t = off/Nscan;
1165         sc = off%Nscan;
1166         if(rp = kbmapent(t, sc)){
1167                 sprint(tmp, "%11d %11d %11d\n", t, sc, *rp);
1168                 n = strlen(&tmp[soff]);
1169                 if(req->ifcall.count < n)
1170                         n = req->ifcall.count;
1171                 req->ofcall.count = n;
1172                 memmove(req->ofcall.data, &tmp[soff], n);
1173         }else
1174                 req->ofcall.count = 0;
1175         respond(req, nil);
1176 }
1177
1178 Rune
1179 kbcompat(Rune r)
1180 {
1181         static Rune o = Spec|0x60, tab[] = {
1182                 Kshift, Kbreak, Kctl, Kalt,
1183                 Kcaps, Knum, Kmiddle, Kaltgr,
1184                 Kmod4,
1185         };
1186         if(r >= o && r < o+nelem(tab))
1187                 return tab[r - o];
1188         return r;
1189 }
1190
1191 void
1192 kbmapwrite(Req *req)
1193 {
1194         char line[100], *lp, *b;
1195         Rune r, *rp;
1196         int sc, t, l;
1197         Fid *f;
1198
1199         f = req->fid;
1200         b = req->ifcall.data;
1201         l = req->ifcall.count;
1202         lp = line;
1203         if(f->aux){
1204                 strcpy(line, f->aux);
1205                 lp = line+strlen(line);
1206                 free(f->aux);
1207                 f->aux = nil;
1208         }
1209         while(--l >= 0) {
1210                 *lp++  = *b++;
1211                 if(lp[-1] == '\n' || lp == &line[sizeof(line)-1]) {
1212                         *lp = 0;
1213                         if(*line == 0){
1214                         Badarg:
1215                                 respond(req, Ebadarg);
1216                                 return;
1217                         }
1218                         if(*line == '\n' || *line == '#'){
1219                                 lp = line;
1220                                 continue;
1221                         }
1222                         lp = line;
1223                         while(*lp == ' ' || *lp == '\t')
1224                                 lp++;
1225                         t = strtoul(line, &lp, 0);
1226                         sc = strtoul(lp, &lp, 0);
1227                         while(*lp == ' ' || *lp == '\t')
1228                                 lp++;
1229                         if((rp = kbmapent(t, sc)) == nil)
1230                                 goto Badarg;
1231                         r = 0;
1232                         if(*lp == '\'' && lp[1])
1233                                 chartorune(&r, lp+1);
1234                         else if(*lp == '^' && lp[1]){
1235                                 chartorune(&r, lp+1);
1236                                 if(0x40 <= r && r < 0x60)
1237                                         r -= 0x40;
1238                                 else
1239                                         goto Badarg;
1240                         }else if(*lp == 'M' && ('1' <= lp[1] && lp[1] <= '5'))
1241                                 r = Kmouse+lp[1]-'0';
1242                         else if(*lp>='0' && *lp<='9') /* includes 0x... */
1243                                 r = strtoul(lp, &lp, 0);
1244                         else
1245                                 goto Badarg;
1246                         *rp = kbcompat(r);
1247                         lp = line;
1248                 }
1249         }
1250         if(lp != line){
1251                 l = lp-line;
1252                 f->aux = lp = emalloc9p(l+1);
1253                 memmove(lp, line, l);
1254                 lp[l] = 0;
1255         }
1256         req->ofcall.count = req->ifcall.count;
1257         respond(req, nil);
1258 }
1259
1260 /*
1261  * Filesystem
1262  */
1263
1264 static int
1265 fillstat(ulong qid, Dir *d)
1266 {
1267         struct Qtab *t;
1268
1269         memset(d, 0, sizeof *d);
1270         d->uid = d->gid = user;
1271         d->muid = "";
1272         d->qid = (Qid){qid, 0, 0};
1273         d->atime = time(0);
1274         t = qtab + qid;
1275         d->name = t->name;
1276         d->qid.type = t->type;
1277         d->mode = t->mode;
1278         return 1;
1279 }
1280
1281 static void
1282 fsattach(Req *r)
1283 {
1284         char *spec;
1285
1286         spec = r->ifcall.aname;
1287         if(spec && spec[0]){
1288                 respond(r, Ebadspec);
1289                 return;
1290         }
1291         r->fid->qid = (Qid){Qroot, 0, QTDIR};
1292         r->ofcall.qid = r->fid->qid;
1293         respond(r, nil);
1294 }
1295
1296 static void
1297 fsstat(Req *r)
1298 {
1299         fillstat((ulong)r->fid->qid.path, &r->d);
1300         r->d.name = estrdup9p(r->d.name);
1301         r->d.uid = estrdup9p(r->d.uid);
1302         r->d.gid = estrdup9p(r->d.gid);
1303         r->d.muid = estrdup9p(r->d.muid);
1304         respond(r, nil);
1305 }
1306
1307 static char*
1308 fswalk1(Fid *fid, char *name, Qid *qid)
1309 {
1310         int i;
1311         ulong path;
1312
1313         path = fid->qid.path;
1314         switch(path){
1315         case Qroot:
1316                 if (strcmp(name, "..") == 0) {
1317                         *qid = (Qid){Qroot, 0, QTDIR};
1318                         fid->qid = *qid;
1319                         return nil;
1320                 }
1321                 for(i = fid->qid.path; i<Nqid; i++){
1322                         if(strcmp(name, qtab[i].name) != 0)
1323                                 continue;
1324                         *qid = (Qid){i, 0, 0};
1325                         fid->qid = *qid;
1326                         return nil;
1327                 }
1328                 return Enonexist;
1329                 
1330         default:
1331                 return Ewalk;
1332         }
1333 }
1334
1335 static void
1336 fsopen(Req *r)
1337 {
1338         Fid *f;
1339         static int need[4] = { 4, 2, 6, 1 };
1340         struct Qtab *t;
1341         int n;
1342
1343         f = r->fid;
1344         t = qtab + f->qid.path;
1345         n = need[r->ifcall.mode & 3]<<6;
1346         if((n & t->mode) != n)
1347                 respond(r, Eperm);
1348         else{
1349                 f->aux = nil;
1350                 switch((ulong)f->qid.path){
1351                 case Qkbd:
1352                         if(kbdopen){
1353                                 respond(r, Einuse);
1354                                 return;
1355                         }
1356                         kbdopen++;
1357                         break;
1358                 case Qconsctl:
1359                         consctlopen++;
1360                         break;
1361                 }
1362                 respond(r, nil);
1363         }
1364 }
1365
1366 static int
1367 readtopdir(Fid*, uchar *buf, long off, int cnt, int blen)
1368 {
1369         int i, m, n;
1370         long pos;
1371         Dir d;
1372
1373         n = 0;
1374         pos = 0;
1375         for (i = 1; i < Nqid; i++){
1376                 fillstat(i, &d);
1377                 m = convD2M(&d, &buf[n], blen-n);
1378                 if(off <= pos){
1379                         if(m <= BIT16SZ || m > cnt)
1380                                 break;
1381                         n += m;
1382                         cnt -= m;
1383                 }
1384                 pos += m;
1385         }
1386         return n;
1387 }
1388
1389 static void
1390 fsread(Req *r)
1391 {
1392         Fid *f;
1393
1394         f = r->fid;
1395         switch((ulong)f->qid.path){
1396         default:
1397                 respond(r, Ephase);
1398                 return;
1399         case Qroot:
1400                 r->ofcall.count = readtopdir(f, (void*)r->ofcall.data, r->ifcall.offset,
1401                         r->ifcall.count, r->ifcall.count);
1402                 break;
1403         case Qkbd:
1404                 sendp(kbdreqchan, r);
1405                 return;
1406         case Qcons:
1407                 sendp(consreqchan, r);
1408                 return;
1409         case Qkbmap:
1410                 kbmapread(r);
1411                 return;
1412         }
1413         respond(r, nil);
1414 }
1415
1416 static void
1417 fswrite(Req *r)
1418 {
1419         Fid *f;
1420         char *p;
1421         int n, i;
1422
1423         f = r->fid;
1424         p = r->ifcall.data;
1425         n = r->ifcall.count;
1426         switch((ulong)f->qid.path){
1427         default:
1428                 respond(r, Ephase);
1429                 return;
1430
1431         case Qcons:
1432                 if(write(1, p, n) != n){
1433                         responderror(r);
1434                         return;
1435                 }
1436                 break;
1437
1438         case Qconsctl:
1439                 if(n >= 5 && memcmp(p, "rawon", 5) == 0)
1440                         sendul(ctlchan, Rawon);
1441                 else if(n >= 6 && memcmp(p, "rawoff", 6) == 0)
1442                         sendul(ctlchan, Rawoff);
1443                 else {
1444                         respond(r, Ebadarg);
1445                         return;
1446                 }
1447                 break;
1448
1449         case Qkbdin:
1450         case Qkbin:
1451                 if(f->aux == nil){
1452                         f->aux = emalloc9p(sizeof(Scan));
1453                         memset(f->aux, 0, sizeof(Scan));
1454                 }
1455                 if(f->qid.path == Qkbin){
1456                         for(i=0; i<n; i++)
1457                                 kbdputsc((Scan*)f->aux, (uchar)p[i]);
1458                 } else {
1459                         kbdin((Scan*)f->aux, p, n);
1460                 }
1461                 break;
1462
1463         case Qkbmap:
1464                 kbmapwrite(r);
1465                 return;
1466
1467         }
1468         r->ofcall.count = n;
1469         respond(r, nil);
1470 }
1471
1472 static void
1473 fsflush(Req *r)
1474 {
1475         switch((ulong)r->oldreq->fid->qid.path) {
1476         case Qkbd:
1477                 sendp(kbdreqchan, r);
1478                 return;
1479         case Qcons:
1480                 sendp(consreqchan, r);
1481                 return;
1482         }
1483         respond(r, nil);
1484 }
1485
1486 static void
1487 fsdestroyfid(Fid *f)
1488 {
1489         void *p;
1490
1491         if(f->omode != -1)
1492                 switch((ulong)f->qid.path){
1493                 case Qkbdin:
1494                 case Qkbin:
1495                 case Qkbmap:
1496                         if(p = f->aux){
1497                                 f->aux = nil;
1498                                 free(p);
1499                         }
1500                         break;
1501                 case Qkbd:
1502                         kbdopen--;
1503                         break;
1504                 case Qconsctl:
1505                         if(--consctlopen == 0)
1506                                 sendul(ctlchan, Rawoff);
1507                         break;
1508                 }
1509 }
1510
1511 static int
1512 procopen(int pid, char *name, int mode)
1513 {
1514         char buf[128];
1515
1516         snprint(buf, sizeof(buf), "/proc/%d/%s", pid, name);
1517         return eopen(buf, mode);
1518 }
1519
1520 static void
1521 elevate(void)
1522 {
1523         Dir *d, nd;
1524         int fd;
1525
1526         if(debug)
1527                 return;
1528
1529         if((fd = procopen(getpid(), "ctl", OWRITE)) < 0)
1530                 return;
1531
1532         /* get higher than normal priority */
1533         fprint(fd, "pri 16\n");
1534
1535         /* always present in physical memory */
1536         fprint(fd, "noswap\n");
1537
1538         /* dont let anybody kill us */
1539         if(d = dirfstat(fd)){
1540                 nulldir(&nd);
1541                 nd.mode = d->mode & ~0222;
1542                 dirfwstat(fd, &nd);
1543                 free(d);
1544         }
1545
1546         close(fd);
1547 }
1548
1549 static void
1550 fsstart(Srv*)
1551 {
1552         killfd = procopen(getpid(), "notepg", OWRITE);
1553         elevate();
1554         proccreate(ctlproc, nil, STACK);
1555 }
1556
1557 static void
1558 fsend(Srv*)
1559 {
1560         shutdown();
1561 }
1562
1563 Srv fs = {
1564         .start=                 fsstart,
1565         .attach=                fsattach,
1566         .walk1=                 fswalk1,
1567         .open=                  fsopen,
1568         .read=                  fsread,
1569         .write=                 fswrite,
1570         .stat=                  fsstat,
1571         .flush=                 fsflush,
1572         .destroyfid=            fsdestroyfid,
1573         .end=                   fsend,
1574 };
1575
1576 void
1577 usage(void)
1578 {
1579         fprint(2, "usage: %s [ -qdD ] [ -s sname ] [ -m mntpnt ] [ file ]\n", argv0);
1580         exits("usage");
1581 }
1582
1583 void
1584 threadmain(int argc, char** argv)
1585 {
1586         ARGBEGIN{
1587         case 'd':
1588                 debug++;
1589                 break;
1590         case 'D':
1591                 chatty9p++;
1592                 break;
1593         case 's':
1594                 sname = EARGF(usage());
1595                 break;
1596         case 'm':
1597                 mntpt = EARGF(usage());
1598                 break;
1599         case 'q':
1600                 quiet++;
1601                 break;
1602         default:
1603                 usage();
1604         }ARGEND
1605
1606         if(*argv)
1607                 consfd = eopen(*argv, OREAD);
1608
1609         kbdifd = open(dev("kbd"), OREAD);
1610         if(kbdifd < 0){
1611                 scanfd = eopen(dev("scancode"), OREAD);
1612                 ledsfd = eopen(dev("leds"), OWRITE);
1613         }
1614         mctlfd = eopen(dev("mousectl"), OWRITE);
1615         msinfd = eopen(dev("mousein"), OWRITE);
1616
1617         notefd = procopen(getpid(), "notepg", OWRITE);
1618
1619         consreqchan = chancreate(sizeof(Req*), 0);
1620         kbdreqchan = chancreate(sizeof(Req*), 0);
1621
1622         keychan = chancreate(sizeof(Key), 64);
1623         mctlchan = chancreate(sizeof(Key), 64);
1624         ctlchan = chancreate(sizeof(int), 0);
1625         rawchan = chancreate(sizeof(Rune), 0);
1626         runechan = chancreate(sizeof(Rune), 256);
1627         conschan = chancreate(sizeof(char*), 128);
1628         kbdchan = chancreate(sizeof(char*), 128);
1629         intchan = chancreate(sizeof(int), 0);
1630
1631         user = getuser();
1632         threadpostmountsrv(&fs, sname, mntpt, MBEFORE);
1633         threadexits(0);
1634 }