Return to CIMConfigCommand.cpp CVS log | Up to [Pegasus] / pegasus / src / Clients / cimconfig |
File: [Pegasus] / pegasus / src / Clients / cimconfig / CIMConfigCommand.cpp
(download)
Revision: 1.75.6.2, Sat Apr 6 03:38:15 2013 UTC (11 years, 3 months ago) by dl.meetei Branch: RELEASE_2_11-branch CVS Tags: RELEASE_2_11_2-RC1, RELEASE_2_11_2 Changes since 1.75.6.1: +1 -0 lines BUG#: 9422 TITLE: Create a static configuration for the SLP Registration Timeout DESCRIPTION: Reused Marek's patch for 9486 |
//%LICENSE//////////////////////////////////////////////////////////////// // // Licensed to The Open Group (TOG) under one or more contributor license // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with // this work for additional information regarding copyright ownership. // Each contributor licenses this file to you under the OpenPegasus Open // Source License; you may not use this file except in compliance with the // License. // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // ////////////////////////////////////////////////////////////////////////// // //%///////////////////////////////////////////////////////////////////////////// #include <Pegasus/Common/Config.h> #include <Pegasus/Common/Constants.h> #include <Pegasus/Common/System.h> #include <Pegasus/Common/FileSystem.h> #include <Pegasus/Common/CIMProperty.h> #include <Pegasus/Common/CIMObjectPath.h> #include <Pegasus/Common/CIMStatusCode.h> #include <Pegasus/Common/Exception.h> #include <Pegasus/Common/PegasusVersion.h> #include <Pegasus/Common/StringConversion.h> #include <Pegasus/getoopt/getoopt.h> #include <Pegasus/Client/CIMClient.h> #include <Pegasus/Config/ConfigFileHandler.h> #include <Pegasus/Config/ConfigManager.h> #include <Pegasus/Config/ConfigExceptions.h> #include "CIMConfigCommand.h" #ifdef PEGASUS_OS_PASE # include <ILEWrapper/ILEUtilities.h> #endif #ifdef PEGASUS_OS_ZOS #include <Pegasus/General/SetFileDescriptorToEBCDICEncoding.h> #endif PEGASUS_NAMESPACE_BEGIN //l10n /** * The CLI message resource name */ static const char MSG_PATH [] = "pegasus/pegasusCLI"; //l10n end /** The command name. */ static const char COMMAND_NAME [] = "cimconfig"; /** The usage string for this command. This string is displayed when an error occurs in parsing or validating the command line. */ static const char USAGE [] = "Usage: "; /** This constant represents the getoopt argument designator */ static const char GETOPT_ARGUMENT_DESIGNATOR = ':'; /* These constants represent the operation modes supported by the CLI. Any new operation should be added here. */ /** This constant signifies that an operation option has not been recorded */ static const Uint32 OPERATION_TYPE_UNINITIALIZED = 0; /** This constant represents a property get operation */ static const Uint32 OPERATION_TYPE_GET = 1; /** This constant represents a property set operation */ static const Uint32 OPERATION_TYPE_SET = 2; /** This constant represents a property unset operation */ static const Uint32 OPERATION_TYPE_UNSET = 3; /** This constant represents a property list operation */ static const Uint32 OPERATION_TYPE_LIST = 4; /** This constant represents a help operation */ static const Uint32 OPERATION_TYPE_HELP = 5; /** This constant represents a version display operation */ static const Uint32 OPERATION_TYPE_VERSION = 6; /** The constants representing the string literals. */ static const CIMName PROPERTY_NAME = CIMName ("PropertyName"); static const CIMName DEFAULT_VALUE = CIMName ("DefaultValue"); static const CIMName CURRENT_VALUE = CIMName ("CurrentValue"); static const CIMName PLANNED_VALUE = CIMName ("PlannedValue"); static const CIMName DYNAMIC_PROPERTY = CIMName ("DynamicProperty"); /** The name of the method that implements the property value update using the timeout period. */ static const CIMName METHOD_UPDATE_PROPERTY_VALUE = CIMName("UpdatePropertyValue"); /** The input parameter names for the UpdatePropertyValue() method. */ static const String PARAM_PROPERTYVALUE = String("PropertyValue"); static const String PARAM_RESETVALUE = String("ResetValue"); static const String PARAM_UPDATEPLANNEDVALUE = String("SetPlannedValue"); static const String PARAM_UPDATECURRENTVALUE = String("SetCurrentValue"); static const String PARAM_TIMEOUTPERIOD = String("TimeoutPeriod"); /** The constants representing the messages. */ static const char FILE_NOT_READABLE [] = "Configuration file not readable."; static const char FAILED_TO_GET_PROPERTY [] = "Failed to get the config property."; static const char FAILED_TO_SET_PROPERTY [] = "Failed to set the config property."; static const char FAILED_TO_UNSET_PROPERTY [] = "Failed to unset the config property."; static const char FAILED_TO_LIST_PROPERTIES [] = "Failed to list the config properties. "; static const char CONFIG_SCHEMA_NOT_LOADED [] = "Please restore the internal repository on the CIM Server."; static const char PROPERTY_NOT_FOUND [] = "Specified property name was not found."; static const char INVALID_PROPERTY_VALUE [] = "Specified property value is not valid."; static const char PROPERTY_NOT_MODIFIED [] = "Specified property can not be modified."; //l10n default messages and resource keys static const char OPTION_INVALID_CIM_RUNNING [] = "Option -$0 is not valid for this command when CIM server is not running."; static const char OPTION_INVALID_CIM_RUNNING_KEY [] = "Clients.CIMConfig.CIMConfigCommand.OPTION_INVALID_CIM_RUNNING"; static const char FILE_NOT_READABLE_KEY [] = "Clients.CIMConfig.CIMConfigCommand.FILE_NOT_READABLE"; static const char FAILED_TO_GET_PROPERTY_KEY [] = "Clients.CIMConfig.CIMConfigCommand.FAILED_TO_GET_PROPERTY"; static const char FAILED_TO_SET_PROPERTY_KEY [] = "Clients.CIMConfig.CIMConfigCommand.FAILED_TO_SET_PROPERTY"; static const char FAILED_TO_UNSET_PROPERTY_KEY [] = "Clients.CIMConfig.CIMConfigCommand.FAILED_TO_UNSET_PROPERTY"; static const char FAILED_TO_LIST_PROPERTIES_KEY [] = "Clients.CIMConfig.CIMConfigCommand.FAILED_TO_LIST_PROPERTIES"; static const char CONFIG_SCHEMA_NOT_LOADED_KEY [] = "Clients.CIMConfig.CIMConfigCommand.CONFIG_SCHEMA_NOT_LOADED"; static const char PROPERTY_NOT_FOUND_KEY [] = "Clients.CIMConfig.CIMConfigCommand.PROPERTY_NOT_FOUND"; static const char INVALID_PROPERTY_VALUE_KEY [] = "Clients.CIMConfig.CIMConfigCommand.INVALID_PROPERTY_VALUE"; static const char PROPERTY_NOT_MODIFIED_KEY [] = "Clients.CIMConfig.CIMConfigCommand.PROPERTY_NOT_MODIFIED"; static const char PLANNED_VALUE_OF_PROPERTY_IS [] = "Planned value for the property $0 is set to \"$1\" in CIMServer."; static const char PLANNED_VALUE_OF_PROPERTY_IS_KEY [] = "Clients.CIMConfig.CIMConfigCommand.PLANNED_VALUE_OF_PROPERTY_IS"; static const char CURRENT_VALUE_OF_PROPERTY_IS [] = "Current value for the property $0 is set to \"$1\" in CIMServer."; static const char CURRENT_VALUE_OF_PROPERTY_IS_KEY [] = "Clients.CIMConfig.CIMConfigCommand.CURRENT_VALUE_OF_PROPERTY_IS"; static const char CURRENT_VALUE_OF_PROPERTY_CANNOT_BE_SET [] = "Current value for the property '$0' can not be set because the" " CIM server is not running."; static const char CURRENT_VALUE_OF_PROPERTY_CANNOT_BE_SET_KEY [] = "Clients.CIMConfig.CIMConfigCommand." "CURRENT_VALUE_OF_PROPERTY_CANNOT_BE_SET"; static const char FAILED_UPDATE_OF_PLANNED_VALUE_IN_FILE [] = "Failed to update the planned value of the Property '$0' in" " configuration file."; static const char FAILED_UPDATE_OF_PLANNED_VALUE_IN_FILE_KEY [] = "Clients.CIMConfig.CIMConfigCommand." "FAILED_UPDATE_OF_PLANNED_VALUE_IN_FILE"; static const char PROPERTY_UPDATED_IN_FILE [] = "Property '$0' updated in configuration file."; static const char PROPERTY_UPDATED_IN_FILE_KEY [] = "Clients.CIMConfig.CIMConfigCommand.PROPERTY_UPDATED_IN_FILE"; static const char PLANNED_VALUE_IS [] = "Planned value: $0"; static const char PLANNED_VALUE_IS_KEY [] = "Clients.CIMConfig.CIMConfigCommand.PLANNED_VALUE_IS"; static const char CURRENT_VALUE_IS [] = "Current value: $0"; static const char CURRENT_VALUE_IS_KEY [] = "Clients.CIMConfig.CIMConfigCommand.CURRENT_VALUE_IS"; static const char DEFAULT_VALUE_IS [] = "Default value: $0"; static const char DEFAULT_VALUE_IS_KEY [] = "Clients.CIMConfig.CIMConfigCommand.DEFAULT_VALUE_IS"; static const char CANNOT_DETERMINE_PLANNED_VALUE_CIM_RUNNING [] = "Planned value can not be determined because the CIM server is not" " running."; static const char CANNOT_DETERMINE_PLANNED_VALUE_CIM_RUNNING_KEY [] = "Clients.CIMConfig.CIMConfigCommand." "CANNOT_DETERMINE_PLANNED_VALUE_CIM_RUNNING"; static const char CANNOT_DETERMINE_CURRENT_VALUE_CIM_RUNNING [] = "Current value can not be determined because the CIM server is" " not running."; static const char CANNOT_DETERMINE_CURRENT_VALUE_CIM_RUNNING_KEY [] = "Clients.CIMConfig.CIMConfigCommand." "CANNOT_DETERMINE_CURRENT_VALUE_CIM_RUNNING"; static const char PROPERTY_VALUE_ALREADY_SET_TO [] = "The property '$0' value is already set to '$1'."; static const char PROPERTY_VALUE_ALREADY_SET_TO_KEY [] = "Clients.CIMConfig.CIMConfigCommand.PROPERTY_VALUE_ALREADY_SET_TO"; static const char CURRENT_PROPERTY_SET_TO_DEFAULT [] = "Current value for the property '$0' is set to default value in CIMServer."; static const char CURRENT_PROPERTY_SET_TO_DEFAULT_KEY [] = "Clients.CIMConfig.CIMConfigCommand.CURRENT_PROPERTY_SET_TO_DEFAULT"; static const char PROPERTY_UNSET_IN_FILE [] = "Property '$0' is unset in the configuration file."; static const char PROPERTY_UNSET_IN_FILE_KEY [] = "Clients.CIMConfig.CIMConfigCommand.PROPERTY_UNSET_IN_FILE"; static const char CURRENT_PROPERTY_CANNOT_BE_UNSET_CIM_NOT_RUNNING [] = "Current value for the property '$0' can not be unset because the" " CIM server is not running."; static const char CURRENT_PROPERTY_CANNOT_BE_UNSET_CIM_NOT_RUNNING_KEY [] = "Clients.CIMConfig.CIMConfigCommand." "CURRENT_PROPERTY_CANNOT_BE_UNSET_CIM_NOT_RUNNING"; static const char PROPERTY_VALUE_ALREADY_UNSET [] = "The property '$0' value is already unset."; static const char PROPERTY_VALUE_ALREADY_UNSET_KEY [] = "Clients.CIMConfig.CIMConfigCommand.PROPERTY_VALUE_ALREADY_UNSET"; static const char CURRENT_VALUES_CANNOT_BE_LISTED_CIM_NOT_RUNNING [] = "Current value of properties can not be listed because the CIM server" " is not running."; static const char CURRENT_VALUES_CANNOT_BE_LISTED_CIM_NOT_RUNNING_KEY [] = "Clients.CIMConfig.CIMConfigCommand." "CURRENT_VALUES_CANNOT_BE_LISTED_CIM_NOT_RUNNING"; static const char NO_PROPERTIES_FOUND_IN_FILE [] = "No configuration properties found in the configuration file."; static const char NO_PROPERTIES_FOUND_IN_FILE_KEY [] = "Clients.CIMConfig.CIMConfigCommand.NO_PROPERTIES_FOUND_IN_FILE"; static const char REQUIRED_ARGS_MISSING [] = "Required arguments missing."; static const char REQUIRED_ARGS_MISSING_KEY [] = "Clients.cimuser.CIMUserCommand.REQUIRED_ARGS_MISSING"; static const char ERR_USAGE [] = "Use '--help' to obtain command syntax."; static const char ERR_USAGE_KEY [] = "Clients.CIMConfig.CIMConfigCommand.ERR_USAGE"; //l10n end default messages and keys /** The option character used to specify get config property. */ static const char OPTION_GET = 'g'; /** The option character used to specify set config property. */ static const char OPTION_SET = 's'; #ifdef PEGASUS_OS_PASE /** The option character used to specify no output to stdout or stderr. */ static const char OPTION_QUIET_VALUE = 'q'; #endif /** The option character used to specify unset config property. */ static const char OPTION_UNSET = 'u'; /** The option character used to specify listing of config properties. */ static const char OPTION_LIST = 'l'; /** The option character used to specify the current config value. */ static const char OPTION_CURRENT_VALUE = 'c'; /** The option character used to specify the planned config value. */ static const char OPTION_PLANNED_VALUE = 'p'; /** The option character used to specify the default config value. */ static const char OPTION_DEFAULT_VALUE = 'd'; /** The option character used to specify the timeout value. */ static const char OPTION_TIMEOUT_VALUE = 't'; /** The option character used to display help info. */ static const char OPTION_HELP = 'h'; /** The option character used to display version info. */ static const char OPTION_VERSION = 'v'; static const char LONG_HELP [] = "help"; static const char LONG_VERSION [] = "version"; /** Constructs a CIMConfigCommand and initializes instance variables. */ CIMConfigCommand::CIMConfigCommand () { /** Initialize the instance variables. */ _operationType = OPERATION_TYPE_UNINITIALIZED; _propertyName = CIMName (); _currentValueSet = false; _plannedValueSet = false; _defaultValueSet = false; #ifdef PEGASUS_OS_PASE _defaultQuietSet = false; #endif /** Build the usage string for the config command. */ usage.reserveCapacity(200); usage.append(USAGE); usage.append(COMMAND_NAME); usage.append(" -").append(OPTION_GET).append(" name"); usage.append(" [ -").append(OPTION_CURRENT_VALUE); usage.append(" ] [ -").append(OPTION_DEFAULT_VALUE); usage.append(" ] [ -").append(OPTION_PLANNED_VALUE).append(" ]\n"); #ifdef PEGASUS_OS_PASE usage.append(" ] [ -").append(OPTION_QUIET_VALUE).append(" ]\n"); #endif usage.append(" -").append(OPTION_SET).append(" name=value"); usage.append(" [ -").append(OPTION_CURRENT_VALUE); usage.append(" ] [ -").append(OPTION_PLANNED_VALUE); usage.append(" ] [ -").append(OPTION_TIMEOUT_VALUE).append(" ]\n"); #ifdef PEGASUS_OS_PASE usage.append(" ] [ -").append(OPTION_QUIET_VALUE).append(" ]\n"); #endif usage.append(" -").append(OPTION_UNSET).append(" name"); usage.append(" [ -").append(OPTION_CURRENT_VALUE); usage.append(" ] [ -").append(OPTION_PLANNED_VALUE); usage.append(" ] [ -").append(OPTION_TIMEOUT_VALUE).append(" ]\n"); #ifdef PEGASUS_OS_PASE usage.append(" ] [ -").append(OPTION_QUIET_VALUE).append(" ]\n"); #endif usage.append(" -").append(OPTION_LIST); usage.append(" [ -").append(OPTION_CURRENT_VALUE); usage.append(" | -").append(OPTION_PLANNED_VALUE).append(" ]\n"); usage.append(" -").append(OPTION_HELP).append("\n"); usage.append(" --").append(LONG_HELP).append("\n"); usage.append(" --").append(LONG_VERSION).append("\n"); usage.append("Options : \n"); usage.append(" -c - Use current configuration\n"); usage.append(" -d - Use default configuration\n"); usage.append(" -g - Get the value of specified configuration" " property\n"); usage.append(" -h, --help - Display this help message\n"); usage.append(" -l - Display all the configuration properties\n"); usage.append(" -p - Configuration used on next CIM Server" " start\n"); #ifdef PEGASUS_OS_PASE usage.append(" -q - Specify quiet mode," "avoiding output to stdout or stderr\n"); #endif usage.append(" -s - Add or Update configuration property" " value\n"); usage.append(" -u - Reset configuration property to its" " default value\n"); usage.append(" -t - Timeout value in seconds for updating the" " current or planned value\n"); usage.append(" --version - Display CIM Server version number\n"); usage.append("\nUsage note: The cimconfig command can be used to update" " the next planned\n"); usage.append( "configuration without having the CIM Server running." " All other options \n"); usage.append("of the cimconfig command require that the CIM Server" " is running."); //l10n localize usage #ifdef PEGASUS_HAS_ICU MessageLoaderParms menuparms( "Clients.CIMConfig.CIMConfigCommand.MENU.STANDARD",usage); menuparms.msg_src_path = MSG_PATH; usage = MessageLoader::getMessage(menuparms); #endif setUsage (usage); } /** Parses the command line, validates the options, and sets instance variables based on the option arguments. */ void CIMConfigCommand::setCommand (Uint32 argc, char* argv []) { unsigned int i = 0; Uint32 c = 0; String property = String (); String badOptionString = String (); String optString = String (); Uint32 equalsIndex = 0; // // Construct optString // optString.append(OPTION_GET); optString.append(GETOPT_ARGUMENT_DESIGNATOR); optString.append(OPTION_SET); optString.append(GETOPT_ARGUMENT_DESIGNATOR); optString.append(OPTION_UNSET); optString.append(GETOPT_ARGUMENT_DESIGNATOR); optString.append(OPTION_TIMEOUT_VALUE); optString.append(GETOPT_ARGUMENT_DESIGNATOR); optString.append(OPTION_LIST); optString.append(OPTION_CURRENT_VALUE); optString.append(OPTION_PLANNED_VALUE); optString.append(OPTION_DEFAULT_VALUE); #ifdef PEGASUS_OS_PASE optString.append(OPTION_QUIET_VALUE); #endif optString.append(OPTION_HELP); // // Initialize and parse options // getoopt options (""); options.addFlagspec(optString); //PEP#167 - adding long flag for options : 'help' and 'version' options.addLongFlagspec(LONG_HELP,getoopt::NOARG); options.addLongFlagspec(LONG_VERSION,getoopt::NOARG); options.parse (argc, argv); if (options.hasErrors ()) { throw CommandFormatException(options.getErrorStrings()[0]); } _operationType = OPERATION_TYPE_UNINITIALIZED; _timeoutSeconds = 0; // // Get options and arguments from the command line // for (i = options.first (); i < options.last (); i++) { if (options[i].getType () == Optarg::LONGFLAG) { if (options[i].getopt () == LONG_HELP) { if (_operationType != OPERATION_TYPE_UNINITIALIZED) { // // More than one operation option was found // throw UnexpectedOptionException(String(LONG_HELP)); } _operationType = OPERATION_TYPE_HELP; } else if (options[i].getopt () == LONG_VERSION) { if (_operationType != OPERATION_TYPE_UNINITIALIZED) { // // More than one operation option was found // throw UnexpectedOptionException(String(LONG_VERSION)); } _operationType = OPERATION_TYPE_VERSION; } } else if (options [i].getType () == Optarg::REGULAR) { // // The cimconfig command has no non-option argument options // throw UnexpectedArgumentException(options[i].Value()); } else /* if (options [i].getType () == Optarg::FLAG) */ { c = options [i].getopt () [0]; switch (c) { case OPTION_GET: { if (_operationType != OPERATION_TYPE_UNINITIALIZED) { // // More than one operation option was found // throw UnexpectedOptionException(OPTION_GET); } if (options.isSet (OPTION_GET) > 1) { // // More than one get option was found // throw DuplicateOptionException(OPTION_GET); } try { _propertyName = options [i].Value (); } catch (const InvalidNameException&) { throw InvalidOptionArgumentException( options[i].Value(), OPTION_GET); } _operationType = OPERATION_TYPE_GET; break; } case OPTION_SET: { if (_operationType != OPERATION_TYPE_UNINITIALIZED) { // // More than one operation option was found // throw UnexpectedOptionException(OPTION_SET); } if (options.isSet (OPTION_SET) > 1) { // // More than one set option was found // throw DuplicateOptionException(OPTION_SET); } _operationType = OPERATION_TYPE_SET; property = options [i].Value (); equalsIndex = property.find ('='); if ( equalsIndex == PEG_NOT_FOUND ) { // // The property value was not specified // throw InvalidOptionArgumentException( property, OPTION_SET); } try { _propertyName = CIMName (property.subString (0, equalsIndex)); } catch (const InvalidNameException&) { throw InvalidOptionArgumentException( property, OPTION_SET); } _propertyValue = property.subString( equalsIndex + 1 ); break; } case OPTION_TIMEOUT_VALUE: { if (options.isSet (OPTION_TIMEOUT_VALUE) > 1) { throw DuplicateOptionException(OPTION_TIMEOUT_VALUE); } property = options [i].Value (); Uint64 value = 0; if (!StringConversion::decimalStringToUint64( property.getCString(), value) || !value) { throw InvalidOptionArgumentException( property, OPTION_TIMEOUT_VALUE); } _timeoutSeconds = (Uint32)value; break; } case OPTION_UNSET: { if (_operationType != OPERATION_TYPE_UNINITIALIZED) { // // More than one operation option was found // throw UnexpectedOptionException(OPTION_UNSET); } if (options.isSet (OPTION_UNSET) > 1) { // // More than one unset option was found // throw DuplicateOptionException(OPTION_UNSET); } try { _propertyName = options [i].Value (); } catch (const InvalidNameException&) { throw InvalidOptionArgumentException( options[i].Value(), OPTION_UNSET); } _operationType = OPERATION_TYPE_UNSET; break; } case OPTION_LIST: { if (_operationType != OPERATION_TYPE_UNINITIALIZED) { // // More than one operation option was found // throw UnexpectedOptionException(OPTION_LIST); } if (options.isSet (OPTION_LIST) > 1) { // // More than one list option was found // throw DuplicateOptionException(OPTION_LIST); } _operationType = OPERATION_TYPE_LIST; break; } case OPTION_CURRENT_VALUE: { if (options.isSet (OPTION_CURRENT_VALUE) > 1) { // // More than one current value option was found // throw DuplicateOptionException(OPTION_CURRENT_VALUE); } _currentValueSet = true; break; } case OPTION_PLANNED_VALUE: { if (options.isSet (OPTION_PLANNED_VALUE) > 1) { // // More than one planned value option was found // throw DuplicateOptionException(OPTION_PLANNED_VALUE); } _plannedValueSet = true; break; } case OPTION_DEFAULT_VALUE: { if (options.isSet (OPTION_DEFAULT_VALUE) > 1) { // // More than one default value option was found // throw DuplicateOptionException(OPTION_DEFAULT_VALUE); } _defaultValueSet = true; break; } //PEP#167 - 2 new cases added below for HELP and VERSION case OPTION_HELP: { if (_operationType != OPERATION_TYPE_UNINITIALIZED) { // // More than one operation option was found // throw UnexpectedOptionException(OPTION_HELP); } if (options.isSet (OPTION_HELP) > 1) { // // More than one list option was found // throw DuplicateOptionException(OPTION_HELP); } _operationType = OPERATION_TYPE_HELP; break; } case OPTION_VERSION: { if (_operationType != OPERATION_TYPE_UNINITIALIZED) { // // More than one operation option was found // throw UnexpectedOptionException(OPTION_VERSION); } if (options.isSet (OPTION_VERSION) > 1) { // // More than one list option was found // throw DuplicateOptionException(OPTION_VERSION); } _operationType = OPERATION_TYPE_VERSION; break; } #ifdef PEGASUS_OS_PASE // check for quiet option // before processing the rest of the options case OPTION_QUIET_VALUE: { _defaultQuietSet = true; freopen("/dev/null","w",stdout); freopen("/dev/null","w",stderr); break; } #endif default: // // Should never get here // break; } } } if ( _operationType == OPERATION_TYPE_UNINITIALIZED ) { // // No operation type was specified; throw exception // so that usage can be displayed. // throw CommandFormatException(localizeMessage( MSG_PATH, REQUIRED_ARGS_MISSING_KEY, REQUIRED_ARGS_MISSING)); } if ( ( _operationType != OPERATION_TYPE_GET ) && ( _defaultValueSet ) ) { // // An invalid option was encountered // throw InvalidOptionException(OPTION_DEFAULT_VALUE); } if (_operationType != OPERATION_TYPE_SET && _operationType != OPERATION_TYPE_UNSET && _timeoutSeconds != 0) { // // An invalid option was encountered // throw InvalidOptionException(OPTION_TIMEOUT_VALUE); } if (_operationType == OPERATION_TYPE_LIST) { if ( _currentValueSet && _plannedValueSet ) { // // An invalid option was encountered // throw InvalidOptionException(OPTION_CURRENT_VALUE); } #ifdef PEGASUS_OS_PASE if( _defaultQuietSet ) { // // An invalid option was encountered // throw InvalidOptionException(OPTION_QUIET_VALUE); } #endif } else { // // if no options specified for get, set or unset operations // then set option as _currentValueSet // if ( !_currentValueSet && !_plannedValueSet && !_defaultValueSet ) { _currentValueSet = true; } } } /** Executes the command and writes the results to the PrintWriters. */ Uint32 CIMConfigCommand::execute( ostream& outPrintWriter, ostream& errPrintWriter) { Boolean connected = false; String defaultValue; String currentValue; String plannedValue; String pegasusHome; Boolean gotCurrentValue = false; Boolean gotPlannedValue = false; if (_operationType == OPERATION_TYPE_UNINITIALIZED) { // // The command was not initialized // return RC_ERROR; } else if (_operationType == OPERATION_TYPE_HELP) { cerr << usage << endl; return RC_SUCCESS; } else if (_operationType == OPERATION_TYPE_VERSION) { cerr << "Version " << PEGASUS_PRODUCT_VERSION << endl; return RC_SUCCESS; } // // Get local host name // _hostName.assign(System::getHostName()); try { // Construct the CIMClient and set to request server messages // in the default language of this client process. _client.reset(new CIMClient); _client->setRequestDefaultLanguages(); } catch (const Exception& e) { errPrintWriter << e.getMessage() << endl; return RC_ERROR; } try { // // Open connection with CIMSever // _client->connectLocal(); connected = true; } catch (const Exception&) { // // Failed to connect, so process the request offline. // connected = false; } if (!connected) { // // Locate the config files // const char* env = getenv("PEGASUS_HOME"); String currentFile = FileSystem::getAbsolutePath(env, PEGASUS_CURRENT_CONFIG_FILE_PATH); String plannedFile = FileSystem::getAbsolutePath(env, PEGASUS_PLANNED_CONFIG_FILE_PATH); try { // // Open default config files and load current config properties // _configFileHandler.reset( new ConfigFileHandler(currentFile, plannedFile, true));; } catch (const NoSuchFile&) { } catch (const FileNotReadable& fnr) { errPrintWriter << localizeMessage( MSG_PATH, FILE_NOT_READABLE_KEY, FILE_NOT_READABLE) << fnr.getMessage() << endl; return RC_ERROR; } catch (const ConfigFileSyntaxError& cfse) { errPrintWriter << cfse.getMessage() << endl; return RC_ERROR; } // // When the CIM Server is not running, cimconfig only updates the // planned config properties. // _configFileHandler->loadPlannedConfigProperties(); } // // Perform the requested operation // switch (_operationType) { case OPERATION_TYPE_GET: try { if (connected) { Array<String> propertyValues; _getPropertiesFromCIMServer( outPrintWriter, errPrintWriter, _propertyName, propertyValues); defaultValue = propertyValues[1]; currentValue = propertyValues[2]; gotCurrentValue = true; plannedValue = propertyValues[3]; gotPlannedValue = true; } else { if (_defaultValueSet) { errPrintWriter << localizeMessage(MSG_PATH, OPTION_INVALID_CIM_RUNNING_KEY, OPTION_INVALID_CIM_RUNNING, String(&OPTION_DEFAULT_VALUE,1)) << endl; return ( RC_ERROR ); } else { gotCurrentValue = _configFileHandler->getCurrentValue ( _propertyName, currentValue ); gotPlannedValue = _configFileHandler->getPlannedValue ( _propertyName, plannedValue ); } } } catch (const CIMException& e) { CIMStatusCode code = e.getCode(); if (code == CIM_ERR_NOT_FOUND || code == CIM_ERR_FAILED) { outPrintWriter << localizeMessage(MSG_PATH, PROPERTY_NOT_FOUND_KEY, PROPERTY_NOT_FOUND) << endl; errPrintWriter << e.getMessage() << endl; } else if (code == CIM_ERR_INVALID_CLASS) { outPrintWriter << localizeMessage(MSG_PATH, FAILED_TO_GET_PROPERTY_KEY, FAILED_TO_GET_PROPERTY) << endl << localizeMessage(MSG_PATH, CONFIG_SCHEMA_NOT_LOADED_KEY, CONFIG_SCHEMA_NOT_LOADED) << endl; } else { outPrintWriter << localizeMessage( MSG_PATH, FAILED_TO_GET_PROPERTY_KEY, FAILED_TO_GET_PROPERTY) << e.getMessage() << endl; } return ( RC_ERROR ); } catch (const Exception& e) { outPrintWriter << localizeMessage(MSG_PATH,FAILED_TO_GET_PROPERTY_KEY, FAILED_TO_GET_PROPERTY) << endl << e.getMessage() << endl; return ( RC_ERROR ); } if( _currentValueSet || ( !_plannedValueSet && !_defaultValueSet )) { if (gotCurrentValue) { outPrintWriter << localizeMessage(MSG_PATH, CURRENT_VALUE_IS_KEY, CURRENT_VALUE_IS, currentValue) << endl; } else { outPrintWriter << localizeMessage(MSG_PATH, CANNOT_DETERMINE_CURRENT_VALUE_CIM_RUNNING_KEY, CANNOT_DETERMINE_CURRENT_VALUE_CIM_RUNNING) << endl; return RC_ERROR; } } if( _plannedValueSet ) { if (gotPlannedValue) { outPrintWriter << localizeMessage(MSG_PATH, PLANNED_VALUE_IS_KEY, PLANNED_VALUE_IS, plannedValue) << endl; } else { outPrintWriter << localizeMessage(MSG_PATH, CANNOT_DETERMINE_PLANNED_VALUE_CIM_RUNNING_KEY, CANNOT_DETERMINE_PLANNED_VALUE_CIM_RUNNING) << endl; return RC_ERROR; } } if( _defaultValueSet ) { outPrintWriter << localizeMessage(MSG_PATH, DEFAULT_VALUE_IS_KEY, DEFAULT_VALUE_IS, defaultValue) << endl; } break; case OPERATION_TYPE_SET: // // send changes to CIMOM if running, else send to config file // try { if (connected) { _updatePropertyInCIMServer( outPrintWriter, errPrintWriter, _propertyName, _propertyValue, false); if ( _currentValueSet ) { outPrintWriter << localizeMessage(MSG_PATH, CURRENT_VALUE_OF_PROPERTY_IS_KEY, CURRENT_VALUE_OF_PROPERTY_IS, _propertyName.getString(), _propertyValue) << endl; } if ( _plannedValueSet ) { outPrintWriter << localizeMessage(MSG_PATH, PLANNED_VALUE_OF_PROPERTY_IS_KEY, PLANNED_VALUE_OF_PROPERTY_IS, _propertyName.getString(), _propertyValue) << endl; } } else { if (_currentValueSet) { outPrintWriter << localizeMessage(MSG_PATH, CURRENT_VALUE_OF_PROPERTY_CANNOT_BE_SET_KEY, CURRENT_VALUE_OF_PROPERTY_CANNOT_BE_SET, _propertyName.getString()) << endl; return ( RC_ERROR ); } else if (_plannedValueSet) { // Check if new planned value is valid by // asking the ConfigManager which does the same for the // server ConfigManager* myCfgMgr=ConfigManager::getInstance(); if (!myCfgMgr->validatePropertyValue( _propertyName.getString(), _propertyValue)) { outPrintWriter << localizeMessage(MSG_PATH, INVALID_PROPERTY_VALUE_KEY, INVALID_PROPERTY_VALUE) << endl; return ( RC_ERROR ); } if ( !_configFileHandler->updatePlannedValue( _propertyName, _propertyValue, false ) ) { outPrintWriter << localizeMessage(MSG_PATH, FAILED_UPDATE_OF_PLANNED_VALUE_IN_FILE_KEY, FAILED_UPDATE_OF_PLANNED_VALUE_IN_FILE, _propertyName.getString()) << endl; return ( RC_ERROR ); } } outPrintWriter << localizeMessage(MSG_PATH, PROPERTY_UPDATED_IN_FILE_KEY, PROPERTY_UPDATED_IN_FILE, _propertyName.getString()) << endl; } } catch (const CIMException& e) { CIMStatusCode code = e.getCode(); if (code == CIM_ERR_TYPE_MISMATCH) { outPrintWriter << localizeMessage(MSG_PATH, INVALID_PROPERTY_VALUE_KEY, INVALID_PROPERTY_VALUE) << endl; errPrintWriter << e.getMessage() << endl; } else if (code == CIM_ERR_NOT_FOUND) { outPrintWriter << localizeMessage(MSG_PATH, PROPERTY_NOT_FOUND_KEY, PROPERTY_NOT_FOUND) << endl; errPrintWriter << e.getMessage() << endl; } else if (code == CIM_ERR_NOT_SUPPORTED) { outPrintWriter << localizeMessage(MSG_PATH, PROPERTY_NOT_MODIFIED_KEY, PROPERTY_NOT_MODIFIED) << endl; errPrintWriter << e.getMessage() << endl; } else if (code == CIM_ERR_FAILED) { outPrintWriter << localizeMessage(MSG_PATH, FAILED_TO_SET_PROPERTY_KEY, FAILED_TO_SET_PROPERTY) << e.getMessage() << endl; } else if (code == CIM_ERR_ALREADY_EXISTS) { outPrintWriter << localizeMessage(MSG_PATH, PROPERTY_VALUE_ALREADY_SET_TO_KEY, PROPERTY_VALUE_ALREADY_SET_TO, _propertyName.getString(), _propertyValue) << endl; errPrintWriter << e.getMessage() << endl; } else if (code == CIM_ERR_INVALID_CLASS) { outPrintWriter << localizeMessage(MSG_PATH, FAILED_TO_SET_PROPERTY_KEY, FAILED_TO_SET_PROPERTY) << endl << localizeMessage(MSG_PATH, CONFIG_SCHEMA_NOT_LOADED_KEY, CONFIG_SCHEMA_NOT_LOADED) << endl; } else { errPrintWriter << e.getMessage() << endl; } return ( RC_ERROR ); } catch (const Exception& e) { outPrintWriter << localizeMessage(MSG_PATH, FAILED_TO_SET_PROPERTY_KEY, FAILED_TO_SET_PROPERTY) << endl << e.getMessage() << endl; return ( RC_ERROR ); } break; case OPERATION_TYPE_UNSET: // // send changes to CIMOM if running, else send to config file // try { if (connected) { _propertyValue = String::EMPTY; _updatePropertyInCIMServer( outPrintWriter, errPrintWriter, _propertyName, _propertyValue, true); if ( _currentValueSet ) { outPrintWriter << localizeMessage(MSG_PATH, CURRENT_PROPERTY_SET_TO_DEFAULT_KEY, CURRENT_PROPERTY_SET_TO_DEFAULT, _propertyName.getString()) << endl; } if ( _plannedValueSet ) { outPrintWriter << localizeMessage(MSG_PATH, PROPERTY_UNSET_IN_FILE_KEY, PROPERTY_UNSET_IN_FILE, _propertyName.getString()) << endl; } } else { if (_currentValueSet) { outPrintWriter << localizeMessage(MSG_PATH, CURRENT_PROPERTY_CANNOT_BE_UNSET_CIM_NOT_RUNNING_KEY, CURRENT_PROPERTY_CANNOT_BE_UNSET_CIM_NOT_RUNNING, _propertyName.getString()) << endl; return ( RC_ERROR ); } if ( !_configFileHandler->updatePlannedValue( _propertyName, _propertyValue, true ) ) { return ( RC_ERROR ); } outPrintWriter << localizeMessage(MSG_PATH, PROPERTY_UNSET_IN_FILE_KEY, PROPERTY_UNSET_IN_FILE, _propertyName.getString()) << endl; } } catch (const CIMException& e) { CIMStatusCode code = e.getCode(); if (code == CIM_ERR_TYPE_MISMATCH) { outPrintWriter << localizeMessage(MSG_PATH, INVALID_PROPERTY_VALUE_KEY, INVALID_PROPERTY_VALUE) << endl; errPrintWriter << e.getMessage() << endl; } else if (code == CIM_ERR_NOT_FOUND) { outPrintWriter << localizeMessage(MSG_PATH, PROPERTY_NOT_FOUND_KEY, PROPERTY_NOT_FOUND) << endl; errPrintWriter << e.getMessage() << endl; } else if (code == CIM_ERR_NOT_SUPPORTED) { outPrintWriter << localizeMessage(MSG_PATH, PROPERTY_NOT_MODIFIED_KEY, PROPERTY_NOT_MODIFIED) << endl; errPrintWriter << e.getMessage() << endl; } else if (code == CIM_ERR_FAILED) { outPrintWriter << localizeMessage(MSG_PATH, FAILED_TO_UNSET_PROPERTY_KEY, FAILED_TO_UNSET_PROPERTY) << e.getMessage() << endl; } else if (code == CIM_ERR_ALREADY_EXISTS) { outPrintWriter << localizeMessage(MSG_PATH, PROPERTY_VALUE_ALREADY_UNSET_KEY, PROPERTY_VALUE_ALREADY_UNSET, _propertyName.getString()) << endl; errPrintWriter << e.getMessage() << endl; } else if (code == CIM_ERR_INVALID_CLASS) { outPrintWriter << localizeMessage(MSG_PATH, FAILED_TO_UNSET_PROPERTY_KEY, FAILED_TO_UNSET_PROPERTY) << endl << localizeMessage(MSG_PATH, CONFIG_SCHEMA_NOT_LOADED_KEY, CONFIG_SCHEMA_NOT_LOADED) << endl; } else { errPrintWriter << e.getMessage() << endl; } return ( RC_ERROR ); } catch (const Exception& e) { outPrintWriter << localizeMessage(MSG_PATH, FAILED_TO_UNSET_PROPERTY_KEY, FAILED_TO_UNSET_PROPERTY) << endl << e.getMessage() << endl; return ( RC_ERROR ); } break; case OPERATION_TYPE_LIST: // // send request to CIMOM if running, else send to config file // try { Array<CIMName> propertyNames; Array<String> propertyValues; if (connected) { _listAllPropertiesInCIMServer(outPrintWriter, errPrintWriter, propertyNames, propertyValues); } else { if (_plannedValueSet) { _configFileHandler->getAllPlannedProperties( propertyNames, propertyValues); } else { outPrintWriter << localizeMessage(MSG_PATH, CURRENT_VALUES_CANNOT_BE_LISTED_CIM_NOT_RUNNING_KEY, CURRENT_VALUES_CANNOT_BE_LISTED_CIM_NOT_RUNNING) << endl; return RC_ERROR; } } Uint32 valuesSize = propertyValues.size(); Uint32 namesSize = propertyNames.size(); if (namesSize == 0) { outPrintWriter << localizeMessage(MSG_PATH, NO_PROPERTIES_FOUND_IN_FILE_KEY, NO_PROPERTIES_FOUND_IN_FILE) << endl; break; } for ( Uint32 i = 0; i < namesSize; i++ ) { outPrintWriter << propertyNames[i].getString(); if ( ( _currentValueSet || _plannedValueSet ) && ( valuesSize == namesSize) ) { outPrintWriter << "=" << propertyValues[i]; } outPrintWriter << endl; } break; } catch (const CIMException& e) { CIMStatusCode code = e.getCode(); if (code == CIM_ERR_NOT_FOUND || code == CIM_ERR_INVALID_CLASS) { outPrintWriter << localizeMessage(MSG_PATH, FAILED_TO_LIST_PROPERTIES_KEY, FAILED_TO_LIST_PROPERTIES) << endl << localizeMessage(MSG_PATH, CONFIG_SCHEMA_NOT_LOADED_KEY, CONFIG_SCHEMA_NOT_LOADED) << endl; } else if (code == CIM_ERR_FAILED) { outPrintWriter << localizeMessage(MSG_PATH, FAILED_TO_LIST_PROPERTIES_KEY, FAILED_TO_LIST_PROPERTIES) << e.getMessage() << endl; } else { errPrintWriter << e.getMessage() << endl; } return ( RC_ERROR ); } catch (const Exception& e) { outPrintWriter << localizeMessage(MSG_PATH, FAILED_TO_LIST_PROPERTIES_KEY, FAILED_TO_LIST_PROPERTIES) << endl << e.getMessage() << endl; return ( RC_ERROR ); } default: // // Should never get here // break; } return (RC_SUCCESS); } /** Get property values for the specified property from the CIM Server. */ void CIMConfigCommand::_getPropertiesFromCIMServer ( ostream& outPrintWriter, ostream& errPrintWriter, const CIMName& propName, Array <String>& propValues ) { CIMProperty prop; Array<CIMKeyBinding> kbArray; CIMKeyBinding kb; kb.setName(PROPERTY_NAME); kb.setValue(propName.getString()); kb.setType(CIMKeyBinding::STRING); kbArray.append(kb); CIMObjectPath reference( _hostName, PEGASUS_NAMESPACENAME_CONFIG, PEGASUS_CLASSNAME_CONFIGSETTING, kbArray); CIMInstance cimInstance = _client->getInstance(PEGASUS_NAMESPACENAME_CONFIG, reference); Uint32 pos = cimInstance.findProperty(PROPERTY_NAME); prop = (CIMProperty)cimInstance.getProperty(pos); propValues.append(prop.getValue().toString()); pos = cimInstance.findProperty(DEFAULT_VALUE); prop = (CIMProperty)cimInstance.getProperty(pos); propValues.append(prop.getValue().toString()); pos = cimInstance.findProperty(CURRENT_VALUE); prop = (CIMProperty)cimInstance.getProperty(pos); propValues.append(prop.getValue().toString()); pos = cimInstance.findProperty(PLANNED_VALUE); prop = (CIMProperty)cimInstance.getProperty(pos); propValues.append(prop.getValue().toString()); pos = cimInstance.findProperty(DYNAMIC_PROPERTY); prop = (CIMProperty)cimInstance.getProperty(pos); propValues.append(prop.getValue().toString()); } /** Send an updated property value to the CIM Server. */ void CIMConfigCommand::_updatePropertyInCIMServer ( ostream& outPrintWriter, ostream& errPrintWriter, const CIMName& propName, const String& propValue, Boolean isUnsetOperation ) { Array<CIMKeyBinding> kbArray; CIMKeyBinding kb; kb.setName(PROPERTY_NAME); kb.setValue(propName.getString()); kb.setType(CIMKeyBinding::STRING); kbArray.append(kb); CIMObjectPath reference( _hostName, PEGASUS_NAMESPACENAME_CONFIG, PEGASUS_CLASSNAME_CONFIGSETTING, kbArray); if (_timeoutSeconds == 0) { _timeoutSeconds = (PEGASUS_DEFAULT_CLIENT_TIMEOUT_MILLISECONDS / 1000); } Array<CIMParamValue> inParams; Array<CIMParamValue> outParams; inParams.append( CIMParamValue(PARAM_PROPERTYVALUE, CIMValue(propValue))); inParams.append( CIMParamValue( PARAM_RESETVALUE, CIMValue(isUnsetOperation))); inParams.append( CIMParamValue( PARAM_UPDATEPLANNEDVALUE, CIMValue(_plannedValueSet))); inParams.append( CIMParamValue( PARAM_UPDATECURRENTVALUE, CIMValue(_currentValueSet))); inParams.append( CIMParamValue( PARAM_TIMEOUTPERIOD, CIMValue(_timeoutSeconds))); // Set timeout and add some grace time. _client->setTimeout( (_timeoutSeconds + 10) * 1000); _client->invokeMethod( PEGASUS_NAMESPACENAME_CONFIG, reference, METHOD_UPDATE_PROPERTY_VALUE, inParams, outParams); } /** get a list of all property names and value from the CIM Server. */ void CIMConfigCommand::_listAllPropertiesInCIMServer ( ostream& outPrintWriter, ostream& errPrintWriter, Array <CIMName>& propNames, Array <String>& propValues ) { Array<CIMInstance> configNamedInstances; if ( _currentValueSet || _plannedValueSet ) { // // get all the instances of class PG_ConfigSetting // configNamedInstances = _client->enumerateInstances( PEGASUS_NAMESPACENAME_CONFIG, PEGASUS_CLASSNAME_CONFIGSETTING); // // copy all the property names and values // for (Uint32 i = 0; i < configNamedInstances.size(); i++) { CIMInstance& configInstance = configNamedInstances[i]; Uint32 pos = configInstance.findProperty (CIMName ("PropertyName")); CIMProperty prop = (CIMProperty)configInstance.getProperty(pos); propNames.append(prop.getValue().toString()); if (_currentValueSet) { // // get current value // pos = configInstance.findProperty(CIMName ("CurrentValue")); prop = (CIMProperty)configInstance.getProperty(pos); propValues.append(prop.getValue().toString()); } else if (_plannedValueSet) { // // get planned value // pos = configInstance.findProperty(CIMName ("PlannedValue")); prop = (CIMProperty)configInstance.getProperty(pos); propValues.append(prop.getValue().toString()); } } } else { // // call enumerateInstanceNames // Array<CIMObjectPath> instanceNames = _client->enumerateInstanceNames( PEGASUS_NAMESPACENAME_CONFIG, PEGASUS_CLASSNAME_CONFIGSETTING); // // copy all the property names // for (Uint32 i = 0; i < instanceNames.size(); i++) { Array<CIMKeyBinding> kbArray = instanceNames[i].getKeyBindings(); if (kbArray.size() > 0) { propNames.append(kbArray[0].getValue()); } } } } PEGASUS_NAMESPACE_END // // exclude main from the Pegasus Namespace // PEGASUS_USING_PEGASUS; PEGASUS_USING_STD; /////////////////////////////////////////////////////////////////////////////// /** Parses the command line, and execute the command. @param args the string array containing the command line arguments */ /////////////////////////////////////////////////////////////////////////////// int main (int argc, char* argv []) { #ifdef PEGASUS_OS_PASE // Allow user group name larger than 8 chars in PASE environemnt setenv("PASE_USRGRP_LIMITED","N",1); #endif AutoPtr<CIMConfigCommand> command; Uint32 returnCode; //l10n set message loading to process locale MessageLoader::_useProcessLocale = true; MessageLoader::setPegasusMsgHomeRelative(argv[0]); #ifdef PEGASUS_OS_PASE // Check special authorities in PASE environment if (!umeCheckCmdAuthorities(false)) return Command::RC_ERROR; #endif #ifdef PEGASUS_OS_ZOS // for z/OS set stdout and stderr to EBCDIC setEBCDICEncoding(STDOUT_FILENO); setEBCDICEncoding(STDERR_FILENO); #endif command.reset(new CIMConfigCommand ()); try { command->setCommand (argc, argv); } catch (const CommandFormatException& cfe) { cerr << COMMAND_NAME << ": " << cfe.getMessage() << endl; MessageLoaderParms parms(ERR_USAGE_KEY,ERR_USAGE); parms.msg_src_path = MSG_PATH; cerr << COMMAND_NAME << ": " << MessageLoader::getMessage(parms) << endl; exit (Command::RC_ERROR); } returnCode = command->execute (cout, cerr); command.reset(); exit (returnCode); return 0; }
No CVS admin address has been configured |
Powered by ViewCVS 0.9.2 |