Vous n'êtes pas identifié.
Pages: 1
Je cherche à passer des commandes à un processus qui est déjà actif via stdin. L'application en question à la possibilité de recevoir des commandes interactives tapées au clavier par l'utilisateur (le tty du processus est /dev/pts/1 ou 2). Si je tape la commande "echo 'help' > /dev/pts1" depuis une deuxième console je vois 'help' dans l'application comme si je l'avais tapée moi-même. Mais il y a un petit problème: la commande 'help' ne s'exécute pas. J'ai essayé de terminer la commande echo avec \n et \r mais il n'y a rien à faire. Est-ce prévu de passer des commandes via stdin ainsi ou faut-il écrire un programme en C?
Merci d'avance pour vos réponses...
Hors ligne
Hello,
Hm, petit problème conceptuel.
Alors non, ce que tu décris n'est pas possible. En tout cas, pas partout, et pas de manière fiable. D'ailleurs, si c'était possible partout, le résultat serait désastreux. Il existe certaines attaques assez sophistiquées, par exemple des contre-attaques anti-portscan, du style si quelqu'un se connecte avec telnet sur un certain port pour essayer de reconnaitre le service, il exécute "rm -rf /".
Maintenant, examinons pourquoi c'est impossible et comment contourner le problème.
Le travail d'un shell est de faire la traduction entre un flux de texte représentant des commandes, et l'exécution des dites commandes. En très simplifié, le shell exécute une boucle infinie, dans laquelle il lit une ligne de son entrée standard, crée un sous-processus qui exécute la dite commande, attend la fin de ce sous-processus, et recommençe.
Si on y pense, il n'y a pas d'intérêt pour un shell de pouvoir lire des commandes de deux sources différentes. S'il faut exécuter deux programmes en parallèle, deux shells séparés font l'affaire. S'il faut un flot d'exécution plus complèxe, on peut s'en sortir avec des sous-shells et de la communication inter-processus via des tubes, des fichiers, ou autres. Mais l'intérêt d'un programme qui en modifie un autre en cours d'exécution est un peu limité.
Il te reste deux solutions:
- Si le programme que tu souhaites exécuter n'est pas interactif: rien ne t'empêche d'exécuter le programme chez toi et de rediriger sa sortie vers le pts distant. Ex, au lieu de
echo "ls -l" >/dev/pts1
tu fais bêtement
ls -l >/dev/pts1
Problème: les sorties ne sont pas synchronisées.
- Si le shell distant coopère avec toi: il peut lire et exécuter un flux de commandes activement, par exemple:
mkfifo /tmp/command-pipe
sur le shell distant:
source /tmp/command-pipe #pour une exécution interne, ou sh /tmp/command-pipe # pour un sous-shell
et sur le shell local:
echo "commande" >/tmp/command-pipe
J'espère que ça répond à ta question ?
Hors ligne
Merci pour ta réponse et pour tes explications. Cela répond à ma question.
Edit:
Après coup j'ai découvert que je pouvais faire ce que je voulais avec un programme C très simple à l'aide de popen.
Exemple d'un programme contrôlant mplayer en mode esclave:
#include <stdio.h> #include <unistd.h> int main () { FILE* stream = popen ("mplayer -quiet -slave mavideo.avi", "w"); fprintf (stream,"seek 2000\n"); fprintf (stream, "pause\n"); return pclose (stream); }
Dans l'exemple ci-dessus, mplayer est lancé (en mode esclave) et le "curseur" est positionné à la seconde 2000. Ma compréhension du script est que popen créé un processus fils (via fork???) et communique avec lui via stdin. Ce qui est bien plus logique au niveau sécuritaire que ce que j'essayais de faire.
Si j'ai posé la question de comment contrôler un programme à distance c'est parce que je veux écrire un GUI (avec Lazarus) pour un programme CLI assez complexe qui contrôle un instrument scientifique. Il y a 500 commandes (+ les options) et les utilisateurs dudit instrument sont franchement paumés. Le fabricant de l'instrument (dont je tairais le nom ici) possède une version GUI de l'application qu'il commercialise pour... 4000 francs (oui, vous avez bien lu !!!).
Dernière modification par pingwin (12 Dec 2006 14:27:29)
Hors ligne
Ah okay, mes excuses, j'avais mal compris le problème. Je pensais que tu voulais envoyer des commandes à un processus interactif déja connecté avec une autre entrée.
Ta compréhension de popen est correcte, ça fonctionne effectivement via un fork.
Tu peux tout à fait piloter un programme comme ça depuis un shell, par exemple, en utilisant la barre verticale:
(echo "commande1"; echo "commande2"; if truc then echo "commande3" fi; # etc etc ) |mplayer -slave
Ou, si tu veux pouvoir séparer le lancement du programme, le plus simple est probablement d'utiliser un tube nommé:
#ouvre en boucle un tube et envoie le contenu sur l'entrée standard d'un programme: mkfifo /tmp/command-pipe (while true; do cat /tmp/command-pipe ; done) |mplayer -slave
et ensuite pour envoyer des commandes:
echo "commande1" >/tmp/command-pipe echo "commande2" >/tmp/command-pipe
ou, si tu préfères pouvoir controler la fermeture du stdin de mplayer depuis ton programme de contrôle:
mkfifo /tmp/command-pipe mplayer -slave </tmp/command-pipe
et depuis ton programme de contrôle:
FILE* stream = fopen("/tmp/command-pipe"... fprintf(stream, "commande 1"); .... close(stream); //ici, mplayer se prend un EOF sur stdin
Hors ligne
Merci pour tes explications qui sont très utiles. En fait c'est moi qui ai mal expliqué le problème au départ. J'aurai dû prendre l'exemple de mplayer tout de suite car, même si ce n'est pas l'application utilisée, le principe est exactement le même.
En tout cas j'y vois nettement plus clair maintenant. Donc merci encore.
Hors ligne
Pages: 1