xref: /inferno-os/appl/cmd/tee.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement Tee;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth	sys: Sys;
5*37da2899SCharles.Forsyth
6*37da2899SCharles.Forsythinclude "draw.m";
7*37da2899SCharles.Forsyth
8*37da2899SCharles.Forsythinclude "arg.m";
9*37da2899SCharles.Forsyth
10*37da2899SCharles.ForsythTee: module
11*37da2899SCharles.Forsyth{
12*37da2899SCharles.Forsyth	init:	fn(nil: ref Draw->Context, nil: list of string);
13*37da2899SCharles.Forsyth};
14*37da2899SCharles.Forsyth
15*37da2899SCharles.ForsythFile: adt
16*37da2899SCharles.Forsyth{
17*37da2899SCharles.Forsyth	fd:	ref Sys->FD;
18*37da2899SCharles.Forsyth	name:	string;
19*37da2899SCharles.Forsyth};
20*37da2899SCharles.Forsyth
21*37da2899SCharles.Forsythusage()
22*37da2899SCharles.Forsyth{
23*37da2899SCharles.Forsyth	sys->fprint(sys->fildes(2), "Usage: tee [-a] [file ...]\n");
24*37da2899SCharles.Forsyth	raise "fail:usage";
25*37da2899SCharles.Forsyth}
26*37da2899SCharles.Forsyth
27*37da2899SCharles.Forsythinit(nil: ref Draw->Context, args: list of string)
28*37da2899SCharles.Forsyth{
29*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
30*37da2899SCharles.Forsyth	arg := load Arg Arg->PATH;
31*37da2899SCharles.Forsyth	if(arg == nil)
32*37da2899SCharles.Forsyth		err(sys->sprint("can't load %s: %r", Arg->PATH));
33*37da2899SCharles.Forsyth
34*37da2899SCharles.Forsyth	append := 0;
35*37da2899SCharles.Forsyth	arg->init(args);
36*37da2899SCharles.Forsyth	while((c := arg->opt()) != 0)
37*37da2899SCharles.Forsyth		case c {
38*37da2899SCharles.Forsyth		'a' =>	append = 1;
39*37da2899SCharles.Forsyth		* =>		usage();
40*37da2899SCharles.Forsyth		}
41*37da2899SCharles.Forsyth	names := arg->argv();
42*37da2899SCharles.Forsyth	arg = nil;
43*37da2899SCharles.Forsyth
44*37da2899SCharles.Forsyth	fd0 := sys->fildes(0);
45*37da2899SCharles.Forsyth	if(fd0 == nil)
46*37da2899SCharles.Forsyth		err("no standard input");
47*37da2899SCharles.Forsyth	nf := 0;
48*37da2899SCharles.Forsyth	files := array[len names + 1] of ref File;
49*37da2899SCharles.Forsyth	for(; names != nil; names = tl names){
50*37da2899SCharles.Forsyth		f := hd names;
51*37da2899SCharles.Forsyth		fd: ref Sys->FD;
52*37da2899SCharles.Forsyth		if(append){
53*37da2899SCharles.Forsyth			fd = sys->open(f, Sys->OWRITE);
54*37da2899SCharles.Forsyth			if(fd != nil)
55*37da2899SCharles.Forsyth				sys->seek(fd, big 0, 2);
56*37da2899SCharles.Forsyth			else
57*37da2899SCharles.Forsyth				fd = sys->create(f, Sys->OWRITE, 8r666);
58*37da2899SCharles.Forsyth		}else
59*37da2899SCharles.Forsyth			fd = sys->create(f, Sys->OWRITE, 8r666 );
60*37da2899SCharles.Forsyth		if(fd == nil)
61*37da2899SCharles.Forsyth			err(sys->sprint("cannot open %s: %r", f));
62*37da2899SCharles.Forsyth		files[nf++] = ref File(fd, f);
63*37da2899SCharles.Forsyth	}
64*37da2899SCharles.Forsyth	files[nf++] = ref File(sys->fildes(1), "standard output");
65*37da2899SCharles.Forsyth	buf := array[Sys->ATOMICIO] of byte;
66*37da2899SCharles.Forsyth	while((n := sys->read(fd0, buf, len buf)) > 0){
67*37da2899SCharles.Forsyth		for(i := 0; i < nf; i++)
68*37da2899SCharles.Forsyth			if(sys->write(files[i].fd, buf, n) != n)
69*37da2899SCharles.Forsyth				err(sys->sprint("error writing %s: %r", files[i].name));
70*37da2899SCharles.Forsyth	}
71*37da2899SCharles.Forsyth	if(n < 0)
72*37da2899SCharles.Forsyth		err(sys->sprint("read error: %r"));
73*37da2899SCharles.Forsyth}
74*37da2899SCharles.Forsyth
75*37da2899SCharles.Forsytherr(s: string)
76*37da2899SCharles.Forsyth{
77*37da2899SCharles.Forsyth	sys->fprint(sys->fildes(2), "tee: %s\n", s);
78*37da2899SCharles.Forsyth	raise "fail:error";
79*37da2899SCharles.Forsyth}
80