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