# This file was automatically generated by SWIG (http://www.swig.org).
# Version 1.3.39
#
# Do not make changes to this file unless you know what you are doing--modify
# the SWIG interface file instead.

package Amanda::Util;
use base qw(Exporter);
use base qw(DynaLoader);
package Amanda::Utilc;
bootstrap Amanda::Util;
package Amanda::Util;
@EXPORT = qw();

# ---------- BASE METHODS -------------

package Amanda::Util;

sub TIEHASH {
    my ($classname,$obj) = @_;
    return bless $obj, $classname;
}

sub CLEAR { }

sub FIRSTKEY { }

sub NEXTKEY { }

sub FETCH {
    my ($self,$field) = @_;
    my $member_func = "swig_${field}_get";
    $self->$member_func();
}

sub STORE {
    my ($self,$field,$newval) = @_;
    my $member_func = "swig_${field}_set";
    $self->$member_func($newval);
}

sub this {
    my $ptr = shift;
    return tied(%$ptr);
}


# ------- FUNCTION WRAPPERS --------

package Amanda::Util;

*get_original_cwd = *Amanda::Utilc::get_original_cwd;
*sanitise_filename = *Amanda::Utilc::sanitise_filename;
*quote_string = *Amanda::Utilc::quote_string;
*unquote_string = *Amanda::Utilc::unquote_string;
*set_pname = *Amanda::Utilc::set_pname;
*set_ptype = *Amanda::Utilc::set_ptype;
*set_pcontext = *Amanda::Utilc::set_pcontext;
*safe_cd = *Amanda::Utilc::safe_cd;
*check_running_as = *Amanda::Utilc::check_running_as;

# ------- VARIABLE STUBS --------

package Amanda::Util;

*RUNNING_AS_ANY = *Amanda::Utilc::RUNNING_AS_ANY;
*RUNNING_AS_ROOT = *Amanda::Utilc::RUNNING_AS_ROOT;
*RUNNING_AS_DUMPUSER = *Amanda::Utilc::RUNNING_AS_DUMPUSER;
*RUNNING_AS_DUMPUSER_PREFERRED = *Amanda::Utilc::RUNNING_AS_DUMPUSER_PREFERRED;
*RUNNING_AS_CLIENT_LOGIN = *Amanda::Utilc::RUNNING_AS_CLIENT_LOGIN;
*RUNNING_AS_UID_ONLY = *Amanda::Utilc::RUNNING_AS_UID_ONLY;
*CONTEXT_DEFAULT = *Amanda::Utilc::CONTEXT_DEFAULT;
*CONTEXT_CMDLINE = *Amanda::Utilc::CONTEXT_CMDLINE;
*CONTEXT_DAEMON = *Amanda::Utilc::CONTEXT_DAEMON;
*CONTEXT_SCRIPTUTIL = *Amanda::Utilc::CONTEXT_SCRIPTUTIL;

@EXPORT_OK = ();
%EXPORT_TAGS = ();

use Amanda::Debug qw(:init);
use Amanda::Config qw(:getconf);
use Carp;
use POSIX qw( :fcntl_h strftime );

=head1 NAME

Amanda::Util - Runtime support for Amanda applications

=head1 Application Initialization

Application initialization generally looks like this:

  use Amanda::Config qw( :init );
  use Amanda::Util qw( :constants );
  use Amanda::Debug;

  Amanda::Util::setup_application("myapp", "server", $CONTEXT_CMDLINE);
  # .. command-line processing ..
  Amanda::Config::config_init(...);
  Amanda::Util::finish_setup($RUNNING_AS_DUMPUSER);

=over

=item C<setup_application($name, $type, $context)>

Set up the operating environment for an application, without requiring any
configuration.

C<$name> is the name of the application, used in log messages, etc.  C<$type>
is usualy one of "server" or "client".  It specifies the subdirectory in which
debug logfiles will be created.  C<$context> indicates the usual manner in
which this application is invoked; one of C<$CONTEXT_CMDLINE> for a
user-invoked command-line utility (e.g., C<amadmin>) which should send
human-readable error messages to stderr; C<$CONTEXT_DAEMON> for a program
started by C<amandad>, e.g., C<sendbackup>; or C<$CONTEXT_SCRIPTUTIL> for a
small program used from shell scripts, e.g., C<amgetconf>

Based on C<$type> and C<$context>, this function does the following:

=over

=item *

sets up debug logging;

=item *

configures internationalization

=item *

sets the umask;

=item *

sets the current working directory to the debug or temporary directory;

=item *

closes any unnecessary file descriptors as a security meaasure;

=item *

ignores C<SIGPIPE>; and

=item *

sets the appropriate target for error messages.

=back

=cut

# private package variables
my $_pname;
my $_ptype;
my $_pcontext;

