shithub: cflood

ref: b503317e6c71100ce331e24715d8cc538781840b
dir: /kbd/kbdbind.c/

View raw version
#include <u.h>
#include <libc.h>

enum {
	NumF = 12
};

static char *funcs[NumF];

void main(int, char**) {
	funcs[0] = "Fi";
	funcs[1] = "Ru";
	funcs[2] = "window";

	int in = open("/dev/kbd", OREAD);
	if(in < 0)
		sysfatal("open failed: %r");

	int p[2];
	pipe(p);
	int fd = create("/srv/kbdbind", OWRITE, 0600);
	if(fd < 0)
		sysfatal("create failed: %r");
	fprint(fd, "%d", p[0]);
	close(fd);
	close(p[0]);
	int out = p[1];

	for(;;) {
		uchar b[128];
		long size = read(in, b, sizeof(b));

		if(size < 0)
			break;
		for(long i = 0; i < size;) {
			int isfunc =
				size >= 5 &&
				(b[i] == 'k' || b[i] == 'c') &&
				b[i+1] == 0xef &&
				b[i+2] == 0x80 &&
				(b[i+3] >= 0x81 && b[i+3] <= (0x81+NumF));
			int funcid = isfunc ? b[i+3] - 0x81 : -1;

			if(funcid < 0 || funcs[funcid] == nil) {
				int k = i;
				for(; i < size; i++) {
					if(!b[i]) {
						i++;
						break;
					}
				}
				if(i - k > 0) {
					write(out, &b[k], i - k);
				}
			} else {
				int down = b[i] == 'k';
				i += 5;
				if(!down)
					continue;
				switch(rfork(RFFDG|RFREND|RFPROC|RFNOWAIT)) {
				case 0:
					if(execl("/bin/rc", "/bin/rc", funcs[funcid], 0) < 0)
						fprint(2, "execl failed: %r");
					break;
				case -1:
					fprint(2, "rfork failed: %r");
					break;
				}
			}
		}
	}
}