Mailinglist Archive: opensuse-programming-de (124 mails)

< Previous Next >
Re: stdio von einem per system() gestartetem Prozess
  • From: Michael Matz <matz@xxxxxxx>
  • Date: Thu, 22 Aug 2002 14:53:22 +0200 (CEST)
  • Message-id: <Pine.LNX.4.33.0208221316150.1243-100000@xxxxxxxxxxxxx>
Hi,

On 22 Aug 2002, Volker Kroll wrote:

getpass() Funktion macht das z.B. von Haus aus. Wenn du sowas machen
willst (also direkt ans Terminal schreiben), musst du selber ein
pseudo-tty erstellen und mit stdin verbinden. expect(1) tut sowas (schau
dir die Funktion send_tty an)

Du meinst vermutlich in den Sourcen von expect?

Nicht direkt, nein. expect verarbeitet Skripte (in TCL), und eines der
builtins, die man in diesen benutzen kann, heisst send_tty. Siehe
expect(1).

, und IIRC gibt es auch perl-Module, die das
koennen. Es selber in C zu programmieren ist hoechst untrivial.

:-)) Schöne Formulierung
Wie würde man denn theoretisch vorgehen, wenn man es doch machen wollte?

Wenn man linux-Spezifisch bleibt (Ok, eigentlich BSD derived), dann schaue
man sich openpty(3) oder, wenn man gleich Subprozesse oeffnen will,
forkpty(3) an. Unten ist ein kleines Testprogramm, was ein pty Paar
oeffnet, forkt, das Slave-Pty mit den std{in,out,err} des Childs
verbindet, getpass() aufruft, und ein Passwort vom Parent zum Child
uebergibt.

Das Programm unten funktioniert manchmal nicht richtig (es sind
Synchronisationsprobleme, also timing abhaengig, so dass manchmal in dem
Child das Passwort zu frueh da ist, getpass() es nicht mehr mitbekommt,
und deshalb einfach wartet). Da muesste man also eigentlich was tun.

Wenn man generisch bleiben will, also nicht glibc2 (oder BSD) spezifisch,
dann schaue man sich intensiv z.B. sshpty.c von OpenSSH an, das auf ca.
500 Zeilen C aubreitet, wie man Pseudo-TTY's behandelt, Rechte darauf
korrekt setzt, und sowas. Oder einfach in ein beliebiges X-Terminal, der
das gleiche tun muss.

Muß ich dafür erst analysieren, was das Programm macht? lsof zeigt mir
an, daß /dev/tty als CHR offen ist. Muß ich jetzt ein umgebogenes stdin
und stdout an /dev/tty binden?

Nee, /dev/tty hat damit erstmal nichts zu tun. Es ist implizit das
controlling terminal des Prozesses. Um dieses aber zu aendern, muss man
ein pseudo-tty Paar oeffnen, und ein TIOCSCTTY ioctl drauf tun.


Ciao,
Micha.
--

#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pty.h>

int main()
{
int master, slave, pid;
pid = forkpty (&master, NULL, NULL, NULL);
if (pid < 0)
perror ("fork()");
if (pid)
{
char buf[80];
int r, len = 0;
write (master, "hallihallo\n", 11);
while (1)
{
r = waitpid (-1, NULL, WNOHANG);
if (r > 0 || (r < 0 && errno != EINTR))
break;
len = read (master, buf, 80);
if (len == 0 || (len < 0 && errno != EINTR))
break;
if (len > 0)
write (1, buf, len);
}
if (len > 0)
write (1, buf, len);
return r != pid;
}
else
{
char *p;
printf ("Hallo\n");
if (isatty (0))
printf ("Yeah, we have a terminal.\n");
else
printf ("Shit, we have something else.\n");
p = getpass ("A prompt: ");
printf ("password = %s\n", p?p:"<NIL>");
return 0;
}
}


< Previous Next >
References