mirror of
https://github.com/ksherlock/mpw-shell.git
synced 2025-01-29 19:31:49 +00:00
control-c support
This commit is contained in:
parent
f58f6d4115
commit
0dfecbd520
11
command.cpp
11
command.cpp
@ -4,6 +4,7 @@
|
|||||||
#include "fdset.h"
|
#include "fdset.h"
|
||||||
#include "builtins.h"
|
#include "builtins.h"
|
||||||
#include "mpw-shell.h"
|
#include "mpw-shell.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
@ -16,6 +17,8 @@
|
|||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sysexits.h>
|
#include <sysexits.h>
|
||||||
|
|
||||||
|
extern volatile int control_c;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
std::string &lowercase(std::string &s) {
|
std::string &lowercase(std::string &s) {
|
||||||
@ -121,6 +124,9 @@ command::~command()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
int simple_command::execute(Environment &env, const fdmask &fds, bool throwup) {
|
int simple_command::execute(Environment &env, const fdmask &fds, bool throwup) {
|
||||||
|
|
||||||
|
if (control_c) throw execution_of_input_terminated();
|
||||||
|
|
||||||
std::string s = expand_vars(text, env);
|
std::string s = expand_vars(text, env);
|
||||||
|
|
||||||
env.echo("%s", s.c_str());
|
env.echo("%s", s.c_str());
|
||||||
@ -160,6 +166,8 @@ int simple_command::execute(Environment &env, const fdmask &fds, bool throwup) {
|
|||||||
|
|
||||||
int evaluate_command::execute(Environment &env, const fdmask &fds, bool throwup) {
|
int evaluate_command::execute(Environment &env, const fdmask &fds, bool throwup) {
|
||||||
|
|
||||||
|
if (control_c) throw execution_of_input_terminated();
|
||||||
|
|
||||||
std::string s = expand_vars(text, env);
|
std::string s = expand_vars(text, env);
|
||||||
|
|
||||||
env.echo("%s", s.c_str());
|
env.echo("%s", s.c_str());
|
||||||
@ -215,6 +223,9 @@ int vector_command::execute(Environment &e, const fdmask &fds, bool throwup) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int error_command::execute(Environment &e, const fdmask &fds, bool throwup) {
|
int error_command::execute(Environment &e, const fdmask &fds, bool throwup) {
|
||||||
|
|
||||||
|
if (control_c) throw execution_of_input_terminated();
|
||||||
|
|
||||||
std::string s = expand_vars(text, e);
|
std::string s = expand_vars(text, e);
|
||||||
|
|
||||||
e.echo("%s", s.c_str());
|
e.echo("%s", s.c_str());
|
||||||
|
2
error.h
2
error.h
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
class execution_of_input_terminated : public std::runtime_error {
|
class execution_of_input_terminated : public std::runtime_error {
|
||||||
public:
|
public:
|
||||||
execution_of_input_terminated(int status) :
|
execution_of_input_terminated(int status = -9) :
|
||||||
std::runtime_error("MPW Shell - Execution of input Terminated."), _status(status)
|
std::runtime_error("MPW Shell - Execution of input Terminated."), _status(status)
|
||||||
{}
|
{}
|
||||||
constexpr int status() const noexcept { return _status; }
|
constexpr int status() const noexcept { return _status; }
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#include "mpw-shell.h"
|
#include "mpw-shell.h"
|
||||||
#include "fdset.h"
|
#include "fdset.h"
|
||||||
@ -57,6 +58,7 @@ void init(Environment &env) {
|
|||||||
env.set("echo", std::string("1"));
|
env.set("echo", std::string("1"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int read_file(phase1 &p, const std::string &file) {
|
int read_file(phase1 &p, const std::string &file) {
|
||||||
const mapped_file mf(file, mapped_file::readonly);
|
const mapped_file mf(file, mapped_file::readonly);
|
||||||
|
|
||||||
@ -96,6 +98,16 @@ int read_fd(phase1 &p, int fd) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volatile int control_c = 0;
|
||||||
|
void control_c_handler(int signal, siginfo_t *sinfo, void *context) {
|
||||||
|
|
||||||
|
// libedit gobbles up the first control-C and doesn't return until the second.
|
||||||
|
// GNU's readline may return no the first.
|
||||||
|
if (control_c > 3) abort();
|
||||||
|
control_c++;
|
||||||
|
//fprintf(stderr, "interrupt!\n");
|
||||||
|
}
|
||||||
|
|
||||||
int interactive(phase1 &p, phase2& p2) {
|
int interactive(phase1 &p, phase2& p2) {
|
||||||
|
|
||||||
std::string history_file = root();
|
std::string history_file = root();
|
||||||
@ -103,12 +115,32 @@ int interactive(phase1 &p, phase2& p2) {
|
|||||||
read_history(history_file.c_str());
|
read_history(history_file.c_str());
|
||||||
|
|
||||||
|
|
||||||
|
struct sigaction act;
|
||||||
|
struct sigaction old_act;
|
||||||
|
memset(&act, 0, sizeof(struct sigaction));
|
||||||
|
sigemptyset(&act.sa_mask);
|
||||||
|
|
||||||
|
act.sa_sigaction = control_c_handler;
|
||||||
|
act.sa_flags = SA_SIGINFO;
|
||||||
|
|
||||||
|
sigaction(SIGINT, &act, &old_act);
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
const char *prompt = "# ";
|
const char *prompt = "# ";
|
||||||
if (p2.continuation()) prompt = "> ";
|
if (p2.continuation()) prompt = "> ";
|
||||||
char *cp = readline(prompt);
|
char *cp = readline(prompt);
|
||||||
if (!cp) break;
|
if (!cp) {
|
||||||
|
if (control_c) {
|
||||||
|
control_c = 0;
|
||||||
|
fprintf(stdout, "\n");
|
||||||
|
p.abort();
|
||||||
|
p2.abort();
|
||||||
|
e.status(-9, false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
control_c = 0;
|
||||||
std::string s(cp);
|
std::string s(cp);
|
||||||
free(cp);
|
free(cp);
|
||||||
|
|
||||||
@ -137,9 +169,12 @@ int interactive(phase1 &p, phase2& p2) {
|
|||||||
p.reset();
|
p.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sigaction(SIGINT, &old_act, nullptr);
|
||||||
|
|
||||||
write_history(history_file.c_str());
|
write_history(history_file.c_str());
|
||||||
fprintf(stdout, "\n");
|
fprintf(stdout, "\n");
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,9 +247,11 @@ int main(int argc, char **argv) {
|
|||||||
try {
|
try {
|
||||||
ptr->execute(e, fds);
|
ptr->execute(e, fds);
|
||||||
} catch (execution_of_input_terminated &ex) {
|
} catch (execution_of_input_terminated &ex) {
|
||||||
|
control_c = 0;
|
||||||
if (!(ptr->terminal() && ++iter == v.end())) {
|
if (!(ptr->terminal() && ++iter == v.end())) {
|
||||||
fprintf(stderr, "%s\n", ex.what());
|
fprintf(stderr, "%s\n", ex.what());
|
||||||
}
|
}
|
||||||
|
e.status(ex.status(), false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user