Just a little correction at the it.po file.
[midnight-commander.git] / src / cons.handler.c
blob8ad88d5698e278b4cdf39036862740982e08e058
1 /* Client interface for General purpose Linux console save/restore server
2 Copyright (C) 1994 Janne Kukonlehto <jtklehto@stekt.oulu.fi>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 #include <config.h>
20 #ifdef HAVE_UNISTD_H
21 # include <unistd.h>
22 #endif
23 #include <sys/types.h>
24 #include <signal.h>
25 #include <stdio.h>
27 #ifdef SCO_FLAVOR
28 #include <sys/types.h>
29 #include <sys/vid.h>
30 #include <sys/console.h>
31 #include <sys/vtkd.h>
32 #include <memory.h>
33 #include <signal.h>
34 #endif /* SCO_FLAVOR */
36 #ifdef __FreeBSD__
37 #include <sys/consio.h>
38 #include <sys/ioctl.h>
39 #endif /* __FreeBSD__ */
41 #include "global.h"
42 #include "tty.h"
43 #include "cons.saver.h"
45 signed char console_flag = 0;
47 #ifdef __linux__
49 /* The cons saver can't have a pid of 1, used to prevent bunches of
50 * #ifdef linux */
52 int cons_saver_pid = 1;
53 static int pipefd1[2] = { -1, -1 };
54 static int pipefd2[2] = { -1, -1 };
56 static void
57 show_console_contents_linux (int starty, unsigned char begin_line,
58 unsigned char end_line)
60 unsigned char message = 0;
61 unsigned short bytes = 0;
62 int i;
64 /* Is tty console? */
65 if (!console_flag)
66 return;
67 /* Paranoid: Is the cons.saver still running? */
68 if (cons_saver_pid < 1 || kill (cons_saver_pid, SIGCONT)) {
69 cons_saver_pid = 0;
70 console_flag = 0;
71 return;
74 /* Send command to the console handler */
75 message = CONSOLE_CONTENTS;
76 write (pipefd1[1], &message, 1);
77 /* Check for outdated cons.saver */
78 read (pipefd2[0], &message, 1);
79 if (message != CONSOLE_CONTENTS)
80 return;
82 /* Send the range of lines that we want */
83 write (pipefd1[1], &begin_line, 1);
84 write (pipefd1[1], &end_line, 1);
85 /* Read the corresponding number of bytes */
86 read (pipefd2[0], &bytes, 2);
88 /* Read the bytes and output them */
89 for (i = 0; i < bytes; i++) {
90 if ((i % COLS) == 0)
91 move (starty + (i / COLS), 0);
92 read (pipefd2[0], &message, 1);
93 addch (message);
96 /* Read the value of the console_flag */
97 read (pipefd2[0], &message, 1);
100 static void
101 handle_console_linux (unsigned char action)
103 char *tty_name;
104 char *mc_conssaver;
105 int status;
107 switch (action) {
108 case CONSOLE_INIT:
109 /* Close old pipe ends in case it is the 2nd time we run cons.saver */
110 close (pipefd1[1]);
111 close (pipefd2[0]);
112 /* Create two pipes for communication */
113 pipe (pipefd1);
114 pipe (pipefd2);
115 /* Get the console saver running */
116 cons_saver_pid = fork ();
117 if (cons_saver_pid < 0) {
118 /* Cannot fork */
119 /* Delete pipes */
120 close (pipefd1[1]);
121 close (pipefd1[0]);
122 close (pipefd2[1]);
123 close (pipefd2[0]);
124 console_flag = 0;
125 } else if (cons_saver_pid > 0) {
126 /* Parent */
127 /* Close the extra pipe ends */
128 close (pipefd1[0]);
129 close (pipefd2[1]);
130 /* Was the child successful? */
131 read (pipefd2[0], &console_flag, 1);
132 if (!console_flag) {
133 close (pipefd1[1]);
134 close (pipefd2[0]);
135 waitpid (cons_saver_pid, &status, 0);
137 } else {
138 /* Child */
139 /* Close the extra pipe ends */
140 close (pipefd1[1]);
141 close (pipefd2[0]);
142 tty_name = ttyname (0);
143 /* Bind the pipe 0 to the standard input */
144 close (0);
145 dup (pipefd1[0]);
146 close (pipefd1[0]);
147 /* Bind the pipe 1 to the standard output */
148 close (1);
149 dup (pipefd2[1]);
150 close (pipefd2[1]);
151 /* Bind standard error to /dev/null */
152 close (2);
153 open ("/dev/null", O_WRONLY);
154 if (tty_name) {
155 /* Exec the console save/restore handler */
156 mc_conssaver = concat_dir_and_file (LIBDIR, "cons.saver");
157 execl (mc_conssaver, "cons.saver", tty_name, NULL);
159 /* Console is not a tty or execl() failed */
160 console_flag = 0;
161 write (1, &console_flag, 1);
162 close (1);
163 close (0);
164 _exit (3);
165 } /* if (cons_saver_pid ...) */
166 break;
168 case CONSOLE_DONE:
169 case CONSOLE_SAVE:
170 case CONSOLE_RESTORE:
171 /* Is tty console? */
172 if (!console_flag)
173 return;
174 /* Paranoid: Is the cons.saver still running? */
175 if (cons_saver_pid < 1 || kill (cons_saver_pid, SIGCONT)) {
176 cons_saver_pid = 0;
177 console_flag = 0;
178 return;
180 /* Send command to the console handler */
181 write (pipefd1[1], &action, 1);
182 if (action != CONSOLE_DONE) {
183 /* Wait the console handler to do its job */
184 read (pipefd2[0], &console_flag, 1);
186 if (action == CONSOLE_DONE || !console_flag) {
187 /* We are done -> Let's clean up */
188 close (pipefd1[1]);
189 close (pipefd2[0]);
190 waitpid (cons_saver_pid, &status, 0);
191 console_flag = 0;
193 break;
197 #elif defined(SCO_FLAVOR)
200 ** SCO console save/restore handling routines
201 ** Copyright (C) 1997 Alex Tkachenko <alex@bcs.zaporizhzhe.ua>
204 #include "color.h"
206 static int FD_OUT = 2;
208 static unsigned short *vidbuf = NULL;
209 static unsigned short *screen = NULL;
210 static int height = 0, width = 0, saved_attr = 0;
211 static int mode = 0;
213 #define SIG_ACQUIRE 21 /* originally: handset, line status change (?) */
215 static int
216 vt_active ()
218 struct vid_info vi;
219 int adapter = ioctl (FD_OUT, CONS_CURRENT, 0);
221 vi.size = sizeof (struct vid_info);
222 ioctl (FD_OUT, CONS_GETINFO, &(vi));
223 return (vi.m_num == ioctl (FD_OUT, CONSADP, adapter));
226 static void
227 console_acquire_vt ()
229 struct vt_mode smode;
231 signal (SIG_ACQUIRE, SIG_DFL);
232 smode.mode = VT_AUTO;
233 smode.waitv = smode.relsig = smode.acqsig = smode.frsig = 0;
234 ioctl (FD_OUT, VT_SETMODE, &smode);
235 ioctl (FD_OUT, VT_RELDISP, VT_ACKACQ);
238 static void
239 console_shutdown ()
241 if (!console_flag) {
242 return;
244 if (screen != NULL) {
245 g_free (screen);
247 console_flag = 0;
250 static void
251 console_save ()
253 struct m6845_info mi;
255 if (!console_flag) {
256 return;
259 if (!vt_active ()) {
260 struct vt_mode smode;
263 ** User switched out of our vt. Let's wait until we get SIG_ACQUIRE,
264 ** otherwise we could save wrong screen image
266 signal (SIG_ACQUIRE, console_acquire_vt);
267 smode.mode = VT_PROCESS;
268 smode.waitv = 0;
269 smode.waitv = smode.relsig = smode.acqsig = smode.frsig =
270 SIG_ACQUIRE;
271 ioctl (FD_OUT, VT_SETMODE, &smode);
273 pause ();
276 saved_attr = ioctl (FD_OUT, GIO_ATTR, 0);
278 vidbuf = (unsigned short *) ioctl (FD_OUT, MAPCONS, 0);
280 mi.size = sizeof (struct m6845_info);
281 ioctl (FD_OUT, CONS_6845INFO, &mi);
284 unsigned short *start = vidbuf + mi.screen_top;
285 memcpy (screen, start, width * height * 2);
288 write (FD_OUT, "\0337", 2); /* save cursor position */
291 static void
292 console_restore ()
294 struct m6845_info mi;
295 unsigned short *start;
297 if (!console_flag) {
298 return;
301 write (FD_OUT, "\033[2J", 4);
303 mi.size = sizeof (struct m6845_info);
304 ioctl (FD_OUT, CONS_6845INFO, &mi);
306 start = vidbuf + mi.screen_top;
307 memcpy (start, screen, width * height * 2);
308 write (FD_OUT, "\0338", 2); /* restore cursor position */
311 static void
312 console_init ()
314 struct vid_info vi;
315 int adapter = ioctl (FD_OUT, CONS_CURRENT, 0);
317 console_flag = 0;
319 if (adapter != -1) {
320 vi.size = sizeof (struct vid_info);
321 ioctl (FD_OUT, CONS_GETINFO, &(vi));
323 if (vt_active ()) {
324 console_flag = 1;
326 height = vi.mv_rsz;
327 width = vi.mv_csz;
329 screen = (unsigned short *) g_malloc (height * width * 2);
330 if (screen == NULL) {
331 console_shutdown ();
332 return;
334 console_save ();
335 mode = ioctl (FD_OUT, CONS_GET, 0);
336 ioctl (FD_OUT, MODESWITCH | mode, 0);
337 console_restore ();
342 static void
343 handle_console_sco (unsigned char action)
345 switch (action) {
346 case CONSOLE_INIT:
347 console_init ();
348 break;
350 case CONSOLE_DONE:
351 console_shutdown ();
352 break;
354 case CONSOLE_SAVE:
355 console_save ();
356 break;
358 case CONSOLE_RESTORE:
359 console_restore ();
360 break;
361 default:
362 /* Nothing */ ;
366 static void
367 show_console_contents_sco (int starty, unsigned char begin_line,
368 unsigned char end_line)
370 register int i, len = (end_line - begin_line) * width;
372 attrset (DEFAULT_COLOR);
373 for (i = 0; i < len; i++) {
374 if ((i % width) == 0)
375 move (starty + (i / width), 0);
376 addch ((unsigned char) screen[width * starty + i]);
380 #elif defined(__FreeBSD__)
383 * FreeBSD support copyright (C) 2003 Alexander Serkov <serkov@ukrpost.net>.
384 * Support for screenmaps by Max Khon <fjoe@FreeBSD.org>
387 #define FD_OUT 1
389 static struct scrshot screen_shot;
390 static struct vid_info screen_info;
392 static void
393 console_init (void)
395 if (console_flag)
396 return;
398 screen_info.size = sizeof (screen_info);
399 if (ioctl (FD_OUT, CONS_GETINFO, &screen_info) == -1)
400 return;
402 memset (&screen_shot, 0, sizeof (screen_shot));
403 screen_shot.xsize = screen_info.mv_csz;
404 screen_shot.ysize = screen_info.mv_rsz;
405 if ((screen_shot.buf =
406 g_malloc (screen_info.mv_csz * screen_info.mv_rsz * 2)) == NULL)
407 return;
409 console_flag = 1;
412 static void
413 set_attr (unsigned attr)
416 * Convert color indices returned by SCRSHOT (red=4, green=2, blue=1)
417 * to indices for ANSI sequences (red=1, green=2, blue=4).
419 static const int color_map[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
420 int bc, tc;
422 tc = attr & 0xF;
423 bc = (attr >> 4) & 0xF;
425 printf ("\x1B[%d;%d;3%d;4%dm", (bc & 8) ? 5 : 25, (tc & 8) ? 1 : 22,
426 color_map[tc & 7], color_map[bc & 7]);
429 #define cursor_to(x, y) do { \
430 printf("\x1B[%d;%df", (y) + 1, (x) + 1); \
431 fflush(stdout); \
432 } while (0)
434 static void
435 console_restore (void)
437 int i, last;
439 if (!console_flag)
440 return;
442 cursor_to (0, 0);
444 /* restoring all content up to cursor position */
445 last = screen_info.mv_row * screen_info.mv_csz + screen_info.mv_col;
446 for (i = 0; i < last; ++i) {
447 set_attr ((screen_shot.buf[i] >> 8) & 0xFF);
448 putc (screen_shot.buf[i] & 0xFF, stdout);
451 /* restoring cursor color */
452 set_attr ((screen_shot.buf[last] >> 8) & 0xFF);
454 fflush (stdout);
457 static void
458 console_shutdown (void)
460 if (!console_flag)
461 return;
463 g_free (screen_shot.buf);
465 console_flag = 0;
468 static void
469 console_save (void)
471 int i;
472 scrmap_t map;
473 scrmap_t revmap;
475 if (!console_flag)
476 return;
478 /* screen_info.size is already set in console_init() */
479 if (ioctl (FD_OUT, CONS_GETINFO, &screen_info) == -1) {
480 console_shutdown ();
481 return;
484 /* handle console resize */
485 if (screen_info.mv_csz != screen_shot.xsize
486 || screen_info.mv_rsz != screen_shot.ysize) {
487 console_shutdown ();
488 console_init ();
491 if (ioctl (FD_OUT, CONS_SCRSHOT, &screen_shot) == -1) {
492 console_shutdown ();
493 return;
496 if (ioctl (FD_OUT, GIO_SCRNMAP, &map) == -1) {
497 console_shutdown ();
498 return;
501 for (i = 0; i < 256; i++) {
502 char *p = memchr (map.scrmap, i, 256);
503 revmap.scrmap[i] = p ? p - map.scrmap : i;
506 for (i = 0; i < screen_shot.xsize * screen_shot.ysize; i++) {
507 screen_shot.buf[i] =
508 (screen_shot.buf[i] & 0xff00) | (unsigned char) revmap.
509 scrmap[screen_shot.buf[i] & 0xff];
513 static void
514 show_console_contents_freebsd (int starty, unsigned char begin_line,
515 unsigned char end_line)
517 int col, line;
518 char c;
520 if (!console_flag)
521 return;
523 for (line = begin_line; line <= end_line; line++) {
524 move (starty + line - begin_line, 0);
525 for (col = 0; col < min (COLS, screen_info.mv_csz); col++) {
526 c = screen_shot.buf[line * screen_info.mv_csz + col] & 0xFF;
527 addch (c);
532 static void
533 handle_console_freebsd (unsigned char action)
535 switch (action) {
536 case CONSOLE_INIT:
537 console_init ();
538 break;
540 case CONSOLE_DONE:
541 console_shutdown ();
542 break;
544 case CONSOLE_SAVE:
545 console_save ();
546 break;
548 case CONSOLE_RESTORE:
549 console_restore ();
550 break;
553 #endif /* __FreeBSD__ */
555 void
556 show_console_contents (int starty, unsigned char begin_line,
557 unsigned char end_line)
559 standend ();
561 if (look_for_rxvt_extensions ()) {
562 show_rxvt_contents (starty, begin_line, end_line);
563 return;
565 #ifdef __linux__
566 show_console_contents_linux (starty, begin_line, end_line);
567 #elif defined (__FreeBSD__)
568 show_console_contents_freebsd (starty, begin_line, end_line);
569 #elif defined (SCO_FLAVOR)
570 show_console_contents_sco (starty, begin_line, end_line);
571 #else
572 console_flag = 0;
573 #endif
576 void
577 handle_console (unsigned char action)
579 if (look_for_rxvt_extensions ())
580 return;
582 #ifdef __linux__
583 handle_console_linux (action);
584 #elif defined (__FreeBSD__)
585 handle_console_freebsd (action);
586 #elif defined (SCO_FLAVOR)
587 handle_console_sco (action);
588 #endif