ESH

Executive Shell
git clone http://git.omkov.net/ESH
Log | Tree | Refs | README | Download

ESH/src/exec.c (103 lines, 2.7 KiB) -rw-r--r-- file download

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