| 665 | |
| 666 | |
| 667 | [=#console] |
| 668 | = Serial Console |
| 669 | |
| 670 | == Serial Console Window Size |
| 671 | console applications running inside Linux virtual terminal applications (xterm, rxvt etc) will receive SIGWINCH after a resize operation has taken place and adjust accordingly. |
| 672 | |
| 673 | When using a serial console there is no such mechanism and you can see the affect of this by connecting to a serial console (ie jtag_com/jtag_gang) and showing your size either via env vars or via the 'stty size' app: |
| 674 | {{{#!bash |
| 675 | ~# echo $LINES $COLUMNS |
| 676 | 24 80 |
| 677 | ~# stty size |
| 678 | 24 80 |
| 679 | }}} |
| 680 | |
| 681 | No matter how you resize that virtual terminal window (ie xterm), the above commands will always report the same size. |
| 682 | |
| 683 | It is possible for the application to actively ask for the current console window size so the second best thing is to do this every time a command prompt is printed by the shell. This can be achieved by sending a ANSI code to position the cursor to 999,999 then request the cursor position. |
| 684 | |
| 685 | The 'resize' app from the 'xterm' package does this, but here is also a cleaner version with less dependencies: |
| 686 | {{{#!bash |
| 687 | wget http://web.archive.org/web/20081224152013/http://www.davehylands.com/gumstix-wiki/resize/resize.c |
| 688 | gcc resize.c -o /usr/local/bin/resize |
| 689 | }}} |
| 690 | |
| 691 | You can also do this with shell scripts that do the same thing: |
| 692 | {{{#!bash |
| 693 | resize() { |
| 694 | old=$(stty -g) |
| 695 | stty raw -echo min 0 time 5 |
| 696 | printf '\0337\033[r\033[999;999H\033[6n\0338' > /dev/tty |
| 697 | IFS='[;R' read -r _ rows cols _ < /dev/tty |
| 698 | stty "$old" |
| 699 | #echo "size:${cols}x${rows}" |
| 700 | stty cols "$cols" rows "$rows" |
| 701 | } |
| 702 | }}} |
| 703 | |
| 704 | you could add this and the following to your /etc/bash.bashrc: |
| 705 | {{{#!bash |
| 706 | [[ "$(tty)" =~ "/dev/ttymxc" ]] && { resize; } |
| 707 | }}} |
| 708 | |
| 709 | some people also opt to use the 'trap' shell function to execute it on every command: |
| 710 | {{{#!bash |
| 711 | [[ "$(tty)" =~ "/dev/ttymxc" ]] && { trap resize DEBUG; } |
| 712 | }}} |
| 713 | |
| 714 | Notes: |
| 715 | - 'tty' shows the name of the terminal device (ie /dev/ttymxc1 if on a Ventana serial console) |
| 716 | - 'stty size' outputs the current terminal size based on what the kernel thinks |
| 717 | - this has nothing to do with terminal type (TERM) |
| 718 | - when remotely connected to a board via ssh for example, this isn't an issue as that can use SIGWINCH |
| 719 | orts 24 80 |
| 720 | - the COLUMNS and LINES env variables reflect the size of the tty |
| 721 | - resizable terminals are the result of NAWS 'Negotiate About Window Size' from RFC 1073 Telnet Window Size Option |
| 722 | |
| 723 | References: |
| 724 | - https://unix.stackexchange.com/questions/16578/resizable-serial-console-window |
| 725 | - http://web.archive.org/web/20081224152013/http://www.davehylands.com/gumstix-wiki/resize/resize.c |
| 726 | {{{#!c |
| 727 | /* resize.c */ |
| 728 | |
| 729 | #include <stdio.h> |
| 730 | #include <ctype.h> |
| 731 | #include <stdlib.h> |
| 732 | #include <unistd.h> |
| 733 | #include <sys/types.h> |
| 734 | #include <string.h> |
| 735 | #include <termio.h> |
| 736 | #include <termios.h> |
| 737 | |
| 738 | |
| 739 | #include <signal.h> |
| 740 | #include <pwd.h> |
| 741 | |
| 742 | #define ESC "\033" |
| 743 | |
| 744 | |
| 745 | #define TIMEOUT 10 |
| 746 | |
| 747 | |
| 748 | char *myname; |
| 749 | |
| 750 | char getsize[] = ESC "7" ESC "[r" ESC "[999;999H" ESC "[6n"; |
| 751 | char restore[] = ESC "8"; |
| 752 | |
| 753 | struct termios tioorig; |
| 754 | |
| 755 | char size[] = ESC "[%d;%dR"; |
| 756 | |
| 757 | int tty; |
| 758 | FILE *ttyfp; |
| 759 | |
| 760 | static void onintr (int sig); |
| 761 | static void resize_timeout (int sig); |
| 762 | static void Usage (void); |
| 763 | static void readstring (FILE *fp, char *buf, char *str); |
| 764 | |
| 765 | char * |
| 766 | x_basename(char *name) |
| 767 | { |
| 768 | char *cp; |
| 769 | |
| 770 | cp = strrchr(name, '/'); |
| 771 | return (cp ? cp + 1 : name); |
| 772 | } |
| 773 | |
| 774 | |
| 775 | /* |
| 776 | tells tty driver to reflect current screen size |
| 777 | */ |
| 778 | |
| 779 | int |
| 780 | main (int argc, char **argv) |
| 781 | { |
| 782 | |
| 783 | int rows, cols; |
| 784 | struct termios tio; |
| 785 | char buf[BUFSIZ]; |
| 786 | struct winsize ws; |
| 787 | char *name_of_tty; |
| 788 | |
| 789 | myname = x_basename(argv[0]); |
| 790 | |
| 791 | if (argc > 1) Usage(); |
| 792 | |
| 793 | name_of_tty = "/dev/tty"; |
| 794 | |
| 795 | if ((ttyfp = fopen (name_of_tty, "r+")) == NULL) { |
| 796 | fprintf (stderr, "%s: can't open terminal %s\n", |
| 797 | myname, name_of_tty); |
| 798 | exit (1); |
| 799 | } |
| 800 | tty = fileno(ttyfp); |
| 801 | |
| 802 | tcgetattr(tty, &tioorig); |
| 803 | tio = tioorig; |
| 804 | tio.c_iflag &= ~ICRNL; |
| 805 | tio.c_lflag &= ~(ICANON | ECHO); |
| 806 | tio.c_cflag |= CS8; |
| 807 | tio.c_cc[VMIN] = 6; |
| 808 | tio.c_cc[VTIME] = 1; |
| 809 | signal(SIGINT, onintr); |
| 810 | signal(SIGQUIT, onintr); |
| 811 | signal(SIGTERM, onintr); |
| 812 | tcsetattr(tty, TCSADRAIN, &tio); |
| 813 | |
| 814 | write(tty, getsize, strlen(getsize)); |
| 815 | readstring(ttyfp, buf, size); |
| 816 | if(sscanf (buf, size, &rows, &cols) != 2) { |
| 817 | fprintf(stderr, "%s: Can't get rows and columns\r\n", myname); |
| 818 | onintr(0); |
| 819 | } |
| 820 | write(tty, restore, strlen(restore)); |
| 821 | |
| 822 | if (ioctl (tty, TIOCGWINSZ, &ws) != -1) { |
| 823 | /* we don't have any way of directly finding out |
| 824 | the current height & width of the window in pixels. We try |
| 825 | our best by computing the font height and width from the "old" |
| 826 | struct winsize values, and multiplying by these ratios...*/ |
| 827 | if (ws.ws_col != 0) |
| 828 | ws.ws_xpixel = cols * (ws.ws_xpixel / ws.ws_col); |
| 829 | if (ws.ws_row != 0) |
| 830 | ws.ws_ypixel = rows * (ws.ws_ypixel / ws.ws_row); |
| 831 | ws.ws_row = rows; |
| 832 | ws.ws_col = cols; |
| 833 | ioctl (tty, TIOCSWINSZ, &ws); |
| 834 | } |
| 835 | |
| 836 | tcsetattr(tty, TCSADRAIN, &tioorig); |
| 837 | signal(SIGINT, SIG_DFL); |
| 838 | signal(SIGQUIT, SIG_DFL); |
| 839 | signal(SIGTERM, SIG_DFL); |
| 840 | |
| 841 | exit(0); |
| 842 | } |
| 843 | |
| 844 | |
| 845 | static void |
| 846 | readstring(register FILE *fp, register char *buf, char *str) |
| 847 | { |
| 848 | register int last, c; |
| 849 | |
| 850 | signal(SIGALRM, resize_timeout); |
| 851 | alarm (TIMEOUT); |
| 852 | if ((c = getc(fp)) == 0233) { /* meta-escape, CSI */ |
| 853 | *buf++ = c = ESC[0]; |
| 854 | *buf++ = '['; |
| 855 | } else { |
| 856 | *buf++ = c; |
| 857 | } |
| 858 | if(c != *str) { |
| 859 | fprintf(stderr, "%s: unknown character, exiting.\r\n", myname); |
| 860 | onintr(0); |
| 861 | } |
| 862 | last = str[strlen(str) - 1]; |
| 863 | while((*buf++ = getc(fp)) != last) |
| 864 | ; |
| 865 | alarm (0); |
| 866 | *buf = 0; |
| 867 | } |
| 868 | |
| 869 | static void |
| 870 | Usage(void) |
| 871 | { |
| 872 | fprintf(stderr, |
| 873 | "Usage: %s\n" |
| 874 | " sets size via ioctl\n", myname); |
| 875 | exit(1); |
| 876 | } |
| 877 | |
| 878 | static void |
| 879 | resize_timeout(int sig) |
| 880 | { |
| 881 | fprintf(stderr, "\n%s: timeout occurred\r\n", myname); |
| 882 | onintr(sig); |
| 883 | } |
| 884 | |
| 885 | /* ARGSUSED */ |
| 886 | static void |
| 887 | onintr(int sig) |
| 888 | { |
| 889 | tcsetattr (tty, TCSADRAIN, &tioorig); |
| 890 | exit(1); |
| 891 | } |
| 892 | |
| 893 | }}} |