MINI MINI MANI MO

Path : /opt/oracle/product/18c/dbhomeXE/lib/
File Upload :
Current File : //opt/oracle/product/18c/dbhomeXE/lib/asmcmdug.pm

# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
#
#    NAME
#      asmcmdug - ASM CoMmanD line interface (users and groups)
#
#    DESCRIPTION
#      This module is a dummy/sample module that provides a working 
#      template for module additions.
#
#    NOTES
#      usage: asmcmdcore [-p] [command]
#
#    MODIFIED  (MM/DD/YY)
#    anovelo    10/24/16 - 24706236: Update call to asmcmdshare_get_subdirs
#    diguzman   05/30/16 - 19654070: Little change at _no_instance_cmd routine
#    dacavazo   05/04/16 - Add -R and --filter options to chmod
#    diguzman   07/22/15 - 11736372: expand * wildcard in chmod command
#    shlian     04/16/15 - 20721939: double quote user and passwd in sql stmt
#    dacavazo   03/10/15 - 20657441: trim DBD ERROR from trace for
#                          asmcmdug_process_orapwusr, asmcmdug_process_passwd
#    dacavazo   01/21/15 - Showing user as <user>@<cluster> if cluster user
#    ykatada    10/03/14 - #19617921: use bind variables to SELECTs
#    pvenkatr   02/05/14 - Bug # 18163398 - Processing a list of matching
#                          files.
#    pvenkatr   08/30/13 - #13535543 - support to retain existing privileges in
#                          orapwusr.
#    manuegar   05/08/13 - Bug13951456 Support bind parameters
#    pvenkatr   02/01/13 - using asmcmdshare_filter_invisible_cmds
#    mchimang   12/24/12 - XbranchMerge mchimang_bug-15895228_2 from
#                          st_rdbms_12.1.0.1
#    pvenkatr   04/20/12 - Bug #13964467 - changed splitting username/group in
#                          chown.
#    pvenkatr   03/06/12 - Bug 13813189 - check for error on modify user.
#    shmubeen   12/26/11 - bug fix# for 13518852, change in orapwusr function
#    pvenkatr   12/11/11 - Bug 13479282: SQL Syntax in ORAPWUSR.
#    pvenkatr   08/24/11 - Removed flags hash table - using from XML
#    adileepk   06/20/11 - Connection Pooling.
#    kwoseo     01/11/11 - add command rpusr
#    adileepk   11/08/10 - Adding changes to integrate the parser module with
#                          asmcmd.
#    moreddy    05/06/10 - bug 8667038 NLS for error messages
#    amitroy    04/21/10 - BUG 8933243 - USE DIFFERENT CHARACTER IN ASMCMD TO
#                          "HIDE COLUMN DETAILS" INSTEAD OF -H
#    pvenkatr   03/31/10 - Syntax, description, example - all from XML
#    moreddy    03/22/10 - Adding more tracing
#    moreddy    01/18/10 - Adding tracing messages
#    pvenkatr   09/03/09 - Help message from xml file
#    sanselva   07/07/09 - fix --privilege flag in GetOptions for orapwusr
#    sanselva   06/24/09 - fix help text msg for orapwusr,grpmod
#    sanselva   04/27/09 - add diskgroup filter in 'groups' command,remove
#                          -R from chmod,chgrp,chown & handle incorrect alias
#    sanselva   04/06/09 - ASMCMD long options and consistency
#    heyuen     03/23/09 - add rmusr -r
#    heyuen     10/14/08 - use dynamic modules
#    heyuen     09/10/08 - use dgname for lsusr
#    heyuen     07/28/08 - use command properties array
#    heyuen     05/22/08 - fix lsgrp
#    heyuen     04/30/08 - bug 6994254: supress aditional error messages
#    heyuen     04/22/08 - add order to lsusr and lsgrp
#    heyuen     04/15/08 - reorder help messages
#    heyuen     03/30/08 - add passwd
#    heyuen     03/11/08 - rename to mkusr, mkug, rmusr, rmug, chug
#    heyuen     02/12/08 - change help messages
#    heyuen     09/20/07 - creation
#
#############################################################################
#
############################ Functions List #################################
#
# asmcmdug_init
# asmcmdug_process_cmd 
# asmcmdug_process_help 
# asmcmdug_is_cmd 
# asmcmdug_is_wildcard_cmd 
# asmcmdug_is_no_instance_cmd 
# asmcmdug_parse_int_args 
# asmcmdug_syntax_error 
# asmcmdug_get_cmd_syntax 
# asmcmdug_get_asmcmd_cmds 
# asmcmdug_process_lsusr
# asmcmdug_process_mkgrp
# asmcmdug_process_rmgrp
# asmcmdug_process_mkusr
# asmcmdug_process_rmusr
# asmcmdug_process_lsgrp
# asmcmdug_process_chown
# asmcmdug_process_chmod
# asmcmdug_process_chgrp
# asmcmdug_process_grpmod
# asmcmdug_process_orapwusr
# asmcmdug_process_lspwusr
# asmcmdug_process_rpusr
#############################################################################

package asmcmdug;
require Exporter;
our @ISA    = qw(Exporter);
our @EXPORT = qw(asmcmdug_init
                 );

use strict;
use DBI qw(:sql_types);
use Getopt::Long qw(:config no_ignore_case bundling);
use asmcmdglobal;
use asmcmdshare;
use asmcmdbase;
use asmcmdparser;
use asmcmdexceptions;

use List::Util qw[min max];

####################### ASMCMDTMPL Global Constants ######################
# ASMCMD Column Header Names:
# Below are the names of the column headers for lstmpl.
our (%asmcmdug_lsusr_header) = ('dgname'         , 'DG_Name',
                                'user_number'    , 'User_Num',
                                'compound_index' , 'Cmpnd_Idx',
                                'incarnation'    , 'Incarn',
                                'os_id'          , 'OS_ID',
                                'os_name'        , 'OS_Name'
                               );


our (%asmcmdug_lsgrp_header) = ('dgname'         , 'DG_Name',
                                'name'           , 'Grp_Name',
                                'member'         , 'Member',
                                'owner'          , 'Owner',
                                'members'        , 'Members'
                               );

our (%asmcmdug_lspwusr_header) = ('username',    'Username',
                                  'sysdba',      'sysdba',
                                  'sysoper',     'sysoper',
                                  'sysasm',      'sysasm'
                                 );

####################### ASMCMDTMPL Global Variables ######################
our (%asmcmdug_cmds) = ( lsusr     => {},
                         mkgrp     => {},
                         rmgrp     => {},
                         mkusr     => {},
                         rmusr     => {},
                         rpusr     => {},
                         lsgrp     => {},
                         chown     => {},
                         chmod     => {},
                         chgrp     => {},
                         grpmod    => {},
                         groups    => {},
                         orapwusr  => {},
                         lspwusr   => {},
                         passwd    => {}
                       );

