#!/usr/bin/perl
#
# Module: vyatta-reboot.pl
# 
# **** License ****
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
# 
# 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.
# 
# This code was originally developed by Vyatta, Inc.
# Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc.
# All Rights Reserved.
# 
# Author: Stig Thormodsrud
# Date: May 2008
# Description: Script to reboot or schedule a reboot
# 
# **** End License ****
#

use lib "/opt/vyatta/share/perl5/";
use Getopt::Long;
use POSIX;
use IO::Prompt;
use Sys::Syslog qw(:standard :macros);

use strict;
use warnings;

my $reboot_job_file = '/var/run/reboot.job';


sub parse_at_output {
    my @lines = @_;
    
    foreach my $line (@lines) {
	if ($line =~ /error/) {
	    return (1, '', '');
	} elsif ($line =~ /job (\d+) (.*)$/) {
	    return (0, $1, $2);
	} 
    }
    return (1, '', '');
}

sub is_reboot_pending {

    if ( ! -f $reboot_job_file) {
	return (0, '');
    }
    my $job = `cat $reboot_job_file`;
    chomp $job;
    my $line = `atq $job`;
    if ($line =~ /\d+\s+(.*)\sa root$/) {
	return (1, $1);
    } else {
	return (0, '');
    }
}

sub do_reboot {
    my $login = shift;

    syslog("warning", "Reboot now requested by $login");
    exec("sudo /sbin/reboot");
}

sub cancel_reboot {
    my ($login, $time) = @_;

    my $job = `cat $reboot_job_file`;
    chomp $job;
    system("atrm $job");
    system("rm $reboot_job_file");
    syslog("warning", "Reboot scheduled for [$time] - CANCELED by $login");
}

#
# main
#
my ($action, $at_time, $now);
GetOptions("action=s"  => \$action,
	   "at_time=s" => \$at_time,
           "now!"      => \$now,
);

if (! defined $action) {
    die "no action specified";
} 

openlog($0, "", LOG_USER);
my $login = getlogin() || getpwuid($<) || "unknown";

#
# reboot
#
if ($action eq "reboot") {

    my ($rc, $time) = is_reboot_pending();
    if ($rc) {
        if (defined $now) {
            cancel_reboot($login, $time);
            do_reboot($login);
        } else {
            print "Reboot already scheduled for [$time]\n";
            exit 1;
        }
    }

    if (defined $now) {
        do_reboot($login);
    } else {
        if (prompt("Proceed with reboot? [confirm]", -y1d=>"y")) {
            do_reboot($login);
        } else {
            print "Reboot canceled\n";
            exit 1;
        }
    }
}

#
# reboot_at
#
if ($action eq "reboot_at") {
    if (! -f '/usr/bin/at') {
	die "Package [at] not installed";
    }

    if (! defined $at_time) {
	die "no at_time specified";
    }

    my ($rc, $rtime) = is_reboot_pending();
    if ($rc) {
	print "Reboot already scheduled for [$rtime]\n";
	exit 1;
    }

    #
    # check if the time format is valid, then
    # remove that job
    #
    my @lines = `echo true | at $at_time 2>&1`;
    my ($err, $job, $time) = parse_at_output(@lines);
    if ($err) {
	print "Invalid time format [$at_time]\n";
	exit 1;
    }
    system("atrm $job");

    print "\nReload scheduled for $time\n\n";
    if (! prompt("Proceed with reboot schedule? [confirm]", -y1d=>"y")) {
	print "Reboot canceled\n";
	exit 1;
    }

    @lines = `echo sudo /sbin/reboot | at $at_time 2>&1`;
    ($err, $job, $time) = parse_at_output(@lines);
    if ($err) {
	print "Error: unable to schedule reboot\n";
	exit 1;
    }
    system("echo $job > $reboot_job_file");
    print "\nReboot scheduled for $time\n";
    syslog("warning", "Reboot scheduled for [$time] by $login");

    exit 0;
}

#
# reboot_cancel
#
if ($action eq "reboot_cancel") {

    my ($rc, $time) = is_reboot_pending();
    if (! $rc) {
	print "No reboot currently scheduled\n";
	exit 1;
    }
    cancel_reboot($login, $time);
    print "Reboot canceled\n";
    exit 0;
}

#
# show_reboot
#
if ($action eq "show_reboot") {

    my ($rc, $time) = is_reboot_pending();
    if ($rc) {
	print "Reboot scheduled for [$time]\n";
	exit 0;
    } else {
	print "No reboot currently scheduled\n";
    }
    exit 1;
}

exit 1;

# end of file