Construire une command en mettant une string dans un tty

J'ai réussi à faire ça

  echo -n " command "> / dev / tty1 

Les lettres apparaissent et le slider se déplace, mais ce sont des "fantômes" – si vous appuyez sur Entrée , rien ne se passe (ils ne sont pas dans stdin).

Modifier:

Au milieu de la capture d'écran ci-dessous, vous voyez pourquoi je vois l'utilisation de cela. (La ligne avec une légende rouge, juste en dessous de la ligne avec une légende jaune.) Comme c'est le cas maintenant, vous n'êtes pas vraiment "éditer" le text de la note; vous êtes invité à écrire un nouveau text, qui replacea le text de la note que vous éditez (pas vraiment). Ainsi, j'ai pensé qu'il pourrait être remédié en collant simplement l'ancien text dans le tty: si l'user frappe input, aucune modification n'est faite. (Ce programme est en Perl / MySQL, mais j'ai pensé qu'il serait plus intéressant de requestr une solution générale que "comment faire en Perl".)

Exemple

Édition 2:

Voici le code Perl, qui utilise le code C ci-dessous (fonctionne exactement comme prévu), ainsi qu'une nouvelle capture d'écran – espérons que cela clarifiera les choses au-delà de tout doute 🙂 Encore une fois, regardez au milieu de la capture d'écran, où la modification est faite au text de la note – cette fois-ci, l'ancien text est là, par exemple si vous voulez juste corriger une faute de frappe, vous n'aurez pas à retaper la totalité du text de la note.

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

meilleur_exemple

Je viens de find un petit programme en C appelé writevt qui fait l'affaire. Prenez le code source ici . Pour le comstackr avec gcc supprimez d'abord les lignes suivantes:

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

Mise à jour . La command fait désormais partie de console-tools , donc disponible dans des systèmes plus récents, sauf si votre dissortingbution utilise kbd au lieu de console-tools , auquel cas vous pouvez le comstackr à partir de la source (version beaucoup plus récente, aucune modification nécessaire).

Usage:

 sudo writevt /dev/ttyN command 

Notez que, pour une raison quelconque, vous devez utiliser '\r' (ou '\x0D' ) au lieu de '\n' (ou '\x0A' ) pour envoyer un return.

Un terminal se double de deux choses: un périphérique d'input (comme un keyboard) et un périphérique d'affichage (tel qu'un moniteur). Lorsque vous lisez à partir du terminal, vous obtenez ce qui vient du périphérique d'input. Lorsque vous écrivez au terminal, datatables vont sur le périphérique d'affichage.

Il n'y a pas de moyen général de forcer l'input dans un terminal. Il est rarement nécessaire de le faire. Si vous avez besoin d'interagir avec un programme nécessitant un terminal, utilisez un émulateur de terminal dédié tel que Expect ou Empty , ou un wrapper de terminal programmable tel que Screen ou Tmux . Vous pouvez forcer la saisie dans une console Linux avec un ioctl . Vous pouvez forcer l'input dans un émulateur de terminal X11 avec des outils tels que xdotool ou xmacro .

Au less Linux et BSD ont le TIOCSTI ioctl pour repousser les caractères dans le buffer d'input du terminal (jusqu'à une limite de 4096 caractères sous 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); } 

Comstackz-le et appelez-le comme:

 cmd foo bar < "$some_tty" 

pour repousser des caractères sur un tty.

Et en perl:

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

Edit : Je réalise maintenant que c'est la même chose que dans la solution writevt . Le commentaire et le nom de la command sont trompeurs car TIOCSTI fonctionne pour n'importe quel terminal, pas seulement pour les VT.

J'ai une démo plus complète sur Stack Overflow .

En python, vous pouvez faire:

 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) 

C'est en supposant une simple valeur "command" de ls -la et en utilisant le path tty spécifié par OP.