sub is_asmcmd
{
  return 1;
}

########
# NAME
#   asmcmdug_init
#
# DESCRIPTION
#   This function initializes the asmcmdug module.  For now it simply 
#   registers its callbacks with the asmcmdglobal module.
#
# PARAMETERS
#   None
#
# RETURNS
#   Null
#
# NOTES
#   Only asmcmdcore_main() calls this routine.
########
sub init
{
  # All of the arrays defined in the asmcmdglobal module must be
  # initialized here.  Otherwise, an internal error will result.
  push (@asmcmdglobal_command_callbacks, \&asmcmdug_process_cmd);
  push (@asmcmdglobal_help_callbacks, \&asmcmdug_process_help);
  push (@asmcmdglobal_command_list_callbacks, \&asmcmdug_get_asmcmd_cmds);
  push (@asmcmdglobal_is_command_callbacks, \&asmcmdug_is_cmd);
  push (@asmcmdglobal_is_wildcard_callbacks, \&asmcmdug_is_wildcard_cmd);
  push (@asmcmdglobal_syntax_error_callbacks, \&asmcmdug_syntax_error);
  push (@asmcmdglobal_no_instance_callbacks, \&asmcmdug_is_no_instance_cmd);
  %asmcmdglobal_cmds = (%asmcmdglobal_cmds, %asmcmdug_cmds);

  #Perform ASMCMD consistency check if enabled
  if($asmcmdglobal_hash{'consistchk'} eq 'y')
  {
     if(!asmcmdshare_check_option_consistency(%asmcmdug_cmds))
     {
       exit 1;
     }
  }
}

########
# NAME
#   asmcmdug_process_cmd
#
# DESCRIPTION
#   This routine calls the appropriate routine to process the command 
#   specified by $asmcmdglobal_hash{'cmd'}.
#
# PARAMETERS
#   dbh       (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   1 if command is found in the asmcmdug module; 0 if not.
#
# NOTES
#   Only asmcmdcore_shell() calls this routine.
########
sub asmcmdug_process_cmd 
{
  my ($dbh) = @_;
  my ($succ) = 0;

  # Get current command from global value, which is set by 
  # asmcmdug_parse_asmcmd_args()and by asmcmdcore_shell().
  my ($cmd) = $asmcmdglobal_hash{'cmd'};

  # Declare and initialize hash of function pointers, each designating a 
  # routine that processes an ASMCMDUG command.
  my (%cmdhash) = ( lsusr         => \&asmcmdug_process_lsusr,
                    mkgrp         => \&asmcmdug_process_mkgrp,
                    rmgrp         => \&asmcmdug_process_rmgrp,
                    mkusr         => \&asmcmdug_process_mkusr,
                    rmusr         => \&asmcmdug_process_rmusr,
                    rpusr         => \&asmcmdug_process_rpusr,
                    lsgrp         => \&asmcmdug_process_lsgrp,
                    chown         => \&asmcmdug_process_chown,
                    chmod         => \&asmcmdug_process_chmod,
                    chgrp         => \&asmcmdug_process_chgrp,
                    grpmod        => \&asmcmdug_process_grpmod,
                    groups        => \&asmcmdug_process_groups,
                    orapwusr      => \&asmcmdug_process_orapwusr,
                    lspwusr       => \&asmcmdug_process_lspwusr,
                    passwd        => \&asmcmdug_process_passwd);


  if (defined ( $cmdhash{ $cmd } ))
  {    # If user specifies a known command, then call routine to process it. #
    $cmdhash{ $cmd }->($dbh);
    $succ = 1;
  }

  return $succ;
}


########
# NAME
#   asmcmdug_process_help
#
# DESCRIPTION
#   This function is the help function for the ASMCMDUG module.
#
# PARAMETERS
#   command     (IN) - display the help message for this command.
#
# RETURNS
#   1 if command found; 0 otherwise.
########
sub asmcmdug_process_help 
{
  my ($command) = shift;       # User-specified argument; show help on $cmd. #
  my ($desc);                                # Command description for $cmd. #
  my ($succ) = 0;                         # 1 if command found, 0 otherwise. #

  if (asmcmdug_is_cmd ($command)) 
  {                              # User specified a command name to look up. #
    $desc = asmcmdshare_get_help_desc($command);
    asmcmdshare_print "$desc\n";
    $succ = 1;
  }

  return $succ;
}


########
# NAME
#   asmcmdug_is_cmd
#
# DESCRIPTION
#   This routine checks if a user-entered command is one of the known
#   ASMCMD internal commands that belong to the ASMCMDUG module.
#
# PARAMETERS
#   arg   (IN) - user-entered command name string.
#
# RETURNS
#   True if $arg is one of the known commands, false otherwise.
########
sub asmcmdug_is_cmd 
{
  my ($arg) = shift;

  return defined ( $asmcmdug_cmds{ $arg } );
}


########
# NAME
#   asmcmdug_is_wildcard_cmd
#
# DESCRIPTION
#   This routine determines if an ASMCMDUG command allows the use 
#   of wild cards.
#
# PARAMETERS
#   arg   (IN) - user-entered command name string.
#
# RETURNS
#   True if $arg is a command that can take wildcards as part of its argument, 
#   false otherwise.
########
sub asmcmdug_is_wildcard_cmd 
{
  my ($arg) = shift;
  # Empty hash; no ASMCMDUG command supports wildcards. # 

  return defined ($asmcmdug_cmds{ $arg }) &&
         (asmcmdshare_get_cmd_wildcard($arg) eq "true");
}


########
# NAME
#   asmcmdug_is_no_instance_cmd
#
# DESCRIPTION
#   This routine determines if a command can run without an ASM instance.
#
# PARAMETERS
#   arg   (IN) - user-entered command name string.
#
# RETURNS
#   1 if $arg is a command that can run without an ASM instance or it does not
#   belong to this module
#   0 if $arg is a command that needs to connect to an ASM instance
#   -1 if $arg is a command that may use an ASM instance.
#
# NOTES
#   The asmcmdug module currently supports no command that can run 
#   without an ASM instance.
########
sub asmcmdug_is_no_instance_cmd 
{
  my ($arg) = shift;
  my ($rc);

  return 1 unless defined($asmcmdug_cmds{$arg});

  $rc = asmcmdshare_get_cmd_noinst($arg);
  if ($rc eq "true")
  {
    return 1;
  }
  elsif ($rc eq "undef")
  {
    return -1;
  }

  return 0;
}


