Skip to content
Snippets Groups Projects
Commit 65c97d44 authored by Joey Le's avatar Joey Le
Browse files

Added few stuff to dshlib.c

parent eb933219
No related branches found
No related tags found
No related merge requests found
......@@ -9,6 +9,174 @@
#include "dshlib.h"
int build_cmd_buff(char *cmd_line, cmd_buff_t *cmd_buff) {
if (cmd_line == NULL || cmd_buff == NULL) {
return ERR_CMD_OR_ARGS_TOO_BIG;
}
char *original_line = strdup(cmd_line);
if (original_line == NULL) {
return ERR_MEMORY;
}
char *trimmed_line = original_line;
while (*trimmed_line == ' ') {
trimmed_line++;
}
size_t len = strlen(trimmed_line);
while (len > 0 && trimmed_line[len - 1] == ' ') {
trimmed_line[--len] = '\0';
}
cmd_buff->argc = 0;
cmd_buff->_cmd_buffer = original_line;
char *saveptr1;
char *token = strtok_r(trimmed_line, " ", &saveptr1);
while (token != NULL && cmd_buff->argc < CMD_ARGV_MAX) {
if (token[0] == '"' || token[0] == '\'') {
char *end_quote = strchr(token + 1, token[0]);
if (end_quote != NULL) {
*end_quote = '\0';
cmd_buff->argv[cmd_buff->argc++] = token + 1;
token = strtok_r(NULL, " ", &saveptr1);
continue;
}
}
cmd_buff->argv[cmd_buff->argc++] = token;
token = strtok_r(NULL, " ", &saveptr1);
}
cmd_buff->argv[cmd_buff->argc] = NULL;
return OK;
}
int execute_pipeline(command_list_t *cmd_list) {
int num_commands = cmd_list->num;
int pipefd[2];
int prev_pipe_read = -1;
pid_t pids[num_commands];
for (int i = 0; i < num_commands; i++) {
if (i < num_commands - 1) {
if (pipe(pipefd) == -1) {
perror("pipe");
return ERR_MEMORY;
}
}
pids[i] = fork();
if (pids[i] == -1) {
perror("fork");
return ERR_MEMORY;
}
if (pids[i] == 0) {
if (prev_pipe_read != -1) {
dup2(prev_pipe_read, STDIN_FILENO);
close(prev_pipe_read);
}
if (i < num_commands - 1) {
dup2(pipefd[1], STDOUT_FILENO);
close(pipefd[1]);
close(pipefd[0]);
}
cmd_buff_t *cmd = &cmd_list->commands[i];
execvp(cmd->exe, cmd->argv);
perror("execvp");
exit(EXIT_FAILURE);
} else {
if (prev_pipe_read != -1) {
close(prev_pipe_read);
}
if (i < num_commands - 1) {
prev_pipe_read = pipefd[0];
close(pipefd[1]);
}
}
}
for (int i = 0; i < num_commands; i++) {
waitpid(pids[i], NULL, 0);
}
return OK;
}
int parse_pipeline(char *cmd_line, command_list_t *clist) {
if (cmd_line == NULL || clist == NULL) {
return ERR_CMD_OR_ARGS_TOO_BIG;
}
char *original_line = strdup(cmd_line);
if (original_line == NULL) {
return ERR_MEMORY;
}
char *trimmed_line = original_line;
while (*trimmed_line == ' ') {
trimmed_line++;
}
size_t len = strlen(trimmed_line);
while (len > 0 && trimmed_line[len - 1] == ' ') {
trimmed_line[--len] = '\0';
}
int command_count = 0;
char *saveptr1, *saveptr2;
char *command = strtok_r(trimmed_line, PIPE_STRING, &saveptr1);
while (command != NULL && command_count < CMD_MAX) {
memset(&clist->commands[command_count], 0, sizeof(command_t));
char *token = strtok_r(command, " ", &saveptr2);
if (token != NULL) {
if (strlen(token) >= EXE_MAX) {
free(original_line);
return ERR_CMD_OR_ARGS_TOO_BIG;
}
strcpy(clist->commands[command_count].exe, token);
int arg_count = 0;
while ((token = strtok_r(NULL, " ", &saveptr2)) != NULL) {
if (arg_count >= ARG_MAX - 1) {
free(original_line);
return ERR_CMD_OR_ARGS_TOO_BIG;
}
if (strlen(token) >= ARG_MAX) {
free(original_line);
return ERR_CMD_OR_ARGS_TOO_BIG;
}
strcpy(clist->commands[command_count].args[arg_count], token);
arg_count++;
}
clist->commands[command_count].args[arg_count] = NULL;
}
command_count++;
command = strtok_r(NULL, PIPE_STRING, &saveptr1);
}
if (command != NULL) {
// Too many commands
free(original_line);
return ERR_TOO_MANY_COMMANDS;
}
clist->num = command_count;
free(original_line);
return OK;
}
/*
* Implement your exec_local_cmd_loop function by building a loop that prompts the
* user for input. Use the SH_PROMPT constant from dshlib.h and then
......@@ -52,8 +220,90 @@
* Standard Library Functions You Might Want To Consider Using (assignment 2+)
* fork(), execvp(), exit(), chdir()
*/
int exec_local_cmd_loop()
{
return OK;
int exec_local_cmd_loop() {
char cmd_buff[SH_CMD_MAX];
int rc = OK;
while (1) {
printf("%s", SH_PROMPT);
if (fgets(cmd_buff, SH_CMD_MAX, stdin) == NULL) {
printf("\n");
break;
}
cmd_buff[strcspn(cmd_buff, "\n")] = '\0';
if (strlen(cmd_buff) == 0) {
printf("%s\n", CMD_WARN_NO_CMD);
rc = WARN_NO_CMDS;
continue;
}
if (strstr(cmd_buff, "|") != NULL) {
command_list_t cmd_list;
if (parse_pipeline(cmd_buff, &cmd_list) != OK) {
fprintf(stderr, "%s\n", CMD_ERR_PIPE_LIMIT);
rc = ERR_TOO_MANY_COMMANDS;
continue;
}
if (execute_pipeline(&cmd_list) != OK) {
fprintf(stderr, "%s\n", CMD_ERR_EXECUTE);
rc = ERR_MEMORY;
}
free_command_list(&cmd_list);
} else {
cmd_buff_t cmd;
if (build_cmd_buff(cmd_buff, &cmd) != OK) {
fprintf(stderr, "%s\n", CMD_ERR_EXECUTE);
rc = ERR_MEMORY;
continue;
}
if (strcmp(cmd.argv[0], EXIT_CMD) == 0) {
free(cmd._cmd_buffer);
break;
}
if (strcmp(cmd.argv[0], "cd") == 0) {
if (cmd.argc == 1) {
chdir(getenv("HOME"));
} else if (cmd.argc == 2) {
if (chdir(cmd.argv[1]) != 0) {
perror("cd");
}
} else {
fprintf(stderr, "%s\n", CMD_ERR_PIPE_LIMIT);
}
free(cmd._cmd_buffer);
continue;
}
pid_t pid = fork();
if (pid < 0) {
perror("fork failed");
rc = ERR_MEMORY;
} else if (pid == 0) {
execvp(cmd.argv[0], cmd.argv);
perror("execvp failed");
exit(EXIT_FAILURE);
} else {
int status;
wait(&status);
if (WIFEXITED(status)) {
if (WEXITSTATUS(status) != 0) {
fprintf(stderr, "Command failed with exit code %d\n", WEXITSTATUS(status));
}
}
}
free(cmd._cmd_buffer);
}
}
return rc;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment