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
30 #include <sys/types.h>
32 #include <sys/consio.h>
33 #include <sys/ioctl.h>
37 #include "lib/global.h"
39 #include "lib/tty/tty.h"
40 #include "lib/skin.h" /* tty_set_normal_attrs */
41 #include "lib/tty/win.h"
42 #include "lib/util.h" /* concat_dir_and_file() */
44 #include "consaver/cons.saver.h"
46 /*** global variables ****************************************************************************/
49 int cons_saver_pid
= 1;
50 #endif /* __linux__ */
52 /*** file scope macro definitions ****************************************************************/
54 #if defined(__FreeBSD__)
56 #define cursor_to(x, y) \
59 printf("\x1B[%d;%df", (y) + 1, (x) + 1); \
62 #endif /* __linux__ */
64 /*** file scope type declarations ****************************************************************/
66 /*** file scope variables ************************************************************************/
69 /* The cons saver can't have a pid of 1, used to prevent bunches of
71 static int pipefd1
[2] = { -1, -1 };
72 static int pipefd2
[2] = { -1, -1 };
73 #elif defined(__FreeBSD__)
74 static struct scrshot screen_shot
;
75 static struct vid_info screen_info
;
76 #endif /* __linux__ */
78 /*** file scope functions ************************************************************************/
79 /* --------------------------------------------------------------------------------------------- */
83 show_console_contents_linux (int starty
, unsigned char begin_line
, unsigned char end_line
)
85 unsigned char message
= 0;
86 unsigned short bytes
= 0;
91 if (!mc_global
.tty
.console_flag
)
93 /* Paranoid: Is the cons.saver still running? */
94 if (cons_saver_pid
< 1 || kill (cons_saver_pid
, SIGCONT
))
97 mc_global
.tty
.console_flag
= '\0';
101 /* Send command to the console handler */
102 message
= CONSOLE_CONTENTS
;
103 ret
= write (pipefd1
[1], &message
, 1);
104 /* Check for outdated cons.saver */
105 ret
= read (pipefd2
[0], &message
, 1);
106 if (message
!= CONSOLE_CONTENTS
)
109 /* Send the range of lines that we want */
110 ret
= write (pipefd1
[1], &begin_line
, 1);
111 ret
= write (pipefd1
[1], &end_line
, 1);
112 /* Read the corresponding number of bytes */
113 ret
= read (pipefd2
[0], &bytes
, 2);
115 /* Read the bytes and output them */
116 for (i
= 0; i
< bytes
; i
++)
119 tty_gotoyx (starty
+ (i
/ COLS
), 0);
120 ret
= read (pipefd2
[0], &message
, 1);
121 tty_print_char (message
);
124 /* Read the value of the mc_global.tty.console_flag */
125 ret
= read (pipefd2
[0], &message
, 1);
128 /* --------------------------------------------------------------------------------------------- */
131 handle_console_linux (unsigned char action
)
140 /* Close old pipe ends in case it is the 2nd time we run cons.saver */
141 status
= close (pipefd1
[1]);
142 status
= close (pipefd2
[0]);
143 /* Create two pipes for communication */
144 if (!((pipe (pipefd1
) == 0) && ((pipe (pipefd2
)) == 0)))
146 mc_global
.tty
.console_flag
= '\0';
149 /* Get the console saver running */
150 cons_saver_pid
= fork ();
151 if (cons_saver_pid
< 0)
155 status
= close (pipefd1
[1]);
156 status
= close (pipefd1
[0]);
157 status
= close (pipefd2
[1]);
158 status
= close (pipefd2
[0]);
159 mc_global
.tty
.console_flag
= '\0';
161 else if (cons_saver_pid
> 0)
164 /* Close the extra pipe ends */
165 status
= close (pipefd1
[0]);
166 status
= close (pipefd2
[1]);
167 /* Was the child successful? */
168 status
= read (pipefd2
[0], &mc_global
.tty
.console_flag
, 1);
169 if (!mc_global
.tty
.console_flag
)
172 status
= close (pipefd1
[1]);
173 status
= close (pipefd2
[0]);
174 ret
= waitpid (cons_saver_pid
, &status
, 0);
180 /* Close the extra pipe ends */
181 status
= close (pipefd1
[1]);
182 status
= close (pipefd2
[0]);
183 tty_name
= ttyname (0);
184 /* Bind the pipe 0 to the standard input */
187 if (dup2 (pipefd1
[0], 0) == -1)
189 status
= close (pipefd1
[0]);
190 /* Bind the pipe 1 to the standard output */
191 if (dup2 (pipefd2
[1], 1) == -1)
194 status
= close (pipefd2
[1]);
195 /* Bind standard error to /dev/null */
196 status
= open ("/dev/null", O_WRONLY
);
197 if (dup2 (status
, 2) == -1)
199 status
= close (status
);
202 /* Exec the console save/restore handler */
203 mc_conssaver
= concat_dir_and_file (SAVERDIR
, "cons.saver");
204 execl (mc_conssaver
, "cons.saver", tty_name
, (char *) NULL
);
206 /* Console is not a tty or execl() failed */
209 mc_global
.tty
.console_flag
= '\0';
210 status
= write (1, &mc_global
.tty
.console_flag
, 1);
212 } /* if (cons_saver_pid ...) */
217 case CONSOLE_RESTORE
:
218 /* Is tty console? */
219 if (!mc_global
.tty
.console_flag
)
221 /* Paranoid: Is the cons.saver still running? */
222 if (cons_saver_pid
< 1 || kill (cons_saver_pid
, SIGCONT
))
225 mc_global
.tty
.console_flag
= '\0';
228 /* Send command to the console handler */
229 status
= write (pipefd1
[1], &action
, 1);
230 if (action
!= CONSOLE_DONE
)
232 /* Wait the console handler to do its job */
233 status
= read (pipefd2
[0], &mc_global
.tty
.console_flag
, 1);
235 if (action
== CONSOLE_DONE
|| !mc_global
.tty
.console_flag
)
237 /* We are done -> Let's clean up */
241 ret
= waitpid (cons_saver_pid
, &status
, 0);
242 mc_global
.tty
.console_flag
= '\0';
248 #elif defined(__FreeBSD__)
250 /* --------------------------------------------------------------------------------------------- */
252 * FreeBSD support copyright (C) 2003 Alexander Serkov <serkov@ukrpost.net>.
253 * Support for screenmaps by Max Khon <fjoe@FreeBSD.org>
259 if (mc_global
.tty
.console_flag
)
262 screen_info
.size
= sizeof (screen_info
);
263 if (ioctl (FD_OUT
, CONS_GETINFO
, &screen_info
) == -1)
266 memset (&screen_shot
, 0, sizeof (screen_shot
));
267 screen_shot
.xsize
= screen_info
.mv_csz
;
268 screen_shot
.ysize
= screen_info
.mv_rsz
;
269 screen_shot
.buf
= g_try_malloc (screen_info
.mv_csz
* screen_info
.mv_rsz
* 2);
270 if (screen_shot
.buf
!= NULL
)
271 mc_global
.tty
.console_flag
= '\001';
274 /* --------------------------------------------------------------------------------------------- */
277 set_attr (unsigned attr
)
280 * Convert color indices returned by SCRSHOT (red=4, green=2, blue=1)
281 * to indices for ANSI sequences (red=1, green=2, blue=4).
283 static const int color_map
[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
287 bc
= (attr
>> 4) & 0xF;
289 printf ("\x1B[%d;%d;3%d;4%dm", (bc
& 8) ? 5 : 25, (tc
& 8) ? 1 : 22,
290 color_map
[tc
& 7], color_map
[bc
& 7]);
293 /* --------------------------------------------------------------------------------------------- */
296 console_restore (void)
300 if (!mc_global
.tty
.console_flag
)
305 /* restoring all content up to cursor position */
306 last
= screen_info
.mv_row
* screen_info
.mv_csz
+ screen_info
.mv_col
;
307 for (i
= 0; i
< last
; ++i
)
309 set_attr ((screen_shot
.buf
[i
] >> 8) & 0xFF);
310 putc (screen_shot
.buf
[i
] & 0xFF, stdout
);
313 /* restoring cursor color */
314 set_attr ((screen_shot
.buf
[last
] >> 8) & 0xFF);
319 /* --------------------------------------------------------------------------------------------- */
322 console_shutdown (void)
324 if (!mc_global
.tty
.console_flag
)
327 g_free (screen_shot
.buf
);
329 mc_global
.tty
.console_flag
= '\0';
332 /* --------------------------------------------------------------------------------------------- */
341 if (!mc_global
.tty
.console_flag
)
344 /* screen_info.size is already set in console_init() */
345 if (ioctl (FD_OUT
, CONS_GETINFO
, &screen_info
) == -1)
351 /* handle console resize */
352 if (screen_info
.mv_csz
!= screen_shot
.xsize
|| screen_info
.mv_rsz
!= screen_shot
.ysize
)
358 if (ioctl (FD_OUT
, CONS_SCRSHOT
, &screen_shot
) == -1)
364 if (ioctl (FD_OUT
, GIO_SCRNMAP
, &map
) == -1)
370 for (i
= 0; i
< 256; i
++)
372 char *p
= memchr (map
.scrmap
, i
, 256);
373 revmap
.scrmap
[i
] = p
? p
- map
.scrmap
: i
;
376 for (i
= 0; i
< screen_shot
.xsize
* screen_shot
.ysize
; i
++)
379 (screen_shot
.buf
[i
] & 0xff00) | (unsigned char) revmap
.
380 scrmap
[screen_shot
.buf
[i
] & 0xff];
384 /* --------------------------------------------------------------------------------------------- */
387 show_console_contents_freebsd (int starty
, unsigned char begin_line
, unsigned char end_line
)
392 if (!mc_global
.tty
.console_flag
)
395 for (line
= begin_line
; line
<= end_line
; line
++)
397 tty_gotoyx (starty
+ line
- begin_line
, 0);
398 for (col
= 0; col
< min (COLS
, screen_info
.mv_csz
); col
++)
400 c
= screen_shot
.buf
[line
* screen_info
.mv_csz
+ col
] & 0xFF;
406 /* --------------------------------------------------------------------------------------------- */
409 handle_console_freebsd (unsigned char action
)
425 case CONSOLE_RESTORE
:
430 #endif /* __FreeBSD__ */
432 /* --------------------------------------------------------------------------------------------- */
433 /*** public functions ****************************************************************************/
434 /* --------------------------------------------------------------------------------------------- */
437 show_console_contents (int starty
, unsigned char begin_line
, unsigned char end_line
)
439 tty_set_normal_attrs ();
441 if (look_for_rxvt_extensions ())
443 show_rxvt_contents (starty
, begin_line
, end_line
);
447 show_console_contents_linux (starty
, begin_line
, end_line
);
448 #elif defined (__FreeBSD__)
449 show_console_contents_freebsd (starty
, begin_line
, end_line
);
451 mc_global
.tty
.console_flag
= '\0';
455 /* --------------------------------------------------------------------------------------------- */
458 handle_console (unsigned char action
)
462 if (look_for_rxvt_extensions ())
466 handle_console_linux (action
);
467 #elif defined (__FreeBSD__)
468 handle_console_freebsd (action
);
472 /* --------------------------------------------------------------------------------------------- */