xref: /inferno-os/appl/wm/task.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1implement WmTask;
2
3include "sys.m";
4	sys: Sys;
5	Dir: import sys;
6
7include "draw.m";
8	draw: Draw;
9
10include "tk.m";
11	tk: Tk;
12	Toplevel: import tk;
13
14include "tkclient.m";
15	tkclient: Tkclient;
16
17include "dialog.m";
18	dialog: Dialog;
19
20Prog: adt
21{
22	pid:	int;
23	pgrp: int;
24	size:	int;
25	state:	string;
26	mod:	string;
27};
28
29WmTask: module
30{
31	init:	fn(ctxt: ref Draw->Context, argv: list of string);
32};
33
34Wm: module
35{
36	init:	fn(ctxt: ref Draw->Context, argv: list of string);
37};
38
39task_cfg := array[] of {
40	"frame .fl",
41	"scrollbar .fl.scroll -command {.fl.l yview}",
42	"listbox .fl.l -width 40w -yscrollcommand {.fl.scroll set}",
43	"frame .b",
44	"button .b.ref -text Refresh -command {send cmd r}",
45	"button .b.deb -text Debug -command {send cmd d}",
46	"button .b.files -text Files -command {send cmd f}",
47	"button .b.kill -text Kill -command {send cmd k}",
48	"button .b.killg -text {Kill Group} -command {send cmd kg}",
49	"pack .b.ref .b.deb .b.files .b.kill .b.killg -side left -padx 2 -pady 2",
50	"pack .b -fill x",
51	"pack .fl.scroll -side left -fill y",
52	"pack .fl.l -fill both -expand 1",
53	"pack .fl -fill both -expand 1",
54	"pack propagate . 0",
55};
56
57init(ctxt: ref Draw->Context, nil: list of string)
58{
59	sys  = load Sys  Sys->PATH;
60	if (ctxt == nil) {
61		sys->fprint(sys->fildes(2), "task: no window context\n");
62		raise "fail:bad context";
63	}
64	draw = load Draw Draw->PATH;
65	tk   = load Tk   Tk->PATH;
66	tkclient= load Tkclient Tkclient->PATH;
67	dialog = load Dialog Dialog->PATH;
68
69	tkclient->init();
70	dialog->init();
71
72	sysnam := sysname();
73
74	(t, wmctl) := tkclient->toplevel(ctxt, "", sysnam, Tkclient->Appl);
75	if(t == nil)
76		return;
77
78	cmd := chan of string;
79	tk->namechan(t, cmd, "cmd");
80
81	for (c:=0; c<len task_cfg; c++)
82		tk->cmd(t, task_cfg[c]);
83
84	readprog(t);
85
86	tk->cmd(t, ".fl.l see end;update");
87	tkclient->onscreen(t, nil);
88	tkclient->startinput(t, "kbd"::"ptr"::nil);
89
90	for(;;) alt {
91	s := <-t.ctxt.kbd =>
92		tk->keyboard(t, s);
93	s := <-t.ctxt.ptr =>
94		tk->pointer(t, *s);
95	s := <-t.ctxt.ctl or
96	s = <-t.wreq =>
97		tkclient->wmctl(t, s);
98	menu := <-wmctl =>
99		case menu {
100		"exit" =>
101			return;
102		"task" =>
103			tkclient->wmctl(t, menu);
104			tk->cmd(t, ".fl.l delete 0 end");
105			readprog(t);
106			tk->cmd(t, ".fl.l see end;update");
107		* =>
108			tkclient->wmctl(t, menu);
109		}
110	bcmd := <-cmd =>
111		case bcmd {
112		"d" =>
113			sel := tk->cmd(t, ".fl.l curselection");
114			if(sel == "")
115				break;
116			pid := int tk->cmd(t, ".fl.l get "+sel);
117			stk := load Wm "/dis/wm/deb.dis";
118			if(stk == nil)
119				break;
120			spawn stk->init(ctxt, "wm/deb" :: "-p "+string pid :: nil);
121			stk = nil;
122		"k" or "kg" =>
123			sel := tk->cmd(t, ".fl.l curselection");
124			if(sel == "")
125				break;
126			pid := int tk->cmd(t, ".fl.l get "+sel);
127			what := "opening ctl file";
128			cfile := "/prog/"+string pid+"/ctl";
129			cfd := sys->open(cfile, sys->OWRITE);
130			if(cfd != nil) {
131				if(bcmd == "kg"){
132					if(sys->fprint(cfd, "killgrp") > 0){
133						cfd = nil;
134						refresh(t);
135						break;
136					}
137				}else if(sys->fprint(cfd, "kill") > 0){
138					tk->cmd(t, ".fl.l delete "+sel);
139					cfd = nil;
140					break;
141				}
142				cfd = nil;
143				what = "sending kill request";
144			}
145			if(bcmd == "k" && sys->sprint("%r") == "file does not exist") {
146				refresh(t);
147				break;
148			}
149			dialog->prompt(ctxt, t.image, "error -fg red", "Kill",
150					"Error "+what+"\n"+
151					 "System: "+sys->sprint("%r"),
152					0, "OK" :: nil);
153		"r" =>
154			refresh(t);
155		"f" =>
156			sel := tk->cmd(t, ".fl.l curselection");
157			if(sel == "")
158				break;
159			pid := int tk->cmd(t, ".fl.l get "+sel);
160			fi := load Wm "/dis/wm/edit.dis";
161			if(fi == nil)
162				break;
163			spawn fi->init(ctxt,
164				"edit" ::
165				"/prog/"+string pid+"/fd" :: nil);
166			fi = nil;
167		}
168	}
169}
170
171refresh(t: ref Tk->Toplevel)
172{
173	tk->cmd(t, ".fl.l delete 0 end");
174	readprog(t);
175	tk->cmd(t, ".fl.l see end;update");
176}
177
178mkprog(file: string): ref Prog
179{
180	fd := sys->open("/prog/"+file+"/status", sys->OREAD);
181	if(fd == nil)
182		return nil;
183
184	buf := array[256] of byte;
185	n := sys->read(fd, buf, len buf);
186	if(n <= 0)
187		return nil;
188
189	(v, l) := sys->tokenize(string buf[0:n], " ");
190	if(v < 6)
191		return nil;
192
193	prg := ref Prog;
194	prg.pid = int hd l;
195	l = tl l;
196	prg.pgrp = int hd l;
197	l = tl l;
198	l = tl l;
199	# eat blanks in user name
200	while(len l > 3)
201		l = tl l;
202	prg.state = hd l;
203	l = tl l;
204	prg.size = int hd l;
205	l = tl l;
206	prg.mod = hd l;
207
208	return prg;
209}
210
211readprog(t: ref Toplevel)
212{
213	fd := sys->open("/prog", sys->OREAD);
214	if(fd == nil)
215		return;
216	for(;;) {
217		(n, d) := sys->dirread(fd);
218		if(n <= 0)
219			break;
220		for(i := 0; i < n; i++) {
221			p := mkprog(d[i].name);
222			if(p != nil){
223				l := sys->sprint("%4d %4d %3dK %-7s  %s", p.pid, p.pgrp, p.size, p.state, p.mod);
224				tk->cmd(t, ".fl.l insert end '"+l);
225			}
226		}
227	}
228}
229
230sysname(): string
231{
232	fd := sys->open("#c/sysname", sys->OREAD);
233	if(fd == nil)
234		return "Anon";
235	buf := array[128] of byte;
236	n := sys->read(fd, buf, len buf);
237	if(n < 0)
238		return "Anon";
239	return string buf[0:n];
240}
241