diff options
| author | Charles Forsyth <charles.forsyth@gmail.com> | 2015-03-02 11:35:43 +0000 |
|---|---|---|
| committer | Charles Forsyth <charles.forsyth@gmail.com> | 2015-03-02 11:35:43 +0000 |
| commit | 437898b63d972fa000f072902ebf00cf7e489fc4 (patch) | |
| tree | 96ce9c9bdaee049cbe64da9a6e55475688de6a06 | |
| parent | 28272a0014d067c3b39985261782b42f361449d3 (diff) | |
add missing file
| -rw-r--r-- | appl/tiny/kill.b | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/appl/tiny/kill.b b/appl/tiny/kill.b new file mode 100644 index 00000000..7ff5a39a --- /dev/null +++ b/appl/tiny/kill.b @@ -0,0 +1,146 @@ +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; +} |
