aboutsummaryrefslogtreecommitdiff
path: root/smash/exec.c
blob: 3b62f41db06a5d284f188f17c7dc4d452b36ecc6 (plain)
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
#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/io.h"
#include "../lib/sys/exit.h"
#include "../lib/cstr/cstr.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 exec(char *line)
{
	expression_list_t *exps = new_expression_from_line(line);
	expression_list_t *exp = exps;
	char **envp = { 0 };

	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]);

			execve(argv[0], argv, envp);
			write(STDOUT_FD, "command not found: ", 19);
			write(STDOUT_FD, argv[0], cstr_length(argv[0]));
			write(STDOUT_FD, "\n", 1);
			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);
}