From 73bf2e5058fb46adf652cc823d2591995c7b2ee7 Mon Sep 17 00:00:00 2001 From: vyvyvyThao <wn73@drexel.edu> Date: Wed, 12 Feb 2025 22:10:13 -0500 Subject: [PATCH] Upload A3 --- 3-Shell/.vscode/settings.json | 5 + 3-Shell/dsh | Bin 0 -> 24856 bytes 3-Shell/dsh_cli.c | 84 ++++++++++++++ 3-Shell/dshlib.c | 161 ++++++++++++++++++++++++++ 3-Shell/dshlib.h | 50 ++++++++ 3-Shell/makefile.txt | 27 +++++ 3-Shell/test.sh | 212 ++++++++++++++++++++++++++++++++++ 7 files changed, 539 insertions(+) create mode 100644 3-Shell/.vscode/settings.json create mode 100755 3-Shell/dsh create mode 100644 3-Shell/dsh_cli.c create mode 100644 3-Shell/dshlib.c create mode 100644 3-Shell/dshlib.h create mode 100644 3-Shell/makefile.txt create mode 100644 3-Shell/test.sh diff --git a/3-Shell/.vscode/settings.json b/3-Shell/.vscode/settings.json new file mode 100644 index 0000000..d4a224b --- /dev/null +++ b/3-Shell/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "ctype.h": "c" + } +} \ No newline at end of file diff --git a/3-Shell/dsh b/3-Shell/dsh new file mode 100755 index 0000000000000000000000000000000000000000..a8c1465c640b180fbb9787195897c4d0481646df GIT binary patch literal 24856 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 literal 0 HcmV?d00001 diff --git a/3-Shell/dsh_cli.c b/3-Shell/dsh_cli.c new file mode 100644 index 0000000..4b3b192 --- /dev/null +++ b/3-Shell/dsh_cli.c @@ -0,0 +1,84 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "dshlib.h" + +/* + * Implement your main 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. Since we want fgets to also handle + * end of file so we can run this headless for testing we need to check + * the return code of fgets. I have provided an example below of how + * to do this assuming you are storing user input inside of the cmd_buff + * variable. + * + * 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 + * + * Expected output: + * + * CMD_OK_HEADER if the command parses properly. You will + * follow this by the command details + * + * CMD_WARN_NO_CMD if the user entered a blank command + * CMD_ERR_PIPE_LIMIT if the user entered too many commands using + * the pipe feature, e.g., cmd1 | cmd2 | ... | + * + * See the provided test cases for output expectations. + */ +void _exit(char *buff) { + free(buff); + exit(OK); +} + +int main() +{ + char *cmd_buff = malloc(ARG_MAX); + command_list_t *clist = malloc(sizeof(command_list_t)); + int commandCount = 0; + + int code = 0; + + while(1){ + clist->num = 0; + + printf("%s", SH_PROMPT); + if (fgets(cmd_buff, ARG_MAX, stdin) == NULL){ + break; + } + + //remove the trailing \n from cmd_buff + cmd_buff[strcspn(cmd_buff,"\n")] = '\0'; + + //IMPLEMENT THE REST OF THE REQUIREMENTS + if (strcmp(cmd_buff, EXIT_CMD) == 0) { + _exit(cmd_buff); + } + + else { + // printf("Command line: %s\n", cmd_buff); + code = build_cmd_list(cmd_buff, clist); + } + + } + + free(clist); +} \ No newline at end of file diff --git a/3-Shell/dshlib.c b/3-Shell/dshlib.c new file mode 100644 index 0000000..abe3c79 --- /dev/null +++ b/3-Shell/dshlib.c @@ -0,0 +1,161 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> + +#include "dshlib.h" + +/* + * build_cmd_list + * cmd_line: the command line from the user + * clist *: pointer to clist structure to be populated + * + * This function builds the command_list_t structure passed by the caller + * It does this by first splitting the cmd_line into commands by spltting + * the string based on any pipe characters '|'. It then traverses each + * command. For each command (a substring of cmd_line), it then parses + * that command by taking the first token as the executable name, and + * then the remaining tokens as the arguments. + * + * NOTE your implementation should be able to handle properly removing + * leading and trailing spaces! + * + * errors returned: + * + * OK: No Error + * ERR_TOO_MANY_COMMANDS: There is a limit of CMD_MAX (see dshlib.h) + * commands. + * ERR_CMD_OR_ARGS_TOO_BIG: One of the commands provided by the user + * was larger than allowed, either the + * executable name, or the arg string. + * + * Standard Library Functions You Might Want To Consider Using + * memset(), strcmp(), strcpy(), strtok(), strlen(), strchr() + */ +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 build_cmd_list(char *cmd_line, command_list_t *clist) +{ + if (strlen(cmd_line) == 0) { + printf(CMD_WARN_NO_CMD); + return OK; + } + + // get the first command + char* token; + + token = strtok(cmd_line, PIPE_STRING); + + + // keep getting commands until token is NULL + while (token != 0) { + + // trim empty space at the start and end of command + while (*token == SPACE_CHAR) token++; + + if (token[strlen(token) - 1] == SPACE_CHAR) token[strlen(token) - 1] = '\0'; + + command_t* command = malloc(sizeof(command_t)); + + if (strlen(token) > SH_CMD_MAX) { + return ERR_CMD_OR_ARGS_TOO_BIG; + } + + strcpy(command->exe,token); + + clist->commands[clist->num] = *command; + clist->num += 1; + + // printf("Current: %s\n", token); + token = strtok(0, PIPE_STRING); + } + + if (clist->num > CMD_MAX) { + printf("dsh> "); + printf(CMD_ERR_PIPE_LIMIT, CMD_MAX); + return ERR_TOO_MANY_COMMANDS; + } + + + printf(CMD_OK_HEADER, clist->num); + + // printf("Number of commands read in: %d\n", clist->num); + for (int i = 0; i < clist->num; i++){ + // printf("Command #%d: %s\n", i+1, clist->commands[i].exe); + // char *exe = malloc(EXE_MAX * sizeof(char)); + // char *args = malloc(ARG_MAX * sizeof(char)); + + // exe = strtok(clist->commands[i].exe, " "); + // args = strtok(0, ""); + + char *exe = strtok(clist->commands[i].exe, " "); + char *args = strtok(NULL, ""); + + if (exe) { + if (strcmp(exe, "dragon") == 0) { + printDragon(); + } + strcpy(clist->commands[i].exe, exe); + } + + if (args) { + strcpy(clist->commands[i].args, args); + printf("<%d> %s [%s]\n", i+1, clist->commands[i].exe, clist->commands[i].args); + } else { + printf("<%d> %s\n", i+1, clist->commands[i].exe); + } + // printf("Exe: %s\t Arguments: %s\n", clist->commands[i].exe, clist->commands[i].args); + } + + return OK; +} \ No newline at end of file diff --git a/3-Shell/dshlib.h b/3-Shell/dshlib.h new file mode 100644 index 0000000..1353bbd --- /dev/null +++ b/3-Shell/dshlib.h @@ -0,0 +1,50 @@ +#ifndef __DSHLIB_H__ +#define __DSHLIB_H__ + +// Constants for command structure sizes +#define EXE_MAX 64 +#define ARG_MAX 256 +#define CMD_MAX 8 +// Longest command that can be read from the shell +#define SH_CMD_MAX EXE_MAX + ARG_MAX + +typedef struct command +{ + char exe[EXE_MAX]; + char args[ARG_MAX]; +} command_t; + +typedef struct command_list +{ + int num; + command_t commands[CMD_MAX]; +} command_list_t; + +// Special character #defines +#define SPACE_CHAR ' ' +#define PIPE_CHAR '|' +#define PIPE_STRING "|" + +#define SH_PROMPT "dsh> " +#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 + +// starter code +#define M_NOT_IMPL "The requested operation is not implemented yet!\n" +#define EXIT_NOT_IMPL 3 +#define NOT_IMPLEMENTED_YET 0 + +// prototypes +int build_cmd_list(char *cmd_line, command_list_t *clist); + +// 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/3-Shell/makefile.txt b/3-Shell/makefile.txt new file mode 100644 index 0000000..9d20e5b --- /dev/null +++ b/3-Shell/makefile.txt @@ -0,0 +1,27 @@ +# 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: + ./test.sh + +# Phony targets +.PHONY: all clean \ No newline at end of file diff --git a/3-Shell/test.sh b/3-Shell/test.sh new file mode 100644 index 0000000..6d586db --- /dev/null +++ b/3-Shell/test.sh @@ -0,0 +1,212 @@ +#!/usr/bin/env bats + +@test "Simple Command" { + run ./dsh <<EOF +test_command +exit +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="dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS1<1>test_commanddsh>" + + # 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" + + # Check exact match + [ "$stripped_output" = "$expected_output" ] + + # Assertions + [ "$status" -eq 0 ] + +} + +@test "Simple Command with Args" { + run ./dsh <<EOF +cmd -a1 -a2 +exit +EOF + + # Strip all whitespace (spaces, tabs, newlines) from the output + stripped_output=$(echo "$output" | tr -d '[:space:]') + + # Expected output + expected_output="dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS1<1>cmd[-a1-a2]dsh>" + + # 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" + + # Check exact match + [ "$stripped_output" = "$expected_output" ] + + # Assertions + [ "$status" -eq 0 ] + +} + + +@test "No command provided" { + run ./dsh <<EOF + +exit +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="dsh>warning:nocommandsprovideddsh>" + + # 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" + + # Check exact match + [ "$stripped_output" = "$expected_output" ] + + # Assertions + [ "$status" -eq 0 ] + +} + +@test "Two commands" { + run ./dsh <<EOF +command_one | command_two +exit +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="dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS2<1>command_one<2>command_twodsh>" + + # 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" + + # Check exact match + [ "$stripped_output" = "$expected_output" ] + + # Assertions + [ "$status" -eq 0 ] + +} + +@test "three commands with args" { + run ./dsh <<EOF +cmd1 a1 a2 a3 | cmd2 a4 a5 a6 | cmd3 a7 a8 a9 +exit +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="dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS3<1>cmd1[a1a2a3]<2>cmd2[a4a5a6]<3>cmd3[a7a8a9]dsh>" + + # 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" + + # Check exact match + [ "$stripped_output" = "$expected_output" ] + + # Assertions + [ "$status" -eq 0 ] + +} + +@test "try max (8) commands" { + run ./dsh <<EOF +cmd1 | cmd2 | cmd3 | cmd4 | cmd5 | cmd6 | cmd7 | cmd8 +exit +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="dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS8<1>cmd1<2>cmd2<3>cmd3<4>cmd4<5>cmd5<6>cmd6<7>cmd7<8>cmd8dsh>" + + # 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" + + # Check exact match + [ "$stripped_output" = "$expected_output" ] + + # Assertions + [ "$status" -eq 0 ] + +} + +@test "try too many commands" { + run ./dsh <<EOF +cmd1 | cmd2 | cmd3 | cmd4 | cmd5 | cmd6 | cmd7 | cmd8 | cmd9 +exit +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="dsh>error:pipinglimitedto8commandsdsh>" + + # 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" + + # Check exact match + [ "$stripped_output" = "$expected_output" ] + + # Assertions + [ "$status" -eq 0 ] + +} + +@test "kitchen sink - multiple commands" { + run ./dsh <<EOF +cmd1 +cmd2 arg arg2 +p1 | p2 +p3 p3a1 p3a2 | p4 p4a1 p4a2 +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="dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS1<1>cmd1dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS1<1>cmd2[argarg2]dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS2<1>p1<2>p2dsh>PARSEDCOMMANDLINE-TOTALCOMMANDS2<1>p3[p3a1p3a2]<2>p4[p4a1p4a2]dsh>" + + # 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" + + # Check exact match + [ "$stripped_output" = "$expected_output" ] + + # Assertions + [ "$status" -eq 0 ] + +} \ No newline at end of file -- GitLab