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


15

我设法做到了

echo -n“ 命令 ”> / dev / tty1

出现字母,并且光标移动,但是它们是“鬼”-如果您单击Enter,则什么也不会发生(它们不在stdin中)。

编辑:

在下面的屏幕截图的中间,您会看到为什么我会看到此用法。(带有红色标题的行,位于带有黄色标题的行的正下方。)到现在为止,您实际上并不是在“编辑”注释文本。只是要求您编写一个新文本,它将替换您(不是真的)正在编辑的笔记的文本。因此,我认为可以通过简单地将旧文本粘贴到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);

better_example


如果您感兴趣的话,我在Python Overstack Overflow上完成了此操作。stackoverflow.com/a/29616465/117471
Bruno Bronosky

您的问题陈述不清楚。问题是什么?

Answers:


3

我刚刚找到了一个叫做C的小程序writevt,可以解决问题。在此处获取源代码。要使其编译,gcc只需先删除以下几行:

#include <lct/cline.h>
#include <lct/utils.h>

更新。该命令现在是console-tools的一部分,因此可以在更新的系统中使用,除非您的发行版使用kbd而不是console-tools,在这种情况下,您可以从源代码进行编译(更新的版本,不需要进行任何修改)。

用法:

sudo writevt /dev/ttyN command 

请注意,由于某种原因,您必须使用'\r'(或'\x0D')而不是'\n'(或'\x0A')发送退货。


确实可以,但是有很多错误,而不仅仅是那些错误。我不得不放弃使用函数,并progname加上和_,并注释掉一些函数调用main()
Michael Mrozek

@MichaelMrozek该_()函数通常是使用gettext的标志。对于这样一个简单的演示代码来说,似乎有点过头了,但我想并没有受到伤害。
jw013

以上答案中的链接已断开。我在writevt.c 这里找到了另一个(在github.com/  grawity;它似乎本质上是相同的程序。
G-Man说'Resstate Monica''Oct

对我不起作用-仅打印命令。\ r或\ n负责任地重复任职; /
Antoniossss19年

10

终端可以兼作两件事:输入设备(例如键盘)和显示设备(例如监视器)。从终端上读取时,您会从输入设备获得信息。当您写入终端时,数据进入显示设备。

没有强迫终端输入的一般方法。几乎没有必要这样做。如果需要与需要终端的程序进行交互,请使用专用的终端仿真器(例如ExpectEmpty)或可编程的终端包装器(例如ScreenTmux)。您可以使用ioctl强制输入Linux控制台。您可以使用xdotoolxmacro之类的工具强制输入X11终端仿真器。


对我的帖子进行了编辑。看看,您会明白我的想法。
伊曼纽尔·伯格

@EmanuelBerg您的编辑很难理解。您是否正在尝试以编程方式将输入输入到您还以交互方式使用的程序中?如果您要这样做,请在screen或中运行程序,tmux然后使用其stuff(屏幕)或send-key(tmux)命令或粘贴缓冲区功能。
吉尔斯(Gillles)“所以-别再邪恶了”

使用Perl代码进行第二次编辑-在那里C二进制文件的调用。我不知道...因为它是如此简单(只需一行代码)-真的可以按自己的方式(使用screentmux工具)进行处理吗?
伊曼纽尔·伯格

@EmanuelBerg所以,您正在寻找screen -X stuff 'note version one'
吉尔斯(Gillles)“所以-别再邪恶了”

7

至少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;

编辑:我现在知道它是与writevt解决方案中相同的ioctl 。该命令的注释和命令名称具有误导性,因为TIOCSTI可用于任何终端,而不仅限于VT。


查看我对问题的第二次编辑。我已经编译了从@htor获得的代码-可以看到,它很棒。您可以使用此代码看到任何好处吗?(但感谢您在任何情况下的努力。)
Emanuel Berg 2012年

是。查看我最近的编辑。关键是要使用TIOCSTI ioctl。我提供的代码仅对文件描述符0(stdin)执行此操作。
斯特凡Chazelas

并不是每个人都拥有TIOCSTI。编写此答案的五年后,人们开始将其从内核中删除。 unix.stackexchange.com/q/406690/5132
JdeBP

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.