########
# NAME
#   asmcmdug_parse_int_args
#
# DESCRIPTION
#   This routine parses the arguments for flag options for ASMCMDUG 
#   internal commands.  
#
# PARAMETERS
#   cmd      (IN)  - user-entered command name string.
#   args_ref (OUT) - hash of user-specified flag options for a command, 
#                    populated by getopts().
#
# RETURNS
#   Zero on success; undefined on error.
#
# NOTES
#   $cmd must already be verified as a valid ASMCMDUG internal command.
########
sub asmcmdug_parse_int_args 
{
  my ($cmd, $args_ref) = @_;
  my ($key);
  my (@string);

  #include deprecated options if any
  if($asmcmdglobal_deprecated_options{ $cmd })
  {
    foreach my $key(keys %{$asmcmdglobal_deprecated_options{ $cmd }})
    {
      push(@string, $asmcmdglobal_deprecated_options{$cmd}{$key}[0]);
    }
  }

  # Use asmcmdparser_parse_issued_command() from the asmcmdparser package to parse arguments for
  # internal commands.  These arguments are stored in @ARGV.
  if (!asmcmdparser_parse_issued_command($cmd, $args_ref, \@string))
  {
    # Print correct command format if syntax error. #
    asmcmdug_syntax_error($cmd);
    return undef;
  }
  return 0;
}


########
# NAME
#   asmcmdug_syntax_error
#
# DESCRIPTION
#   This function prints the correct syntax for a command to STDERR, used 
#   when there is a syntax error.  This function is responsible for 
#   only ASMCMDUG commands.
#
# PARAMETERS
#   cmd   (IN) - user-entered command name string.
#
# RETURNS
#   1 if the command belongs to this module; 0 if command not found.
#
# NOTES
#   These errors are user-errors and not internal errors.  They are of type
#   record, not signal.  
# 
#   N.B. Functions in this module can call this function directly, without
#   calling the asmcmdshare::asmcmdshare_syntax_error equivalent.  The
#   latter is used only by the asmcmdcore module.
########
sub asmcmdug_syntax_error 
{
  my ($cmd) = shift;
  my ($cmd_syntax);                               # Correct syntax for $cmd. #
  my ($succ) = 0;

  # display syntax only for commands from this module.
  if(asmcmdug_is_cmd($cmd))
  {
    $cmd_syntax = asmcmdshare_get_help_syntax($cmd);  # Get syntax for $cmd. #
    $cmd_syntax = asmcmdshare_trim_str ($cmd_syntax);   # Trim blank spaces #

    if (defined ($cmd_syntax))
    {
      asmcmdshare_printstderr 'usage: ' . $cmd_syntax . "\n";
      asmcmdshare_printstderr 'help:  help ' . $cmd . "\n";
      $succ = 1;
    }
  }

  return $succ;
}


########
# NAME
#   asmcmdug_get_asmcmd_cmds
#
# DESCRIPTION
#   This routine constructs a string that contains a list of the names of all 
#   ASMCMD internal commands and returns this string.
#
# PARAMETERS
#   None.
#
# RETURNS
#   A string contain a list of the names of all ASMCMD internal commands.
#
# NOTES
#   Used by the help command and by the error command when the user enters
#   an invalid internal command.
#
#   IMPORTANT: the commands names must be preceded by eight (8) spaces of
#              indention!  This formatting is mandatory.
########
sub asmcmdug_get_asmcmd_cmds 
{
  return asmcmdshare_filter_invisible_cmds(%asmcmdug_cmds);
}


########
# NAME
#   asmcmdug_process_lsusr
#
# DESCRIPTION
#   This function processes the asmcmd command lstmpl.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_lsusr
{
  my ($dbh) = @_;
  my (%args);
  my ($ret);
  my ($dgname, $headers, $gnum, $pattern);
  my (@what, @from, $sth, $qry, @where, @order, @binds, @tmp_cols);
  my (@usr_list);
  my ($row, $k, $v, $h);
  my (@eargs);
  my (%min_col_wid, $print_format, $print_string, @what_print);

  # Get option parameters, if any.
  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  #Set the correct options if deprecated options were used and print WARNING.
  asmcmdshare_handle_deprecation($asmcmdglobal_hash{'cmd'},\%args);

  # print headers?
  $headers = defined($args{'suppressheader'});

  # get disk group name
  if (defined($args{'G'}))
  {
    $dgname = $args{'G'};
    $gnum = asmcmdshare_get_gnum_from_gname($dbh, $dgname);
    if (!defined($gnum))
    {
      @eargs = ($dgname);
      asmcmdshare_error_msg(8001, \@eargs);
      return;
    }
    push (@where, 'v$asm_diskgroup.group_number = ?');
    push (@binds, [$gnum, SQL_INTEGER]);
  }
  else
  {
    push (@what, 'v$asm_diskgroup.name as dgname');
  }

  # get pattern
  if (defined($args{'lsusr'}))
  {
    my ($like_pattern);

    ($pattern) = @{$args{'lsusr'}};
    $pattern =~ s,$ASMCMDGLOBAL_WCARD_CHARS,\%,g;
    $like_pattern = '%' . $pattern . '%';

    push (@where, 'v$asm_user.os_name like ?');
    push (@binds, [$like_pattern, SQL_VARCHAR]);
  }

  push (@what, 'v$asm_user.user_number as user_number');
  push (@what, 'v$asm_user.os_id as os_id');
  push (@what, '(v$asm_user.os_name || \'@\' || v$asm_user.cluster_id) '.
               'as os_name');

  push (@from, 'v$asm_user');
  push (@from, 'v$asm_diskgroup');

  #join
  push (@where, 'v$asm_user.group_number = v$asm_diskgroup.group_number');

  #order
  push (@order, 'v$asm_user.group_number');
  push (@order, 'v$asm_user.os_name');

  $sth = asmcmdshare_do_construct_select($dbh, \@what, \@from, \@where,
                                         \@order, \@binds);

  @tmp_cols = @{$sth->{NAME}};

  @what = ();
  foreach (@tmp_cols)
  {
    push (@what, "\L$_");
  }

  #initialize the min_col_wid array
  foreach(@what)
  {
    $min_col_wid{$_} = length($asmcmdug_lsusr_header{$_});
  }

  #get the rows
  while (defined($row = asmcmdshare_fetch($sth)))
  {
    my(%usr_info) = ();

    while(($k,$v) = each(%{$row}))
    {
      $k =~ tr/[A-Z]/[a-z]/;
      $v = ' ' if (!defined($v));
      $v =~ s/\@$//g if ($k eq 'os_name');
      $usr_info{$k}    = $v;
      $min_col_wid{$k} = max($min_col_wid{$k}, length($v));
    }

    push (@usr_list, \%usr_info);
  }
  asmcmdshare_finish($sth);

  #create print format
  $print_format = '';

  foreach (@what)
  {
    $print_format .= "%-" . $min_col_wid{$_} . "s ";
  }
  $print_format .= "\n";

  #print header
  if (!defined ($args{'suppressheader'}) )
  {
    @what_print = ();
    foreach (@what)
    {
      push (@what_print, $asmcmdug_lsusr_header{$_});
    }
    $print_string = sprintf($print_format, @what_print);
    asmcmdshare_print($print_string);
  }

  #print rows
  foreach $h (@usr_list)
  {
    @what_print = ();
    foreach (@what)
    {
      push (@what_print, $h->{$_});
    }
    $print_string = sprintf($print_format, @what_print);
    asmcmdshare_print($print_string);
  }
}


