-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexecutable.cc
More file actions
80 lines (74 loc) · 2.88 KB
/
executable.cc
File metadata and controls
80 lines (74 loc) · 2.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// The definition of the Base_executable and Binary classes. The former
// provides functionality common to all derived types, the latter executes
// external programs.
//
// Copyright (C) 2005-2019 Samuel Newbold
#include <list>
#include <map>
#include <set>
#include <string>
#include <sys/time.h>
#include <sys/wait.h>
#include <unistd.h>
#include <vector>
#include "rwsh_stream.h"
#include "argm.h"
#include "call_stack.h"
#include "clock.h"
#include "executable.h"
#include "executable_map.h"
#include "plumber.h"
void Base_executable::operator() (const Argm& argm,
Error_list& parent_exceptions) {
if (global_stack.global_nesting > global_stack.max_nesting+1)
parent_exceptions.add_error(Exception(Argm::Excessive_nesting));
if (global_stack.unwind_stack()) return;
else ++executable_nesting, ++global_stack.global_nesting;
Error_list children;
struct timeval start_time;
gettimeofday(&start_time, rwsh_clock.no_timezone);
try {execute(argm, children);}
catch (Exception error) {children.add_error(error);}
struct timeval end_time;
gettimeofday(&end_time, rwsh_clock.no_timezone);
last_execution_time_v = Clock::timeval_sub(end_time, start_time);
Clock::timeval_add(total_execution_time_v, last_execution_time_v);
++execution_count_v;
--global_stack.global_nesting;
if (global_stack.caught_signal) {
Exception focus(global_stack.caught_signal);
global_stack.caught_signal = Argm::No_exception;
executable_map.run(focus, children);}
if (children.size()) {
last_exception_v = "";
for (auto j = children.begin(); j != children.end();) {
last_exception_v += j->str() + " " + argm.str();
j->push_back(argm[0]);
parent_exceptions.push_back(*j);
if (++j != children.end()) last_exception_v += "; ";}}
--executable_nesting;
if (del_on_term && !executable_nesting) delete this;}
Binary::Binary(const std::string& impl) : implementation(impl) {}
// run the given binary
void Binary::execute(const Argm& argm_i, Error_list& exceptions) {
int ret,
input = argm_i.input.fd(),
output = argm_i.output.fd(),
error = argm_i.error.fd();
if (!fork()) {
plumber.after_fork();
if (dup2(input, 0) < 0) argm_i.error <<"dup2 didn't like changing input\n";
if (dup2(output, 1) < 0)
argm_i.error <<"dup2 didn't like changing output\n";
if (dup2(error, 2) < 0) argm_i.error <<"dup2 didn't like changing error\n";
Old_argv argv(argm_i.subrange(0));
std::vector<char *>env;
argm_i.export_env(env);
ret = execve(implementation.c_str(), argv.argv(), &env[0]);
exceptions.add_error(Exception(Argm::Binary_does_not_exist, argm_i[0]));
global_stack.exception_handler(exceptions);
executable_map.unused_var_check_at_exit();
exit(ret);}
else plumber.wait(&ret);
if (WIFEXITED(ret) && WEXITSTATUS(ret))
exceptions.add_error(Exception(Argm::Return_code, WEXITSTATUS(ret)));}