#!$ORACLE_HOME/perl/bin/perl -w # # Copyright (c) 2004, 2009, Oracle and/or its affiliates. All rights reserved. # # NAME # asmcmdcore - ASM CoMmanD line interface (Driver Program) # # DESCRIPTION # ASMCMD is a Perl utility that provides easy nagivation of files within # ASM diskgroups. Simple UNIX shell-like commands allow directory # traversal, directory creation and deletion, user alias creation and # deletion, and file deletion capabilities, among other features. # We implement this utility as a wrapper around existing SQL statements, # and we use the Perl DBI Module to connect to an ASM instance and to # issue these SQL statements. # # NOTES # usage: asmcmdcore [-v] [-a ] [-p] [command] # # MODIFIED (MM/DD/YY) # gayavenk 06/11/09 - reconnect after dsset # sanselva 06/04/09 - Enable consistencychk when 'c' option used # heyuen 04/20/09 - add spbackup # heyuen 12/03/08 - reconnect after spmove # heyuen 11/10/08 - fix asmcmd prompt in windows # heyuen 10/14/08 - use dynamic modules # heyuen 08/02/08 - add verbose # heyuen 07/28/08 - rewrite asmcmdcore to use getopt # heyuen 06/16/08 - force disk scan during startup # heyuen 05/14/08 - reconnect after spcopy # heyuen 04/15/08 - bug 6957288 # heyuen 03/26/08 - reconnect at instance startup # heyuen 03/21/08 - enable lsdsk in non connected mode # heyuen 02/15/08 - add history # hqian 11/29/07 - #5661841, #5629952: enable ASMCMD for RDBMS instance # heyuen 09/20/07 - flush error messages as well as pending messages # before the prompt # heyuen 08/09/07 - refresh from main # heyuen 07/24/07 - add error message for connection failure # hqian 07/06/07 - #6174647: set $ENV{'PATH'} to include # $ENV{'ORACLE_HOME'}/bin # hqian 06/25/07 - Reset $ENV{'PATH'} for security reasons # heyuen 04/02/07 - remove error message when issuing asmcmd help- # and not being able to connect to ASM # hqian 03/09/07 - Notify user when failed to connect to ASM # hqian 03/02/07 - add asmcmdcore_get_asm_version # jilim 02/19/07 - fix for invalid $dbh after the cp # hqian 11/21/06 - fix signal_handler # jilim 09/27/06 - bug-5402303: added passing arg, contype, # for asmcmdbase_connect() # averhuls 07/06/06 - # hqian 07/12/06 - 11gR1: enable AMBR, disk repair, and other features # hqian 06/26/06 - disable asmcmddisk and asmcmdambr for initial merge # hqian 06/15/06 - add asmcmddisk module # msharang 03/28/06 - Add asmcmdambr # hqian 01/26/06 - rename asmcmdbase_global to asmcmdglobal_hash # hqian 01/24/06 - #4939032: split off callback defs into asmcmdglobal # hqian 01/20/06 - #4939032: rename bad_cmd() to show_commands() # hqian 01/18/06 - #4939032: support additional modules # hqian 01/18/06 - #4939032: keep only main() and shell() # hqian 01/18/06 - #4939032: split up asmcmd into modules # hqian 07/19/05 - Remove RCS header # hqian 06/23/05 - #4450221: support wildcards for CD # hqian 05/18/05 - Mention 'missing view attributes' in help ls # hqian 05/03/05 - #4329688: improve SQL efficiency # hqian 04/13/05 - ls_get_file_info() -> ls_process_file() # hqian 04/08/05 - Improve implementation of ls # hqian 04/08/05 - Improve help documentation # hqian 04/07/05 - LRG 1843355: include seconds in mod-time # hqian 04/01/05 - #4261342: use asmcmd messages for certain errors # hqian 02/28/05 - #4204122: change NLS date format for minute to 'MI' # hqian 10/27/04 - hqian_asmcmd_13306_linux_3 # hqian 10/19/04 - Rename asmcmd0 to asmcmdcore # hqian 08/03/04 - hqian_asmcmd_13306_linux_2 # hqian 07/28/04 - Add % as wildcard char in addition to *. # hqian 07/13/04 - Add implementation of find [-t ]. # hqian 06/30/04 - Make code that uses BigInt work for both Perl 5.6.1 # and Perl 5.8.3; take out -c # functionality. # hqian 06/29/04 - Fix 10gR1 compatibility issues; fix alias name # case-sensitive bug, should be case insensitive # but case retentive. # hqian 06/25/04 - Rename the main program from asmcmd to asmcmd0, so # that we can name the wrapper script asmcmd; rename # global constants, global variables, and function # names so that they are prefixed by 'asmcmd0_', # as per coding style standards; fix ORA-15128 bug. # hqian 06/23/04 - Inaccurate error message bug: add error message # 8004, do not print error when '*' matches nothing; # fix rm -rf * double error message bug; fix find # diskgroup bug; fix print header in empty directory # bug; fix space in alias name bug. # hqian 06/22/04 - Give the option to turn off the functionality of # the -c flag; add constants for better code design. # hqian 06/09/04 - Fix bugs; improve comments. # hqian 06/07/04 - Organize code for better maintenance; code review # changes (suggested by Dave Friedman). # hqian 06/01/04 - Fix some bugs. # hqian 05/24/04 - Implement rm [-rf] and rm *; some code review fixes. # hqian 05/20/04 - Implement help, instance_type security check, # - connection error checks, and debug mode. # hqian 05/18/04 - Implement ls flags and lsct. # hqian 05/14/04 - hqian_asmcmd_13306 # hqian 04/21/04 - Creation # # # ############################################################################# # ############################ Functions List ################################# # # Top Level Routines # asmcmdcore_main # asmcmdcore_shell # asmcmdcore_parse_asmcmd_args # asmcmdcore_module_driver # asmcmdcore_process_help # asmcmdcore_show_commands # asmcmdcore_is_cmd # asmcmdcore_check_global_callbacks # asmcmdcore_syntax_error ############################################################################# use strict; # load global modules use asmcmdglobal; use asmcmdshare; use Getopt::Std; use Term::ReadLine; #find all the modules that exist, and include them my (%asm_modules); foreach (@INC) { if (-d $_) { my ($dir) = $_; my (@files) = (); opendir (MODDIR, $dir); @files = readdir(MODDIR); foreach (@files) { if ( $_ =~ /^asmcmd/ && $_ =~ /pm$/ ) { my (@temp) = (split(/\./, $_))[0]; $asm_modules{$temp[0]} = $dir . '/' . $_; } } closedir(MODDIR); } } delete($asm_modules{'asmcmdglobal'}); delete($asm_modules{'asmcmdshare'}); # If the module does not belong to asmcmd, remove it my @not_mod = (); my ($module); foreach $module(keys %asm_modules) { require "$module.pm"; my ($is_asm) = $module. "::is_asmcmd()"; eval ($is_asm); push (@not_mod, $module) if ($@); } foreach (@not_mod) { delete ($asm_modules{$_}); } # import modules foreach $module(sort(keys %asm_modules)) { $module->import; } ######################## ASMCMDCORE Global Variables ######################## # # # Each module needs to specify its initialization function here. my (@asmcmdcore_init_modules) = (); foreach $module(sort(keys %asm_modules)) { push (@asmcmdcore_init_modules, $module . "::init()"); } $SIG{INT} = \&asmcmdshare_signal_handler;# Signal handler for asmcmd # ############################ Top Level Routines ############################## # # Routines that calls exit(): # asmcmdcore_main - exit 0 # asmcmdcore_syntax_error - exit 0 # asmcmdbase_show_commands - exit 0 # asmcmdbase_check_insttype - exit 0 # asmcmdbase_signal_exception - exit 1 # asmcmdcore_shell - exit -1 # asmcmddisk_process_lsdsk - exit -1 0 1 2 ######## # NAME # asmcmdcore_main # # DESCRIPTION # This function is the main function of ASMCMD. It is the first # function that is called. # # PARAMETERS # None. # # RETURNS # Null. # ######## sub asmcmdcore_main { my ($dbh); my ($module); # Set these environment variables to null. We don't use them for # security reasons. $ENV{'PATH'} = ''; $ENV{'CDPATH'} = ''; # But we still need $ORACLE_HOME/bin in the path for NT compatibility. # NT has the necessary dll's in that directory. $ENV{'PATH'} = "$ENV{'ORACLE_HOME'}/bin"; # Un-taint the variable. Note that the extra scope is necessary # so that $1 is confined within that scope. { $ENV{'PATH'} =~ /([^\n^\r^\t]+)/; $ENV{'PATH'} = $1; } # Parse for consistency check option before calling init_modules asmcmdcore_consistency_check(); # Initialize modules. for $module (@asmcmdcore_init_modules) { eval($module); } # Check to see if all the modules have initialized the global callbacks # correctly. asmcmdcore_check_global_callbacks(); asmcmdcore_parse_asmcmd_args(); asmcmdcore_get_system_endian(); # If we're in non-interactive mode, and command is help, then there is # no need to attempt a network connection. Just run help and exit. # if (($asmcmdglobal_hash{'mode'} eq 'n') && # $asmcmdglobal_hash{'cmd'} eq 'help') # { # asmcmdcore_process_help(); # exit 0; # } # Now run the shell to process command(s). $dbh = asmcmdcore_shell(); asmcmdbase_disconnect($dbh) if defined ($dbh); # Always exit zero here. Exiting non-zero is done only from exception # routine. See asmcmdcore_signal_exception(). exit 0; } asmcmdcore_main(); ######## # NAME # asmcmdcore_get_system_endian # # DESCRIPTION # This routine gets the system's endianness and stores it in a global # variable. # # PARAMETERS # None. # # RETURNS # Null. # # NOTES ######## sub asmcmdcore_get_system_endian { # The first bit of a little endian system is 1, and that of big endian # system is 0. if (unpack("b*", pack("s", 1)) =~ /^1/) { # System is little endian. $asmcmdglobal_hash{'endn'} = 1; } else { # System is big endian. $asmcmdglobal_hash{'endn'} = 0; } } ######## # NAME # asmcmdcore_connect # # DESCRIPTION # This routine initiates a conneciton to the ASM instance. Calls # asmcmdbase_connect(). # # PARAMETERS # None. # # RETURNS # Null. # # NOTES ######## sub asmcmdcore_connect { my ($dbh); # Connect to ASM instance first $dbh = asmcmdbase_connect($asmcmdglobal_hash{'usr'}, $asmcmdglobal_hash{'pswd'}, $asmcmdglobal_hash{'ident'}, $asmcmdglobal_hash{'contyp'}); # added contyp, # # bug-5402303 # if (defined ($dbh)) { my ($qry, $sth, $row); # Bugs 5661841 and 5629952: now that these bugs are fixed, ASMCMD # can work on both ASM and RDBMS instances. No need to check instance # type, anymore. # Initialize global variables, including getting group_number and name # of the first diskgroup. asmcmdbase_init_global($dbh); } return $dbh; } ######## # NAME # asmcmdcore_shell # # DESCRIPTION # This routine contains the top-level shell loop that prompts the user for # for commands and calls other routines to process them. # # PARAMETERS # dbh (IN) - initialized database handle, must be non-null. # # RETURNS # Null. # # NOTES # Should call asmcmdcore_connect to initialize $dbh before calling this # routine. ######## sub asmcmdcore_shell { my ($dbh); my ($line); # One line of input from user. # my ($prompt) = 'ASMCMD> '; # ASMCMD user prompt value. # my ($term); my (@eargs); # Try to connect to ASM if the command is different from help if ($asmcmdglobal_hash{'cmd'} ne 'help') { $dbh = asmcmdcore_connect(); if (defined($dbh)) { $asmcmdglobal_hash{'ver'} = asmcmdshare_get_asm_version($dbh); # $$$ In order to test different version numbers of ASM and their # relative behaviors on ASMCMD, comment out the line above and # uncomment the line below. Set the version number to the one # that's to be tested. Note that this testing method works only # # $asmcmdglobal_hash{'ver'} = '11.1.0.3.0'; } else { # Inform user that connection to ASM failed, except when the issued # command is help, startup, shutdown, or lsdsk if ($asmcmdglobal_hash{'verbose'} eq 'y') { print STDERR "$DBI::errstr\n"; $|++; @eargs = ($ENV{'ORACLE_SID'}) if defined($ENV{'ORACLE_SID'}); asmcmdshare_error_msg (8103, \@eargs); } else { print STDERR "Connected to an idle instance.\n"; } } } # If non-interactive mode, process command and return. if ($asmcmdglobal_hash{'mode'} eq 'n') { if (!defined ($dbh) && asmcmdshare_is_no_instance_cmd($asmcmdglobal_hash{'cmd'}) != 1) { # Connection failed, and command requires ASM instance; record error. # asmcmdshare_error_msg (8102, undef); } else { asmcmdcore_module_driver($dbh); } exit $asmcmdglobal_hash{'e'}; } $asmcmdglobal_hash{'cwdnm'} = '+'; if (-e "/dev/tty") { $term = new Term::ReadLine("", \*STDIN, \*STDOUT); } else { $term = new Term::ReadLine("CON", \*STDIN, \*STDOUT); } if ($term->Features->{ornaments}) { local $Term::ReadLine::termcap_nowarn = 1; $term->ornaments(0); } while (1) { my (@token);# Need fresh array of parsed tokens of arguments from $line. # # Prepare prompt, if long version of prompt is needed. if ($asmcmdglobal_hash{'lprmt'} eq 'y') { $prompt = 'ASMCMD [' . $asmcmdglobal_hash{'cwdnm'} . '] > '; } select STDERR; $|++; select STDOUT; $|++; $line = $term->readline($prompt); if (defined($line)) { chomp($line); # Remove newline character. # $line =~ s,^\s+,,g; # Remove initial spaces. # $line =~ s,\s+$,,g; # Remove trailing spaces. # } # Terminate if EOF or 'exit'. if (! defined($line)) { $line = 'exit'; print "exit\n"; } last if ($line eq 'exit'); last if ($line eq 'quit'); # Parse $line into an array of arguments. if (asmcmdbase_parse_int_cmd_line($line, \@token)) { # asmcmdcore_parse_int_cmd_line() returned error. # asmcmdshare_error_msg(8007, undef); next; # Error, so done with this command, move on to next comand. # } next if ($token[0] eq ''); # Empty line, so skip command. # $asmcmdglobal_hash{'cmd'} = shift(@token); # Save command name. # @ARGV = @token; # Save in global @ARGV for internal command parsing. # if (!defined ($dbh) && asmcmdshare_is_no_instance_cmd($asmcmdglobal_hash{'cmd'}) != 1) { # Connection failed, and command requires ASM instance; record error. # asmcmdshare_error_msg (8102); } else { asmcmdcore_module_driver($dbh); } $term->addhistory($line); if ($asmcmdglobal_hash{'cmd'} eq 'cp' || $asmcmdglobal_hash{'cmd'} eq 'spcopy' || $asmcmdglobal_hash{'cmd'} eq 'spmove' || $asmcmdglobal_hash{'cmd'} eq 'spset' || $asmcmdglobal_hash{'cmd'} eq 'spbackup' || $asmcmdglobal_hash{'cmd'} eq 'dsset') { # re-connect to asm instance after the cp # # this must be done since $dbh is now invalidated by the cp # # and it was orginally set at this module level # asmcmdbase_disconnect($dbh) if defined ($dbh); $dbh = asmcmdbase_connect($asmcmdglobal_hash{'usr'}, $asmcmdglobal_hash{'pswd'}, $asmcmdglobal_hash{'ident'}, $asmcmdglobal_hash{'contyp'}); # added contyp, bug-5402303 # if (!defined($dbh)) { # re-connect to the asm instance failed # asmcmdshare_signal_exception (8201); } } # re-connect if we startup/shutdown an instance # if we cannot get a $dbh, that means there is no instance # but this is not a reason to signal error since we can # try startup again if ($asmcmdglobal_hash{'cmd'} eq 'startup' || $asmcmdglobal_hash{'cmd'} eq 'shutdown') { asmcmdbase_disconnect($dbh) if defined ($dbh); $dbh = asmcmdbase_connect($asmcmdglobal_hash{'usr'}, $asmcmdglobal_hash{'pswd'}, $asmcmdglobal_hash{'ident'}, $asmcmdglobal_hash{'contyp'}); if (!defined($dbh)) { if ($asmcmdglobal_hash{'verbose'} eq 'y') { print STDERR "$DBI::errstr\n"; $|++; @eargs = ($ENV{'ORACLE_SID'}) if defined($ENV{'ORACLE_SID'}); asmcmdshare_error_msg (8103, \@eargs); } else { print STDERR "Connected to an idle instance.\n"; } } } } return $dbh; } ######## # NAME # asmcmdcore_consistency_check # # DESCRIPTION # This routine parses command line arguments only for consistency check option # not anyother the arguments related to ASMCMD or commands internal to ASMCMD. # # PARAMETERS # GLOBAL: @ARGV (IN/OUT) - list of all command line arguments for asmcmd. # # RETURNS # Null. # # Note also that this routine removes the consistency check option if found in # ARGV ######## sub asmcmdcore_consistency_check { #consistency check option my $element = '-check'; if (my $pos = grep {$_ eq $element} @ARGV) { #remove the option from ARGV array if found splice(@ARGV,$pos-1,1); #set the global to denote that consistency check is ON #later used in init() function in all perl modules $asmcmdglobal_hash{'consistchk'} = 'y'; print STDERR "WARNING: ASMCMD consistency check enabled\n"; } return; } ######## # NAME # asmcmdcore_parse_asmcmd_args # # DESCRIPTION # This routine parses the command line arguments for ASMCMD. These are # not the arguments for commands internal to ASMCMD. # asmcmdbase_parse_int_args() handles the latter cases. # # PARAMETERS # GLOBAL: @ARGV (IN/OUT) - list of all command line arguments for asmcmd. # # RETURNS # Null. # # Note also that this routine *modifies* @ARGV; all parsed arguments are # removed from this array. ######## sub asmcmdcore_parse_asmcmd_args { my ($flags) = "Vva:p"; my ($args_ref); my (%args) = (); my ($i, $len); my (@asmcmd_arg) = (); my (@cmd_arg) = (); # chop off the @ARGV array, so we process asmcmd arguments for ($i = 0; $i < $#ARGV+1; $i++) { if (defined ($asmcmdglobal_cmds{$ARGV[$i]})) { last; } } $len = $#ARGV; @asmcmd_arg = @ARGV[0..$i-1] if (defined(@ARGV[0..$i-1])); @cmd_arg = @ARGV[$i..$len] if (defined(@ARGV[$i..$len])); @ARGV = @asmcmd_arg; if( !getopts( $flags, \%args)) { asmcmdcore_syntax_error('asmcmd'); asmcmdcore_show_commands('exit', \*STDERR); } # if a command is passed, check that it is a valid one if (defined($ARGV[0])) { if (!defined($asmcmdglobal_cmds{$ARGV[0]})) { asmcmdcore_show_commands('exit', \*STDERR); return; } } # reconstruct @ARGV for the command arguments @ARGV = @cmd_arg; if (defined($args{'V'})) { print 'asmcmd version ' . $asmcmdglobal_hash{'acver'}. "\n"; exit 0; } if (defined($args{'v'})) { $asmcmdglobal_hash{'verbose'} = 'y'; } if (defined($args{'a'})) { if (($args{'a'} =~ /^sysasm$/i) || ($args{'a'} =~ /^sysdba$/i)) { $asmcmdglobal_hash{'contyp'} = $args{'a'}; } else { asmcmdcore_syntax_error('asmcmd'); return; } } if (defined($args{'p'})) { $asmcmdglobal_hash{'lprmt'} = 'y'; } if (defined($ARGV[0])) { $asmcmdglobal_hash{'mode'} = 'n'; if (asmcmdcore_is_cmd($ARGV[0])) { $asmcmdglobal_hash{'cmd'} = $ARGV[0]; shift(@ARGV); return; } else { asmcmdcore_show_commands('exit', \*STDERR); } } return; } ######## # NAME # asmcmdcore_module_driver # # DESCRIPTION # This function calls in each module the respective function that # processes commands responsible by the said module. All ASMCMD # commands must pass through this function before being processed # by the modules. # # PARAMETERS # dbh (IN) - initialized database handle, must be non-null. # # RETURNS # Null. # ######## sub asmcmdcore_module_driver { my ($dbh) = shift; my ($succ) = 0; my ($module); my (@eargs); # Array of error arguments. # foreach $module (@asmcmdglobal_command_callbacks) { if ($module->($dbh)) { # Assert that we find only one occurrence of this command in # the modules. @eargs = ("asmcmdcore_module_driver_05", $asmcmdglobal_hash{'cmd'}); asmcmdshare_assert(($succ == 0), \@eargs); $succ = 1; } } if ($asmcmdglobal_hash{'cmd'} eq 'help') { # Assert that we find only one occurrence of this command in # the modules. @eargs = ("asmcmdcore_module_driver_10", $asmcmdglobal_hash{'cmd'}); asmcmdshare_assert(($succ == 0), \@eargs); asmcmdcore_process_help(); $succ = 1; } if (! $succ) { asmcmdcore_show_commands(undef, \*STDERR); } return; } ######## # NAME # asmcmdcore_process_help # # DESCRIPTION # This top-level routine processes the help command. # # PARAMETERS # None. # # RETURNS # Null. # ######## sub asmcmdcore_process_help { my (%args); # Argument hash used by getopts(). # my ($ret); # asmcmdbase_parse_int_args() return value. # my ($cmd); # User-specified command-name argument; show help on $cmd. # my ($syntax); # Command syntax for $cmd. # my ($desc); # Command description for $cmd. # my ($module); # A module's help function. # my ($succ) = 0; # 1 if command exists, 0 otherwise. # my (@eargs); # Array of error arguments. # # Get option parameters, if any. $ret = asmcmdbase_parse_int_args($asmcmdglobal_hash{'cmd'}, \%args); return unless defined ($ret); # Check if number of non-option parameters are correct. if (@ARGV > 1) { asmcmdcore_syntax_error($asmcmdglobal_hash{'cmd'}); return; } $cmd = shift (@ARGV); if (defined ($cmd)) { # Search each module for the command's help message. foreach $module (@asmcmdglobal_help_callbacks) { if ($module->($cmd) == 1) { # Assert that we find only one occurrence of this command in # the modules. @eargs = ("asmcmdcore_process_help_05", $cmd); asmcmdshare_assert(($succ == 0), \@eargs); # We found the command's help message. $succ = 1; } } } if (! defined ($cmd) || ($succ == 0)) { # No command name specified, or command not found; # # show help on asmcmd and list all commands. # if ($ASMCMDGLOBAL_USE_CONN_STR) { $syntax = asmcmdbase_get_cmd_syntax('asmcmd'); $desc = asmcmdbase_get_cmd_desc('asmcmd'); } else { # If -c is deprecated, then use syntax without -c option. # $syntax = asmcmdbase_get_cmd_syntax('asmcmd_no_conn_str'); $desc = asmcmdbase_get_cmd_desc('asmcmd_no_conn_str'); } print " $syntax\n"; print "$desc\n\n"; asmcmdcore_show_commands(undef, \*STDOUT); # Print list of all commands. # } return; } ######## # NAME # asmcmdcore_show_commands # # DESCRIPTION # This routine prints a list of all valid internal commands, used # as an error message when the user has entered an invalid command name. # If $exit is set to 'exit', then also call exit(0). This option is to # accommodate the non-interactive option, when quitting asmcmd is necessary. # The caller can specify whether he wants to direct the output to # STDOUT or STDERR. # # PARAMETERS # exit (IN) - flag: causes asmcmdbase_show_commands() to call exit() # iff value is 'exit'. # IO_handle (IN) - handle where to print output: STDOUT or STDERR. # # RETURNS # Null. # ######## sub asmcmdcore_show_commands { my ($exit, $output_handle) = @_; my ($asmcmd_cmds) = ''; my ($module); print $output_handle " commands:\n"; print $output_handle " --------\n\n"; foreach $module (@asmcmdglobal_command_list_callbacks) { $asmcmd_cmds .= $module->() . "\n"; } print $output_handle $asmcmd_cmds; exit 0 if (defined($exit) && ($exit eq 'exit')); return; } ######## # NAME # asmcmdcore_is_cmd # # DESCRIPTION # This routine checks if a user-entered command is one of the known ASMCMD # internal commands. # # PARAMETERS # arg (IN) - user-entered command name string. # # RETURNS # 1 if $arg is one of the known commands, 0 otherwise. # # NOTES # This routine calls the callbacks from each module to check if $arg # belongs to any of the modules. It asserts that the command is found # in only one module. ######## sub asmcmdcore_is_cmd { my ($command) = shift; my ($module); my ($succ) = 0; my ($count) = 0; my (@eargs); # Array of error arguments. # foreach $module (@asmcmdglobal_is_command_callbacks) { if ($module->($command)) { $succ = 1; $count++; } } # Assert that $count is at most 1 and at least 0. @eargs = ("asmcmdcore_is_cmd_05", $asmcmdglobal_hash{'cmd'}, $count); asmcmdshare_assert( (($count == 1) || ($count == 0)), \@eargs); return $succ; } ######## # NAME # asmcmdcore_check_global_callbacks # # DESCRIPTION # This function checks to see if the global callback arrays have been # initialized correctly. # # PARAMETERS # None # # RETURNS # Null if the assertion passes; signals exception otherwise. # # NOTES # This function asserts that all the callback arrays, including # asmcmdcore_init_modules, have the same number of elements. ######## sub asmcmdcore_check_global_callbacks { my (@eargs); # Error arguments for the assert. # my ($temp); @eargs = ("asmcmdcore_check_global_callbacks_05", scalar(@asmcmdcore_init_modules), scalar(@asmcmdglobal_command_callbacks), scalar(@asmcmdglobal_help_callbacks), scalar(@asmcmdglobal_command_list_callbacks), scalar(@asmcmdglobal_is_command_callbacks), scalar(@asmcmdglobal_is_wildcard_callbacks), scalar(@asmcmdglobal_syntax_error_callbacks), scalar(@asmcmdglobal_no_instance_callbacks), scalar(@asmcmdglobal_error_message_callbacks), scalar(@asmcmdglobal_signal_exception_callbacks)); $temp = scalar(@asmcmdcore_init_modules); asmcmdshare_assert(((scalar(@asmcmdglobal_command_callbacks) == $temp) && (scalar(@asmcmdglobal_help_callbacks) == $temp) && (scalar(@asmcmdglobal_command_list_callbacks) == $temp) && (scalar(@asmcmdglobal_is_command_callbacks) == $temp) && (scalar(@asmcmdglobal_is_wildcard_callbacks) == $temp) && (scalar(@asmcmdglobal_syntax_error_callbacks) == $temp) && (scalar(@asmcmdglobal_no_instance_callbacks) == $temp) && (scalar(@asmcmdglobal_error_message_callbacks) == $temp) && (scalar(@asmcmdglobal_signal_exception_callbacks) == $temp)), \@eargs); return; } ######## # NAME # asmcmdcore_syntax_error # # DESCRIPTION # This function calls into each module to display the correct syntax # for a given ASMCMD command. # # PARAMETERS # command (IN) - the user-specified ASMCMD command # # RETURNS # Null. # # NOTES # This routine calls the callbacks from each module to display the # correct syntax for $command. ######## sub asmcmdcore_syntax_error { my ($command) = shift; my ($module); my ($count) = 0; my (@eargs); # Array of error arguments. # foreach $module (@asmcmdglobal_syntax_error_callbacks) { if ($module->($command)) { $count++; } } # Assert that $count is at most 1 and at least 0. @eargs = ("asmcmdcore_syntax_error_05", $asmcmdglobal_hash{'cmd'}, $count); asmcmdshare_assert( (($count == 1) || ($count == 0)), \@eargs); return; } ##############################################################################