When I was (not very successfully) reading errors and typos in the previous post,
bobry offered to discuss how to make a story in the console (which is Shift-PgUp).
The obvious way to do something related to the terminals is to look at what others have done and do the same. In the process of studying this, we noticed an interesting feature: some programs, showing the contents, restore the screen before launching the application (mc, vim, nano, less, etc.). In addition, when they start, the scroll bar disappears (in xterm / gnome-terminal).
To study “how” it was decided to focus on MC, as the oldest (and independent of ncurses) application.
')
Next comes the romatic story of how mc makes toggle_panel () with a lot of quotes from the source code.
At the same time, the reader will be able to see what the “look in the source” process looks like.
So, the source code is MC. It is known that the screen "behind" can be seen on Ctrl-O. The combination of buttons appeared in the old Norton Commander, from which all subsequent NC console clones borrowed it: Dos Navigator, Volkov Commander, Far Navigator, etc.
They downloaded raw materials (apt-get source mc), looked inside.
Pretty quickly, we found the keybind.c file, where it was easy to see that the Ctrl-letter combinations were encoded as “CL” (in our case, “Co”). A simple array of enums (or is it definees? Not important), the required line:
{XCTRL ('o'), CK_ShowCommandLine, "Co"},
Next (we don’t know, MC architecture, and don’t really want to know), we simply use the
grep utility to find where this function is:
grep CK_ShowCommandLine -A3 -B3 -r *
Required file - main.c
main.c: case CK_ShowCommandLine:
main.c- view_other_cmd ();
main.c- break;
and near:
viewer / actions_cmd.c: case CK_ShowCommandLine:
viewer / actions_cmd.c- view_other_cmd ();
viewer / actions_cmd.c- break;
And the viewer. and mc itself use the same function: view_other_cmd. Similar grep, is the file cmd.c with the desired function:
void
view_other_cmd (void)
{
static int message_flag = TRUE;
if (! xterm_flag &&! console_flag &&! use_subshell &&! output_starts_shell) {
if (message_flag)
message (D_ERROR, MSG_ERROR,
_ ("Not an xterm or Linux console; \ n"
"the panels cannot be toggled."));
message_flag = FALSE;
} else {
toggle_panels ();
}
}
The eye cuts the old style of text formatting a little, but ...
So,
- The sought toggle_pannels () function. In fact, we immediately rushed to watch it, but now we will be more consistent and carefully read the error case (note the elegant emulation of closures in C - using static in a variable in order to display an error message only once programs).
- The error is displayed if ... if we have NOT xterm and NOT console. The part related to the subshell does not interest us, but about a separate xterm check we tick the box.
We are looking for toggle_pannels (). File execute.c. The function is large, I will quote an interesting place.
tty_reset_screen ();
do_exit_ca_mode ();
tty_raw_mode ();
if (console_flag)
handle_console (CONSOLE_RESTORE);
- tty_reset_screen - let's say
- do_exit_ca_mode - oh interesting
- tty_raw_mode is just a switch of character input modes
- Interestingly, if we have a console, then a handle_console is made ...
What is ca_mode? Minor hitch (file not in src, but in lib), tty / win.c. next to it is the opposite do_enter_ca_mode:
void
do_enter_ca_mode (void)
{
if (xterm_flag) {
fprintf (stdout, / * ESC_STR ") 0" * / ESC_STR "7" ESC_STR "[? 47h");
fflush (stdout);
}
}
void
do_exit_ca_mode (void)
{
if (xterm_flag) {
fprintf (stdout, ESC_STR "[? 47l" ESC_STR "8" ESC_STR "[m");
fflush (stdout);
}
}
Total - switching of the strange mode which we do not know. Associate with xterm. Quickgun suggests that this is "Use Alternate Screen Buffer":
Xterm maintains two screen buffers. The normal screen buffer is saved by the saveLines resource. This screen contains no additional saved lines. When you alternate screen buffer is active, you can’t scroll back to view saved lines. Xterm provides control sequences and menu entries for switching between the two.
OK. Clear. Xterm has a special esc code.
And linux? Go to the linux console (real, Ctrl-Alt-F1), try vim - when you exit, we see the previous contents on the screen. less ... see. nano ... see. That is, linux (according to console_codes) does not support this. I see. And mc? And mc works, asshole! How? Why? Go back to the mc source code, see ... And what does the handle_console do?
We are looking for ... (cons.handler.c):
void
handle_console (unsigned char action)
{
(void) action;
if (look_for_rxvt_extensions ())
return;
#ifdef __linux__
handle_console_linux (action);
#elif defined (__FreeBSD__)
handle_console_freebsd (action);
#endif
Hmm ... It turns out that in linux and in FreeBSD this is handled differently. (But what about solaris? There is no more your solaris, Oracle threw the boots onto the remote.)
We look handle_console_linux, through it console_save. What do we see? MC forks a separate process called cons.saver, which does ioctl, reading and writing to strange / dev / vcsa * devices. What kind of devices?
Oh, new, wonderful world
It turns out that linux has pseudo-devices that correspond to the CGA (VGA) memory of the adapter in text mode, where the data is stored as an array
struct {
char char;
char Attrib;
}
Yes, yes, that old long forgotten DOS, with direct access to video memory. We check - indeed, hexdump files completely show us the contents of the screen. Note that to access the device, you must have the rights to it. This is usually done in the following way: they put a group on the device file, put the owner of this group on the file, and set the sgid-bit to it.
In Debian, cons.saver has sgid bits for the tty group (common group for accessing pseudo-terminals), and in centos for the special group vcsa. In principle, agree with the approach of RHEL / CentOS, it is more secure.
So, a special file ... That is, the MC with the help of a cunning hack reads the contents of the screen, and when necessary, writes it back ...
But the virtual machine console is not on the VGA-adapter! This is a clean serial port. And a simple check is suspicious - on all virtual machines vcsa is pristine clean, because we do not have a VGA adapter. I mean, video cards.
What to do? Well, for starters, check out what mc will do in a serial port situation. As we know, there is no difference between a UNIX98 pseudo-terminal and a serial port. We go back to the real linux (console), log in via ssh to any server, start mc, and, voila - not supported.
Thus, we, making the console on the serial port, in principle, cannot provide an analogue of vcsa - and the hack in mc about ctrl-o cannot work. Basically.
What about xterm?
Implementing an esc code for xterm would be easy. But ... We do not have access to the contents of the virtual machines, we can not change the environment of the users - and therefore, by default, linux expects that on the serial port it has the terminal type linux (TERM = linux) and does not implement xterm / xrvt functions meaning - they still will not use.
Just in case, we check how mc learns about the existence of xterm extensions ...
const char * termvalue;
termvalue = getenv ("TERM");
Alas, the environment variable (and I was hoping for a query string). Well, definitely not. Alas.
By the way, exactly the same hack (but adjusted for architectural features) is used in FreeBSD. Alas.
Morality?
We will not fully work Ctrl-O in our wonderful console in Linux. Alas, never. And the rest was interesting.
... By the way, if you have a live server and it is alive, you can remotely see what's happening on consoles there - cat / dev / vcsa *. And special fans can watch and watch others work on consoles.