########
# NAME
#   asmcmdug_process_mkgrp
#
# DESCRIPTION
#   This function processes the asmcmd command mkgrp.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_mkgrp
{
  my ($dbh) = @_;
  my (%args);
  my ($ret);
  my ($sth, $qry);
  my ($dgname, $grpname);
  my (@usrs);

  # Get option parameters, if any.
  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  $dgname = shift(@{$args{'mkgrp'}});
  $grpname = shift(@{$args{'mkgrp'}});

  # get the users
  foreach (@{$args{'mkgrp'}})
  {
    push (@usrs, "\'".$_."\'");
  }

  $qry = "alter diskgroup " . $dgname . " add usergroup \'" . $grpname . "\'";

  if (@usrs)
  {
    $qry .= " with member " . join(',', @usrs);
  }

  $ret = asmcmdshare_do_stmt($dbh, $qry);
}


########
# NAME
#   asmcmdug_process_rmgrp
#
# DESCRIPTION
#   This function processes the asmcmd command rmgrp.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_rmgrp
{
  my ($dbh) = @_;
  my (%args);
  my ($ret);
  my ($sth, $qry, $dgname);
  my ($grpname);

  # Get option parameters, if any.
  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  ($dgname, $grpname) = @{$args{'rmgrp'}};

  $qry = "alter diskgroup " . $dgname . " drop usergroup \'" . $grpname . "\'";

  $ret = asmcmdshare_do_stmt($dbh, $qry);
}


########
# NAME
#   asmcmdug_process_mkusr
#
# DESCRIPTION
#   This function processes the asmcmd command mkusr.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_mkusr
{
  my ($dbh) = @_;
  my (%args);
  my ($ret);
  my ($sth, $qry, $dgname);
  my ($username);

  # Get option parameters, if any.
  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  ($dgname, $username) = @{$args{'mkusr'}};

  $qry = "alter diskgroup " . $dgname . " add user \'" . $username ."\'";

  $ret = asmcmdshare_do_stmt($dbh, $qry);
}


########
# NAME
#   asmcmdug_process_rmusr
#
# DESCRIPTION
#   This function processes the asmcmd command rmusr.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_rmusr
{
  my ($dbh) = @_;
  my (%args);
  my ($ret);
  my ($sth, $qry, $dgname);
  my ($username);

  # Get option parameters, if any.
  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  ($dgname, $username) = @{$args{'rmusr'}};

  $qry = "alter diskgroup " . $dgname . " drop user \'" . $username . "\'";

  if (defined($args{'r'}))
  {
    $qry .= ' cascade';
  }

  $ret = asmcmdshare_do_stmt($dbh, $qry);
}

########
# NAME
#   asmcmdug_process_rpusr
#
# DESCRIPTION
#   This function processes the asmcmd command rpusr.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_rpusr
{
  my ($dbh) = @_;
  my (%args);
  my ($ret, $qry);
  my ($dgname, $username1, $username2);

  # Get option parameters, if any.
  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  # get disk group name and user names
  ($dgname, $username1, $username2) = @{$args{'rpusr'}};

  $qry = "alter diskgroup " . $dgname . " replace user "; 
  $qry .= "\'" . $username1 . "\' with \'" . $username2 . "\'";

  $ret = asmcmdshare_do_stmt($dbh, $qry);
}


########
# NAME
#   asmcmdug_get_users
#
# DESCRIPTION
#   This function gets the users given a diskgroup name and a usergroup name.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#
########
sub asmcmdug_get_users
{
  my ($dbh, $gname, $ugname) = @_;
  my ($gnum, $ugnum);
  my (@what, @where, @from, @order, @binds);
  my ($sth, $row, $res);

  $gnum = asmcmdshare_get_gnum_from_gname($dbh, $gname);
  return if (!defined($gnum));

  $ugnum = asmcmdshare_get_ugnum_from_ugname($dbh, $gnum, $ugname);
  return if (!defined($ugnum));

  push (@what, 'v$asm_user.os_name as os_name');
  push (@what, 'v$asm_user.cluster_id as cluster_id');

  push (@from, 'v$asm_user');
  push (@from, 'v$asm_usergroup_member');

  push (@where, 'v$asm_user.group_number = ?');
  push (@binds, [$gnum, SQL_INTEGER]);

  push (@where, 'v$asm_usergroup_member.group_number = ?');
  push (@binds, [$gnum, SQL_INTEGER]);

  push (@where, 'v$asm_usergroup_member.usergroup_number = ?');
  push (@binds, [$ugnum, SQL_INTEGER]);

  push (@where, 'v$asm_usergroup_member.group_number = v$asm_user.group_number');
  push (@where, 'v$asm_usergroup_member.member_number = v$asm_user.user_number');

  push (@order, 'v$asm_user.os_name');

  $sth = asmcmdshare_do_construct_select($dbh, \@what, \@from, \@where,
                                         \@order, \@binds);

  $res = '';
  while (defined($row = asmcmdshare_fetch($sth)))
  {
    $res .= $row->{'OS_NAME'};
    $res .= '@'.$row->{'CLUSTER_ID'} if (defined($row->{'CLUSTER_ID'}));
    $res .= ' ';
  }
  asmcmdshare_finish($sth);

  return $res;
}

