#include "paint.h" static int mainerr; extern void (*_sysfatal)(char*, va_list); /* write sysfatal messages to the main window, instead of to a log window which is about to disappear */ void _paintfatal(char *fmt, va_list args) { char buf[1024]; vseprint(buf, buf + sizeof(buf), fmt, args); if(argv0) fprint(mainerr, "%s: %s\n", argv0, buf); else fprint(mainerr, "%s\n", buf); threadexitsall(buf); } static void copyproc(void *arg) { int in; uchar buf[1024]; int n; threadsetname("copy"); in = *(int *)arg; while((n = read(in, buf, sizeof buf)) > 0) { if(write(1, buf, n) != n) sysfatal("log: copy write: %r"); } if(n < 0) sysfatal("log: copy read: %r"); } static void stampproc(void *argvp) { void **argv; int *inp, *outp; threadsetname("stamp"); argv = argvp; inp = argv[0]; outp = argv[1]; close(inp[1]); close(outp[0]); if(dup(inp[0], 0) < 0 || dup(outp[1], 1) < 0) sysfatal("log: dup: %r"); procexecl(nil, "/bin/stamp", "stamp", "iso", nil); procexecl(nil, "/bin/aux/clog", "aux/clog", "/fd/0", "/fd/1", nil); procexecl(nil, "/bin/cat", "cat", nil); sysfatal("log: exec: %r"); } /* -> lp[1] -> lp[0] -> logproc -> sp[1] -> sp[0] -> stampproc -> cp[1] -> cp[0] -> copyproc -> /dev/cons */ static void logproc(void *arg) { int lp[2], sp[2], cp[2], cons, wctl, label; void *stampargv[2]; int opened; uchar buf[1024]; int n; threadsetname("log"); lp[0] = ((int *)arg)[0]; lp[1] = ((int *)arg)[1]; close(lp[1]); if(pipe(sp) < 0 || pipe(cp) < 0) sysfatal("log: pipe 2: %r"); stampargv[0] = sp; stampargv[1] = cp; procrfork(stampproc, stampargv, 1024, RFFDG|RFNAMEG|RFENVG); proccreate(copyproc, &cp[0], 4*1024); close(cp[1]); opened = 0; SET(cons); SET(wctl); while((n = read(lp[0], buf, sizeof buf)) >= 0) { /* if the window has never been opened or has been closed */ if(opened == 0 || read(label, &label, 0) < 0) { if(opened) { close(cons); close(wctl); close(label); } opened = 1; if(newwindow("-hide -scroll") < 0) sysfatal("log: newwindow: %r"); if((cons = open("/dev/cons", OWRITE)) < 0) sysfatal("log: open /dev/cons: %r"); if((wctl = open("/dev/wctl", OWRITE)) < 0) sysfatal("log: open /dev/wctl: %r"); if((label = open("/dev/label", ORDWR)) < 0) sysfatal("log: open /dev/label: %r"); if(fprint(label, "%s errors", argv0) < 0) sysfatal("log: write label: %r"); /* replace copyproc's stdout */ if(dup(cons, 1) < 0) sysfatal("log: dup: %r"); } fprint(wctl, "unhide"); write(sp[1], buf, n); } sysfatal("log: read: %r"); } void logproccreate(void) { int p[2]; if((mainerr = dup(2, -1)) < 0) sysfatal("log: dup mainerr: %r"); if(pipe(p) < 0) sysfatal("log: pipe 1: %r"); procrfork(logproc, p, 8*1024, RFFDG|RFNAMEG|RFENVG); /* errors from logproc will continue writing to the main window */ _sysfatal = _paintfatal; if(dup(p[1], 2) < 0) sysfatal("log: dup 2: %r"); close(p[0]); close(p[1]); }