From ea9272dce3d0c9cf05610c4587feac2dde990aa9 Mon Sep 17 00:00:00 2001
From: cxb23 <cxb23@tux1.cci.drexel.edu>
Date: Fri, 21 Feb 2025 23:55:10 -0500
Subject: [PATCH] finished assignment 4

---
 4-ShellP2/.dshlib.c.swp           | Bin 0 -> 24576 bytes
 4-ShellP2/bats/assignment_test.sh | 118 +++++++++++++
 4-ShellP2/bats/student_test.sh    |  14 ++
 4-ShellP2/dragon.c                |  37 ++++
 4-ShellP2/dragon.txt              |  38 +++++
 4-ShellP2/dsh                     | Bin 0 -> 24968 bytes
 4-ShellP2/dsh_cli.c               |  13 ++
 4-ShellP2/dshlib.c                | 275 ++++++++++++++++++++++++++++++
 4-ShellP2/dshlib.h                |  85 +++++++++
 4-ShellP2/makefile                |  31 ++++
 10 files changed, 611 insertions(+)
 create mode 100644 4-ShellP2/.dshlib.c.swp
 create mode 100644 4-ShellP2/bats/assignment_test.sh
 create mode 100644 4-ShellP2/bats/student_test.sh
 create mode 100644 4-ShellP2/dragon.c
 create mode 100644 4-ShellP2/dragon.txt
 create mode 100755 4-ShellP2/dsh
 create mode 100644 4-ShellP2/dsh_cli.c
 create mode 100644 4-ShellP2/dshlib.c
 create mode 100644 4-ShellP2/dshlib.h
 create mode 100644 4-ShellP2/makefile

diff --git a/4-ShellP2/.dshlib.c.swp b/4-ShellP2/.dshlib.c.swp
new file mode 100644
index 0000000000000000000000000000000000000000..7b1c66f6e023becd69f71d5ed390e4de36e131a8
GIT binary patch
literal 24576
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

literal 0
HcmV?d00001

