1 | /* Copyright 1990, 1991, 1998 by the Massachusetts Institute of Technology. |
---|
2 | * |
---|
3 | * Permission to use, copy, modify, and distribute this |
---|
4 | * software and its documentation for any purpose and without |
---|
5 | * fee is hereby granted, provided that the above copyright |
---|
6 | * notice appear in all copies and that both that copyright |
---|
7 | * notice and this permission notice appear in supporting |
---|
8 | * documentation, and that the name of M.I.T. not be used in |
---|
9 | * advertising or publicity pertaining to distribution of the |
---|
10 | * software without specific, written prior permission. |
---|
11 | * M.I.T. makes no representations about the suitability of |
---|
12 | * this software for any purpose. It is provided "as is" |
---|
13 | * without express or implied warranty. |
---|
14 | */ |
---|
15 | |
---|
16 | static const char rcsid[] = "$Id: console.c,v 1.1 1998-12-17 16:26:02 ghudson Exp $"; |
---|
17 | |
---|
18 | #include <stdio.h> |
---|
19 | #include <stdlib.h> |
---|
20 | #include <sys/types.h> |
---|
21 | #include <fcntl.h> |
---|
22 | #include <ctype.h> |
---|
23 | #include <sys/time.h> |
---|
24 | #include <sys/file.h> |
---|
25 | #include <sys/stat.h> |
---|
26 | #include <errno.h> |
---|
27 | #include <signal.h> |
---|
28 | #include <syslog.h> |
---|
29 | #include <Jets/Jets.h> |
---|
30 | #include <Jets/Window.h> |
---|
31 | #include <Jets/Button.h> |
---|
32 | #include <Jets/Label.h> |
---|
33 | #include <Jets/Form.h> |
---|
34 | #include <Jets/ScrollBar.h> |
---|
35 | #include <Jets/TextDisplay.h> |
---|
36 | #include <Jets/Arrow.h> |
---|
37 | #include <X11/Xresource.h> |
---|
38 | |
---|
39 | #ifndef CONSOLEDEFAULTS |
---|
40 | #define CONSOLEDEFAULTS "/etc/athena/login/Console" |
---|
41 | #endif |
---|
42 | |
---|
43 | #define XENV "XENVIRONMENT" |
---|
44 | #define CONSOLEFILE "/var/athena/console.log" |
---|
45 | |
---|
46 | extern int DEBUG; |
---|
47 | |
---|
48 | static XrmOptionDescRec opTable[] = { |
---|
49 | {"+rv", "*reverseVideo", XrmoptionNoArg, (caddr_t) "off"}, |
---|
50 | {"-background", "*background", XrmoptionSepArg, (caddr_t) NULL}, |
---|
51 | {"-bd", "*window.borderColor", XrmoptionSepArg, (caddr_t) NULL}, |
---|
52 | {"-bg", "*background", XrmoptionSepArg, (caddr_t) NULL}, |
---|
53 | {"-bordercolor","*borderColor", XrmoptionSepArg, (caddr_t) NULL}, |
---|
54 | {"-borderwidth","*window.borderWidth", XrmoptionSepArg, (caddr_t) NULL}, |
---|
55 | {"-bw", "*window.borderWidth", XrmoptionSepArg, (caddr_t) NULL}, |
---|
56 | {"-display", ".display", XrmoptionSepArg, (caddr_t) NULL}, |
---|
57 | {"-fg", "*foreground", XrmoptionSepArg, (caddr_t) NULL}, |
---|
58 | {"-fn", "*font", XrmoptionSepArg, (caddr_t) NULL}, |
---|
59 | {"-font", "*font", XrmoptionSepArg, (caddr_t) NULL}, |
---|
60 | {"-foreground", "*foreground", XrmoptionSepArg, (caddr_t) NULL}, |
---|
61 | {"-geometry", "*window.geometry", XrmoptionSepArg, (caddr_t) NULL}, |
---|
62 | {"-icongeometry", "*iconWindow.geometry", XrmoptionSepArg, (caddr_t) NULL}, |
---|
63 | {"-name", ".name", XrmoptionSepArg, (caddr_t) NULL}, |
---|
64 | {"-reverse", "*reverseVideo", XrmoptionNoArg, (caddr_t) "on"}, |
---|
65 | {"-rv", "*reverseVideo", XrmoptionNoArg, (caddr_t) "on"}, |
---|
66 | {"-xrm", NULL, XrmoptionResArg, (caddr_t) NULL}, |
---|
67 | {"-appdefs", ".appDefs", XrmoptionSepArg, (caddr_t) NULL}, |
---|
68 | {"-f", ".appDefs", XrmoptionSepArg, (caddr_t) NULL}, |
---|
69 | {"-blink", ".frequency", XrmoptionSepArg, (caddr_t) NULL}, |
---|
70 | {"-unmap", ".autoUnmap", XrmoptionSepArg, (caddr_t) NULL}, |
---|
71 | {"-map", "*window.mapped", XrmoptionNoArg, (caddr_t) "True"}, |
---|
72 | {"+map", "*window.mapped", XrmoptionNoArg, (caddr_t) "False"}, |
---|
73 | {"-input", ".input", XrmoptionSepArg, (caddr_t) NULL}, |
---|
74 | {"-inputfd", ".inputfd", XrmoptionSepArg, (caddr_t) NULL}, |
---|
75 | {"-nostdin", ".nostdin", XrmoptionNoArg, (caddr_t) "True"}, |
---|
76 | {"-iconic", "*window.iconic", XrmoptionNoArg, (caddr_t) "True"}, |
---|
77 | {"+iconic", "*window.iconic", XrmoptionNoArg, (caddr_t) "False"}, |
---|
78 | {"-notimestamp",".timestamp", XrmoptionNoArg, (caddr_t) "False"}, |
---|
79 | {"-timestamp", ".timestamp", XrmoptionNoArg, (caddr_t) "True"}, |
---|
80 | {"-hidelabel", "*hideLabel.label", XrmoptionSepArg, (caddr_t) NULL}, |
---|
81 | {"-title", "*title.label", XrmoptionSepArg, (caddr_t) NULL}, |
---|
82 | {"-hideproc", "*hideButton.activateProc", XrmoptionSepArg, (caddr_t) NULL}, |
---|
83 | {"-cc", "*textDisplay.charClass", XrmoptionSepArg, (caddr_t) NULL}, |
---|
84 | {"-titlebar", "*window.title",XrmoptionSepArg, (caddr_t) NULL}, |
---|
85 | {"-nosession", "*showCommand", XrmoptionNoArg, (caddr_t) "false"}, |
---|
86 | {"-global", "*global", XrmoptionNoArg, (caddr_t) "true"}, |
---|
87 | {"-autoscroll", ".autoscroll", XrmoptionNoArg, (caddr_t) "True"}, |
---|
88 | {"-noautoscroll",".autoscroll", XrmoptionNoArg, (caddr_t) "False"}, |
---|
89 | {"-file", ".file", XrmoptionSepArg, (caddr_t) ""}, |
---|
90 | {"-debug", ".debug", XrmoptionNoArg, (caddr_t) "true"}, |
---|
91 | }; |
---|
92 | |
---|
93 | typedef struct _MyResources |
---|
94 | { |
---|
95 | int frequency, autoUnmap; |
---|
96 | char *input; |
---|
97 | int inputfd; |
---|
98 | Boolean timestamp, autoscroll, nostdin; |
---|
99 | char *file; |
---|
100 | Boolean debug; |
---|
101 | } MyResources; |
---|
102 | |
---|
103 | typedef struct _MyResources *MyResourcesPtr; |
---|
104 | |
---|
105 | MyResources parms; |
---|
106 | |
---|
107 | #define offset(field) XjOffset(MyResourcesPtr,field) |
---|
108 | |
---|
109 | static XjResource appResources[] = |
---|
110 | { |
---|
111 | { "frequency", "Frequency", XjRInt, sizeof(int), |
---|
112 | offset(frequency), XjRInt, (caddr_t)1000 }, |
---|
113 | { "autoUnmap", "AutoUnmap", XjRInt, sizeof(int), |
---|
114 | offset(autoUnmap), XjRInt, (caddr_t)0 }, |
---|
115 | { "input", "Input", XjRString, sizeof(char *), |
---|
116 | offset(input), XjRString, (caddr_t)"" }, |
---|
117 | { "inputfd", "Inputfd", XjRInt, sizeof(int), |
---|
118 | offset(inputfd), XjRInt, (caddr_t)0 }, |
---|
119 | { "nostdin", "Nostdin", XjRBoolean, sizeof(Boolean), |
---|
120 | offset(nostdin), XjRBoolean, (caddr_t) False }, |
---|
121 | { "timestamp", "Timestamp", XjRBoolean, sizeof(Boolean), |
---|
122 | offset(timestamp), XjRBoolean, (caddr_t) True }, |
---|
123 | { "autoscroll", "Autoscroll", XjRBoolean, sizeof(Boolean), |
---|
124 | offset(autoscroll), XjRBoolean, (caddr_t) True }, |
---|
125 | { "file", "File", XjRString, sizeof(char *), |
---|
126 | offset(file), XjRString, (caddr_t)CONSOLEFILE }, |
---|
127 | { "debug", "Debug", XjRBoolean, sizeof(Boolean), |
---|
128 | offset(debug), XjRBoolean, (caddr_t) False }, |
---|
129 | }; |
---|
130 | |
---|
131 | #undef offset |
---|
132 | |
---|
133 | #define INPUTSIZE 1024 |
---|
134 | char inputbuf[INPUTSIZE]; |
---|
135 | |
---|
136 | #define BUFSIZE 16384 /* must be at least two times as big as INPUTSIZE */ |
---|
137 | char *text; |
---|
138 | int length; |
---|
139 | |
---|
140 | |
---|
141 | #define HUP 0 |
---|
142 | #define FPE 1 |
---|
143 | #define USR1 2 |
---|
144 | #define USR2 3 |
---|
145 | #define NUMSIGS 4 |
---|
146 | int sigflags[NUMSIGS]; |
---|
147 | int val = 0; |
---|
148 | Jet root; |
---|
149 | WindowJet iconWindow; |
---|
150 | LabelJet icon; |
---|
151 | WindowJet win; |
---|
152 | ScrollBarJet sj; |
---|
153 | TextDisplayJet tj; |
---|
154 | int inverted = False, blinking = False, timerid; |
---|
155 | int unmaptimerid; |
---|
156 | |
---|
157 | |
---|
158 | static int loadFile(filename, info, max) |
---|
159 | char *filename, *info; |
---|
160 | int max; |
---|
161 | { |
---|
162 | int fd, size; |
---|
163 | struct stat buf; |
---|
164 | int num; |
---|
165 | char errtext[100]; |
---|
166 | char *errfmt = "error %d %s `%s'"; |
---|
167 | |
---|
168 | if (-1 == (fd = open(filename, O_RDONLY, 0))) |
---|
169 | { |
---|
170 | sprintf(errtext, errfmt, errno, "opening", filename); |
---|
171 | XjWarning(errtext); |
---|
172 | return 0; |
---|
173 | } |
---|
174 | |
---|
175 | if (-1 == fstat(fd, &buf)) /* could only return EIO */ |
---|
176 | { |
---|
177 | sprintf(errtext, errfmt, errno, "in fstat for", filename); |
---|
178 | XjWarning(errtext); |
---|
179 | close(fd); |
---|
180 | return 0; |
---|
181 | } |
---|
182 | |
---|
183 | size = (int)buf.st_size; |
---|
184 | |
---|
185 | if (-1 == (num = read(fd, info, MIN(size, max - 1)))) |
---|
186 | { |
---|
187 | sprintf(errtext, errfmt, errno, "reading", filename); |
---|
188 | XjWarning(errtext); |
---|
189 | close(fd); |
---|
190 | return 0; |
---|
191 | } |
---|
192 | close(fd); |
---|
193 | |
---|
194 | info[num] = '\0'; |
---|
195 | return num; |
---|
196 | } |
---|
197 | |
---|
198 | |
---|
199 | static void saveFile(filename, info, length) |
---|
200 | char *filename, *info; |
---|
201 | int length; |
---|
202 | { |
---|
203 | int fd; |
---|
204 | char errtext[100]; |
---|
205 | char *errfmt = "error %d %s `%s'"; |
---|
206 | |
---|
207 | if (-1 == (fd = open(filename, O_TRUNC | O_CREAT | O_WRONLY, 0644))) |
---|
208 | { |
---|
209 | sprintf(errtext, errfmt, errno, "opening", filename); |
---|
210 | XjWarning(errtext); |
---|
211 | return; |
---|
212 | } |
---|
213 | |
---|
214 | if (length != write(fd, info, length)) |
---|
215 | { |
---|
216 | sprintf(errtext, errfmt, errno, "writing", filename); |
---|
217 | XjWarning(errtext); |
---|
218 | close(fd); /* I doubt it. */ |
---|
219 | return; |
---|
220 | } |
---|
221 | |
---|
222 | close(fd); |
---|
223 | } |
---|
224 | |
---|
225 | |
---|
226 | int hide(fromJet, what, data) |
---|
227 | Jet fromJet; |
---|
228 | char *what; |
---|
229 | caddr_t data; |
---|
230 | /*ARGSUSED*/ |
---|
231 | { |
---|
232 | UnmapWindow(win); |
---|
233 | return 0; |
---|
234 | } |
---|
235 | |
---|
236 | |
---|
237 | void resetunmaptimer() |
---|
238 | { |
---|
239 | if (parms.autoUnmap != 0) |
---|
240 | { |
---|
241 | if (unmaptimerid != 0) |
---|
242 | (void)XjRemoveWakeup(unmaptimerid); |
---|
243 | unmaptimerid = XjAddWakeup(hide, 0, 1000 * parms.autoUnmap); |
---|
244 | } |
---|
245 | } |
---|
246 | |
---|
247 | |
---|
248 | int scroll(fromJet, increment, data) |
---|
249 | Jet fromJet; |
---|
250 | int increment; |
---|
251 | caddr_t data; |
---|
252 | /*ARGSUSED*/ |
---|
253 | { |
---|
254 | int cl, vl; |
---|
255 | |
---|
256 | resetunmaptimer(); |
---|
257 | cl = CountLines(tj); |
---|
258 | vl = VisibleLines(tj); |
---|
259 | val = GetScrollBarValue(sj); |
---|
260 | if ((increment > 0 && val < cl - vl) |
---|
261 | || (increment < 0 && val > 0)) |
---|
262 | { |
---|
263 | val += increment; |
---|
264 | SetScrollBar(sj, 0, MAX(0, cl - 1), vl, val); |
---|
265 | SetLine(tj, val); |
---|
266 | } |
---|
267 | return 0; |
---|
268 | } |
---|
269 | |
---|
270 | |
---|
271 | int newvalue(fromJet, nothing, data) |
---|
272 | Jet fromJet; |
---|
273 | int nothing; |
---|
274 | caddr_t data; |
---|
275 | /*ARGSUSED*/ |
---|
276 | { |
---|
277 | resetunmaptimer(); |
---|
278 | SetLine(tj, val = GetScrollBarValue((ScrollBarJet) fromJet)); |
---|
279 | return 0; |
---|
280 | } |
---|
281 | |
---|
282 | |
---|
283 | int textscroll(fromJet, nothing, data) |
---|
284 | Jet fromJet; |
---|
285 | int nothing; |
---|
286 | caddr_t data; |
---|
287 | /*ARGSUSED*/ |
---|
288 | { |
---|
289 | int cl, vl; |
---|
290 | |
---|
291 | resetunmaptimer(); |
---|
292 | cl = CountLines(tj); |
---|
293 | vl = VisibleLines(tj); |
---|
294 | val = TopLine(tj); |
---|
295 | SetScrollBar(sj, 0, MAX(0, cl - 1), vl, val); |
---|
296 | return 0; |
---|
297 | } |
---|
298 | |
---|
299 | |
---|
300 | int textresize(fromJet, nothing, data) |
---|
301 | Jet fromJet; |
---|
302 | int nothing; |
---|
303 | caddr_t data; |
---|
304 | /*ARGSUSED*/ |
---|
305 | { |
---|
306 | int cl, vl; |
---|
307 | |
---|
308 | resetunmaptimer(); |
---|
309 | cl = CountLines(tj); |
---|
310 | vl = VisibleLines(tj); |
---|
311 | |
---|
312 | if ((val != 0) && (val > cl - vl)) |
---|
313 | { |
---|
314 | if (parms.autoscroll) |
---|
315 | { |
---|
316 | val = MAX(0, cl - vl); |
---|
317 | |
---|
318 | SetLine(tj, val); |
---|
319 | } |
---|
320 | } |
---|
321 | |
---|
322 | SetScrollBar(sj, 0, MAX(0, cl - 1), vl, val); |
---|
323 | return 0; |
---|
324 | } |
---|
325 | |
---|
326 | |
---|
327 | int delete(fromJet, what, data) |
---|
328 | Jet fromJet; |
---|
329 | char *what; |
---|
330 | caddr_t data; |
---|
331 | /*ARGSUSED*/ |
---|
332 | { |
---|
333 | XjDestroyJet(fromJet); |
---|
334 | XCloseDisplay(root->core.display); |
---|
335 | XjExit(0); |
---|
336 | return 0; /* For linting... */ |
---|
337 | } |
---|
338 | |
---|
339 | |
---|
340 | void blinkoff() |
---|
341 | { |
---|
342 | if (blinking) |
---|
343 | { |
---|
344 | if (inverted) |
---|
345 | { |
---|
346 | inverted = !inverted; |
---|
347 | setIcon(icon, Center, inverted); |
---|
348 | } |
---|
349 | |
---|
350 | (void)XjRemoveWakeup(timerid); |
---|
351 | blinking = False; |
---|
352 | } |
---|
353 | } |
---|
354 | |
---|
355 | |
---|
356 | int mapnotify(fromJet, what, data) |
---|
357 | Jet fromJet; |
---|
358 | char *what; |
---|
359 | caddr_t data; |
---|
360 | /*ARGSUSED*/ |
---|
361 | { |
---|
362 | blinkoff(); |
---|
363 | return 0; |
---|
364 | } |
---|
365 | |
---|
366 | |
---|
367 | void OurMapWindow(who) |
---|
368 | WindowJet who; |
---|
369 | { |
---|
370 | blinkoff(); |
---|
371 | resetunmaptimer(); |
---|
372 | MapWindow(who, True); |
---|
373 | } |
---|
374 | |
---|
375 | |
---|
376 | int blink(info, id) |
---|
377 | int info, id; |
---|
378 | /*ARGSUSED*/ |
---|
379 | { |
---|
380 | inverted = !inverted; |
---|
381 | setIcon(icon, Center, inverted); |
---|
382 | timerid = XjAddWakeup(blink, 0, MAX(100, parms.frequency)); |
---|
383 | return 0; |
---|
384 | } |
---|
385 | |
---|
386 | |
---|
387 | int appendToBuffer(what, howmuch) |
---|
388 | char *what; |
---|
389 | int howmuch; |
---|
390 | { |
---|
391 | int moved = 0; |
---|
392 | |
---|
393 | if (howmuch == 0) /* if nothing to copy, return */ |
---|
394 | return 0; |
---|
395 | |
---|
396 | /* |
---|
397 | * If there's not enough room to copy in whatever was asked for, then |
---|
398 | * chop off the beginning of the text, using bcopy... |
---|
399 | */ |
---|
400 | if (BUFSIZE - length <= howmuch) |
---|
401 | { |
---|
402 | char *c; |
---|
403 | |
---|
404 | c = text + MIN(INPUTSIZE, length); |
---|
405 | while ((c < text + length) && *c != '\0' && *c != '\n') |
---|
406 | c++; |
---|
407 | if (*c != '\n') /* if this is a looooong line, screw it. */ |
---|
408 | c = text + MIN(INPUTSIZE, length); |
---|
409 | else |
---|
410 | c++; |
---|
411 | |
---|
412 | moved = c - text; |
---|
413 | length -= moved; |
---|
414 | |
---|
415 | memmove(text, c, length); |
---|
416 | } |
---|
417 | |
---|
418 | memcpy(text + length, what, howmuch); |
---|
419 | length += howmuch; |
---|
420 | text[length] = '\0'; /* Null terminate the string... */ |
---|
421 | /* WARNING: This can overflow! Why? */ |
---|
422 | return moved; |
---|
423 | } |
---|
424 | |
---|
425 | |
---|
426 | int input(fd, pfd) |
---|
427 | int fd; |
---|
428 | int *pfd; |
---|
429 | /*ARGSUSED*/ |
---|
430 | { |
---|
431 | int redo = 0; |
---|
432 | int cl, vl, l; |
---|
433 | char ctrl[2]; |
---|
434 | int i = 0, j, err; |
---|
435 | static int eol = 1; |
---|
436 | |
---|
437 | ctrl[0] = '^'; |
---|
438 | l = read(*pfd, inputbuf, INPUTSIZE); |
---|
439 | |
---|
440 | if (l < 0 && errno != EIO && errno != EINTR) |
---|
441 | { |
---|
442 | err = errno; |
---|
443 | syslog(LOG_ERR, "Error reading from fd %d: %m", *pfd); |
---|
444 | XjReadCallback((XjCallbackProc)NULL, *pfd, (caddr_t) pfd); |
---|
445 | sprintf(inputbuf, "Error reading from fd %d: %s\n", *pfd, |
---|
446 | strerror(err)); |
---|
447 | l = strlen(inputbuf); |
---|
448 | } |
---|
449 | |
---|
450 | if (l > 0) |
---|
451 | { |
---|
452 | while (i < l) |
---|
453 | { |
---|
454 | if (eol && parms.timestamp) |
---|
455 | { |
---|
456 | struct timeval now; |
---|
457 | time_t timet; |
---|
458 | char *timestr; |
---|
459 | |
---|
460 | gettimeofday(&now, NULL); |
---|
461 | timet = (time_t) now.tv_sec; |
---|
462 | timestr = (char *) ctime(&timet); |
---|
463 | redo += appendToBuffer(×tr[11], 5); |
---|
464 | redo += appendToBuffer(" ", 1); |
---|
465 | } |
---|
466 | |
---|
467 | eol = 0; |
---|
468 | j = i; |
---|
469 | while (j < l && !eol) |
---|
470 | { |
---|
471 | if (iscntrl(inputbuf[j])) |
---|
472 | { |
---|
473 | redo += appendToBuffer(&inputbuf[i], j - i); |
---|
474 | i = j + 1; |
---|
475 | |
---|
476 | switch(inputbuf[j]) |
---|
477 | { |
---|
478 | case 7: /* bell compression option... */ |
---|
479 | XBell(root->core.display, 0); |
---|
480 | case 0: |
---|
481 | case 13: |
---|
482 | break; |
---|
483 | case '\n': |
---|
484 | eol = 1; |
---|
485 | case '\t': |
---|
486 | redo += appendToBuffer(&inputbuf[j], 1); |
---|
487 | break; |
---|
488 | default: |
---|
489 | ctrl[1] = inputbuf[j] | 64; |
---|
490 | redo += appendToBuffer(ctrl, 2); |
---|
491 | break; |
---|
492 | } |
---|
493 | } |
---|
494 | j++; |
---|
495 | } |
---|
496 | redo += appendToBuffer(&inputbuf[i], j - i); |
---|
497 | i = j; |
---|
498 | } |
---|
499 | if (!redo) |
---|
500 | AddText(tj); /* ??? */ |
---|
501 | else |
---|
502 | MoveText(tj, text, redo); |
---|
503 | |
---|
504 | cl = CountLines(tj); |
---|
505 | vl = VisibleLines(tj); |
---|
506 | |
---|
507 | if (parms.autoscroll) |
---|
508 | { |
---|
509 | val = MAX(0, cl - vl); |
---|
510 | |
---|
511 | SetScrollBar(sj, 0, MAX(cl - 1, 0), vl, val); |
---|
512 | SetLine(tj, val); |
---|
513 | } |
---|
514 | |
---|
515 | if (!WindowMapped((WindowJet)win)) |
---|
516 | { |
---|
517 | if (!WindowMapped(iconWindow)) |
---|
518 | OurMapWindow((WindowJet)win); /* we're hidden, not iconified */ |
---|
519 | else |
---|
520 | { |
---|
521 | if (!blinking) |
---|
522 | { |
---|
523 | blinking = True; |
---|
524 | blink(0, 0); |
---|
525 | } |
---|
526 | } |
---|
527 | } |
---|
528 | else |
---|
529 | { |
---|
530 | resetunmaptimer(); |
---|
531 | if (WindowVisibility(win) != VisibilityUnobscured) |
---|
532 | XRaiseWindow(win->core.display, win->core.window); /* ICCCM ok */ |
---|
533 | } |
---|
534 | } |
---|
535 | return 0; |
---|
536 | } |
---|
537 | |
---|
538 | void sighandler(sig) |
---|
539 | int sig; |
---|
540 | { |
---|
541 | switch(sig) |
---|
542 | { |
---|
543 | case SIGHUP: |
---|
544 | sigflags[HUP] = 1; |
---|
545 | break; |
---|
546 | case SIGFPE: |
---|
547 | sigflags[FPE] = 1; |
---|
548 | break; |
---|
549 | case SIGUSR1: |
---|
550 | sigflags[USR1] = 1; |
---|
551 | break; |
---|
552 | case SIGUSR2: |
---|
553 | sigflags[USR2] = 1; |
---|
554 | break; |
---|
555 | } |
---|
556 | return; |
---|
557 | } |
---|
558 | |
---|
559 | |
---|
560 | XjCallbackRec callbacks[] = |
---|
561 | { |
---|
562 | { "newvalue", newvalue }, |
---|
563 | { "textresize", textresize }, |
---|
564 | { "textscroll", textscroll }, |
---|
565 | { "delete", delete }, |
---|
566 | { "hide", hide }, |
---|
567 | { "mapnotify", mapnotify }, |
---|
568 | { "scroll", scroll }, |
---|
569 | }; |
---|
570 | |
---|
571 | |
---|
572 | static int checkSignals() |
---|
573 | { |
---|
574 | int sigs; |
---|
575 | int cl, vl; |
---|
576 | int ret_code=0; |
---|
577 | |
---|
578 | do |
---|
579 | { |
---|
580 | sigs = 0; |
---|
581 | |
---|
582 | if (sigflags[FPE]) |
---|
583 | { |
---|
584 | sigs++; |
---|
585 | sigflags[FPE] = 0; |
---|
586 | text[0] = '\0'; |
---|
587 | length = 0; |
---|
588 | saveFile(parms.file, text, length); |
---|
589 | |
---|
590 | blinkoff(); |
---|
591 | if (WindowMapped(win)) |
---|
592 | UnmapWindow(win); |
---|
593 | |
---|
594 | SetText(tj, text); |
---|
595 | |
---|
596 | cl = CountLines(tj); |
---|
597 | vl = VisibleLines(tj); |
---|
598 | |
---|
599 | val = MAX(0, cl - vl); |
---|
600 | |
---|
601 | SetScrollBar(sj, 0, MAX(cl - 1, 0), vl, val); |
---|
602 | SetLine(tj, val); |
---|
603 | XFlush(tj->core.display); |
---|
604 | } |
---|
605 | |
---|
606 | if (sigflags[USR1]) |
---|
607 | { |
---|
608 | sigs++; |
---|
609 | sigflags[USR1] = 0; |
---|
610 | if (!WindowMapped((WindowJet)win)) |
---|
611 | { |
---|
612 | OurMapWindow((WindowJet)win); |
---|
613 | XFlush(win->core.display); |
---|
614 | } |
---|
615 | else |
---|
616 | if (WindowVisibility(win) != VisibilityUnobscured) |
---|
617 | { |
---|
618 | XRaiseWindow(win->core.display, win->core.window); /* ICCCM ok */ |
---|
619 | XFlush(win->core.display); |
---|
620 | } |
---|
621 | } |
---|
622 | |
---|
623 | if (sigflags[USR2]) |
---|
624 | { |
---|
625 | sigs++; |
---|
626 | sigflags[USR2] = 0; |
---|
627 | if (WindowMapped(win)) |
---|
628 | { |
---|
629 | UnmapWindow(win); |
---|
630 | XFlush(win->core.display); |
---|
631 | } |
---|
632 | } |
---|
633 | |
---|
634 | if (sigflags[HUP]) |
---|
635 | { |
---|
636 | sigs++; |
---|
637 | sigflags[HUP] = 0; |
---|
638 | saveFile(parms.file, text, length); |
---|
639 | XCloseDisplay(root->core.display); |
---|
640 | XjExit(0); |
---|
641 | } |
---|
642 | ret_code += sigs; |
---|
643 | } |
---|
644 | while(sigs); |
---|
645 | return ret_code; |
---|
646 | } |
---|
647 | |
---|
648 | |
---|
649 | fatal(display) |
---|
650 | Display *display; |
---|
651 | /*ARGSUSED*/ |
---|
652 | { |
---|
653 | XjExit(1); |
---|
654 | } |
---|
655 | |
---|
656 | |
---|
657 | main(argc, argv) |
---|
658 | int argc; |
---|
659 | char **argv; |
---|
660 | { |
---|
661 | Jet w, b, f; |
---|
662 | int cl, vl, i; |
---|
663 | int zero = 0; |
---|
664 | int auxinput = -1; |
---|
665 | int size=0; |
---|
666 | char *envvar; |
---|
667 | struct stat buf; |
---|
668 | struct sigaction act; |
---|
669 | sigemptyset(&act.sa_mask); |
---|
670 | act.sa_flags = 0; |
---|
671 | |
---|
672 | openlog("console", 0, LOG_USER); |
---|
673 | |
---|
674 | for (i = 0; i < NUMSIGS; i++) |
---|
675 | sigflags[i] = 0; |
---|
676 | |
---|
677 | act.sa_handler= sighandler; |
---|
678 | (void) sigaction(SIGHUP, &act, NULL); |
---|
679 | (void) sigaction(SIGFPE, &act, NULL); |
---|
680 | (void) sigaction(SIGUSR1, &act, NULL); |
---|
681 | (void) sigaction(SIGUSR2, &act, NULL); |
---|
682 | |
---|
683 | if (getenv(XENV) == NULL) |
---|
684 | { |
---|
685 | envvar = malloc(strlen(XENV) + strlen(CONSOLEDEFAULTS) + 2); |
---|
686 | if (!envvar) |
---|
687 | { |
---|
688 | fprintf(stderr, "malloc failed! Aborting.\n"); |
---|
689 | exit(1); |
---|
690 | } |
---|
691 | sprintf(envvar, "%s=%s", XENV, CONSOLEDEFAULTS); |
---|
692 | putenv(envvar); |
---|
693 | } |
---|
694 | |
---|
695 | root = XjCreateRoot(&argc, argv, "Console", NULL, |
---|
696 | opTable, XjNumber(opTable)); |
---|
697 | |
---|
698 | (void) XSetIOErrorHandler(fatal); |
---|
699 | |
---|
700 | XjLoadFromResources(NULL, |
---|
701 | NULL, |
---|
702 | programClass, |
---|
703 | programName, |
---|
704 | appResources, |
---|
705 | XjNumber(appResources), |
---|
706 | (caddr_t) &parms); |
---|
707 | |
---|
708 | DEBUG = parms.debug; |
---|
709 | |
---|
710 | XjRegisterCallbacks(callbacks, XjNumber(callbacks)); |
---|
711 | |
---|
712 | iconWindow = (WindowJet) XjVaCreateJet("iconWindow", |
---|
713 | windowJetClass, root, NULL, NULL); |
---|
714 | icon = (LabelJet) XjVaCreateJet("icon", |
---|
715 | labelJetClass, iconWindow, NULL, NULL); |
---|
716 | XjRealizeJet(root); |
---|
717 | |
---|
718 | win = (WindowJet) XjVaCreateJet("window", windowJetClass, root, |
---|
719 | XjNiconWindow, iconWindow, |
---|
720 | NULL, NULL); |
---|
721 | f = XjVaCreateJet("form", formJetClass, win, NULL, NULL); |
---|
722 | |
---|
723 | /* |
---|
724 | * Button |
---|
725 | */ |
---|
726 | w = XjVaCreateJet("hide", windowJetClass, f, NULL, NULL); |
---|
727 | b = XjVaCreateJet("hideButton", buttonJetClass, w, NULL, NULL); |
---|
728 | (void) XjVaCreateJet("hideLabel", labelJetClass, b, NULL, NULL); |
---|
729 | |
---|
730 | /* |
---|
731 | * Arrow buttons |
---|
732 | */ |
---|
733 | w = XjVaCreateJet("scrollup", windowJetClass, f, NULL, NULL); |
---|
734 | b = XjVaCreateJet("scrollupButton", buttonJetClass, w, NULL, NULL); |
---|
735 | (void) XjVaCreateJet("scrollupArrow", arrowJetClass, b, NULL, NULL); |
---|
736 | |
---|
737 | w = XjVaCreateJet("scrolldown", windowJetClass, f, NULL, NULL); |
---|
738 | b = XjVaCreateJet("scrolldownButton", buttonJetClass, w, NULL, NULL); |
---|
739 | (void) XjVaCreateJet("scrolldownArrow", arrowJetClass, b, NULL, NULL); |
---|
740 | |
---|
741 | /* |
---|
742 | * Label |
---|
743 | */ |
---|
744 | (void) XjVaCreateJet("title", labelJetClass, f, NULL, NULL); |
---|
745 | |
---|
746 | /* |
---|
747 | * Scrollbar |
---|
748 | */ |
---|
749 | w = XjVaCreateJet("scrollBarWindow", windowJetClass, f, NULL, NULL); |
---|
750 | sj = (ScrollBarJet) XjVaCreateJet("scrollBar", |
---|
751 | scrollBarJetClass, w, NULL, NULL); |
---|
752 | |
---|
753 | /* |
---|
754 | * TextDisplay |
---|
755 | */ |
---|
756 | w = XjVaCreateJet("textDisplayWindow", windowJetClass, f, NULL, NULL); |
---|
757 | tj = (TextDisplayJet) XjVaCreateJet("textDisplay", |
---|
758 | textDisplayJetClass, w, NULL, NULL); |
---|
759 | |
---|
760 | |
---|
761 | XjRealizeJet((Jet) XjParent(f)); |
---|
762 | |
---|
763 | |
---|
764 | if (! stat(parms.file, &buf)) /* If there was an error stat'ing the */ |
---|
765 | size = (int)buf.st_size; /* file, we will find out soon enough */ |
---|
766 | /* when we call loadFile below. No need */ |
---|
767 | /* to display an error msg here. */ |
---|
768 | |
---|
769 | size = (size > BUFSIZE) ? size : BUFSIZE; |
---|
770 | text = XjMalloc(size); |
---|
771 | text[0] = '\0'; |
---|
772 | length = 0; |
---|
773 | length = loadFile(parms.file, text, size); |
---|
774 | |
---|
775 | if (parms.input && *parms.input) |
---|
776 | { |
---|
777 | auxinput = open(parms.input, O_RDONLY, 0); |
---|
778 | if (auxinput == -1) |
---|
779 | { |
---|
780 | #define CANT_OPEN "console: can't open input\n" |
---|
781 | appendToBuffer(CANT_OPEN, sizeof(CANT_OPEN)-1); |
---|
782 | } |
---|
783 | } |
---|
784 | SetText(tj, text); |
---|
785 | |
---|
786 | cl = CountLines(tj); |
---|
787 | vl = VisibleLines(tj); |
---|
788 | |
---|
789 | if (parms.autoscroll) |
---|
790 | { |
---|
791 | val = MAX(0, cl - vl); |
---|
792 | |
---|
793 | SetScrollBar(sj, 0, MAX(cl - 1, 0), vl, val); |
---|
794 | SetLine(tj, val); |
---|
795 | } |
---|
796 | |
---|
797 | if (parms.nostdin == False) |
---|
798 | XjReadCallback((XjCallbackProc)input, zero, (caddr_t) &zero); |
---|
799 | |
---|
800 | if (auxinput != -1) |
---|
801 | XjReadCallback((XjCallbackProc)input, auxinput, (caddr_t) &auxinput); |
---|
802 | |
---|
803 | if (parms.inputfd != 0) |
---|
804 | XjReadCallback((XjCallbackProc)input, parms.inputfd, |
---|
805 | (caddr_t) &parms.inputfd); |
---|
806 | |
---|
807 | XjSetSignalChecker(checkSignals); |
---|
808 | |
---|
809 | XjEventLoop(root); |
---|
810 | } |
---|