implement Kill; include "sys.m"; sys: Sys;include "draw.m";include "arg.m"; Kill: module { init: fn(nil: ref Draw->Context, args: list of string);}; stderr: ref Sys->FD; usage(){ sys->fprint(stderr, "usage: kill [-g] pid|module [...]\n"); raise "fail: usage";} init(nil: ref Draw->Context, args: list of string){ sys = load Sys Sys->PATH; stderr = sys->fildes(2); arg := load Arg Arg->PATH; if(arg == nil){ sys->fprint(stderr, "kill: cannot load %s: %r\n", Arg->PATH); raise "fail:load"; } msg := array of byte "kill"; arg->init(args); while((o := arg->opt()) != 0) case o { 'g' => msg = array of byte "killgrp"; * => usage(); } argv := arg->argv(); arg = nil; if(argv == nil) usage(); n := 0; for(v := argv; v != nil; v = tl v) { s := hd v; if (s == nil) usage(); if(s[0] >= '0' && s[0] <= '9') n += killpid(s, msg, 1); else n += killmod(s, msg); } if (n == 0 && argv != nil) raise "fail:nothing killed";} killpid(pid: string, msg: array of byte, sbok: int): int{ fd := sys->open("/prog/"+pid+"/ctl", sys->OWRITE); if(fd == nil) { err := sys->sprint("%r"); elen := len err; if(sbok || err != "thread exited" && elen >= 14 && err[elen-14:] != "does not exist") sys->fprint(stderr, "kill: cannot open /prog/%s/ctl: %r\n", pid); return 0; } n := sys->write(fd, msg, len msg); if(n < 0) { err := sys->sprint("%r"); elen := len err; if(sbok || err != "thread exited") sys->fprint(stderr, "kill: cannot kill %s: %r\n", pid); return 0; } return 1;} killmod(mod: string, msg: array of byte): int{ fd := sys->open("/prog", sys->OREAD); if(fd == nil) { sys->fprint(stderr, "kill: open /prog: %r\n"); return 0; } pids: list of string; for(;;) { (n, d) := sys->dirread(fd); if(n <= 0) { if (n < 0) sys->fprint(stderr, "kill: read /prog: %r\n"); break; } for(i := 0; i < n; i++) if (killmatch(d[i].name, mod)) pids = d[i].name :: pids; } if (pids == nil) { sys->fprint(stderr, "kill: cannot find %s\n", mod); return 0; } n := 0; for (; pids != nil; pids = tl pids) if (killpid(hd pids, msg, 0)) { sys->print("%s ", hd pids); n++; } if (n > 0) sys->print("\n"); return n;} killmatch(dir, mod: string): int{ status := "/prog/"+dir+"/status"; fd := sys->open(status, sys->OREAD); if(fd == nil) return 0; buf := array[512] of byte; n := sys->read(fd, buf, len buf); if(n < 0) { err := sys->sprint("%r"); if(err != "thread exited") sys->fprint(stderr, "kill: cannot read %s: %s\n", status, err); return 0; } # module name is last field (nil, fields) := sys->tokenize(string buf[0:n], " "); for(s := ""; fields != nil; fields = tl fields) s = hd fields; # strip builtin module, e.g. Sh[$Sys] for(i := 0; i < len s; i++) { if(s[i] == '[') { s = s[0:i]; break; } } return s == mod;}
implement Kill;
include "sys.m";
sys: Sys;
include "draw.m";
include "arg.m";
Kill: module {
init: fn(nil: ref Draw->Context, args: list of string);
};
stderr: ref Sys->FD;
usage()
{
sys->fprint(stderr, "usage: kill [-g] pid|module [...]\n");
raise "fail: usage";
}
init(nil: ref Draw->Context, args: list of string)
{
sys = load Sys Sys->PATH;
stderr = sys->fildes(2);
arg := load Arg Arg->PATH;
if(arg == nil){
sys->fprint(stderr, "kill: cannot load %s: %r\n", Arg->PATH);
raise "fail:load";
}
msg := array of byte "kill";
arg->init(args);
while((o := arg->opt()) != 0)
case o {
'g' =>
msg = array of byte "killgrp";
* =>
usage();
}
argv := arg->argv();
arg = nil;
if(argv == nil)
usage();
n := 0;
for(v := argv; v != nil; v = tl v) {
s := hd v;
if (s == nil)
usage();
if(s[0] >= '0' && s[0] <= '9')
n += killpid(s, msg, 1);
else
n += killmod(s, msg);
}
if (n == 0 && argv != nil)
raise "fail:nothing killed";
}
killpid(pid: string, msg: array of byte, sbok: int): int
{
fd := sys->open("/prog/"+pid+"/ctl", sys->OWRITE);
if(fd == nil) {
err := sys->sprint("%r");
elen := len err;
if(sbok || err != "thread exited" && elen >= 14 && err[elen-14:] != "does not exist")
sys->fprint(stderr, "kill: cannot open /prog/%s/ctl: %r\n", pid);
return 0;
}
n := sys->write(fd, msg, len msg);
if(n < 0) {
err := sys->sprint("%r");
elen := len err;
if(sbok || err != "thread exited")
sys->fprint(stderr, "kill: cannot kill %s: %r\n", pid);
return 0;
}
return 1;
}
killmod(mod: string, msg: array of byte): int
{
fd := sys->open("/prog", sys->OREAD);
if(fd == nil) {
sys->fprint(stderr, "kill: open /prog: %r\n");
return 0;
}
pids: list of string;
for(;;) {
(n, d) := sys->dirread(fd);
if(n <= 0) {
if (n < 0)
sys->fprint(stderr, "kill: read /prog: %r\n");
break;
}
for(i := 0; i < n; i++)
if (killmatch(d[i].name, mod))
pids = d[i].name :: pids;
}
if (pids == nil) {
sys->fprint(stderr, "kill: cannot find %s\n", mod);
return 0;
}
n := 0;
for (; pids != nil; pids = tl pids)
if (killpid(hd pids, msg, 0)) {
sys->print("%s ", hd pids);
n++;
}
if (n > 0)
sys->print("\n");
return n;
}
killmatch(dir, mod: string): int
{
status := "/prog/"+dir+"/status";
fd := sys->open(status, sys->OREAD);
if(fd == nil)
return 0;
buf := array[512] of byte;
n := sys->read(fd, buf, len buf);
if(n < 0) {
err := sys->sprint("%r");
if(err != "thread exited")
sys->fprint(stderr, "kill: cannot read %s: %s\n", status, err);
return 0;
}
# module name is last field
(nil, fields) := sys->tokenize(string buf[0:n], " ");
for(s := ""; fields != nil; fields = tl fields)
s = hd fields;
# strip builtin module, e.g. Sh[$Sys]
for(i := 0; i < len s; i++) {
if(s[i] == '[') {
s = s[0:i];
break;
}
}
return s == mod;
}