F
Francis Avila
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()
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()