#!/usr/bin/env python """ This tool uses pexpect to test expected Canonical mode length. All systems use the value of MAX_CANON which can be found using fpathconf(3) value PC_MAX_CANON -- with the exception of Linux and FreeBSD. Linux, though defining a value of 255, actually honors the value of 4096 from linux kernel include file tty.h definition N_TTY_BUF_SIZE. Linux also does not honor IMAXBEL. termios(3) states, "Linux does not implement this bit, and acts as if it is always set." Although these tests ensure it is enabled, this is a non-op for Linux. FreeBSD supports neither, and instead uses a fraction (1/5) of the tty speed which is always 9600. Therefor, the maximum limited input line length is 9600 / 5 = 1920. These tests only ensure the correctness of the behavior described by the sendline() docstring -- the values listed there, and above should be equal to the output of the given OS described, but no promises! """ # std import from __future__ import print_function import sys import os def detect_maxcanon(): import pexpect bashrc = os.path.join( # re-use pexpect/replwrap.py's bashrc file, os.path.dirname(__file__), os.path.pardir, 'pexpect', 'bashrc.sh') child = pexpect.spawn('bash', ['--rcfile', bashrc], echo=True, encoding='utf8', timeout=3) child.sendline(u'echo -n READY_; echo GO') child.expect_exact(u'READY_GO') child.sendline(u'stty icanon imaxbel erase ^H; echo -n retval: $?') child.expect_exact(u'retval: 0') child.sendline(u'echo -n GO_; echo AGAIN') child.expect_exact(u'GO_AGAIN') child.sendline(u'cat') child.delaybeforesend = 0 column, blocksize = 0, 64 ch_marker = u'_' print('auto-detecting MAX_CANON: ', end='') sys.stdout.flush() while True: child.send(ch_marker * blocksize) result = child.expect([ch_marker * blocksize, u'\a']) if result == 0: # entire block fit without emitting bel column += blocksize elif result == 1: # an '\a' was emitted, count the number of ch_markers # found since last blocksize, determining our MAX_CANON column += child.before.count(ch_marker) break print(column) if __name__ == '__main__': try: detect_maxcanon() except ImportError: # we'd like to use this with CI -- but until we integrate # with tox, we can't determine a period in testing when # the pexpect module has been installed print('warning: pexpect not in module path, MAX_CANON ' 'could not be determined by systems test.', file=sys.stderr)