perl/gtk stdin auf Entry umleiten

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
davewood
Beiträge: 92
Registriert: 08.10.2003 16:38:11

perl/gtk stdin auf Entry umleiten

Beitrag von davewood » 27.02.2007 11:28:23

Versuchs nun schon seit ein paar Stunden aber komm nicht weiter.

Mein Perl Skript erzeugt ein Fenster mit User/PW Eingabefeldern.

Dann gibts nen "Connect" Button, wenn der gedrückt wird soll per sshfs ein Verzeichnis gemountet werden.

sshfs user@host:/verzeichnis /mnt/verzeichnis
Usernamen und Password hab ich in den Variablen $usr und $pw gespeichert.
Nach dem Aufruf von sshfs fragt er in der Shell nach dem PW, ich will aber aus dem Perl Skript das PW übergeben.
Auch die PW Eingabeaufforderung will ich im Shell Skript verarbeiten. Hab mich ein wenig mit IPC::Open2 gespielt aber das will nicht so wie ich will. >> http://search.cpan.org/~nwclark/perl-5. ... C/Open2.pm

Kann wer helfen? :)

danke

david

Code: Alles auswählen

!/usr/bin/perl -w

use strict;
use Glib qw/TRUE FALSE/;
use Gtk2;
use IPC::Open2;

my $window;
my $frame;
my $box;
my $hbox_usr;
my $hbox_pw;
my $hbox_btn;
my $label_usr;
my $label_pw;
my $entry_usr;
my $entry_pw;
my $btn_connect;
my $btn_exit;
my $info;

Gtk2->init();

sub connect() {
        my ($widget, $window) = @_;
        [b]my $usr = $entry_usr->get_text();
        my $pw = $entry_pw->get_text();
        my $pid = open2(\*CHLD_OUT, \*CHLD_IN, "sshfs $usr\@nfsserver.g2:/g2/bildarchiv /mnt/global2000/bildarchiv");
        while (<CHLD_OUT>) {
                $info->get_buffer()->insert_at_cursor("$_");
        }
        print CHLD_IN "$pw";[/b]
}

#delete event occurred
sub delete_event() {
        return FALSE;
}
#create main window
$window = Gtk2::Window->new('toplevel');
$window->set_title("Connect");
$window->signal_connect(delete_event => \&delete_event);
$window->signal_connect(destroy => sub { Gtk2->main_quit(); });

# create containers
$frame = Gtk2::Frame->new ("Mount");
$frame->set_border_width(4);
$box = Gtk2::VBox->new();
$hbox_usr = Gtk2::HBox->new();
$hbox_pw = Gtk2::HBox->new();
$hbox_btn = Gtk2::HBox->new();
$hbox_btn->set_homogeneous(TRUE);

# create connect button
$btn_connect = Gtk2::Button->new_from_stock('gtk-ok');
$btn_connect->signal_connect(clicked => \&connect, $window);
# create exit button
$btn_exit = Gtk2::Button->new_from_stock('gtk-cancel');
$btn_exit->signal_connect(clicked => sub { Gtk2->main_quit(); });

# create labels
$label_usr = Gtk2::Label->new("Username");
$label_pw = Gtk2::Label->new("Password");

# create textfields
$entry_usr = Gtk2::Entry->new();
$entry_pw = Gtk2::Entry->new();
$entry_pw->set_visibility(FALSE);
$info = Gtk2::TextView->new();
$info->set_editable(FALSE);
$info->set_border_width(2);

# add widgets to main window
$hbox_usr->pack_start($label_usr, TRUE, TRUE, 5);
$hbox_usr->pack_start($entry_usr, FALSE, TRUE, 5);
$hbox_pw->pack_start($label_pw, TRUE, TRUE, 5);
$hbox_pw->pack_start($entry_pw, FALSE, TRUE, 5);
$hbox_btn->pack_start($btn_connect, FALSE, TRUE, 5);
$hbox_btn->pack_start($btn_exit, FALSE, TRUE, 5);
$box->add($hbox_usr);
$box->add($hbox_pw);
$box->add($hbox_btn);
$box->add($info);
$frame->add($box);
$window->add($frame);

