Echo console to a device (and vice-versa)?

Francis Avila francisgavila at yahoo.com
Fri Oct 3 03:35:53 EDT 2003


This is not really a python question, but a posix question.  (If it's too
little of a python question to be OT, please let me know.)

I wanted a simple "bi-directional cat", i.e. something that passes stdin to
a device, and takes the device's output to stdout (Like 'screen
/dev/ttyS0'). I couldn't find a simple thing like this anywhere, so I
figured I would just write one.

However, I can't seem to get it to work: nothing is ever output or input on
either end (also, if run in emacs it hangs it until I can kill python--it's
eating stdin and stdout, I suspect).  I suspect I have a deep ignorance of
file descriptors, but I don't understand what it could be.  Might it also be
possible that the interpreter is somehow getting "in the way" of
stdin/stdout?  A C-c still sends KeyboardInterrupt, for example, so I know
python is still looking at stdin.

Here's the important code, which went through some revisions:


import os, sys
from errno import EAGAIN
import fcntl


usage = """usage: scat TTY-DEV"""

def main():
    try:
        ttyfn = sys.argv[1]
    except IndexError:
        print >> sys.stderr, usage
        return 1

    try:
        ttyfdout = os.open(ttyfn, os.O_RDONLY | os.O_NONBLOCK)
        ttyfdin  = os.open(ttyfn, os.O_WRONLY | os.O_NONBLOCK)
    except:
        print >> sys.stderr, usage
        print >> sys.stderr, "invalid filename " + ttyfn
        return 1

    if not os.isatty(ttyfdin):
        print >> sys.stderr, usage
        print >> sys.stderr, ttyfn + " is not a tty"
        return 1

    stdin  = sys.stdin.fileno()
    stdout = sys.stdout.fileno()

    # make the above non-blocking
    fcntl.fcntl(stdin,  fcntl.F_SETFL, os.O_NONBLOCK)
    fcntl.fcntl(stdout, fcntl.F_SETFL, os.O_NONBLOCK)

    while 1:
        #read tty, write to stdout
        try:
            ttybuf = os.read(ttyfdout, 1)
        except OSError, err:
            if err == EAGAIN:
                pass
        else:
            os.write(stdout, ttybuf)

        #read stdin, write to tty
        try:
            stdinbuf = os.read(stdin, 1)
        except OSError, err:
            if err == EAGAIN:
                pass
        else:
            os.write(ttyfdin, stdinbuf)


if __name__ == '__main__':
    main()

--
Francis Avila





More information about the Python-list mailing list