ref: ec35f468e0eba87c9f09cbbe5fa8af2591e6f914
dir: /appl/cmd/tee.b/
implement Tee; include "sys.m"; sys: Sys; include "draw.m"; include "arg.m"; Tee: module { init: fn(nil: ref Draw->Context, nil: list of string); }; File: adt { fd: ref Sys->FD; name: string; }; usage() { sys->fprint(sys->fildes(2), "Usage: tee [-a] [file ...]\n"); raise "fail:usage"; } init(nil: ref Draw->Context, args: list of string) { sys = load Sys Sys->PATH; arg := load Arg Arg->PATH; if(arg == nil) err(sys->sprint("can't load %s: %r", Arg->PATH)); append := 0; arg->init(args); while((c := arg->opt()) != 0) case c { 'a' => append = 1; * => usage(); } names := arg->argv(); arg = nil; fd0 := sys->fildes(0); if(fd0 == nil) err("no standard input"); nf := 0; files := array[len names + 1] of ref File; for(; names != nil; names = tl names){ f := hd names; fd: ref Sys->FD; if(append){ fd = sys->open(f, Sys->OWRITE); if(fd != nil) sys->seek(fd, big 0, 2); else fd = sys->create(f, Sys->OWRITE, 8r666); }else fd = sys->create(f, Sys->OWRITE, 8r666 ); if(fd == nil) err(sys->sprint("cannot open %s: %r", f)); files[nf++] = ref File(fd, f); } files[nf++] = ref File(sys->fildes(1), "standard output"); buf := array[Sys->ATOMICIO] of byte; while((n := sys->read(fd0, buf, len buf)) > 0){ for(i := 0; i < nf; i++) if(sys->write(files[i].fd, buf, n) != n) err(sys->sprint("error writing %s: %r", files[i].name)); } if(n < 0) err(sys->sprint("read error: %r")); } err(s: string) { sys->fprint(sys->fildes(2), "tee: %s\n", s); raise "fail:error"; }