The days of 80 columns in a terminal are long gone. With wide screens and tabbed terminal emulators, I now often have terminals which are up to 150 or more columns wide. This can cause problems for applications which assume an 80 column terminal or are initialised with 80 columns and then are not ‘told’ that the terminal is wider.

If you’re using a terminal emulator over serial, then you can run into some annoying problems. For example, using a utility called picocom to open a serial terminal to some other system, which then presents a console with bash. Even if the terminal you started with was 150 columns wide, Bash wraps lines at 80 characters, which is annoying if you’re navigating around in a deep filesystem hierarchy.

So, the solution:

Before you start your picocom session, resize your terminal to the preferred width.

You can use the tput command to show you how many columns you’ve got if you’re interested:

elesueur@simple ~$ tput cols

Open picocom to your target:

elesueur@simple:~$ picocom -b 115200 /dev/ttyUSB2
picocom v1.4

port is        : /dev/ttyUSB2
flowcontrol    : none
baudrate is    : 115200
parity is      : none
databits are   : 8
escape is      : C-a
noinit is      : no
noreset is     : no
nolock is      : no
send_cmd is    : ascii_xfr -s -v -l10
receive_cmd is : rz -vv

Terminal ready

Ubuntu 10.10 elesueur-panda ttyO2

elesueur-panda login:

Login, and type stty -a

elesueur@elesueur-panda:~$ stty -a
speed 115200 baud; rows 0; columns 0; line = 0;

elesueur@elesueur-panda:~$ tput cols

elesueur@elesueur-panda:~$ echo $COLUMNS

Notice that Bash thinks the terminal is only 80 columns wide.

We could use stty or setterm to set our terminal width:

elesueur@elesueur-panda:~$ stty cols 143
elesueur@elesueur-panda:~$ stty -a
speed 115200 baud; rows 0; columns 143; line = 0;

But we still have the same problem. Bash needs to know that the terminfo data has been updated, and this is done with a simple command:

elesueur@elesueur-panda:~$ resize

An strace of resize shows that it firstly writes a string to /dev/tty to obtain the current window size, then does a TIOCSWINSZ ioctl on /dev/tty to set the current size of the terminal:

write(3, “\0337\33[r\33[999;999H\33[6n”, 19

read(3, “\33[57;143R”, 4096)            = 9

ioctl(3, TIOCGWINSZ, {ws_row=0, ws_col=0, ws_xpixel=0, ws_ypixel=0}) = 0
ioctl(3, TIOCSWINSZ, {ws_row=57, ws_col=143, ws_xpixel=0, ws_ypixel=0}) = 0
— SIGWINCH (Window changed) @ 0 (0) —

Then immediately after it does the TIOCSWINSZ, it sends a SIGWINCH to Bash, which tells Bash that the window size has changed.

You don’t actually need to manually set the width with stty, resize figures the details out for you.

I don’t know why Bash can’t figure out the correct width when first started. Never-the-less, resize works well, and you could stick it in your .bashrc.

Post a Comment