LINES and COLUMNS environment magic

Ever wondered why you can read the $LINES and $COLUMNS environment variables from your text shell and have them seemingly aware (or indeed, actually aware) of the size of the graphical terminal in which that shell is running?

Enter SIGWINCH – a signal sent to processes when a window size changes. This signal causes a process to retrieve it’s current window size. For example in linux it is done though an ioctl call in termios.h:

Get and set window size
Window sizes are kept in the kernel, but not used by the kernel
(except in the case of virtual consoles, where the kernel will update
the window size when the size of the virtual console changes, for
example, by loading a new font).

The following constants and structure are defined in <sys/ioctl.h>.

TIOCGWINSZ struct winsize *argp
Get window size.

TIOCSWINSZ const struct winsize *argp
Set window size.

The struct used by these ioctls is defined as

struct winsize {

unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel; /* unused */
unsigned short ws_ypixel; /* unused */

};

When the window size changes, a SIGWINCH signal is sent to the fore‐
ground process group.

Where ws_row and ws_col are the current size of the window in rows ($LINES) and columns ($COLUMNS).

A proposal to standardise the way this is done has been made and apparently accepted – when this is adopted termios.h will also define tcgetwinsize() and tcsetwinsize() functions.

And as an amusing aside sometimes you can cause interesting effects such as to kill processes like apache and wsgi servers when you run them in the foreground and resize the terminal window as “Due to the lack of other signal numbers and given the fact that httpd normally runs detached from a terminal the SIGWINCH signal was chosen to instruct httpd to do a graceful shutdown.”

Leave a Reply

Your email address will not be published. Required fields are marked *