summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xperl-install/standalone/drakroam445
1 files changed, 445 insertions, 0 deletions
diff --git a/perl-install/standalone/drakroam b/perl-install/standalone/drakroam
new file mode 100755
index 000000000..6237ca8ae
--- /dev/null
+++ b/perl-install/standalone/drakroam
@@ -0,0 +1,445 @@
+#!/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
+# - 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
+
+use Gtk2 '-init';
+use Gtk2::SimpleList;
+use Glib qw(TRUE FALSE);
+use lib qw(/usr/lib/libDrakX);
+use common;
+require_root_capability;
+
+# global settings
+$config = '/etc/wlandetect.conf';
+$route = '/sbin/route';
+$AboutFile = 'ABOUT';
+$HelpFile = 'README';
+$WLanDetect = '/usr/sbin/wlandetect';
+$IWList = '/sbin/iwlist';
+$IWConfig = '/sbin/iwconfig';
+$IFConfig = '/sbin/ifconfig';
+$IFUp = '/sbin/ifup';
+$IFDown = '/sbin/ifdown';
+$DHClient = '/sbin/dhclient';
+
+# initialize variables
+$ScanInterval = 60; # tell deamon to search for new nets every x seconds
+$NumberOfNets = 0; # really lame way to count the number of nets to write to config file
+# there must be a better way to count the number of arrays in $KnownList->{data} !!
+
+# initialize main window
+$MainWindow = Gtk2::Window->new;
+$MainWindow->set_title ('Drakroam');
+$MainWindow->set_border_width(2);
+$MainWindow->signal_connect (delete_event => sub {
+ Gtk2->main_quit;
+});
+
+# add main box; everything goes in here
+$MainBox = Gtk2::VBox->new(0);
+$MainWindow->add ($MainBox);
+
+# add status box and frame
+$StatusBox = Gtk2::VBox->new(0);
+$StatusFrame = Gtk2::Frame->new("Status");
+$StatusFrame->set_border_width(2);
+$StatusFrame->add($StatusBox);
+$MainBox->pack_start ($StatusFrame, 0, 0, 0);
+
+# add status labels in three columns
+$StatusLabels = Gtk2::HBox->new(0,0);
+$StatusBox->pack_start ($StatusLabels, 0, 0, 0);
+$StatusColumnA = Gtk2::VBox->new(0);
+$StatusColumnB = Gtk2::VBox->new(0);
+$StatusColumnC = Gtk2::VBox->new(0);
+$StatusLabels->pack_start ($StatusColumnA, 0, 0, 10);
+$StatusLabels->pack_start ($StatusColumnB, 0, 0, 10);
+$StatusLabels->pack_start ($StatusColumnC, 0, 0, 10);
+$StatusLabelA = Gtk2::Label->new;
+$StatusLabelB = Gtk2::Label->new;
+$StatusLabelC = Gtk2::Label->new;
+$StatusColumnA->pack_start ($StatusLabelA, 0, 0, 0);
+$StatusColumnB->pack_start ($StatusLabelB, 0, 0, 0);
+$StatusColumnC->pack_start ($StatusLabelC, 0, 0, 0);
+
+# add disconnect and refresh buttons
+$StatusControls = Gtk2::HBox->new(1,0);
+$DisconnectButton = Gtk2::Button->new("Disconnect");
+$StatusControls->pack_start($DisconnectButton, 0, 0, 0);
+$DisconnectButton->signal_connect (clicked=>sub { &Disconnect });
+$RefreshButton = Gtk2::Button->new("Refresh");
+$StatusControls->pack_start($RefreshButton, 0, 0, 0);
+$RefreshButton->signal_connect (clicked=>sub { &UpdateStatus });
+$StatusBox->pack_start($StatusControls, 0, 0, 0);
+
+# add roaming box and frame
+$RoamBox = Gtk2::HBox->new(1,0);
+$RoamFrame = Gtk2::Frame->new("Roaming");
+$RoamFrame->set_border_width(2);
+$RoamFrame->add($RoamBox);
+$MainBox->pack_start ($RoamFrame, 0, 0, 0);
+
+# add roam status and controls
+$RoamControls = Gtk2::VBox->new(0);
+$RoamStatus = Gtk2::Label->new("Roaming: off");
+$RoamControls->pack_start($RoamStatus, 0, 0, 0);
+$RoamStartStop = Gtk2::HBox->new(0);
+$StartButton = Gtk2::Button->new("Start");
+$StartButton->signal_connect(clicked=>sub { &StartRoam });
+$RoamStartStop->pack_start($StartButton, 0, 0, 0);
+$StopButton = Gtk2::Button->new("Stop");
+$RoamStartStop->pack_start($StopButton, 0, 0, 0);
+$StopButton->signal_connect(clicked=>sub { &StopRoam });
+$RoamControls->pack_start($RoamStartStop, 0, 0, 0);
+$RoamBox->pack_start($RoamControls, 0, 0, 0);
+
+# add scan controls
+$ScanControl = Gtk2::VBox->new(0);
+$ScanDialogue = Gtk2::HBox->new(0);
+$ScanLabel = Gtk2::Label->new("Scan interval (sec): ");
+$ScanControl->pack_start($ScanLabel, 0, 0, 0);
+$ScanEntry = Gtk2::Entry->new;
+$ScanEntry->set_width_chars(4);
+$ScanDialogue->pack_start($ScanEntry, 0, 0, 0);
+$ScanEntry->set_text("$ScanInterval");
+$ScanSetButton = Gtk2::Button->new("Set");
+$ScanSetButton->signal_connect(clicked=>sub { &SetInterval });
+$ScanDialogue->pack_start($ScanSetButton, 0, 0, 0);
+$ScanControl->pack_start($ScanDialogue, 0, 0, 0);
+$RoamBox->pack_start($ScanControl, 0, 0, 0);
+
+# add known network box
+$KnownBox = Gtk2::VBox->new(0);
+$KnownFrame = Gtk2::Frame->new("Known Networks (Drag up/down or edit)");
+$KnownFrame->set_border_width(2);
+$KnownFrame->add($KnownBox);
+$MainBox->pack_start ($KnownFrame, 0, 0, 0);
+
+# make list and scroll box for known networks
+$KnownList = Gtk2::SimpleList->new(
+ "ESSID" => "text",
+ "Mode" => "text",
+ "Channel" => "int",
+ "Key" => "text",
+ "DHCP" => "bool"
+);
+$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 (3, TRUE); # allow to change key
+#$KnownBox->pack_start($KnownList, 0, 0, 0);
+$KnownScroll = Gtk2::ScrolledWindow->new;
+$KnownScroll->set_policy ('automatic', 'automatic');
+$KnownScroll->add ($KnownList);
+$KnownBox->pack_start ($KnownScroll, 0, 0, 0);
+
+# add controls for known networks
+$KnownControls = Gtk2::HBox->new(1);
+$RemoveNetButton = Gtk2::Button->new("Remove");
+$KnownControls->pack_start($RemoveNetButton, 0, 0, 0);
+$RemoveNetButton->signal_connect(clicked=>sub {
+ my @selected = $KnownList->get_selected_indices;
+ splice @{$KnownList->{data}}, "@selected", 1;
+ $NumberOfNets--;
+});
+$ConnectButton = Gtk2::Button->new("Connect");
+$KnownControls->pack_start($ConnectButton, 0, 0, 0);
+$ConnectButton->signal_connect(clicked=>sub {
+ my @selected = $KnownList->get_selected_indices;
+ &ConnectNow (@selected);
+});
+$SaveConfigButton = Gtk2::Button->new("Save");
+$KnownControls->pack_start($SaveConfigButton, 0, 0, 0);
+$SaveConfigButton->signal_connect(clicked=>sub { &WriteConfig });
+$KnownBox->pack_start($KnownControls, 0, 0, 0);
+
+# add available networks box
+$AvailableBox = Gtk2::VBox->new(0);
+$AvailableFrame = Gtk2::Frame->new("Available Networks");
+$AvailableFrame->set_border_width(2);
+$AvailableFrame->add($AvailableBox);
+$MainBox->pack_start ($AvailableFrame, 0, 0, 0);
+
+# make list and scroll box for available networks
+$AvailableList = Gtk2::SimpleList->new(
+ "ESSID" => "text",
+ "Type" => "text",
+ "Encryption" => "text",
+ "Signal (%)" => "int"
+);
+$AvailableList->get_selection->set_mode ('single');
+#$AvailableBox->pack_start($AvailableList, 0, 0, 0);
+$AvailableScroll = Gtk2::ScrolledWindow->new;
+$AvailableScroll->set_policy ('automatic', 'automatic');
+$AvailableScroll->add ($AvailableList);
+$AvailableBox->pack_start ($AvailableScroll, 0, 0, 0);
+
+# add controls for available networks
+$AvailableControls = Gtk2::HBox->new(1);
+$AddNetButton = Gtk2::Button->new("Add");
+$AvailableControls->pack_start($AddNetButton, 0, 0, 0);
+$AddNetButton->signal_connect(clicked=>sub {
+ my @selected = $KnownList->get_selected_indices;
+ my $essid = $AvailableList->{data}[@selected][0];
+ my $mode = undef;
+ my $channel = undef;
+ my $key = undef;
+ my $dhcp = 1; # assume dhcp for new networks
+ &AddNet ($essid, $mode, $channel, $key, $dhcp);
+});
+$UpdateAvailableButton = Gtk2::Button->new("Rescan");
+$AvailableControls->pack_start($UpdateAvailableButton, 0, 0, 0);
+$UpdateAvailableButton->signal_connect(clicked=>sub { &UpdateAvailable });
+$AvailableBox->pack_start($AvailableControls, 0, 0, 0);
+
+# add master controls
+$MasterBox = Gtk2::HBox->new(1);
+$HelpButton = Gtk2::Button->new("Help");
+$MasterBox->pack_start($HelpButton, 0, 0, 0);
+$HelpButton->signal_connect (clicked=>sub { &Dialog ("$HelpFile") });
+$AboutButton = Gtk2::Button->new("About");
+$MasterBox->pack_start($AboutButton, 0, 0, 0);
+$AboutButton->signal_connect (clicked=>sub { &Dialog ("$AboutFile") });
+$CloseButton = Gtk2::Button->new("Save and close");
+$MasterBox->pack_start($CloseButton, 0, 0, 0);
+$CloseButton->signal_connect (clicked=>sub {
+ &WriteConfig;
+ Gtk2->main_quit;
+});
+$MainBox->pack_start($MasterBox, 0, 0, 0);
+
+# fill the GUI
+&ReadConfig;
+&UpdateAll;
+
+sub UpdateAll {
+ &UpdateAvailable; #must go first as it defines the device name
+ &UpdateStatus;
+ &UpdateRoaming;
+}
+
+sub UpdateRoaming {
+ open (PS, "ps -A |") or die ("Can't open ps\n");
+ while (<PS>) {
+ if (/wlandetect/) {
+ $RoamStatus->set_text("Roaming: on");
+ }
+ else {
+ $RoamStatus->set_text("Roaming: off");
+ }
+ }
+ close PS;
+}
+
+sub UpdateStatus {
+ my $CurrentNet = "-";
+ my $CurrentIP = "---.---.---.---";
+ $CurrentGW = "---.---.---.---";
+ $CurrentMode = "";
+ $CurrentWEP = "";
+ $CurrentSignal = "-";
+ print ("Updating\n");
+ open (IWSTATUS, "$IWConfig 2>/dev/null |") or die ("Can't run iwconfig\n");
+ while (<IWSTATUS>) {
+ if (/ESSID:\"(\S*)\"/) { $CurrentNet = $1 }
+ if (/Mode:(\S*)\s/) { $CurrentMode = $1 }
+ if (/key:(\S*)\s/) { $CurrentWEP = $1 }
+ if (/Quality:(\S*)\//) { $CurrentSignal = $1 }
+ }
+ close IWSTATUS;
+ open (IFSTATUS, "$IFConfig $device |") or die ("Can't run ifconfig\n");
+ while (<IFSTATUS>) {
+ if (/inet addr:(\S*)\s/) { $CurrentIP = $1 }
+ }
+ close IFSTATUS;
+ open (ROUTE, "$route |") or die ("Can't run route\n");
+ while (<ROUTE>) {
+ if (/default\s*(\S*)\s/) { $CurrentGW = $1 }
+ else { $CurrentGW = "---.---.---.---" }
+ }
+ close ROUTE;
+ $StatusLabelA->set_text ("Net: $CurrentNet\nMode: $CurrentMode");
+ $StatusLabelB->set_text ("IP: $CurrentIP\nEncryption: $CurrentWEP");
+ $StatusLabelC->set_text ("Gateway: $CurrentGW\nSignal: $CurrentSignal");
+}
+
+sub UpdateAvailable {
+ print ("Running iwlist\n");
+ open (LIST, "$IWList scan 2>/dev/null |") or die ("Can't run iwlist");
+ @{$AvailableList->{data}} = ();
+ while (<LIST>) {
+ if(/([^ ]+)([ \t]+)Scan completed :/) { $device = $1 }
+ elsif (/([^ ]+)([ \t]+)No scan results/) { $device = $1 }
+ if (/ESSID:"(\S*)"/) {
+ $essid = $1;
+ print ("Found $essid.\n");
+ my $mode = undef;
+ my $wep = undef;
+ my $signal = undef;
+ }
+ if (/Mode:(\S*)/) { $mode = $1 }
+ if (/Quality:(\S*)\//) { $signal = $1 }
+ if (/key:(\S*)\s/) {
+ $wep = $1;
+ print ("Mode: $mode, WEP: $wep, Signal: $signal\n");
+ push @{$AvailableList->{data}}, [$essid, $mode, $wep, $signal];
+ }
+ }
+ close LIST;
+}
+
+sub AddNet {
+ my $essid = shift @_;
+ my $mode = shift @_;
+ my $channel = shift @_;
+ my $key = shift @_;
+ my $dhcp = shift @_;
+ print "Adding net $essid\n";
+ push (@{$KnownList->{data}}, [$essid, $mode, $channel, $key, $dhcp]);
+ $NumberOfNets++;
+}
+
+sub ReadConfig {
+ open(CONFIG, $config) or die "Configuration file not found.\n";
+ print "Reading config file.\n\n";
+ $line = 0;
+ while (<CONFIG>) {
+ $line++;
+ if (/^#/) {} #ignore comments
+ elsif (/^\n/) {} #ignore blank lines
+ elsif (/([^ \t]+)([ \t]+)(.*)/) {
+ my $essid = $1;
+ my $command = $3;
+ # setup new network entry
+ my $mode = undef;
+ my $channel = undef;
+ my $key = undef;
+ my $dhcp = undef;
+ if ($command =~ /mode\s(\S*);/) { $mode = $1; }
+ elsif ($command =~ /mode\s(\S*)\s/) { $mode = $1; }
+ if ($command =~ /channel\s(\S*);/) { $channel = $1; }
+ elsif ($command =~ /channel\s(\S*)\s/) { $channel = $1; }
+ if ($command =~ /key\s(\S*);/) { $key = $1; }
+ elsif ($command =~ /key\s(\S*)\s/) { $key = $1; }
+ if ($command =~ /dhclient/) { $dhcp = 1; }
+ else { $dhcp = 0; }
+ &AddNet ($essid, $mode, $channel, $key, $dhcp);
+ }
+ else { die "Line $line of configuration file is not parseable.\n"; }
+ }
+ close CONFIG;
+}
+
+sub WriteConfig {
+ open (CONFIG, "> $config") or die ("Can't open configuration file\n");
+ print CONFIG ("#wlandetect configuration file\n#format: essid<tab><tab>commands\n#use @DEV@ for device name\n");
+ for ($row=0; $row<$NumberOfNets; $row++) { # again, lame
+ print CONFIG "$KnownList->{data}[$row][0]\t\t$IWConfig essid $KnownList->{data}[$row][0]";
+ if ($KnownList->{data}[$row][1]) {
+ print CONFIG "mode $KnownList->{data}[$row][1] ";
+ }
+ if ($KnownList->{data}[$row][2]) {
+ print CONFIG "channel $KnownList->{data}[$row][2] ";
+ }
+ if ($KnownList->{data}[$row][3]) {
+ print CONFIG "key $KnownList->{data}[$row][3] ";
+ }
+ print CONFIG "; ";
+ if ($KnownList->{data}[$row][4]) {
+ print CONFIG "$IFConfig \@DEV\@ up; $DHClient \@DEV\@";
+ }
+ else {
+ print CONFIG "$IFUp \@DEV\@"
+ }
+ print CONFIG "\n";
+ }
+ close CONFIG;
+}
+
+sub StartRoam {
+ system ("killall wlandetect; $WLanDetect -d -t $ScanInterval &");
+ &UpdateRoaming
+}
+
+sub StopRoam {
+ system ("killall wlandetect");
+ &UpdateRoaming;
+}
+
+sub SetInterval {
+ $ScanInterval = $ScanEntry->get_text;
+ system ("killall wlandetect; $WLanDetect -d -t $ScanInterval &");
+}
+
+sub ConnectNow {
+ my @command = "";
+ push @command, "$IWConfig 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][3]) {
+ push @command, "key $KnownList->{data}[$row][3] ";
+ }
+ push @command, "; ";
+ if ($KnownList->{data}[$row][4]) {
+ push @command, "$IFConfig $decive up; $DHClient $device";
+ }
+ else {
+ push @command, "$IFUp $device"
+ }
+ $ToBash = join ("", @command);
+ print ("Sending $ToBash\n");
+ system ($ToBash);
+ &UpdateStatus;
+}
+
+sub Disconnect {
+ system ("$IFDown $device");
+ &UpdateStatus;
+}
+
+sub Dialog {
+# read file
+$FilePointer = pop @_;
+open FILE, "<$FilePointer";
+undef $/;
+my $content = <FILE>;
+close FILE;
+$/ = "\n";
+# dump into a dialog
+$AboutWindow = Gtk2::Dialog->new ("Drakroam Info", $MainWindow,
+ 'destroy-with-parent',
+ 'gtk-ok' => 'none');
+$AboutLabel = Gtk2::Label->new ($content);
+$DialogScroll = Gtk2::ScrolledWindow->new;
+#$DialogScroll->set_policy ('automatic', 'automatic');
+$DialogScroll->add_with_viewport($AboutLabel);
+$AboutWindow->vbox->add ($DialogScroll);
+$AboutWindow->signal_connect (response => sub { $_[0]->destroy });
+$AboutWindow->show_all;
+}
+
+# start GUI
+print "Stating GUI\n";
+$MainWindow->show_all;
+Gtk2->main;