########
# NAME
#   asmcmdug_process_lsgrp
#
# DESCRIPTION
#   This function processes the asmcmd command lsgrp.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_lsgrp
{
  my ($dbh) = @_;
  my (%args);
  my ($ret);
  my ($dgname, $headers, $gnum, $pattern);
  my (@what, @from, $sth, $qry, @where, @order, @binds);
  my (@tmp_cols);
  my ($row, $k, $v, $h);
  my (@eargs);
  my (%min_col_wid, $print_format, $print_string, @what_print, @grp_list);

  # Get option parameters, if any.
  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  #Set the correct options if deprecated options were used and print WARNING.
  asmcmdshare_handle_deprecation($asmcmdglobal_hash{'cmd'},\%args);

  # filter disk group
  if (defined($args{'G'}))
  {
    $dgname = $args{'G'};
    $gnum = asmcmdshare_get_gnum_from_gname($dbh, $dgname);
    if (!defined($gnum))
    {
      @eargs = ($dgname);
      asmcmdshare_error_msg(8001, \@eargs);
      return;
    }
    push (@where, 'v$asm_usergroup.group_number = ?');
    push (@binds, [$gnum, SQL_INTEGER]);
  }

  # filter user group
  if (defined($args{'lsgrp'}))
  {
    ($pattern) = @{$args{'lsgrp'}};
    push (@where, 'v$asm_usergroup.name like ?');
    push (@binds, [$pattern, SQL_VARCHAR]);
  }

  push (@what, 'v$asm_diskgroup.name as dgname');
  push (@what, 'v$asm_usergroup.name');
  push (@what, '(u.os_name || \'@\' || u.cluster_id) as owner');

  push (@from, 'v$asm_usergroup');
  push (@from, 'v$asm_diskgroup');
  push (@from, 'v$asm_user u');        #owner

  #join
  push (@where, 'u.user_number = v$asm_usergroup.owner_number');
  push (@where, 'u.group_number = v$asm_diskgroup.group_number');
  push (@where, 'v$asm_usergroup.group_number = v$asm_diskgroup.group_number');

  #order
  push (@order, 'v$asm_usergroup.name');

  $sth = asmcmdshare_do_construct_select($dbh, \@what, \@from, \@where,
                                         \@order, \@binds);

  @tmp_cols = @{$sth->{NAME}};

  @what = ();
  foreach (@tmp_cols)
  {
    push (@what, "\L$_");
  }

  #initialize the min_col_wid array
  foreach(@what)
  {
    $min_col_wid{$_} = length($asmcmdug_lsgrp_header{$_});
  }

  if (defined($args{'a'}))
  {
    $min_col_wid{'members'} = length($asmcmdug_lsgrp_header{'members'});
  }

  while (defined($row = asmcmdshare_fetch($sth)))
  {
    my(%grp_info) = ();
    while(($k,$v) = each(%{$row}))
    {
      $k =~ tr/[A-Z]/[a-z]/;
      $v =~ s/\@$//g if ($k eq 'owner');
      $grp_info{$k}    = $v;

      $min_col_wid{$k} = max($min_col_wid{$k}, length($v));
    }

    if (defined($args{'a'}))
    {
      $v = asmcmdug_get_users($dbh, $grp_info{'dgname'}, $grp_info{'name'});
      $grp_info{'members'} = $v;

      $min_col_wid{'members'} = max($min_col_wid{'members'}, length($v));
    }

    push (@grp_list, \%grp_info);
  }
  asmcmdshare_finish($sth);

  if (defined($args{'a'}))
  {
    push (@what, 'members');
  }

  #create print format
  $print_format = '';

  foreach (@what)
  {
    $print_format .= "%-" . $min_col_wid{$_} . "s  ";
  }
  $print_format .= "\n";

  #print header
  if (!defined ($args{'suppressheader'}) )
  {
    @what_print = ();
    foreach (@what)
    {
      push (@what_print, $asmcmdug_lsgrp_header{$_});
    }
    $print_string = sprintf($print_format, @what_print);
    asmcmdshare_print($print_string);
  }

  #print rows
  foreach $h (@grp_list)
  {
    @what_print = ();
    foreach (@what)
    {
      push (@what_print, $h->{$_});
    }
    $print_string = sprintf($print_format, @what_print);
    asmcmdshare_print($print_string);
  }
}


