diff options
Diffstat (limited to 'perl-install/standalone/drakroam')
| -rwxr-xr-x | perl-install/standalone/drakroam | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/perl-install/standalone/drakroam b/perl-install/standalone/drakroam new file mode 100755 index 000000000..bdb25e61c --- /dev/null +++ b/perl-install/standalone/drakroam @@ -0,0 +1,397 @@ +#!/usr/bin/perl + +# drakroam: wireless network roaming GUI +# beta version uses wlandetect as backend +# Austin Acton, 2004 +# <austin@mandrake.org> +# Licensed under the GPL + +# problems +# - deletes comments in config file +# - expects an ifcfg file for static IP configurations (not uncommon) +# - roaming status fails (no idea why) +# maybe same reason bash-completion killall can't see wlandetect? + +# todo (wlandetect version) +# - make known and available lists have more rows by default (why so small?) +# - refresh status every x seconds +# - find a good way to drop the access point and resume roaming +# - make 'key' column wider by default +# todo (waproamd version) +# - listen to dbus for pings from waproamd; update all on receiving a dbus ping +# - setup static network configurations +# - handle keys (can key file be named after ESSID?) +# - should files be named as MAC or as essid:ESSID ? + +use lib qw(/usr/lib/libDrakX); + +use standalone; +use common; +use run_program; + +require ugtk2; +ugtk2->import(qw(:wrappers :create)); +use Gtk2::SimpleList; + +require_root_capability(); + +# global settings +my $route = '/sbin/route'; +my $AboutFile = 'ABOUT'; +my $HelpFile = 'README'; +my $IWList = '/sbin/iwlist'; +my $IWConfig = '/sbin/iwconfig'; +my $IFConfig = '/sbin/ifconfig'; +my $IFUp = '/sbin/ifup'; +my $IFDown = '/sbin/ifdown'; +my $DHClient = '/sbin/dhclient'; + +# initialize variables +my $ScanInterval = 30; # tell deamon to search for new nets every x seconds + +my ($KnownList, $AvailableList); +my $device; + +my %available_roaming_daemons = ( + wlandetect => { + config_location => '/etc/wlandetect.conf', + binary => '/usr/sbin/wlandetect', + start_options => sub { + my ($interval, $device) = @_; + "-d -t $interval"; + }, + read_config => sub { + my ($config) = @_; + each_index { + /^#/ || /^\n/ and next; #ignore comments and blank lines + if (/^(\S+)\s+(.*)$/) { + my ($essid, $mode, $channel, $dhcp, $key); + my $command = $2; + # setup new network entry + $essid = $1; + ($mode) = $command =~ /mode\s([^\s;]+)/; + ($channel) = $command =~ /channel\s([^\s;]+)/; + ($key) = $command =~ /key\s([^\s;]+)/; + $dhcp = $command =~ /dhclient/; + &AddNet($essid, $mode, $channel, $dhcp, $key); + } + else { die "Line $::i of configuration file is not parseable.\n" } + } cat_($config) + }, + write_config => sub { + my ($config) = @_; + my @contents = ( + "#wlandetect configuration file\n", + "#format: essid<tab><tab>commands\n", + "#use \@DEV\@ for device name\n" + ); + foreach my $row (@{$KnownList->{data}}) { # again, lame + my $essid = $row->[0]; + my $iwc = join(' ', $IWConfig, "essid $essid", + if_($row->[1], "mode $row->[1]"), + if_($row->[2], "channel $row->[2]"), + if_($row->[4], "key $row->[4]")); + my $ifc = $row->[3] ? "$IFConfig \@DEV\@ up; $DHClient \@DEV\@" : "$IFUp \@DEV\@"; + push @contents, "$essid\t\t$iwc; $ifc\n"; + } + output_p($config, @contents); + }, + add_net => sub {}, + remove_net => sub {}, + }, + waproamd => { + config_location => '/etc/waproamd/scripts', + binary => '/usr/sbin/waproamd', + start_options => sub { + my ($interval, $device) = @_; + "-i $device -t $interval"; + }, + read_config => sub { + my ($config) = @_; + foreach my $net (all($config)) { + $net eq "default" or next; + print "Adding net $net\n"; + push @{$KnownList->{data}}, [$net]; + } + }, + write_config => sub {}, + add_net => sub { + my ($config, $essid) = @_; + output_p("$config/$essid", qq(# essid specific config file)); + }, + remove_net => sub { + my ($config, $essid) = @_; + system("rm -f $config/$essid"); + }, + }, +); + +my $roaming_daemon = $available_roaming_daemons{wlandetect}; + +my $ScanEntry = Gtk2::Entry->new; +$ScanEntry->set_width_chars(4); +$ScanEntry->set_text($ScanInterval); + +$KnownList = Gtk2::SimpleList->new( + "ESSID" => "text", + "Mode" => "text", + "Channel" => "text", + "DHCP" => "bool", + "Key" => "text" + ); +$KnownList->get_selection->set_mode('single'); +$KnownList->set_reorderable(1); +$KnownList->set_column_editable(1, TRUE); # allow to change mode +$KnownList->set_column_editable(2, TRUE); # allow to change channel +$KnownList->set_column_editable(4, TRUE); # allow to change key + +$AvailableList = Gtk2::SimpleList->new( + "ESSID" => "text", + "Type" => "text", + "Encryption" => "text", + "Signal (%)" => "int" + ); +$AvailableList->get_selection->set_mode('single'); + +my $NetLabel = Gtk2::Label->new; +my $IpLabel = Gtk2::Label->new; +my $GwLabel = Gtk2::Label->new; +my $ModeLabel = Gtk2::Label->new; +my $WepLabel = Gtk2::Label->new; +my $SignalLabel = Gtk2::Label->new; + +my $w = ugtk2->new('Drakroam'); +gtkadd(gtkset_border_width($w->{window}, 2), + gtkpack_(Gtk2::VBox->new, + 0, gtkadd(gtkset_border_width(Gtk2::Frame->new("Status"), 2), + gtkpack(Gtk2::VBox->new, + create_packtable({ col_spacings => 5, row_spacings => 5, homogenous => 1 }, + [ $NetLabel, $IpLabel, $GwLabel ], + [ $ModeLabel, $WepLabel, $SignalLabel ], + ), + gtkpack(create_hbox(), + gtksignal_connect(Gtk2::Button->new("Disconnect"), clicked => sub { &Disconnect }), + gtksignal_connect(Gtk2::Button->new("Refresh"), clicked => sub { &UpdateStatus }) + ) + ) + ), + 0, gtkadd(gtkset_border_width(Gtk2::Frame->new("Roaming"), 2), + gtkpack(create_hbox(), + gtkpack(Gtk2::VBox->new, + my $RoamStatus = Gtk2::Label->new("Roaming: off"), + gtkpack(create_hbox(), + gtksignal_connect(Gtk2::Button->new("Start"), clicked => sub { &StartRoam }), + gtksignal_connect(Gtk2::Button->new("Stop"), clicked => sub { &StopRoam }) + ) + ), + gtkpack(Gtk2::VBox->new, + Gtk2::Label->new("Scan interval (sec): "), + gtkpack(Gtk2::HBox->new, + $ScanEntry, + gtksignal_connect(Gtk2::Button->new("Set"), clicked => sub { &SetInterval }) + ) + ) + ) + ), + 1, gtkadd(gtkset_border_width(Gtk2::Frame->new("Known Networks (Drag up/down or edit)"), 2), + gtkpack_(Gtk2::VBox->new, + 1, create_scrolled_window($KnownList), + 0, gtkpack(create_hbox(), + gtksignal_connect(Gtk2::Button->new("Remove"), clicked => sub { + my ($selected) = $KnownList->get_selected_indices; + &RemoveNet($selected); + }), + gtksignal_connect(Gtk2::Button->new("Connect"), clicked => sub { + my ($selected) = $KnownList->get_selected_indices; + &ConnectNow($selected); + }), + gtksignal_connect(Gtk2::Button->new("Save"), clicked => sub { &WriteConfig }) + ) + ) + ), + 1, gtkadd(gtkset_border_width(Gtk2::Frame->new("Available Networks"), 2), + gtkpack_(Gtk2::VBox->new, + 1, create_scrolled_window($AvailableList), + 0, gtkpack(create_hbox(), + gtksignal_connect(Gtk2::Button->new("Add"), clicked => sub { + my @selected = $AvailableList->get_selected_indices; + my ($mode, $channel, $key); + my $essid = $AvailableList->{data}["@selected"][0]; + my $dhcp = 1; # assume dhcp for new networks + &AddNet($essid, $mode, $channel, $dhcp, $key); + }), + gtksignal_connect(Gtk2::Button->new("Rescan"), clicked => sub { &UpdateAvailable }) + ) + ) + ), + 0, gtkpack(create_hbox(), + gtksignal_connect(Gtk2::Button->new("Help"), clicked => sub { &Dialog($HelpFile) }), + gtksignal_connect(Gtk2::Button->new("About"), clicked => sub { &Dialog($AboutFile) }), + gtksignal_connect(Gtk2::Button->new("Save and close"), clicked => sub { + &WriteConfig; + Gtk2->main_quit; + }) + ) + ) + ); + +# fill the GUI +&ReadConfig; +&UpdateAll; + +sub UpdateAll { + &UpdateAvailable; #must go first as it defines the device name + &UpdateStatus; + &UpdateRoaming; +} + +sub isRoamingRunning() { + my $name = basename($roaming_daemon->{binary}); + any { /\Q$name\E$/ } run_program::get_stdout("ps", "-A"); +} + +sub UpdateRoaming() { + my $status = isRoamingRunning() ? "on" : "off"; + $RoamStatus->set_text("Roaming: $status"); + return FALSE; #- do not update again if launched on timeout +} + +sub UpdateStatus() { + my $CurrentNet = "-"; + my $CurrentIP = "---.---.---.---"; + my $CurrentGW = "---.---.---.---"; + my $CurrentMode = ""; + my $CurrentWEP = ""; + my $CurrentSignal = "-"; + print("Updating\n"); + foreach (run_program::get_stdout($IWConfig, $device)) { + /ESSID:"(\S*)"/ and $CurrentNet = $1; + /Mode:(\S*)\s/ and $CurrentMode = $1; + /key:(\S*)\s/ and $CurrentWEP = $1; + m!Quality:(\S*)/! and $CurrentSignal = $1; + } + foreach (run_program::get_stdout($IFConfig, $device)) { + if (/inet addr:(\S*)\s/) { $CurrentIP = $1 } + } + foreach (run_program::get_stdout($route)) { + if (/default\s*(\S*)\s/) { $CurrentGW = $1 } + else { $CurrentGW = "---.---.---.---" } + } + $NetLabel->set_text("Net: $CurrentNet"); + $ModeLabel->set_text("Mode: $CurrentMode"); + $IpLabel->set_text("IP: $CurrentIP"); + $WepLabel->set_text("Encryption: $CurrentWEP"); + $GwLabel->set_text("Gateway: $CurrentGW"); + $SignalLabel->set_text("Signal: $CurrentSignal"); +} + +sub UpdateAvailable() { + my ($essid, $mode, $wep, $signal); + print("Running iwlist\n"); + @{$AvailableList->{data}} = (); + foreach (run_program::get_stdout($IWList, "scan")) { + /([^ ]+)([ \t]+)Scan completed :/ and $device = $1; + /([^ ]+)([ \t]+)No scan results/ and $device = $1; + /ESSID:"(\S*)"/ and $essid = $1; + /Mode:(\S*)/ and $mode = $1; + m!Quality:(\S*)/! and $signal = $1; + if (/key:(\S*)\s/) { + $wep = $1; + print("ESSID: $essid, Mode: $mode, WEP: $wep, Signal: $signal\n"); + push @{$AvailableList->{data}}, [$essid, $mode, $wep, $signal]; + } + } +} + +sub AddNet { + my ($essid, $mode, $channel, $dhcp, $key) = @_; + print "Adding net $essid\n"; + push @{$KnownList->{data}}, [ $essid, $mode, $channel, $dhcp, $key ]; + $_->{add_net}($_->{config_location}, $essid) foreach values %available_roaming_daemons; +} + +sub RemoveNet { + my ($selected) = @_; + my $essid = $KnownList->{data}[$selected][0]; + print "Removing net $essid\n"; + splice @{$KnownList->{data}}, $selected, 1; + $_->{remove_net}($_->{config_location}, $essid) foreach values %available_roaming_daemons; +} + +sub ReadConfig() { + $_->{read_config}($_->{config_location}) foreach values %available_roaming_daemons; +} + +sub WriteConfig() { + $_->{write_config}($_->{config_location}) foreach values %available_roaming_daemons; +} + +sub StartRoam() { + my $options = $roaming_daemon->{start_options}($ScanInterval, $device); + my $name = basename($roaming_daemon->{binary}); + system("killall $name; $roaming_daemon->{binary} $options &"); + Glib::Timeout->add(1000, \&UpdateRoaming); +} + +sub StopRoam() { + my $name = basename($roaming_daemon->{binary}); + system("killall $name"); + Glib::Timeout->add(1000, \&UpdateRoaming); +} + +sub SetInterval() { + $ScanInterval = $ScanEntry->get_text; + if (isRoamingRunning()) { + StopRoam(); + StartRoam(); + } +} + +sub ConnectNow { + my ($row) = @_; + my @command = ""; + push @command, "$IWConfig $device essid $KnownList->{data}[$row][0] "; + if ($KnownList->{data}[$row][1]) { + push @command, "mode $KnownList->{data}[$row][1] "; + } + if ($KnownList->{data}[$row][2]) { + push @command, "channel $KnownList->{data}[$row][2] "; + } + if ($KnownList->{data}[$row][4]) { + push @command, "key $KnownList->{data}[$row][4] "; + } + push @command, "; "; + if ($KnownList->{data}[$row][3]) { + push @command, "$IFConfig $device up; $DHClient $device"; + } + else { + push @command, "$IFUp $device" + } + my $ToBash = join("", @command); + print("Sending $ToBash\n"); + system($ToBash); + &UpdateStatus; +} + +sub Disconnect { + print("Dropping $device\n"); + system("$IFDown $device"); + &UpdateStatus; +} + +sub Dialog { + my ($FilePointer) = @_; + my $content = join('', cat_($FilePointer)); + # dump into a dialog + my $AboutWindow = Gtk2::Dialog->new("Drakroam Info", $w->{window}, + 'destroy-with-parent', + N("Ok") => 'none'); + $AboutWindow->vbox->add(create_scrolled_window(Gtk2::Label->new($content))); + $AboutWindow->signal_connect(response => sub { $_[0]->destroy }); + $AboutWindow->show_all; +} + +# start GUI +print "Starting GUI\n"; + +$w->main; |
