1 | /* |
---|
2 | * $Id: dash.c,v 1.4 2001-08-01 13:43:20 ghudson Exp $ |
---|
3 | * |
---|
4 | * Copyright 1990, 1991 by the Massachusetts Institute of Technology. |
---|
5 | * |
---|
6 | * For copying and distribution information, please see the file |
---|
7 | * <mit-copyright.h>. |
---|
8 | * |
---|
9 | */ |
---|
10 | |
---|
11 | #if (!defined(lint)) && (!defined(SABER)) |
---|
12 | static char *rcsid = |
---|
13 | "$Id: dash.c,v 1.4 2001-08-01 13:43:20 ghudson Exp $"; |
---|
14 | #endif |
---|
15 | |
---|
16 | #include "mit-copyright.h" |
---|
17 | #include <stdio.h> |
---|
18 | #include <stdlib.h> |
---|
19 | #include <string.h> |
---|
20 | #include <ctype.h> |
---|
21 | #include <errno.h> |
---|
22 | #include <signal.h> |
---|
23 | #include <sys/types.h> |
---|
24 | #include <sys/stat.h> |
---|
25 | #include <sys/wait.h> |
---|
26 | #include <sys/time.h> |
---|
27 | #include <sys/resource.h> |
---|
28 | #include <sys/param.h> |
---|
29 | #include <fcntl.h> |
---|
30 | #include <athdir.h> |
---|
31 | #include <X11/Xlib.h> |
---|
32 | #include <X11/Xutil.h> |
---|
33 | #include <X11/Xatom.h> |
---|
34 | #include <X11/Xmu/WinUtil.h> |
---|
35 | #include <Jets/Jets.h> |
---|
36 | #include <Jets/Window.h> |
---|
37 | #include <Jets/Button.h> |
---|
38 | #include <Jets/Label.h> |
---|
39 | #include <Jets/Menu.h> |
---|
40 | #include <Jets/DClock.h> |
---|
41 | #include <Jets/AClock.h> |
---|
42 | #include <Jets/Form.h> |
---|
43 | #include <Jets/Tree.h> |
---|
44 | /* #include <StripChart.h> */ |
---|
45 | /* #include <List.h> */ |
---|
46 | #include <Jets/warn.h> |
---|
47 | #include "dash.h" |
---|
48 | |
---|
49 | |
---|
50 | extern int DEBUG; |
---|
51 | |
---|
52 | #define LOADST "/usr/athena/lib/gnuemacs/etc/loadst" |
---|
53 | |
---|
54 | #define DASH "Dash" |
---|
55 | #define DASH_NOP (char)0x00 |
---|
56 | #define DASH_DEBUG (char)0x01 |
---|
57 | #define DASH_KILL (char)0x02 |
---|
58 | #define DASH_CREATE (char)0x03 |
---|
59 | #define DASH_DESTROY (char)0x04 |
---|
60 | #define DASH_MAP (char)0x05 |
---|
61 | #define DASH_UNMAP (char)0x06 |
---|
62 | #define DASH_CREATEORMAP (char)0x07 |
---|
63 | #define DASH_RESTART (char)0x08 |
---|
64 | |
---|
65 | Atom dashAtom, nameAtom; |
---|
66 | #define DASH_ATOM "_ATHENA_DASH" |
---|
67 | |
---|
68 | |
---|
69 | |
---|
70 | Jet root; |
---|
71 | /* |
---|
72 | * These definitions are needed by the tree jet |
---|
73 | */ |
---|
74 | JetClass *jetClasses[] = |
---|
75 | { &treeJetClass, &windowJetClass, &buttonJetClass, &labelJetClass, |
---|
76 | &menuJetClass, &dClockJetClass, |
---|
77 | &aClockJetClass, &formJetClass, |
---|
78 | /* &stripChartJetClass, */ |
---|
79 | /* &listJetClass, */}; |
---|
80 | |
---|
81 | int numJetClasses = XjNumber(jetClasses); |
---|
82 | |
---|
83 | static XrmOptionDescRec opTable[] = { |
---|
84 | {"+rv", "*reverseVideo", XrmoptionNoArg, (caddr_t) "off"}, |
---|
85 | {"-background", "*background", XrmoptionSepArg, (caddr_t) NULL}, |
---|
86 | {"-bd", "*borderColor", XrmoptionSepArg, (caddr_t) NULL}, |
---|
87 | {"-bg", "*background", XrmoptionSepArg, (caddr_t) NULL}, |
---|
88 | {"-bordercolor","*borderColor", XrmoptionSepArg, (caddr_t) NULL}, |
---|
89 | {"-borderwidth",".borderWidth", XrmoptionSepArg, (caddr_t) NULL}, |
---|
90 | {"-bw", ".borderWidth", XrmoptionSepArg, (caddr_t) NULL}, |
---|
91 | {"-display", ".display", XrmoptionSepArg, (caddr_t) NULL}, |
---|
92 | {"-fg", "*foreground", XrmoptionSepArg, (caddr_t) NULL}, |
---|
93 | {"-fn", "*font", XrmoptionSepArg, (caddr_t) NULL}, |
---|
94 | {"-font", "*font", XrmoptionSepArg, (caddr_t) NULL}, |
---|
95 | {"-foreground", "*foreground", XrmoptionSepArg, (caddr_t) NULL}, |
---|
96 | {"-geometry", "*menuTree.window.geometry", XrmoptionSepArg, |
---|
97 | (caddr_t) NULL}, |
---|
98 | {"-reverse", "*reverseVideo", XrmoptionNoArg, (caddr_t) "on"}, |
---|
99 | {"-rv", "*reverseVideo", XrmoptionNoArg, (caddr_t) "on"}, |
---|
100 | {"+rude", "*rude", XrmoptionNoArg, (caddr_t) "off"}, |
---|
101 | {"-rude", "*rude", XrmoptionNoArg, (caddr_t) "on"}, |
---|
102 | {"+verify", "*verify", XrmoptionNoArg, (caddr_t) "off"}, |
---|
103 | {"-verify", "*verify", XrmoptionNoArg, (caddr_t) "on"}, |
---|
104 | {"-xrm", NULL, XrmoptionResArg, (caddr_t) NULL}, |
---|
105 | {"-name", ".name", XrmoptionSepArg, (caddr_t) NULL}, |
---|
106 | {"-appdefs", ".appDefs", XrmoptionSepArg, (caddr_t) NULL}, |
---|
107 | {"-f", ".appDefs", XrmoptionSepArg, (caddr_t) NULL}, |
---|
108 | {"-userdefs", ".userDefs", XrmoptionSepArg, (caddr_t) NULL}, |
---|
109 | {"-menus", "*Menu.file", XrmoptionSepArg, (caddr_t) NULL}, |
---|
110 | {"-send", ".send", XrmoptionNoArg, (caddr_t) "true"}, |
---|
111 | {"-kill", ".kill", XrmoptionNoArg, (caddr_t) "true"}, |
---|
112 | {"-run", ".run", XrmoptionNoArg, (caddr_t) "true"}, |
---|
113 | {"-restart", ".restart", XrmoptionNoArg, (caddr_t) "true"}, |
---|
114 | {"-debug", ".debug", XrmoptionNoArg, (caddr_t) "true"}, |
---|
115 | {"-nofork", ".nofork", XrmoptionNoArg, (caddr_t) "true"}, |
---|
116 | {"-nosession", "*showCommand", XrmoptionNoArg, (caddr_t) "false"}, |
---|
117 | #ifdef HAVE_KRB4 |
---|
118 | {"-nochecktickets", ".checkTickets", XrmoptionNoArg, (caddr_t) "false"}, |
---|
119 | #endif /* HAVE_KRB4 */ |
---|
120 | }; |
---|
121 | |
---|
122 | MyResources parms; |
---|
123 | |
---|
124 | #define offset(field) XjOffset(MyResourcesPtr,field) |
---|
125 | |
---|
126 | static XjResource appResources[] = |
---|
127 | { |
---|
128 | { "verify", "Verify", XjRBoolean, sizeof(Boolean), |
---|
129 | offset(verifyOn), XjRBoolean, (caddr_t) True }, |
---|
130 | { "notify", "Notify", XjRBoolean, sizeof(Boolean), |
---|
131 | offset(notifyOn), XjRBoolean, (caddr_t) True }, |
---|
132 | { "startString", "StartString", XjRString, sizeof(char *), |
---|
133 | offset(startString), XjRString, (caddr_t) NULL }, |
---|
134 | { "run", "Run", XjRBoolean, sizeof(Boolean), |
---|
135 | offset(run), XjRBoolean, (caddr_t) False }, |
---|
136 | { "send", "Send", XjRBoolean, sizeof(Boolean), |
---|
137 | offset(send), XjRBoolean, (caddr_t) False }, |
---|
138 | { "kill", "Kill", XjRBoolean, sizeof(Boolean), |
---|
139 | offset(kill), XjRBoolean, (caddr_t) False }, |
---|
140 | { "restart", "Restart", XjRBoolean, sizeof(Boolean), |
---|
141 | offset(restart), XjRBoolean, (caddr_t) False }, |
---|
142 | { "debug", "Debug", XjRBoolean, sizeof(Boolean), |
---|
143 | offset(debug), XjRBoolean, (caddr_t) False }, |
---|
144 | { "nofork", "Nofork", XjRBoolean, sizeof(Boolean), |
---|
145 | offset(nofork), XjRBoolean, (caddr_t) False }, |
---|
146 | #ifdef HAVE_KRB4 |
---|
147 | { "checkTickets", "CheckTickets", XjRBoolean, sizeof(Boolean), |
---|
148 | offset(checkTickets), XjRBoolean, (caddr_t) True }, |
---|
149 | #endif /* HAVE_KRB4 */ |
---|
150 | }; |
---|
151 | |
---|
152 | #undef offset |
---|
153 | |
---|
154 | |
---|
155 | /* |
---|
156 | * setenv() doesn't exist on some systems... it's putenv instead. |
---|
157 | * So, we write our own setenv routine, and use it instead. |
---|
158 | * |
---|
159 | * Arguments: (same as setenv in BSD Unix) |
---|
160 | * char *name; name of environment variable to set or change. |
---|
161 | * char *value; value to set or change environment variable to. |
---|
162 | * int overwrite; if non-zero, force variable to value. |
---|
163 | * if zero, and variable does not exist, add variable |
---|
164 | * to environment. |
---|
165 | * else, do nothing. |
---|
166 | * |
---|
167 | * Returns: (same as setenv in bsd Unix) |
---|
168 | * -1 if unsuccessful (unable to malloc enough space for |
---|
169 | * an expanded environment). |
---|
170 | * 0 otherwise. |
---|
171 | * |
---|
172 | */ |
---|
173 | static int psetenv(name, value, overwrite) |
---|
174 | char *name, *value; |
---|
175 | int overwrite; |
---|
176 | { |
---|
177 | char *string; |
---|
178 | |
---|
179 | if ((overwrite) || |
---|
180 | ( (char *) getenv(name) == NULL)) |
---|
181 | { |
---|
182 | string = (char *) malloc((strlen(name) + strlen(value) + 2) |
---|
183 | * sizeof(char)); |
---|
184 | /* add 1 for the null and 1 for "=" */ |
---|
185 | if (string == NULL) |
---|
186 | return(-1); |
---|
187 | strcpy(string, name); |
---|
188 | strcat(string, "="); |
---|
189 | strcat(string, value); |
---|
190 | if (! putenv(string) ) |
---|
191 | return(-1); |
---|
192 | } |
---|
193 | return(0); |
---|
194 | } |
---|
195 | |
---|
196 | |
---|
197 | /* |
---|
198 | * Set utilities |
---|
199 | */ |
---|
200 | |
---|
201 | typedef struct _Set |
---|
202 | { |
---|
203 | struct _Set *next; |
---|
204 | char *name; |
---|
205 | } Set; |
---|
206 | |
---|
207 | Set *setCache[100]; |
---|
208 | int cacheSize = 0; |
---|
209 | |
---|
210 | /* |
---|
211 | * Single level expansion of name |
---|
212 | */ |
---|
213 | Set *expandName(name) |
---|
214 | char *name; |
---|
215 | { |
---|
216 | char *type; |
---|
217 | XrmValue value; |
---|
218 | Set *tmp, *list; |
---|
219 | char *start, *end, *more; |
---|
220 | char n[50], c[50]; |
---|
221 | int i; |
---|
222 | |
---|
223 | if (!strcasecmp("NULL", name)) |
---|
224 | return NULL; |
---|
225 | |
---|
226 | for (i = 0; i < cacheSize; i++) |
---|
227 | if (!strcmp(name, setCache[i]->name)) |
---|
228 | return setCache[i]->next; |
---|
229 | |
---|
230 | sprintf(n, "%s.set.%s", programName, name); |
---|
231 | sprintf(c, "%s.Set.%s", programClass, name); |
---|
232 | |
---|
233 | if (XrmGetResource(rdb, n, c, &type, &value)) |
---|
234 | start = (char *)(value.addr); |
---|
235 | else |
---|
236 | { |
---|
237 | char errtext[100]; |
---|
238 | |
---|
239 | sprintf(errtext, "no set %s exists", name); |
---|
240 | XjWarning(errtext); |
---|
241 | return NULL; |
---|
242 | } |
---|
243 | |
---|
244 | list = (Set *)XjMalloc((unsigned) sizeof(Set)); |
---|
245 | list->name = XjNewString(name); |
---|
246 | list->next = NULL; |
---|
247 | |
---|
248 | while (isspace(*start)) start++; |
---|
249 | while (*start != '\0') |
---|
250 | { |
---|
251 | end = start; |
---|
252 | while (!isspace(*end) && *end != '\0') end++; |
---|
253 | more = end; |
---|
254 | if (*end != '\0') more++; |
---|
255 | *end = '\0'; |
---|
256 | |
---|
257 | tmp = (Set *)XjMalloc((unsigned) sizeof(Set)); |
---|
258 | tmp->name = start; |
---|
259 | tmp->next = list->next; |
---|
260 | list->next = tmp; |
---|
261 | |
---|
262 | start = more; |
---|
263 | } |
---|
264 | |
---|
265 | setCache[cacheSize++] = list; |
---|
266 | return list->next; |
---|
267 | } |
---|
268 | |
---|
269 | Set *resolveName(name, list) |
---|
270 | char *name; |
---|
271 | Set *list; |
---|
272 | { |
---|
273 | Set *e, *tmp; |
---|
274 | |
---|
275 | e = expandName(name); |
---|
276 | while (e != NULL) |
---|
277 | { |
---|
278 | if (*(e->name) == '_') |
---|
279 | { |
---|
280 | tmp = (Set *)XjMalloc((unsigned) sizeof(Set)); |
---|
281 | tmp->name = e->name + 1; |
---|
282 | tmp->next = list; |
---|
283 | list = tmp; |
---|
284 | } |
---|
285 | else |
---|
286 | list = resolveName(e->name, list); |
---|
287 | e = e->next; |
---|
288 | } |
---|
289 | |
---|
290 | return list; |
---|
291 | } |
---|
292 | |
---|
293 | void freeSet(set) |
---|
294 | Set *set; |
---|
295 | { |
---|
296 | Set *back; |
---|
297 | |
---|
298 | while (set) |
---|
299 | { |
---|
300 | back = set; |
---|
301 | set = set->next; |
---|
302 | XjFree((char *) back); |
---|
303 | } |
---|
304 | } |
---|
305 | |
---|
306 | /* |
---|
307 | * Tree callbacks... |
---|
308 | */ |
---|
309 | |
---|
310 | int printTree(fromJet, what, data) |
---|
311 | Jet fromJet; |
---|
312 | char *what; |
---|
313 | caddr_t data; |
---|
314 | { |
---|
315 | Jet j; |
---|
316 | |
---|
317 | for (j = root->core.child; j != NULL; j = j->core.sibling) |
---|
318 | fprintf(stdout, "%s\n", j->core.name); |
---|
319 | return 0; |
---|
320 | } |
---|
321 | |
---|
322 | int mapTree(fromJet, what, data) |
---|
323 | Jet fromJet; |
---|
324 | char *what; |
---|
325 | caddr_t data; |
---|
326 | { |
---|
327 | Jet w; |
---|
328 | |
---|
329 | w = XjFindJet(what, root); |
---|
330 | |
---|
331 | if (w != NULL) |
---|
332 | { |
---|
333 | w = w->core.child; |
---|
334 | while (w) |
---|
335 | { |
---|
336 | MapWindow(w, True); |
---|
337 | w = w->core.sibling; |
---|
338 | } |
---|
339 | return 0; |
---|
340 | } |
---|
341 | else |
---|
342 | { |
---|
343 | char errtext[100]; |
---|
344 | |
---|
345 | sprintf(errtext, "couldn't find %s to map it", what); |
---|
346 | XjWarning(errtext); |
---|
347 | return 1; |
---|
348 | } |
---|
349 | } |
---|
350 | |
---|
351 | int mapSet(fromJet, what, data) |
---|
352 | Jet fromJet; |
---|
353 | char *what; |
---|
354 | caddr_t data; |
---|
355 | { |
---|
356 | Set *set, *ptr; |
---|
357 | |
---|
358 | set = resolveName(what, NULL); |
---|
359 | if (set) |
---|
360 | { |
---|
361 | for (ptr = set; ptr != NULL; ptr = ptr->next) |
---|
362 | (void)mapTree(fromJet, ptr->name, data); |
---|
363 | freeSet(set); |
---|
364 | } |
---|
365 | return 0; |
---|
366 | } |
---|
367 | |
---|
368 | int unmapTree(fromJet, what, data) |
---|
369 | Jet fromJet; |
---|
370 | char *what; |
---|
371 | caddr_t data; |
---|
372 | { |
---|
373 | Jet w; |
---|
374 | |
---|
375 | w = XjFindJet(what, root); |
---|
376 | |
---|
377 | if (w != NULL) |
---|
378 | { |
---|
379 | w = w->core.child; |
---|
380 | while (w) |
---|
381 | { |
---|
382 | UnmapWindow(w); |
---|
383 | w = w->core.sibling; |
---|
384 | } |
---|
385 | return 0; |
---|
386 | } |
---|
387 | else |
---|
388 | { |
---|
389 | char errtext[100]; |
---|
390 | |
---|
391 | sprintf(errtext, "couldn't find %s to unmap it", what); |
---|
392 | XjWarning(errtext); |
---|
393 | return 1; |
---|
394 | } |
---|
395 | } |
---|
396 | |
---|
397 | int unmapSet(fromJet, what, data) |
---|
398 | Jet fromJet; |
---|
399 | char *what; |
---|
400 | caddr_t data; |
---|
401 | { |
---|
402 | Set *set, *ptr; |
---|
403 | |
---|
404 | set = resolveName(what, NULL); |
---|
405 | if (set) |
---|
406 | { |
---|
407 | for (ptr = set; ptr != NULL; ptr = ptr->next) |
---|
408 | (void)unmapTree(fromJet, ptr->name, data); |
---|
409 | freeSet(set); |
---|
410 | } |
---|
411 | return 0; |
---|
412 | } |
---|
413 | |
---|
414 | int createTree(fromJet, what, data) |
---|
415 | Jet fromJet; |
---|
416 | char *what; |
---|
417 | caddr_t data; |
---|
418 | { |
---|
419 | if (NULL == XjFindJet(what, root)) |
---|
420 | XjRealizeJet(XjVaCreateJet(what, treeJetClass, root, NULL, NULL)); |
---|
421 | return 0; |
---|
422 | } |
---|
423 | |
---|
424 | int createSet(fromJet, what, data) |
---|
425 | Jet fromJet; |
---|
426 | char *what; |
---|
427 | caddr_t data; |
---|
428 | { |
---|
429 | Set *set, *ptr; |
---|
430 | |
---|
431 | set = resolveName(what, NULL); |
---|
432 | if (set) |
---|
433 | { |
---|
434 | for (ptr = set; ptr != NULL; ptr = ptr->next) |
---|
435 | (void)createTree(fromJet, ptr->name, data); |
---|
436 | freeSet(set); |
---|
437 | } |
---|
438 | return 0; |
---|
439 | } |
---|
440 | |
---|
441 | int createMapTree(fromJet, what, data) |
---|
442 | Jet fromJet; |
---|
443 | char *what; |
---|
444 | caddr_t data; |
---|
445 | { |
---|
446 | if (NULL == XjFindJet(what, root)) |
---|
447 | XjRealizeJet(XjVaCreateJet(what, treeJetClass, root, NULL, NULL)); |
---|
448 | else |
---|
449 | mapTree(fromJet, what, data); |
---|
450 | |
---|
451 | return 0; |
---|
452 | } |
---|
453 | |
---|
454 | int createMapSet(fromJet, what, data) |
---|
455 | Jet fromJet; |
---|
456 | char *what; |
---|
457 | caddr_t data; |
---|
458 | { |
---|
459 | Set *set, *ptr; |
---|
460 | |
---|
461 | set = resolveName(what, NULL); |
---|
462 | if (set) |
---|
463 | { |
---|
464 | for (ptr = set; ptr != NULL; ptr = ptr->next) |
---|
465 | (void)createMapTree(fromJet, ptr->name, data); |
---|
466 | freeSet(set); |
---|
467 | } |
---|
468 | return 0; |
---|
469 | } |
---|
470 | |
---|
471 | int destroyTree(fromJet, what, data) |
---|
472 | Jet fromJet; |
---|
473 | char *what; |
---|
474 | caddr_t data; |
---|
475 | { |
---|
476 | Jet w; |
---|
477 | |
---|
478 | w = XjFindJet(what, root); |
---|
479 | if (w != NULL) |
---|
480 | { |
---|
481 | XjDestroyJet(w); |
---|
482 | return 0; |
---|
483 | } |
---|
484 | else |
---|
485 | { |
---|
486 | char errtext[100]; |
---|
487 | |
---|
488 | sprintf(errtext, "couldn't find %s to destroy it", what); |
---|
489 | XjWarning(errtext); |
---|
490 | return 1; |
---|
491 | } |
---|
492 | } |
---|
493 | |
---|
494 | int destroySet(fromJet, what, data) |
---|
495 | Jet fromJet; |
---|
496 | char *what; |
---|
497 | caddr_t data; |
---|
498 | { |
---|
499 | Set *set, *ptr; |
---|
500 | |
---|
501 | set = resolveName(what, NULL); |
---|
502 | if (set) |
---|
503 | { |
---|
504 | for (ptr = set; ptr != NULL; ptr = ptr->next) |
---|
505 | (void)destroyTree(fromJet, ptr->name, data); |
---|
506 | freeSet(set); |
---|
507 | } |
---|
508 | return 0; |
---|
509 | } |
---|
510 | |
---|
511 | int warpTree(fromJet, what, data) |
---|
512 | Jet fromJet; |
---|
513 | char *what; |
---|
514 | caddr_t data; |
---|
515 | { |
---|
516 | Jet w; |
---|
517 | |
---|
518 | w = XjFindJet(what, root); |
---|
519 | |
---|
520 | if (w != NULL) |
---|
521 | { |
---|
522 | w = w->core.child; |
---|
523 | if (w != NULL) |
---|
524 | XWarpPointer(w->core.display, |
---|
525 | None, |
---|
526 | w->core.window, |
---|
527 | 0, 0, 0, 0, |
---|
528 | w->core.width / 2, |
---|
529 | w->core.height / 2); |
---|
530 | return 0; |
---|
531 | } |
---|
532 | else |
---|
533 | { |
---|
534 | char errtext[100]; |
---|
535 | |
---|
536 | sprintf(errtext, "couldn't find %s to warp there", what); |
---|
537 | XjWarning(errtext); |
---|
538 | return 1; |
---|
539 | } |
---|
540 | } |
---|
541 | |
---|
542 | int warpSet(fromJet, what, data) |
---|
543 | Jet fromJet; |
---|
544 | char *what; |
---|
545 | caddr_t data; |
---|
546 | { |
---|
547 | Set *set; |
---|
548 | |
---|
549 | set = resolveName(what, NULL); |
---|
550 | if (set) |
---|
551 | { |
---|
552 | (void)warpTree(fromJet, set->name, data); |
---|
553 | freeSet(set); |
---|
554 | } |
---|
555 | return 0; |
---|
556 | } |
---|
557 | |
---|
558 | /* |
---|
559 | * Exec related callbacks |
---|
560 | */ |
---|
561 | int sh(fromJet, what, data) |
---|
562 | Jet fromJet; |
---|
563 | char *what; |
---|
564 | caddr_t data; |
---|
565 | { |
---|
566 | if (127 == system(what)) |
---|
567 | { |
---|
568 | XjWarning("couldn't execute shell"); |
---|
569 | return 1; |
---|
570 | } |
---|
571 | return 0; |
---|
572 | } |
---|
573 | |
---|
574 | /* |
---|
575 | * Translate the string "what," expanding %M, %S, etc, and place |
---|
576 | * it into the string "where." |
---|
577 | */ |
---|
578 | void expand(what, where) |
---|
579 | char *what, *where; |
---|
580 | { |
---|
581 | static int initialized = 0; |
---|
582 | static char sys[20], bin[20], sysdir[50], bindir[50], home[100]; |
---|
583 | char *start, *wherestart, *tmp, **found; |
---|
584 | struct stat bdir; |
---|
585 | |
---|
586 | if (initialized == 0) |
---|
587 | { |
---|
588 | initialized++; |
---|
589 | |
---|
590 | tmp = getenv("HOME"); |
---|
591 | if (tmp != NULL) |
---|
592 | strncpy(home, tmp, sizeof(home)/sizeof(char)); |
---|
593 | else |
---|
594 | sprintf(home, "nohome"); |
---|
595 | |
---|
596 | tmp = getenv("ATHENA_SYS"); |
---|
597 | if (tmp != NULL) |
---|
598 | strncpy(sys, tmp, sizeof(sys)/sizeof(char)); |
---|
599 | else |
---|
600 | sprintf(sys, "@sys"); |
---|
601 | |
---|
602 | tmp = getenv("HOSTTYPE"); |
---|
603 | if (tmp != NULL) |
---|
604 | strncpy(bin, tmp, sizeof(bin)/sizeof(char)); |
---|
605 | else |
---|
606 | strcpy(bin, HOSTTYPE); |
---|
607 | |
---|
608 | sprintf(sysdir, "arch/%s/bin", sys); |
---|
609 | sprintf(bindir, "%sbin", bin); |
---|
610 | } |
---|
611 | |
---|
612 | while (isspace(*what)) what++; |
---|
613 | start = what; |
---|
614 | wherestart = where; |
---|
615 | |
---|
616 | while (*what != '\0') |
---|
617 | { |
---|
618 | while (*what != '\0' && *what != '%' && *what != '~') |
---|
619 | *where++ = *what++; |
---|
620 | |
---|
621 | if (*what == '~' && what == start) |
---|
622 | { |
---|
623 | strncpy(where, home, strlen(home)); |
---|
624 | where += strlen(home); |
---|
625 | what++; |
---|
626 | } |
---|
627 | else |
---|
628 | if (*what == '%') |
---|
629 | { |
---|
630 | what++; |
---|
631 | switch(*what) |
---|
632 | { |
---|
633 | case '%': |
---|
634 | *where++ = '%'; |
---|
635 | what++; |
---|
636 | break; |
---|
637 | case 'M': |
---|
638 | strncpy(where, bin, strlen(bin)); |
---|
639 | where += strlen(bin); |
---|
640 | what++; |
---|
641 | break; |
---|
642 | case 'S': |
---|
643 | strncpy(where, sys, strlen(sys)); |
---|
644 | where += strlen(sys); |
---|
645 | what++; |
---|
646 | break; |
---|
647 | case 'B': |
---|
648 | /* Make tmp point to the beginning of the path we're |
---|
649 | * looking for binary directories under, and null |
---|
650 | * terminate it. |
---|
651 | */ |
---|
652 | tmp = where; |
---|
653 | if (where != wherestart) |
---|
654 | { |
---|
655 | tmp--; |
---|
656 | while (*tmp != ' ' && tmp > wherestart) |
---|
657 | tmp--; |
---|
658 | if (*tmp == ' ') tmp++; |
---|
659 | } |
---|
660 | *where = '\0'; |
---|
661 | |
---|
662 | /* Let athdir do the work... */ |
---|
663 | found = athdir_get_paths(tmp, "bin", |
---|
664 | NULL, NULL, NULL, NULL, 0); |
---|
665 | if (found) |
---|
666 | { |
---|
667 | /* Replace partially constructed path ending with |
---|
668 | * %B with the path athdir returned. |
---|
669 | */ |
---|
670 | strcpy(tmp, *found); |
---|
671 | where = tmp + strlen(*found); |
---|
672 | athdir_free_paths(found); |
---|
673 | } |
---|
674 | else |
---|
675 | { |
---|
676 | /* If we found nothing to substitute, don't. */ |
---|
677 | strcpy(where, "%B"); |
---|
678 | where += 2; |
---|
679 | } |
---|
680 | |
---|
681 | what++; |
---|
682 | break; |
---|
683 | default: |
---|
684 | *where++ = '%'; |
---|
685 | what++; |
---|
686 | } |
---|
687 | } |
---|
688 | } |
---|
689 | *where = '\0'; |
---|
690 | } |
---|
691 | |
---|
692 | static char *cwd = NULL; /* working directory for exec'ed programs */ |
---|
693 | static char *subject = NULL; |
---|
694 | static char buf[MAXPATHLEN]; |
---|
695 | static char addpath[MAXPATHLEN]; |
---|
696 | |
---|
697 | int setup(fromJet, what, data) |
---|
698 | caddr_t fromJet; |
---|
699 | char *what; |
---|
700 | caddr_t data; |
---|
701 | { |
---|
702 | subject = what; |
---|
703 | return 0; |
---|
704 | } |
---|
705 | |
---|
706 | int cd(fromJet, what, data) |
---|
707 | caddr_t fromJet; |
---|
708 | char *what; |
---|
709 | caddr_t data; |
---|
710 | { |
---|
711 | cwd = what; |
---|
712 | return 0; |
---|
713 | } |
---|
714 | |
---|
715 | void setupEnvironment() |
---|
716 | { |
---|
717 | char *path, *space; |
---|
718 | |
---|
719 | if (displayName != NULL) |
---|
720 | psetenv("DISPLAY", displayName, True); |
---|
721 | |
---|
722 | if (cwd != NULL) |
---|
723 | { |
---|
724 | expand(cwd, buf); |
---|
725 | if (-1 == chdir(buf)) |
---|
726 | { |
---|
727 | char errtext[100]; |
---|
728 | |
---|
729 | sprintf(errtext, "cd to %s failed with error %d", |
---|
730 | cwd, errno); |
---|
731 | XjWarning(errtext); |
---|
732 | } |
---|
733 | } |
---|
734 | |
---|
735 | if (subject != NULL) |
---|
736 | psetenv("SUBJECT", subject, True); |
---|
737 | |
---|
738 | if (*addpath != '\0') |
---|
739 | { |
---|
740 | path = (char *) getenv("PATH"); |
---|
741 | if (path == NULL) |
---|
742 | { |
---|
743 | space = XjMalloc((unsigned) MAXPATHLEN); |
---|
744 | space[0] = '\0'; |
---|
745 | } |
---|
746 | else |
---|
747 | { |
---|
748 | space = XjMalloc((unsigned) (MAXPATHLEN + strlen(path))); |
---|
749 | strcpy(space, path); |
---|
750 | strcat(space, ":"); |
---|
751 | } |
---|
752 | |
---|
753 | strcat(addpath, "/%B"); |
---|
754 | expand(addpath, &space[strlen(space)]); |
---|
755 | psetenv("PATH", space, True); |
---|
756 | } |
---|
757 | } |
---|
758 | |
---|
759 | |
---|
760 | int add(fromJet, what, data) |
---|
761 | Jet fromJet; |
---|
762 | char *what; |
---|
763 | caddr_t data; |
---|
764 | { |
---|
765 | int err; |
---|
766 | FILE *a; |
---|
767 | int l; |
---|
768 | sigset_t set, oset; |
---|
769 | char line1[100], line2[100]; |
---|
770 | |
---|
771 | line2[0] = '\0'; |
---|
772 | sprintf(addpath, "attach -p %s", what); |
---|
773 | (void) sigemptyset(&set); |
---|
774 | (void) sigaddset(&set, SIGCHLD); |
---|
775 | (void) sigprocmask(SIG_BLOCK, &set, &oset); |
---|
776 | if (NULL != (a = popen(addpath, "r"))) |
---|
777 | { |
---|
778 | fgets(addpath, MAXPATHLEN, a); |
---|
779 | err = pclose(a); |
---|
780 | (void) sigprocmask(SIG_SETMASK, &oset, NULL); |
---|
781 | |
---|
782 | if (err != 0) |
---|
783 | sprintf(line2, "Attach failed with error %d", err/256); |
---|
784 | else |
---|
785 | { |
---|
786 | l = strlen(addpath); |
---|
787 | if (l > 0) |
---|
788 | if (addpath[l - 1] == '\n') |
---|
789 | addpath[l - 1] = '\0'; |
---|
790 | return 0; |
---|
791 | } |
---|
792 | } |
---|
793 | (void) sigprocmask(SIG_SETMASK, &oset, NULL); |
---|
794 | sprintf(line1, "Could not attach %s", what); |
---|
795 | XjUserWarning(root, NULL, True, line1, line2); |
---|
796 | |
---|
797 | return 1; |
---|
798 | } |
---|
799 | |
---|
800 | int attach(fromJet, what, data) |
---|
801 | Jet fromJet; |
---|
802 | char *what; |
---|
803 | caddr_t data; |
---|
804 | { |
---|
805 | int err; |
---|
806 | |
---|
807 | err = add(fromJet, what, data); |
---|
808 | addpath[0] = '\0'; |
---|
809 | |
---|
810 | return err; |
---|
811 | } |
---|
812 | |
---|
813 | typedef struct _Child |
---|
814 | { |
---|
815 | struct _Child *next; |
---|
816 | int pid; |
---|
817 | char *title; |
---|
818 | } Child; |
---|
819 | |
---|
820 | static Child *firstChild = NULL; |
---|
821 | |
---|
822 | |
---|
823 | /* |
---|
824 | * Avoid zombies |
---|
825 | */ |
---|
826 | void checkChildren(sig) |
---|
827 | int sig; |
---|
828 | { |
---|
829 | Boolean found; |
---|
830 | Child *ch, **last; |
---|
831 | int child, status; |
---|
832 | |
---|
833 | while ((child = waitpid(-1, &status, WNOHANG)) > 0) |
---|
834 | { |
---|
835 | found = False; |
---|
836 | last = &firstChild; |
---|
837 | for (ch = firstChild; |
---|
838 | ch != NULL && !found; |
---|
839 | last = &ch->next, ch = ch->next) |
---|
840 | if (ch->pid == child) |
---|
841 | { |
---|
842 | found = True; |
---|
843 | *last = ch->next; |
---|
844 | |
---|
845 | if (WIFEXITED(status) && WEXITSTATUS(status)) |
---|
846 | { |
---|
847 | char line1[100]; |
---|
848 | |
---|
849 | sprintf(line1, "%s exited with status %d", |
---|
850 | ch->title, WEXITSTATUS(status)); |
---|
851 | XjUserWarning(root, NULL, True, line1, ""); |
---|
852 | } |
---|
853 | if (WIFSIGNALED(status) && WTERMSIG(status)) |
---|
854 | { |
---|
855 | char line1[100], line2[100]; |
---|
856 | |
---|
857 | sprintf(line1, "%s exited with signal %d", |
---|
858 | ch->title, WTERMSIG(status)); |
---|
859 | if (WCOREDUMP(status)) |
---|
860 | strcpy(line2, "(core dumped!)"); |
---|
861 | else |
---|
862 | line2[0] = '\0'; |
---|
863 | XjUserWarning(root, NULL, True, line1, line2); |
---|
864 | } |
---|
865 | |
---|
866 | XjFree((char *) ch); |
---|
867 | } |
---|
868 | } |
---|
869 | } |
---|
870 | |
---|
871 | char *NAME; /* oh no! a global variable! */ |
---|
872 | |
---|
873 | |
---|
874 | input(fd, name) |
---|
875 | int fd; |
---|
876 | char *name; |
---|
877 | { |
---|
878 | char buf[MAXPATHLEN]; |
---|
879 | char buf2[MAXPATHLEN + 7]; /* add some in for the length of errno */ |
---|
880 | int n; |
---|
881 | |
---|
882 | if (read(fd, buf2, MAXPATHLEN + 7)) |
---|
883 | { |
---|
884 | char line1[100], line2[100]; |
---|
885 | |
---|
886 | sscanf(buf2, "%s %d", buf, &n); |
---|
887 | sprintf(line1, "Could not start %s:", name); |
---|
888 | sprintf(line2, "%s: %s", buf, strerror(n)); |
---|
889 | XjUserWarning(root, NULL, True, line1, line2); |
---|
890 | } |
---|
891 | XjReadCallback((XjCallbackProc)NULL, fd, &fd); |
---|
892 | close(fd); |
---|
893 | } |
---|
894 | |
---|
895 | |
---|
896 | int exec(info, what, data) |
---|
897 | MenuInfo *info; |
---|
898 | char *what; |
---|
899 | caddr_t data; |
---|
900 | { |
---|
901 | int pid; |
---|
902 | char *ptr; |
---|
903 | int argc = 0; |
---|
904 | char *argv[100]; |
---|
905 | Child *ch; |
---|
906 | char *name; |
---|
907 | int fd[2]; |
---|
908 | int pipes; |
---|
909 | int num_fds; |
---|
910 | |
---|
911 | |
---|
912 | if (info != NULL && /* exec through menu item */ |
---|
913 | info->null == NULL) |
---|
914 | name = info->menu->title; |
---|
915 | else |
---|
916 | if (NAME != NULL) /* exec through verify, because verify */ |
---|
917 | { /* can't pass the menuinfo structure */ |
---|
918 | name = NAME; /* it got, since the menus may have */ |
---|
919 | NAME = NULL; /* rearranged by now. There _is_ a better */ |
---|
920 | } /* solution, but if I had time to do it, you */ |
---|
921 | else /* wouldn't be reading this! */ |
---|
922 | name = what; /* exec through non-menu item */ |
---|
923 | |
---|
924 | if ((pipes = pipe(fd))) |
---|
925 | { |
---|
926 | char line1[100], line2[100]; |
---|
927 | |
---|
928 | sprintf(line1, "Could not set up pipe: %s", strerror(errno)); |
---|
929 | sprintf(line2, "There will be no warning if `%s' can't be started.", |
---|
930 | name); |
---|
931 | XjUserWarning(root, NULL, True, line1, line2); |
---|
932 | } |
---|
933 | pipes = !pipes; |
---|
934 | |
---|
935 | pid = fork(); /* vfork will block indefinitely... :-( */ |
---|
936 | |
---|
937 | if (pid == -1) |
---|
938 | { |
---|
939 | char line1[100], line2[100]; |
---|
940 | |
---|
941 | sprintf(line1, "Could not start %s:", name); |
---|
942 | sprintf(line2, "Fork - %s", strerror(errno)); |
---|
943 | XjUserWarning(root, NULL, True, line1, line2); |
---|
944 | if (pipes) |
---|
945 | { |
---|
946 | close(fd[0]); |
---|
947 | close(fd[1]); |
---|
948 | } |
---|
949 | return 1; |
---|
950 | } |
---|
951 | |
---|
952 | if (pid != 0) /* We're in the parent... */ |
---|
953 | { |
---|
954 | addpath[0] = '\0'; |
---|
955 | cwd = NULL; |
---|
956 | subject = NULL; |
---|
957 | |
---|
958 | ch = (Child *)XjMalloc((unsigned) sizeof(Child)); |
---|
959 | ch->pid = pid; |
---|
960 | ch->title = name; |
---|
961 | ch->next = firstChild; |
---|
962 | firstChild = ch; |
---|
963 | |
---|
964 | if (pipes) |
---|
965 | { |
---|
966 | close(fd[1]); /* Parent reads on fd[0] */ |
---|
967 | XjReadCallback((XjCallbackProc)input, fd[0], name); |
---|
968 | } |
---|
969 | return 0; |
---|
970 | } |
---|
971 | |
---|
972 | setupEnvironment(); |
---|
973 | |
---|
974 | expand(what, buf); |
---|
975 | ptr = buf; |
---|
976 | |
---|
977 | while (*ptr != '\0') |
---|
978 | { |
---|
979 | while (isspace(*ptr)) |
---|
980 | ptr++; |
---|
981 | |
---|
982 | argv[argc++] = ptr; |
---|
983 | |
---|
984 | while (!isspace(*ptr) && *ptr != '\0') |
---|
985 | ptr++; |
---|
986 | |
---|
987 | if (*ptr != '\0') |
---|
988 | { |
---|
989 | *ptr = '\0'; |
---|
990 | ptr++; |
---|
991 | } |
---|
992 | |
---|
993 | } |
---|
994 | |
---|
995 | argv[argc] = NULL; |
---|
996 | |
---|
997 | for (num_fds = 3; num_fds < getdtablesize(); num_fds++) |
---|
998 | fcntl(num_fds, F_SETFD, 1); |
---|
999 | |
---|
1000 | if (-1 == execvp(argv[0], argv)) |
---|
1001 | { |
---|
1002 | char buf2[MAXPATHLEN + 7]; /* add some in for the length of errno */ |
---|
1003 | int n; |
---|
1004 | |
---|
1005 | /* Child writes on the wall with crayon... just kidding - fd[1] */ |
---|
1006 | if (pipes) |
---|
1007 | { |
---|
1008 | sprintf(buf2, "%s %d", buf, errno); |
---|
1009 | n = strlen(buf2); |
---|
1010 | if (write(fd[1], buf2, n) == n) |
---|
1011 | _exit(0); |
---|
1012 | } |
---|
1013 | _exit(42); |
---|
1014 | } |
---|
1015 | return 42; /* never reached, but makes saber happy... */ |
---|
1016 | } |
---|
1017 | |
---|
1018 | int restart(info, what, data) |
---|
1019 | MenuInfo *info; |
---|
1020 | char *what; |
---|
1021 | caddr_t data; |
---|
1022 | { |
---|
1023 | char *ptr; |
---|
1024 | int argc = 0; |
---|
1025 | char *argv[100]; |
---|
1026 | char line1[100], line2[100]; |
---|
1027 | |
---|
1028 | setupEnvironment(); |
---|
1029 | |
---|
1030 | if (what != NULL && |
---|
1031 | *what != '\0') |
---|
1032 | { |
---|
1033 | expand(what, buf); |
---|
1034 | ptr = buf; |
---|
1035 | |
---|
1036 | while (*ptr != '\0') |
---|
1037 | { |
---|
1038 | while (isspace(*ptr)) |
---|
1039 | ptr++; |
---|
1040 | |
---|
1041 | argv[argc++] = ptr; |
---|
1042 | |
---|
1043 | while (!isspace(*ptr) && *ptr != '\0') |
---|
1044 | ptr++; |
---|
1045 | |
---|
1046 | if (*ptr != '\0') |
---|
1047 | { |
---|
1048 | *ptr = '\0'; |
---|
1049 | ptr++; |
---|
1050 | } |
---|
1051 | } |
---|
1052 | execvp(argv[0], argv); |
---|
1053 | } |
---|
1054 | else |
---|
1055 | execvp(global_argv[0], global_argv); |
---|
1056 | |
---|
1057 | sprintf(line1, "Attempt to restart failed with error %d", errno); |
---|
1058 | sprintf(line2, "%s: %s", global_argv[0], strerror(errno)); |
---|
1059 | XjUserWarning(root, NULL, True, line1, line2); |
---|
1060 | return 1; |
---|
1061 | } |
---|
1062 | |
---|
1063 | int addMenus(info, file, data) |
---|
1064 | MenuInfo *info; |
---|
1065 | char *file; |
---|
1066 | caddr_t data; |
---|
1067 | { |
---|
1068 | if (info->null != NULL) /* we weren't called by menu code */ |
---|
1069 | return 1; |
---|
1070 | |
---|
1071 | return loadNewMenus(info->menubar, file); |
---|
1072 | } |
---|
1073 | |
---|
1074 | /* |
---|
1075 | * Danger Will Robinson! |
---|
1076 | * This mechanism makes it possible for callbacks to |
---|
1077 | * be called after the calling jet has already been |
---|
1078 | * destroyed. Ain't that special? |
---|
1079 | */ |
---|
1080 | typedef struct _vstruct { |
---|
1081 | Jet top; |
---|
1082 | Jet yes; |
---|
1083 | XjCallback me; |
---|
1084 | Menu *menu; |
---|
1085 | char *string; |
---|
1086 | char *title; |
---|
1087 | } Verify; |
---|
1088 | |
---|
1089 | int yesorno(who, v, data) |
---|
1090 | Jet who; |
---|
1091 | Verify *v; |
---|
1092 | caddr_t data; |
---|
1093 | { |
---|
1094 | XUnmapWindow(v->top->core.display, XjWindow(v->top)); |
---|
1095 | XFlush(v->top->core.display); |
---|
1096 | |
---|
1097 | if (v->yes == who) |
---|
1098 | { |
---|
1099 | NAME = v->title; |
---|
1100 | XjCallCallbacks((caddr_t) who, v->menu->activateProc, NULL); |
---|
1101 | } |
---|
1102 | |
---|
1103 | XjDestroyJet(v->top); |
---|
1104 | XjFree(v->string); |
---|
1105 | XjFree((char *) v); |
---|
1106 | return 0; |
---|
1107 | } |
---|
1108 | |
---|
1109 | int verify(info, foo, data) |
---|
1110 | MenuInfo *info; |
---|
1111 | int foo; |
---|
1112 | caddr_t data; |
---|
1113 | { |
---|
1114 | Verify *v; |
---|
1115 | Jet lqtop, lqform, logo, lqlabel, lqybutton, lqnbutton, |
---|
1116 | lqnwindow, lqywindow, lqylabel, lqnlabel; |
---|
1117 | |
---|
1118 | if (info->null != NULL) /* we weren't called by menu code */ |
---|
1119 | return 1; |
---|
1120 | |
---|
1121 | if (!parms.verifyOn) |
---|
1122 | { |
---|
1123 | XjCallCallbacks((caddr_t) info, info->menu->activateProc, NULL); |
---|
1124 | return 0; |
---|
1125 | } |
---|
1126 | |
---|
1127 | v = (Verify *)XjMalloc((unsigned) sizeof(Verify)); |
---|
1128 | |
---|
1129 | v->me.next = NULL; |
---|
1130 | v->me.argType = argPtr; |
---|
1131 | v->me.passPtr = v; |
---|
1132 | v->me.proc = yesorno; |
---|
1133 | v->menu = info->menu; |
---|
1134 | |
---|
1135 | lqtop = XjVaCreateJet("lqWindow", windowJetClass, root, NULL, NULL); |
---|
1136 | lqform = XjVaCreateJet("lqForm", formJetClass, lqtop, NULL, NULL); |
---|
1137 | |
---|
1138 | /* in this structure because that widget may need it forever, long |
---|
1139 | after it's off the stack and we have returned */ |
---|
1140 | v->title = info->menu->title; |
---|
1141 | v->string = XjMalloc((unsigned) (strlen(info->menu->title) + 1 |
---|
1142 | + strlen(parms.startString))); |
---|
1143 | sprintf(v->string, parms.startString, info->menu->title); |
---|
1144 | |
---|
1145 | logo = XjVaCreateJet("dashLogo", labelJetClass, lqform, |
---|
1146 | NULL, NULL); |
---|
1147 | lqlabel = XjVaCreateJet("lqLabel", labelJetClass, lqform, |
---|
1148 | XjNlabel, v->string, NULL, NULL); |
---|
1149 | lqywindow = XjVaCreateJet("lqYWindow", windowJetClass, lqform, NULL, NULL); |
---|
1150 | lqnwindow = XjVaCreateJet("lqNWindow", windowJetClass, lqform, NULL, NULL); |
---|
1151 | lqybutton = XjVaCreateJet("lqYButton", buttonJetClass, lqywindow, |
---|
1152 | XjNactivateProc, &(v->me), NULL, NULL); |
---|
1153 | lqnbutton = XjVaCreateJet("lqNButton", buttonJetClass, lqnwindow, |
---|
1154 | XjNactivateProc, &(v->me), NULL, NULL); |
---|
1155 | lqylabel = XjVaCreateJet("lqYLabel", labelJetClass, lqybutton, NULL, NULL); |
---|
1156 | lqnlabel = XjVaCreateJet("lqNLabel", labelJetClass, lqnbutton, NULL, NULL); |
---|
1157 | |
---|
1158 | v->top = lqtop; |
---|
1159 | v->yes = lqybutton; |
---|
1160 | |
---|
1161 | XjRealizeJet(lqtop); |
---|
1162 | return 0; |
---|
1163 | } |
---|
1164 | |
---|
1165 | |
---|
1166 | int toggleVerify(info, otherName, data) |
---|
1167 | MenuInfo *info; |
---|
1168 | char *otherName; |
---|
1169 | caddr_t data; |
---|
1170 | { |
---|
1171 | static int initialized = 0; |
---|
1172 | static char *onName, *offName; |
---|
1173 | |
---|
1174 | if (info->null != NULL) /* we weren't called by menu code */ |
---|
1175 | return 1; |
---|
1176 | |
---|
1177 | if (initialized == 0) |
---|
1178 | { |
---|
1179 | char *ptr = otherName; |
---|
1180 | |
---|
1181 | initialized = 1; |
---|
1182 | |
---|
1183 | /* Deal with star BS... */ |
---|
1184 | if (ptr[0] == ' ' && ptr[1] == ' ' && ptr[2] == ' ') |
---|
1185 | ptr += 3; |
---|
1186 | if (ptr[0] == '*' && ptr[1] == ' ') |
---|
1187 | ptr += 2; |
---|
1188 | /* Rip this code out in a future */ |
---|
1189 | /* release... */ |
---|
1190 | |
---|
1191 | if (parms.verifyOn) |
---|
1192 | { |
---|
1193 | onName = info->menu->title; |
---|
1194 | offName = ptr; |
---|
1195 | } |
---|
1196 | else |
---|
1197 | { |
---|
1198 | onName = ptr; |
---|
1199 | offName = info->menu->title; |
---|
1200 | } |
---|
1201 | } |
---|
1202 | |
---|
1203 | if (parms.verifyOn) |
---|
1204 | info->menu->title = offName; |
---|
1205 | else |
---|
1206 | info->menu->title = onName; |
---|
1207 | |
---|
1208 | parms.verifyOn = !parms.verifyOn; |
---|
1209 | |
---|
1210 | computeMenuSize(info->menubar, info->menu); |
---|
1211 | computeMenuSize(info->menubar, info->menu->parent); /* bug */ |
---|
1212 | return 0; |
---|
1213 | } |
---|
1214 | |
---|
1215 | int toggleHelp(info, otherName, data) |
---|
1216 | MenuInfo *info; |
---|
1217 | char *otherName; |
---|
1218 | caddr_t data; |
---|
1219 | { |
---|
1220 | static int initialized = 0; |
---|
1221 | static char *onName, *offName; |
---|
1222 | XjSize size; |
---|
1223 | |
---|
1224 | if (info->null != NULL) /* we weren't called by menu code */ |
---|
1225 | return 1; |
---|
1226 | |
---|
1227 | if (initialized == 0) |
---|
1228 | { |
---|
1229 | char *ptr = otherName; |
---|
1230 | |
---|
1231 | initialized = 1; |
---|
1232 | |
---|
1233 | /* Deal with star BS... */ |
---|
1234 | if (ptr[0] == ' ' && ptr[1] == ' ' && ptr[2] == ' ') |
---|
1235 | ptr += 3; |
---|
1236 | if (ptr[0] == '*' && ptr[1] == ' ') |
---|
1237 | ptr += 2; |
---|
1238 | /* Rip this code out in a future */ |
---|
1239 | /* release... */ |
---|
1240 | |
---|
1241 | if (info->menubar->menu.showHelp == 1) |
---|
1242 | { |
---|
1243 | onName = info->menu->title; |
---|
1244 | offName = ptr; |
---|
1245 | } |
---|
1246 | else |
---|
1247 | { |
---|
1248 | onName = ptr; |
---|
1249 | offName = info->menu->title; |
---|
1250 | } |
---|
1251 | } |
---|
1252 | |
---|
1253 | if (info->menubar->menu.showHelp == 1) |
---|
1254 | info->menu->title = offName; |
---|
1255 | else |
---|
1256 | info->menu->title = onName; |
---|
1257 | |
---|
1258 | info->menubar->menu.showHelp = !info->menubar->menu.showHelp; |
---|
1259 | |
---|
1260 | computeAllMenuSizes(info->menubar, info->menubar->menu.rootMenu); |
---|
1261 | computeRootMenuSize(info->menubar, &size); |
---|
1262 | return 0; |
---|
1263 | } |
---|
1264 | |
---|
1265 | int quit(fromJet, what, data) |
---|
1266 | caddr_t fromJet; |
---|
1267 | int what; |
---|
1268 | caddr_t data; |
---|
1269 | { |
---|
1270 | XjExit(what); |
---|
1271 | return 0; /* For linting... */ |
---|
1272 | } |
---|
1273 | |
---|
1274 | int enableGnome(fromJet, what, data) |
---|
1275 | caddr_t fromJet; |
---|
1276 | int what; |
---|
1277 | caddr_t data; |
---|
1278 | { |
---|
1279 | system("rm -f $HOME/.athena_dash_interface"); |
---|
1280 | return 0; /* For linting... */ |
---|
1281 | } |
---|
1282 | |
---|
1283 | int debug(fromJet, what, data) |
---|
1284 | caddr_t fromJet; |
---|
1285 | char *what; |
---|
1286 | caddr_t data; |
---|
1287 | { |
---|
1288 | fprintf(stdout, "malloced %d\n", malloced); |
---|
1289 | return 0; |
---|
1290 | } |
---|
1291 | |
---|
1292 | int usage(fromJet, what, data) |
---|
1293 | caddr_t fromJet; |
---|
1294 | char *what; |
---|
1295 | caddr_t data; |
---|
1296 | { |
---|
1297 | XjUsage(what); |
---|
1298 | return 0; |
---|
1299 | } |
---|
1300 | |
---|
1301 | int printMenu(info, what, data) |
---|
1302 | MenuInfo *info; |
---|
1303 | char *what; |
---|
1304 | caddr_t data; |
---|
1305 | { |
---|
1306 | if (info->null != NULL) /* we weren't called by menu code */ |
---|
1307 | return 1; |
---|
1308 | |
---|
1309 | PrintMenu(info->menubar); /* call only from a menu item. :-) */ |
---|
1310 | return 0; |
---|
1311 | } |
---|
1312 | |
---|
1313 | /* when the menu works without being overrideRedirect, this should |
---|
1314 | be made ICCCM compliant. */ |
---|
1315 | int lowerMenu(info, what, data) |
---|
1316 | MenuInfo *info; |
---|
1317 | char *what; |
---|
1318 | caddr_t data; |
---|
1319 | { |
---|
1320 | #ifndef sgi |
---|
1321 | if (info->null != NULL) |
---|
1322 | return 1; |
---|
1323 | |
---|
1324 | XLowerWindow(info->menubar->core.display, |
---|
1325 | info->menubar->core.window); |
---|
1326 | return 0; |
---|
1327 | #else |
---|
1328 | /* HACK HACK HACK |
---|
1329 | * If fam is running with icons on the background, it puts a window |
---|
1330 | * up in front of the root window but behind everything else, |
---|
1331 | * override redirect, but the full size of the screen. The code in |
---|
1332 | * the other half of this ifdef pushes dash behind that window |
---|
1333 | * where you can't see it. This is clearly not satisfactory. |
---|
1334 | */ |
---|
1335 | Window rooter, parent, *list; |
---|
1336 | WindowJet menuWindow; |
---|
1337 | int i; |
---|
1338 | unsigned int num; |
---|
1339 | XWindowAttributes win; |
---|
1340 | XWindowChanges config; |
---|
1341 | |
---|
1342 | if (info->null != NULL) |
---|
1343 | return 1; |
---|
1344 | |
---|
1345 | /* |
---|
1346 | * If the menu bar is not override redirect, we're ok. |
---|
1347 | * If XQueryTree fails, just lower ourselves. |
---|
1348 | */ |
---|
1349 | menuWindow = (WindowJet)info->menubar->core.parent; |
---|
1350 | if (menuWindow->window.overrideRedirect == False || |
---|
1351 | !XQueryTree(root->core.display, root->core.window, |
---|
1352 | &rooter, &parent, &list, &num)) |
---|
1353 | { |
---|
1354 | XLowerWindow(info->menubar->core.display, |
---|
1355 | info->menubar->core.window); |
---|
1356 | return 0; |
---|
1357 | } |
---|
1358 | |
---|
1359 | /* |
---|
1360 | * Start examining the children of the root from back to font. |
---|
1361 | */ |
---|
1362 | for (i = 0; i < num; i++) |
---|
1363 | { |
---|
1364 | /* Ignore ourselves. */ |
---|
1365 | if (list[i] == info->menubar->core.window) |
---|
1366 | continue; |
---|
1367 | |
---|
1368 | if (XGetWindowAttributes(root->core.display, list[i], &win)) |
---|
1369 | { |
---|
1370 | /* Is this the fam window? A fine heuristic. It's override |
---|
1371 | redirect, we can see it, and it takes up the whole |
---|
1372 | screen. */ |
---|
1373 | if (win.override_redirect == True && |
---|
1374 | win.map_state == IsViewable && |
---|
1375 | win.x == 0 && win.y == 0 && |
---|
1376 | win.width == root->core.width && |
---|
1377 | win.height == root->core.height) |
---|
1378 | break; |
---|
1379 | |
---|
1380 | /* Is this a normal viewable window? Then we're safe putting |
---|
1381 | ourselves behind it. (Or, in front of the window behind |
---|
1382 | it.) This catches the case where fam isn't actually |
---|
1383 | running. */ |
---|
1384 | if (win.override_redirect == False && |
---|
1385 | win.map_state == IsViewable) |
---|
1386 | { |
---|
1387 | if (i > 0) |
---|
1388 | i--; /* bug; we should probably really change |
---|
1389 | to Below, below, for this case */ |
---|
1390 | break; |
---|
1391 | } |
---|
1392 | } |
---|
1393 | |
---|
1394 | /* We didn't find the fam window or any viewable windows at all. |
---|
1395 | So we simply lower ourselves to the bottom. We could probably |
---|
1396 | just as well do nothing at all. */ |
---|
1397 | if (i == num) |
---|
1398 | { |
---|
1399 | XLowerWindow(info->menubar->core.display, |
---|
1400 | info->menubar->core.window); |
---|
1401 | XFree(list); |
---|
1402 | return 0; |
---|
1403 | } |
---|
1404 | } |
---|
1405 | |
---|
1406 | config.sibling = list[i]; |
---|
1407 | config.stack_mode = Above; |
---|
1408 | XConfigureWindow(root->core.display, info->menubar->core.window, |
---|
1409 | CWSibling | CWStackMode, &config); |
---|
1410 | |
---|
1411 | XFree(list); |
---|
1412 | return 0; |
---|
1413 | #endif |
---|
1414 | } |
---|
1415 | |
---|
1416 | int logout(fromJet, what, data) |
---|
1417 | caddr_t fromJet; |
---|
1418 | char *what; |
---|
1419 | caddr_t data; |
---|
1420 | { |
---|
1421 | char *pid_string; |
---|
1422 | int pid_int; |
---|
1423 | |
---|
1424 | if (pid_string = (char *) getenv("XSESSION")) |
---|
1425 | if (pid_int = atoi(pid_string)) |
---|
1426 | if (!kill(pid_int, SIGHUP)) |
---|
1427 | return 0; |
---|
1428 | |
---|
1429 | NAME = "logout"; |
---|
1430 | /*return exec(NULL, "/usr/athena/end_session", NULL);*/ |
---|
1431 | return exec(NULL, "end_session", NULL); |
---|
1432 | } |
---|
1433 | |
---|
1434 | fatal(display) |
---|
1435 | Display *display; |
---|
1436 | { |
---|
1437 | XjExit(-1); |
---|
1438 | } |
---|
1439 | |
---|
1440 | static int (*def_handler)(); |
---|
1441 | |
---|
1442 | static int handler(display, error) |
---|
1443 | Display *display; |
---|
1444 | XErrorEvent *error; |
---|
1445 | { |
---|
1446 | if (error->error_code == BadWindow || error->error_code == BadAtom) |
---|
1447 | return 0; |
---|
1448 | |
---|
1449 | def_handler(display, error); |
---|
1450 | return 0; /* it'll never get this far anyway... */ |
---|
1451 | } |
---|
1452 | |
---|
1453 | |
---|
1454 | |
---|
1455 | Window findDASH(display) |
---|
1456 | Display *display; |
---|
1457 | { |
---|
1458 | char *atom_name; |
---|
1459 | Atom actual_type; |
---|
1460 | int actual_format; |
---|
1461 | unsigned long nitems; |
---|
1462 | unsigned long bytes_after; |
---|
1463 | Window *prop; |
---|
1464 | unsigned char *name; |
---|
1465 | /* unsigned char *prop; */ |
---|
1466 | int status; |
---|
1467 | |
---|
1468 | #ifdef TIME_STARTUP |
---|
1469 | struct timeval start, end; |
---|
1470 | |
---|
1471 | gettimeofday(&start, NULL); |
---|
1472 | printf("findDASH: - %d.%d + \n", start.tv_sec, start.tv_usec); |
---|
1473 | #endif |
---|
1474 | |
---|
1475 | atom_name = (char *) XjMalloc(strlen(programName) + strlen(DASH_ATOM) |
---|
1476 | + 2); |
---|
1477 | sprintf(atom_name, "%s_%s", DASH_ATOM, programName); |
---|
1478 | nameAtom = XInternAtom(display, atom_name, False); |
---|
1479 | XjFree(atom_name); |
---|
1480 | |
---|
1481 | status = XGetWindowProperty(display, RootWindow(display, 0), |
---|
1482 | nameAtom, 0, 1, |
---|
1483 | False, AnyPropertyType, &actual_type, |
---|
1484 | &actual_format, &nitems, &bytes_after, |
---|
1485 | (unsigned char **) &prop); |
---|
1486 | if (status==BadWindow) |
---|
1487 | XjFatalError("rootWindow does not exist!"); |
---|
1488 | if (status!=Success) |
---|
1489 | return (Window) NULL; |
---|
1490 | if (! prop) |
---|
1491 | return (Window) NULL; |
---|
1492 | |
---|
1493 | def_handler = XSetErrorHandler(handler); |
---|
1494 | status = XGetWindowProperty(display, *prop, |
---|
1495 | dashAtom, 0, 1, |
---|
1496 | False, AnyPropertyType, &actual_type, |
---|
1497 | &actual_format, &nitems, &bytes_after, |
---|
1498 | &name); |
---|
1499 | (void) XSetErrorHandler(def_handler); |
---|
1500 | |
---|
1501 | if (status==BadWindow) |
---|
1502 | { |
---|
1503 | XjFatalError("rootWindow does not exist!"); |
---|
1504 | } |
---|
1505 | if (status!=Success) |
---|
1506 | { |
---|
1507 | return (Window) NULL; |
---|
1508 | } |
---|
1509 | |
---|
1510 | #ifdef TIME_STARTUP |
---|
1511 | gettimeofday(&end, NULL); |
---|
1512 | printf("findDASH: %d.%d = %d.%06.6d\n", end.tv_sec, end.tv_usec, |
---|
1513 | (end.tv_usec > start.tv_usec) |
---|
1514 | ? end.tv_sec - start.tv_sec |
---|
1515 | : end.tv_sec - start.tv_sec - 1, |
---|
1516 | (end.tv_usec > start.tv_usec) |
---|
1517 | ? end.tv_usec - start.tv_usec |
---|
1518 | : end.tv_usec + 1000000 - start.tv_usec ); |
---|
1519 | #endif |
---|
1520 | |
---|
1521 | if (!strcmp((char *)name, programName)) |
---|
1522 | { |
---|
1523 | XjFree(name); |
---|
1524 | return *prop; |
---|
1525 | } |
---|
1526 | |
---|
1527 | XjFree(name); |
---|
1528 | return (Window) NULL; |
---|
1529 | } |
---|
1530 | |
---|
1531 | |
---|
1532 | |
---|
1533 | Status sendEvent(display, window, opcode, data) |
---|
1534 | Display *display; |
---|
1535 | Window window; |
---|
1536 | char opcode; |
---|
1537 | char *data; |
---|
1538 | { |
---|
1539 | Status s; |
---|
1540 | XEvent e; |
---|
1541 | |
---|
1542 | e.xclient.type = ClientMessage; |
---|
1543 | e.xclient.window = window; |
---|
1544 | e.xclient.message_type = dashAtom; |
---|
1545 | e.xclient.format = 8; |
---|
1546 | memset(e.xclient.data.b, 0, sizeof(e.xclient.data.b)); |
---|
1547 | e.xclient.data.b[0] = opcode; |
---|
1548 | if (data) |
---|
1549 | strcpy(&e.xclient.data.b[1], data); |
---|
1550 | |
---|
1551 | if (s = XSendEvent(display, window, False, NoEventMask, &e)) |
---|
1552 | XFlush(display); |
---|
1553 | |
---|
1554 | return s; |
---|
1555 | } |
---|
1556 | |
---|
1557 | int delete(fromJet, what, data) |
---|
1558 | Jet fromJet; |
---|
1559 | char *what; |
---|
1560 | caddr_t data; |
---|
1561 | { |
---|
1562 | XjDestroyJet(fromJet); |
---|
1563 | return 0; |
---|
1564 | } |
---|
1565 | |
---|
1566 | int deleteParent(fromJet, what, data) |
---|
1567 | Jet fromJet; |
---|
1568 | char *what; |
---|
1569 | caddr_t data; |
---|
1570 | { |
---|
1571 | XjDestroyJet(XjParent(fromJet)); |
---|
1572 | return 0; |
---|
1573 | } |
---|
1574 | |
---|
1575 | int message(info, zilch, data) |
---|
1576 | WindowInfo *info; |
---|
1577 | char *zilch; |
---|
1578 | caddr_t data; |
---|
1579 | { |
---|
1580 | char errtext[100]; |
---|
1581 | info->event->xclient.data.b[19] = '\0'; /* just in case */ |
---|
1582 | |
---|
1583 | if (info->event->xclient.message_type == dashAtom) |
---|
1584 | switch(info->event->xclient.data.b[0]) |
---|
1585 | { |
---|
1586 | case DASH_NOP: |
---|
1587 | break; |
---|
1588 | case DASH_DEBUG: |
---|
1589 | DEBUG = !DEBUG; |
---|
1590 | printTree(NULL, NULL, NULL); |
---|
1591 | break; |
---|
1592 | case DASH_KILL: |
---|
1593 | XjExit(0); |
---|
1594 | break; |
---|
1595 | case DASH_CREATE: |
---|
1596 | createSet(NULL, &info->event->xclient.data.b[1], NULL); |
---|
1597 | break; |
---|
1598 | case DASH_DESTROY: |
---|
1599 | destroySet(NULL, &info->event->xclient.data.b[1], NULL); |
---|
1600 | break; |
---|
1601 | case DASH_MAP: |
---|
1602 | mapSet(NULL, &info->event->xclient.data.b[1], NULL); |
---|
1603 | break; |
---|
1604 | case DASH_UNMAP: |
---|
1605 | unmapSet(NULL, &info->event->xclient.data.b[1], NULL); |
---|
1606 | break; |
---|
1607 | case DASH_CREATEORMAP: |
---|
1608 | createMapSet(NULL, &info->event->xclient.data.b[1], NULL); |
---|
1609 | break; |
---|
1610 | case DASH_RESTART: |
---|
1611 | restart(NULL, NULL, NULL); |
---|
1612 | break; |
---|
1613 | default: |
---|
1614 | sprintf(errtext, "unknown ClientMessage opcode: %d\n", |
---|
1615 | (int)info->event->xclient.data.b[0]); |
---|
1616 | break; |
---|
1617 | } |
---|
1618 | else |
---|
1619 | { |
---|
1620 | sprintf(errtext, "unrecognized ClientMessage: %d\n", |
---|
1621 | info->event->xclient.message_type); |
---|
1622 | XjWarning(errtext); |
---|
1623 | return 1; |
---|
1624 | } |
---|
1625 | |
---|
1626 | return 0; |
---|
1627 | } |
---|
1628 | |
---|
1629 | /* |
---|
1630 | struct loadInfo { |
---|
1631 | FILE *f; |
---|
1632 | StripChartJet who; |
---|
1633 | }; |
---|
1634 | |
---|
1635 | void getLoad(fd, info) |
---|
1636 | int fd; |
---|
1637 | struct loadInfo *info; |
---|
1638 | { |
---|
1639 | char s[40]; |
---|
1640 | int l1, l2, l3; |
---|
1641 | |
---|
1642 | fscanf(info->f, "%s %d.%d[%d]\n", s, &l1, &l2, &l3); |
---|
1643 | XjStripChartData(info->who, 100*l1+l2); |
---|
1644 | } |
---|
1645 | |
---|
1646 | int load(init, foo, data) |
---|
1647 | StripChartInit *init; |
---|
1648 | int foo; |
---|
1649 | caddr_t data; |
---|
1650 | { |
---|
1651 | FILE *loadFile; |
---|
1652 | char command[80]; |
---|
1653 | struct loadInfo *info; |
---|
1654 | |
---|
1655 | sprintf(command, "%s %d", LOADST, init->interval/1000); |
---|
1656 | loadFile = popen(command, "r"); |
---|
1657 | info = (struct loadInfo *)XjMalloc(sizeof(struct loadInfo)); |
---|
1658 | info->who = init->j; |
---|
1659 | info->f = loadFile; |
---|
1660 | |
---|
1661 | XjReadCallback((XjCallbackProc)getLoad, fileno(loadFile), info); |
---|
1662 | return 0; |
---|
1663 | } |
---|
1664 | |
---|
1665 | int cpu(where) |
---|
1666 | int *where; |
---|
1667 | { |
---|
1668 | double l; |
---|
1669 | |
---|
1670 | getcpu(NULL, NULL, &l); |
---|
1671 | *where = (int)(l * 100.0); |
---|
1672 | return 0; |
---|
1673 | } |
---|
1674 | |
---|
1675 | int pstat(where) |
---|
1676 | int *where; |
---|
1677 | { |
---|
1678 | FILE *ps; |
---|
1679 | static int Pused, Ptext, Pfree, Pwasted, Pmissing; |
---|
1680 | static int Pnum[6], Psize[6]; |
---|
1681 | static struct timeval last = { 0, 0 }; |
---|
1682 | struct timeval now; |
---|
1683 | |
---|
1684 | gettimeofday(&now, NULL); |
---|
1685 | if (now.tv_sec - last.tv_sec > 60) |
---|
1686 | { |
---|
1687 | last = now; |
---|
1688 | |
---|
1689 | ps = popen("/etc/pstat -s", "r"); |
---|
1690 | |
---|
1691 | fscanf(ps, "%dk used (%dk text), %dk free, %dk wasted, %dk missing\n", |
---|
1692 | &Pused, &Ptext, &Pfree, &Pwasted, &Pmissing); |
---|
1693 | fscanf(ps, "avail: %d*%dk %d*%dk %d*%dk %d*%dk %d*%dk %d*%dk\n", |
---|
1694 | &Pnum[0], &Psize[0], &Pnum[1], &Psize[1], &Pnum[2], &Psize[2], |
---|
1695 | &Pnum[3], &Psize[3], &Pnum[4], &Psize[4], &Pnum[5], &Psize[5]); |
---|
1696 | |
---|
1697 | pclose(ps); |
---|
1698 | } |
---|
1699 | |
---|
1700 | *where = 100 * Pused / (Pused + Pfree + Pwasted + Pmissing); |
---|
1701 | |
---|
1702 | return 0; |
---|
1703 | } |
---|
1704 | */ |
---|
1705 | |
---|
1706 | |
---|
1707 | int std_out(fromJet, what, data) |
---|
1708 | Jet fromJet; |
---|
1709 | char *what; |
---|
1710 | caddr_t data; |
---|
1711 | { |
---|
1712 | printf(what); |
---|
1713 | fflush(stdout); |
---|
1714 | return 0; /* For linting... */ |
---|
1715 | } |
---|
1716 | |
---|
1717 | int std_err(fromJet, what, data) |
---|
1718 | Jet fromJet; |
---|
1719 | char *what; |
---|
1720 | caddr_t data; |
---|
1721 | { |
---|
1722 | fprintf(stderr, what); |
---|
1723 | fflush(stderr); |
---|
1724 | return 0; /* For linting... */ |
---|
1725 | } |
---|
1726 | |
---|
1727 | |
---|
1728 | XjCallbackRec callbacks[] = |
---|
1729 | { |
---|
1730 | /* tree operations */ |
---|
1731 | { "createTree", createTree }, |
---|
1732 | { "createMapTree", createMapTree }, |
---|
1733 | { "destroyTree", destroyTree }, |
---|
1734 | { "warpTree", warpTree }, |
---|
1735 | { "mapTree", mapTree }, |
---|
1736 | { "unmapTree", unmapTree }, |
---|
1737 | { "printTree", printTree }, |
---|
1738 | /* set operations */ |
---|
1739 | { "createSet", createSet }, |
---|
1740 | { "createMapSet", createMapSet }, |
---|
1741 | { "destroySet", destroySet }, |
---|
1742 | { "warpSet", warpSet }, |
---|
1743 | { "mapSet", mapSet }, |
---|
1744 | { "unmapSet", unmapSet }, |
---|
1745 | /* misc */ |
---|
1746 | { "quit", quit }, |
---|
1747 | { "exec", exec }, |
---|
1748 | { "sh", sh }, |
---|
1749 | { "toggleHelp", toggleHelp }, |
---|
1750 | { "toggleVerify", toggleVerify }, |
---|
1751 | { "debug", debug }, |
---|
1752 | { "usage", usage }, |
---|
1753 | { "logout", logout }, |
---|
1754 | { "delete", delete }, |
---|
1755 | { "deleteParent", deleteParent }, |
---|
1756 | { "printMenu", printMenu }, |
---|
1757 | { "lowerMenu", lowerMenu }, |
---|
1758 | { "cd", cd }, |
---|
1759 | { "attach", attach }, |
---|
1760 | { "add", add }, |
---|
1761 | { "setup", setup }, |
---|
1762 | { "addMenus", addMenus }, |
---|
1763 | { "verify", verify }, |
---|
1764 | { "restart", restart }, |
---|
1765 | { "message", message }, |
---|
1766 | { "stdout", std_out }, |
---|
1767 | { "stderr", std_err }, |
---|
1768 | { "enableGnome", enableGnome }, |
---|
1769 | /* |
---|
1770 | { "load", load }, |
---|
1771 | { "cpu", cpu }, |
---|
1772 | { "pstat", pstat }, |
---|
1773 | */ |
---|
1774 | }; |
---|
1775 | |
---|
1776 | main(argc, argv) |
---|
1777 | int argc; |
---|
1778 | char **argv; |
---|
1779 | { |
---|
1780 | Display *display; |
---|
1781 | char *home; |
---|
1782 | char userFile[100]; |
---|
1783 | Window handle = (Window) NULL; |
---|
1784 | int cd[50]; |
---|
1785 | Set *tmp, *list; |
---|
1786 | char *nameOptions[50]; |
---|
1787 | int i, numOptions = 0; |
---|
1788 | int count, sign = 1; |
---|
1789 | Status e; |
---|
1790 | Jet handlejet; |
---|
1791 | struct sigaction act; |
---|
1792 | sigemptyset(&act.sa_mask); |
---|
1793 | act.sa_flags = 0; |
---|
1794 | |
---|
1795 | expand("~/.dashrc", userFile); /* Also guarantees expand() is initialized |
---|
1796 | in this process, not multiple times in |
---|
1797 | children. */ |
---|
1798 | |
---|
1799 | (void)XSetIOErrorHandler(fatal); |
---|
1800 | |
---|
1801 | root = XjCreateRoot(&argc, argv, DASH, userFile, |
---|
1802 | opTable, XjNumber(opTable)); |
---|
1803 | |
---|
1804 | XjLoadFromResources(NULL, |
---|
1805 | NULL, |
---|
1806 | programClass, |
---|
1807 | programName, |
---|
1808 | appResources, |
---|
1809 | XjNumber(appResources), |
---|
1810 | (caddr_t) &parms); |
---|
1811 | display = root->core.display; |
---|
1812 | |
---|
1813 | dashAtom = XInternAtom(display, DASH_ATOM, False); |
---|
1814 | |
---|
1815 | /* |
---|
1816 | * Parse special creation options out of command line. |
---|
1817 | */ |
---|
1818 | argv++; |
---|
1819 | while (*argv) |
---|
1820 | { |
---|
1821 | if (!strcmp(*argv, "-show")) |
---|
1822 | sign = 1; |
---|
1823 | else |
---|
1824 | { |
---|
1825 | if (!strcmp(*argv, "-hide")) |
---|
1826 | sign = 0; |
---|
1827 | else |
---|
1828 | { |
---|
1829 | if (**argv == '+' || **argv == '-') |
---|
1830 | { |
---|
1831 | cd[numOptions] = (**argv) == '+' ? 0 : 1; |
---|
1832 | nameOptions[numOptions++] = *argv + 1; |
---|
1833 | } |
---|
1834 | else |
---|
1835 | { |
---|
1836 | cd[numOptions] = sign; |
---|
1837 | nameOptions[numOptions++] = *argv; |
---|
1838 | } |
---|
1839 | } |
---|
1840 | } |
---|
1841 | argv++; |
---|
1842 | } |
---|
1843 | |
---|
1844 | if (numOptions == 0) |
---|
1845 | { |
---|
1846 | nameOptions[0] = "default"; |
---|
1847 | cd[0] = 1; |
---|
1848 | numOptions = 1; |
---|
1849 | } |
---|
1850 | |
---|
1851 | if (!parms.run) /* don't get a handle if we don't care */ |
---|
1852 | handle = findDASH(display); |
---|
1853 | |
---|
1854 | if (!handle && (parms.send || parms.kill)) |
---|
1855 | { |
---|
1856 | /* try harder... */ |
---|
1857 | count = 3; |
---|
1858 | while (!handle && count) |
---|
1859 | { |
---|
1860 | sleep(10); |
---|
1861 | handle = findDASH(display); |
---|
1862 | count--; |
---|
1863 | } |
---|
1864 | |
---|
1865 | if (!handle) |
---|
1866 | { |
---|
1867 | char errtext[100]; |
---|
1868 | |
---|
1869 | sprintf(errtext, "couldn't find a running %s", programName); |
---|
1870 | XjWarning(errtext); |
---|
1871 | XjExit(1); |
---|
1872 | } |
---|
1873 | } |
---|
1874 | |
---|
1875 | /* |
---|
1876 | * -kill |
---|
1877 | */ |
---|
1878 | if (handle && parms.kill) |
---|
1879 | { |
---|
1880 | if (sendEvent(display, handle, DASH_KILL, NULL)) |
---|
1881 | XjExit(0); |
---|
1882 | else |
---|
1883 | XjFatalError("sendEvent failed"); |
---|
1884 | } |
---|
1885 | |
---|
1886 | /* |
---|
1887 | * -restart |
---|
1888 | */ |
---|
1889 | if (handle && parms.restart) |
---|
1890 | { |
---|
1891 | if (sendEvent(display, handle, DASH_RESTART, NULL)) |
---|
1892 | XjExit(0); |
---|
1893 | else |
---|
1894 | XjFatalError("sendEvent failed"); |
---|
1895 | } |
---|
1896 | |
---|
1897 | /* |
---|
1898 | * -debug |
---|
1899 | */ |
---|
1900 | if (handle && parms.debug) |
---|
1901 | { |
---|
1902 | if (sendEvent(display, handle, DASH_DEBUG, NULL)) |
---|
1903 | XjExit(0); |
---|
1904 | else |
---|
1905 | XjFatalError("sendEvent failed"); |
---|
1906 | } |
---|
1907 | |
---|
1908 | /* |
---|
1909 | * Either -send, or a dash exists and not -run |
---|
1910 | */ |
---|
1911 | if (handle) |
---|
1912 | { |
---|
1913 | for (i = 0; i < numOptions; i++) |
---|
1914 | { |
---|
1915 | if (cd[i] == 0) |
---|
1916 | e = sendEvent(display, handle, DASH_UNMAP, nameOptions[i]); |
---|
1917 | else |
---|
1918 | e = sendEvent(display, handle, DASH_CREATEORMAP, nameOptions[i]); |
---|
1919 | if (!e) |
---|
1920 | XjFatalError("sendEvent failed"); |
---|
1921 | } |
---|
1922 | XjExit(0); |
---|
1923 | } |
---|
1924 | |
---|
1925 | /* |
---|
1926 | * Now we deal with the rest of the command line args... |
---|
1927 | */ |
---|
1928 | if (!parms.nofork) |
---|
1929 | { |
---|
1930 | switch (fork()) |
---|
1931 | { |
---|
1932 | case 0: /* child */ |
---|
1933 | break; |
---|
1934 | case -1: /* error */ |
---|
1935 | perror ("Can't fork"); |
---|
1936 | XjExit(-1); |
---|
1937 | default: /* parent */ |
---|
1938 | XjExit(0); |
---|
1939 | } |
---|
1940 | } |
---|
1941 | |
---|
1942 | if (parms.startString == NULL) |
---|
1943 | parms.startString = "Start %s?"; |
---|
1944 | |
---|
1945 | DEBUG = parms.debug; |
---|
1946 | |
---|
1947 | XjRegisterCallbacks(callbacks, XjNumber(callbacks)); |
---|
1948 | |
---|
1949 | for (i = 0; i < numOptions; i++) |
---|
1950 | { |
---|
1951 | tmp = resolveName(nameOptions[i], NULL); |
---|
1952 | if (cd[i] == 1) |
---|
1953 | for (list = tmp; list != NULL; list = list->next) |
---|
1954 | (void)XjVaCreateJet(list->name, treeJetClass, root, NULL, NULL); |
---|
1955 | freeSet(tmp); |
---|
1956 | } |
---|
1957 | |
---|
1958 | XjRealizeJet(root); |
---|
1959 | /* |
---|
1960 | * Okay, so there is no handle... we'll create one and install the |
---|
1961 | * property on the root. |
---|
1962 | */ |
---|
1963 | handlejet = XjVaCreateJet("handleWindow", windowJetClass, root, |
---|
1964 | XjNoverrideRedirect, True, |
---|
1965 | XjNmapped, False, |
---|
1966 | XjNx, -100, |
---|
1967 | XjNy, -100, |
---|
1968 | XjNwidth, 1, |
---|
1969 | XjNheight, 1, |
---|
1970 | XjNtitle, DASH_ATOM, |
---|
1971 | NULL, NULL); |
---|
1972 | XjRealizeJet(handlejet); |
---|
1973 | handle = XjWindow(handlejet); |
---|
1974 | XChangeProperty(display, handle, dashAtom, |
---|
1975 | XA_STRING, 8, PropModeReplace, |
---|
1976 | (unsigned char *) programName, strlen(programName)); |
---|
1977 | XChangeProperty(display, RootWindow(display, 0), nameAtom, |
---|
1978 | XA_WINDOW, 32, PropModeReplace, |
---|
1979 | (unsigned char *) &handle, 1); |
---|
1980 | XFlush(display); |
---|
1981 | |
---|
1982 | |
---|
1983 | |
---|
1984 | act.sa_handler= (void (*)())checkChildren; |
---|
1985 | (void) sigaction(SIGCHLD, &act, NULL); |
---|
1986 | |
---|
1987 | #ifdef HAVE_KRB4 |
---|
1988 | if (parms.checkTickets) |
---|
1989 | checkTkts(0,0); |
---|
1990 | #endif /* HAVE_KRB4 */ |
---|
1991 | |
---|
1992 | XjEventLoop(root); |
---|
1993 | } |
---|