#! /usr/local/bin/sperl

#
# This requires that the environment variable BU_HOST be set to the host 
# that is being backed up, and BU_DIRECTORY is the name of the directory. 
#
# Ewww, gross.  This is a helper script for backing up sybase 
# databases with the osu-cis backup system.  It takes 1 argument on the
# command line - one of "start", "stop" or "setup".
#
# Using the system: create a sybase user MrBackup with some password.
# Make sure that $backup_user and $backup_password (see below) match
# your values.  Create a directory somewhere on a file system that
# sybase will be able to write, with enough space to hold database dumps
# of all of your databases.  It should (probably) be owned by sybase,
# group "backup", mode 770.  Change the value of $ddb_dir below to
# match.
#
# You'll need to install this script somewhere - I just put mine in the
# script directory with the rest of the backup system.  It needs to be
# run with perl that includes sybase support - we have that installed as
# sperl, so I compiled and installed a separate version of the wrapper
# program that has PERL set to /usr/local/bin/sperl and made a symlink
# sybase=helper that points at that.
#
# "sybase-helper setup" deletes and then recreates the dump devices that
# will be used to backup each of the databases.  Each dump device name
# starts with "ddb_" - this prefix shouldn't be used by any other dump
# devices, else they will be deleted and recreated, probably
# incorrectly.  This also makes a half hearted attempt to add the backup
# user to each of the known databases.  You will need to run this once
# to set things up, and then again when you add/delete databases or
# change the location of the database dump directory ($ddb_dir).
#
# To use the script for backups, list $ddb_dir in your /etc/backups
# file, like this:
#
#  /n/archive/0/sybbackup gtar script=/usr/local/utils/nbu/sybase-helper.
#
# When that backup is run, it will first run "sybase-helper stop", which
# will do a "dump database" of each known database to the backup
# directory.  Then it will run gtar to back that up, and finally it will
# run "sybase-helper start" which will delete all of the database dumps
# to reclaim space.

require 'global.defs';
require 'local.defs';

$prefix = "ddb_";

@nul = ('not null','null');
@sysdb = ('master', 'model', 'tempdb');

$usage = "usage: sybase-backup start | stop | setup
  'stop' uses 'dump database' to back each database up.  This is 
  usually run by the backup system, see backups(5) for details.

  'start' deletes the dump files.  This is usually run by the
  backup system, see backups(5) for details.

  'setup' is intended to be run by hand - be prepared to give it
  the Sybase sa password.  It creates the dump devices and ensures 
  that the backup user has permission to run dump database.  Run it 
  when you add/delete databases or move the directory where the 
  dumps are written to.\n";

require "sybperl.pl";
require "sybdb.ph";
require "sql.pl";
require "yagrip.pl";

$what = shift;

if ($what eq "setup") {
    $| = 0;
    print "What host are you setting up? ";
    chop($client_host = <STDIN>);
    print "What is the backup directory? ";
    chop($client_directory = <STDIN>);
    $| = 1;
} else {
    $client_host = $ENV{"BU_HOST"};
    $client_directory = $ENV{"BU_DIRECTORY"};
}

$ddb_dir = $client_directory;

if (! defined($sybase_backup_user{"$client_host:$client_directory"})) {
    die "You must define appropriate entries for $client_host:$client_directory\nin global.defs!\n";
}

$backup_user = $sybase_backup_user{"$client_host:$client_directory"};
$backup_password = $sybase_backup_password{"$client_host:$client_directory"};
if ($sybase_backup_dsquery{"$client_host:$client_directory"} ne "") {
    $ENV{"DSQUERY"} = $sybase_backup_dsquery{"$client_host:$client_directory"};
}

if ($what eq "stop" || $what eq "setup") {
    &setup_or_dump_databases();
} elsif ($what eq "start") {
    &cleanup();
} else {
    die $usage;
}


sub setup_or_dump_databases {
    if ($what eq "setup") {
	$who = "sa";
	$password = "";
    } else {
	$who = $backup_user;
	$password = $backup_password;
    }

    if ($password eq "") {
	$| = 1;
	print "password for $who: ";
	chop($password = <STDIN>);
    }

    $dbproc = &dblogin($who, $password);	# Login to sybase
    &dbmsghandle ("sql_message_handler"); # Some user defined error handlers
    &dberrhandle ("sql_error_handler");

    &my_sql($dbproc, "use master\n");

    #
    # Get the names of all the databases
    #
    &drop_em_all($dbproc) if $what eq "setup";

    @database_names = &my_sql($dbproc, "select name from master..sysdatabases\n", "\t");
    foreach $db (@database_names) {
	print $db, "\n";
	if ($what eq "setup") {
	    &create_device($dbproc, "$prefix$db", "$ddb_dir/$prefix$db");
	    &my_sql($dbproc, "use $db\n", "\t");
#	    &my_sql($dbproc, "if not exists (select name from sysusers where name = \"$backup_user\") sp_adduser $backup_user\n", "\t");
	    &my_sql($dbproc, "grant dump database to $backup_user\n", "\t");
	} else {
	    &my_sql($dbproc, "dump database $db to $prefix$db\n", "\t");
	}
    }

    &dbexit;

    exit(0);
}

sub cleanup {
    local($number_deleted);

    chdir($ddb_dir) || die "can't chdir to $ddb_dir ($!)\n";
    $number_deleted = unlink <ddb_*>;
    warn "couldn't remove any files: $!\n" if $number_deleted == 0;
    exit(0);
}

sub my_sql {
    local($db, $cmd, $sep) = @_;

    print $cmd if $verbose;
    &sql($db, $cmd, $sep);
}

sub drop_device {
    local($dbproc, $name) = @_;

    &my_sql($dbproc, "sp_dropdevice $name\n", "\t");
}

sub create_device {
    local($dbproc, $name, $path) = @_;

    &my_sql($dbproc, "sp_addumpdevice \"disk\", $name, \"$path\", 2\n", "\t");
}

sub drop_em_all {
    local($dbproc) = @_;
    local($db, @names);

    @names = &my_sql($dbproc, "select name from master..sysdevices\n", "\t");
    foreach $db (@names) {
	if ($db =~ m/^$prefix/) {
	    print "$db: ";
	    &drop_device($dbproc, $db);
	}
    }
}