########
# NAME
#   asmcmdug_process_chown
#
# DESCRIPTION
#   This function processes the asmcmd command chown.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_chown
{
  my ($dbh) = @_;
  my (%args);
  my ($ret);
  my ($sth, $qry, $dgname);
  my ($strperm, $strwho, $alphabet, $oper, $inst, @files);
  my ($owner, $group);
  my (@eargs);
  my (%norm);

  # Get option parameters, if any.
  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  #-R not implemented

  $owner = shift(@{$args{'chown'}});

  foreach (@{$args{'chown'}})
  {
    push (@files, $_);
  }

  ($owner, $group) = split(/\:/,$owner);

  foreach (@files)
  {
    if ($_ =~ m/(\w+)[\/]?.*/)
    {

      #Normalize path and fetch the grp and file_number
      %norm = asmcmdshare_normalize_path($dbh, $_, 0, \$ret);

      if($ret != 0)
      {
          @eargs = ($_);
          asmcmdshare_error_msg(8014, \@eargs);
          asmcmdshare_trace(1, $DBI::errstr, 'y', 
                       'y') if(defined($DBI::errstr));
          next;#continue with next file
      }

      $dgname = (split(/\//, $norm{'path'}->[0]))[0];
      $dgname =~s/\+//g;


      $qry = "alter diskgroup " . $dgname . " set ownership ";
      $qry .= " owner=\'" . $owner . "\'";
      if (defined($group))
      {
        $qry .= ", group=\'" . $group . "\'";
      }
      $qry .= " for file \'" . $norm{'path'}->[0] . "\'";

      eval
      {
         $ret = asmcmdshare_do_stmt($dbh, $qry);
      };
      if (asmcmdexceptions::catch())
      {
        @eargs = ($_);
        asmcmdshare_error_msg(8402, \@eargs);
        # After printing the error message propogate the exception up
        asmcmdexceptions::throw("asmcmdexceptions");
      }
    }
    else
    { 
      @eargs = ($_);
      asmcmdshare_error_msg(8014, \@eargs); 
      asmcmdshare_trace(1, $DBI::errstr, 'y', 'y') if(defined($DBI::errstr));
    }
  }
}


########
# NAME
#   asmcmdug_process_chmod
#
# DESCRIPTION
#   This function processes the asmcmd command chmod.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_chmod
{
  my ($dbh) = @_;
  my (%args);
  my ($ret);
  my ($sth, $qry, $dgname);
  my ($strperm, $strwho, $alphabet, $oper, $inst, @files);
  my (@sqlperm);
  my ($x, $ct);
  my (@eargs);
  my (%norm);
  my (@info);
  my ($qry_perm, $fnum, $fname, $row, $end_perm, $gnum);
  my ($req_perm);
  my ($not_digit) = 0;
  my ($i, $file);

  use warnings qw/FATAL all/;

  # Get option parameters, if any.
  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  $inst = shift(@{$args{'chmod'}});

  # Process each path
  foreach my $path (@{$args{'chmod'}})
  {
    # See if path is valid. Get all paths if $path contains a wildcard.
    %norm = asmcmdshare_normalize_path($dbh, $path, 0, \$ret);
    next if ($ret == -1);

    for ($i = 0; $i < @{$norm{'path'}}; $i++)
    {
      my (@match);
      if ($args{'R'})
      {
        # Find all files and directories recursively in the given directory
        @match = asmcmdbase_find_sql($dbh, $path, '*', undef, undef, 0, 0);
      }

      if (@match == 0)
      {
        # Add path if it matches the filter
        push(@files, $norm{'path'}->[$i]) if (!defined($args{'filter'}) ||
                                     $norm{'path'}->[$i] =~ /$args{'filter'}/);
      }
      else
      {
        # This is a directory, so iterate through all files in it
        foreach my $item (@match)
        {
          # Add path if it matches the filter
          push(@files, $item->{'full_path'})
               if ($item->{'alias_directory'} ne 'Y' &&
                   (!defined($args{'filter'}) ||
                    $item->{'full_path'} =~ /$args{'filter'}/));
        }
      }
    }
  }

  # Check if it is in 3 digit format
  if ($inst =~ m/\d{3}/ && length($inst) == 3)
  {
    my (@perm);

    if ($inst =~ m/(0|4|6)/)
    {
      @perm = split('', $inst);

      push(@sqlperm, "owner=read write") if ($perm[0] == 6);
      push(@sqlperm, "owner=read only")  if ($perm[0] == 4);
      push(@sqlperm, "owner=none")  if ($perm[0] == 0);

      push(@sqlperm, "group=read write") if ($perm[1] == 6);
      push(@sqlperm, "group=read only")  if ($perm[1] == 4);
      push(@sqlperm, "group=none")  if ($perm[1] == 0);

      push(@sqlperm, "other=read write") if ($perm[2] == 6);
      push(@sqlperm, "other=read only")  if ($perm[2] == 4);
      push(@sqlperm, "other=none")  if ($perm[2] == 0);
    }
    else
    {
      asmcmdug_syntax_error($asmcmdglobal_hash{'cmd'});
      return;
    }
  }
  elsif ($inst =~ m/^(.*)(\+|\-)(r|w|rw|wr)$/) # Permissions in ug+r/w format
  {
    $not_digit =1;
    if (defined($1))             # we are setting it to someone other than all
    {
      $strwho = join('', sort(split('', $1)));    #sort the string
    }
    else
    {
      $strwho = "gou";
    }

    $oper = "add" if ($2 eq '+');
    $oper = "del" if ($2 eq '-');

    $req_perm = $3;
    $req_perm = 'rw' if($req_perm eq 'wr');

    $x = $strwho;

    $x =~ s/[^agou]//g;              #remove invalid characters
    if ($x ne $strwho)
    {
      asmcmdug_syntax_error($asmcmdglobal_hash{'cmd'});
      return;
    }

    #now look for repetitions of the valid characters
    if ( ($x =~ tr/a/a/) > 1 )          # excess of a
    {
      asmcmdug_syntax_error($asmcmdglobal_hash{'cmd'});
      return;
    }

    if ( ($x =~ tr/u/u/) > 1 )          # excess of u
    {
      asmcmdug_syntax_error($asmcmdglobal_hash{'cmd'});
      return;
    }

    if ( ($x =~ tr/g/g/) > 1 )          # excess of g
    {
      asmcmdug_syntax_error($asmcmdglobal_hash{'cmd'});
      return;
    }

    if ( ($x =~ tr/o/o/) > 1 )          # excess of o
    {
      asmcmdug_syntax_error($asmcmdglobal_hash{'cmd'});
      return;
    }

    if ( $strwho =~ tr/a/a/ )
    {
      $strwho = "gou";
    }
  }
  else
  {
    asmcmdug_syntax_error($asmcmdglobal_hash{'cmd'});
    return;
  }
 
  my %hash   = map { $_ => 1 } @files;
  @files = keys %hash;

  foreach (@files)
  {
    if ($_ =~ m/(\w+)[\/]?.*|^\*$/)
    {
      #$dgname = $1;

      #If not in numeric format
      $fname =(split(/\//, $_))[-1];

      #Normalize path and fetch the grp and file_number
      %norm = asmcmdshare_normalize_path($dbh, $_, 0, \$ret);

      if($ret != 0)
      {
        @eargs = ($_);
        asmcmdshare_error_msg(8014, \@eargs);
        asmcmdshare_trace(1, $DBI::errstr, 'y', 
                           'y') if(defined($DBI::errstr));
        next;#continue with next file
      }

      for ($i = 0; $i < @{$norm{'path'}}; $i++)
      {
        $file = $norm{'path'}->[$i];

        $dgname = (split(/\//, $file))[0];         # diskgroup 
        $dgname =~s/\+//g;
        $file =~ s,.*/([^/]+)$,$1,;   # Get last level of path for name.

        if($not_digit == 1)
        {
          undef @info; # Clear previous file info
          # Retrieve the file perms and make sure that after granting requested
          # we do not end up in write only

          # Retrieve the unique file number given the parent_id,reference_id,
          # group_number and filename
          asmcmdshare_get_subdirs($dbh, \@info, undef, $norm{'gnum'}->[$i],
                $norm{'ref_id'}->[$i],$norm{'par_id'}->[$i],$file, undef, 0, 
                0);

          # Skip alias directories
          if ($info[0]->{'alias_directory'} eq 'Y')
          {
            @eargs = ($file);
            asmcmdshare_error_msg(8402, \@eargs);
            next;
          }

          $fnum = $info[0]->{'file_number'};
          $gnum = $norm{'gnum'}->[0];

          if(!defined($fnum))
          {
             @eargs = ($file);
             asmcmdshare_error_msg(8014, \@eargs);
             asmcmdshare_trace(1, $DBI::errstr, 'y', 
                                            'y') if(defined($DBI::errstr));
             next;
          }

          $qry_perm ="select permissions from v\$asm_file where 
                       file_number=? and group_number=?";
          eval
          {
            $sth = asmcmdshare_do_prepare($dbh, $qry_perm);
            $sth->bind_param(1,$fnum);
            $sth->bind_param(2,$gnum);
            asmcmdshare_do_execute($sth);
          };
          if(asmcmdexceptions::catch())
          {
             @eargs = ($file);
             asmcmdshare_error_msg(8014, \@eargs);
             next;
          }

          $row = asmcmdshare_fetch($sth);
          asmcmdshare_finish($sth);
          if(!defined($row))
          {
             @eargs = ($file);
             asmcmdshare_error_msg(8014, \@eargs);
             asmcmdshare_trace(1, $DBI::errstr, 'y', 
                                    'y') if(defined($DBI::errstr));
             next;
          }

          #user,group and other permissions
          my $user = substr($row->{'PERMISSIONS'},0,2);
          $user =~s/-//g;

          my $group = substr($row->{'PERMISSIONS'},3,2);   
          $group =~s/-//g;

          my $other = substr($row->{'PERMISSIONS'},6,2);
          $other  =~s/-//g;

          #check if operation can be allowed to user
          if ( $strwho =~ tr/u/u/ )
          {
             if(asmcmdug_chmod_get_end_perm($user,$req_perm,$oper,\$end_perm))
             {
                push( @sqlperm, "owner=" . $end_perm );
             }
             else
             {
                @eargs = ($_);
                asmcmdshare_error_msg(8409, \@eargs);
                asmcmdshare_trace(1, $DBI::errstr, 'y',
                                       'y') if(defined($DBI::errstr));
                return;
             }
          }
          #check if operation can be allowed to group
          if ( $strwho =~ tr/g/g/ )
          {
            if(asmcmdug_chmod_get_end_perm($group,$req_perm,$oper,\$end_perm))
            {
               push( @sqlperm, "group=" . $end_perm ) ;
            }
            else
            {
               @eargs = ($_);
               asmcmdshare_error_msg(8409, \@eargs);
               asmcmdshare_trace(1, $DBI::errstr, 'y', 
                                            'y') if(defined($DBI::errstr));
               return;
            }
          }
          #check if operation can be allowed to other
          if ( $strwho =~ tr/o/o/ )
          {
            if(asmcmdug_chmod_get_end_perm($other,$req_perm,$oper,\$end_perm))
            {
               push( @sqlperm, "other=" . $end_perm );
            }
            else
            {
               @eargs = ($_);
               asmcmdshare_error_msg(8409, \@eargs);
               asmcmdshare_trace(1, $DBI::errstr, 'y', 
                                            'y') if(defined($DBI::errstr));
               return;
            }
          }
        }

        $qry = "alter diskgroup " . $dgname . " set permission ";
        $qry .= join (' , ', @sqlperm);
        $qry .= " for file \'" .  $norm{'path'}->[$i] . "\'";

        eval
        {
           $ret = asmcmdshare_do_stmt($dbh, $qry);
        };
        if (asmcmdexceptions::catch())
        {
          @eargs = ($file);
          asmcmdshare_error_msg(8402, \@eargs);
          next;
        }

        #Clear out previous effective permissions 
        if($not_digit == 1)
        {
          @sqlperm=();
        }
      }
    }
    else
    {
      @eargs = ($_);
      asmcmdshare_error_msg (8014, \@eargs);
      asmcmdshare_trace (1, $DBI::errstr, 'y', 'y') if(defined($DBI::errstr))
    }
  }
}

########
# NAME
#   asmcmdug_chmod_get_end_perm
# DESCRIPTION
#   This function checks whether the current chmod is allowed.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_chmod() calls this function.
########
sub asmcmdug_chmod_get_end_perm
{
   my ($role,$req_perm,$oper,$end_perm) = @_;
   my ($retval) = 1;

   if($oper eq 'add')
   { 
      $role .= $req_perm;
   }
   elsif($oper eq 'del')
   {
     $role  =~ s/$req_perm/-/g ;
   }

   # write only option is not allowed
   if(($role=~ /w/) and !($role =~ /r/))
   {
     $retval = 0;
     return $retval;
   }
  
   $$end_perm = "none";
   $$end_perm = "read only" if($role =~ /r/);
   $$end_perm = "read write" if($role =~ /rw/);
   
   return $retval; 
}

########
# NAME
#   asmcmdug_process_chgrp
#
# DESCRIPTION
#   This function processes the asmcmd command chgrp.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_chgrp
{
  my ($dbh) = @_;
  my (%args);
  my ($ret);
  my ($sth, $qry, $dgname, $group);
  my (@files);
  my (@eargs);
  my (%norm);

  # Get option parameters, if any.
  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  $group = shift(@{$args{'chgrp'}});

  # get files
  foreach (@{$args{'chgrp'}})
  {
    push (@files, $_);
  }

  foreach (@files)
  {
    if ($_ =~ m/(\w+)[\/]?.*/)
    {
      #Normalize path and fetch the grp and file_number
      %norm = asmcmdshare_normalize_path($dbh, $_, 0, \$ret);

      if($ret != 0)
      {
          @eargs = ($_);
          asmcmdshare_error_msg(8014, \@eargs);
          asmcmdshare_trace(1, $DBI::errstr, 'y', 
                                 'y') if(defined($DBI::errstr));
          next;#continue with next file
      }

      $dgname = (split(/\//, $norm{'path'}->[0]))[0];
      $dgname =~s/\+//g;

      $qry = "alter diskgroup " . $dgname . " set ownership ";
      $qry .= "group=\'" . $group . "\'";
      $qry .= " for file \'" . $norm{'path'}->[0] . "\'";

      eval
      {
         $ret = asmcmdshare_do_stmt($dbh, $qry);
      };
      if (asmcmdexceptions::catch())
      {
        @eargs = ($_);
        asmcmdshare_error_msg(8402, \@eargs);
        asmcmdexceptions::throw("asmcmdexecptions");
      }
    }
    else
    {
       @eargs = ($_);
       asmcmdshare_error_msg(8014, \@eargs);
       asmcmdshare_trace(1, $DBI::errstr, 'y', 'y') if(defined($DBI::errstr));
    }    
  }
}


########
# NAME
#   asmcmdug_process_grpmod
#
# DESCRIPTION
#   This function processes the asmcmd command grpmod.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
#
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_grpmod
{
  my ($dbh) = @_;
  my (%args);
  my ($ret);
  my ($sth, $qry, $dgname, $grpname, $action);
  my (@usrs);

  # Get option parameters, if any.
  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  $dgname = shift(@{$args{'grpmod'}});
  $grpname = shift(@{$args{'grpmod'}});

  # get the users
  foreach (@{$args{'grpmod'}})
  {
    push (@usrs, "\'".$_."\'");
  }

  if ($args{'add'})   #add
  {
    $action = "add";
  }

  elsif ($args{'delete'})   #drop
  {
    $action = "drop";
  }

  $qry = "alter diskgroup " . $dgname . " modify usergroup \'" .$grpname."\' ";
  $qry .= $action . " member " . join(',', @usrs);

  $ret = asmcmdshare_do_stmt($dbh, $qry);
}


########
# NAME
#   asmcmdug_process_groups
# 
# DESCRIPTION
#   Returns the groups that a user belongs to (ASM context).
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
# 
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_groups
{
  my ($dbh) = @_;
  my (%args);
  my ($ret);
  my ($dgname, $grpname, $usrname, $clstrname);
  my (@what, @from, $sth, $qry, @where, @order, @binds);
  my (@usrs, $row);
  my (@groups);
  my ($print_string);
  # Get option parameters, if any.
  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  ($dgname, $usrname) = @{$args{'groups'}};
  ($usrname, $clstrname) = split('@', $usrname);
  $clstrname = '' if (!defined($clstrname));
  $dgname =~ tr/a-z/A-Z/;

  push (@what, 'v$asm_usergroup.name as usergroup_name');

  push (@from, 'v$asm_usergroup');
  push (@from, 'v$asm_user');
  push (@from, 'v$asm_usergroup_member');
  push (@from, 'v$asm_diskgroup_stat');

  push (@where, 'v$asm_user.os_name = ?');
  push (@binds, [$usrname, SQL_VARCHAR]);
  if (!defined($clstrname) || $clstrname eq '')
  {
    push (@where, "v\$asm_user.cluster_id is null" );
  }
  else
  {
    push (@where, "v\$asm_user.cluster_id = ?" );
    push (@binds, [$clstrname, SQL_VARCHAR]);
  }

  push (@where, 'v$asm_diskgroup_stat.name = ?');
  push (@binds, [$dgname, SQL_VARCHAR]);

  push (@where, 'v$asm_usergroup_member.usergroup_number = ' .
        'v$asm_usergroup.usergroup_number');
  push (@where, 'v$asm_usergroup_member.member_number = ' .
        'v$asm_user.user_number');
  push (@where, 'v$asm_usergroup_member.group_number = ' .
        'v$asm_user.group_number');
  push (@where, 'v$asm_user.group_number = ' .
        'v$asm_diskgroup_stat.group_number');
  push (@where, 'v$asm_usergroup_member.group_number = ' .
        'v$asm_diskgroup_stat.group_number');
  push (@where, 'v$asm_usergroup.group_number = ' .
        'v$asm_diskgroup_stat.group_number');

  push (@order, 'v$asm_diskgroup_stat.name');
  push (@order, 'usergroup_name');

  $sth = asmcmdshare_do_construct_select($dbh, \@what, \@from, \@where, 
                                         \@order, \@binds);

  while (defined($row = asmcmdshare_fetch($sth)))
  {
    push (@groups, $row->{'USERGROUP_NAME'});
  }

  $print_string = join(',', @groups) . "\n";
  asmcmdshare_print($print_string);

  asmcmdshare_finish($sth);
}


########
# NAME
#   asmcmdug_process_orapwusr
# 
# DESCRIPTION
#   Handles Oracle pwfile users.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
# 
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_orapwusr
{
  my ($dbh) = @_;
  my (%args);
  my ($ret);
#  my ($dgname, $grpname, $usrname);
#  my (@what, @from, $sth, $qry, @where);
#  my (@usrs, $row);
#  my (@groups, $user, $passwd, $stmt);
#  my $desc;
  my ($stmt, $sth, $user, $passwd);
  my ($trim) = 0;

  $stmt = "";  # start with empty string.

  # Get option parameters, if any.
  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  #Set the correct options if deprecated options were used and print WARNING.
  asmcmdshare_handle_deprecation($asmcmdglobal_hash{'cmd'}, \%args);

  ($user) = @{$args{'orapwusr'}};               # user
  $user = qq("$user");

  if (defined($args{'add'}))                    #add user
  {
    $passwd = asmcmdshare_getpswd();
    $passwd = qq("$passwd");
    $stmt = "create user " . $user . " identified by " . $passwd;
    $trim = 1;
  }

  if (defined($args{'modify'}))               # modify user
  {
    $passwd = asmcmdshare_getpswd();
    $passwd = qq("$passwd");
    $stmt = "alter user " . $user . " identified by " . $passwd;
    $trim = 1;
  }

  if (defined($args{'delete'}))               # drop user
  {
    $stmt = "drop user " . $user;
  }

  if (defined($args{'grant'}))                 # grant privileges
  {
    $stmt = "grant ". $args{'grant'}. " to ". $user;
  }

  if (defined($args{'revoke'}))                # revoke privileges
  {
    $stmt = "revoke ". $args{'revoke'} . " from ". $user;
  }
  $sth = asmcmdshare_do_stmt($dbh, $stmt, $trim);
}


########
# NAME
#   asmcmdug_process_lspwusr
# 
# DESCRIPTION
#   Lists Oracle pwfile users.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
# 
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_lspwusr
{
  my ($dbh) = @_;
  my (%args);
  my ($ret);
  my ($dgname, $grpname, $usrname);
  my (@what, @from, $sth, $qry, @where);
  my (@usrs, $row);
  my (@groups);

  my (%min_col_wid, $print_format, $print_string, @what_print);
  my ($k, $v, $h);

  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  #Set the correct options if deprecated options were used and print WARNING.
  asmcmdshare_handle_deprecation($asmcmdglobal_hash{'cmd'},\%args);

  push (@what, 'username');
  push (@what, 'sysdba');
  push (@what, 'sysoper');
  push (@what, 'sysasm');

  push (@from, 'v$pwfile_users');

  $sth = asmcmdshare_do_construct_select($dbh, \@what, \@from, \@where);

  foreach(@what)
  {
    $min_col_wid{$_} = length($asmcmdug_lspwusr_header{$_});
  }

  #get the rows
  while (defined($row = asmcmdshare_fetch($sth)))
  {
    my (%usr_info) = ();

    while(($k,$v) = each(%{$row}))
    {
      $k =~ tr/[A-Z]/[a-z]/;
      $usr_info{$k}    = $v;
      $min_col_wid{$k} = max($min_col_wid{$k}, length($v));
    }

    push (@usrs, \%usr_info);
  }
  asmcmdshare_finish($sth);

  foreach (@what)
  {
    $print_format .= "%" . $min_col_wid{$_} . "s ";
  }
  $print_format .= "\n";

  #print header
  if (!defined ($args{'suppressheader'}) )
  {
    @what_print = ();
    foreach (@what)
    {
      push (@what_print, $asmcmdug_lspwusr_header{$_});
    }
    $print_string = sprintf($print_format, @what_print);
    asmcmdshare_print($print_string);
  }

  #print rows
  foreach $h (@usrs)
  {
    @what_print = ();
    foreach (@what)
    {
      push (@what_print, $h->{$_});
    }
    $print_string = sprintf($print_format, @what_print);
    asmcmdshare_print($print_string);
  }

}


########
# NAME
#   asmcmdug_process_passwd
# 
# DESCRIPTION
#   Sets/changes the password of a user.
#
# PARAMETERS
#   dbh   (IN) - initialized database handle, must be non-null.
# 
# RETURNS
#   Null.
#
# NOTES
#   Only asmcmdug_process_cmd() calls this function.
########
sub asmcmdug_process_passwd
{
  my ($dbh) = @_;
  my (%args);
  my ($ret);
  my ($dgname, $usr, $oldpasswd, $newpasswd, $stmt);
  my (@eargs);
  my ($trim) = 1;

  my (%min_col_wid, $print_format, $printf_code, @what_print);
  my ($k, $v, $h);

  $ret = asmcmdug_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args);
  return unless defined ($ret);

  ($usr) = @{$args{'passwd'}};
  $usr = qq("$usr");

  $oldpasswd = asmcmdshare_getpswd('Enter old password (optional): ');
  $newpasswd = asmcmdshare_getpswd('Enter new password: ');

  if ($newpasswd eq '')
  {
    @eargs = ('');
    asmcmdshare_error_msg(8406, \@eargs);
    return;
  }

  $newpasswd = qq("$newpasswd");
  $stmt = ' ALTER USER ' . $usr . ' IDENTIFIED BY ' . $newpasswd;

  if ($oldpasswd ne '')
  {
    $oldpasswd = qq("$oldpasswd");
    $stmt .= ' REPLACE ' . $oldpasswd;
  }

  $ret = asmcmdshare_do_stmt($dbh, $stmt, $trim);
}
1;

OHA YOOOO