diff options
Diffstat (limited to 'appl/alphabet/reports.b')
| -rw-r--r-- | appl/alphabet/reports.b | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/appl/alphabet/reports.b b/appl/alphabet/reports.b new file mode 100644 index 00000000..d9336d8b --- /dev/null +++ b/appl/alphabet/reports.b @@ -0,0 +1,189 @@ +implement Reports; +include "sys.m"; + sys: Sys; +include "draw.m"; +include "sh.m"; +include "alphabet/reports.m"; + +Reporter: adt { + id: int; + name: string; + stopc: chan of int; +}; + +reportproc(errorc: chan of string, stopc: chan of int, reply: chan of ref Report) +{ + if(sys == nil) + sys = load Sys Sys->PATH; + r := ref Report(chan of (string, chan of string, chan of int), chan of int); + if(stopc == nil) + stopc = chan of int; + else + sys->pctl(Sys->NEWPGRP, nil); + reply <-= r; + reportproc0(stopc, errorc, r.startc, r.enablec); +} + +Report.start(r: self ref Report, name: string): chan of string +{ + if(r == nil) + return nil; + errorc := chan of string; + r.startc <-= (name, errorc, nil); + return errorc; +} + +Report.add(r: self ref Report, name: string, errorc: chan of string, stopc: chan of int) +{ + r.startc <-= (name, errorc, stopc); +} + +Report.enable(r: self ref Report) +{ + r.enablec <-= 0; +} + +reportproc0( + stopc: chan of int, + reportc: chan of string, + startc: chan of (string, chan of string, chan of int), + enablec: chan of int + ) +{ + realc := array[2] of chan of string; + p := array[len realc] of Reporter; + a := array[0] of chan of string; + id := n := 0; + stopped := 0; +out: + for(;;) alt{ + <-stopc => + stopped = 1; + break out; + (prefix, c, stop) := <-startc => + if(n == len realc){ + if(realc == a) + a = nil; + realc = (array[n * 2] of chan of string)[0:] = realc; + p = (array[n * 2] of Reporter)[0:] = p; + if(a == nil) + a = realc; + } + realc[n] = c; + p[n] = (id++, prefix, stop); + n++; + <-enablec => + if(n == 0) + break out; + a = realc; + (x, msg) := <-a => + if(msg == nil){ + if(--n == 0) + break out; + if(n != x){ + a[x] = a[n]; + a[n] = nil; + p[x] = p[n]; + p[n] = (-1, nil, nil); + } + }else{ + if(reportc != nil){ + alt{ + reportc <-= sys->sprint("%d. %s: %s", p[x].id, p[x].name, msg) => + ; + <-stopc => + stopped = 1; + break out; + } + } + } + } + if(stopped == 0){ + if(reportc != nil){ + alt{ + reportc <-= nil => + ; + <-stopc => + stopped = 1; + } + } + } + if(stopped){ + for(i := 0; i < n; i++) + note(p[i].stopc); + note(stopc); + } +} + +quit(errorc: chan of string) +{ + if(errorc != nil) + errorc <-= nil; + exit; +} + +report(errorc: chan of string, err: string) +{ + if(errorc != nil) + errorc <-= err; +} + +newpgrp(stopc: chan of int, flags: int): chan of int +{ + if(sys == nil) + sys = load Sys Sys->PATH; + if(flags&PROPAGATE){ + if(stopc == nil) + stopc = chan[1] of int; + sys->pipe(p := array[2] of ref Sys->FD); + spawn deadman(p[1]); + sys->pctl(Sys->NEWPGRP, nil); + spawn watchproc(p[0], stopc); + }else + sys->pctl(Sys->NEWPGRP, nil); + spawn grpproc(stopc, newstopc := chan[1] of int, flags&KILL); + return newstopc; +} + +grpproc(noteparent, noteself: chan of int, kill: int) +{ + if(noteparent == nil) + noteparent = chan of int; + alt{ + <-noteparent => + note(noteparent); + <-noteself => + ; + } + note(noteself); + if(kill){ + pid := sys->pctl(0, nil); + fd := sys->open("#p/"+string pid+"/ctl", Sys->OWRITE); + if(fd == nil) + fd = sys->open("/prog/"+string pid+"/ctl", Sys->OWRITE); + sys->fprint(fd, "killgrp"); + } +} + +note(c: chan of int) +{ + if(c != nil){ + alt { + c <-= 1 => + ; + * => + ; + } + } +} + +deadman(nil: ref Sys->FD) +{ + <-chan of int; +} + +watchproc(fd: ref Sys->FD, stopc: chan of int) +{ + sys->read(fd, array[1] of byte, 1); + note(stopc); +} |
