blob: 567086f09cd4f711255b9bea6143abda0e253d91
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" |
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(resize, BB_DIR_USR_BIN, BB_SUID_DROP)) |
27 | |
28 | //kbuild:lib-$(CONFIG_RESIZE) += resize.o |
29 | |
30 | //usage:#define resize_trivial_usage |
31 | //usage: "" |
32 | //usage:#define resize_full_usage "\n\n" |
33 | //usage: "Resize the screen" |
34 | |
35 | #include "libbb.h" |
36 | #include "common_bufsiz.h" |
37 | |
38 | #define ESC "\033" |
39 | |
40 | #define old_termios_p ((struct termios*)bb_common_bufsiz1) |
41 | #define INIT_G() do { setup_common_bufsiz(); } while (0) |
42 | |
43 | static void |
44 | onintr(int sig UNUSED_PARAM) |
45 | { |
46 | tcsetattr(STDERR_FILENO, TCSANOW, old_termios_p); |
47 | _exit(EXIT_FAILURE); |
48 | } |
49 | |
50 | int resize_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
51 | int resize_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) |
52 | { |
53 | struct termios new; |
54 | struct winsize w = { 0, 0, 0, 0 }; |
55 | int ret; |
56 | |
57 | INIT_G(); |
58 | |
59 | /* We use _stderr_ in order to make resize usable |
60 | * in shell backticks (those redirect stdout away from tty). |
61 | * NB: other versions of resize open "/dev/tty" |
62 | * and operate on it - should we do the same? |
63 | */ |
64 | |
65 | tcgetattr(STDERR_FILENO, old_termios_p); /* fiddle echo */ |
66 | memcpy(&new, old_termios_p, sizeof(new)); |
67 | new.c_cflag |= (CLOCAL | CREAD); |
68 | new.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); |
69 | bb_signals(0 |
70 | + (1 << SIGINT) |
71 | + (1 << SIGQUIT) |
72 | + (1 << SIGTERM) |
73 | + (1 << SIGALRM) |
74 | , onintr); |
75 | tcsetattr(STDERR_FILENO, TCSANOW, &new); |
76 | |
77 | /* save_cursor_pos 7 |
78 | * scroll_whole_screen [r |
79 | * put_cursor_waaaay_off [$x;$yH |
80 | * get_cursor_pos [6n |
81 | * restore_cursor_pos 8 |
82 | */ |
83 | fprintf(stderr, ESC"7" ESC"[r" ESC"[999;999H" ESC"[6n"); |
84 | alarm(3); /* Just in case terminal won't answer */ |
85 | //BUG: death by signal won't restore termios |
86 | scanf(ESC"[%hu;%huR", &w.ws_row, &w.ws_col); |
87 | fprintf(stderr, ESC"8"); |
88 | |
89 | /* BTW, other versions of resize recalculate w.ws_xpixel, ws.ws_ypixel |
90 | * by calculating character cell HxW from old values |
91 | * (gotten via TIOCGWINSZ) and recomputing *pixel values */ |
92 | ret = ioctl(STDERR_FILENO, TIOCSWINSZ, &w); |
93 | |
94 | tcsetattr(STDERR_FILENO, TCSANOW, old_termios_p); |
95 | |
96 | if (ENABLE_FEATURE_RESIZE_PRINT) |
97 | printf("COLUMNS=%d;LINES=%d;export COLUMNS LINES;\n", |
98 | w.ws_col, w.ws_row); |
99 | |
100 | return ret; |
101 | } |
102 |