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. */
23 #include <sys/types.h>
28 #include <sys/types.h>
30 #include <sys/console.h>
34 #endif /* SCO_FLAVOR */
37 #include <sys/consio.h>
38 #include <sys/ioctl.h>
39 #endif /* __FreeBSD__ */
43 #include "cons.saver.h"
45 signed char console_flag
= 0;
49 /* The cons saver can't have a pid of 1, used to prevent bunches of
52 int cons_saver_pid
= 1;
53 static int pipefd1
[2] = { -1, -1 };
54 static int pipefd2
[2] = { -1, -1 };
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;
67 /* Paranoid: Is the cons.saver still running? */
68 if (cons_saver_pid
< 1 || kill (cons_saver_pid
, SIGCONT
)) {
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
)
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
++) {
91 move (starty
+ (i
/ COLS
), 0);
92 read (pipefd2
[0], &message
, 1);
96 /* Read the value of the console_flag */
97 read (pipefd2
[0], &message
, 1);
101 handle_console_linux (unsigned char action
)
109 /* Close old pipe ends in case it is the 2nd time we run cons.saver */
112 /* Create two pipes for communication */
115 /* Get the console saver running */
116 cons_saver_pid
= fork ();
117 if (cons_saver_pid
< 0) {
125 } else if (cons_saver_pid
> 0) {
127 /* Close the extra pipe ends */
130 /* Was the child successful? */
131 read (pipefd2
[0], &console_flag
, 1);
135 waitpid (cons_saver_pid
, &status
, 0);
139 /* Close the extra pipe ends */
142 tty_name
= ttyname (0);
143 /* Bind the pipe 0 to the standard input */
147 /* Bind the pipe 1 to the standard output */
151 /* Bind standard error to /dev/null */
153 open ("/dev/null", O_WRONLY
);
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 */
161 write (1, &console_flag
, 1);
165 } /* if (cons_saver_pid ...) */
170 case CONSOLE_RESTORE
:
171 /* Is tty console? */
174 /* Paranoid: Is the cons.saver still running? */
175 if (cons_saver_pid
< 1 || kill (cons_saver_pid
, SIGCONT
)) {
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 */
190 waitpid (cons_saver_pid
, &status
, 0);
197 #elif defined(SCO_FLAVOR)
200 ** SCO console save/restore handling routines
201 ** Copyright (C) 1997 Alex Tkachenko <alex@bcs.zaporizhzhe.ua>
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;
213 #define SIG_ACQUIRE 21 /* originally: handset, line status change (?) */
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
));
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
);
244 if (screen
!= NULL
) {
253 struct m6845_info mi
;
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
;
269 smode
.waitv
= smode
.relsig
= smode
.acqsig
= smode
.frsig
=
271 ioctl (FD_OUT
, VT_SETMODE
, &smode
);
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 */
294 struct m6845_info mi
;
295 unsigned short *start
;
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 */
315 int adapter
= ioctl (FD_OUT
, CONS_CURRENT
, 0);
320 vi
.size
= sizeof (struct vid_info
);
321 ioctl (FD_OUT
, CONS_GETINFO
, &(vi
));
329 screen
= (unsigned short *) g_malloc (height
* width
* 2);
330 if (screen
== NULL
) {
335 mode
= ioctl (FD_OUT
, CONS_GET
, 0);
336 ioctl (FD_OUT
, MODESWITCH
| mode
, 0);
343 handle_console_sco (unsigned char action
)
358 case CONSOLE_RESTORE
:
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>
389 static struct scrshot screen_shot
;
390 static struct vid_info screen_info
;
398 screen_info
.size
= sizeof (screen_info
);
399 if (ioctl (FD_OUT
, CONS_GETINFO
, &screen_info
) == -1)
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
)
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 };
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); \
435 console_restore (void)
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);
458 console_shutdown (void)
463 g_free (screen_shot
.buf
);
478 /* screen_info.size is already set in console_init() */
479 if (ioctl (FD_OUT
, CONS_GETINFO
, &screen_info
) == -1) {
484 /* handle console resize */
485 if (screen_info
.mv_csz
!= screen_shot
.xsize
486 || screen_info
.mv_rsz
!= screen_shot
.ysize
) {
491 if (ioctl (FD_OUT
, CONS_SCRSHOT
, &screen_shot
) == -1) {
496 if (ioctl (FD_OUT
, GIO_SCRNMAP
, &map
) == -1) {
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
++) {
508 (screen_shot
.buf
[i
] & 0xff00) | (unsigned char) revmap
.
509 scrmap
[screen_shot
.buf
[i
] & 0xff];
514 show_console_contents_freebsd (int starty
, unsigned char begin_line
,
515 unsigned char end_line
)
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;
533 handle_console_freebsd (unsigned char action
)
548 case CONSOLE_RESTORE
:
553 #endif /* __FreeBSD__ */
556 show_console_contents (int starty
, unsigned char begin_line
,
557 unsigned char end_line
)
561 if (look_for_rxvt_extensions ()) {
562 show_rxvt_contents (starty
, begin_line
, end_line
);
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
);
577 handle_console (unsigned char action
)
579 if (look_for_rxvt_extensions ())
583 handle_console_linux (action
);
584 #elif defined (__FreeBSD__)
585 handle_console_freebsd (action
);
586 #elif defined (SCO_FLAVOR)
587 handle_console_sco (action
);