mirror of
https://github.com/ksherlock/mpw-shell.git
synced 2024-06-01 08:41:32 +00:00
mpw-make support
This commit is contained in:
parent
41e1424644
commit
d98247bd12
72
command.cpp
72
command.cpp
|
@ -19,6 +19,42 @@
|
||||||
|
|
||||||
extern volatile int control_c;
|
extern volatile int control_c;
|
||||||
|
|
||||||
|
|
||||||
|
void launch_mpw(const Environment &env, const std::vector<std::string> &argv, const fdmask &fds) {
|
||||||
|
|
||||||
|
std::vector<char *> cargv;
|
||||||
|
cargv.reserve(argv.size() + 3);
|
||||||
|
|
||||||
|
|
||||||
|
cargv.push_back((char *)"mpw");
|
||||||
|
//cargv.push_back((char *)"--shell");
|
||||||
|
|
||||||
|
unsigned offset = cargv.size();
|
||||||
|
|
||||||
|
|
||||||
|
std::transform(argv.begin(), argv.end(), std::back_inserter(cargv),
|
||||||
|
[](const std::string &s) { return strdup(s.c_str()); }
|
||||||
|
);
|
||||||
|
cargv.push_back(nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
// export environment...
|
||||||
|
|
||||||
|
for (const auto &kv : env) {
|
||||||
|
if (kv.second) { // exported
|
||||||
|
std::string name = "mpw$" + kv.first;
|
||||||
|
setenv(name.c_str(), kv.second.c_str(), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle any indirection...
|
||||||
|
fds.dup();
|
||||||
|
|
||||||
|
execvp(cargv.front(), cargv.data());
|
||||||
|
perror("execvp: ");
|
||||||
|
exit(EX_OSERR); // raise a signal?
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
std::string &lowercase(std::string &s) {
|
std::string &lowercase(std::string &s) {
|
||||||
|
@ -40,26 +76,15 @@ namespace {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int execute_external(const Environment &env, const std::vector<std::string> &argv, const fdmask &fds) {
|
int execute_external(const Environment &env, const std::vector<std::string> &argv, const fdmask &fds) {
|
||||||
|
|
||||||
std::vector<char *> cargv;
|
|
||||||
cargv.reserve(argv.size() + 3);
|
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
int pid;
|
int pid;
|
||||||
|
|
||||||
cargv.push_back((char *)"mpw");
|
|
||||||
//cargv.push_back((char *)"--shell");
|
|
||||||
|
|
||||||
unsigned offset = cargv.size();
|
|
||||||
|
|
||||||
|
|
||||||
std::transform(argv.begin(), argv.end(), std::back_inserter(cargv),
|
|
||||||
[](const std::string &s) { return strdup(s.c_str()); }
|
|
||||||
);
|
|
||||||
|
|
||||||
cargv.push_back(nullptr);
|
|
||||||
|
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
|
@ -69,26 +94,9 @@ namespace {
|
||||||
|
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
|
launch_mpw(env, argv, fds);
|
||||||
// export environment...
|
|
||||||
|
|
||||||
for (const auto &kv : env) {
|
|
||||||
if (kv.second) { // exported
|
|
||||||
std::string name = "mpw$" + kv.first;
|
|
||||||
setenv(name.c_str(), kv.second.c_str(), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle any indirection...
|
|
||||||
fds.dup();
|
|
||||||
|
|
||||||
execvp(cargv.front(), cargv.data());
|
|
||||||
perror("execvp: ");
|
|
||||||
exit(EX_OSERR);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::for_each(cargv.begin()+offset, cargv.end(), free);
|
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
int status;
|
int status;
|
||||||
pid_t ok;
|
pid_t ok;
|
||||||
|
|
3
fdset.h
3
fdset.h
|
@ -25,6 +25,9 @@ class fdmask {
|
||||||
fdmask(const std::array<int, 3> &rhs) : _fds(rhs)
|
fdmask(const std::array<int, 3> &rhs) : _fds(rhs)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
fdmask(int a, int b, int c) : _fds{{ a, b, c }}
|
||||||
|
{}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
fdmask(std::initializer_list<int> rhs) : _fds(rhs)
|
fdmask(std::initializer_list<int> rhs) : _fds(rhs)
|
||||||
{}
|
{}
|
||||||
|
|
141
mpw-shell.cpp
141
mpw-shell.cpp
|
@ -98,6 +98,71 @@ int read_fd(phase1 &p, int fd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void launch_mpw(const Environment &env, const std::vector<std::string> &argv, const fdmask &fds);
|
||||||
|
|
||||||
|
int read_make(phase1 &p1, phase2 &p2, Environment &env, const std::vector<std::string> &argv) {
|
||||||
|
|
||||||
|
int out[2];
|
||||||
|
int ok;
|
||||||
|
|
||||||
|
|
||||||
|
env.set("echo", "1");
|
||||||
|
env.set("exit", "1");
|
||||||
|
|
||||||
|
ok = pipe(out);
|
||||||
|
if (ok < 0) {
|
||||||
|
perror("pipe");
|
||||||
|
exit(EX_OSERR);
|
||||||
|
}
|
||||||
|
fcntl(out[0], F_SETFD, FD_CLOEXEC);
|
||||||
|
fcntl(out[1], F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
|
int child = fork();
|
||||||
|
if (child < 0) {
|
||||||
|
perror("fork");
|
||||||
|
exit(EX_OSERR);
|
||||||
|
}
|
||||||
|
if (child == 0) {
|
||||||
|
// child.
|
||||||
|
fdmask fds = {-1, out[1], -1};
|
||||||
|
|
||||||
|
launch_mpw(env, argv, fds);
|
||||||
|
|
||||||
|
exit(EX_OSERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(out[1]);
|
||||||
|
int rv = read_fd(p1, out[0]);
|
||||||
|
close(out[0]);
|
||||||
|
p2.finish();
|
||||||
|
|
||||||
|
// check for make errors.
|
||||||
|
for(;;) {
|
||||||
|
int status;
|
||||||
|
int ok = waitpid(child, &status, 0);
|
||||||
|
if (ok < 0) {
|
||||||
|
if (errno == EINTR) continue;
|
||||||
|
perror("waitpid: ");
|
||||||
|
exit(EX_OSERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WIFEXITED(status)) {
|
||||||
|
ok = WEXITSTATUS(status);
|
||||||
|
env.status(ok, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (WIFSIGNALED(status)) {
|
||||||
|
env.status(-9, false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "waitpid - unexpected result\n");
|
||||||
|
exit(EX_OSERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
return env.status();
|
||||||
|
}
|
||||||
|
|
||||||
volatile int control_c = 0;
|
volatile int control_c = 0;
|
||||||
void control_c_handler(int signal, siginfo_t *sinfo, void *context) {
|
void control_c_handler(int signal, siginfo_t *sinfo, void *context) {
|
||||||
|
|
||||||
|
@ -193,7 +258,83 @@ void define(Environment &env, const std::string &s) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string basename(const char *cp) {
|
||||||
|
std::string tmp(cp);
|
||||||
|
auto pos = tmp.rfind('/');
|
||||||
|
if (pos == tmp.npos) return tmp;
|
||||||
|
return tmp.substr(pos+1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void make_help() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int make(int argc, char **argv) {
|
||||||
|
|
||||||
|
Environment e;
|
||||||
|
init(e);
|
||||||
|
|
||||||
|
std::vector<std::string> args;
|
||||||
|
args.reserve(argc+1);
|
||||||
|
bool __ = false;
|
||||||
|
|
||||||
|
args.emplace_back("make");
|
||||||
|
|
||||||
|
for (auto iter = argv; *iter; ++iter) {
|
||||||
|
std::string tmp(*iter);
|
||||||
|
|
||||||
|
if (!__) {
|
||||||
|
if (tmp == "--")
|
||||||
|
{ __ = true; continue; }
|
||||||
|
|
||||||
|
if (tmp == "--help")
|
||||||
|
{ make_help(); exit(0); }
|
||||||
|
|
||||||
|
if (tmp == "--test" || tmp == "--dry-run")
|
||||||
|
{ e.set("test", "1"); continue; }
|
||||||
|
}
|
||||||
|
args.emplace_back(std::move(tmp));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
phase1 p1;
|
||||||
|
phase2 p2;
|
||||||
|
|
||||||
|
p1 >>= [&p2](std::string &&s) {
|
||||||
|
if (s.empty()) p2.finish();
|
||||||
|
else p2(std::move(s));
|
||||||
|
};
|
||||||
|
|
||||||
|
p2 >>= [&e](command_ptr_vector &&v) {
|
||||||
|
|
||||||
|
for (auto iter = v.begin(); iter != v.end(); ++iter) {
|
||||||
|
auto &ptr = *iter;
|
||||||
|
fdmask fds;
|
||||||
|
try {
|
||||||
|
ptr->execute(e, fds);
|
||||||
|
} catch (execution_of_input_terminated &ex) {
|
||||||
|
control_c = 0;
|
||||||
|
if (!(ptr->terminal() && ++iter == v.end())) {
|
||||||
|
fprintf(stderr, "%s\n", ex.what());
|
||||||
|
}
|
||||||
|
e.status(ex.status(), false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return read_make(p1, p2, e, args);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|
||||||
|
|
||||||
|
std::string self = basename(argv[0]);
|
||||||
|
if (self == "mpw-make") return make(argc - 1, argv + 1);
|
||||||
|
if (self == "mpw-shell" && argc > 1 && !strcmp(argv[1],"make")) return make(argc - 2, argv + 2);
|
||||||
|
|
||||||
Environment e;
|
Environment e;
|
||||||
init(e);
|
init(e);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user