Here is Adsm.pm - a perl method for interfacing with *SM from within perl.  Look at the
bottom of the code to see how to use it.

I used it on AIX for ADSM 3.x. I believe that for NT/W2k, you'll need to somehow spoof
the .dsmrc. I'm just starting to get into this on NT, so I don't have the answer yet. 
Let
me know if you already know how to do this.

Regards
# Adsm.pm - A class for interfacing with an ADSM server
#
# by Owen Crow <[EMAIL PROTECTED]>
#
# POD documentation is at the end of the file

package Adsm;

use strict;
use Carp;

BEGIN {
        use vars       qw($VERSION);
        # if using RCS/CVS, this next line may be preferred,
        # but beware two-digit versions.
        $VERSION = (qw$Revision: 0.1 $)[1];
}

sub new {
  my $proto = shift;
  my $class = ref($proto) || $proto;
  my $self = {};
  $self->{id} = shift;
  $self->{pa} = shift;
  if ((! defined($self->{id}) or ! defined($self->{pa})) and
    (exists $ENV{HOME} && -e "$ENV{HOME}/.dsmrc"))
  {
    # This branch is used when the user has a ~/.dsmrc file with the
    # id and password
    my ($mode, $uid)=(stat _)[2,4];
    die "$ENV{HOME}/.dsmrc must be owned by you" if ($uid != $<);
    die "$ENV{HOME}/.dsmrc must have perms of 600 or 400"
      if ( (oct("000477") & $mode) ne oct("000400") );
    open DSMRC,"$ENV{HOME}/.dsmrc"
      or die "Error opening $ENV{HOME}/.dsmrc to read id and password: $!";
    while (<DSMRC>) {
      chomp($self->{id} = $1) if (!defined($self->{id}) and m/^ID\s+(.*)$/);
      chomp($self->{pa} = $1) if (!defined($self->{pa}) and m/^PA\s+(.*)$/);
    }
    close DSMRC or die "Error closing $ENV{HOME}/.dsmrc: $!";
  }
  if (! defined($self->{id}) or ! defined($self->{pa})) {
    if ( -t STDIN ) {
      # This branch is used when STDIN is a terminal (interactively)
      my $stty = `stty`;
      if ( !defined($self->{id}) ) {
        print "Enter your user id:  ";
        chomp($self->{id}=<STDIN>);
      }
      if ( !defined($self->{pa}) ) {
        # Turn off echoing of characters for the password entry (only in UNIX)
        `stty -echo`;
        print "Enter password for $self->{id}: ";
        chomp($self->{pa}=<STDIN>);
        `stty echo` if $stty =~ m/[^-]echo\b/;
        print "\n";
      }
    } else {
      # Last effort is to read the ID and password from stdin
      chomp($self->{id} = <STDIN>);
      chomp($self->{pa} = <STDIN>);
    }
  }
  bless($self, $class);
  return $self;
}

# dsmadmc accepts a list as its argument. The list is joined with spaces
# to form the command submitted to adsm
sub dsmadmc(@) {
  my $self = shift;
  my $command = join " ",@_;
  my (
    $flag,      # flag to signal the beginning of output
    $more,      # true if line = "more..."
    $output,    # contains output of dsmadmc command
    $rc,        # return code
    $stty,      # stty output (for turning echo on and off)
  );

  $output="";
  $flag="";
  $rc=0;

  open(DSM,"dsmadmc -ID=$self->{id} -PA=$self->{pa} $command </dev/null |");
  while (<DSM>) {
    # Capture return code from output of dsmadmc. Did I miss any other
    # messages which contain the return code?
    if (m/^(ANS5103I|ANS5102I|ANS8002I).*?(\d+)\.$/) {
      $rc=$2;
      last;
    }
    # Wait for the flag and skip empty lines
    # Skip any lines starting with "more..."
    if( $flag ) {
        $more = (m/^more\.\.\./) ? 1 : 0;
        $output.=$_ if (!$more);
    }
    # Set the flag on the message which contains the command issued
    $flag=1 if m/^(ANS5101I|ANS8000I)/;
  }
  # Don't check return code from DSM because it will often be non-zero
  while (<DSM>) {
    1;
  }
  close(DSM);
  $?=$rc;       # set return code
  $output;      # return the output as string with multiple lines
}

sub dsmconsole() {
  my $self = shift;

  open(DSM,"dsmadmc -ID=$self->{id} -PA=$self->{pa} -console |");
  \*DSM;

}

END { }       # module clean-up code here (global destructor)

1;            # modules must return true

__END__

=head1 NAME

Adsm - A class which provides methods for sending commands and receiving
output from an IBM ADSM backup server

=head1 SYNOPSIS

    use Adsm;

    $dsm   = Adsm->new[("ID" [, "Password"] )];

    $output = $dsm->dsmadmc("administrative command");
    $return_code = $?;
    $foreach $line ( split( /\n/, $output ) ) { ...

    $dsmfh = $dsm->dsmconsole();
    while (<$dsmfh>) { ...

=head1 DESCRIPTION

The Adsm class implements a set of methods for interacting with IBM's
backup server ADSTAR Distributed Storage Manager.

Using the Adsm class provides the following benefits:

=over 4

=item Standardized, more secure access to IDs and Passwords

IDs and Passwords can be stored in $HOME/.dsmrc, entered via the terminal,
or piped into the script utilizing the Adsm class depending on the needs
of the script.  The .dsmrc file must be owned by the executor of the script
and must have restrictive permissions so no normal user can access the
file.

=item Removes extraneous output from ADSM commands

The name of the program, copywrite and other similar information is
removed from the output stream to simplify parsing of output by user
scripts.

=back

=head1 USAGE

First, include the Adsm class:

    use Adsm;

To create an Adsm object, use:

    $dsm = Adsm->new;

During the construction of the object, the ID and Password are acquired.  If
they are not in the $HOME/.dsmrc file, they are read from the terminal or
STDIN.  If read from a terminal (interactively), a prompt is provided for
each item.  No prompts are issued for non-interactive sessions.

If only the ID is provided in the .dsmrc file, the user will be prompted
for the password.

The format of the .dsmrc file is provided under L<FILES>.

To issue a command via dsmadmc, use:

    $output = $dsm->dsmadmc("command");

$output will contain the filtered output of the command as one string with
newlines.  The return code is stored in $? as with system calls.

To open a console session with dsmadmc, use:

    $dsmfh = $dsm->dsmconsole;

$dsmfh will contain a reference to a filehandle which is a pipe from the
"dsmadmc -console" command.

=head1 FILES

=head2 $HOME/.dsmrc

The .dsmrc file contains key/value pairs for the administrative ID and
password to use in ADSM.  The keys are case-insensitive.  Capitalized
letters in the following key definitions indicate the required letters
for the key:

=over 4

=item ID userid

Defines the ADSM ID as "userid"

=item PAssword password

Defines the ADSM password as "password"

=back

Only the first instance of ID or PA is used.

=head1 ENVIRONMENT

HOME gives the home directory of the user executing the script.  Used to
find the .dsmrc file.

=head1 TODO

Lots!

=over 4

=item Provide more secure password entry?

The ID and Password are removed from the command line listing in `ps`
output on my system.  If this is not universal, I will probably implement
the dsmadmc() method using Open2 instead.

=item Provide object class to hold volume [devclass, policy, management
class, etc.] information.

Probably would be nice to implement objects for each type of data, but
sounds like a lot of work.

=item Provide dsmc method

Since I have never had to provide a password along with dsmc, this is
not a priority.

=cut

Reply via email to