Создайте команду, поместив строку в 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 поверх Stack Overflow, если вам интересно. stackoverflow.com/a/29616465/117471
Бруно Броноски

Ваша проблема не ясна. В чем проблема?

Ответы:


3

Я только что нашел небольшую C-программу под названием, writevtкоторая делает свое дело. Получить исходный код здесь . Для компиляции gccпросто удалите следующие строки:

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

Обновление . Команда теперь является частью консольных инструментов , поэтому доступна в более поздних системах, если в вашем дистрибутиве вместо консольных инструментов не используется kbd , и в этом случае вы можете скомпилировать ее из исходного кода. (гораздо более свежая версия, никаких изменений не требуется).

Использование:

sudo writevt /dev/ttyN command 

Обратите внимание, что по какой-то причине вы должны использовать '\r'(или '\x0D') вместо '\n'(или '\x0A') для отправки возврата.


Это работает, но есть гораздо больше ошибок, чем просто включает. Мне пришлось отказаться от использования функции, сделать prognameи _и закомментировать несколько вызовов функцийmain()
Майкл Мрозек

@MichaelMrozek _()Функция обычно является признаком использования gettext . Кажется, немного излишним для такого простого фрагмента демонстрационного кода, но я полагаю, это не повредит.
jw013

Ссылка в ответе выше сломана. Я нашел другой writevt.c здесь (на github.com/  grawity ) ; Похоже, это по сути та же самая программа.
G-Man говорит: «Восстановите Монику»

У меня не работает - только печатает команду. Отвечать на вопрос по любой причине; /
Антониосс

10

Терминал удваивается как две вещи: устройство ввода (например, клавиатура) и устройство отображения (например, монитор). Когда вы читаете с терминала, вы получаете то, что исходит от устройства ввода. Когда вы пишете в терминал, данные поступают на устройство отображения.

Не существует общего способа принудительного ввода данных в терминал. В этом нет необходимости. Если вам нужно взаимодействовать с программой, для которой требуется терминал, используйте специальный эмулятор терминала, такой как Expect или Empty , или программируемую оболочку терминала, такую ​​как Screen или Tmux . Вы можете принудительно ввести ввод в консоль Linux с помощью ioctl . Вы можете принудительно ввести ввод в эмулятор терминала X11 с помощью таких инструментов, как xdotool или xmacro .


Внес изменения в мой пост. Посмотрите, и вы увидите мое мышление.
Эмануэль Берг

@EmanuelBerg Ваше редактирование трудно понять. Вы пытаетесь программно вводить ввод в программу, которую вы также используете в интерактивном режиме? Если это то, что вы хотите, запустите программу в screenили tmuxи используйте их stuff(screen) или send-key(tmux) команду или их функцию вставки буфера.
Жиль "ТАК - перестать быть злым"

Произведено второе редактирование с включенным кодом Perl - здесь есть вызов двоичного кода C. Я не знаю ... как это было так просто (всего одна строка кода) - действительно ли лучше сделать это по-своему (с помощью инструментов screenили tmux)?
Эмануэль Берг

@EmanuelBerg Так что да, вы ищете screen -X stuff 'note version one'.
Жиль "ТАК - перестать быть злым"

7

По крайней мере, Linux и BSD имеют ioctl TIOCSTI для отправки символов обратно в буфер ввода терминала (до ограничения [4096 символов в Linux]):

#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, что и в решении writevt . Комментарий и название команды вводят в заблуждение, поскольку TIOCSTI работает для любого терминала, а не только для VT.


Проверьте мое второе редактирование на вопрос. Я уже скомпилировал код, полученный от @htor - что я вижу, он прекрасно работает. Можете ли вы увидеть какие-либо преимущества использования этого кода вместо этого? (Но спасибо за ваши усилия в любом случае.)
Эмануэль Берг

Да. Смотрите мое недавнее редактирование. Дело в том, чтобы использовать TIOCSTI ioctl. Код, который я дал, делает это в файловом дескрипторе 0 (stdin).
Стефан Шазелас

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.