无法使用termios.TIOCSTI模拟终端输入

2024-05-12 23:22:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我看到的大多数code samples都试图在没有本地回显的情况下从stdin读取。为此,他们修改"local modes"标志以删除setting to "Echo input characters"。我想我可以将“input modes”标志修改为TIOCSTI,这是为了"Insert the given byte in the input queue."。但是,即使我以root用户身份运行脚本,它也没有任何效果。我写给fd的任何东西似乎都会进入终端输出,而不是终端输入。基本上我想做的是this exact thing,但是用纯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\n')
fd.close()

Tags: thein终端input标志localsettingprint
2条回答

我从@ulfizer那里得到了答案,并对其进行了扩展,使之成为一个完整且可用的应用程序。在

import sys
import fcntl
import termios
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('tty', type=argparse.FileType('w'),
                    help='full tty path as given by the tty command')
group = parser.add_mutually_exclusive_group()
group.add_argument('-n', action='store_true',
                   help='prevent sending a trailing newline character')
group.add_argument(' stdin', action='store_true',
                   help='read input from stdin')
group = parser.add_argument_group()
group.add_argument('cmd', nargs='?',
                    help='command to run (required if not using  stdin)')
group.add_argument('args', nargs='*',
                    help='arguments to command')
args = parser.parse_known_args()

if args.stdin:
    data = sys.stdin.read()
else:
    data = ' '.join([args.cmd] + args.args)

for c in data:
    fcntl.ioctl(args.tty, termios.TIOCSTI, c)
if not args.n and data[-1][-1] != '\n':
    fcntl.ioctl(args.tty, termios.TIOCSTI, '\n')

以下是如何使用它:

终端1:执行。。。在

^{pr2}$

终端2:执行。。。在

$ sudo python termfake.py $(cat /tmp/t1) date +%s

终端1:观察。。。在

$ tty > /tmp/t1
$ date +%s
1487276400

TIOCSTI是一个ioctl(在tty_ioctl(4)中有说明),不是一个终端设置,因此不能使用tcsetattr(),而是需要将伪输入的每个字符输入到ioctl()。以前从未从Python中执行ioctl,但以下操作似乎适用于在运行Bash的不同终端(指定为参数,例如/dev/pts/13)中运行ls

import fcntl
import sys
import termios

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

TIOCSTI需要根特权(或者CAP_SYS_ADMIN更具体,但在实践中通常是相同的),参见capabilities(7)。在

相关问题 更多 >