da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
0
|
// Copyright (C) 2023, Jakob Wakeling |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
1
|
// All rights reserved. |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
2
|
|
59a2eec |
Jakob Wakeling |
2023-12-28 14:17:38 |
3
|
#include "bltn.h" |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
4
|
#include "exec.h" |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
5
|
#include "parse.h" |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
6
|
#include "util/log.h" |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
7
|
#include "util/util.h" |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
8
|
|
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
9
|
#include <fcntl.h> |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
10
|
#include <sys/wait.h> |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
11
|
#include <unistd.h> |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
12
|
|
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
13
|
#include <errno.h> |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
14
|
#include <signal.h> |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
15
|
#include <stdio.h> |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
16
|
#include <stdlib.h> |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
17
|
#include <string.h> |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
18
|
|
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
19
|
s32 _ret; |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
20
|
|
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
21
|
static s32 execute_comm(ast *a, int fdi, int fd[2]); |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
22
|
static s32 execute_pipe(ast *a, int fdi, int fd[2]); |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
23
|
|
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
24
|
/* Execute a program. */ |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
25
|
s32 execute(ast *a, int fdi, int fd[2]) { |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
26
|
switch (a->k) { |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
27
|
case AK_COMM: {} return execute_comm(a, fdi, fd); |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
28
|
case AK_PIPE: {} return execute_pipe(a, fdi, fd); |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
29
|
default: { log_warn("Unhandled AST kind \"%s\"", ast_ks[a->k]); } return -1; |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
30
|
} |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
31
|
} |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
32
|
|
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
33
|
/* Execute a command statement. */ |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
34
|
static s32 execute_comm(ast *a, int fdi, int fd[2]) { |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
35
|
/* If the command is null, then do nothing */ |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
36
|
if (!a->s) { return _ret; } |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
37
|
|
59a2eec |
Jakob Wakeling |
2023-12-28 14:17:38 |
38
|
/* Handle builtins */ |
59a2eec |
Jakob Wakeling |
2023-12-28 14:17:38 |
39
|
for (bltn *b = bltns; b->name; b += 1) { |
59a2eec |
Jakob Wakeling |
2023-12-28 14:17:38 |
40
|
if (strcmp(a->s, b->name) == 0) { |
59a2eec |
Jakob Wakeling |
2023-12-28 14:17:38 |
41
|
return b->fn(a->c.al - 1, a->c.a); |
59a2eec |
Jakob Wakeling |
2023-12-28 14:17:38 |
42
|
} |
59a2eec |
Jakob Wakeling |
2023-12-28 14:17:38 |
43
|
} |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
44
|
|
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
45
|
pid_t pid; int status, rin = -1, rout = -1, rerr = -1; |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
46
|
|
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
47
|
/* Open redirect files. */ |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
48
|
if (a->rin.s && (rin = open(a->rin.s, O_RDONLY)) == -1) { |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
49
|
log_warn("%s: %s", a->rin.s, strerror(errno)); return -1; |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
50
|
} |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
51
|
if (a->rout.s && (rout = open(a->rout.s, O_WRONLY | O_CREAT | (a->rout.app ? O_APPEND : O_TRUNC), 0666)) == -1) { |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
52
|
if (rin != -1) { close(rin); } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
53
|
log_warn("%s: %s", a->rout.s, strerror(errno)); return -1; |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
54
|
} |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
55
|
if (a->rerr.s && (rerr = open(a->rerr.s, O_WRONLY | O_CREAT | (a->rerr.app ? O_APPEND : O_TRUNC), 0666)) == -1) { |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
56
|
if (rin != -1) { close(rin); } if (rout != -1) { close(rout); } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
57
|
log_warn("%s: %s", a->rerr.s, strerror(errno)); return -1; |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
58
|
} |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
59
|
|
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
60
|
char **av = a->c.a; |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
61
|
|
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
62
|
/* Fork and exec the child process */ |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
63
|
if ((pid = fork()) == 0) { |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
64
|
signal(SIGINT, SIG_DFL); |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
65
|
|
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
66
|
if (rin != -1) { dup2(rin, STDIN_FILENO); } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
67
|
else { dup2(fdi, STDIN_FILENO); } |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
68
|
|
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
69
|
if (rout != -1) { dup2(rout, STDOUT_FILENO); } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
70
|
else if (fd) { dup2(fd[1], STDOUT_FILENO); } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
71
|
if (fd && fd[0]) { close(fd[0]); } |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
72
|
|
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
73
|
if (rerr != -1) { dup2(rerr, STDERR_FILENO); } |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
74
|
|
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
75
|
if (execvp((char *)av[0], (char **)av) == -1) { |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
76
|
if (errno == ENOENT) { log_warn("%s: Command not found", av[0]); } |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
77
|
else { perror((char *)av[0]); } exit(1); |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
78
|
} |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
79
|
} |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
80
|
else if (pid == -1) { perror((char *)av[0]); } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
81
|
else { |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
82
|
if (rout == -1 && fd) { |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
83
|
if (fdi != STDIN_FILENO) { close(fdi); } close(fd[1]); |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
84
|
} |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
85
|
else { |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
86
|
if (fd) { close(fd[1]); } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
87
|
waitpid(pid, &status, 0); |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
88
|
} |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
89
|
} |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
90
|
|
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
91
|
if (rin != -1) { close(rin); } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
92
|
if (rout != -1) { close(rout); } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
93
|
if (rerr != -1) { close(rerr); } |
4a1246f |
Jakob Wakeling |
2023-12-28 14:53:40 |
94
|
|
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
95
|
return WEXITSTATUS(status); |
da120bb |
Jakob Wakeling |
2023-12-27 17:28:40 |
96
|
} |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
97
|
|
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
98
|
static s32 execute_pipe(ast *a, int fdi, int fd[2]) { |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
99
|
int pd[2]; if (pipe(pd) == -1) { log_warn("PIPE: %s", strerror(errno)); return -1; } |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
100
|
execute(a->lc, fdi, pd); return execute(a->rc, pd[0], fd); |
1e336bf |
Jakob Wakeling |
2023-12-28 13:35:12 |
101
|
} |
|
|
|
102
|
|