Last fuzzy trimmed...
[midnight-commander.git] / src / cons.handler.c
blob549cdfe990cc1cb4f0efff420e80fabe2d63012e
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 /* The cons saver can't have a pid of 1, used to prevent bunches of */
19 /*#ifdef linux */
20 #include <config.h>
22 #ifdef HAVE_UNISTD_H
23 # include <unistd.h>
24 #endif
25 #include <fcntl.h>
26 #include <sys/types.h>
27 #include <signal.h>
29 #include "global.h"
30 #include "tty.h"
31 #include "cons.saver.h"
33 signed char console_flag = 0;
35 #if defined(linux) || defined(__linux__)
36 #include "main.h"
38 int cons_saver_pid = 1;
39 static int pipefd1 [2] = {-1, -1}, pipefd2 [2] = {-1, -1};
41 void show_console_contents (int starty, unsigned char begin_line, unsigned char end_line)
43 unsigned char message = 0;
44 unsigned short bytes = 0;
45 int i;
47 standend ();
49 if (look_for_rxvt_extensions ()) {
50 show_rxvt_contents (starty, begin_line, end_line);
51 return;
54 /* Is tty console? */
55 if (!console_flag)
56 return;
57 /* Paranoid: Is the cons.saver still running? */
58 if (cons_saver_pid < 1 || kill (cons_saver_pid, SIGCONT)){
59 cons_saver_pid = 0;
60 console_flag = 0;
61 return;
64 /* Send command to the console handler */
65 message = CONSOLE_CONTENTS;
66 write (pipefd1[1], &message, 1);
67 /* Check for outdated cons.saver */
68 read (pipefd2[0], &message, 1);
69 if (message != CONSOLE_CONTENTS)
70 return;
72 /* Send the range of lines that we want */
73 write (pipefd1[1], &begin_line, 1);
74 write (pipefd1[1], &end_line, 1);
75 /* Read the corresponding number of bytes */
76 read (pipefd2[0], &bytes, 2);
78 /* Read the bytes and output them */
79 for (i = 0; i < bytes; i++){
80 if ((i % COLS) == 0)
81 move (starty+(i/COLS), 0);
82 read (pipefd2[0], &message, 1);
83 addch (message);
86 /* Read the value of the console_flag */
87 read (pipefd2[0], &message, 1);
90 void handle_console (unsigned char action)
92 char *tty_name;
93 char *mc_conssaver;
94 int status;
96 switch (action){
97 case CONSOLE_INIT:
98 if (look_for_rxvt_extensions ())
99 return;
100 /* Close old pipe ends in case it is the 2nd time we run cons.saver */
101 close (pipefd1[1]);
102 close (pipefd2[0]);
103 /* Create two pipes for communication */
104 pipe (pipefd1);
105 pipe (pipefd2);
106 /* Get the console saver running */
107 cons_saver_pid = fork ();
108 if (cons_saver_pid < 0){
109 /* Cannot fork */
110 /* Delete pipes */
111 close (pipefd1[1]);
112 close (pipefd1[0]);
113 close (pipefd2[1]);
114 close (pipefd2[0]);
115 console_flag = 0;
116 } else if (cons_saver_pid > 0){
117 /* Parent */
118 /* Close the extra pipe ends */
119 close (pipefd1[0]);
120 close (pipefd2[1]);
121 /* Was the child successful? */
122 read (pipefd2[0], &console_flag, 1);
123 if (!console_flag){
124 close (pipefd1[1]);
125 close (pipefd2[0]);
126 waitpid (cons_saver_pid, &status, 0);
128 } else {
129 /* Child */
130 /* Close the extra pipe ends */
131 close (pipefd1[1]);
132 close (pipefd2[0]);
133 tty_name = ttyname (0);
134 /* Bind the pipe 0 to the standard input */
135 close (0);
136 dup (pipefd1[0]);
137 close (pipefd1[0]);
138 /* Bind the pipe 1 to the standard output */
139 close (1);
140 dup (pipefd2[1]);
141 close (pipefd2[1]);
142 /* Bind standard error to /dev/null */
143 close (2);
144 open ("/dev/null", O_WRONLY);
145 if (tty_name) {
146 /* Exec the console save/restore handler */
147 mc_conssaver = concat_dir_and_file (mc_home, "bin/cons.saver");
148 execl (mc_conssaver, "cons.saver", tty_name, NULL);
150 /* Console is not a tty or execl() failed */
151 console_flag = 0;
152 write (1, &console_flag, 1);
153 close (1);
154 close (0);
155 _exit (3);
156 } /* if (cons_saver_pid ...) */
157 break;
159 case CONSOLE_DONE:
160 case CONSOLE_SAVE:
161 case CONSOLE_RESTORE:
162 if (look_for_rxvt_extensions ())
163 return;
164 /* Is tty console? */
165 if (!console_flag)
166 return;
167 /* Paranoid: Is the cons.saver still running? */
168 if (cons_saver_pid < 1 || kill (cons_saver_pid, SIGCONT)){
169 cons_saver_pid = 0;
170 console_flag = 0;
171 return;
173 /* Send command to the console handler */
174 write (pipefd1[1], &action, 1);
175 if (action != CONSOLE_DONE){
176 /* Wait the console handler to do its job */
177 read (pipefd2[0], &console_flag, 1);
179 if (action == CONSOLE_DONE || !console_flag){
180 /* We are done -> Let's clean up */
181 close (pipefd1 [1]);
182 close (pipefd2 [0]);
183 waitpid (cons_saver_pid, &status, 0);
184 console_flag = 0;
186 break;
190 #endif /* #ifdef linux */
192 #ifdef SCO_FLAVOR
194 ** SCO console save/restore handling routines
195 ** Copyright (C) 1997 Alex Tkachenko <alex@bcs.zaporizhzhe.ua>
198 #include <stdio.h>
199 #include <sys/types.h>
200 #include <sys/vid.h>
201 #include <sys/console.h>
202 #include <sys/vtkd.h>
203 #include <memory.h>
204 #include <signal.h>
205 #include "tty.h"
206 #include "util.h"
207 #include "color.h"
208 #include "cons.saver.h"
210 static int FD_OUT = 2;
212 static unsigned short* vidbuf = NULL;
213 static unsigned short* screen = NULL;
214 static int height = 0, width = 0, saved_attr = 0;
215 static int mode = 0;
217 #define SIG_ACQUIRE 21 /* originally: handset, line status change (?) */
219 static int
220 vt_active()
222 struct vid_info vi;
223 int adapter = ioctl(FD_OUT, CONS_CURRENT, 0);
225 vi.size = sizeof(struct vid_info);
226 ioctl(FD_OUT, CONS_GETINFO, &(vi));
227 return (vi.m_num == ioctl(FD_OUT,CONSADP,adapter));
230 static void
231 console_acquire_vt()
233 struct vt_mode smode;
235 signal(SIG_ACQUIRE, SIG_DFL);
236 smode.mode = VT_AUTO;
237 smode.waitv = smode.relsig = smode.acqsig = smode.frsig = 0;
238 ioctl(FD_OUT, VT_SETMODE, &smode);
239 ioctl(FD_OUT, VT_RELDISP, VT_ACKACQ);
242 static void
243 console_shutdown()
245 if (!console_flag)
247 return;
249 if (screen != NULL)
251 g_free (screen);
253 console_flag = 0;
256 static void
257 console_save()
259 struct m6845_info mi;
261 if (!console_flag)
263 return;
266 if (!vt_active())
268 struct vt_mode smode;
271 ** User switched out of our vt. Let's wait until we get SIG_ACQUIRE,
272 ** otherwise we could save wrong screen image
274 signal(SIG_ACQUIRE, console_acquire_vt);
275 smode.mode = VT_PROCESS;
276 smode.waitv = 0;
277 smode.waitv = smode.relsig = smode.acqsig = smode.frsig = SIG_ACQUIRE;
278 ioctl(FD_OUT, VT_SETMODE, &smode);
280 pause();
283 saved_attr = ioctl(FD_OUT, GIO_ATTR, 0);
285 vidbuf = (unsigned short*) ioctl(FD_OUT, MAPCONS, 0);
287 mi.size = sizeof(struct m6845_info);
288 ioctl(FD_OUT, CONS_6845INFO, &mi);
291 unsigned short* start = vidbuf + mi.screen_top;
292 memcpy(screen, start, width * height * 2);
295 write(FD_OUT,"\0337",2); /* save cursor position */
298 static void
299 console_restore()
301 struct m6845_info mi;
302 unsigned short* start;
304 if (!console_flag)
306 return;
309 write (FD_OUT, "\033[2J", 4);
311 mi.size = sizeof(struct m6845_info);
312 ioctl(FD_OUT, CONS_6845INFO, &mi);
314 start = vidbuf + mi.screen_top;
315 memcpy(start, screen, width * height * 2);
316 write(FD_OUT,"\0338",2); /* restore cursor position */
319 static void
320 console_init()
322 struct vid_info vi;
323 int adapter = ioctl(FD_OUT, CONS_CURRENT, 0);
325 console_flag = 0;
327 if (adapter != -1)
329 vi.size = sizeof(struct vid_info);
330 ioctl(FD_OUT, CONS_GETINFO, &(vi));
332 if (vt_active())
334 console_flag = 1;
336 height = vi.mv_rsz;
337 width = vi.mv_csz;
339 screen = (unsigned short*) g_malloc (height * width * 2);
340 if (screen == NULL)
342 console_shutdown();
343 return;
345 console_save();
346 mode = ioctl(FD_OUT, CONS_GET, 0);
347 ioctl(FD_OUT, MODESWITCH | mode, 0);
348 console_restore();
353 void
354 handle_console (unsigned char action)
356 if (look_for_rxvt_extensions ())
357 return;
358 switch (action){
359 case CONSOLE_INIT:
360 console_init();
361 break;
363 case CONSOLE_DONE:
364 console_shutdown();
365 break;
367 case CONSOLE_SAVE:
368 console_save();
369 break;
371 case CONSOLE_RESTORE:
372 console_restore();
373 break;
374 default:
375 /* Nothing */;
379 void
380 show_console_contents (int starty, unsigned char begin_line, unsigned char end_line)
382 register int i, len = (end_line - begin_line) * width;
384 if (look_for_rxvt_extensions ()) {
385 show_rxvt_contents (starty, begin_line, end_line);
386 return;
388 attrset(DEFAULT_COLOR);
389 for (i = 0; i < len; i++)
391 if ((i % width) == 0)
392 move (starty+(i/width), 0);
393 addch ((unsigned char)screen[width*starty + i]);
397 #endif /* SCO_FLAVOR */
400 #if !defined(linux) && !defined(__linux__) && !defined(SCO_FLAVOR)
402 #include "tty.h"
404 void show_console_contents (int starty, unsigned char begin_line, unsigned char end_line)
406 standend ();
408 if (look_for_rxvt_extensions ()) {
409 show_rxvt_contents (starty, begin_line, end_line);
410 return;
412 console_flag = 0;
415 void handle_console (unsigned char action)
417 look_for_rxvt_extensions ();
420 #endif /* !defined(linux) && !defined(__linux__) && !defined(SCO_FLAVOR) */