1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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";
}
|