hs.hsadmin/hsacppcli/hsadminc/source/cmdlineparser.cpp

773 lines
22 KiB
C++
Raw Normal View History

/***************************************************************************
* Copyright (C) 2005 by Christof Donat *
* cdonat@gmx.de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/format.hpp>
#include <iostream>
#include <sstream>
#include <fstream>
#include "cmdlineparser.h"
#include "logger.h"
#include <termios.h>
#include <unistd.h>
namespace commandline {
using std::cout;
using std::cin;
using std::flush;
using std::ifstream;
using std::ostringstream;
using boost::lexical_cast;
using boost::bad_lexical_cast;
using boost::shared_ptr;
using boost::scoped_ptr;
using boost::starts_with;
using boost::erase_first;
// dynamic cast needs this
vector<string> callParameter::parseDisplayspec() {
vector<string> rval;
boost::regex pattern("\\$\\{([^\\}]*)\\}");
boost::sregex_iterator end;
for(boost::sregex_iterator i(this->m_display.begin(),this->m_display.end(),pattern); i != end; i++ )
rval.insert(rval.end(),(*i)[1]);
Logger::log(Logger::DEBUG,"have parsed displayspec Parameter '"+this->m_display+"'");
return rval;
}
string callParameter::evalDisplay(const map<string, string> &values) {
string rval = this->m_display;
string::size_type pos;
for( map<string,string>::const_iterator i = values.begin(); i != values.end(); i++ ) {
string pattstring = "${"+i->first+"}";
while( (pos = rval.find(pattstring,0)) != string::npos ) rval.replace(pos,pattstring.length(),i->second);
}
while( (pos = rval.find("\\n",0)) != string::npos ) rval.replace(pos,2,"\n");
while( (pos = rval.find("\\t",0)) != string::npos ) rval.replace(pos,2,"\t");
while( (pos = rval.find("\\r",0)) != string::npos ) rval.replace(pos,2,"\r");
Logger::log(Logger::DEBUG,"have evaluated displayspec Parameter '"+this->m_display+"': '"+rval+"'");
return rval;
}
string setParameter::toXML(string &username, shared_ptr< ::ConfigFileParser > cfgfile) {
string rpccall = "<struct>";
rpccall += "<member><name>property</name><value>"+m_property+"</value></member>";
rpccall += "<member><name>value</name><value>"+m_value+"</value></member>";
rpccall += "</struct>";
return rpccall;
}
string whereParameter::toXML(string &username, shared_ptr< ::ConfigFileParser > cfgfile) {
string rpccall = "<struct>";
rpccall += "<member><name>property</name><value>"+m_property+"</value></member>";
rpccall += "<member><name>value</name><value>"+m_pattern+"</value></member>";
rpccall += "</struct>";
return rpccall;
}
string orderParameter::toXML(string &username, shared_ptr< ::ConfigFileParser > cfgfile) {
string rpccall = "<struct>";
rpccall += "<member><name>property</name><value>"+m_property+"</value></member>";
rpccall += "<member><name>ascending</name><value><boolean>";
rpccall += string((m_ascending?"1":"0"))+"</boolean></value></member>";
rpccall += "</struct>";
return rpccall;
}
string callParameter::toXML(string &username, shared_ptr< ::ConfigFileParser > cfgfile) {
string rpccall = "<struct>";
rpccall += "<member>";
rpccall += "<name>module</name>";
rpccall += "<value>"+m_module+"</value>";
rpccall += "</member>";
rpccall += "<member>";
rpccall += "<name>function</name>";
rpccall += "<value>"+m_function+"</value>";
rpccall += "</member>";
if( m_force ) {
rpccall += "<member>";
rpccall += "<name>force</name>";
rpccall += "<value><boolean>1</boolean></value>";
rpccall += "</member>";
}
if( m_ignoreerror ) {
rpccall += "<member>";
rpccall += "<name>ignoreerror</name>";
rpccall += "<value><boolean>1</boolean></value>";
rpccall += "</member>";
}
// read
vector<string> reads = parseDisplayspec();
if(reads.size()) {
rpccall += "<member>";
rpccall += "<name>read</name>";
rpccall += "<value><array><data>";
for(vector<string>::iterator j = reads.begin(); j != reads.end(); j++ )
rpccall += "<value>"+(*j)+"</value>";
rpccall += "</data></array></value>";
rpccall += "</member>";
}
if( m_where.size() ) {
rpccall += "<member>";
rpccall += "<name>where</name>";
rpccall += "<value><array><data>";
for(vector<shared_ptr<whereParameter> >::iterator j = m_where.begin(); j != m_where.end(); j++ )
rpccall += "<value>"+((*j)->toXML(username,cfgfile))+"</value>";
rpccall += "</data></array></value>";
rpccall += "</member>";
}
if( m_set.size() ) {
rpccall += "<member>";
rpccall += "<name>set</name>";
rpccall += "<value><array><data>";
for(vector<shared_ptr<setParameter> >::iterator j = m_set.begin(); j != m_set.end(); j++ )
rpccall += "<value>"+((*j)->toXML(username,cfgfile))+"</value>";
rpccall += "</data></array></value>";
rpccall += "</member>";
}
if( m_order.size() ) {
rpccall += "<member>";
rpccall += "<name>order</name>";
rpccall += "<value><array><data>";
for(vector<shared_ptr<orderParameter> >::iterator j = m_order.begin(); j != m_order.end(); j++ )
rpccall += "<value>"+((*j)->toXML(username,cfgfile))+"</value>";
rpccall += "</data></array></value>";
rpccall += "</member>";
}
if( m_objects.size() ) {
rpccall += "<member>";
rpccall += "<name>objectid</name>";
rpccall += "<value><array><data>";
for(vector<string>::iterator j = m_objects.begin(); j != m_objects.end(); j++ )
rpccall += "<value>"+(*j)+"</value>";
rpccall += "</data></array></value>";
rpccall += "</member>";
}
if( m_unset.size() ) {
rpccall += "<member>";
rpccall += "<name>unset</name>";
rpccall += "<value><array><data>";
for(vector<string>::iterator j = m_unset.begin(); j != m_unset.end(); j++ )
rpccall += "<value><struct><member><name>property</name><value>"+(*j)+"</value></member></struct></value>";
rpccall += "</data></array></value>";
rpccall += "</member>";
}
rpccall += "</struct>";
return rpccall;
}
parsedParameters::parsedParameters():
m_error(NOERROR),
m_user(""),
m_ticket(""),
m_defaultDisplay(""),
m_addConfigFile(""),
m_test(false),
m_ignoreerrors(false) {}
string parsedParameters::toXML(string &username, shared_ptr< ::ConfigFileParser > cfgfile) {
// begin method call
string rpccall = "<?xml version=\"1.0\"?><methodCall><methodName>hsadmin.transaction</methodName><params>";
// ticket
rpccall += "<param><value><string>";
if( this->m_ticket != "" ) {
string ticket;
ifstream file(this->m_ticket.c_str());
if( ! file ) {
string msg = Logger::getMessageFormatString(Logger::CouldNotOpenFile);
boost::format fmt(msg);
fmt % this->m_ticket;
Logger::log(Logger::FATAL,fmt.str());
exit(-1);
}
char ch;
while(file.get(ch)) ticket += ch;
boost::regex findticket(".*\\n---\\n");
ticket = boost::regex_replace(ticket,findticket,"");
if( ticket[ticket.size()-1] == '\0' ) ticket = ticket.substr(0,ticket.size()-2);
rpccall += ticket;
} else {
rpccall += cfgfile->getTicket(username);
}
Logger::log(Logger::DEBUG,"have read ticket");
rpccall += "</string></value></param>";
// global Parameters
rpccall += "<param><value><struct>";
if( this->m_test )
rpccall += "<member><name>test</name><value><boolean>1</boolean></value></member>";
rpccall += "</struct></value></param>";
// calls Array
rpccall += "<param><value><array><data>";
for( vector<shared_ptr<callParameter> >::iterator c = m_call.begin(); c != m_call.end(); c++ )
rpccall += "<value>"+((*c)->toXML(username,cfgfile))+"</value>";
rpccall += "</data></array></value></param>";
rpccall += "</params></methodCall>\n";
return rpccall;
}
// specific Parser for --runas-Option
bool VerbosityOption::parseThis(vector<string>& options, shared_ptr<parsedParameters> result) {
bool rval = false;
if( starts_with(options[0], "-v") ) {
if( options[1] == "none" ||
options[1] == "normal" ||
options[1] == "high" ||
options[1] == "debug" ||
options[1] == "debugXML" ||
options[1] == "debugAll" ) {
if( rval = this->handle(options[1], result) ) {
if( options[0] == "-v" )
options.erase(options.begin(),options.begin()+2);
else {
erase_first(options[0], "v");
options.erase(options.begin()+1);
}
}
} else {
string p;
if( rval = this->handle(p, result) ) {
if( options[0] == "-v" )
options.erase(options.begin());
else
erase_first(options[0], "v");
}
}
}
if( starts_with(options[0], "--verbosity=") ) {
string p = options[0].substr(12);
if( rval = this->handle(p, result) )
options.erase(options.begin());
}
return rval;
}
// constuctors
TestOption::TestOption() {
m_longName = "test";
m_shortName = "t";
}
IgnoreErrorOption::IgnoreErrorOption() {
m_longName = "ignoreerror";
m_shortName = "e";
}
IgnoreErrorsOption::IgnoreErrorsOption() {
m_longName = "ignoreerrors";
m_shortName = "E";
}
VerbosityOption::VerbosityOption() {
m_longName = "verbosity";
m_shortName = "v";
m_parameterSeparator = "=";
}
RunAsOption::RunAsOption() {
m_longName = "runas";
m_shortName = "r";
m_parameterSeparator = "=";
}
TicketOption::TicketOption() {
m_longName = "ticket";
m_shortName = "T";
m_parameterSeparator = "=";
}
ConfigOption::ConfigOption() {
m_longName = "config";
m_shortName = "C";
m_parameterSeparator = "=";
}
ForceOption::ForceOption() {
m_longName = "force";
}
GlobalsOption::GlobalsOption() {
m_longName = "globals";
m_shortName = "l";
}
WhereOption::WhereOption() {
m_longName = "where";
m_shortName = "w";
m_parameterSeparator = ":";
}
OnlyOption::OnlyOption() {
m_longName = "only";
m_shortName = "W";
m_parameterSeparator = ":";
}
SetOption::SetOption() {
m_longName = "set";
m_shortName = "s";
m_parameterSeparator = ":";
}
SetAllOption::SetAllOption() {
m_longName = "setall";
m_shortName = "S";
m_parameterSeparator = ":";
}
InfileOption::InfileOption() {
m_longName = "infile";
m_shortName = "f";
m_parameterSeparator = ":";
}
OrderOption::OrderOption() {
m_longName = "order";
m_shortName = "o";
m_parameterSeparator = ":";
}
GlobalOrderOption::GlobalOrderOption() {
m_longName = "global-order";
m_shortName = "O";
m_parameterSeparator = ":";
}
InputOption::InputOption() {
m_longName = "input";
m_shortName = "i";
m_parameterSeparator = ":";
}
PassInputOption::PassInputOption() {
m_longName = "passinput";
m_shortName = "p";
m_parameterSeparator = ":";
}
DisplayOption::DisplayOption() {
m_longName = "display";
m_shortName = "d";
m_parameterSeparator = ":";
}
DefaultDisplayOption::DefaultDisplayOption() {
m_longName = "default-display";
m_shortName = "D";
m_parameterSeparator = ":";
}
CallOption::CallOption() {
m_longName = "call";
m_shortName = "c";
m_parameterSeparator = ":";
}
UnsetOption::UnsetOption() {
m_longName = "unset";
m_shortName = "u";
m_parameterSeparator = ":";
}
UnsetAllOption::UnsetAllOption() {
m_longName = "unsetall";
m_shortName = "U";
m_parameterSeparator = ":";
}
ObjectID::ObjectID() { };
// handle functions
bool TestOption::handle(shared_ptr<parsedParameters> result) {
result->m_test = true;
Logger::log(Logger::DEBUG," found test Option");
return true;
}
bool IgnoreErrorOption::handle(shared_ptr<parsedParameters> result) {
if( result->m_call.size() <= 0 ) {
result->m_error = NeedCall;
return false;
}
result->m_call.back()->m_ignoreerror = true;
Logger::log(Logger::DEBUG," found ignoreerror Option");
return true;
}
bool IgnoreErrorsOption::handle(shared_ptr<parsedParameters> result) {
result->m_ignoreerrors = true;
Logger::log(Logger::DEBUG," found ignoreerrors Option");
return true;
}
bool VerbosityOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
if( parameter == "none" ) Logger::setLevel(0);
else if( parameter == "normal") Logger::setLevel(1);
else if( parameter == "high") Logger::setLevel(2);
else if( parameter == "debug") Logger::setLevel(3);
else if( parameter == "debugXML") Logger::setLevel(4);
else if( parameter == "debugAll") Logger::setLevel(5);
else Logger::incrementLevel();
Logger::log(Logger::DEBUG," set Verbosity Level to "+lexical_cast<string>(Logger::level));
return true;
}
bool QuietOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
Logger::decrementLevel();
Logger::log(Logger::DEBUG," set Verbosity Level to "+lexical_cast<string>(Logger::level));
return true;
}
bool RunAsOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
result->m_user = parameter;
Logger::log(Logger::DEBUG," found runas Option: "+parameter);
return true;
}
bool TicketOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
result->m_ticket = parameter;
Logger::log(Logger::DEBUG," found ticket Option: "+parameter);
return true;
}
bool ConfigOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
result->m_addConfigFile = parameter;
Logger::log(Logger::DEBUG," found config Option: "+parameter);
return true;
}
bool ForceOption::handle(shared_ptr<parsedParameters> result) {
if( result->m_call.size() <= 0 ) {
result->m_error = NeedCall;
return false;
}
result->m_call.back()->m_force = true;
Logger::log(Logger::DEBUG," found force Option");
return true;
}
bool GlobalsOption::handle(shared_ptr<parsedParameters> result) {
if( result->m_call.size() <= 0 ) {
result->m_error = NeedCall;
return false;
}
result->m_call.back()->m_globalOrderIndex = result->m_call.back()->m_order.size();
Logger::log(Logger::DEBUG," found globals Option");
return true;
}
bool WhereOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
if( result->m_call.size() <= 0 ) {
result->m_error = NeedCall;
return false;
}
string::size_type pos = parameter.find('=');
string property(parameter,0,pos);
string pattern(parameter,(pos != string::npos)?(pos+1):(string::npos));
whereParameter *where = new whereParameter();
where->m_property = property;
where->m_pattern = pattern;
result->m_call.back()->m_where.push_back(shared_ptr<whereParameter>(where));
Logger::log(Logger::DEBUG," found where Option: "+parameter);
return true;
}
bool OnlyOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
string::size_type pos = parameter.find('=');
string property(parameter,0,pos);
string pattern(parameter,(pos != string::npos)?(pos+1):(string::npos));
whereParameter *where = new whereParameter();
where->m_property = property;
where->m_pattern = pattern;
result->m_only.push_back(shared_ptr<whereParameter>(where));
Logger::log(Logger::DEBUG," found only Option: "+parameter);
return true;
}
bool UnsetOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
if( result->m_call.size() <= 0 ) {
result->m_error = NeedCall;
return false;
}
result->m_call.back()->m_unset.push_back(parameter);
Logger::log(Logger::DEBUG," found unset Option: "+parameter);
return true;
}
bool UnsetAllOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
result->m_unsetall.push_back(parameter);
Logger::log(Logger::DEBUG," found unsetall Option: "+parameter);
return true;
}
bool OrderOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
if( result->m_call.size() <= 0 ) {
result->m_error = NeedCall;
return false;
}
string::size_type pos = parameter.find('=');
string *property;
string * direction;
if( pos != string::npos ) {
property = new string(parameter,0,pos);
direction = new string(parameter,(pos != string::npos)?(pos+1):(string::npos));
} else {
property = new string(parameter);
direction = new string("a");
}
orderParameter *order = new orderParameter();
order->m_property = *property;
order->m_ascending = ((*direction)[0] == 'a');
result->m_call.back()->m_order.push_back(shared_ptr<orderParameter>(order));
Logger::log(Logger::DEBUG," found order Option: "+parameter);
return true;
}
bool GlobalOrderOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
string::size_type pos = parameter.find('=');
string *property;
string * direction;
if( pos != string::npos ) {
property = new string(parameter,0,pos);
direction = new string(parameter,(pos != string::npos)?(pos+1):(string::npos));
} else {
property = new string(parameter);
direction = new string("a");
}
orderParameter *order = new orderParameter();
order->m_property = *property;
order->m_ascending = ((*direction)[0] == 'a');
result->m_globalOrder.push_back(shared_ptr<orderParameter>(order));
Logger::log(Logger::DEBUG," found global order Option: "+parameter);
return true;
}
bool SetOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
if( result->m_call.size() <= 0 ) {
result->m_error = NeedCall;
return false;
}
string::size_type pos = parameter.find('=');
string property(parameter,0,pos);
string value(parameter,(pos != string::npos)?(pos+1):(string::npos));
setParameter *set = new setParameter();
set->m_property = property;
set->m_value = value;
result->m_call.back()->m_set.push_back(shared_ptr<setParameter>(set));
Logger::log(Logger::DEBUG," found set Option: "+parameter);
return true;
}
bool SetAllOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
string::size_type pos = parameter.find('=');
string property(parameter,0,pos);
string value(parameter,(pos != string::npos)?(pos+1):(string::npos));
setParameter *set = new setParameter();
set->m_property = property;
set->m_value = value;
result->m_setall.push_back(shared_ptr<setParameter>(set));
Logger::log(Logger::DEBUG," found setall Option: "+parameter);
return true;
}
bool InfileOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
if( result->m_call.size() <= 0 ) {
result->m_error = NeedCall;
return false;
}
string::size_type pos = parameter.find('=');
string property(parameter,0,pos);
string filename(parameter,(pos != string::npos)?(pos+1):(string::npos));
setParameter *set = new setParameter();
set->m_property = property;
ifstream file(filename.c_str());
if( ! file ) {
string msg = Logger::getMessageFormatString(Logger::CouldNotOpenFile);
boost::format fmt(msg);
fmt % filename;
Logger::log(Logger::FATAL,fmt.str());
exit(-1);
}
char ch;
while(file.get(ch)) set->m_value += ch;
result->m_call.back()->m_set.push_back(shared_ptr<setParameter>(set));
Logger::log(Logger::DEBUG," found infile Option: "+parameter);
return true;
}
bool InputOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
if( result->m_call.size() <= 0 ) {
result->m_error = NeedCall;
return false;
}
setParameter *set = new setParameter();
set->m_property = parameter;
cout << "Eingabe (" << parameter << "): " << flush;
std::getline(cin, set->m_value);
result->m_call.back()->m_set.push_back(shared_ptr<setParameter>(set));
Logger::log(Logger::DEBUG," found input Option: "+parameter);
return true;
}
string readPasswd() {
string rval = "";
struct termios t, t2;
tcgetattr(0,&t);
t2 = t;
t2.c_lflag &= ~ECHO;
tcsetattr(0,TCSANOW,&t2);
std::getline(cin, rval);
tcsetattr(0,TCSANOW,&t);
return rval;
}
bool PassInputOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
if( result->m_call.size() <= 0 ) {
result->m_error = NeedCall;
return false;
}
setParameter *set = new setParameter();
set->m_property = parameter;
cout << "Passworteingabe (" << parameter << "): " << flush;
set->m_value = readPasswd();
result->m_call.back()->m_set.push_back(shared_ptr<setParameter>(set));
Logger::log(Logger::DEBUG," found password-input Option: "+parameter);
return true;
}
bool DisplayOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
if( result->m_call.size() <= 0 ) {
result->m_error = NeedCall;
return false;
}
result->m_call.back()->m_display = parameter;
Logger::log(Logger::DEBUG," found display Option: "+parameter);
return true;
}
bool DefaultDisplayOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
result->m_defaultDisplay = parameter;
Logger::log(Logger::DEBUG," found default display Option: "+parameter);
return true;
}
bool ObjectID::handle(string &parameter, shared_ptr<parsedParameters> result) {
if( result->m_call.size() <= 0 ) {
result->m_error = NeedCall;
return false;
}
result->m_call.back()->m_objects.push_back(parameter);
Logger::log(Logger::DEBUG," found an ObjectID: "+parameter);
return true;
}
bool CallOption::handle(string &parameter, shared_ptr<parsedParameters> result) {
string::size_type pos = parameter.find('.');
string module(parameter,0,pos);
string function(parameter,(pos != string::npos)?(pos+1):(string::npos));
callParameter *call = new callParameter();
call->m_module = module;
call->m_function = function;
result->m_call.push_back(shared_ptr<callParameter>(call));
Logger::log(Logger::DEBUG," found call Option: "+parameter);
return true;
}
};