cppcheck: reduce variable scope.
[midnight-commander.git] / src / cons.handler.c
blob8c1ff4ff23ba9e7e0e0d721c8c5ff53c7e971290
1 /*
2 Client interface for General purpose Linux console save/restore server
4 Copyright (C) 1994, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
5 2006, 2007, 2011
6 The Free Software Foundation, Inc.
8 This file is part of the Midnight Commander.
10 The Midnight Commander is free software: you can redistribute it
11 and/or modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation, either version 3 of the License,
13 or (at your option) any later version.
15 The Midnight Commander is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 /** \file cons.handler.c
25 * \brief Source: client %interface for General purpose Linux console save/restore server
28 #include <config.h>
30 #include <stdlib.h>
31 #include <sys/wait.h>
32 #include <signal.h>
33 #include <stdio.h>
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #ifdef __FreeBSD__
37 #include <sys/consio.h>
38 #ifdef HAVE_SYS_IOCTL_H
39 #include <sys/ioctl.h>
40 #endif
41 #endif
42 #include <unistd.h>
44 #include "lib/global.h"
46 #include "lib/tty/tty.h"
47 #include "lib/skin.h" /* tty_set_normal_attrs */
48 #include "lib/tty/win.h"
49 #include "lib/util.h" /* mc_build_filename() */
51 #include "consaver/cons.saver.h"
53 /*** global variables ****************************************************************************/
55 #ifdef __linux__
56 int cons_saver_pid = 1;
57 #endif /* __linux__ */
59 /*** file scope macro definitions ****************************************************************/
61 #if defined(__FreeBSD__)
62 #define FD_OUT 1
63 #define cursor_to(x, y) \
64 do \
65 { \
66 printf("\x1B[%d;%df", (y) + 1, (x) + 1); \
67 fflush(stdout); \
68 } while (0)
69 #endif /* __linux__ */
71 /*** file scope type declarations ****************************************************************/
73 /*** file scope variables ************************************************************************/
75 #ifdef __linux__
76 /* The cons saver can't have a pid of 1, used to prevent bunches of
77 * #ifdef linux */
78 static int pipefd1[2] = { -1, -1 };
79 static int pipefd2[2] = { -1, -1 };
80 #elif defined(__FreeBSD__)
81 static struct scrshot screen_shot;
82 static struct vid_info screen_info;
83 #endif /* __linux__ */
85 /*** file scope functions ************************************************************************/
86 /* --------------------------------------------------------------------------------------------- */
88 #ifdef __linux__
89 static void
90 show_console_contents_linux (int starty, unsigned char begin_line, unsigned char end_line)
92 unsigned char message = 0;
93 unsigned short bytes = 0;
94 int i;
95 ssize_t ret;
97 /* Is tty console? */
98 if (mc_global.tty.console_flag == '\0')
99 return;
100 /* Paranoid: Is the cons.saver still running? */
101 if (cons_saver_pid < 1 || kill (cons_saver_pid, SIGCONT))
103 cons_saver_pid = 0;
104 mc_global.tty.console_flag = '\0';
105 return;
108 /* Send command to the console handler */
109 message = CONSOLE_CONTENTS;
110 ret = write (pipefd1[1], &message, 1);
111 /* Check for outdated cons.saver */
112 ret = read (pipefd2[0], &message, 1);
113 if (message != CONSOLE_CONTENTS)
114 return;
116 /* Send the range of lines that we want */
117 ret = write (pipefd1[1], &begin_line, 1);
118 ret = write (pipefd1[1], &end_line, 1);
119 /* Read the corresponding number of bytes */
120 ret = read (pipefd2[0], &bytes, 2);
122 /* Read the bytes and output them */
123 for (i = 0; i < bytes; i++)
125 if ((i % COLS) == 0)
126 tty_gotoyx (starty + (i / COLS), 0);
127 ret = read (pipefd2[0], &message, 1);
128 tty_print_char (message);
131 /* Read the value of the mc_global.tty.console_flag */
132 ret = read (pipefd2[0], &message, 1);
133 (void) ret;
136 /* --------------------------------------------------------------------------------------------- */
138 static void
139 handle_console_linux (console_action_t action)
141 int status;
143 switch (action)
145 case CONSOLE_INIT:
146 /* Close old pipe ends in case it is the 2nd time we run cons.saver */
147 status = close (pipefd1[1]);
148 status = close (pipefd2[0]);
149 /* Create two pipes for communication */
150 if (!((pipe (pipefd1) == 0) && ((pipe (pipefd2)) == 0)))
152 mc_global.tty.console_flag = '\0';
153 break;
155 /* Get the console saver running */
156 cons_saver_pid = fork ();
157 if (cons_saver_pid < 0)
159 /* Cannot fork */
160 /* Delete pipes */
161 status = close (pipefd1[1]);
162 status = close (pipefd1[0]);
163 status = close (pipefd2[1]);
164 status = close (pipefd2[0]);
165 mc_global.tty.console_flag = '\0';
167 else if (cons_saver_pid > 0)
169 /* Parent */
170 /* Close the extra pipe ends */
171 status = close (pipefd1[0]);
172 status = close (pipefd2[1]);
173 /* Was the child successful? */
174 status = read (pipefd2[0], &mc_global.tty.console_flag, 1);
175 if (mc_global.tty.console_flag == '\0')
177 pid_t ret;
178 status = close (pipefd1[1]);
179 status = close (pipefd2[0]);
180 ret = waitpid (cons_saver_pid, &status, 0);
181 (void) ret;
184 else
186 /* Child */
187 char *tty_name;
189 /* Close the extra pipe ends */
190 status = close (pipefd1[1]);
191 status = close (pipefd2[0]);
192 tty_name = ttyname (0);
193 /* Bind the pipe 0 to the standard input */
196 if (dup2 (pipefd1[0], 0) == -1)
197 break;
198 status = close (pipefd1[0]);
199 /* Bind the pipe 1 to the standard output */
200 if (dup2 (pipefd2[1], 1) == -1)
201 break;
203 status = close (pipefd2[1]);
204 /* Bind standard error to /dev/null */
205 status = open ("/dev/null", O_WRONLY);
206 if (dup2 (status, 2) == -1)
207 break;
208 status = close (status);
209 if (tty_name != NULL)
211 char *mc_conssaver;
213 /* Exec the console save/restore handler */
214 mc_conssaver = mc_build_filename (SAVERDIR, "cons.saver", NULL);
215 execl (mc_conssaver, "cons.saver", tty_name, (char *) NULL);
217 /* Console is not a tty or execl() failed */
219 while (0);
220 mc_global.tty.console_flag = '\0';
221 status = write (1, &mc_global.tty.console_flag, 1);
222 my_exit (3);
223 } /* if (cons_saver_pid ...) */
224 break;
226 case CONSOLE_DONE:
227 case CONSOLE_SAVE:
228 case CONSOLE_RESTORE:
229 /* Is tty console? */
230 if (mc_global.tty.console_flag == '\0')
231 return;
232 /* Paranoid: Is the cons.saver still running? */
233 if (cons_saver_pid < 1 || kill (cons_saver_pid, SIGCONT))
235 cons_saver_pid = 0;
236 mc_global.tty.console_flag = '\0';
237 return;
239 /* Send command to the console handler */
240 status = write (pipefd1[1], &action, 1);
241 if (action != CONSOLE_DONE)
243 /* Wait the console handler to do its job */
244 status = read (pipefd2[0], &mc_global.tty.console_flag, 1);
246 if (action == CONSOLE_DONE || mc_global.tty.console_flag == '\0')
248 /* We are done -> Let's clean up */
249 pid_t ret;
250 close (pipefd1[1]);
251 close (pipefd2[0]);
252 ret = waitpid (cons_saver_pid, &status, 0);
253 mc_global.tty.console_flag = '\0';
254 (void) ret;
256 break;
257 default:
258 break;
262 #elif defined(__FreeBSD__)
264 /* --------------------------------------------------------------------------------------------- */
266 * FreeBSD support copyright (C) 2003 Alexander Serkov <serkov@ukrpost.net>.
267 * Support for screenmaps by Max Khon <fjoe@FreeBSD.org>
270 static void
271 console_init (void)
273 if (mc_global.tty.console_flag != '\0')
274 return;
276 screen_info.size = sizeof (screen_info);
277 if (ioctl (FD_OUT, CONS_GETINFO, &screen_info) == -1)
278 return;
280 memset (&screen_shot, 0, sizeof (screen_shot));
281 screen_shot.xsize = screen_info.mv_csz;
282 screen_shot.ysize = screen_info.mv_rsz;
283 screen_shot.buf = g_try_malloc (screen_info.mv_csz * screen_info.mv_rsz * 2);
284 if (screen_shot.buf != NULL)
285 mc_global.tty.console_flag = '\001';
288 /* --------------------------------------------------------------------------------------------- */
290 static void
291 set_attr (unsigned attr)
294 * Convert color indices returned by SCRSHOT (red=4, green=2, blue=1)
295 * to indices for ANSI sequences (red=1, green=2, blue=4).
297 static const int color_map[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
298 int bc, tc;
300 tc = attr & 0xF;
301 bc = (attr >> 4) & 0xF;
303 printf ("\x1B[%d;%d;3%d;4%dm", (bc & 8) ? 5 : 25, (tc & 8) ? 1 : 22,
304 color_map[tc & 7], color_map[bc & 7]);
307 /* --------------------------------------------------------------------------------------------- */
309 static void
310 console_restore (void)
312 int i, last;
314 if (mc_global.tty.console_flag == '\0')
315 return;
317 cursor_to (0, 0);
319 /* restoring all content up to cursor position */
320 last = screen_info.mv_row * screen_info.mv_csz + screen_info.mv_col;
321 for (i = 0; i < last; ++i)
323 set_attr ((screen_shot.buf[i] >> 8) & 0xFF);
324 putc (screen_shot.buf[i] & 0xFF, stdout);
327 /* restoring cursor color */
328 set_attr ((screen_shot.buf[last] >> 8) & 0xFF);
330 fflush (stdout);
333 /* --------------------------------------------------------------------------------------------- */
335 static void
336 console_shutdown (void)
338 if (mc_global.tty.console_flag == '\0')
339 return;
341 g_free (screen_shot.buf);
343 mc_global.tty.console_flag = '\0';
346 /* --------------------------------------------------------------------------------------------- */
348 static void
349 console_save (void)
351 int i;
352 scrmap_t map;
353 scrmap_t revmap;
355 if (mc_global.tty.console_flag == '\0')
356 return;
358 /* screen_info.size is already set in console_init() */
359 if (ioctl (FD_OUT, CONS_GETINFO, &screen_info) == -1)
361 console_shutdown ();
362 return;
365 /* handle console resize */
366 if (screen_info.mv_csz != screen_shot.xsize || screen_info.mv_rsz != screen_shot.ysize)
368 console_shutdown ();
369 console_init ();
372 if (ioctl (FD_OUT, CONS_SCRSHOT, &screen_shot) == -1)
374 console_shutdown ();
375 return;
378 if (ioctl (FD_OUT, GIO_SCRNMAP, &map) == -1)
380 console_shutdown ();
381 return;
384 for (i = 0; i < 256; i++)
386 char *p = memchr (map.scrmap, i, 256);
387 revmap.scrmap[i] = p ? p - map.scrmap : i;
390 for (i = 0; i < screen_shot.xsize * screen_shot.ysize; i++)
392 /* *INDENT-OFF* */
393 screen_shot.buf[i] = (screen_shot.buf[i] & 0xff00)
394 | (unsigned char) revmap.scrmap[screen_shot.buf[i] & 0xff];
395 /* *INDENT-ON* */
399 /* --------------------------------------------------------------------------------------------- */
401 static void
402 show_console_contents_freebsd (int starty, unsigned char begin_line, unsigned char end_line)
404 int col, line;
405 char c;
407 if (mc_global.tty.console_flag == '\0')
408 return;
410 for (line = begin_line; line <= end_line; line++)
412 tty_gotoyx (starty + line - begin_line, 0);
413 for (col = 0; col < min (COLS, screen_info.mv_csz); col++)
415 c = screen_shot.buf[line * screen_info.mv_csz + col] & 0xFF;
416 tty_print_char (c);
421 /* --------------------------------------------------------------------------------------------- */
423 static void
424 handle_console_freebsd (console_action_t action)
426 switch (action)
428 case CONSOLE_INIT:
429 console_init ();
430 break;
432 case CONSOLE_DONE:
433 console_shutdown ();
434 break;
436 case CONSOLE_SAVE:
437 console_save ();
438 break;
440 case CONSOLE_RESTORE:
441 console_restore ();
442 break;
443 default:
444 break;
447 #endif /* __FreeBSD__ */
449 /* --------------------------------------------------------------------------------------------- */
450 /*** public functions ****************************************************************************/
451 /* --------------------------------------------------------------------------------------------- */
453 void
454 show_console_contents (int starty, unsigned char begin_line, unsigned char end_line)
456 tty_set_normal_attrs ();
458 if (look_for_rxvt_extensions ())
460 show_rxvt_contents (starty, begin_line, end_line);
461 return;
463 #ifdef __linux__
464 show_console_contents_linux (starty, begin_line, end_line);
465 #elif defined (__FreeBSD__)
466 show_console_contents_freebsd (starty, begin_line, end_line);
467 #else
468 mc_global.tty.console_flag = '\0';
469 #endif
472 /* --------------------------------------------------------------------------------------------- */
474 void
475 handle_console (console_action_t action)
477 (void) action;
479 if (look_for_rxvt_extensions ())
480 return;
482 #ifdef __linux__
483 handle_console_linux (action);
484 #elif defined (__FreeBSD__)
485 handle_console_freebsd (action);
486 #endif
489 /* --------------------------------------------------------------------------------------------- */