mirror of
https://github.com/ksherlock/mpw-shell.git
synced 2025-01-15 03:30:00 +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 "builtins.h"
|
||||
#include "mpw-shell.h"
|
||||
#include "error.h"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
@ -16,6 +17,8 @@
|
||||
#include <sys/wait.h>
|
||||
#include <sysexits.h>
|
||||
|
||||
extern volatile int control_c;
|
||||
|
||||
namespace {
|
||||
|
||||
std::string &lowercase(std::string &s) {
|
||||
@ -121,6 +124,9 @@ command::~command()
|
||||
*/
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
|
||||
if (control_c) throw execution_of_input_terminated();
|
||||
|
||||
std::string s = expand_vars(text, env);
|
||||
|
||||
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) {
|
||||
|
||||
if (control_c) throw execution_of_input_terminated();
|
||||
|
||||
std::string s = expand_vars(text, e);
|
||||
|
||||
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 {
|
||||
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)
|
||||
{}
|
||||
constexpr int status() const noexcept { return _status; }
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cerrno>
|
||||
#include <signal.h>
|
||||
|
||||
#include "mpw-shell.h"
|
||||
#include "fdset.h"
|
||||
@ -57,6 +58,7 @@ void init(Environment &env) {
|
||||
env.set("echo", std::string("1"));
|
||||
}
|
||||
|
||||
|
||||
int read_file(phase1 &p, const std::string &file) {
|
||||
const mapped_file mf(file, mapped_file::readonly);
|
||||
|
||||
@ -96,6 +98,16 @@ int read_fd(phase1 &p, int fd) {
|
||||
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) {
|
||||
|
||||
std::string history_file = root();
|
||||
@ -103,12 +115,32 @@ int interactive(phase1 &p, phase2& p2) {
|
||||
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(;;) {
|
||||
const char *prompt = "# ";
|
||||
if (p2.continuation()) 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);
|
||||
free(cp);
|
||||
|
||||
@ -137,9 +169,12 @@ int interactive(phase1 &p, phase2& p2) {
|
||||
p.reset();
|
||||
}
|
||||
|
||||
sigaction(SIGINT, &old_act, nullptr);
|
||||
|
||||
write_history(history_file.c_str());
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -212,9 +247,11 @@ int main(int argc, char **argv) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user