#include <9pm/windows.h> #include <9pm/u.h> #include <9pm/libc.h> int debug; int _dontforkconsole = 1; int fd[3]; HANDLE h[3]; int tab[] = { STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE, }; /* * It appears that win NT 4.0 has a bug in ReadConsole * If ReadConsole is called with a buffer that is smaller than * the input that is buffered, it appears that readconsoles buffer * can get corrupted by WriteConsole * i.e * char buf[3]; * int n2; * * for(;;) { * if(!ReadConsole(h, buf, sizeof(buf), &n2, 0)) * exit(0); * if(!WriteConsole(h2, buf, n2, &n2, 0)) * exit(0); * * Sleep(100); * } * */ static void consoleread(HANDLE h, int fd) { int n2, i; Rune r, rbuf[200]; char err[ERRMAX]; char *p; uchar buf[200*UTFmax]; for(;;){ if(!ReadConsole(h, rbuf, nelem(rbuf), &n2, 0)){ if(debug){ osrerrstr(err, sizeof err); pm_dprint(~0, "ReadConsole: %s\n", err); } break; } if(n2 == 0) continue; for(i=0,p=buf; i0) { buf[i] = *p; i++; p++; n--; if(fullrune(buf, i)) { nbuf = 0; chartorune(buf2, buf); if(!WriteConsole(h, buf2, 1, &n, 0)){ if(debug){ osrerrstr(err, sizeof err); pm_dprint(~0, "WriteConsole1: %s\n", err); } close(fd); return; } break; } } } while(n >= UTFmax || fullrune(p, n)) { n2 = nelem(buf2); q = buf2; while(n2) { if(n < UTFmax && !fullrune(p, n)) break; i = chartorune(q, p); p += i; n -= i; n2--; q++; } if(!WriteConsole(h, buf2, q-buf2, &n2, 0)) { if(debug){ osrerrstr(err, sizeof err); pm_dprint(~0, "WriteConsole2: %s\n", err); } close(fd); return; } } if(n != 0) { assert(n+nbuf < UTFmax); memmove(buf+nbuf, p, n); nbuf += n; } } close(fd); CloseHandle(h); } void dispatch(void *a) { switch((int)a){ case 0: consoleread(h[0], fd[0]); break; case 1: consolewrite(fd[1], h[1]); break; case 2: consolewrite(fd[2], h[2]); break; default: pm_dprint(~0, "dispatch %d?\n", (int)a); } } void watchproc(void *a) { WaitForSingleObject(a, INFINITE); ExitProcess(0); } void main(int argc, char **argv) { char buf[ERRMAX]; int i, pid, p[2], test; HANDLE hproc; test = 0; ARGBEGIN{ case 'd': debug = 1; break; case 't': test = 1; pipe(p); break; }ARGEND if(argc != 3 && argc != 4){ pm_dwrite("usage: console [-t] fd0 fd1 fd2 [processid]\n"); exits("usage"); } if(argc==4){ pid = atoi(argv[3]); hproc = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); if(hproc == nil){ osrerrstr(buf, sizeof buf); pm_dprint(~0, "OpenProcess: %s\n", buf); exits("OpenProcess"); } ffork(0, watchproc, hproc, 8192); } for(i=0; i<3; i++){ if(test && i<2) fd[i] = p[i]; else fd[i] = atoi(argv[i]); if(fd[i] != -1){ h[i] = GetStdHandle(tab[i]); if(h[i]!=INVALID_HANDLE_VALUE && h[i]!=nil) ffork(0, dispatch, (void*)i, 8192); } } _exits(0); }