#include "util.hpp" #include #include #include #include #include #include std::string indenting_string="\t"; std::string indent(int n) { std::string ret; for(int i=0; i const& values) { for(auto it: values) if(in == it) return true; return false; } std::vector split(std::string const& in, const char* splitters) { uint32_t i=0,j=0; std::vector ret; // skip first splitters while(i split(std::string const& in, char c) { size_t i=0,j=0; std::vector ret; while(j const& args) { std::string ret; for(auto it: args) ret += it + ' '; ret.pop_back(); return ret; } std::set prune_matching(std::set& in, std::regex re) { std::set ret; auto it=in.begin(); auto prev=in.end(); while(it!=in.end()) { if( std::regex_match(*it, re) ) { ret.insert(*it); in.erase(it); if(prev == in.end()) it = in.begin(); else { it = prev; it++; } } else { prev=it; it++; } } return ret; } int _exec(std::string const& bin, std::vector const& args) { std::vector rargs; for(auto it=args.begin(); it!=args.end(); it++) rargs.push_back((char*) it->c_str()); rargs.push_back(NULL); pid_t pid; // forking if((pid = fork()) == -1) { perror("fork"); exit(1); } // child process if(pid == 0) { setpgid(pid, pid); //Needed so negative PIDs can kill children of /bin/sh execvp(bin.c_str(), rargs.data()); exit(1); // exec didn't work } int stat; // wait for end and get return value while (waitpid(pid, &stat, 0) == -1) { if (errno != EINTR) { stat = -1; break; } } return stat; } std::string stringReplace(std::string subject, const std::string& search, const std::string& replace) { size_t pos = 0; while ((pos = subject.find(search, pos)) != std::string::npos) { subject.replace(pos, search.length(), replace); pos += replace.length(); } return subject; } std::string repeatString(std::string const& str, uint32_t n) { std::string ret; for(uint32_t i=0; i= 0) { while(i < in_size && i < index) { if(in[i] == '\n') { line++; j=i+1; } 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()); 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; }