Renamed some functions and variables in SIGINT handling. README updated. Removed "using" directives in the headers. Input, output and error streams are now fields
of Shell. stringToArgcArgv has its own namespace.
This commit is contained in:
parent
f6c3135c27
commit
5d68248b18
15 changed files with 646 additions and 315 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -2,7 +2,7 @@
|
||||||
build-*
|
build-*
|
||||||
|
|
||||||
#internal test
|
#internal test
|
||||||
msh-console-library/main.cpp
|
#msh-console-library/main.cpp
|
||||||
|
|
||||||
# Autosaves
|
# Autosaves
|
||||||
*.autosave
|
*.autosave
|
||||||
|
|
17
README.md
17
README.md
|
@ -1,8 +1,17 @@
|
||||||
# msh-console
|
# Msh-console
|
||||||
Library that provides a bash-like interface for CLI C++ programs
|
* included flag handling implemented with popt.h;
|
||||||
|
Library that provides a bash-like command line for C++ programs. Features included:
|
||||||
|
* creation of personalized commands in the same thread of the shell or in other threads;
|
||||||
|
* basic shell functionalities, such as execution of other programs in the system. This is implemented with execvp().
|
||||||
|
What is not actually included:
|
||||||
|
* advanced shell features, like:
|
||||||
|
* piping,
|
||||||
|
* redirection,
|
||||||
|
* scripting,
|
||||||
|
* command history.
|
||||||
### Credits
|
### Credits
|
||||||
Code based on "Write a Shell in C" - by Stephen Brennan (http://brennan.io/2015/01/16/write-a-shell-in-c/)
|
Code based on "Write a Shell in C" tutorial by Stephen Brennan (http://brennan.io/2015/01/16/write-a-shell-in-c/).
|
||||||
The code has been slightly modified.
|
The code has been slightly modified.
|
||||||
The code contains stringtoargcargv.cpp, a set of functions written by Bernhard Eder (http://web.archive.org/web/20121030075237/http://bbgen.net/blog/2011/06/string-to-argc-argv) for parsing a string into argc and argv.
|
The code contains stringtoargcargv.cpp, a set of functions written by Bernhard Eder (http://web.archive.org/web/20121030075237/http://bbgen.net/blog/2011/06/string-to-argc-argv) for parsing a string into argc and argv.
|
||||||
### The library
|
### Compiling
|
||||||
The library can be compiled as shared library with the CMakeLists.txt file already in msh-console-library/.
|
The library can be compiled as shared library with the CMakeLists.txt file already in msh-console-library/.
|
||||||
|
|
|
@ -1,22 +1,38 @@
|
||||||
# msh-console dynamic library by praticamentetilde (Claudio Maggioni)
|
# MIT License
|
||||||
# licensed with "The Unlicense"
|
#
|
||||||
|
# Copyright (c) 2016 Claudio Maggioni
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
project(msh-console-library)
|
project(msh-console-library)
|
||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -lpopt")
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -lpopt")
|
||||||
FILE(GLOB sources *.cpp)
|
list(APPEND SRC_LIST "command.cpp" "commandexecutor.h" "commands.cpp" "datas.cpp" "shell.cpp" "stringtoargcargv.cpp"
|
||||||
FILE(GLOB headers *.h)
|
"commandexecutor.cpp" "command.h" "data.cpp" "main.cpp" "shell.h" "stringtoargcargv.h")
|
||||||
|
|
||||||
set(lib OFF)
|
set(lib ON) #off=debug demo with main.cpp, on=library
|
||||||
if(${lib})
|
if(${lib})
|
||||||
MESSAGE( STATUS "Building .so.1")
|
MESSAGE(STATUS "Building .so.1")
|
||||||
#compile the library
|
list(REMOVE_ITEM SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp) #remove demo file
|
||||||
# Create a library which includes the source listed.
|
|
||||||
# The extension is already found. Any number of sources could be listed here.
|
|
||||||
list(REMOVE_ITEM SRC_LIST ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
|
|
||||||
add_library (mshconsole SHARED ${SRC_LIST})
|
add_library (mshconsole SHARED ${SRC_LIST})
|
||||||
else(${lib})
|
else(${lib})
|
||||||
MESSAGE( STATUS "Building exec (debug only)")
|
MESSAGE(STATUS "Building exec (debug only)")
|
||||||
add_executable(${PROJECT_NAME} ${sources} ${headers})
|
add_executable(${PROJECT_NAME} ${SRC_LIST})
|
||||||
endif(${lib})
|
endif(${lib})
|
||||||
|
|
|
@ -1,7 +1,31 @@
|
||||||
|
/**
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 Claudio Maggioni
|
||||||
|
|
||||||
|
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 "shell.h"
|
#include "shell.h"
|
||||||
namespace mshconsole {
|
namespace mshconsole {
|
||||||
|
|
||||||
Command::Command(const string& n, int (*funcptr)(CommandExecutor* whoExecuted,const Datas& data, const vector<const char*> argv)) :
|
Command::Command(const std::string& n, int (*funcptr)(CommandExecutor* whoExecuted,const Datas& data, const std::vector<const char*> argv)) :
|
||||||
name(n), funcCommand(funcptr), optionNum(0){
|
name(n), funcCommand(funcptr), optionNum(0){
|
||||||
checkObj();
|
checkObj();
|
||||||
}
|
}
|
||||||
|
@ -16,7 +40,7 @@ namespace mshconsole {
|
||||||
optionNum++;
|
optionNum++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Command::execute(const struct Params& p, CommandExecutor* c){
|
int Command::execute(const struct Params& p, CommandExecutor* c, std::ostream& errorStream){
|
||||||
if(p.argc<=0) return -1;
|
if(p.argc<=0) return -1;
|
||||||
|
|
||||||
// options a, b, c take integer arguments
|
// options a, b, c take integer arguments
|
||||||
|
@ -46,32 +70,32 @@ namespace mshconsole {
|
||||||
// poptGetNextOpt returns -1 when the final argument has been parsed
|
// poptGetNextOpt returns -1 when the final argument has been parsed
|
||||||
// otherwise an error occured
|
// otherwise an error occured
|
||||||
if (val != -1) {
|
if (val != -1) {
|
||||||
cerr << name << ": ";
|
errorStream << name << ": ";
|
||||||
switch(val) {
|
switch(val) {
|
||||||
case POPT_ERROR_NOARG:
|
case POPT_ERROR_NOARG:
|
||||||
cerr << "argument missing for an option\n";
|
errorStream << "argument missing for an option\n";
|
||||||
return 1;
|
return 1;
|
||||||
case POPT_ERROR_BADOPT:
|
case POPT_ERROR_BADOPT:
|
||||||
cerr << "option not found\n";
|
errorStream << "option not found\n";
|
||||||
return 1;
|
return 1;
|
||||||
case POPT_ERROR_BADNUMBER:
|
case POPT_ERROR_BADNUMBER:
|
||||||
case POPT_ERROR_OVERFLOW:
|
case POPT_ERROR_OVERFLOW:
|
||||||
cerr << "option could not be converted to number\n";
|
errorStream << "option could not be converted to number\n";
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
cerr << "unknown error in option processing\n";
|
errorStream << "unknown error in option processing\n";
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<const char*> nonOptionArgs;
|
std::vector<const char*> nonOptionArgs;
|
||||||
while (poptPeekArg(pc) != NULL)
|
while (poptPeekArg(pc) != NULL)
|
||||||
nonOptionArgs.push_back(const_cast<const char*>(poptGetArg(pc)));
|
nonOptionArgs.push_back(const_cast<const char*>(poptGetArg(pc)));
|
||||||
|
|
||||||
return (*funcCommand)(c,datas,nonOptionArgs);
|
return (*funcCommand)(c,datas,nonOptionArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
const string& Command::getName(){
|
const std::string& Command::getName(){
|
||||||
return this->name;
|
return this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,32 @@
|
||||||
|
/**
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 Claudio Maggioni
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef COMMAND_H
|
#ifndef COMMAND_H
|
||||||
#define COMMAND_H
|
#define COMMAND_H
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
extern "C"{
|
extern "C"{
|
||||||
|
@ -9,15 +34,12 @@ extern "C"{
|
||||||
}
|
}
|
||||||
#include "commandexecutor.h"
|
#include "commandexecutor.h"
|
||||||
|
|
||||||
using std::string;
|
|
||||||
using std::vector;
|
|
||||||
|
|
||||||
namespace mshconsole{
|
namespace mshconsole{
|
||||||
class Command
|
class Command
|
||||||
{
|
{
|
||||||
const string name;
|
const std::string name;
|
||||||
void checkObj();
|
void checkObj();
|
||||||
vector<poptOption> opts;
|
std::vector<poptOption> opts;
|
||||||
static const struct poptOption POPT_TERMINATOR;
|
static const struct poptOption POPT_TERMINATOR;
|
||||||
size_t optionNum;
|
size_t optionNum;
|
||||||
|
|
||||||
|
@ -55,26 +77,26 @@ namespace mshconsole{
|
||||||
double getDouble() const;
|
double getDouble() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Datas : public vector<Data*>{
|
class Datas : public std::vector<Data*>{
|
||||||
public:
|
public:
|
||||||
Data* getOptData(const string& optionName) const;
|
Data* getOptData(const std::string& optionName) const;
|
||||||
Data* getOptData(char opt) const;
|
Data* getOptData(char opt) const;
|
||||||
Data* operator[](const string& opt) const;
|
Data* operator[](const std::string& opt) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DuplicatedOptionException{};
|
class DuplicatedOptionException{};
|
||||||
class CommandNameNotValidException{};
|
class CommandNameNotValidException{};
|
||||||
class InvalidOptionException{};
|
class InvalidOptionException{};
|
||||||
|
|
||||||
Command(const string& n, int (*funcptr)(CommandExecutor* whoExecuted,const Datas& data, const vector<const char*> argv));
|
Command(const std::string& n, int (*funcptr)(CommandExecutor* whoExecuted,const Datas& data, const std::vector<const char*> argv));
|
||||||
Command(const Command&);
|
Command(const Command&);
|
||||||
~Command();
|
~Command();
|
||||||
const string& getName();
|
const std::string& getName();
|
||||||
int execute(const struct Params&, CommandExecutor*);
|
int execute(const struct Params&, CommandExecutor*,std::ostream& errorStream=std::cerr);
|
||||||
void addOption(const poptOption& option);
|
void addOption(const poptOption& option);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int (*funcCommand)(CommandExecutor* whoExecuted,const Datas& data, const vector<const char*> argv);
|
int (*funcCommand)(CommandExecutor* whoExecuted,const Datas& data, const std::vector<const char*> argv);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,27 @@
|
||||||
|
/**
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 Claudio Maggioni
|
||||||
|
|
||||||
|
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 "commandexecutor.h"
|
#include "commandexecutor.h"
|
||||||
namespace mshconsole {
|
namespace mshconsole {
|
||||||
CommandExecutor::CommandExecutor() {}
|
CommandExecutor::CommandExecutor() {}
|
||||||
|
|
|
@ -1,3 +1,27 @@
|
||||||
|
/**
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 Claudio Maggioni
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef COMMANDEXECUTOR_H
|
#ifndef COMMANDEXECUTOR_H
|
||||||
#define COMMANDEXECUTOR_H
|
#define COMMANDEXECUTOR_H
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
|
@ -1,3 +1,27 @@
|
||||||
|
/**
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 Claudio Maggioni
|
||||||
|
|
||||||
|
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 "shell.h"
|
#include "shell.h"
|
||||||
namespace mshconsole {
|
namespace mshconsole {
|
||||||
Shell::Commands::Commands(Shell* s) : commands(), threadCommands()
|
Shell::Commands::Commands(Shell* s) : commands(), threadCommands()
|
||||||
|
|
|
@ -1,3 +1,27 @@
|
||||||
|
/**
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 Claudio Maggioni
|
||||||
|
|
||||||
|
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 "command.h"
|
#include "command.h"
|
||||||
|
|
||||||
namespace mshconsole{
|
namespace mshconsole{
|
||||||
|
|
|
@ -1,7 +1,31 @@
|
||||||
|
/**
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 Claudio Maggioni
|
||||||
|
|
||||||
|
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 "command.h"
|
#include "command.h"
|
||||||
|
|
||||||
namespace mshconsole {
|
namespace mshconsole {
|
||||||
Command::Data* Command::Datas::getOptData(const string& opt) const{
|
Command::Data* Command::Datas::getOptData(const std::string& opt) const{
|
||||||
for(size_t i=0; i<this->size(); i++){
|
for(size_t i=0; i<this->size(); i++){
|
||||||
if(opt == this->at(i)->of->longName) return this->at(i);
|
if(opt == this->at(i)->of->longName) return this->at(i);
|
||||||
}
|
}
|
||||||
|
@ -11,7 +35,7 @@ namespace mshconsole {
|
||||||
if(opt == this->at(i)->of->shortName) return this->at(i);
|
if(opt == this->at(i)->of->shortName) return this->at(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Command::Data* Command::Datas::operator [](const string& opt) const{
|
Command::Data* Command::Datas::operator [](const std::string& opt) const{
|
||||||
if(opt.length()>2) return getOptData(opt);
|
if(opt.length()>2) return getOptData(opt);
|
||||||
if(opt.length()==1) return getOptData(opt[0]);
|
if(opt.length()==1) return getOptData(opt[0]);
|
||||||
else return nullptr;
|
else return nullptr;
|
||||||
|
|
75
msh-console-library/main.cpp
Normal file
75
msh-console-library/main.cpp
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
#include "../msh-console-library/shell.h"
|
||||||
|
#include "../msh-console-library/command.h"
|
||||||
|
using namespace std;
|
||||||
|
using namespace mshconsole;
|
||||||
|
|
||||||
|
static void setup(Shell *);
|
||||||
|
|
||||||
|
int cdExecute(CommandExecutor* whoExecuted,const Command::Datas& data, const vector<const char*> argv){
|
||||||
|
if (argv.size() == 0) {
|
||||||
|
cerr << "expected argument to \"cd\"\n";
|
||||||
|
} else {
|
||||||
|
int ret;
|
||||||
|
if (strcmp("~",argv[0])==0) {
|
||||||
|
ret = chdir(getenv("HOME"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = chdir(argv[0]);
|
||||||
|
}
|
||||||
|
if (ret != 0) {
|
||||||
|
cerr << "cd: error executing the command\n";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int exitExecute(CommandExecutor* whoExecuted,const Command::Datas& data, const vector<const char*> argv){
|
||||||
|
whoExecuted->exit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int helpExecute(CommandExecutor* whoExecuted,const Command::Datas& data, const vector<const char*> argv){
|
||||||
|
cout << data.getOptData('p')->getString() << "\n";
|
||||||
|
if(data.getOptData('h')->getInt()){
|
||||||
|
cout << "These are the further details." << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(strcmp(data.getOptData('p')->getString(),"prova")==0){
|
||||||
|
cout << "prova\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cout << "Snippet console generated with msh-console library.\nUse option -h for further details." << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Little snippet for library use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
string c = "msh-console-test";
|
||||||
|
string ps = "[msh-console-test]:";
|
||||||
|
Shell mshConsoleTest(c, ps, cin,cout,cerr, &setup);
|
||||||
|
Command* help = new Command("help", &helpExecute);
|
||||||
|
struct poptOption h = {"help",'h',POPT_ARG_NONE,NULL,1000,"advance","advaced options"};
|
||||||
|
struct poptOption p = {"prova",'p',POPT_ARG_STRING,NULL,1000,"cose","cosecose"};
|
||||||
|
help->addOption(h);
|
||||||
|
help->addOption(p);
|
||||||
|
|
||||||
|
//add builtin commands
|
||||||
|
mshConsoleTest.addCmd(help);
|
||||||
|
mshConsoleTest.addCmd(new Command("exit", &exitExecute));
|
||||||
|
mshConsoleTest.addCmd(new Command("cd", &cdExecute));
|
||||||
|
mshConsoleTest.launch();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup(Shell *s){
|
||||||
|
cout << "Now entering in test shell...\n" << endl;
|
||||||
|
//s->executeCmd("stty -ctlecho");
|
||||||
|
}
|
|
@ -1,81 +1,109 @@
|
||||||
|
/**
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 Claudio Maggioni
|
||||||
|
|
||||||
|
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 "shell.h"
|
#include "shell.h"
|
||||||
namespace mshconsole {
|
namespace mshconsole {
|
||||||
string Shell::getPs() const
|
const std::string& Shell::getPs() const{
|
||||||
{
|
|
||||||
return ps;
|
return ps;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shell::setPs(const string &value)
|
void Shell::setPs(const std::string &value){
|
||||||
{
|
|
||||||
ps = value;
|
ps = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
string Shell::getName() const
|
const std::string& Shell::getName() const{
|
||||||
{
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shell::setName(const string &value)
|
void Shell::setName(const std::string &value){
|
||||||
{
|
|
||||||
name = value;
|
name = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Shell::Shell( string n, string ps,void (*s)(Shell*), void (*pss)(Shell*)) : cmds(this)
|
Shell::Shell(std::string nam, std::string ps, std::istream &i, std::ostream &o, std::ostream &e,
|
||||||
{
|
void (*s)(Shell*), void (*pss)(Shell*)) : cmds(this), inputStream(i),
|
||||||
|
outputStream(o), errorStream(e){
|
||||||
shellSetup = s;
|
shellSetup = s;
|
||||||
name = n;
|
name = nam;
|
||||||
this->ps = ps;
|
this->ps = ps;
|
||||||
shellPostSetup = pss;
|
shellPostSetup = pss;
|
||||||
notLoop = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Shell::launch(){
|
int Shell::launch(){
|
||||||
|
//Forbid launching shell if it is already launched in other threads.
|
||||||
|
static bool notLoop=false;
|
||||||
|
if(notLoop) return -1;
|
||||||
|
notLoop = true;
|
||||||
|
|
||||||
//launch setup
|
//Launch the shell setup.
|
||||||
if(notLoop) {
|
if(shellSetup!=0) (*shellSetup)(this);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if(shellSetup!=0) {
|
|
||||||
notLoop = true;
|
|
||||||
(*shellSetup)(this);
|
|
||||||
notLoop = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//launch loop
|
//Run the shell loop.
|
||||||
string* line;
|
|
||||||
struct Params p;
|
|
||||||
int exitCode;
|
int exitCode;
|
||||||
|
|
||||||
try{
|
try{
|
||||||
do {
|
std::string* line=nullptr;
|
||||||
bool readSuccess;
|
struct Params p;
|
||||||
do{
|
|
||||||
cout << ps << " ";
|
while(1){
|
||||||
|
delete line;
|
||||||
|
outputStream << ps << " "; //Print the prompt.
|
||||||
|
|
||||||
|
//Try reading the line. if SIGINT is caught, print another time the prompt and retry.
|
||||||
try{
|
try{
|
||||||
line = read_line();
|
line = readLine();
|
||||||
readSuccess = true;
|
|
||||||
}
|
}
|
||||||
catch (IsUndoingLineException){
|
catch (IsUndoingLineException){
|
||||||
cout << "\n";
|
outputStream << "\n";
|
||||||
readSuccess = false;
|
continue;
|
||||||
}
|
}
|
||||||
}while(!readSuccess);
|
|
||||||
p = split_line(line);
|
//Try line conversion from string to argc and argv. stringToArgcArgv() throws a std::runtime_error
|
||||||
executeCmd(p);
|
//exception if the string has unproper quotes.
|
||||||
} while (1);
|
try{
|
||||||
|
p = splitLine(line);
|
||||||
|
}
|
||||||
|
catch(std::runtime_error e){
|
||||||
|
errorStream << name << ": error in line parsing\n";
|
||||||
|
errorStream << e.what() << "\n";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Execute the command.
|
||||||
|
executeCmd(p);
|
||||||
|
};
|
||||||
} catch(CommandExecutor::ExitException c) {
|
} catch(CommandExecutor::ExitException c) {
|
||||||
exitCode=c.getCode();
|
exitCode=c.getCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
//launch postSetup
|
//Launch postSetup().
|
||||||
if(shellPostSetup!=0) {
|
if(shellPostSetup!=0) shellPostSetup(this);
|
||||||
shellPostSetup(this);
|
|
||||||
}
|
notLoop = false;
|
||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Shell::launchCmd(const struct Params& p)
|
int Shell::launchCmd(const struct Params& p){
|
||||||
{
|
|
||||||
using std::exit;
|
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
|
@ -84,21 +112,23 @@ namespace mshconsole {
|
||||||
|
|
||||||
//execute threadCommand
|
//execute threadCommand
|
||||||
int a;
|
int a;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
a=cmds.launch(p, true);
|
a=cmds.launch(p, true);
|
||||||
|
std::exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
catch (CommandNotFoundException){
|
catch (CommandNotFoundException){}
|
||||||
//execute bash command or program
|
|
||||||
if((a=execvp(p.argv[0], p.argv)) == -1) {
|
//execute bash command or program
|
||||||
cerr << name <<": command " << p.argv[0] << " not found\n";
|
if((a=execvp(p.argv[0], p.argv)) == -1) {
|
||||||
}
|
outputStream << name << ": execution failed. Errno is set to: "<<strerror(errno)<<"\n";
|
||||||
exit(EXIT_FAILURE);
|
std::exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
exit(EXIT_SUCCESS);
|
else std::exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
else if (pid < 0) {
|
else if (pid < 0) {
|
||||||
// Error forking
|
// Error forking
|
||||||
cerr << name <<": error forking the process\n";
|
errorStream << name <<": error in process forking.\n";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Parent process
|
// Parent process
|
||||||
|
@ -110,34 +140,32 @@ namespace mshconsole {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Shell::executeCmd(const struct Params& p)
|
int Shell::executeCmd(const struct Params& p){
|
||||||
{
|
if (!p.argc) return 1; //Return if the line is empty.
|
||||||
if (!p.argc) { //empty line
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
int ret;
|
|
||||||
try {
|
try {
|
||||||
ret = cmds.launch(p, false);
|
//Search in non-thread commands.
|
||||||
|
return cmds.launch(p, false);
|
||||||
}
|
}
|
||||||
catch(CommandNotFoundException) {
|
catch(CommandNotFoundException) {}
|
||||||
ret = launchCmd(p);
|
|
||||||
}
|
//Execute the threadCommand or the executable.
|
||||||
return ret;
|
return launchCmd(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int Shell::executeCmd(const std::string &args){
|
inline int Shell::executeCmd(const std::string &args){
|
||||||
return executeCmd(split_line(&args));
|
return executeCmd(splitLine(&args));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shell::EofHandler(int){
|
void Shell::SIGINTHandler(int,siginfo_t*, void *){
|
||||||
undoingLine = true;
|
SIGINTRaised = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shell::setShellSetup(void (*s)(Shell *)){
|
void Shell::setShellSetup(void (*s)(Shell *)){
|
||||||
shellSetup=s;
|
shellSetup=s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void (*Shell::getShellSetup())(Shell*) {
|
void (*Shell::getShellSetup())(Shell*) const{
|
||||||
return shellSetup;
|
return shellSetup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,40 +173,46 @@ namespace mshconsole {
|
||||||
shellPostSetup=s;
|
shellPostSetup=s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void (*Shell::getShellPostSetup())(Shell*) {
|
void (*Shell::getShellPostSetup())(Shell*) const{
|
||||||
return shellPostSetup;
|
return shellPostSetup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void setEofHandler(void (*funcptr)(int)){
|
struct sigaction* setHandler(unsigned signal, void (*funcptr)(int, siginfo_t*, void*)){
|
||||||
struct sigaction *sa = new struct sigaction();
|
struct sigaction* before = new struct sigaction();
|
||||||
sa->sa_handler = funcptr;
|
struct sigaction sa;
|
||||||
sa->sa_flags = 0; // not SA_RESTART!;
|
sa.sa_sigaction = funcptr;
|
||||||
sigaction(SIGINT, sa, NULL);
|
sa.sa_flags = 0;
|
||||||
delete sa;
|
sigaction(signal, &sa, before);
|
||||||
}
|
}
|
||||||
|
|
||||||
string* Shell::read_line()
|
void restoreHandler(unsigned signal, struct sigaction* before){
|
||||||
{
|
sigaction(signal, before, NULL);
|
||||||
string* buffer = new string();
|
delete before;
|
||||||
setEofHandler(EofHandler);
|
}
|
||||||
getline(cin,*buffer); // get command
|
|
||||||
cin.clear(); // clear flags
|
|
||||||
|
|
||||||
if(undoingLine){
|
std::string* Shell::readLine(){
|
||||||
undoingLine=false;
|
std::string* buffer = new std::string();
|
||||||
|
struct sigaction* beforeSIGINT = setHandler(SIGINT,SIGINTHandler);
|
||||||
|
getline(inputStream,*buffer); //Get line of input TODO: handle directional keys
|
||||||
|
inputStream.clear(); //Clear flags. This is needed for the detection of SIGINT
|
||||||
|
|
||||||
|
if(SIGINTRaised){
|
||||||
|
SIGINTRaised=false;
|
||||||
throw IsUndoingLineException();
|
throw IsUndoingLineException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
restoreHandler(SIGINT, beforeSIGINT);
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Params Shell::split_line(const string* line){
|
struct Params Shell::splitLine(const std::string* line){
|
||||||
struct Params p;
|
struct Params p;
|
||||||
stringToArgcArgv(*line, &(p.argc), &(p.argv));
|
stringToArgcArgv(*line, &(p.argc), &(p.argv));
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Shell::undoingLine = false;
|
bool Shell::SIGINTRaised = false;
|
||||||
|
|
||||||
void Shell::addCmd(Command* cmd, bool isthread){
|
void Shell::addCmd(Command* cmd, bool isthread){
|
||||||
cmds.add(cmd, isthread);
|
cmds.add(cmd, isthread);
|
||||||
|
|
|
@ -1,3 +1,27 @@
|
||||||
|
/**
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2016 Claudio Maggioni
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef SHELL_H
|
#ifndef SHELL_H
|
||||||
#define SHELL_H
|
#define SHELL_H
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -7,20 +31,14 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sstream>
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
#include <cerrno>
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include <wordexp.h>
|
#include <wordexp.h>
|
||||||
#include "commandexecutor.h"
|
#include "commandexecutor.h"
|
||||||
#include "stringtoargcargv.h"
|
#include "stringtoargcargv.h"
|
||||||
using std::string;
|
using namespace StringToArgcArgv;
|
||||||
using std::cin;
|
|
||||||
using std::cout;
|
|
||||||
using std::cerr;
|
|
||||||
using std::string;
|
|
||||||
using std::vector;
|
|
||||||
using std::istringstream;
|
|
||||||
|
|
||||||
namespace mshconsole {
|
namespace mshconsole {
|
||||||
|
|
||||||
|
@ -29,8 +47,8 @@ namespace mshconsole {
|
||||||
class Commands
|
class Commands
|
||||||
{
|
{
|
||||||
Shell* parent;
|
Shell* parent;
|
||||||
vector<Command*> commands; //commands that work the same thread of the shell
|
std::vector<Command*> commands; //commands that work the same thread of the shell
|
||||||
vector<Command*> threadCommands; //commands that work on a different thread
|
std::vector<Command*> threadCommands; //commands that work on a different thread
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Commands(Shell*);
|
Commands(Shell*);
|
||||||
|
@ -39,40 +57,47 @@ namespace mshconsole {
|
||||||
int launch(const struct Params& args, bool launchThread=false);
|
int launch(const struct Params& args, bool launchThread=false);
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool undoingLine;
|
static bool SIGINTRaised;
|
||||||
Commands cmds;
|
Commands cmds;
|
||||||
string ps;
|
std::string ps;
|
||||||
string name;
|
std::string name;
|
||||||
|
std::ostream& errorStream;
|
||||||
|
std::ostream& outputStream;
|
||||||
|
std::istream& inputStream;
|
||||||
void (*shellSetup)(Shell *);
|
void (*shellSetup)(Shell *);
|
||||||
void (*shellPostSetup)(Shell *);
|
void (*shellPostSetup)(Shell *);
|
||||||
bool notLoop;
|
|
||||||
|
|
||||||
int launchCmd(const struct Params& args);
|
int launchCmd(const struct Params& args);
|
||||||
static void EofHandler(int);
|
static void SIGINTHandler(int,siginfo_t *info, void *);
|
||||||
string* read_line();
|
std::string* readLine();
|
||||||
struct Params split_line(const string* line);
|
struct Params splitLine(const std::string* line);
|
||||||
|
|
||||||
class IsUndoingLineException {};
|
class IsUndoingLineException {};
|
||||||
class CommandNotFoundException {};
|
class CommandNotFoundException {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Shell(string n="msh", string ps="MSH$", void (*s)(Shell*)=0, void (*pss)(Shell*)=0);
|
Shell(std::string n, std::string ps, std::istream& inputStream, std::ostream& outputStream,
|
||||||
string getPs() const;
|
std::ostream& errorStream, void (*s)(Shell*)=0, void (*pss)(Shell*)=0);
|
||||||
void setPs(const string &value);
|
const std::string& getPs() const;
|
||||||
string getName() const;
|
void setPs(const std::string &value);
|
||||||
void setName(const string &value);
|
const std::string& getName() const;
|
||||||
|
void setName(const std::string &value);
|
||||||
int launch();
|
int launch();
|
||||||
void setShellSetup(void (*)(Shell *));
|
void setShellSetup(void (*)(Shell *));
|
||||||
void (*getShellSetup())(Shell*);
|
void (*getShellSetup())(Shell*) const;
|
||||||
void setShellPostSetup(void (*)(Shell *));
|
void setShellPostSetup(void (*)(Shell *));
|
||||||
void (*getShellPostSetup())(Shell*);
|
void (*getShellPostSetup())(Shell*) const;
|
||||||
|
|
||||||
//for in-shell commands
|
//for in-shell commands
|
||||||
void addCmd(Command *cmd, bool isThread=false);
|
void addCmd(Command *cmd, bool isThread=false);
|
||||||
size_t howManyCmds() const;
|
|
||||||
int executeCmd(const struct Params& args);
|
int executeCmd(const struct Params& args);
|
||||||
int executeCmd(const string& args);
|
int executeCmd(const std::string& args);
|
||||||
|
size_t howManyCmds() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern struct sigaction* setHandler(unsigned signal, void (*funcptr)(int, siginfo_t*, void*));
|
||||||
|
extern void restoreHandler(unsigned signal, struct sigaction* before);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SHELL_H
|
#endif // SHELL_H
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* stringtoargcargv.cpp -- Parsing a string to std::vector<string>
|
/** stringtoargcargv.cpp -- Parsing a string to std::vector<string>
|
||||||
|
|
||||||
Copyright (C) 2011 Bernhard Eder
|
Copyright (C) 2011 Bernhard Eder
|
||||||
|
|
||||||
|
@ -22,171 +22,176 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
///The code is modified for the null-termination of argv
|
||||||
|
|
||||||
#include "stringtoargcargv.h"
|
#include "stringtoargcargv.h"
|
||||||
|
|
||||||
/*
|
namespace StringToArgcArgv{
|
||||||
* Usage:
|
/*
|
||||||
* int argc;
|
* Usage:
|
||||||
* char** argv;
|
* int argc;
|
||||||
* stringToArgcArgv("foo bar", &argc, &argv);
|
* char** argv;
|
||||||
*/
|
* stringToArgcArgv("foo bar", &argc, &argv);
|
||||||
void stringToArgcArgv(const std::string& str, int* argc, char*** argv)
|
*/
|
||||||
{
|
void stringToArgcArgv(const std::string& str, int* argc, char*** argv)
|
||||||
std::vector<std::string> args = parse(str);
|
{
|
||||||
|
std::vector<std::string> args = parse(str);
|
||||||
|
|
||||||
*argv = (char**)std::malloc(args.size() * sizeof(char*));
|
*argv = (char**)std::malloc((args.size()+1) * sizeof(char*));
|
||||||
|
|
||||||
int i=0;
|
int i=0;
|
||||||
for(std::vector<std::string>::iterator it = args.begin();
|
for(std::vector<std::string>::iterator it = args.begin();
|
||||||
it != args.end();
|
it != args.end();
|
||||||
++it, ++i)
|
++it, ++i)
|
||||||
{
|
{
|
||||||
std::string arg = *it;
|
std::string arg = *it;
|
||||||
(*argv)[i] = (char*)std::malloc((arg.length()+1) * sizeof(char));
|
(*argv)[i] = (char*)std::malloc((arg.length()+1) * sizeof(char));
|
||||||
std::strcpy((*argv)[i], arg.c_str());
|
std::strcpy((*argv)[i], arg.c_str());
|
||||||
}
|
|
||||||
|
|
||||||
*argc = args.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> parse(const std::string& args)
|
|
||||||
{
|
|
||||||
std::stringstream ain(args); // used to iterate over input string
|
|
||||||
ain >> std::noskipws; // do not skip white spaces
|
|
||||||
std::vector<std::string> oargs; // output list of arguments
|
|
||||||
|
|
||||||
std::stringstream currentArg("");
|
|
||||||
currentArg >> std::noskipws;
|
|
||||||
|
|
||||||
// current state
|
|
||||||
enum State {
|
|
||||||
InArg, // currently scanning an argument
|
|
||||||
InArgQuote, // currently scanning an argument (which started with quotes)
|
|
||||||
OutOfArg // currently not scanning an argument
|
|
||||||
};
|
|
||||||
State currentState = OutOfArg;
|
|
||||||
|
|
||||||
char currentQuoteChar = '\0'; // to distinguish between ' and " quotations
|
|
||||||
// this allows to use "foo'bar"
|
|
||||||
|
|
||||||
char c;
|
|
||||||
while(!ain.eof() && (ain >> c)) { // iterate char by char
|
|
||||||
|
|
||||||
if(_isQuote(c)) {
|
|
||||||
switch(currentState) {
|
|
||||||
case OutOfArg:
|
|
||||||
currentArg.str(std::string());
|
|
||||||
case InArg:
|
|
||||||
currentState = InArgQuote;
|
|
||||||
currentQuoteChar = c;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case InArgQuote:
|
|
||||||
if(c == currentQuoteChar)
|
|
||||||
currentState = InArg;
|
|
||||||
else
|
|
||||||
currentArg << c;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
(*argv)[i]=NULL;
|
||||||
|
|
||||||
|
*argc = args.size();
|
||||||
}
|
}
|
||||||
else if(_isWhitespace(c)) {
|
|
||||||
switch(currentState) {
|
std::vector<std::string> parse(const std::string& args)
|
||||||
case InArg:
|
{
|
||||||
oargs.push_back(currentArg.str());
|
std::stringstream ain(args); // used to iterate over input string
|
||||||
currentState = OutOfArg;
|
ain >> std::noskipws; // do not skip white spaces
|
||||||
break;
|
std::vector<std::string> oargs; // output list of arguments
|
||||||
case InArgQuote:
|
|
||||||
currentArg << c;
|
std::stringstream currentArg("");
|
||||||
break;
|
currentArg >> std::noskipws;
|
||||||
case OutOfArg:
|
|
||||||
// nothing
|
// current state
|
||||||
break;
|
enum State {
|
||||||
}
|
InArg, // currently scanning an argument
|
||||||
}
|
InArgQuote, // currently scanning an argument (which started with quotes)
|
||||||
else if(_isEscape(c)) {
|
OutOfArg // currently not scanning an argument
|
||||||
switch(currentState) {
|
};
|
||||||
case OutOfArg:
|
State currentState = OutOfArg;
|
||||||
currentArg.str(std::string());
|
|
||||||
currentState = InArg;
|
char currentQuoteChar = '\0'; // to distinguish between ' and " quotations
|
||||||
case InArg:
|
// this allows to use "foo'bar"
|
||||||
case InArgQuote:
|
|
||||||
if(ain.eof())
|
char c;
|
||||||
{
|
while(!ain.eof() && (ain >> c)) { // iterate char by char
|
||||||
#ifdef WIN32
|
|
||||||
// Windows doesn't care about an escape character at the end.
|
if(_isQuote(c)) {
|
||||||
// It just adds \ to the arg.
|
switch(currentState) {
|
||||||
currentArg << c;
|
case OutOfArg:
|
||||||
#else
|
currentArg.str(std::string());
|
||||||
throw(std::runtime_error("Found Escape Character at end of file."));
|
case InArg:
|
||||||
#endif
|
currentState = InArgQuote;
|
||||||
|
currentQuoteChar = c;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InArgQuote:
|
||||||
|
if(c == currentQuoteChar)
|
||||||
|
currentState = InArg;
|
||||||
|
else
|
||||||
|
currentArg << c;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
}
|
||||||
#ifdef WIN32
|
else if(_isWhitespace(c)) {
|
||||||
// Windows only escapes the " character.
|
switch(currentState) {
|
||||||
// Every other character is just printed and the \ is added itself.
|
case InArg:
|
||||||
char c1 = c;
|
oargs.push_back(currentArg.str());
|
||||||
ain >> c;
|
currentState = OutOfArg;
|
||||||
if(c != '\"')
|
break;
|
||||||
currentArg << c1; // only ignore \ when next char is "
|
case InArgQuote:
|
||||||
ain.unget();
|
currentArg << c;
|
||||||
#else
|
break;
|
||||||
ain >> c;
|
case OutOfArg:
|
||||||
currentArg << c;
|
// nothing
|
||||||
#endif
|
break;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
|
else if(_isEscape(c)) {
|
||||||
|
switch(currentState) {
|
||||||
|
case OutOfArg:
|
||||||
|
currentArg.str(std::string());
|
||||||
|
currentState = InArg;
|
||||||
|
case InArg:
|
||||||
|
case InArgQuote:
|
||||||
|
if(ain.eof())
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
// Windows doesn't care about an escape character at the end.
|
||||||
|
// It just adds \ to the arg.
|
||||||
|
currentArg << c;
|
||||||
|
#else
|
||||||
|
throw(std::runtime_error("Found Escape Character at end of file."));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef WIN32
|
||||||
|
// Windows only escapes the " character.
|
||||||
|
// Every other character is just printed and the \ is added itself.
|
||||||
|
char c1 = c;
|
||||||
|
ain >> c;
|
||||||
|
if(c != '\"')
|
||||||
|
currentArg << c1; // only ignore \ when next char is "
|
||||||
|
ain.unget();
|
||||||
|
#else
|
||||||
|
ain >> c;
|
||||||
|
currentArg << c;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
switch(currentState) {
|
||||||
|
case InArg:
|
||||||
|
case InArgQuote:
|
||||||
|
currentArg << c;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OutOfArg:
|
||||||
|
currentArg.str(std::string());
|
||||||
|
currentArg << c;
|
||||||
|
currentState = InArg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(currentState == InArg)
|
||||||
|
oargs.push_back(currentArg.str());
|
||||||
|
else if(currentState == InArgQuote)
|
||||||
|
throw(std::runtime_error("Starting quote has no ending quote."));
|
||||||
|
|
||||||
|
return oargs;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
switch(currentState) {
|
|
||||||
case InArg:
|
|
||||||
case InArgQuote:
|
|
||||||
currentArg << c;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OutOfArg:
|
bool _isQuote(char c)
|
||||||
currentArg.str(std::string());
|
{
|
||||||
currentArg << c;
|
if(c == '\"')
|
||||||
currentState = InArg;
|
return true;
|
||||||
break;
|
else if(c == '\'')
|
||||||
}
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(currentState == InArg)
|
bool _isEscape(char c)
|
||||||
oargs.push_back(currentArg.str());
|
{
|
||||||
else if(currentState == InArgQuote)
|
if(c == '\\')
|
||||||
throw(std::runtime_error("Starting quote has no ending quote."));
|
return true;
|
||||||
|
|
||||||
return oargs;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _isQuote(char c)
|
bool _isWhitespace(char c)
|
||||||
{
|
{
|
||||||
if(c == '\"')
|
if(c == ' ')
|
||||||
return true;
|
return true;
|
||||||
else if(c == '\'')
|
else if(c == '\t')
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _isEscape(char c)
|
|
||||||
{
|
|
||||||
if(c == '\\')
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _isWhitespace(char c)
|
|
||||||
{
|
|
||||||
if(c == ' ')
|
|
||||||
return true;
|
|
||||||
else if(c == '\t')
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
#ifndef STRINGTOARGCARGV_H
|
/** stringtoargcargv.cpp -- Parsing a string to std::vector<string>
|
||||||
#define STRINGTOARGCARGV_H
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
/* stringtoargcargv.cpp -- Parsing a string to std::vector<string>
|
|
||||||
|
|
||||||
Copyright (C) 2011 Bernhard Eder
|
Copyright (C) 2011 Bernhard Eder
|
||||||
|
|
||||||
|
@ -26,6 +22,10 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef STRINGTOARGCARGV_H
|
||||||
|
#define STRINGTOARGCARGV_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
@ -35,11 +35,12 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
bool _isQuote(char c);
|
namespace StringToArgcArgv{
|
||||||
bool _isEscape(char c);
|
bool _isQuote(char c);
|
||||||
bool _isEscape(char c);
|
bool _isEscape(char c);
|
||||||
bool _isWhitespace(char c);
|
bool _isEscape(char c);
|
||||||
std::vector<std::string> parse(const std::string& args);
|
bool _isWhitespace(char c);
|
||||||
void stringToArgcArgv(const std::string& str, int* argc, char*** argv);
|
std::vector<std::string> parse(const std::string& args);
|
||||||
|
void stringToArgcArgv(const std::string& str, int* argc, char*** argv);
|
||||||
|
}
|
||||||
#endif //STRINGTOARGCARGV_H
|
#endif //STRINGTOARGCARGV_H
|
||||||
|
|
Loading…
Reference in a new issue