diff --git a/4-ShellP2/bats/assignment_test.sh b/4-ShellP2/bats/assignment_test.sh
new file mode 100644
index 0000000..30b12ec
--- /dev/null
+++ b/4-ShellP2/bats/assignment_test.sh
@@ -0,0 +1,118 @@
+#!/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 "${stripped_output} -> ${expected_output}"
+
+    # Check exact match
+    [ "$stripped_output" = "$expected_output" ]
+}
diff --git a/4-ShellP2/bats/student_test.sh b/4-ShellP2/bats/student_test.sh
new file mode 100644
index 0000000..638bc34
--- /dev/null
+++ b/4-ShellP2/bats/student_test.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-ShellP2/dragon.c b/4-ShellP2/dragon.c
new file mode 100644
index 0000000..b5ac87f
--- /dev/null
+++ b/4-ShellP2/dragon.c
@@ -0,0 +1,37 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "dshlib.h"
+
+// EXTRA CREDIT - print the drexel dragon from the readme.md
+extern void print_dragon(){
+	// TODO implement
+	FILE *dragon = fopen("dragon.txt", "r");
+	if (dragon == NULL) {
+		return;
+  	}
+
+	char *s = NULL;
+	size_t nbyte;
+	ssize_t nchar;
+
+	while (1) {
+		nchar = getline(&s, &nbyte, dragon);
+		if (nchar == -1) { // end of file reached
+            break;
+        }
+        if (nchar == 0) {
+            continue;
+        }
+        if (s == NULL) { // out of memory
+            exit(1);
+        }
+        if (s[nchar - 1] == '\n') {
+            s[nchar - 1] = '\0'; // remove newline
+            nchar--; // newline removed
+        }
+
+        printf("%s\n", s);
+	}
+	free(s);
+	fclose(dragon);
+}
diff --git a/4-ShellP2/dragon.txt b/4-ShellP2/dragon.txt
new file mode 100644
index 0000000..a9177fd
--- /dev/null
+++ b/4-ShellP2/dragon.txt
@@ -0,0 +1,38 @@
+                                                                        @%%%%                       
+                                                                     %%%%%%                         
+                                                                    %%%%%%                          
+                                                                 % %%%%%%%           @              
+                                                                %%%%%%%%%%        %%%%%%%           
+                                       %%%%%%%  %%%%@         %%%%%%%%%%%%@    %%%%%%  @%%%%        
+                                  %%%%%%%%%%%%%%%%%%%%%%      %%%%%%%%%%%%%%%%%%%%%%%%%%%%          
+                                %%%%%%%%%%%%%%%%%%%%%%%%%%   %%%%%%%%%%%% %%%%%%%%%%%%%%%           
+                               %%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%     %%%            
+                             %%%%%%%%%%%%%%%%%%%%%%%%%%%%@ @%%%%%%%%%%%%%%%%%%        %%            
+                            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%                
+                            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              
+                            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@%%%%%%@              
+      %%%%%%%%@           %%%%%%%%%%%%%%%%        %%%%%%%%%%%%%%%%%%%%%%%%%%      %%                
+    %%%%%%%%%%%%%         %%@%%%%%%%%%%%%           %%%%%%%%%%% %%%%%%%%%%%%      @%                
+  %%%%%%%%%%   %%%        %%%%%%%%%%%%%%            %%%%%%%%%%%%%%%%%%%%%%%%                        
+ %%%%%%%%%       %         %%%%%%%%%%%%%             %%%%%%%%%%%%@%%%%%%%%%%%                       
+%%%%%%%%%@                % %%%%%%%%%%%%%            @%%%%%%%%%%%%%%%%%%%%%%%%%                     
+%%%%%%%%@                 %%@%%%%%%%%%%%%            @%%%%%%%%%%%%%%%%%%%%%%%%%%%%                  
+%%%%%%%@                   %%%%%%%%%%%%%%%           %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              
+%%%%%%%%%%                  %%%%%%%%%%%%%%%          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%      %%%%  
+%%%%%%%%%@                   @%%%%%%%%%%%%%%         %%%%%%%%%%%%@ %%%% %%%%%%%%%%%%%%%%%   %%%%%%%%
+%%%%%%%%%%                  %%%%%%%%%%%%%%%%%        %%%%%%%%%%%%%      %%%%%%%%%%%%%%%%%% %%%%%%%%%
+%%%%%%%%%@%%@                %%%%%%%%%%%%%%%%@       %%%%%%%%%%%%%%     %%%%%%%%%%%%%%%%%%%%%%%%  %%
+ %%%%%%%%%%                  % %%%%%%%%%%%%%%@        %%%%%%%%%%%%%%   %%%%%%%%%%%%%%%%%%%%%%%%%% %%
+  %%%%%%%%%%%%  @           %%%%%%%%%%%%%%%%%%        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%% 
+   %%%%%%%%%%%%% %%  %  %@ %%%%%%%%%%%%%%%%%%          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    %%% 
+    %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%           @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    %%%%%%% 
+     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              %%%%%%%%%%%%%%%%%%%%%%%%%%%%        %%%   
+      @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                  %%%%%%%%%%%%%%%%%%%%%%%%%               
+        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                      %%%%%%%%%%%%%%%%%%%  %%%%%%%          
+           %%%%%%%%%%%%%%%%%%%%%%%%%%                           %%%%%%%%%%%%%%%  @%%%%%%%%%         
+              %%%%%%%%%%%%%%%%%%%%           @%@%                  @%%%%%%%%%%%%%%%%%%   %%%        
+                  %%%%%%%%%%%%%%%        %%%%%%%%%%                    %%%%%%%%%%%%%%%    %         
+                %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                      %%%%%%%%%%%%%%            
+                %%%%%%%%%%%%%%%%%%%%%%%%%%  %%%% %%%                      %%%%%%%%%%  %%%@          
+                     %%%%%%%%%%%%%%%%%%% %%%%%% %%                          %%%%%%%%%%%%%@          
+                                                                                 %%%%%%%@       
diff --git a/4-ShellP2/dsh b/4-ShellP2/dsh
new file mode 100755
index 0000000000000000000000000000000000000000..bc71f23f06921448398c90d8c8ef9609de2dbfd4
GIT binary patch
literal 24968
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
Qfhh*iN_PkgLZa&j0IxVzO8@`>

literal 0
HcmV?d00001

diff --git a/4-ShellP2/dsh_cli.c b/4-ShellP2/dsh_cli.c
new file mode 100644
index 0000000..ef8029b
--- /dev/null
+++ b/4-ShellP2/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);
+}
diff --git a/4-ShellP2/dshlib.c b/4-ShellP2/dshlib.c
new file mode 100644
index 0000000..c168f6d
--- /dev/null
+++ b/4-ShellP2/dshlib.c
@@ -0,0 +1,275 @@
+#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"
+
+int numInstanceOf(char *str, const char c) {
+	int count = 0;
+	while (*str != '\0') {
+		if (*str == c) count++;
+		str++;
+	}
+	return count;
+}
+
+int alloc_cmd_buff(cmd_buff_t *cmd_buff) {
+	if (cmd_buff == NULL) {
+		return ERR_MEMORY;
+	}
+	cmd_buff->argc = 0;
+	
+	cmd_buff->argv = (char**)malloc(CMD_ARGV_MAX * sizeof(char *));
+	if (cmd_buff->argv == NULL) {
+    	free(cmd_buff);
+    	return ERR_MEMORY;
+	}
+
+	for (int i = 0; i < CMD_ARGV_MAX; i++) {
+        cmd_buff->argv[i] = (char *)malloc(ARG_MAX);
+        if (cmd_buff->argv[i] == NULL) {
+            for (int j = 0; j < i; j++) {
+                free(cmd_buff->argv[j]);
+            }
+            free(cmd_buff->argv);
+            return ERR_MEMORY;
+        }
+    }
+
+	cmd_buff->_cmd_buffer = (char *)malloc(SH_CMD_MAX);
+	if (cmd_buff->_cmd_buffer == NULL) {
+        free(cmd_buff->_cmd_buffer);
+		for (int i = 0; i < CMD_ARGV_MAX; i++) {
+            free(cmd_buff->argv[i]);
+        }
+        free(cmd_buff->argv);
+        return ERR_MEMORY;
+    }
+
+
+	return OK_EXIT;
+}
+
+int free_cmd_buff(cmd_buff_t *cmd_buff) {
+	free(cmd_buff->_cmd_buffer);
+	 
+	for (int i = 0; i < CMD_ARGV_MAX - 1; i++) free(cmd_buff->argv[i]);
+	free(cmd_buff);
+	return OK_EXIT;
+}
+
+int clear_cmd_buff(cmd_buff_t *cmd_buff) {
+	cmd_buff->argc = 0;
+	free(cmd_buff->_cmd_buffer);
+	
+	for (int i = 0; i < CMD_ARGV_MAX; i++) cmd_buff->argv[i] = NULL;
+	return OK_EXIT;
+}
+
+char* trim_whitespace(char *str) {
+	int start = 0;
+	while (isspace((unsigned char)str[start])) {
+		start++;
+	}
+
+  	int end = strlen(str) - 1;
+  	while (end > start && isspace((unsigned char)str[end])) {
+    	end--;
+  	}
+
+  	int j = 0;
+  	for (int i = start; i <= end; i++) {
+    	str[j++] = str[i];
+  	}
+  	str[j] = '\0';
+  	
+  	return str;
+}
+
+int build_cmd_buff(char *cmd_line, cmd_buff_t *cmd_buff) {
+	if ((int)strlen(cmd_line) > SH_CMD_MAX) return ERR_CMD_OR_ARGS_TOO_BIG;
+
+	if ((int)strlen(cmd_line) == 0) return WARN_NO_CMDS;	
+	
+	cmd_buff->_cmd_buffer = strdup(trim_whitespace(cmd_line));
+	if (cmd_buff->_cmd_buffer == NULL) {
+		free(cmd_buff);
+		return ERR_MEMORY;
+	}
+	
+	char *token = cmd_buff->_cmd_buffer;
+	bool quotes = false;
+	char *p = NULL;
+
+	while (*token) {
+		if (*token == DOUBLE_QUOTE_CHAR) {
+			quotes = !quotes;
+			if (quotes) p = token + 1;
+			else *token = '\0';
+		} else if (!quotes && (*token == SPACE_CHAR || *token == '\t')) {
+			*token = '\0';
+
+			if (p != NULL) {
+				cmd_buff->argv[cmd_buff->argc++] = p;
+				p = NULL;
+			}
+		} else if (p == NULL) {
+			p = token;
+		}
+		token++;
+	}
+
+	if (p != NULL) cmd_buff->argv[cmd_buff->argc++] = p;
+
+	cmd_buff->argv[cmd_buff->argc] = NULL;
+	return OK_EXIT;
+}
+/*
+ * 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()
+ */
+int exec_local_cmd_loop()
+{
+    char *cmd_buff = malloc(ARG_MAX * sizeof(char));
+	int rc = 0;
+    cmd_buff_t *cmd = malloc(CMD_ARGV_MAX * sizeof(char *));
+	
+	if ((rc = alloc_cmd_buff(cmd)) != OK_EXIT) exit(rc);
+
+    // TODO IMPLEMENT MAIN LOOP
+	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, "rc") == 0) {
+        	printf("%d\n", rc);
+			if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
+			continue;
+		}
+
+        if (strcmp(cmd_buff, "\0") == 0) {
+            rc = WARN_NO_CMDS;
+            printf(CMD_WARN_NO_CMD);
+            //if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
+            continue;
+        }
+		
+		// TODO IMPLEMENT parsing input to cmd_buff_t *cmd_buff
+		if ((rc = build_cmd_buff(cmd_buff, cmd)) != OK_EXIT) {
+            exit(rc);
+            rc = 0;
+    	}
+		/*
+		if (strcmp(cmd->argv[0], "echo") == 0) {
+			for (int i = 1; i < CMD_ARGV_MAX; i++) {
+				printf("%s ", cmd->argv[i]);
+			}
+			printf("\n");
+			if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
+			continue;
+		}*/
+		
+		// TODO IMPLEMENT if built-in command, execute builtin logic for exit, cd (extra credit: dragon)
+		if (strcmp(cmd_buff, "dragon") == 0) {
+            print_dragon();
+            if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
+            rc = 0;
+            continue;
+        }
+
+    	// the cd command should chdir to the provided directory; if no directory is provided, do nothing
+    	if (strcmp(cmd->argv[0], "cd") == 0) {
+			if (cmd->argc < 2) {
+				if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
+				rc = 0;
+				continue;
+			}
+			if (chdir(cmd->argv[1]) != 0) {
+				perror("chdir failed");
+				rc = 1;
+			}
+			if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
+			rc = 0;
+			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("fork failed");
+			if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
+			continue;
+    	} else if (pid == 0) {
+			execvp(cmd->argv[0], cmd->argv);
+			perror(CMD_ERR_EXECUTE);
+			exit(1);
+    	} else {
+			int status;
+			waitpid(pid, &status, 0);
+			if (WIFEXITED(status)) {
+				rc = WEXITSTATUS(status);
+			} else {
+				rc = 1;
+			}
+    	}
+		if ((rc = clear_cmd_buff(cmd)) != OK_EXIT) exit(rc);
+	}
+	free(cmd_buff);
+	free_cmd_buff(cmd);
+    return OK;
+}
diff --git a/4-ShellP2/dshlib.h b/4-ShellP2/dshlib.h
new file mode 100644
index 0000000..df2f9a4
--- /dev/null
+++ b/4-ShellP2/dshlib.h
@@ -0,0 +1,85 @@
+#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;
+    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 SPACE_STRING " "
+#define PIPE_CHAR   '|'
+#define PIPE_STRING "|"
+#define DOUBLE_QUOTE_CHAR '"' 
+
+#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();
+int free_cmd_buff(cmd_buff_t *);
+int clear_cmd_buff(cmd_buff_t *);
+int build_cmd_buff(char *, cmd_buff_t *);
+void exeCD(char *path);
+void execFork(char *);
+extern void print_dragon();
+
+//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"
+#define CMD_ERR_EXECUTE     "Command not found in PATH\n"
+
+#endif
diff --git a/4-ShellP2/makefile b/4-ShellP2/makefile
new file mode 100644
index 0000000..a079ef4
--- /dev/null
+++ b/4-ShellP2/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
-- 
GitLab