Improve direct execution
+ Add -o option + Add shebang analysis + Implement missing cleanup
This commit is contained in:
parent
8777abda32
commit
72a77c7088
5 changed files with 114 additions and 28 deletions
19
README.md
19
README.md
|
|
@ -16,9 +16,23 @@ These commands can be placed anywhere within the script like regular commands.
|
|||
|
||||
## Other features
|
||||
|
||||
### Output generated code
|
||||
|
||||
Output the generated shell code to stdout with either:
|
||||
- `-o` option
|
||||
- shebang other than lxsh
|
||||
|
||||
> Redirect stdout to a file to create a script file. <br>
|
||||
> The resulting script is not dependent on lxsh
|
||||
|
||||
### Live execution
|
||||
|
||||
Execute an extended shell script directly with the `-e` option.
|
||||
Directly execute an extended shell script with either
|
||||
- `-e` option
|
||||
- shebang is lxsh
|
||||
|
||||
> Direct execution introduces direct dependency on lxsh and overhead,
|
||||
> therefore it should be avoided outside of development use
|
||||
|
||||
### Minimize code
|
||||
|
||||
|
|
@ -30,5 +44,6 @@ lxsh should currently fully support POSIX syntax. <br>
|
|||
A POSIX shell script should give a working output.
|
||||
|
||||
Some specific features are missing:
|
||||
- link commands inside arithmetics (`$(())`) are not resolved
|
||||
- link commands in subshells inside arithmetics are not resolved
|
||||
- arithmetics cannot be minimized
|
||||
- link commands placed on the same line as keywords `if`, `then`, `elif`, `else`, `for`, `while`, `do` or `done` are not resolved
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ std::string delete_brackets(std::string const& in);
|
|||
|
||||
std::string pwd();
|
||||
|
||||
void _exec(std::string const& bin, std::vector<std::string> const& args);
|
||||
int _exec(std::string const& bin, std::vector<std::string> const& args);
|
||||
|
||||
std::string stringReplace(std::string subject, const std::string& search, const std::string& replace);
|
||||
|
||||
|
|
|
|||
81
src/main.cpp
81
src/main.cpp
|
|
@ -12,6 +12,48 @@
|
|||
#include "parse.hpp"
|
||||
#include "options.hpp"
|
||||
|
||||
int execute(block& sh, std::vector<std::string>& args)
|
||||
{
|
||||
std::string data=sh.generate();
|
||||
|
||||
std::string filename=ztd::exec("basename", args[0]).first;
|
||||
filename.pop_back();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
auto args=options.process(argc, argv, false, true);
|
||||
|
|
@ -59,37 +101,36 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
g_origin=file;
|
||||
add_include(file);
|
||||
|
||||
try
|
||||
{
|
||||
block sh(parse(import_file(file)));
|
||||
std::string curbin, binshebang;
|
||||
curbin=ztd::exec("basename", argv[0]).first;
|
||||
binshebang=ztd::exec("basename", sh.shebang).first;
|
||||
if(binshebang==curbin)
|
||||
sh.shebang="#!/bin/sh";
|
||||
if(options['e'])
|
||||
{
|
||||
std::string data=sh.generate();
|
||||
// generate path
|
||||
std::string tmpdir = (getenv("TMPDIR") != NULL) ? getenv("TMPDIR") : "/tmp" ;
|
||||
std::string filepath = tmpdir + "/lxsh_exec_" + ztd::sh("tr -dc '[:alnum:]' < /dev/urandom | head -c10");
|
||||
// create stream
|
||||
std::ofstream stream(filepath);
|
||||
if(!stream)
|
||||
throw std::runtime_error("Failed to write to file '"+filepath+'\'');
|
||||
|
||||
// output
|
||||
stream << data;
|
||||
stream.close();
|
||||
auto p = ztd::exec("chmod", "+x", filepath);
|
||||
if(p.second != 0)
|
||||
return p.second;
|
||||
|
||||
args.erase(args.begin());
|
||||
_exec(filepath, args);
|
||||
|
||||
return execute(sh, args);
|
||||
}
|
||||
else if(options['o'])
|
||||
{
|
||||
std::cout << sh.generate();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << sh.generate();
|
||||
if(binshebang == curbin)
|
||||
{
|
||||
return execute(sh, args);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << sh.generate();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(ztd::format_error& e)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ ztd::option_set gen_options()
|
|||
ztd::option_set ret;
|
||||
ret.add(ztd::option('h', "help", false, "Display this help message"));
|
||||
ret.add(ztd::option('m', "minimize", false, "Minimize code"));
|
||||
ret.add(ztd::option('e', "exec", false, "Directly exec instead of outputting"));
|
||||
ret.add(ztd::option('e', "exec", false, "Directly execute script"));
|
||||
ret.add(ztd::option('o', "output", false, "Output result script to stdout"));
|
||||
ret.add(ztd::option("help-commands", false, "Print help for linker commands"));
|
||||
return ret;
|
||||
}
|
||||
|
|
|
|||
37
src/util.cpp
37
src/util.cpp
|
|
@ -1,6 +1,10 @@
|
|||
#include "util.hpp"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <ztd/shell.hpp>
|
||||
|
||||
|
|
@ -69,14 +73,40 @@ std::string pwd()
|
|||
return std::string(buf);
|
||||
}
|
||||
|
||||
void _exec(std::string const& bin, std::vector<std::string> const& args)
|
||||
int _exec(std::string const& bin, std::vector<std::string> const& args)
|
||||
{
|
||||
std::vector<char*> rargs;
|
||||
rargs.push_back((char*) bin.c_str());
|
||||
for(auto it=args.begin(); it!=args.end(); it++)
|
||||
rargs.push_back((char*) it->c_str());
|
||||
rargs.push_back(NULL);
|
||||
execvp(bin.c_str(), rargs.data());
|
||||
|
||||
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)
|
||||
|
|
@ -134,4 +164,3 @@ void printErrorIndex(const char* in, const int index, const std::string& message
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue