无法使用termios.TIOCSTI伪造terminalinput

我见过的大部分代码示例都试图从stdin中读取本地回显。 要做到这一点,他们修改“本地模式”标志,以删除设置为“回声input字符” 。 我以为我可以修改TIOCSTI的“input模式”标志,即“将input队列中的给定字节插入”。 。 但是,即使我以root身份运行脚本,它也没有效果。 我写给fd的任何东西似乎都转到terminal输出,而不是terminalinput。 基本上我想要做的是这个确切的事情 ,但在纯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() 

Solutions Collecting From Web of "无法使用termios.TIOCSTI伪造terminalinput"

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需要root权限(或CAP_SYS_ADMIN更具体,但实际上通常是相同的),请参阅capabilities(7)

我从@Ulfalizer获得了答案,并将其扩展了一点,以成为一个完整且可用的应用程序。

 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:做…

 $ tty > /tmp/t1 

终端#2:做…

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

终端#1:观察…

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