Team BBL
Previous Page Next Page

18.12. Terminal Window Size

Most UNIX systems provide a way to keep track of the current terminal window size and to have the kernel notify the foreground process group when the size changes. The kernel maintains a winsize structure for every terminal and pseudo terminal:

   struct winsize {
     unsigned short ws_row;       /* rows, in characters */
     unsigned short ws_col;       /* columns, in characters */
     unsigned short ws_xpixel;    /* horizontal size, pixels (unused) */
     unsigned short ws_ypixel;    /* vertical size, pixels (unused) */
   };

The rules for this structure are as follows.

  • We can fetch the current value of this structure using an ioctl (Section 3.15) of TIOCGWINSZ.

  • We can store a new value of this structure in the kernel using an ioctl of TIOCSWINSZ. If this new value differs from the current value stored in the kernel, a SIGWINCH signal is sent to the foreground process group. (Note from Figure 10.1 that the default action for this signal is to be ignored.)

  • Other than storing the current value of the structure and generating a signal when the value changes, the kernel does nothing else with this structure. Interpreting the structure is entirely up to the application.

The reason for providing this feature is to notify applications (such as the vi editor) when the window size changes. When it receives the signal, the application can fetch the new size and redraw the screen.

Example

Figure 18.22 shows a program that prints the current window size and goes to sleep. Each time the window size changes, SIGWINCH is caught and the new size is printed. We have to terminate this program with a signal.

Running the program in Figure 18.22 on a windowed terminal gives us

$ ./a.out
35 rows, 80 columns       initial size
SIGWINCH received         change window size: signal is caught
40 rows, 123 columns
SIGWINCH received         and again
42 rows, 33 columns
^? $                      type the interrupt key to terminate

Figure 18.22. Print window size
#include "apue.h"
#include <termios.h>
#ifndef TIOCGWINSZ
#include <sys/ioctl.h>
#endif

static void
pr_winsize(int fd)
{
    struct winsize size;

    if (ioctl(fd, TIOCGWINSZ, (char *) &size) < 0)
        err_sys("TIOCGWINSZ error");
    printf("%d rows, %d columns\n", size.ws_row, size.ws_col);
}

static void
sig_winch(int signo)
{
    printf("SIGWINCH received\n");
    pr_winsize(STDIN_FILENO);
}

int
main(void)
{
    if (isatty(STDIN_FILENO) == 0)
        exit(1);
    if (signal(SIGWINCH, sig_winch) == SIG_ERR)
        err_sys("signal error");
    pr_winsize(STDIN_FILENO);   /* print initial size */
    for ( ; ; )                 /* and sleep forever */
        pause();
}

    Team BBL
    Previous Page Next Page