Some fixups with wrongly highlighted words
[midnight-commander.git] / src / cons.handler.c
blob1574e7e0c3e2db15f70dfc5298a8a4e5a361e408
1 /* Client interface for General purpose Linux console save/restore server
2 Copyright (C) 1994, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3 2006, 2007 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
19 /** \file cons.handler.c
20 * \brief Source: client %interface for General purpose Linux console save/restore server
23 #include <config.h>
25 #include <signal.h>
26 #include <stdio.h>
28 #include <sys/types.h>
29 #ifdef __FreeBSD__
30 # include <sys/consio.h>
31 # include <sys/ioctl.h>
32 #endif
33 #include <unistd.h>
35 #include "global.h"
36 #include "tty.h"
37 #include "cons.saver.h"
39 signed char console_flag = 0;
41 #ifdef __linux__
43 /* The cons saver can't have a pid of 1, used to prevent bunches of
44 * #ifdef linux */
46 int cons_saver_pid = 1;
47 static int pipefd1[2] = { -1, -1 };
48 static int pipefd2[2] = { -1, -1 };
50 static void
51 show_console_contents_linux (int starty, unsigned char begin_line,
52 unsigned char end_line)
54 unsigned char message = 0;
55 unsigned short bytes = 0;
56 int i;
58 /* Is tty console? */
59 if (!console_flag)
60 return;
61 /* Paranoid: Is the cons.saver still running? */
62 if (cons_saver_pid < 1 || kill (cons_saver_pid, SIGCONT)) {
63 cons_saver_pid = 0;
64 console_flag = 0;
65 return;
68 /* Send command to the console handler */
69 message = CONSOLE_CONTENTS;
70 write (pipefd1[1], &message, 1);
71 /* Check for outdated cons.saver */
72 read (pipefd2[0], &message, 1);
73 if (message != CONSOLE_CONTENTS)
74 return;
76 /* Send the range of lines that we want */
77 write (pipefd1[1], &begin_line, 1);
78 write (pipefd1[1], &end_line, 1);
79 /* Read the corresponding number of bytes */
80 read (pipefd2[0], &bytes, 2);
82 /* Read the bytes and output them */
83 for (i = 0; i < bytes; i++) {
84 if ((i % COLS) == 0)
85 move (starty + (i / COLS), 0);
86 read (pipefd2[0], &message, 1);
87 addch (message);
90 /* Read the value of the console_flag */
91 read (pipefd2[0], &message, 1);
94 static void
95 handle_console_linux (unsigned char action)
97 char *tty_name;
98 char *mc_conssaver;
99 int status;
101 switch (action) {
102 case CONSOLE_INIT:
103 /* Close old pipe ends in case it is the 2nd time we run cons.saver */
104 close (pipefd1[1]);
105 close (pipefd2[0]);
106 /* Create two pipes for communication */
107 pipe (pipefd1);
108 pipe (pipefd2);
109 /* Get the console saver running */
110 cons_saver_pid = fork ();
111 if (cons_saver_pid < 0) {
112 /* Cannot fork */
113 /* Delete pipes */
114 close (pipefd1[1]);
115 close (pipefd1[0]);
116 close (pipefd2[1]);
117 close (pipefd2[0]);
118 console_flag = 0;
119 } else if (cons_saver_pid > 0) {
120 /* Parent */
121 /* Close the extra pipe ends */
122 close (pipefd1[0]);
123 close (pipefd2[1]);
124 /* Was the child successful? */
125 read (pipefd2[0], &console_flag, 1);
126 if (!console_flag) {
127 close (pipefd1[1]);
128 close (pipefd2[0]);
129 waitpid (cons_saver_pid, &status, 0);
131 } else {
132 /* Child */
133 /* Close the extra pipe ends */
134 close (pipefd1[1]);
135 close (pipefd2[0]);
136 tty_name = ttyname (0);
137 /* Bind the pipe 0 to the standard input */
138 close (0);
139 dup (pipefd1[0]);
140 close (pipefd1[0]);
141 /* Bind the pipe 1 to the standard output */
142 close (1);
143 dup (pipefd2[1]);
144 close (pipefd2[1]);
145 /* Bind standard error to /dev/null */
146 close (2);
147 open ("/dev/null", O_WRONLY);
148 if (tty_name) {
149 /* Exec the console save/restore handler */
150 mc_conssaver = concat_dir_and_file (SAVERDIR, "cons.saver");
151 execl (mc_conssaver, "cons.saver", tty_name, (char *) NULL);
153 /* Console is not a tty or execl() failed */
154 console_flag = 0;
155 write (1, &console_flag, 1);
156 _exit (3);
157 } /* if (cons_saver_pid ...) */
158 break;
160 case CONSOLE_DONE:
161 case CONSOLE_SAVE:
162 case CONSOLE_RESTORE:
163 /* Is tty console? */
164 if (!console_flag)
165 return;
166 /* Paranoid: Is the cons.saver still running? */
167 if (cons_saver_pid < 1 || kill (cons_saver_pid, SIGCONT)) {
168 cons_saver_pid = 0;
169 console_flag = 0;
170 return;
172 /* Send command to the console handler */
173 write (pipefd1[1], &action, 1);
174 if (action != CONSOLE_DONE) {
175 /* Wait the console handler to do its job */
176 read (pipefd2[0], &console_flag, 1);
178 if (action == CONSOLE_DONE || !console_flag) {
179 /* We are done -> Let's clean up */
180 close (pipefd1[1]);
181 close (pipefd2[0]);
182 waitpid (cons_saver_pid, &status, 0);
183 console_flag = 0;
185 break;
189 #elif defined(__FreeBSD__)
192 * FreeBSD support copyright (C) 2003 Alexander Serkov <serkov@ukrpost.net>.
193 * Support for screenmaps by Max Khon <fjoe@FreeBSD.org>
196 #define FD_OUT 1
198 static struct scrshot screen_shot;
199 static struct vid_info screen_info;
201 static void
202 console_init (void)
204 if (console_flag)
205 return;
207 screen_info.size = sizeof (screen_info);
208 if (ioctl (FD_OUT, CONS_GETINFO, &screen_info) == -1)
209 return;
211 memset (&screen_shot, 0, sizeof (screen_shot));
212 screen_shot.xsize = screen_info.mv_csz;
213 screen_shot.ysize = screen_info.mv_rsz;
214 if ((screen_shot.buf =
215 g_malloc (screen_info.mv_csz * screen_info.mv_rsz * 2)) == NULL)
216 return;
218 console_flag = 1;
221 static void
222 set_attr (unsigned attr)
225 * Convert color indices returned by SCRSHOT (red=4, green=2, blue=1)
226 * to indices for ANSI sequences (red=1, green=2, blue=4).
228 static const int color_map[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
229 int bc, tc;
231 tc = attr & 0xF;
232 bc = (attr >> 4) & 0xF;
234 printf ("\x1B[%d;%d;3%d;4%dm", (bc & 8) ? 5 : 25, (tc & 8) ? 1 : 22,
235 color_map[tc & 7], color_map[bc & 7]);
238 #define cursor_to(x, y) do { \
239 printf("\x1B[%d;%df", (y) + 1, (x) + 1); \
240 fflush(stdout); \
241 } while (0)
243 static void
244 console_restore (void)
246 int i, last;
248 if (!console_flag)
249 return;
251 cursor_to (0, 0);
253 /* restoring all content up to cursor position */
254 last = screen_info.mv_row * screen_info.mv_csz + screen_info.mv_col;
255 for (i = 0; i < last; ++i) {
256 set_attr ((screen_shot.buf[i] >> 8) & 0xFF);
257 putc (screen_shot.buf[i] & 0xFF, stdout);
260 /* restoring cursor color */
261 set_attr ((screen_shot.buf[last] >> 8) & 0xFF);
263 fflush (stdout);
266 static void
267 console_shutdown (void)
269 if (!console_flag)
270 return;
272 g_free (screen_shot.buf);
274 console_flag = 0;
277 static void
278 console_save (void)
280 int i;
281 scrmap_t map;
282 scrmap_t revmap;
284 if (!console_flag)
285 return;
287 /* screen_info.size is already set in console_init() */
288 if (ioctl (FD_OUT, CONS_GETINFO, &screen_info) == -1) {
289 console_shutdown ();
290 return;
293 /* handle console resize */
294 if (screen_info.mv_csz != screen_shot.xsize
295 || screen_info.mv_rsz != screen_shot.ysize) {
296 console_shutdown ();
297 console_init ();
300 if (ioctl (FD_OUT, CONS_SCRSHOT, &screen_shot) == -1) {
301 console_shutdown ();
302 return;
305 if (ioctl (FD_OUT, GIO_SCRNMAP, &map) == -1) {
306 console_shutdown ();
307 return;
310 for (i = 0; i < 256; i++) {
311 char *p = memchr (map.scrmap, i, 256);
312 revmap.scrmap[i] = p ? p - map.scrmap : i;
315 for (i = 0; i < screen_shot.xsize * screen_shot.ysize; i++) {
316 screen_shot.buf[i] =
317 (screen_shot.buf[i] & 0xff00) | (unsigned char) revmap.
318 scrmap[screen_shot.buf[i] & 0xff];
322 static void
323 show_console_contents_freebsd (int starty, unsigned char begin_line,
324 unsigned char end_line)
326 int col, line;
327 char c;
329 if (!console_flag)
330 return;
332 for (line = begin_line; line <= end_line; line++) {
333 move (starty + line - begin_line, 0);
334 for (col = 0; col < min (COLS, screen_info.mv_csz); col++) {
335 c = screen_shot.buf[line * screen_info.mv_csz + col] & 0xFF;
336 addch (c);
341 static void
342 handle_console_freebsd (unsigned char action)
344 switch (action) {
345 case CONSOLE_INIT:
346 console_init ();
347 break;
349 case CONSOLE_DONE:
350 console_shutdown ();
351 break;
353 case CONSOLE_SAVE:
354 console_save ();
355 break;
357 case CONSOLE_RESTORE:
358 console_restore ();
359 break;
362 #endif /* __FreeBSD__ */
364 void
365 show_console_contents (int starty, unsigned char begin_line,
366 unsigned char end_line)
368 standend ();
370 if (look_for_rxvt_extensions ()) {
371 show_rxvt_contents (starty, begin_line, end_line);
372 return;
374 #ifdef __linux__
375 show_console_contents_linux (starty, begin_line, end_line);
376 #elif defined (__FreeBSD__)
377 show_console_contents_freebsd (starty, begin_line, end_line);
378 #else
379 console_flag = 0;
380 #endif
383 void
384 handle_console (unsigned char action)
386 (void) action;
388 if (look_for_rxvt_extensions ())
389 return;
391 #ifdef __linux__
392 handle_console_linux (action);
393 #elif defined (__FreeBSD__)
394 handle_console_freebsd (action);
395 #endif