13d222369SConrad Meyer /* 23d222369SConrad Meyer * resizewin 33d222369SConrad Meyer * 43d222369SConrad Meyer * Query terminal for size and inform the kernel 53d222369SConrad Meyer * 63d222369SConrad Meyer * Copyright 2015 EMC / Isilon Storage Division 73d222369SConrad Meyer * 83d222369SConrad Meyer * Redistribution and use in source and binary forms, with or without 93d222369SConrad Meyer * modification, are permitted provided that the following conditions 103d222369SConrad Meyer * are met: 113d222369SConrad Meyer * 1. Redistributions of source code must retain the above copyright 123d222369SConrad Meyer * notice, this list of conditions and the following disclaimer. 133d222369SConrad Meyer * 2. Redistributions in binary form must reproduce the above copyright 143d222369SConrad Meyer * notice, this list of conditions and the following disclaimer in the 153d222369SConrad Meyer * documentation and/or other materials provided with the distribution. 163d222369SConrad Meyer * 173d222369SConrad Meyer * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 183d222369SConrad Meyer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 193d222369SConrad Meyer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 203d222369SConrad Meyer * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 213d222369SConrad Meyer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 223d222369SConrad Meyer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 233d222369SConrad Meyer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 243d222369SConrad Meyer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 253d222369SConrad Meyer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 263d222369SConrad Meyer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 273d222369SConrad Meyer * SUCH DAMAGE. 283d222369SConrad Meyer */ 293d222369SConrad Meyer 303d222369SConrad Meyer #include <sys/cdefs.h> 313d222369SConrad Meyer __FBSDID("$FreeBSD$"); 323d222369SConrad Meyer #include <sys/ioctl.h> 333d222369SConrad Meyer #include <sys/time.h> 3446f44afbSEdward Tomasz Napierala #include <err.h> 353d222369SConrad Meyer #include <errno.h> 363d222369SConrad Meyer #include <fcntl.h> 373d222369SConrad Meyer #include <stdio.h> 383d222369SConrad Meyer #include <stdlib.h> 393d222369SConrad Meyer #include <strings.h> 403d222369SConrad Meyer #include <termios.h> 413d222369SConrad Meyer #include <unistd.h> 423d222369SConrad Meyer 433d222369SConrad Meyer /* screen doesn't support ESC[18t (return terminal size) so do it the hard way */ 443d222369SConrad Meyer static const char query[] = 453d222369SConrad Meyer "\0337" /* Save cursor position */ 463d222369SConrad Meyer "\033[r" /* Scroll whole screen */ 473d222369SConrad Meyer "\033[999;999H" /* Move cursor */ 483d222369SConrad Meyer "\033[6n" /* Get cursor position */ 493d222369SConrad Meyer "\0338"; /* Restore cursor position */ 50*f1504c0cSEdward Tomasz Napierala 51*f1504c0cSEdward Tomasz Napierala static void 52*f1504c0cSEdward Tomasz Napierala usage(void) 53*f1504c0cSEdward Tomasz Napierala { 54*f1504c0cSEdward Tomasz Napierala 55*f1504c0cSEdward Tomasz Napierala fprintf(stderr, "usage: resizewin [-z]\n"); 56*f1504c0cSEdward Tomasz Napierala exit(1); 57*f1504c0cSEdward Tomasz Napierala } 58*f1504c0cSEdward Tomasz Napierala 593d222369SConrad Meyer int 60*f1504c0cSEdward Tomasz Napierala main(int argc, char **argv) 613d222369SConrad Meyer { 623d222369SConrad Meyer struct termios old, new; 633d222369SConrad Meyer struct winsize w; 64*f1504c0cSEdward Tomasz Napierala int ret, fd, ch, cnt, error, zflag; 653d222369SConrad Meyer char data[20]; 663d222369SConrad Meyer struct timeval then, now; 673d222369SConrad Meyer 6831cf65bbSEdward Tomasz Napierala error = 0; 69*f1504c0cSEdward Tomasz Napierala zflag = 0; 70*f1504c0cSEdward Tomasz Napierala while ((ch = getopt(argc, argv, "z")) != -1) { 71*f1504c0cSEdward Tomasz Napierala switch (ch) { 72*f1504c0cSEdward Tomasz Napierala case 'z': 73*f1504c0cSEdward Tomasz Napierala zflag = 1; 74*f1504c0cSEdward Tomasz Napierala break; 75*f1504c0cSEdward Tomasz Napierala case '?': 76*f1504c0cSEdward Tomasz Napierala default: 77*f1504c0cSEdward Tomasz Napierala usage(); 78*f1504c0cSEdward Tomasz Napierala } 79*f1504c0cSEdward Tomasz Napierala } 80*f1504c0cSEdward Tomasz Napierala argc -= optind; 81*f1504c0cSEdward Tomasz Napierala if (argc != 0) 82*f1504c0cSEdward Tomasz Napierala usage(); 833d222369SConrad Meyer 843d222369SConrad Meyer if ((fd = open("/dev/tty", O_RDWR | O_NONBLOCK)) == -1) 853d222369SConrad Meyer exit(1); 863d222369SConrad Meyer 87*f1504c0cSEdward Tomasz Napierala if (zflag) { 88*f1504c0cSEdward Tomasz Napierala if (ioctl(fd, TIOCGWINSZ, &w) == -1) 89*f1504c0cSEdward Tomasz Napierala exit(1); 90*f1504c0cSEdward Tomasz Napierala if (w.ws_row != 0 && w.ws_col != 0) 91*f1504c0cSEdward Tomasz Napierala exit(0); 92*f1504c0cSEdward Tomasz Napierala } 93*f1504c0cSEdward Tomasz Napierala 943d222369SConrad Meyer /* Disable echo */ 953d222369SConrad Meyer if (tcgetattr(fd, &old) == -1) 963d222369SConrad Meyer exit(1); 973d222369SConrad Meyer 983d222369SConrad Meyer new = old; 993d222369SConrad Meyer new.c_cflag |= (CLOCAL | CREAD); 1003d222369SConrad Meyer new.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 1013d222369SConrad Meyer if (tcsetattr(fd, TCSANOW, &new) == -1) 1023d222369SConrad Meyer exit(1); 1033d222369SConrad Meyer 1047ffc8a54SEdward Tomasz Napierala /* Discard input received so far */ 105048fd859SEdward Tomasz Napierala error = tcflush(fd, TCIOFLUSH); 1067ffc8a54SEdward Tomasz Napierala if (error != 0) 107048fd859SEdward Tomasz Napierala warn("tcflush"); 1087ffc8a54SEdward Tomasz Napierala 1093d222369SConrad Meyer if (write(fd, query, sizeof(query)) != sizeof(query)) { 11031cf65bbSEdward Tomasz Napierala error = 1; 1113d222369SConrad Meyer goto out; 1123d222369SConrad Meyer } 1133d222369SConrad Meyer 1143d222369SConrad Meyer /* Read the response */ 1153d222369SConrad Meyer bzero(data, sizeof(data)); 1163d222369SConrad Meyer gettimeofday(&then, NULL); 1173d222369SConrad Meyer cnt = 0; 1183d222369SConrad Meyer while (1) { 1193d222369SConrad Meyer ret = read(fd, data + cnt, 1); 1203d222369SConrad Meyer 1213d222369SConrad Meyer if (ret == -1) { 1223d222369SConrad Meyer if (errno == EAGAIN) { 1233d222369SConrad Meyer gettimeofday(&now, NULL); 1243d222369SConrad Meyer timersub(&now, &then, &now); 1253d222369SConrad Meyer if (now.tv_sec >= 2) { 12646f44afbSEdward Tomasz Napierala warnx("timeout reading from terminal"); 12731cf65bbSEdward Tomasz Napierala error = 1; 1283d222369SConrad Meyer goto out; 1293d222369SConrad Meyer } 1303d222369SConrad Meyer 1313d222369SConrad Meyer usleep(20000); 1323d222369SConrad Meyer continue; 1333d222369SConrad Meyer } 13431cf65bbSEdward Tomasz Napierala error = 1; 1353d222369SConrad Meyer goto out; 1363d222369SConrad Meyer } 1373d222369SConrad Meyer if (data[cnt] == 'R') 1383d222369SConrad Meyer break; 1393d222369SConrad Meyer 1403d222369SConrad Meyer cnt++; 1413d222369SConrad Meyer if (cnt == sizeof(data) - 2) { 14246f44afbSEdward Tomasz Napierala warnx("response too long"); 14331cf65bbSEdward Tomasz Napierala error = 1; 1443d222369SConrad Meyer goto out; 1453d222369SConrad Meyer } 1463d222369SConrad Meyer } 1473d222369SConrad Meyer 1483d222369SConrad Meyer /* Parse */ 1493d222369SConrad Meyer if (sscanf(data, "\033[%hu;%huR", &w.ws_row, &w.ws_col) != 2) { 15031cf65bbSEdward Tomasz Napierala error = 1; 15146f44afbSEdward Tomasz Napierala warnx("unable to parse response"); 1523d222369SConrad Meyer goto out; 1533d222369SConrad Meyer } 1543d222369SConrad Meyer 1553d222369SConrad Meyer /* Finally, what we want */ 1563d222369SConrad Meyer if (ioctl(fd, TIOCSWINSZ, &w) == -1) 15731cf65bbSEdward Tomasz Napierala error = 1; 1583d222369SConrad Meyer out: 1593d222369SConrad Meyer /* Restore echo */ 1603d222369SConrad Meyer tcsetattr(fd, TCSANOW, &old); 1613d222369SConrad Meyer 1623d222369SConrad Meyer close(fd); 16331cf65bbSEdward Tomasz Napierala exit(error); 1643d222369SConrad Meyer } 165