# show all widgets
$window->show_all();

# start Gtk2 main event loop
Gtk2->main();

exit 0;


  


nepos
Beiträge: 5238
Registriert: 05.01.2005 10:08:12

Beitrag von nepos » 27.02.2007 13:09:28

Ich weiß nicht, ob es dir direkt hilft, aber für solche Fälle könntest du das Expect-Modul zum Einsatz bringen, das genau für solche Fälle gedacht ist.

davewood
Beiträge: 92
Registriert: 08.10.2003 16:38:11

Beitrag von davewood » 27.02.2007 13:24:38

Es würde vermutlich gehen aber
Expect Doku hat geschrieben:As a rule of thumb, Expect is useful for automating things that expect to talk to a human, where no formal standard applies.
und darum halte ich den Einsatz von Expect für einen sehr hässlichen workaround.

Muss doch irgendwie gehen den Ausgabestream des sshfs Befehls abzufangen (direkt umlenken, whatever) und dann ein $var auf den sshfs Inputstream auszugeben.

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 27.02.2007 13:49:55

die standard ssh Kommandos sollten die Environmentvariable SSH-ASKPASS abfragen
probier einmal ob sshfs dies auch tut (das Paket "ssh-askpass" sollte aber vorher installiert sein):

Code: Alles auswählen

 SSH_ASKPASS=/usr/bin/ssh-askpass sshfs $usr\@nfsserver.g2:/g2/bildarchiv /mnt/global2000/bildarchiv
/usr/bin/ssh-askpass kannst du über update-alternatives konfigurieren

Gruß
gms

davewood
Beiträge: 92
Registriert: 08.10.2003 16:38:11

Beitrag von davewood » 27.02.2007 14:21:49

ssh-askpass braucht die gnome libs, sowas is mir schonmal unsympathisch weil das skript auf verschiedenen Rechnern eingesetzt werden soll und nicht ueberall Gnome (bzw die libs) existiert.

Abgesehen davon ist das soweit ichs verstanden hab auch nicht das was ich such.

Ich will nicht undankbar erschein weil ich immer gleich sag "Na, des is ned" aber folgendes geht mir einfach nicht ein.

sshfs kommuniziert mit dem user ueber streams, mein skript muss doch diese streams einfach verwenden können oder?

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 27.02.2007 14:33:57

davewood hat geschrieben:ssh-askpass braucht die gnome libs
sicher ?
davewood hat geschrieben: Ich will nicht undankbar erschein weil ich immer gleich sag "Na, des is ned" aber folgendes geht mir einfach nicht ein.
kein Problem, die endgültige Lösung sollte ja deinen Wünschen entsprechen
davewood hat geschrieben:sshfs kommuniziert mit dem user ueber streams, mein skript muss doch diese streams einfach verwenden können oder?
sshfs habe ich noch nie verwendet, aber wenn es sich ähnlich verhält wie der standard ssh-Client, sollte es über "/dev/tty" direkt kommunizieren

Gruß
gms

davewood
Beiträge: 92
Registriert: 08.10.2003 16:38:11

Beitrag von davewood » 01.03.2007 11:14:15

Hab mich jetzt zwar in ssh key authentication eingelesen aber komme zu dem entschluss dass das nicht für mich geeignet ist..

Darum zurück zum Start.

Wenn ich ein Programm aus einem perl skript starte, dann wird ja auch dieses die 3 file handles STDIN, STDOUT und STDERR haben.
Und genau die will ich verwenden können


(1)ich führe sshfs aus
(2)warte auf einen output vom STDOUT
(3)dann printe ich das PW auf den STDIN file handle


Und mehr will ich wirklich nicht machen, versprochen! Vielleicht hat ja ein Perl crack ein code sample für mich.

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 01.03.2007 11:26:21

