From 91196bcd9705dec2cef878c683b42db5486f5abd Mon Sep 17 00:00:00 2001
From: cxb23 <cxb23@tux2.cci.drexel.edu>
Date: Tue, 11 Feb 2025 22:52:03 -0500
Subject: [PATCH] finished assignment 3-SHellP1

---
 3-ShellP1/.dsh_cli.c.swp | Bin 0 -> 12288 bytes
 3-ShellP1/dsh            | Bin 0 -> 21704 bytes
 3-ShellP1/dsh_cli.c      | 107 ++++++++++++++++++++
 3-ShellP1/dshlib.c       |  94 +++++++++++++++++
 3-ShellP1/dshlib.h       |  51 ++++++++++
 3-ShellP1/makefile       |  27 +++++
 3-ShellP1/test.sh        | 212 +++++++++++++++++++++++++++++++++++++++
 7 files changed, 491 insertions(+)
 create mode 100644 3-ShellP1/.dsh_cli.c.swp
 create mode 100755 3-ShellP1/dsh
 create mode 100644 3-ShellP1/dsh_cli.c
 create mode 100644 3-ShellP1/dshlib.c
 create mode 100644 3-ShellP1/dshlib.h
 create mode 100644 3-ShellP1/makefile
 create mode 100644 3-ShellP1/test.sh

diff --git a/3-ShellP1/.dsh_cli.c.swp b/3-ShellP1/.dsh_cli.c.swp
new file mode 100644
index 0000000000000000000000000000000000000000..bd2da2d883ffa99b5f61bda6b50285fee38b2780
GIT binary patch
literal 12288
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
InGaG10RH^Apa1{>

literal 0
HcmV?d00001

diff --git a/3-ShellP1/dsh b/3-ShellP1/dsh
new file mode 100755
index 0000000000000000000000000000000000000000..4439dfcd727ea2321e58bd7d1b48782c488683a7
GIT binary patch
literal 21704
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
adm%i~*a7GiH5d;;OL;-qS!f#2xC{W}eCV72

literal 0
HcmV?d00001

diff --git a/3-ShellP1/dsh_cli.c b/3-ShellP1/dsh_cli.c
new file mode 100644
index 0000000..e5a80e9
--- /dev/null
+++ b/3-ShellP1/dsh_cli.c
@@ -0,0 +1,107 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dshlib.h"
+
+void printDragon() {
+	printf("[DRAGON for extra credit would print here]\n");
+}
+
+/*
+ * 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.
+ */
+int main()
+{
+    char *cmd_buff = malloc(ARG_MAX * sizeof(char));
+    int rc = OK;
+    command_list_t *clist = malloc(sizeof(command_list_t));
+    clist->num = 0;
+	
+	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
+		if (strcmp(cmd_buff, EXIT_CMD) == 0) {
+			exit(rc);
+		}
+
+		if (strcmp(cmd_buff, "dragon") == 0) {
+			printDragon();
+			continue;
+		}
+
+		if (strcmp(cmd_buff, "\0") == 0) {
+			rc = WARN_NO_CMDS;
+			printf(CMD_WARN_NO_CMD);
+			continue;
+		}
+		
+		rc = build_cmd_list(cmd_buff, clist);
+
+		if (rc == ERR_TOO_MANY_COMMANDS) {
+			printf(CMD_ERR_PIPE_LIMIT, CMD_MAX);
+			continue;
+		}
+
+		printf(CMD_OK_HEADER, clist->num);
+
+		for (int i = 0; i < clist->num; i++) {
+			if (strlen(clist->commands[i].args) > 0) {
+    			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);
+			}
+		}
+	}
+    
+    free(cmd_buff);
+    free(clist);
+    return rc;
+}
+
diff --git a/3-ShellP1/dshlib.c b/3-ShellP1/dshlib.c
new file mode 100644
index 0000000..4e3f473
--- /dev/null
+++ b/3-ShellP1/dshlib.c
@@ -0,0 +1,94 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "dshlib.h"
+
+int numInstanceOf(char *str, const char c) {
+    int count = 0;
+    while (*str != '\0') {
+		if (*str == c) count++;
+    	str++;
+    }
+
+    return count;
+}
+
+/*
+ *  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)
+strcat(command.args, inner_token); *                             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()
+ */
+int build_cmd_list(char *cmd_line, command_list_t *clist)
+{
+	if (numInstanceOf(cmd_line, PIPE_CHAR) > CMD_MAX-1) return ERR_TOO_MANY_COMMANDS;
+	
+	if ((int)strlen(cmd_line) > SH_CMD_MAX) return ERR_CMD_OR_ARGS_TOO_BIG;
+	
+	clist->num = 0;
+
+    char *outer_saveptr = NULL;
+    char *inner_saveptr = NULL;
+    char *outer_token = strtok_r(cmd_line, PIPE_STRING, &outer_saveptr);
+    
+    while (outer_token != NULL) {
+        if (clist->num > CMD_MAX) return ERR_TOO_MANY_COMMANDS;
+
+        command_t command;
+        memset(&command, 0, sizeof(command_t));
+
+
+
+        char *inner_token = strtok_r(outer_token, SPACE_STRING, &inner_saveptr);
+        
+		if (inner_token == NULL) {
+			outer_token = strtok_r(NULL, PIPE_STRING, &outer_saveptr);
+			continue;
+		}
+
+        if (strlen(inner_token) > EXE_MAX) return ERR_CMD_OR_ARGS_TOO_BIG;
+
+        strcpy(command.exe, inner_token);
+		command.args[0] = '\0';
+
+        inner_token = strtok_r(NULL, SPACE_STRING, &inner_saveptr);
+        while (inner_token != NULL) {
+            if (strlen(command.args) + strlen(inner_token) + 1 > ARG_MAX) return ERR_CMD_OR_ARGS_TOO_BIG;
+
+            if (strlen(command.args) > 0) strcat(command.args, SPACE_STRING);
+        	strcat(command.args, inner_token);
+				
+            inner_token = strtok_r(NULL, SPACE_STRING, &inner_saveptr);
+       }
+
+        clist->commands[clist->num] = command;
+        clist->num++;
+
+        outer_token = strtok_r(NULL, PIPE_STRING, &outer_saveptr);
+    }
+
+    return OK;
+}
diff --git a/3-ShellP1/dshlib.h b/3-ShellP1/dshlib.h
new file mode 100644
index 0000000..d0dfe14
--- /dev/null
+++ b/3-ShellP1/dshlib.h
@@ -0,0 +1,51 @@
+#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 SPACE_STRING " "
+#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
diff --git a/3-ShellP1/makefile b/3-ShellP1/makefile
new file mode 100644
index 0000000..d61ca77
--- /dev/null
+++ b/3-ShellP1/makefile
@@ -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
diff --git a/3-ShellP1/test.sh b/3-ShellP1/test.sh
new file mode 100644
index 0000000..676c62b
--- /dev/null
+++ b/3-ShellP1/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 ]
+
+}
-- 
GitLab