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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
#include "exec.h"
#include "../lib/sys/execve.h"
#include "../lib/sys/fork.h"
#include "../lib/sys/wait4.h"
#include "../lib/sys/pipe.h"
#include "../lib/sys/dup2.h"
#include "../lib/sys/close.h"
#include "../lib/sys/exit.h"
#include "../lib/cstr/cstr.h"
#include "../lib/io/io.h"
#include "../lib/env/env.h"
#include "../lib/malloc/malloc.h"
#include "parser.h"
#include "builtin.h"
void print_call(char **argv)
{
while (*argv) {
write(STDOUT_FD, *argv, cstr_length(*argv));
write(STDOUT_FD, "\n", 1);
++argv;
}
}
void __execenv(const char **argv)
{
const char *path = getenv("PATH");
const char *end;
char *filename;
while (*path) {
end = path;
while (*end && *end != ':') ++end;
filename = malloc((end - path) + cstr_length(argv[0]) + 2);
for (int i = 0; i < end - path; ++i)
filename[i] = path[i];
filename[end - path] = '/';
for (int i = 0; i < cstr_length(argv[0]) + 1; ++i)
filename[(end - path) + i + 1] = argv[0][i];
execve(filename, argv, getenvp());
free(filename);
path = end;
if (*path == ':')
++path;
}
execve(argv[0], argv, getenvp());
}
void exec(char *line)
{
expression_list_t *exps = new_expression_from_line(line);
expression_list_t *exp = exps;
int pid;
int pipefd[2][2];
pipefd[0][PIPE_IN] = STDOUT_FD;
pipefd[0][PIPE_OUT] = STDIN_FD;
while (exp) {
char **argv = new_argv(exp->call);
pipe(pipefd[1]);
if (has_builtin_with_name(argv[0])) {
run_builtin(argv[0], (const char**)argv);
break;
}
pid = fork();
if (pid == 0) {
if (pipefd[0][PIPE_OUT] != STDIN_FD) {
dup2(pipefd[0][PIPE_OUT], STDIN_FD);
close(pipefd[0][PIPE_OUT]);
close(pipefd[0][PIPE_IN]);
}
if (exp->next)
dup2(pipefd[1][PIPE_IN], STDOUT_FD);
close(pipefd[1][PIPE_OUT]);
close(pipefd[1][PIPE_IN]);
__execenv((const char **)argv);
wstdf("command not found: %s\n", argv[0]);
exit(-1);
}
if (pipefd[0][PIPE_OUT] != STDIN_FD) {
close(pipefd[0][PIPE_IN]);
close(pipefd[0][PIPE_OUT]);
}
close(pipefd[1][PIPE_IN]);
pipefd[0][0] = pipefd[1][0];
pipefd[0][1] = pipefd[1][1];
free_argv(argv);
wait4(pid, 0, 0);
exp = exp->next;
}
free_expression(exps);
}
#ifdef EXEC_UNIT_TEST
int main() {
char *argv[] = { "ls" };
__execenv(argv);
}
#endif
|