How does less know the terminal resolution?
If you're looking for a way to check from a script, you can do either of these:
- Run
tput cols
andtput lines
, as manatwork suggests - check the values of $LINES and $COLUMNS
But if you want the details, here we go:
For virtual terminals (xterm, et al) there is an ioctl()
system call that will tell you what size the window is. If it can, less
uses this call. Furthermore, when you change the size of the window, whatever's running in that window receives a SIGWINCH
signal that lets less
know that it should check for a new window size. For instance, I started a less
running (as process ID 16663), connected to it with strace
, and resized the window. This is what I saw:
$ strace -p 16663
Process 16663 attached - interrupt to quit
read(3, 0xbfb1f10f, 1) = ? ERESTARTSYS (To be restarted)
--- SIGWINCH (Window changed) @ 0 (0) ---
rt_sigaction(SIGWINCH, {0x805cf10, [WINCH], SA_RESTART}, {0x805cf10, [WINCH], SA_RESTART}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig -icanon -echo ...}) = 0
ioctl(1, TIOCGWINSZ, {ws_row=40, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(2, TIOCGWINSZ, {ws_row=40, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0
This is also what tput cols
and tput lines
do behind the scenes, if they can. For more info on this method, see man tty-ioctl
and search for TIOCGWINSZ.
For other terminals such as those connected to serial ports, though, there's no way to get this info directly. In that case, less
starts looking for clues in the environment variables.
LINES
andCOLUMNS
will often be set to the terminal dimensions. In fact, ifbash
orzsh
can find the terminal dimensions, it will automatically set these variables itself, to make it easy for not-so-clever programs to see the terminal size. However, most other shells, includingdash
andtcsh
, do not set these variables.TERM
is usually set to the terminal type, in which case the terminfo database may contain the expected size of the terminal. Iftput rows
cannot use the IOCTL (for instance, if you're connected over a serial port), it will fall back to the values recorded here. For a terminal whose size can change, this is only a guess and is likely to be wrong.
For more info, see man tput
for the command to control the terminal, and man terminfo
for a list of things you can tell the terminal to do.
If you take a look at the source code, you will know less
calls ioctl()
to retrieve the window size on Linux.
#ifdef TIOCGWINSZ
{
struct winsize w;
if (ioctl(2, TIOCGWINSZ, &w) == 0)
{
if (w.ws_row > 0)
sys_height = w.ws_row;
if (w.ws_col > 0)
sys_width = w.ws_col;
}
}
#else
#ifdef WIOCGETD
{
struct uwdata w;
if (ioctl(2, WIOCGETD, &w) == 0)
{
if (w.uw_height > 0)
sys_height = w.uw_height / w.uw_vs;
if (w.uw_width > 0)
sys_width = w.uw_width / w.uw_hs;
}
}
#endif