xref: /inferno-os/appl/tiny/broke.b (revision 28272a0014d067c3b39985261782b42f361449d3)
1implement Broke;
2
3include "sys.m";
4	sys: Sys;
5include "draw.m";
6
7Broke: module
8{
9	init:	fn(nil: ref Draw->Context, args: list of string);
10};
11
12init(nil: ref Draw->Context, nil: list of string)
13{
14	sys = load Sys Sys->PATH;
15	fd := sys->open("/prog", Sys->OREAD);
16	if(fd == nil)
17		err(sys->sprint("can't open /prog: %r"));
18	killed := "";
19	for(;;){
20		(n, dir) := sys->dirread(fd);
21		if(n <= 0){
22			if(n < 0)
23				err(sys->sprint("error reading /prog: %r"));
24			break;
25		}
26		for(i := 0; i < n; i++)
27			if(isbroken(dir[i].name) && kill(dir[i].name))
28				killed += sys->sprint(" %s", dir[i].name);
29	}
30	if(killed != nil)
31		sys->print("%s\n", killed);
32}
33
34isbroken(pid: string): int
35{
36	statf := "/prog/" + pid + "/status";
37	fd := sys->open(statf, Sys->OREAD);
38	if (fd == nil)
39		return 0;
40	buf := array[256] of byte;
41	n := sys->read(fd, buf, len buf);
42	if (n < 0) {	# process died or is exiting
43		# sys->fprint(stderr(), "broke: can't read %s: %r\n", statf);
44		return 0;
45	}
46	(nf, l) := sys->tokenize(string buf[0:n], " ");
47	return nf >= 5 && hd tl tl tl tl l == "broken";
48}
49
50kill(pid: string): int
51{
52	ctl := "/prog/" + pid + "/ctl";
53	fd := sys->open(ctl, sys->OWRITE);
54	if(fd == nil || sys->fprint(fd, "kill") < 0){
55		sys->fprint(stderr(), "broke: can't kill %s: %r\n", pid);	# but press on
56		return 0;
57	}
58	return 1;
59}
60
61err(s: string)
62{
63	sys->fprint(sys->fildes(2), "broke: %s\n", s);
64	raise "fail:error";
65}
66
67stderr(): ref Sys->FD
68{
69	return sys->fildes(2);
70}
71