通过将字符串放入 tty 来构造命令

通过将字符串放入 tty 来构造命令

我设法做到了这一点

回显-n“命令> /dev/tty1

字母出现,光标移动,但它们是“幽灵”——如果你点击Enter,什么也不会发生(它们不在标准输入中)。

编辑:

在下面的屏幕截图中间,您会明白为什么我会看到它的用途。 (带有红色标题的行,位于带有黄色标题的行的正下方。)现在,您并没有真正“编辑”注释文本;而是在编辑注释文本。您只是被要求编写一个新文本,该文本将替换您正在(不是真正)编辑的注释文本。因此,我认为可以通过简单地将旧文本粘贴到 tty 中来解决这个问题:如果用户按回车键,则不会进行任何修改。 (这个程序是用 Perl/MySQL 编写的,但我认为询问通用解决方案比“我如何在 Perl 中执行此操作”更有趣。)

例子

编辑2:

这是 Perl 代码,它使用下面的 C 代码(完全按照预期工作),以及一个新的屏幕截图 - 希望这将澄清事实:)再次,查看屏幕截图的中间,即进行编辑的位置到注释文本 - 这一次,旧文本就在那里,例如,如果您只是想修复拼写错误,则不必重新输入整个注释文本。

my $edit_note_text = $edit_note_data[2];
print BOLD, RED, " new text: ", RESET;
system("writevt /dev/tty \"$edit_note_text\"");
my $new_text = <$in>;
$new_text = fix_input($new_text);
my $set_text = "UPDATE notes SET note = \"$new_text\" WHERE id = $edit_note_id";
$db->do($set_text);

更好的例子

答案1

终端兼作两个东西:输入设备(例如键盘)和显示设备(例如监视器)。当您从终端读取时,您会得到来自输入设备的内容。当您写入终端时,数据会显示到显示设备上。

没有强制输入到终端的通用方法。很少有必要这样做。如果您需要与需要终端的程序交互,请使用专用的终端模拟器,例如预计或者空的,或可编程终端包装器,例如屏幕或者多路复用器。您可以强制输入 Linux 控制台使用 ioctl。您可以使用以下工具强制输入 X11 终端模拟器xdo工具或者

答案2

至少 Linux 和 BSD 具有 TIOCSTI ioctl 将字符推回终端输入缓冲区(最多限制 [Linux 上为 4096 个字符]):

#include <sys/ioctl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>

void stackchar(char c)
{
  if (ioctl(0, TIOCSTI, &c) < 0) {
    perror("ioctl");
    exit(1);
  }
}
int main(int argc, char *argv[])
{
  int i, j;
  char c;

  for (i = 1; i < argc; i++) {
    if (i > 1) stackchar(' ');
    for (j=0; (c = argv[i][j]); j++) {
      stackchar(c);
    }
  }
  exit(0);
}

编译它,并将其命名为:

cmd foo bar < "$some_tty"

将字符推回到某些 tty 上。

在 Perl 中:

require "sys/ioctl.ph";
ioctl(STDIN, &TIOCSTI, $_) for split "", join " ", @ARGV;

编辑:我现在意识到它与中的 ioctl 相同写文件解决方案。命令的注释和名称具有误导性,因为 TIOCSTI 适用于任何终端,而不仅仅是 VT。

答案3

我有一个Stack Overflow 上有更完整的演示

在Python中你可以这样做:

import fcntl
import sys
import termios

with open('/dev/tty1', 'w') as fd:
    for char in "ls -la\n":
        fcntl.ioctl(fd, termios.TIOCSTI, char)

假设有一个简单的"command"ls -la并使用 OP 指定的 tty 路径。

答案4

编译写vt.cgcc writevt.c -o writevt

然后通过 发送命令./writevt /dev/ttyN 'ls -al^M'。 ^M 表示return char,通过输入 得到ctrl-v ctrl-m

名称管道和 screen/tmux 也是有效的方法,您可能会看到这里了解详情。

相关内容