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