#!/usr/bin/perl -wT
delete $ENV{$_} for qw(PATH BASH_ENV);

# QuickSwitch
# Switch network profiles on the fly
# Copyright (c) 2000 Mohit Muthanna 
#
# Modifications by Paul Seamons
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, 
# Boston, MA  02111-1307, USA.
# 
# Send bug-reports, comments, women to bugs@muthanna.com
#
#
# QuickSwitch Profile Selector
# Mohit Muthanna 2002
#
# Modifications by Paul Seamons (perl@seamons.com)
#
# 
# Frontend to Quickswitch
#
# $Log: switcher,v $
# Revision 1.4  2002/01/15 20:31:42  rhandom
# - Allow for non-default location of switchto.
# - Added security checking on switchto file.
#
# Revision 1.3  2002/01/15 19:49:43  rhandom
# - Major Code rewrite.
# - Now uses switchto as a package library.
# - Compatible with recent Curses::Widgets libraries.
# - Strict, warn, and taint safe.  Allows for setuid execution.
#
# Revision 1.2  2001/12/13 18:42:08 muthanna
# - Switcher fix for files section.
#
# Revision 1.1  2001/12/05 15:18:09 muthanna
# - Initial Commit
#
# CVS: $Id: switcher,v 1.4 2002/01/15 20:31:42 rhandom Exp $

use strict;
use vars qw($PROGNAME $VERSION $AUTHOR $CONF_FILE $SWITCHTO $_SWITCHTO);
use Data::Dumper qw(Dumper);
$PROGNAME = 'QuickSwitch Profile Selector';
$AUTHOR   = 'Mohit Muthanna, Paul Seamons';
$VERSION  = '0.16';

### load curses (using recent version) libraries
use Curses;
use Curses::Widgets '1.992';
use Curses::Widgets::ListBox;


### load quickswitch package
$_SWITCHTO = '/usr/bin/switchto'; # default location
$CONF_FILE = '/etc/switchto.conf';
$SWITCHTO = find_switchto($CONF_FILE);
$ENV{RUNNING_FROM_SWITCHER} = 1;
require $SWITCHTO;
delete $ENV{RUNNING_FROM_SWITCHER};

### execute it
init();
exit 0;


###----------------------------------------------------------------###

sub init {

  ### read the configs (use package from switchto)
  my $self = QuickSwitch->new();
  $self->parse_commandline_switches;
  $self->check_setuid;
  $self->parse_conf_file;


  ### load profiles
  my @profiles = ();
  for my $key ( keys %{ $self->{services} } ){
    push @profiles, $key." - ".$self->{services}->{$key}->{description};
  }
  push @profiles, "No Profile (Exit)";


  my $bg_color = 'blue';

  ### the new window
  $SIG{__DIE__} = sub { endwin(); die @_ };
  END{ endwin() };
  my $win = new Curses;
  noecho();
  halfdelay(5);
  $win->keypad(1);
  curs_set(0);

  ### clean window
  $win->bkgdset(COLOR_PAIR(select_colour('white',$bg_color)));
  $win->erase();

  ### draw a border
  $win->attrset(COLOR_PAIR(select_colour('red',$bg_color)));
  $win->box(ACS_VLINE, ACS_HLINE);
  $win->attrset(0);

  ### draw caption
  $win->standout();
  $win->attrset(COLOR_PAIR(select_colour('yellow',$bg_color)));
  $win->addstr(0, 1, "$PROGNAME $VERSION");
  $win->standend();

  ### draw the information text
  my $swin = $win->subwin(6,67,7+@profiles,5);
  $swin->bkgdset(COLOR_PAIR(select_colour('white',$bg_color)));
  $swin->erase();
  $swin->box(ACS_VLINE, ACS_HLINE);
  $swin->attrset(COLOR_PAIR(select_colour('yellow',$bg_color)));
  $swin->addstr (1,2,"Select the desired network profile here. Profiles are defined");
  $swin->addstr (2,2,"in $self->{conf_file}. Docs at quickswitch.sourceforge.net");
  $swin->addstr (4,2,"$AUTHOR [www.muthanna.com].");
  $swin->refresh();

  $win->attron(A_NORMAL);

  ### draw the listbox
  my $listbox = Curses::Widgets::ListBox->new ({
    Y      => 5,
    X      => 5,
    LENGTH => 65,
    LISTITEMS => \@profiles,
    MULTISEL  => 0,
    SELECTED  => [0],
    CAPTION   => 'Profiles',
    CAPTIONCOL => 'yellow',
    FOREGROUND => 'white',
    BACKGROUND => $bg_color,
    BORDER     => 1,
    BORDERCOL  => 'white',
    FOCUSSWITCH => qr/\s/,
  });

  $listbox->execute($win);
  $win->refresh();

  ### what option was chosen?
  my $sel = $listbox->getField('CURSORPOS');

  ### return the console to its original state
  endwin();
  $SIG{__DIE__} = 'DEFAULT';
  select STDOUT;
  

  ### take the selection and do that service
  if( $sel
      && $sel != $#profiles
      && $profiles[$sel]
      && $profiles[$sel] =~ m/^(\S+)\s+-\s+/ ){
    my $profile = $1;

    ### see if we need to pass any options
    my @_ARGV = ();
    push @_ARGV, "-d$1" if $self->{verbose} && $self->{verbose}=~/(\d+)/;
    push @_ARGV, "-p$1" if $self->{pause} && $self->{pause}=~/(\d+)/;

    my $command = "$SWITCHTO @_ARGV $profile";
#    print Dumper $command,$self;
    exec($command)
  }
}

sub find_switchto {
  my $conf_file = shift;

  my $path = undef;

  ### open the conf file and see if we can find the real location
  open(_CONF,"<$conf_file") || die "Couldn't open $conf_file: $!";
  while(<_CONF>){
    next unless $_;
    next unless /^switchtopath\s*=\s*(\S+)/;
    $path = $1;
    if( $path =~ /([^\w\/\-\.])/ ){
      die "Invalid character ($1) found in switchtopath ($path) from conf file $conf_file\n";
    }elsif( ! -e $path ){
      die "File ($path) does not exist.\n";
    }
    last;
  }
  close(_CONF);
  
  ### set the default if none found
  $path = $_SWITCHTO unless defined $path;

  ### make sure that this file is owned by root
  my $file_uid = (stat($path))[4];
  if( $> == 0 && $file_uid != 0 ){
    die "Error: switchtopath ($path) must be owned by root when running as root.\n";
  }

  return $path;
}
