Package: util-linux Version: 2.28.1-1 Severity: wishlist
Hi! Please advise where to put the attached program. It fixes the problem when you connect to a serial console and your terminal size is not exactly 80x24. If the terminal driver's idea of terminal size doesn't match reality, there's nastiness that ranges from premature wrapping (horizontally and vertically) to screen corruption of full-screen programs, having to edit long commands in bash mostly blindly, etc. Thus, this program queries the terminal and stty-s the result. Alas, this cannot be done unconditionally as the thing attached to the other side of a serial console isn't always a terminal. Some might not support reporting cursor position (I made a timeout of 3 seconds), some expect-likes might be confused by unknown ANSI codes, some unconditionally blast commands (the first one would be partially eaten). Thus, my fix needs to be requested by the user. This thingy is way probably way too small for a separate package. As it fixes a deficiency of getty, it'd be nice to have it next to that. On the other hand, one shouldn't thoughtlessly bloat an essential package. Third option would be patching this into getty, enabled by a command-line switch.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <termios.h> #include <sys/ioctl.h> struct termios saved_attributes; int saved_fl; void tty_raw() { struct termios tattr; fcntl(0,F_GETFL,&saved_fl); tcgetattr(0, &saved_attributes); fcntl(0,F_SETFL,O_NONBLOCK); memcpy(&tattr,&saved_attributes,sizeof(struct termios)); tattr.c_lflag &= ~(ICANON|ECHO); tattr.c_cc[VMIN] = 1; tattr.c_cc[VTIME] = 0; tcsetattr(0, TCSAFLUSH, &tattr); } void tty_restore() { fcntl(0,F_SETFL,saved_fl); tcsetattr(0, TCSANOW, &saved_attributes); } int select_wait() { struct timeval tv; fd_set se; FD_ZERO(&se); FD_SET(0,&se); tv.tv_sec = 3; tv.tv_usec = 0; return select(1,&se,NULL,NULL,&tv); } int main(int argc, char **argv) { // as a side effect, the scrolling region is set to the entire screen static char *teststr = "\e7\e[r\e[999E\e[999C"; static char *cleanup = "\e8"; static char *getpos = "\033[6n"; char retstr[16]; int pos,rc,row,col; struct winsize ws; if (!isatty(0) || !isatty(1)) exit(2); tty_raw(); write(1,teststr,strlen(teststr)); write(1,getpos,strlen(getpos)); for (pos = 0; pos < sizeof(retstr)-1;) { if (0 == select_wait()) break; if (-1 == (rc = read(0,retstr+pos,sizeof(retstr)-1-pos))) { perror("read"); exit(2); } pos += rc; if (retstr[pos-1] == 'R') break; } retstr[pos] = 0; write(1,cleanup,strlen(cleanup)); tty_restore(); rc = sscanf(retstr,"\033[%d;%dR",&row,&col); printf("Terminal size: %dx%d\n", col, row); memset(&ws, 0, sizeof(struct winsize)); ioctl(1,TIOCGWINSZ,&ws); ws.ws_row=row; ws.ws_col=col; ioctl(1,TIOCSWINSZ,&ws); exit(0); }