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