sub setup_application {
    my ($name, $type, $context) = @_;

    # sanity check
    croak("no name given") unless ($name);
    croak("no type given") unless ($type);
    croak("no context given") unless ($context);

    # store these as perl values
    $_pname = $name;
    $_ptype = $type;
    $_pcontext = $context;

    # and let the C side know about them too
    set_pname($name);
    set_ptype($type);
    set_pcontext($context);

    safe_cd(); # (also sets umask)
    check_std_fds();

    # set up debugging, now that we have a name, type, and context
    debug_init();

    # ignore SIGPIPE
    $SIG{'PIPE'} = 'IGNORE';
}

=item C<finish_setup($running_as_flags)>

Perform final initialization tasks that require a loaded configuration.
Specifically, move the debug log into a configuration-specific
subdirectory, and check that the current userid is appropriate for
this applciation.

The user is specified by one of the following flags, which are
available in export tag C<:check_running_as_flags>:

  $RUNNING_AS_ANY                 # any user is OK
  $RUNNING_AS_ROOT                # root
  $RUNNING_AS_DUMPUSER            # dumpuser, from configuration
  $RUNNING_AS_DUMPUSER_PREFERRED  # dumpuser, but client_login is OK too
  $RUNNING_AS_CLIENT_LOGIN        # client_login (--with-user at build time)

If the flag C<$RUNNING_AS_UID_ONLY> is bit-or'd into C<$running_as_flags>, then
the euid is ignored; this is used for programs that expect to be setuid-root.

=cut

sub finish_setup {
    my ($running_as) = @_;

    my $config_name = Amanda::Config::get_config_name();

    if ($config_name) {
	dbrename($config_name, $_ptype);
    }

    check_running_as($running_as);
}

=item C<get_original_cwd()>

Return the original current directory with C<get_original_cwd>.

=cut

push @EXPORT_OK, qw(get_original_cwd);
push @{$EXPORT_TAGS{"util"}}, qw(get_original_cwd);

=head1 Miscellaneous Utilities

=item C<safe_env()>

Return a "safe" environment hash.  For non-setuid programs, this means filtering out any
localization variables.

=cut

sub safe_env {
    my %rv = %ENV;

    delete @rv{qw(IFS CDPATH ENV BASH_ENV LANG)};

    # delete all LC_* variables
    for my $var (grep /^LC_/, keys %rv) {
        delete $rv{$var};
    }

    return %rv;
}


push @EXPORT_OK, qw(running_as_flags_to_strings);
push @{$EXPORT_TAGS{"running_as_flags"}}, qw(running_as_flags_to_strings);

my %_running_as_flags_VALUES;
#Convert a flag value to a list of names for flags that are set.
sub running_as_flags_to_strings {
    my ($flags) = @_;
    my @result = ();

    for my $k (keys %_running_as_flags_VALUES) {
	my $v = $_running_as_flags_VALUES{$k};

	#is this a matching flag?
	if (($v == 0 && $flags == 0) || ($v != 0 && ($flags & $v) == $v)) {
	    push @result, $k;
	}
    }

#by default, just return the number as a 1-element list
    if (!@result) {
	return ($flags);
    }

    return @result;
}

push @EXPORT_OK, qw($RUNNING_AS_ANY);
push @{$EXPORT_TAGS{"running_as_flags"}}, qw($RUNNING_AS_ANY);

$_running_as_flags_VALUES{"RUNNING_AS_ANY"} = $RUNNING_AS_ANY;

push @EXPORT_OK, qw($RUNNING_AS_ROOT);
push @{$EXPORT_TAGS{"running_as_flags"}}, qw($RUNNING_AS_ROOT);

$_running_as_flags_VALUES{"RUNNING_AS_ROOT"} = $RUNNING_AS_ROOT;

push @EXPORT_OK, qw($RUNNING_AS_DUMPUSER);
push @{$EXPORT_TAGS{"running_as_flags"}}, qw($RUNNING_AS_DUMPUSER);

$_running_as_flags_VALUES{"RUNNING_AS_DUMPUSER"} = $RUNNING_AS_DUMPUSER;

push @EXPORT_OK, qw($RUNNING_AS_DUMPUSER_PREFERRED);
push @{$EXPORT_TAGS{"running_as_flags"}}, qw($RUNNING_AS_DUMPUSER_PREFERRED);

$_running_as_flags_VALUES{"RUNNING_AS_DUMPUSER_PREFERRED"} = $RUNNING_AS_DUMPUSER_PREFERRED;

push @EXPORT_OK, qw($RUNNING_AS_CLIENT_LOGIN);
push @{$EXPORT_TAGS{"running_as_flags"}}, qw($RUNNING_AS_CLIENT_LOGIN);

$_running_as_flags_VALUES{"RUNNING_AS_CLIENT_LOGIN"} = $RUNNING_AS_CLIENT_LOGIN;

