#!/usr/bin/perl -w
# $Id$
# This script (sophomorix-bind) is maintained by Rüdiger Beck
# It is Free Software (License GPLv3)
# If you find errors, contact the author
# jeffbeck@web.de  or  jeffbeck@gmx.de


# ????? binds nicht automatisch anlegen/nur dirs (option in sophomorix-devel.conf)
# ????? man page anlegen
# add more performant --quick


# Bibliotheken
use strict;
use Getopt::Long;
use Sophomorix::SophomorixConfig;
use Sophomorix::SophomorixBase;
use Sophomorix::SophomorixAPI;
use Sophomorix::SophomorixPgLdap;
Getopt::Long::Configure ("bundling");
use DBI;
use Sophomorix::SophomorixPgLdap qw(show_modulename
                                   );

my @arguments = @ARGV;

# Scriptname ermitteln
my @list = split(/\//,$0);
my $scriptname = pop @list;

$Conf::log_level=1;
my $help=0;
my $info=0;
my $cron=0;
my $user="";
my $homedir="";
my $host="";
my $login=0; 
my $logout=0;
my $command_log=0;
my $quick=0;


# config
my $seconds_delay=600;

###############################################################################
# Beginn
###############################################################################

# Parsen der Optionen
my $testopt=GetOptions(
           "help|h" => \$help,
           "info|i" => \$info,
           "cron" => \$cron,
           "command-log" => \$command_log,
           "login" => \$login,
           "logout" => \$logout,
           "quick" => \$quick,
           "verbose|v+" => \$Conf::log_level,
           "host:s" => \$host,
           "user:s" => \$user,
           "homedir:s" => \$homedir,
          );


# Prüfen, ob Optionen erkannt wurden
&check_options($testopt);
if ($login==1 and $logout==1 ){
    print "\n Use --login OR --logout\n\n";
    exit;
}
if ($quick==1 and $login==0 and $logout==0 ){
    print "\n Option --quick can only be used with --login or --logout\n\n";
    exit;
}


# --help
if ($help==1) {
   # Befehlbeschreibung
   print "\n$scriptname creates bind mounts to share directories",
         "\non samba login or logout(Replaces links)\n";

   print('
Options
  -h  / --help
  -v  / --verbose
  -vv / --verbose --verbose
  -i / --info
     Show filesystems mounted by sophomorix-bind
  --cron 
     Umount all filesystems mounted by sophomorix-bind
  --login --user username
     Mount all filesystems for the user username
  --logout --user username
     Umount all filesystems for the user username
  --homedir /homedir/of/user
  --host host
  --command-log
     Enable logging to the sophomorix command logging file
     (this is for debugging only)
  --quick
     Do only necessary stuff on login/logout to achieve better performance.
    

Please see the sophomorix-bind(8) man pages for full documentation
');
   print "\n";
   exit;
}



# --cron / --info
if ($cron==1 or $info==1){
    # log to command.log
    if ($cron==1){
        &log_script_start(@arguments);
    }
    if ($info==1){
        print "The following filesystems would be umounted with option --cron:\n";
    } elsif ($cron==1){
        print "Executing the following commands to umount filesystems:\n";
        if (-e ${DevelConf::sophomorix_bind_log}){
            system("rm $DevelConf::sophomorix_bind_log");
        }
    }
    # umount all bind mounted stuff 
    my @filesystems = Sys::Filesystem->filesystems();
    foreach my $fs (@filesystems){
        if ($fs=~/^\/home\// # start with /home/
            and (
              $fs=~/\/${Language::share_dir}/ # contain /__tauschen 
              or 
              $fs=~/\/${Language::task_dir}/ # contain /__vorlagen
              or 
              $fs=~/\/${Language::inspection_dir}/ # contain /_schueler
                )
           )
        {
            if ($info==1){
                print "   $fs\n";
            } 
            if ($cron==1){
	        my $command = "umount $fs";
                print "  $command\n";
                system($command);
            }
        }
    }
    if ($cron==1){
        &log_script_end(@arguments);
    } else {
        exit;
    }
}




############################################################
# mountin/umounting on login/logout
############################################################

if ($command_log==1){
    &log_script_start(@arguments);
}

# in Unix-Zeit
my $epoche=0;
$epoche=time;
if($Conf::log_level>=2){
    print "User:    $user\n";
    print "Homedir: $homedir\n";
    print "Host:    $host\n";
    print "Time:    $epoche\n";
    print "Logfile: $DevelConf::sophomorix_bind_log\n";

}
if ($login==1 and $logout==0 and $user ne ""){
    ########## --login ##########
    print "Type:    LOGIN of $user from $host\n";
    if ($host eq "127.0.0.1"){
        # horde: redo everything after n number of seconds
        my $last_time=&get_last_time($user);
        my $renew_time = $last_time + $seconds_delay;
        my $seconds_to_go = $renew_time - $epoche;
        if ($seconds_to_go < 0){
            print "  * Updating links on login from $host ($seconds_to_go to go)\n";
            &login($user);
            &set_last_time($user,$epoche);
        } else {
            print "  * Doing nothing on login from $host ($seconds_to_go to go )\n";
        }
    } else {
        # run login script
        &login($user);
    }
} elsif ($login==0 and $logout==1 and $user ne ""){
    ########## --logout ##########
    print "Type:    LOGOUT of $user\n";
    if ($host eq "127.0.0.1"){
        ### horde, ... do NOT unbind
        print "  * Doing nothing on logout from $host\n";
    } else {
        ### run logout script
        &logout($user);
    }
} else {
    # options not correctly used
    print "\nWrong Options used.\n\n  Please use option --help/-h\n\n";
    if ($command_log==1){
        &log_script_exit("Wrong Options used",1,1,0,@arguments);
    } else {
        exit;
    }
}



if ($command_log==1){
    &log_script_end(@arguments);
}






############################################################
# subs
############################################################

sub login {
    my ($user) = @_;
    if ($quick==0){
        my $command="/usr/sbin/sophomorix-repair".
                    " --user $user --repair-binds \"\"";
        print "  * $command\n";
        system($command);
    } else {
        my $command="/usr/sbin/sophomorix-repair --quick".
                    " --user $user --repair-binds \"\"";
        print "  * $command\n";
        system($command);
    }
}



sub logout {
    my ($user) = @_;
    if ($quick==0){
        my $command="/usr/sbin/sophomorix-repair --user $user".
                    " --delete-binds \"\"";
        print "  * $command\n";
        system($command);
    } else {
        my $command="/usr/sbin/sophomorix-repair --quick --user".
                    " $user --delete-binds \"\"";
        print "  * $command\n";
        system($command);
    }
}



sub get_last_time {
    my ($user) = @_;
    my $log_time = 0;
    if (not -f ${DevelConf::sophomorix_bind_log}){
        system("touch ${DevelConf::sophomorix_bind_log}");
    }
    open(LOG, "${DevelConf::sophomorix_bind_log}") || die "Fehler: $!";
    while(<LOG>){
        chomp();
        my ($user_log,$log)=split(/::/);
        if ($user_log eq $user){
            $log_time=$log;
            #print "$user logged at $log\n";
        }
    }
    close(LOG);
    print "Last log was at $log_time\n";
    return $log_time;
}



sub set_last_time {
    # append line to logfile
    my ($user,$date) = @_;
    my $entry = $user."::".$date."\n";
    print "Updating db (${DevelConf::sophomorix_bind_log}) with entry:\n$entry\n";
    open(BINDLOG,">>${DevelConf::sophomorix_bind_log}");
    print BINDLOG $entry;
    close(BINDLOG);
}


