Redirrect support for >, >>, <, &>, 2>

- cd does less work now
This commit is contained in:
Aleksandr Lebedev 2026-04-21 02:51:59 +02:00
parent db5aef12c2
commit 17501b59b4

70
main.c
View file

@ -7,6 +7,7 @@
#include <signal.h>
#include <setjmp.h>
#include <ctype.h>
#include <fcntl.h>
constexpr size_t max_length = 1024;
constexpr size_t max_env_var_length = 256;
@ -86,7 +87,7 @@ struct command
* IO redirections; redirect[i] should be used as fd i in the child.
* A value of -1 indicates no redirect.
*/
int redirect[2];
int redirect[3];
/** The arguments; must be NULL-terminated. */
char* argv[];
};
@ -358,6 +359,13 @@ char* parse_token(char** input)
return buf;
}
int open_fout(const char* file, bool append)
{
return open(file,
O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC),
0644);
}
/**
* Parses str into a freshly allocated command struct and returns a pointer to it.
* The redirects in the returned command will be set to -1, ie no redirect.
@ -378,6 +386,8 @@ struct command* parse_command(char* str)
struct command* ret = ccalloc(sizeof(struct command) + strlen(copy) * sizeof(char*), 1);
parser_allocated(ret);
ret->redirect[0] = ret->redirect[1] = ret->redirect[2] = -1;
char* p = copy;
while (*p)
@ -387,9 +397,47 @@ struct command* parse_command(char* str)
if (!token)
break;
if (strcmp(token, ">") == 0)
{
char* file = parse_token(&p);
int fd = open_fout(file, false);
ret->redirect[STDOUT_FILENO] = fd;
continue;
}
if (strcmp(token, ">>") == 0)
{
char* file = parse_token(&p);
int fd = open_fout(file, true);
ret->redirect[STDOUT_FILENO] = fd;
continue;
}
if (strcmp(token, "<") == 0)
{
char* file = parse_token(&p);
int fd = open(file, O_RDONLY);
ret->redirect[STDIN_FILENO] = fd;
continue;
}
if (strcmp(token, "2>") == 0)
{
char* file = parse_token(&p);
int fd = open_fout(file, false);
ret->redirect[STDERR_FILENO] = fd;
continue;
}
if (strcmp(token, "&>") == 0)
{
char* file = parse_token(&p);
int fd = open_fout(file, false);
ret->redirect[STDOUT_FILENO] = fd;
ret->redirect[STDERR_FILENO] = fd;
continue;
}
ret->argv[i++] = token;
}
ret->redirect[0] = ret->redirect[1] = -1;
return ret;
}
@ -495,15 +543,17 @@ void close_ALL_the_pipes(int n_pipes, int (*pipes)[2])
int exec_with_redir(struct command* command, int n_pipes, int (*pipes)[2])
{
int fd = -1;
if ((fd = command->redirect[0]) != -1)
void apply_redir(int fd, int target)
{
dup2(fd, STDIN_FILENO);
}
if ((fd = command->redirect[1]) != -1)
if (fd != -1)
{
dup2(fd, STDOUT_FILENO);
dup2(fd, target);
if (fd > 2) close(fd); //if file
}
}
apply_redir(command->redirect[0], STDIN_FILENO);
apply_redir(command->redirect[1], STDOUT_FILENO);
apply_redir(command->redirect[2], STDERR_FILENO);
close_ALL_the_pipes(n_pipes, pipes);
return execvp(command_name(command), command->argv);
}
@ -536,6 +586,10 @@ pid_t run_with_redir(struct command* command, int n_pipes, int (*pipes)[2])
int cd(char* path)
{
int result = chdir(path);
if(result < 0)
{
return result;
}
char cwd[max_length];
if (getcwd(cwd, sizeof(cwd)) != NULL)
{