push @EXPORT_OK, qw($RUNNING_AS_UID_ONLY);
push @{$EXPORT_TAGS{"running_as_flags"}}, qw($RUNNING_AS_UID_ONLY);

$_running_as_flags_VALUES{"RUNNING_AS_UID_ONLY"} = $RUNNING_AS_UID_ONLY;

#copy symbols in running_as_flags to constants
push @{$EXPORT_TAGS{"constants"}},  @{$EXPORT_TAGS{"running_as_flags"}};

push @EXPORT_OK, qw(pcontext_t_to_string);
push @{$EXPORT_TAGS{"pcontext_t"}}, qw(pcontext_t_to_string);

my %_pcontext_t_VALUES;
#Convert an enum value to a single string
sub pcontext_t_to_string {
    my ($enumval) = @_;

    for my $k (keys %_pcontext_t_VALUES) {
	my $v = $_pcontext_t_VALUES{$k};

	#is this a matching flag?
	if ($enumval == $v) {
	    return $k;
	}
    }

#default, just return the number
    return $enumval;
}

push @EXPORT_OK, qw($CONTEXT_DEFAULT);
push @{$EXPORT_TAGS{"pcontext_t"}}, qw($CONTEXT_DEFAULT);

$_pcontext_t_VALUES{"CONTEXT_DEFAULT"} = $CONTEXT_DEFAULT;

push @EXPORT_OK, qw($CONTEXT_CMDLINE);
push @{$EXPORT_TAGS{"pcontext_t"}}, qw($CONTEXT_CMDLINE);

$_pcontext_t_VALUES{"CONTEXT_CMDLINE"} = $CONTEXT_CMDLINE;

push @EXPORT_OK, qw($CONTEXT_DAEMON);
push @{$EXPORT_TAGS{"pcontext_t"}}, qw($CONTEXT_DAEMON);

$_pcontext_t_VALUES{"CONTEXT_DAEMON"} = $CONTEXT_DAEMON;

push @EXPORT_OK, qw($CONTEXT_SCRIPTUTIL);
push @{$EXPORT_TAGS{"pcontext_t"}}, qw($CONTEXT_SCRIPTUTIL);

$_pcontext_t_VALUES{"CONTEXT_SCRIPTUTIL"} = $CONTEXT_SCRIPTUTIL;

#copy symbols in pcontext_t to constants
push @{$EXPORT_TAGS{"constants"}},  @{$EXPORT_TAGS{"pcontext_t"}};

=item C<quote_string($str)>

Quote a string using Amanda's quoting algorithm.  Strings with no whitespace,
control, or quote characters are returned unchanged.  An empty string is
represented as the two-character string C<"">.  Otherwise, tab, newline,
carriage return, form-feed, backslash, and double-quote (C<">) characters are
escaped with a backslash and the string is surrounded by double quotes.

=item C<unquote_string($str)>

Unquote a string as quoted with C<quote_string>.

=item C<skip_quoted_string($str)>

my($q, $remaider) = skip_quoted_string($str)

Return the first quoted string and the remainder of the string.

Both C<quote_string>, C<unquote_string> and C<skip_quoted_string> are
available under the export tag C<:quoting>.

=cut

sub skip_quoted_string {
    my $str = shift;

    chomp $str;
    my $iq = 0;
    my $i = 0;
    my $c = substr $str, $i, 1;
    while ($c ne "" && !($iq == 0 && $c =~ /\s/)) {
	if ($c eq '"') {
	    $iq = !$iq;
	} elsif ($c eq '\\') {
	    $i++;
	}
	$i++;
	$c = substr $str, $i, 1;
    }
    my $quoted_string = substr $str, 0, $i;
    my $remainder     = substr $str, $i+1;

    return ($quoted_string, $remainder);
}


push @EXPORT_OK, qw(quote_string unquote_string skip_quoted_string sanitise_filename);
push @{$EXPORT_TAGS{"quoting"}}, qw(quote_string unquote_string skip_quoted_string sanitise_filename);

=item C<generate_timestamp()>

Generate a timestamp from the current time, obeying the 'USETIMESTAMPS'
config parameter.  The Amanda configuration must already be loaded.

=cut

sub generate_timestamp {
    # this corresponds to common-src/timestamp.c's get_proper_stamp_from_time
    if (getconf($CNF_USETIMESTAMPS)) {
	return strftime "%Y%m%d%H%M%S", localtime;
    } else {
	return strftime "%Y%m%d", localtime;
    }
}

sub check_std_fds {
    fcntl(STDIN, F_GETFD, 0) or critical("Standard input is not open");
    fcntl(STDOUT, F_GETFD, 0) or critical("Standard output is not open");
    fcntl(STDERR, F_GETFD, 0) or critical("Standard error is not open");
}

=back

=cut
1;