davewood hat geschrieben:Wenn ich ein Programm aus einem perl skript starte, dann wird ja auch dieses die 3 file handles STDIN, STDOUT und STDERR haben.
Und genau die will ich verwenden können
.
diese file handles kannst du ja auch verwenden, nur nicht für die Passworteingabe. Das Passwort wird, wie ich oben schon sagte, direkt über /dev/tty und niemals über /dev/stdin gelesen

davewood
Beiträge: 92
Registriert: 08.10.2003 16:38:11

Beitrag von davewood » 01.03.2007 11:47:09

stimmt, das hast du bereits gesagt. mea culpa.

ist /dev/tty immer genau das terminal des aktuellen prozesses?

hab mich ein wenig rumgespielt damit und es erweckt mir den anschein.

Die eigentliche Frage lautet ob ich wenn ich in meinem perl skript /dev/tty zum schreiben öffne immer am richtigen lande.

Die PW Abfrage (also die aufforderung das pw einzugeben) gibt er, scheinbar, auch auf tty aus und nicht stdout.

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 01.03.2007 11:55:45

davewood hat geschrieben:Die PW Abfrage (also die aufforderung das pw einzugeben) gibt er, scheinbar, auch auf tty aus und nicht stdout.
ja, er öffnet /dev/tty und verwendet diesen handle sowohl für die Aufforderung zur PW Eingabe, als auch zum Lesen des Passworts.
Ich habe mich jetzt ein bißchen umgeschaut, wenn du das Perlmodul IO::Pty verwendest, und damit ein "pty" öffnest, müßtest du darüber das Passwort eingeben könne.
Im Prinzip kannst du dann aber auch gleich das Expect.pm Modul verwenden http://search.cpan.org/~rgiersig/Expect-1.20/Expect.pod

Gruß
gms

davewood
Beiträge: 92
Registriert: 08.10.2003 16:38:11

Beitrag von davewood » 19.03.2007 13:02:40

Ich schreib jetzt mal wie es nicht geht, vielleicht will ja jemand erklären wieso das nicht funktioniert, in der Zwischenzeit versuch ich mich an IO::PTY

Code: Alles auswählen

open (TTY, "</dev/tty") or die $!;
system("ssh david\@airbus");
while (<TTY>) {
   $info->get_buffer()->insert_at_cursor("$_");
}

davewood
Beiträge: 92
Registriert: 08.10.2003 16:38:11

Beitrag von davewood » 20.03.2007 09:26:45

Description:
I have an application that i'm executing with in perl with the system("cmd &") call. For some reason it is requiring it have STDIN. I have closed all STDIN, STDOUT STDERR fd's and tried the POSIX setsid(). All with no luck. Is there anyway in perl I can switch the tty with posix functions and (or) fool the application into a another non-used tty?
Answer: Changing tty's in perl contributed by kjherron

The posix way to obtain a new controlling tty is to first get rid of the old one, as you've outlined, and then open a new one; the first one opened becomes the new controlling tty. You can't use "/dev/tty" for this purpose of course, you'd have to open a real tty device. These are /dev/pty*, /dev/console, and devices corresponding to actual serial ports.

Is the program insisting on a tty, or just a valid stdin? Instead of just closing stdin/stdout/stderr you can try opening them to /dev/null, and see if that is sufficient. If it needs a tty, one can often use /dev/console.
Nicht dass das die Lösung wäre, aber ich sammle clues :)

davewood
Beiträge: 92
Registriert: 08.10.2003 16:38:11

Beitrag von davewood » 22.03.2007 14:20:04

Hab den ganzen gestrigen Tag mit Expect rumgespielt aber auch keinen Erfolg gehabt.

Code: Alles auswählen

#!/usr/bin/perl -w
use strict;
use warnings;
use Expect;

# command and parameters to execute
my $command = "sshfs";
my @params = ("user\@server:/home/user", "~/remote_home");

