diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /appl/cmd/tee.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/cmd/tee.b')
| -rw-r--r-- | appl/cmd/tee.b | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/appl/cmd/tee.b b/appl/cmd/tee.b new file mode 100644 index 00000000..a555487c --- /dev/null +++ b/appl/cmd/tee.b @@ -0,0 +1,79 @@ +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"; +} |
