Bir tty içine bir dize koyarak bir komut oluşturma


15

Bunu yapmayı başardım

echo -n " komut "> / dev / tty1

Harfler belirir ve imleç hareket eder, ancak bunlar "hayalet" tir - vurursanız Enterhiçbir şey olmaz (stdin içinde değildir).

Düzenle:

Aşağıdaki ekran görüntüsünün ortasında, bunun kullanımını neden gördüğümü görüyorsunuz. (Kırmızı başlıklı satır, sarı başlıklı satırın hemen altında.) Şimdilik olduğu gibi, not metnini gerçekten "düzenlemiyorsunuz"; sizden sadece düzenlediğiniz notun metninin yerini alacak yeni bir metin yazmanız istenir. Böylece, sadece eski metni tty'ye yapıştırarak giderilebileceğini düşündüm: kullanıcı girerse, değişiklik yapılmaz. (Bu program Perl / MySQL'de, ancak genel bir çözüm istemenin "bunu Perl'de nasıl yapabilirim" den daha ilginç olacağını düşündüm.)

misal

Düzenleme 2:

İşte aşağıdaki C kodunu (tam olarak tasarlandığı gibi çalışır) ve yeni bir ekran görüntüsünü kullanan Perl kodu - umarım bu şüphenin ötesinde şeyleri netleştirir :) Tekrar, düzenlemenin yapıldığı ekran görüntüsünün ortasına bakın not metnine - bu sefer eski metin oradadır, örneğin sadece bir yazım hatasını düzeltmek istiyorsanız, not metninin tamamını yeniden yazmak zorunda kalmazsınız.

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


Eğer ilgilenirseniz bunu Python üzerinde Stack Overflow üzerinde yaptım. stackoverflow.com/a/29616465/117471
Bruno Bronosky

Sorun ifadeniz net değil. Sorun nedir?

Yanıtlar:


3

Az writevtönce hile yapan küçük bir C programı buldum . Kaynak kodu buradan alın . Derlemek için gccönce aşağıdaki satırları kaldırın:

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

Güncelleme . Komut şimdi konsol araçlarının bir parçasıdır , bu nedenle dağıtımınız konsol araçları yerine kbd kullanmıyorsa , bu durumda onu kaynaktan derleyebilirsiniz (çok daha yeni sürüm, değişiklik gerekmez).

Kullanımı:

sudo writevt /dev/ttyN command 

Bazı nedenlerden dolayı, iade göndermek için '\r'(veya '\x0D') yerine '\n'(veya '\x0A') kullanmanız gerektiğini unutmayın.


Bu işe yarıyor, ama sadece içerdiklerinden çok daha yanlış var. Ben kullanım fonksiyonu hendek, bir prognameve yapmak ve _birkaç fonksiyon çağrıları yorum vardımain()
Michael Mrozek

@MichaelMrozek _()İşlev genellikle kullanılan gettext işaretidir . Demo kod böyle basit bir parça için biraz abartılı gibi görünüyor ama sanırım acıyor.
jw013

Bağlantı yukarıdaki cevap bozuldu. writevt.c Burada başka bir tane buldum (at github.com/  grawity ) ; aslında aynı program gibi görünüyor.
G-Man, 'Monica'yı Yeniden

Benim için çalışmıyor - yalnızca komut yazdırır. Reasson ne olursa olsun resif olarak \ r veya \ n prinst rn; /
Antoniossss

10

Bir terminal iki şey olarak ikiye katlanır: bir giriş cihazı (klavye gibi) ve bir görüntüleme cihazı (monitör gibi). Terminalden okuduğunuzda, giriş cihazından gelenleri alırsınız. Terminale yazdığınızda veriler görüntüleme cihazına gider.

Bir terminale girişi zorlamanın genel bir yolu yoktur. Nadiren buna gerek yoktur. Terminal gerektiren bir programla etkileşime girmeniz gerekiyorsa, Expect veya Empty gibi özel bir terminal emülatörü veya Screen veya Tmux gibi programlanabilir bir terminal sarıcı kullanın . Bir ioctl ile Linux konsoluna girişi zorlayabilirsiniz . Xdotool veya xmacro gibi araçlarla girişi bir X11 terminal emülatörüne zorlayabilirsiniz .


Yayımımda bir düzenleme yaptı. Bir bak ve benim düşüncelerimi göreceksin.
Emanuel Berg

@EmanuelBerg Düzenlemenizi anlamak zor. Girişini etkileşimli olarak kullandığınız bir programa programlı olarak beslemeye mi çalışıyorsunuz? İstediğiniz buysa, programı screenveya içinde çalıştırın tmuxve stuff(screen) veya send-key(tmux) komutunu veya yapıştır arabellek özelliğini kullanın.
Gilles 'SO- kötü olmayı bırak'

Perl kodu dahil olmak üzere ikinci bir düzenleme yapıldı - C ikilisinin çağrılması var. Bilmiyorum ... çok basit olduğu gibi (sadece bir satır kod) - ( screenveya tmuxaraçlarıyla) yolunuzu yapmak gerçekten daha mı iyi ?
Emanuel Berg

@EmanuelBerg Evet, aradınız screen -X stuff 'note version one'.
Gilles 'SO- kötü olmayı bırak'

7

En azından Linux ve BSD'lerde TIOCSTI ioctl karakterleri terminal giriş arabelleğine geri iter (bir sınıra kadar [Linux'ta 4096 karakter]):

#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);
}

Derleyin ve şöyle deyin:

cmd foo bar < "$some_tty"

bazı tty karakterleri geri itmek için.

Ve perl'de:

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

Düzenleme : Şimdi writevt çözümü ile aynı ioctl farkında . TIOCSTI sadece VT'ler için değil, herhangi bir terminal için çalıştığından komutun açıklaması ve adı yanıltıcıdır.


Sorudaki ikinci düzenlememe göz atın. Zaten @htor'dan aldığım kodu derledim - görebildiğim kadarıyla harika çalışıyor. Bunun yerine bu kodu kullanmanın avantajlarını görebiliyor musunuz? (Ama her iki durumda da gösterdiğiniz çaba için teşekkürler.)
Emanuel Berg

Evet. Son düzenlememe bakın. Mesele TIOCSTI ioctl kullanmaktır. Verdiğim kod sadece 0 dosya tanımlayıcısında (stdin) bunu yapıyor.
Stéphane Chazelas

Artık herkesin TIOCSTI'si yok. Bu cevabın yazılmasından beş yıl sonra insanlar cevabı çekirdeklerden atmaya başladı. unix.stackexchange.com/q/406690/5132
JdeBP

3

Stack Overflow üzerinde daha eksiksiz bir demom var .

Python'da şunları yapabilirsiniz:

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)

Bu , OP tarafından belirtilen tty yolunun basit bir "command"değerini varsayar ls -lave kullanır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.