Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
513 views
in Technique[技术] by (71.8m points)

python - Unable to fake terminal input with termios.TIOCSTI

Most of the code samples I've seen are trying to read from stdin without local echo. To do this they modify the "local modes" flag to remove the setting to "Echo input characters". I thought I could just modify the "input modes" flag to TIOCSTI which is for "Insert the given byte in the input queue.". However, even though I run the script as root, it has no effect. anything I write to the fd seems to go to the terminal output, rather than the terminal input. Basically what I want to do is this exact thing, but in pure python.

"""
termfake.py

Usage: sudo python termfake.py /dev/ttys002

Get the tty device path of a different local termimal by running `tty`
in that terminal.
"""

import sys
import termios

fd = open(sys.argv[1], 'w')
fdno = fd.fileno()

# Returns [iflag, oflag, cflag, lflag, ispeed, ospeed, cc]
tatters = termios.tcgetattr(fdno)
print('original', tatters)
tatters[0] = termios.TIOCSTI
print('TIOCSTI', termios.TIOCSTI)

# Set iflag
termios.tcsetattr(fdno, termios.TCSANOW, tatters)

# Verify setting change
with open('/dev/ttys002', 'w') as fd2:
    print('modified', termios.tcgetattr(fd2.fileno()))

fd.write('This is test
')
fd.close()
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

TIOCSTI is an ioctl (documented in tty_ioctl(4)), not a terminal setting, so you can't use tcsetattr() -- you need to feed each character of the fake input to ioctl() instead. Never had to do ioctl's from Python before, but the following seems to work for running an ls in a different terminal (specified as the argument, e.g. /dev/pts/13) that's running Bash:

import fcntl
import sys
import termios

with open(sys.argv[1], 'w') as fd:
    for c in "ls
":
        fcntl.ioctl(fd, termios.TIOCSTI, c)

TIOCSTI requires root privileges (or CAP_SYS_ADMIN to be more specific, but that's usually the same in practice) by the way -- see capabilities(7).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...