diff --git a/Makefile b/Makefile index 9330c31..5e3d449 100644 --- a/Makefile +++ b/Makefile @@ -16,12 +16,22 @@ CC=g++ # compiler flags CXXFLAGS= -I$(IDIR) -Wall -pedantic -std=c++20 ifeq ($(DEBUG),true) - # debugging flags - CXXFLAGS += -g + # debugging flags + CXXFLAGS += -g + RODIR = $(ODIR)/debug else - # release flags - CXXFLAGS += -Ofast + # release flags + CXXFLAGS += -Ofast + RODIR = $(ODIR)/release endif +ifeq ($(STATIC),true) + # static links + LDFLAGS += -l:libztd.a +else + # dynamic links + LDFLAGS += -lztd +endif + ifeq ($(PROFILE),true) CXXFLAGS += -pg @@ -31,51 +41,49 @@ ifneq ($(RELEASE), true) VSUFFIX=-dev-$(SHA_SHORT) endif -ifeq ($(STATIC),true) - # static links - LDFLAGS += -l:libztd.a -else - # dynamic links - LDFLAGS += -lztd -endif - ## END CONFIG ## + $(shell ./generate_version.sh) $(shell ./generate_shellcode.sh) -$(shell mkdir -p $(ODIR)) + +$(shell mkdir -p $(RODIR)) $(shell mkdir -p $(BINDIR)) # automatically find .h and .hpp -DEPS = $(shell find $(IDIR) -type f -regex '.*\.hp?p?' ! -name 'g_version.h' ! -name 'g_shellcode.h') +DEPS = $(shell find $(IDIR) -type f -regex '.*\.hp?p?') # automatically find .c and .cpp and make the corresponding .o rule -OBJ = $(shell find $(SRCDIR) -type f -regex '.*\.cp?p?' | sed 's|\.cpp|.o|g;s|\.c|.o|g;s|^$(SRCDIR)/|$(ODIR)/|g') +OBJ = $(shell find $(SRCDIR) -type f -regex '.*\.cp?p?' | sed 's|\.cpp|.o|g;s|\.c|.o|g;s|^$(SRCDIR)/|$(RODIR)/|g') -build: lxsh $(OBJ) $(DEPS) +build: $(BINDIR)/$(NAME) -$(ODIR)/%.o: $(SRCDIR)/%.c $(DEPS) +# specific files for autogenerated headers +$(OBJDIR)/options.o: $(SRCDIR)/options.cpp $(DEPS) $(IDIR)/g_version.h $(CC) $(CXXFLAGS) -c -o $@ $< -$(ODIR)/%.o: $(SRCDIR)/%.cpp $(DEPS) +$(OBJDIR)/shellcode.o: $(SRCDIR)/shellcode.cpp $(DEPS) $(IDIR)/g_shellcode.h $(CC) $(CXXFLAGS) -c -o $@ $< -$(ODIR)/options.o: $(SRCDIR)/options.cpp $(DEPS) $(IDIR)/g_version.h +$(OBJDIR)/debashify.o: $(SRCDIR)/debashify.cpp $(DEPS) $(IDIR)/g_shellcode.h $(CC) $(CXXFLAGS) -c -o $@ $< -$(ODIR)/shellcode.o: $(SRCDIR)/shellcode.cpp $(DEPS) $(IDIR)/g_shellcode.h +# generic files + +$(RODIR)/%.o: $(SRCDIR)/%.c $(DEPS) $(CC) $(CXXFLAGS) -c -o $@ $< -$(ODIR)/debashify.o: $(SRCDIR)/debashify.cpp $(DEPS) $(IDIR)/g_shellcode.h +$(RODIR)/%.o: $(SRCDIR)/%.cpp $(DEPS) $(CC) $(CXXFLAGS) -c -o $@ $< -lxsh: $(OBJ) - $(CC) $(CXXFLAGS) -o $@ $^ $(LDFLAGS) + +$(BINDIR)/$(NAME): $(OBJ) + $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@ $^ test: $(BINDIR)/$(NAME) $(BINDIR)/$(NAME) clean: - rm $(ODIR)/*.o gmon.out + rm $(ODIR)/*/*.o clear: rm $(BINDIR)/$(NAME) diff --git a/include/struc.hpp b/include/struc.hpp index 8bd007f..326495b 100644 --- a/include/struc.hpp +++ b/include/struc.hpp @@ -102,14 +102,16 @@ class format_error : public std::exception { public: //! @brief Conctructor - inline format_error(const std::string& what, const std::string& origin, const std::string& data, int where) { desc=what; index=where; filename=origin; sdat=data; } - inline format_error(const std::string& what, parse_context const& ctx) { desc=what; index=ctx.i; filename=ctx.filename; sdat=ctx.data; } + inline format_error(const std::string& what, const std::string& origin, const std::string& data, int where, std::string level="error") { desc=what; index=where; filename=origin; sdat=data; severity=level; } + inline format_error(const std::string& what, parse_context const& ctx, std::string level="error") { desc=what; index=ctx.i; filename=ctx.filename; sdat=ctx.data; severity=level; } //! @brief Error message inline const char * what () const throw () {return desc.c_str();} //! @brief Origin of the data, name of imported file, otherwise empty if generated inline const char * origin() const throw () {return filename.c_str();} //! @brief Data causing the exception inline const char * data() const throw () {return sdat.c_str();} + //! @brief Severity of the exception + inline const std::string level() const throw () {return severity.c_str();} //! @brief Where the error is located in the data inline const int where () const throw () {return index;} private: @@ -117,6 +119,7 @@ private: int index; std::string filename; std::string sdat; + std::string severity; }; // objects diff --git a/include/util.hpp b/include/util.hpp index 3c2f871..4c3b434 100644 --- a/include/util.hpp +++ b/include/util.hpp @@ -148,8 +148,5 @@ int _exec(std::string const& bin, std::vector const& args); std::string stringReplace(std::string subject, const std::string& search, const std::string& replace); void printFormatError(format_error const& e, bool print_line=true); -void printErrorIndex(const char* in, const int index, const std::string& message, const std::string& origin, bool print_line=true); - -int execute(shmain* sh, std::vector& args); #endif //UTIL_HPP diff --git a/src/options.cpp b/src/options.cpp index dcb7e9b..e25f5e3 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -30,19 +30,20 @@ ztd::option_set options( { ztd::option('R', "no-resolve", false, "Don't resolve %resolve commands"), ztd::option("no-extend", false, "Don't add lxsh extension functions"), ztd::option("debashify", false, "Attempt to turn a bash-specific script into a POSIX shell script"), - ztd::option("\r [var/fct processing]"), - ztd::option("minify-var", false, "Minify variable names"), - ztd::option("minify-fct", false, "Minify function names"), + ztd::option("remove-unused", false, "Remove unused functions and variables"), + ztd::option("list-cmd", false, "List all commands invoked in the script"), + ztd::option("\r [Variable processing]"), ztd::option("exclude-var", true, "List of matching regex to ignore for variable processing", "list"), - ztd::option("exclude-fct", true, "List of matching regex to ignore for function processing", "list"), ztd::option("no-exclude-reserved",false, "Don't exclude reserved variables"), + ztd::option("minify-var", false, "Minify variable names"), ztd::option("list-var", false, "List all variables set and invoked in the script"), ztd::option("list-var-def", false, "List all variables set in the script"), ztd::option("list-var-call", false, "List all variables invoked in the script"), - ztd::option("list-fct", false, "List all functions defined in the script"), - ztd::option("list-cmd", false, "List all commands invoked in the script"), - ztd::option("remove-unused", false, "Remove unused functions and variables"), - ztd::option("unset-var", false, "Add 'unset' to all vars at the start of the script to avoid environment interference") + ztd::option("unset-var", false, "Add 'unset' to all variables at the start of the script to avoid environment interference"), + ztd::option("\r [Function processing]"), + ztd::option("exclude-fct", true, "List of matching regex to ignore for function processing", "list"), + ztd::option("minify-fct", false, "Minify function names"), + ztd::option("list-fct", false, "List all functions defined in the script") } ); bool g_cd=false; @@ -96,9 +97,8 @@ ztd::option_set create_resolve_opts() void print_help(const char* arg0) { printf("%s [options] [arg...]\n", arg0); - printf("Link extended shell\n"); - printf("Include files and resolve commands on build time\n"); - printf("See --help-commands for help on linker commands\n"); + printf("Extended shell linker\n"); + printf("Include files, resolve commands on build time, process and minify shell code\n"); printf("\n"); printf("Options:\n"); options.print_help(4,25); diff --git a/src/parse.cpp b/src/parse.cpp index 0c7a0f6..44a1cd9 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -41,13 +41,15 @@ std::string unexpected_token(std::string const& s) void parse_error(std::string const& message, parse_context& ctx) { - printFormatError(format_error(message, ctx.filename, ctx.data, ctx.i)); + printFormatError(format_error(message, ctx)); ctx.has_errored=true; } void parse_error(std::string const& message, parse_context& ctx, uint64_t i) { - printFormatError(format_error(message, ctx.filename, ctx.data, i)); + parse_context newctx = ctx; + newctx.i = i; + printFormatError(format_error(message, newctx)); ctx.has_errored=true; } diff --git a/src/shellcode.cpp b/src/shellcode.cpp index 2c2a4bb..03919e3 100644 --- a/src/shellcode.cpp +++ b/src/shellcode.cpp @@ -5,7 +5,7 @@ #include "struc_helper.hpp" const std::map lxsh_extend_fcts = { - { "_lxsh_random", { "[K]", "Generate a random number between 0 and 2^(k*8). Default 2", RANDOM_SH} }, + { "_lxsh_random", { "[K]", "Generate a random number between 0 and 2^(K*8). Default 2", RANDOM_SH} }, { "_lxsh_random_string", { "[N]", "Generate a random alphanumeric string of length N. Default 20", RANDOM_STRING_SH} }, { "_lxsh_random_tmpfile", { "[N]", "Get a random TMP filepath, with N random chars. Default 20", RANDOM_TMPFILE_SH, {"_lxsh_random_string"} } } }; diff --git a/src/util.cpp b/src/util.cpp index 905a916..a0a87fa 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -10,6 +10,7 @@ #include #include +#include std::string indenting_string="\t"; @@ -213,14 +214,13 @@ std::string repeatString(std::string const& str, uint32_t n) void printFormatError(format_error const& e, bool print_line) { - printErrorIndex(e.data(), e.where(), e.what(), e.origin(), print_line); -} + const char* in = e.data(); -void printErrorIndex(const char* in, const int index, const std::string& message, const std::string& origin, bool print_line) -{ - int i=0, j=0; // j: last newline - int line=1; //n: line # - int in_size=strlen(in); + uint64_t index = e.where(); + + uint64_t i=0, j=0; // j: last newline + uint64_t line=1; //n: line # + uint64_t in_size=strlen(in); if(index >= 0) { while(i < in_size && i < index) @@ -233,56 +233,25 @@ void printErrorIndex(const char* in, const int index, const std::string& message i++; } while(i < in_size && in[i]!='\n') - { i++; - } } - fprintf(stderr, "%s:%u:%u: %s\n", origin.c_str(), line, index-j+1, message.c_str()); + std::cerr << ztd::color::b_white; + fprintf(stderr, "%s:%lu:%lu: ", e.origin(), line, index-j+1); + + ztd::color level_color; + const std::string& level = e.level(); + if(level == "error") + level_color = ztd::color::b_red; + else if(level == "warning") + level_color = ztd::color::b_magenta; + else if(level == "info") + level_color = ztd::color::b_cyan; + + std::cerr << level_color << e.level() << ztd::color::none; + fprintf(stderr, ": %s\n", e.what()); if(print_line) { std::cerr << std::string(in+j, i-j) << std::endl; std::cerr << repeatString(" ", index-j) << '^' << std::endl; } } - - -int execute(shmain* sh, std::vector& args) -{ - std::string data=sh->generate(); - - std::string filename = basename(args[0]); - - // generate path - std::string tmpdir = (getenv("TMPDIR") != NULL) ? getenv("TMPDIR") : "/tmp" ; - std::string dirpath = tmpdir + "/lxsh_" + ztd::sh("tr -dc '[:alnum:]' < /dev/urandom | head -c10"); - std::string filepath = dirpath+'/'+filename; - - // create dir - if(ztd::exec("mkdir", "-p", dirpath).second) - { - throw std::runtime_error("Failed to create directory '"+dirpath+'\''); - } - - // create stream - std::ofstream stream(filepath); - if(!stream) - { - ztd::exec("rm", "-rf", dirpath); - throw std::runtime_error("Failed to write to '"+filepath+'\''); - } - - // output - stream << data; - stream.close(); - if(ztd::exec("chmod", "+x", filepath).second != 0) - { - ztd::exec("rm", "-rf", dirpath); - throw std::runtime_error("Failed to make '"+filepath+"' executable"); - } - - // exec - int retval=_exec(filepath, args); - ztd::exec("rm", "-rf", dirpath); - - return retval; -}