busybox/console-tools/resize.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * resize - set terminal width and height.
   4 *
   5 * Copyright 2006 Bernhard Reutner-Fischer
   6 *
   7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
   8 */
   9//config:config RESIZE
  10//config:       bool "resize (903 bytes)"
  11//config:       default y
  12//config:       help
  13//config:       This program is used to (re)set the width and height of your current
  14//config:       terminal.
  15//config:
  16//config:config FEATURE_RESIZE_PRINT
  17//config:       bool "Print environment variables"
  18//config:       default y
  19//config:       depends on RESIZE
  20//config:       help
  21//config:       Prints the newly set size (number of columns and rows) of
  22//config:       the terminal.
  23//config:       E.g.:
  24//config:       COLUMNS=80;LINES=44;export COLUMNS LINES;
  25
  26//applet:IF_RESIZE(APPLET_NOEXEC(resize, resize, BB_DIR_USR_BIN, BB_SUID_DROP, resize))
  27/* bb_common_bufsiz1 usage here is safe wrt NOEXEC: not expecting it to be zeroed. */
  28
  29//kbuild:lib-$(CONFIG_RESIZE) += resize.o
  30
  31//usage:#define resize_trivial_usage
  32//usage:       ""
  33//usage:#define resize_full_usage "\n\n"
  34//usage:       "Resize the screen"
  35
  36#include "libbb.h"
  37#include "common_bufsiz.h"
  38
  39#define ESC "\033"
  40
  41#define old_termios_p ((struct termios*)bb_common_bufsiz1)
  42#define INIT_G() do { setup_common_bufsiz(); } while (0)
  43
  44static void
  45onintr(int sig UNUSED_PARAM)
  46{
  47        tcsetattr(STDERR_FILENO, TCSANOW, old_termios_p);
  48        _exit(EXIT_FAILURE);
  49}
  50
  51int resize_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  52int resize_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
  53{
  54        struct termios new;
  55        struct winsize w = { 0, 0, 0, 0 };
  56        int ret;
  57
  58        INIT_G();
  59
  60        /* We use _stderr_ in order to make resize usable
  61         * in shell backticks (those redirect stdout away from tty).
  62         * NB: other versions of resize open "/dev/tty"
  63         * and operate on it - should we do the same?
  64         */
  65
  66        tcgetattr(STDERR_FILENO, old_termios_p); /* fiddle echo */
  67//TODO: die if the above fails?
  68        memcpy(&new, old_termios_p, sizeof(new));
  69        new.c_cflag |= (CLOCAL | CREAD);
  70        new.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
  71        bb_signals(0
  72                + (1 << SIGINT)
  73                + (1 << SIGQUIT)
  74                + (1 << SIGTERM)
  75                + (1 << SIGALRM)
  76                , onintr);
  77        /* Users report:
  78         *      The resize command messes up the terminal.
  79         *      In my case it looks like it is hanging and
  80         *      I need to press ctrl-c to get a prompt.
  81         *      Actually the program does not hang but just
  82         *      the terminal is messed up.
  83         * Replaced TCSANOW with TCSAFLUSH:
  84         * "the change occurs after all output written to fd
  85         * has been transmitted, and all input that has been
  86         * received but not read will be discarded before
  87         * the change is made.
  88         */
  89        tcsetattr(STDERR_FILENO, TCSAFLUSH, &new);
  90
  91        /* save_cursor_pos 7
  92         * scroll_whole_screen [r
  93         * put_cursor_waaaay_off [$x;$yH
  94         * get_cursor_pos [6n
  95         * restore_cursor_pos 8
  96         */
  97        fprintf(stderr, ESC"7" ESC"[r" ESC"[999;999H" ESC"[6n");
  98        alarm(3); /* Just in case terminal won't answer */
  99//BUG: death by signal won't restore termios
 100        scanf(ESC"[%hu;%huR", &w.ws_row, &w.ws_col);
 101        fprintf(stderr, ESC"8");
 102
 103        /* BTW, other versions of resize recalculate w.ws_xpixel, ws.ws_ypixel
 104         * by calculating character cell HxW from old values
 105         * (gotten via TIOCGWINSZ) and recomputing *pixel values */
 106        ret = ioctl(STDERR_FILENO, TIOCSWINSZ, &w);
 107
 108        tcsetattr(STDERR_FILENO, TCSANOW, old_termios_p);
 109
 110        if (ENABLE_FEATURE_RESIZE_PRINT)
 111                printf("COLUMNS=%d;LINES=%d;export COLUMNS LINES;\n",
 112                        w.ws_col, w.ws_row);
 113
 114        return ret;
 115}
 116