# data to be sent by expect
my $password = "********";

# spawn a new command
my $exp=new Expect();
$exp->debug(3); # 0,1,2,3
$exp->spawn($command, @params) || die "Error: Cannot spawn process. $!\n";

# wait for the password prompt
$exp->expect(5,-re=>'assword:') or die "No password prompt\n";
#print("\nError: " . $exp->error() . "\n");

# send password
$exp->send("$password\n");

$exp->soft_close();

exit(0);
Leider funktioniert das nicht

Debug Output

Code: Alles auswählen

localuser@vigo:~/perl$ ./expect.pl
Spawned 'sshfs user@server:/home/user /home/localuser/home'
        spawn id(3)
        Pid: 8937
        Tty: /dev/pts/1
 at /usr/share/perl5/Expect.pm line 164
        Expect::spawn('Expect=GLOB(0x8345394)', 'sshfs', 'user@server:/home/user', '/home/localuser/home') called at ./expect.pl line 17
Starting EXPECT pattern matching...
 at /usr/share/perl5/Expect.pm line 533
        Expect::expect('Expect=GLOB(0x8345394)', 5, '-re', 'assword:') called at ./expect.pl line 26
user@server's password: Closing spawn id(3).
 at /usr/share/perl5/Expect.pm line 1311
        Expect::soft_close('Expect=GLOB(0x8345394)') called at ./expect.pl line 32

Got EOF from spawn id(3).
spawn id(3) closed.
Pid 8937 of spawn id(3) exited, Status: 0x00
Closing spawn id(3).
 at /usr/share/perl5/Expect.pm line 1388
        Expect::hard_close('Expect=GLOB(0x8345394)') called at /usr/share/perl5/Expect.pm line 1578
        Expect::DESTROY('Expect=GLOB(0x8345394)') called at ./expect.pl line 0
        eval {...} called at ./expect.pl line 0
localuser@vigo:~/perl$

roli
Beiträge: 3174
Registriert: 10.09.2003 17:39:58

Beitrag von roli » 22.03.2007 15:03:35

Hi,

unter http://nopaste.debianforum.de/5480 kannst du ein Perl-Script finden, mit dem ich den Login auf verschiedenen Rechnern automatisiert habe, vielleicht hilfts dir. Die dazugehörige „Passwortdatei“ sieht wie folgt aus:

Code: Alles auswählen

#host user password tool
127.0.0.1 foo bar /usr/bin/telnet
example.com kaese mumpitz /usr/bin/ssh[/url]
So geht's jedenfalls bei mir
Roland


"Aber wenn du schon so unwissend bist, davon noch nicht gehört zu haben,
so will ich es doch als gut ansehen, daß du lieber einmal töricht fragst,
als weiterhin nichts von etwas zu wissen, das man doch wissen sollte."
aus "Die Edda des Snorri Sturluson", "Gylfis Täuschung"

davewood
Beiträge: 92
Registriert: 08.10.2003 16:38:11

Beitrag von davewood » 23.03.2007 12:03:00

naja, mit ssh funktioniert mein snipplet ja auch, aber mit sshfs nicht.

Danke fuer deinen Tipp

gms
Beiträge: 7798
Registriert: 26.11.2004 20:08:38
Lizenz eigener Beiträge: MIT Lizenz

Beitrag von gms » 23.03.2007 12:09:54

davewood hat geschrieben:naja, mit ssh funktioniert mein snipplet ja auch, aber mit sshfs nicht.
mit "scp" funktioniert dein Script bei mir aber auch nicht ( terminiert anscheinend zu früh, größere Dateien werden nicht vollständig kopiert )

ohne dem "soft_close", dafür aber einem "interact" am Ende funktioniert "scp" bei mir auch

Code: Alles auswählen

#$exp->soft_close();
$exp->interact(); 
vielleicht hilft das auch bei sshfs, kann es aber leider nicht selber testen

Gruß
gms

Antworten