2016-03-16 20:15:24 +00:00
|
|
|
#include "shell.h"
|
2016-03-18 17:48:16 +00:00
|
|
|
namespace mshconsole {
|
2016-03-16 20:15:24 +00:00
|
|
|
|
2016-04-16 17:21:39 +00:00
|
|
|
Command::Command(const string& n, int (*funcptr)(CommandExecutor* whoExecuted,const Datas& data, const vector<const char*> argv)) :
|
|
|
|
name(n), funcCommand(funcptr), optionNum(0){
|
2016-03-18 17:48:16 +00:00
|
|
|
checkObj();
|
|
|
|
}
|
2016-03-16 20:15:24 +00:00
|
|
|
|
2016-04-16 17:21:39 +00:00
|
|
|
void Command::addOption(const poptOption& a){
|
|
|
|
if(a.arg!=NULL&&a.arg!=nullptr&&a.arg!=0) throw InvalidOptionException{};
|
|
|
|
for(int i=0; i<opts.size(); i++)
|
|
|
|
if(strcmp((opts[i].longName),(a.longName))==0||
|
|
|
|
opts[i].shortName==a.shortName)
|
|
|
|
throw DuplicatedOptionException();
|
|
|
|
opts.push_back(a);
|
|
|
|
optionNum++;
|
2016-04-06 19:39:27 +00:00
|
|
|
}
|
|
|
|
|
2016-04-16 17:21:39 +00:00
|
|
|
int Command::execute(const struct Params& p, CommandExecutor* c){
|
|
|
|
if(p.argc<=0) return -1;
|
2016-04-02 14:28:03 +00:00
|
|
|
|
2016-04-16 17:21:39 +00:00
|
|
|
// options a, b, c take integer arguments
|
|
|
|
// options f and g take no arguments
|
|
|
|
poptContext pc;
|
|
|
|
opts.push_back(POPT_TERMINATOR);
|
2016-04-02 14:28:03 +00:00
|
|
|
|
2016-04-16 17:21:39 +00:00
|
|
|
Datas datas;
|
|
|
|
for(int i=0; i<optionNum; i++){
|
|
|
|
Data* tmp = new Data(&opts[i]);
|
|
|
|
opts[i].arg=&(tmp->d);
|
|
|
|
datas.push_back(tmp);
|
2016-04-02 14:28:03 +00:00
|
|
|
}
|
|
|
|
|
2016-04-16 17:21:39 +00:00
|
|
|
// pc is the context for all popt-related functions
|
|
|
|
pc = poptGetContext(NULL, p.argc, const_cast<const char**>(p.argv), opts.data(), 0);
|
|
|
|
poptSetOtherOptionHelp(pc, "[ARG...]");
|
|
|
|
if (p.argc < 2 && opts.size()==0) {
|
|
|
|
poptPrintUsage(pc, stderr, 0);
|
|
|
|
return 1;
|
2016-04-02 14:28:03 +00:00
|
|
|
}
|
2016-04-06 19:39:27 +00:00
|
|
|
|
2016-04-16 17:21:39 +00:00
|
|
|
// process options and handle each val returned
|
|
|
|
int val;
|
|
|
|
while ((val = poptGetNextOpt(pc)) >= 0);
|
2016-04-06 19:39:27 +00:00
|
|
|
|
2016-04-16 17:21:39 +00:00
|
|
|
// poptGetNextOpt returns -1 when the final argument has been parsed
|
|
|
|
// otherwise an error occured
|
|
|
|
if (val != -1) {
|
|
|
|
cerr << name << ": ";
|
|
|
|
switch(val) {
|
|
|
|
case POPT_ERROR_NOARG:
|
|
|
|
cerr << "argument missing for an option\n";
|
|
|
|
return 1;
|
|
|
|
case POPT_ERROR_BADOPT:
|
|
|
|
cerr << "option not found\n";
|
|
|
|
return 1;
|
|
|
|
case POPT_ERROR_BADNUMBER:
|
|
|
|
case POPT_ERROR_OVERFLOW:
|
|
|
|
cerr << "option could not be converted to number\n";
|
|
|
|
return 1;
|
|
|
|
default:
|
|
|
|
cerr << "unknown error in option processing\n";
|
|
|
|
return 1;
|
2016-04-02 14:28:03 +00:00
|
|
|
}
|
|
|
|
}
|
2016-04-06 19:39:27 +00:00
|
|
|
|
2016-04-16 17:21:39 +00:00
|
|
|
vector<const char*> nonOptionArgs;
|
|
|
|
while (poptPeekArg(pc) != NULL)
|
|
|
|
nonOptionArgs.push_back(const_cast<const char*>(poptGetArg(pc)));
|
2016-04-06 19:39:27 +00:00
|
|
|
|
2016-04-16 17:21:39 +00:00
|
|
|
return (*funcCommand)(c,datas,nonOptionArgs);
|
2016-03-18 17:48:16 +00:00
|
|
|
}
|
2016-03-16 20:15:24 +00:00
|
|
|
|
2016-04-16 17:21:39 +00:00
|
|
|
const string& Command::getName(){
|
2016-03-18 17:48:16 +00:00
|
|
|
return this->name;
|
|
|
|
}
|
2016-03-16 20:15:24 +00:00
|
|
|
|
2016-03-18 17:48:16 +00:00
|
|
|
Command::Command(const Command& old) : name(old.name) , funcCommand(old.funcCommand){
|
|
|
|
checkObj();
|
|
|
|
}
|
2016-03-16 20:15:24 +00:00
|
|
|
|
2016-03-18 17:48:16 +00:00
|
|
|
void Command::checkObj(){
|
|
|
|
for(unsigned int i=0; i<name.length(); i++){
|
|
|
|
if(!((name[i]>'a'&&name[i]<'z')||(name[i]>'A'&&name[i]<'Z'))){
|
|
|
|
throw CommandNameNotValidException();
|
|
|
|
}
|
2016-03-16 20:15:24 +00:00
|
|
|
}
|
|
|
|
}
|
2016-04-16 17:21:39 +00:00
|
|
|
const struct poptOption Command::POPT_TERMINATOR = {NULL,'\0',POPT_ARG_NONE,NULL,-1,NULL,NULL};
|
2016-03-18 17:48:16 +00:00
|
|
|
}
|