python / subprocess / winch
While I was writing a Python tool to wrap C Gdb so I could fetch some info out of it automatically, I ran into the issue that it reads the terminal size (lines x columns) to adjust its output.
I wanted consistent machine readable output, so I enlarged the terminal size programmatically: now row based output would not get wrapped by Gdb.
Later I noticed that it would cease to use the terminal size — in fact,
use the default 80 columns — if I also redirected stderr
to a non-tty.
That left me with the terminal resize code which could be dropped again.
Here, for my own reference, Python terminal resize code. This simple python snippet starts an application of your choice from a 80x25 window.
import array, fcntl, termios, subprocess, sys
class WinchPopen(subprocess.Popen):
def __init__(self, lines, columns, *args, **kwargs):
self._winch_push(lines, columns)
super(WinchPopen, self).__init__(*args, **kwargs)
def wait(self):
super(WinchPopen, self).wait()
self._winch_pop()
def _winch_push(self, lines, columns):
fileno = sys.stdout.fileno()
# Store window size.
self.__stored_winsize = array.array('h', [0, 0, 0, 0])
fcntl.ioctl(fileno, termios.TIOCGWINSZ, self.__stored_winsize, True)
# Mangle window size.
buf = array.array('h', [lines, columns, 0, 0]) # struct winsize
for fileno in (sys.stdin.fileno(), sys.stdout.fileno(),
sys.stderr.fileno()):
fcntl.ioctl(fileno, termios.TIOCSWINSZ, buf)
def _winch_pop(self):
for fileno in (sys.stdin.fileno(), sys.stdout.fileno(),
sys.stderr.fileno()):
fcntl.ioctl(fileno, termios.TIOCSWINSZ,
self.__stored_winsize)
if __name__ == '__main__':
proc = WinchPopen(columns=80, lines=25, args=sys.argv[1:])
proc.wait() # don't forget to call this!
Example calls:
$ ls /dev
autofs cuse hidraw0 loop3 network_latency ram1 ram6 sda5 sr0 tty14 tty24 tty34 tty44 tty54 tty7 ttyS15 ttyS25 ttyS7 vcs4 vcsa7
block disk hidraw1 loop4 network_throughput ram10 ram7 sdb stderr tty15 tty25 tty35 tty45 tty55 tty8 ttyS16 ttyS26 ttyS8 vcs5 vga_arbiter
bsg dm-0 hidraw2 loop5 null ram11 ram8 sdb1 stdin tty16 tty26 tty36 tty46 tty56 tty9 ttyS17 ttyS27 ttyS9 vcs6 vhci
...
$ python smallwindow.py ls /dev
autofs loop6 rtc tty22 tty55 ttyS29
block loop7 rtc0 tty23 tty56 ttyS3
bsg loop-control sda tty24 tty57 ttyS30
...
$ python smallwindow.py vim 80x25.txt
...