xref: /inferno-os/appl/cmd/kill.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement Kill;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth	sys: Sys;
5*37da2899SCharles.Forsythinclude "draw.m";
6*37da2899SCharles.Forsythinclude "arg.m";
7*37da2899SCharles.Forsyth
8*37da2899SCharles.ForsythKill: module {
9*37da2899SCharles.Forsyth	init: fn(nil: ref Draw->Context, args: list of string);
10*37da2899SCharles.Forsyth};
11*37da2899SCharles.Forsyth
12*37da2899SCharles.Forsythstderr: ref Sys->FD;
13*37da2899SCharles.Forsyth
14*37da2899SCharles.Forsythusage()
15*37da2899SCharles.Forsyth{
16*37da2899SCharles.Forsyth	sys->fprint(stderr, "usage: kill [-g] pid|module [...]\n");
17*37da2899SCharles.Forsyth	raise "fail: usage";
18*37da2899SCharles.Forsyth}
19*37da2899SCharles.Forsyth
20*37da2899SCharles.Forsythinit(nil: ref Draw->Context, args: list of string)
21*37da2899SCharles.Forsyth{
22*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
23*37da2899SCharles.Forsyth	stderr = sys->fildes(2);
24*37da2899SCharles.Forsyth
25*37da2899SCharles.Forsyth	arg := load Arg Arg->PATH;
26*37da2899SCharles.Forsyth	if(arg == nil){
27*37da2899SCharles.Forsyth		sys->fprint(stderr, "kill: cannot load %s: %r\n", Arg->PATH);
28*37da2899SCharles.Forsyth		raise "fail:load";
29*37da2899SCharles.Forsyth	}
30*37da2899SCharles.Forsyth
31*37da2899SCharles.Forsyth	msg := array of byte "kill";
32*37da2899SCharles.Forsyth	arg->init(args);
33*37da2899SCharles.Forsyth	while((o := arg->opt()) != 0)
34*37da2899SCharles.Forsyth		case o {
35*37da2899SCharles.Forsyth		'g' =>
36*37da2899SCharles.Forsyth			msg = array of byte "killgrp";
37*37da2899SCharles.Forsyth		* =>
38*37da2899SCharles.Forsyth			usage();
39*37da2899SCharles.Forsyth		}
40*37da2899SCharles.Forsyth
41*37da2899SCharles.Forsyth	argv := arg->argv();
42*37da2899SCharles.Forsyth	arg = nil;
43*37da2899SCharles.Forsyth	if(argv == nil)
44*37da2899SCharles.Forsyth		usage();
45*37da2899SCharles.Forsyth	n := 0;
46*37da2899SCharles.Forsyth	for(v := argv; v != nil; v = tl v) {
47*37da2899SCharles.Forsyth		s := hd v;
48*37da2899SCharles.Forsyth		if (s == nil)
49*37da2899SCharles.Forsyth			usage();
50*37da2899SCharles.Forsyth		if(s[0] >= '0' && s[0] <= '9')
51*37da2899SCharles.Forsyth			n += killpid(s, msg, 1);
52*37da2899SCharles.Forsyth		else
53*37da2899SCharles.Forsyth			n += killmod(s, msg);
54*37da2899SCharles.Forsyth	}
55*37da2899SCharles.Forsyth	if (n == 0 && argv != nil)
56*37da2899SCharles.Forsyth		raise "fail:nothing killed";
57*37da2899SCharles.Forsyth}
58*37da2899SCharles.Forsyth
59*37da2899SCharles.Forsythkillpid(pid: string, msg: array of byte, sbok: int): int
60*37da2899SCharles.Forsyth{
61*37da2899SCharles.Forsyth	fd := sys->open("/prog/"+pid+"/ctl", sys->OWRITE);
62*37da2899SCharles.Forsyth	if(fd == nil) {
63*37da2899SCharles.Forsyth		err := sys->sprint("%r");
64*37da2899SCharles.Forsyth		elen := len err;
65*37da2899SCharles.Forsyth		if(sbok || err != "thread exited" && elen >= 14 && err[elen-14:] != "does not exist")
66*37da2899SCharles.Forsyth			sys->fprint(stderr, "kill: cannot open /prog/%s/ctl: %r\n", pid);
67*37da2899SCharles.Forsyth		return 0;
68*37da2899SCharles.Forsyth	}
69*37da2899SCharles.Forsyth
70*37da2899SCharles.Forsyth	n := sys->write(fd, msg, len msg);
71*37da2899SCharles.Forsyth	if(n < 0) {
72*37da2899SCharles.Forsyth		err := sys->sprint("%r");
73*37da2899SCharles.Forsyth		elen := len err;
74*37da2899SCharles.Forsyth		if(sbok || err != "thread exited")
75*37da2899SCharles.Forsyth			sys->fprint(stderr, "kill: cannot kill %s: %r\n", pid);
76*37da2899SCharles.Forsyth		return 0;
77*37da2899SCharles.Forsyth	}
78*37da2899SCharles.Forsyth	return 1;
79*37da2899SCharles.Forsyth}
80*37da2899SCharles.Forsyth
81*37da2899SCharles.Forsythkillmod(mod: string, msg: array of byte): int
82*37da2899SCharles.Forsyth{
83*37da2899SCharles.Forsyth	fd := sys->open("/prog", sys->OREAD);
84*37da2899SCharles.Forsyth	if(fd == nil) {
85*37da2899SCharles.Forsyth		sys->fprint(stderr, "kill: open /prog: %r\n");
86*37da2899SCharles.Forsyth		return 0;
87*37da2899SCharles.Forsyth	}
88*37da2899SCharles.Forsyth
89*37da2899SCharles.Forsyth	pids: list of string;
90*37da2899SCharles.Forsyth	for(;;) {
91*37da2899SCharles.Forsyth		(n, d) := sys->dirread(fd);
92*37da2899SCharles.Forsyth		if(n <= 0) {
93*37da2899SCharles.Forsyth			if (n < 0)
94*37da2899SCharles.Forsyth				sys->fprint(stderr, "kill: read /prog: %r\n");
95*37da2899SCharles.Forsyth			break;
96*37da2899SCharles.Forsyth		}
97*37da2899SCharles.Forsyth
98*37da2899SCharles.Forsyth		for(i := 0; i < n; i++)
99*37da2899SCharles.Forsyth			if (killmatch(d[i].name, mod))
100*37da2899SCharles.Forsyth				pids = d[i].name :: pids;
101*37da2899SCharles.Forsyth	}
102*37da2899SCharles.Forsyth	if (pids == nil) {
103*37da2899SCharles.Forsyth		sys->fprint(stderr, "kill: cannot find %s\n", mod);
104*37da2899SCharles.Forsyth		return 0;
105*37da2899SCharles.Forsyth	}
106*37da2899SCharles.Forsyth	n := 0;
107*37da2899SCharles.Forsyth	for (; pids != nil; pids = tl pids)
108*37da2899SCharles.Forsyth		if (killpid(hd pids, msg, 0)) {
109*37da2899SCharles.Forsyth			sys->print("%s ", hd pids);
110*37da2899SCharles.Forsyth			n++;
111*37da2899SCharles.Forsyth		}
112*37da2899SCharles.Forsyth	if (n > 0)
113*37da2899SCharles.Forsyth		sys->print("\n");
114*37da2899SCharles.Forsyth	return n;
115*37da2899SCharles.Forsyth}
116*37da2899SCharles.Forsyth
117*37da2899SCharles.Forsythkillmatch(dir, mod: string): int
118*37da2899SCharles.Forsyth{
119*37da2899SCharles.Forsyth	status := "/prog/"+dir+"/status";
120*37da2899SCharles.Forsyth	fd := sys->open(status, sys->OREAD);
121*37da2899SCharles.Forsyth	if(fd == nil)
122*37da2899SCharles.Forsyth		return 0;
123*37da2899SCharles.Forsyth	buf := array[512] of byte;
124*37da2899SCharles.Forsyth	n := sys->read(fd, buf, len buf);
125*37da2899SCharles.Forsyth	if(n < 0) {
126*37da2899SCharles.Forsyth		err := sys->sprint("%r");
127*37da2899SCharles.Forsyth		if(err != "thread exited")
128*37da2899SCharles.Forsyth			sys->fprint(stderr, "kill: cannot read %s: %s\n", status, err);
129*37da2899SCharles.Forsyth		return 0;
130*37da2899SCharles.Forsyth	}
131*37da2899SCharles.Forsyth
132*37da2899SCharles.Forsyth	# module name is last field
133*37da2899SCharles.Forsyth	(nil, fields) := sys->tokenize(string buf[0:n], " ");
134*37da2899SCharles.Forsyth	for(s := ""; fields != nil; fields = tl fields)
135*37da2899SCharles.Forsyth		s = hd fields;
136*37da2899SCharles.Forsyth
137*37da2899SCharles.Forsyth	# strip builtin module, e.g. Sh[$Sys]
138*37da2899SCharles.Forsyth	for(i := 0; i < len s; i++) {
139*37da2899SCharles.Forsyth		if(s[i] == '[') {
140*37da2899SCharles.Forsyth			s = s[0:i];
141*37da2899SCharles.Forsyth			break;
142*37da2899SCharles.Forsyth		}
143*37da2899SCharles.Forsyth	}
144*37da2899SCharles.Forsyth
145*37da2899SCharles.Forsyth	return s == mod;
146*37da2899SCharles.Forsyth}
147