From 22cc652fc63d46a09e214305a5f163559be7daf4 Mon Sep 17 00:00:00 2001 From: vyvyvyThao <wn73@drexel.edu> Date: Thu, 20 Feb 2025 22:17:38 -0500 Subject: [PATCH] submit --- 4-Shell-Part2/bats/assignment_tests.sh | 119 +++++++++++++ 4-Shell-Part2/bats/student_tests.sh | 14 ++ 4-Shell-Part2/dragon.c | 6 + 4-Shell-Part2/dsh | Bin 0 -> 25008 bytes 4-Shell-Part2/dsh_cli.c | 13 ++ 4-Shell-Part2/dshlib.c | 227 +++++++++++++++++++++++++ 4-Shell-Part2/dshlib.h | 79 +++++++++ 4-Shell-Part2/makefile | 31 ++++ 4-Shell-Part2/shell_roadmap.md | 13 ++ 9 files changed, 502 insertions(+) create mode 100644 4-Shell-Part2/bats/assignment_tests.sh create mode 100644 4-Shell-Part2/bats/student_tests.sh create mode 100644 4-Shell-Part2/dragon.c create mode 100755 4-Shell-Part2/dsh create mode 100644 4-Shell-Part2/dsh_cli.c create mode 100644 4-Shell-Part2/dshlib.c create mode 100644 4-Shell-Part2/dshlib.h create mode 100644 4-Shell-Part2/makefile create mode 100644 4-Shell-Part2/shell_roadmap.md diff --git a/4-Shell-Part2/bats/assignment_tests.sh b/4-Shell-Part2/bats/assignment_tests.sh new file mode 100644 index 0000000..d1363ce --- /dev/null +++ b/4-Shell-Part2/bats/assignment_tests.sh @@ -0,0 +1,119 @@ +#!/usr/bin/env bats + +############################ DO NOT EDIT THIS FILE ##################################### +# File: assignement_tests.sh +# +# DO NOT EDIT THIS FILE +# +# Add/Edit Student tests in student_tests.sh +# +# All tests in this file must pass - it is used as part of grading! +######################################################################################## + +@test "Change directory" { + current=$(pwd) + + cd /tmp + mkdir -p dsh-test + + run "${current}/dsh" <<EOF +cd dsh-test +pwd +EOF + + # Strip all whitespace (spaces, tabs, newlines) from the output + stripped_output=$(echo "$output" | tr -d '[:space:]') + + # Expected output with all whitespace removed for easier matching + expected_output="/tmp/dsh-testdsh2>dsh2>dsh2>cmdloopreturned0" + + # These echo commands will help with debugging and will only print + #if the test fails + echo "Captured stdout:" + echo "Output: $output" + echo "Exit Status: $status" + echo "${stripped_output} -> ${expected_output}" + + # Check exact match + [ "$stripped_output" = "$expected_output" ] + + # Assertions + [ "$status" -eq 0 ] +} + +@test "Change directory - no args" { + current=$(pwd) + + cd /tmp + mkdir -p dsh-test + + run "${current}/dsh" <<EOF +cd +pwd +EOF + + # Strip all whitespace (spaces, tabs, newlines) from the output + stripped_output=$(echo "$output" | tr -d '[:space:]') + + # Expected output with all whitespace removed for easier matching + expected_output="/tmpdsh2>dsh2>dsh2>cmdloopreturned0" + + # These echo commands will help with debugging and will only print + #if the test fails + echo "Captured stdout:" + echo "Output: $output" + echo "Exit Status: $status" + echo "${stripped_output} -> ${expected_output}" + + # Check exact match + [ "$stripped_output" = "$expected_output" ] + + # Assertions + [ "$status" -eq 0 ] +} + + +@test "Which which ... which?" { + run "./dsh" <<EOF +which which +EOF + + # Strip all whitespace (spaces, tabs, newlines) from the output + stripped_output=$(echo "$output" | tr -d '[:space:]') + + # Expected output with all whitespace removed for easier matching + expected_output="/usr/bin/whichdsh2>dsh2>cmdloopreturned0" + + # These echo commands will help with debugging and will only print + #if the test fails + echo "Captured stdout:" + echo "Output: $output" + echo "Exit Status: $status" + echo "${stripped_output} -> ${expected_output}" + + # Check exact match + [ "$stripped_output" = "$expected_output" ] +} + +@test "It handles quoted spaces" { + run "./dsh" <<EOF + echo " hello world " +EOF + + # Strip all whitespace (spaces, tabs, newlines) from the output + stripped_output=$(echo "$output" | tr -d '\t\n\r\f\v') + + # Expected output with all whitespace removed for easier matching + expected_output=" hello world dsh2> dsh2> cmd loop returned 0" + + # These echo commands will help with debugging and will only print + #if the test fails + echo "Captured stdout:" + echo "Output: $output" + echo "Exit Status: $status" + echo "actual: '${stripped_output}'" + echo "expected: '${expected_output}'" + + # Check exact match + [ "$stripped_output" = "$expected_output" ] +} \ No newline at end of file diff --git a/4-Shell-Part2/bats/student_tests.sh b/4-Shell-Part2/bats/student_tests.sh new file mode 100644 index 0000000..638bc34 --- /dev/null +++ b/4-Shell-Part2/bats/student_tests.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bats + +# File: student_tests.sh +# +# Create your unit tests suit in this file + +@test "Example: check ls runs without errors" { + run ./dsh <<EOF +ls +EOF + + # Assertions + [ "$status" -eq 0 ] +} diff --git a/4-Shell-Part2/dragon.c b/4-Shell-Part2/dragon.c new file mode 100644 index 0000000..83d01f2 --- /dev/null +++ b/4-Shell-Part2/dragon.c @@ -0,0 +1,6 @@ +#include <stdio.h> + +// EXTRA CREDIT - print the drexel dragon from the readme.md +extern void print_dragon(){ + // TODO implement +} diff --git a/4-Shell-Part2/dsh b/4-Shell-Part2/dsh new file mode 100755 index 0000000000000000000000000000000000000000..c1bca0df63cee349d5f10f3c4e9cb78eab820083 GIT binary patch literal 25008 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 a!t94~!NWFaO2ATABES@b6q*J!E&~9R$s%n4 literal 0 HcmV?d00001 diff --git a/4-Shell-Part2/dsh_cli.c b/4-Shell-Part2/dsh_cli.c new file mode 100644 index 0000000..9262cf4 --- /dev/null +++ b/4-Shell-Part2/dsh_cli.c @@ -0,0 +1,13 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "dshlib.h" + +/* DO NOT EDIT + * main() logic moved to exec_local_cmd_loop() in dshlib.c +*/ +int main(){ + int rc = exec_local_cmd_loop(); + printf("cmd loop returned %d\n", rc); +} \ No newline at end of file diff --git a/4-Shell-Part2/dshlib.c b/4-Shell-Part2/dshlib.c new file mode 100644 index 0000000..b68964e --- /dev/null +++ b/4-Shell-Part2/dshlib.c @@ -0,0 +1,227 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <stdbool.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/wait.h> +#include <errno.h> +#include "dshlib.h" + +/* + * 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 + * use fgets to accept user input. + * + * while(1){ + * printf("%s", SH_PROMPT); + * if (fgets(cmd_buff, ARG_MAX, stdin) == NULL){ + * printf("\n"); + * break; + * } + * //remove the trailing \n from cmd_buff + * cmd_buff[strcspn(cmd_buff,"\n")] = '\0'; + * + * //IMPLEMENT THE REST OF THE REQUIREMENTS + * } + * + * Also, use the constants in the dshlib.h in this code. + * SH_CMD_MAX maximum buffer size for user input + * EXIT_CMD constant that terminates the dsh program + * SH_PROMPT the shell prompt + * OK the command was parsed properly + * WARN_NO_CMDS the user command was empty + * ERR_TOO_MANY_COMMANDS too many pipes used + * ERR_MEMORY dynamic memory management failure + * + * errors returned + * OK No error + * ERR_MEMORY Dynamic memory management failure + * WARN_NO_CMDS No commands parsed + * ERR_TOO_MANY_COMMANDS too many pipes used + * + * console messages + * CMD_WARN_NO_CMD print on WARN_NO_CMDS + * CMD_ERR_PIPE_LIMIT print on ERR_TOO_MANY_COMMANDS + * CMD_ERR_EXECUTE print on execution failure of external command + * + * Standard Library Functions You Might Want To Consider Using (assignment 1+) + * malloc(), free(), strlen(), fgets(), strcspn(), printf() + * + * Standard Library Functions You Might Want To Consider Using (assignment 2+) + * fork(), execvp(), exit(), chdir() + */ + + void printDragon(){ + const char dragon[39][103] = { +" @%%%% \n", +" %%%%%% \n", +" %%%%%% \n", +" % %%%%%%% @ \n", +" %%%%%%%%%% %%%%%%% \n", +" %%%%%%% %%%%@ %%%%%%%%%%%%@ %%%%%% @%%%% \n", +" %%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%% \n", +" %%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%% %%%%%%%%%%%%%%% \n", +" %%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%% %%% \n", +" %%%%%%%%%%%%%%%%%%%%%%%%%%%%@ @%%%%%%%%%%%%%%%%%% %% \n", +" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%% \n", +" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \n", +" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@%%%%%%@ \n", +" %%%%%%%%@ %%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%% %% \n", +" %%%%%%%%%%%%% %%@%%%%%%%%%%%% %%%%%%%%%%% %%%%%%%%%%%% @% \n", +" %%%%%%%%%% %%% %%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%% \n", +" %%%%%%%%% % %%%%%%%%%%%%% %%%%%%%%%%%%@%%%%%%%%%%% \n", +"%%%%%%%%%@ % %%%%%%%%%%%%% @%%%%%%%%%%%%%%%%%%%%%%%%% \n", +"%%%%%%%%@ %%@%%%%%%%%%%%% @%%%%%%%%%%%%%%%%%%%%%%%%%%%% \n", +"%%%%%%%@ %%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \n", +"%%%%%%%%%% %%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% \n", +"%%%%%%%%%@ @%%%%%%%%%%%%%% %%%%%%%%%%%%@ %%%% %%%%%%%%%%%%%%%%% %%%%%%%%\n", +"%%%%%%%%%% %%%%%%%%%%%%%%%%% %%%%%%%%%%%%% %%%%%%%%%%%%%%%%%% %%%%%%%%%\n", +"%%%%%%%%%@%%@ %%%%%%%%%%%%%%%%@ %%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%% %%\n", +" %%%%%%%%%% % %%%%%%%%%%%%%%@ %%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%% %%\n", +" %%%%%%%%%%%% @ %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% \n", +" %%%%%%%%%%%%% %% % %@ %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% \n", +" %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%% @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%% \n", +" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%% %%% \n", +" @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%% \n", +" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%% %%%%%%% \n", +" %%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%% @%%%%%%%%% \n", +" %%%%%%%%%%%%%%%%%%%% @%@% @%%%%%%%%%%%%%%%%%% %%% \n", +" %%%%%%%%%%%%%%% %%%%%%%%%% %%%%%%%%%%%%%%% % \n", +" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%% \n", +" %%%%%%%%%%%%%%%%%%%%%%%%%% %%%% %%% %%%%%%%%%% %%%@ \n", +" %%%%%%%%%%%%%%%%%%% %%%%%% %% %%%%%%%%%%%%%@ \n", +" %%%%%%%@ \n" + }; + + + for (int i = 0; i < sizeof(dragon) / sizeof(dragon[0]); i++) { + for (int j = 0; j < sizeof(dragon[0]) / sizeof(dragon[0][0]); j++) { + if (dragon[i][j] == 0) break; + putchar((char)dragon[i][j]); + } + } +} + +int exec_local_cmd_loop() +{ + char *cmd_buff; + int rc = 0; + cmd_buff_t cmd; + + // TODO IMPLEMENT MAIN LOOP + + // TODO IMPLEMENT parsing input to cmd_buff_t *cmd_buff + cmd_buff = malloc(SH_CMD_MAX); + if (!cmd_buff) return ERR_MEMORY; + + while(1) { + printf("%s", SH_PROMPT); + + if (fgets(cmd_buff, ARG_MAX, stdin) == NULL) { + printf("\n"); + break; + } + + // Remove trailing newline + cmd_buff[strcspn(cmd_buff, "\n")] = '\0'; + + // Skip empty commands + if (strlen(cmd_buff) == 0) { + printf(CMD_WARN_NO_CMD); + continue; + } + + // Parse command and arguments + char *exe = strtok(cmd_buff, " "); + char *args = strtok(NULL, ""); + + + if (exe) { + cmd.argc = 0; + cmd.argv[cmd.argc++] = exe; + + if (args) { + char* lastChar = args + strlen(args) - 1; + + // removing space after the + while (*lastChar == ' ') { + *lastChar = '\0'; + lastChar--; + } + + char *argsNoQuotes = malloc(ARG_MAX); + int numQuotes = 0; + int argQuoteLength = strlen(args); + int argLength = 0; + + while (*args != '\0') { + if (*args == '\"') { + numQuotes++; + args++; + } else { + *argsNoQuotes = *args; + argLength++; + args++; + argsNoQuotes++; + } + } + + argsNoQuotes -= argLength; + cmd.argv[cmd.argc++] = argsNoQuotes; + } + + else { + cmd.argv[cmd.argc] = NULL; + } + } + + + // TODO IMPLEMENT if built-in command, execute builtin logic for exit, cd (extra credit: dragon) + // the cd command should chdir to the provided directory; if no directory is provided, do nothing + + if (strcmp(cmd.argv[0], EXIT_CMD) == 0) { + break; + + } else if (strcmp(cmd.argv[0], "cd") == 0) { + if (cmd.argv[1]) { + if (chdir(cmd.argv[1]) != 0) { + perror("cd"); + rc = ERR_CMD_ARGS_BAD; + } + } + continue; + + } else if (strcmp(cmd.argv[0], "dragon") == 0) { + printDragon(); + continue; + } + else if (strcmp(cmd.argv[0], "rc") == 0) { + printf("%d\n", rc); + continue; + } + // TODO IMPLEMENT if not built-in command, fork/exec as an external command + // for example, if the user input is "ls -l", you would fork/exec the command "ls" with the arg "-l" + + pid_t pid = fork(); + + if (pid < 0) { + // printf(CMD_ERR_EXECUTE); + return ERR_MEMORY; + } else if (pid == 0) { + execvp(cmd.argv[0], cmd.argv); + // printf(CMD_ERR_EXECUTE); + exit(errno); + } else { + // parent process + wait(&rc); + if (WIFEXITED(rc)) { + rc = WEXITSTATUS(rc); // Store last return code + } else { + rc = ERR_EXEC_CMD; + } + // wait(NULL); + } + } +} diff --git a/4-Shell-Part2/dshlib.h b/4-Shell-Part2/dshlib.h new file mode 100644 index 0000000..32059cc --- /dev/null +++ b/4-Shell-Part2/dshlib.h @@ -0,0 +1,79 @@ +#ifndef __DSHLIB_H__ + #define __DSHLIB_H__ + + +//Constants for command structure sizes +#define EXE_MAX 64 +#define ARG_MAX 256 +#define CMD_MAX 8 +#define CMD_ARGV_MAX (CMD_MAX + 1) +// Longest command that can be read from the shell +#define SH_CMD_MAX EXE_MAX + ARG_MAX + +typedef struct cmd_buff +{ + int argc; + char *argv[CMD_ARGV_MAX]; + char *_cmd_buffer; +} cmd_buff_t; + +/* WIP - Move to next assignment +#define N_ARG_MAX 15 //MAX number of args for a command +typedef struct command{ + char exe [EXE_MAX]; + char args[ARG_MAX]; + int argc; + char *argv[N_ARG_MAX + 1]; //last argv[LAST] must be \0 +}command_t; +*/ + + +//Special character #defines +#define SPACE_CHAR ' ' +#define PIPE_CHAR '|' +#define PIPE_STRING "|" + +#define SH_PROMPT "dsh2> " +#define EXIT_CMD "exit" + +//Standard Return Codes +#define OK 0 +#define WARN_NO_CMDS -1 +#define ERR_TOO_MANY_COMMANDS -2 +#define ERR_CMD_OR_ARGS_TOO_BIG -3 +#define ERR_CMD_ARGS_BAD -4 //for extra credit +#define ERR_MEMORY -5 +#define ERR_EXEC_CMD -6 +#define OK_EXIT -7 + +//prototypes +int alloc_cmd_buff(cmd_buff_t *cmd_buff); +int free_cmd_buff(cmd_buff_t *cmd_buff); +int clear_cmd_buff(cmd_buff_t *cmd_buff); +int build_cmd_buff(char *cmd_line, cmd_buff_t *cmd_buff); + +//built in command stuff +typedef enum { + BI_CMD_EXIT, + BI_CMD_DRAGON, + BI_CMD_CD, + BI_NOT_BI, + BI_EXECUTED, + BI_RC, +} Built_In_Cmds; +Built_In_Cmds match_command(const char *input); +Built_In_Cmds exec_built_in_cmd(cmd_buff_t *cmd); + +//main execution context +int exec_local_cmd_loop(); +int exec_cmd(cmd_buff_t *cmd); + + + + +//output constants +#define CMD_OK_HEADER "PARSED COMMAND LINE - TOTAL COMMANDS %d\n" +#define CMD_WARN_NO_CMD "warning: no commands provided\n" +#define CMD_ERR_PIPE_LIMIT "error: piping limited to %d commands\n" + +#endif \ No newline at end of file diff --git a/4-Shell-Part2/makefile b/4-Shell-Part2/makefile new file mode 100644 index 0000000..b14b072 --- /dev/null +++ b/4-Shell-Part2/makefile @@ -0,0 +1,31 @@ +# Compiler settings +CC = gcc +CFLAGS = -Wall -Wextra -g + +# Target executable name +TARGET = dsh + +# Find all source and header files +SRCS = $(wildcard *.c) +HDRS = $(wildcard *.h) + +# Default target +all: $(TARGET) + +# Compile source to executable +$(TARGET): $(SRCS) $(HDRS) + $(CC) $(CFLAGS) -o $(TARGET) $(SRCS) + +# Clean up build files +clean: + rm -f $(TARGET) + +test: + bats $(wildcard ./bats/*.sh) + +valgrind: + echo "pwd\nexit" | valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=1 ./$(TARGET) + echo "pwd\nexit" | valgrind --tool=helgrind --error-exitcode=1 ./$(TARGET) + +# Phony targets +.PHONY: all clean test \ No newline at end of file diff --git a/4-Shell-Part2/shell_roadmap.md b/4-Shell-Part2/shell_roadmap.md new file mode 100644 index 0000000..9af1434 --- /dev/null +++ b/4-Shell-Part2/shell_roadmap.md @@ -0,0 +1,13 @@ +## Proposed Shell Roadmap + +Week 5: Shell CLI Parser Due + +Week 6: Execute Basic Commands + +Week 7: Add support for pipes (extra-credit for file redirection) + +Week 8: Basic socket assignment + +Week 9: Remote Shell Extension + +Week 11: Add support for something like `nsenter` to enter a namespace \ No newline at end of file -- GitLab