mirror of
https://github.com/Comp211-SP24/project-Rushilwiz.git
synced 2025-04-03 20:20:17 -04:00
130 lines
2.8 KiB
C
130 lines
2.8 KiB
C
// PID: 730677144
|
|
// I pledge the COMP 211 honor code.
|
|
|
|
// All necessary libraries are included in shell.h
|
|
#include "shell.h"
|
|
|
|
void alloc_mem_for_argv(command_t* p_cmd) {
|
|
p_cmd->argv = (char**)malloc((p_cmd->argc + 1) * sizeof(char*));
|
|
for (int i = 0; i < p_cmd->argc; i++) {
|
|
p_cmd->argv[i] = (char*)malloc(MAX_ARG_LEN * sizeof(char));
|
|
}
|
|
|
|
p_cmd->argv[p_cmd->argc] = NULL;
|
|
}
|
|
|
|
void cleanup(command_t* p_cmd) {
|
|
for (int i = 0; i < p_cmd->argc; i++) {
|
|
free(p_cmd->argv[i]);
|
|
p_cmd->argv[i] = NULL;
|
|
}
|
|
|
|
free(p_cmd->argv);
|
|
p_cmd->argv = NULL;
|
|
}
|
|
|
|
void parse(char* line, command_t* p_cmd) {
|
|
char* line_copy = strdup(line);
|
|
char* token = strtok(line_copy, " ");
|
|
p_cmd->argc = 0;
|
|
|
|
while (token != NULL) {
|
|
p_cmd->argc++;
|
|
token = strtok(NULL, " ");
|
|
}
|
|
|
|
free(line_copy);
|
|
|
|
alloc_mem_for_argv(p_cmd);
|
|
|
|
line_copy = strdup(line);
|
|
token = strtok(line_copy, " ");
|
|
|
|
for (int i = 0; i < p_cmd->argc; i++) {
|
|
strcpy(p_cmd->argv[i], token);
|
|
token = strtok(NULL, " ");
|
|
}
|
|
|
|
free(line_copy);
|
|
}
|
|
|
|
bool find_full_path(command_t* p_cmd) {
|
|
char* path = strdup(getenv("PATH"));
|
|
char* token = strtok(path, ":");
|
|
|
|
while (token != NULL) {
|
|
char* full_path = (char*)malloc(MAX_ARG_LEN * sizeof(char));
|
|
strcpy(full_path, token);
|
|
strcat(full_path, "/");
|
|
strcat(full_path, p_cmd->argv[0]);
|
|
|
|
if (access(full_path, F_OK) == 0) {
|
|
strcpy(p_cmd->argv[0], full_path);
|
|
free(path);
|
|
free(full_path);
|
|
return true;
|
|
}
|
|
|
|
free(full_path);
|
|
token = strtok(NULL, ":");
|
|
}
|
|
|
|
free(path);
|
|
|
|
return false;
|
|
}
|
|
|
|
int execute(command_t* p_cmd) {
|
|
if (is_builtin(p_cmd)) {
|
|
return do_builtin(p_cmd);
|
|
}
|
|
|
|
if (!find_full_path(p_cmd)) {
|
|
printf("Command %s not found!\n", p_cmd->argv[0]);
|
|
return ERROR;
|
|
}
|
|
|
|
// start fork
|
|
pid_t pid = fork();
|
|
|
|
if (pid < 0) {
|
|
return ERROR;
|
|
} else if (pid == 0) {
|
|
// child process
|
|
execv(p_cmd->argv[0], p_cmd->argv);
|
|
exit(EXIT_FAILURE);
|
|
} else {
|
|
// parent process
|
|
int status;
|
|
waitpid(pid, &status, 0);
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
bool is_builtin(command_t* p_cmd) {
|
|
// Do not modify
|
|
char* executable = p_cmd->argv[0];
|
|
if (strcmp(executable, "cd") == 0 || strcmp(executable, "exit") == 0) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
int do_builtin(command_t* p_cmd) {
|
|
// Do not modify
|
|
if (strcmp(p_cmd->argv[0], "exit") == 0) {
|
|
exit(SUCCESS);
|
|
}
|
|
|
|
// cd
|
|
if (p_cmd->argc == 1) { // cd with no arguments
|
|
return chdir(getenv("HOME"));
|
|
} else if (p_cmd->argc == 2) { // cd with 1 arg
|
|
return chdir(p_cmd->argv[1]);
|
|
} else {
|
|
fprintf(stderr, "cd: Too many arguments\n");
|
|
return ERROR;
|
|
}
|
|
}
|