From fa6bbd6012fa879b63957e0fe856117b4a0c12d1 Mon Sep 17 00:00:00 2001
From: Bao Mai <bgm47@drexel.edu>
Date: Fri, 14 Mar 2025 23:37:03 -0400
Subject: [PATCH] Update A6

---
 6-RShell/bats/assignment_tests.sh |  36 ++
 6-RShell/bats/student_tests.sh    | 356 ++++++++++++++
 6-RShell/dragon.c                 |   6 +
 6-RShell/dsh                      | Bin 0 -> 95288 bytes
 6-RShell/dsh_cli.c                | 149 ++++++
 6-RShell/dshlib.c                 | 314 +++++++++++++
 6-RShell/dshlib.h                 | 134 ++++++
 6-RShell/makefile                 |  31 ++
 6-RShell/questions.md             |  19 +
 6-RShell/rsh_cli.c                | 244 ++++++++++
 6-RShell/rsh_server.c             | 754 ++++++++++++++++++++++++++++++
 6-RShell/rshlib.h                 |  78 ++++
 12 files changed, 2121 insertions(+)
 create mode 100644 6-RShell/bats/assignment_tests.sh
 create mode 100644 6-RShell/bats/student_tests.sh
 create mode 100644 6-RShell/dragon.c
 create mode 100755 6-RShell/dsh
 create mode 100644 6-RShell/dsh_cli.c
 create mode 100644 6-RShell/dshlib.c
 create mode 100644 6-RShell/dshlib.h
 create mode 100644 6-RShell/makefile
 create mode 100644 6-RShell/questions.md
 create mode 100644 6-RShell/rsh_cli.c
 create mode 100644 6-RShell/rsh_server.c
 create mode 100644 6-RShell/rshlib.h

diff --git a/6-RShell/bats/assignment_tests.sh b/6-RShell/bats/assignment_tests.sh
new file mode 100644
index 0000000..7a8a30c
--- /dev/null
+++ b/6-RShell/bats/assignment_tests.sh
@@ -0,0 +1,36 @@
+#!/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 "Pipes" {
+    run "./dsh" <<EOF                
+ls | grep dshlib.c
+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="dshlib.clocalmodedsh4>dsh4>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 ]
+}
\ No newline at end of file
diff --git a/6-RShell/bats/student_tests.sh b/6-RShell/bats/student_tests.sh
new file mode 100644
index 0000000..7d3fe91
--- /dev/null
+++ b/6-RShell/bats/student_tests.sh
@@ -0,0 +1,356 @@
+#!/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 ]
+}
+
+@test "Basic command execution" {
+    run ./dsh <<EOF
+echo "hello world"
+exit
+EOF
+
+    echo "Output: $output"
+    [[ "$output" == *"hello world"* ]]
+    [ "$status" -eq 0 ]
+}
+
+@test "Simple pipe" {
+    run ./dsh <<EOF
+echo "hello world" | grep "hello"
+exit
+EOF
+
+    echo "Output: $output"
+    [[ "$output" == *"hello world"* ]]
+    [ "$status" -eq 0 ]
+}
+
+@test "Multiple pipes" {
+    run ./dsh <<EOF
+echo -e "line1\nline2\nline3" | grep "line" | wc -l
+exit
+EOF
+
+    echo "Output: $output"
+    [[ "$output" == *"3"* ]]
+    [ "$status" -eq 0 ]
+}
+
+@test "Built-in cd command" {
+    run ./dsh <<EOF
+cd /tmp
+pwd
+exit
+EOF
+
+    echo "Output: $output"
+    [[ "$output" == *"/tmp"* ]]
+    [ "$status" -eq 0 ]
+}
+
+@test "Command not found" {
+    run ./dsh <<EOF
+nonexistentcommand12345
+exit
+EOF
+
+    echo "Output: $output"
+    [[ "$output" == *"Command not found"* ]]
+    [ "$status" -eq 0 ]  # Shell should continue after command not found
+}
+
+@test "Server startup and shutdown" {
+    # Find an available port
+    TEST_PORT=$(shuf -i 20000-30000 -n 1)
+    
+    # Start server in background with the available port
+    ./dsh -s -p $TEST_PORT > server_output.tmp 2>&1 &
+    SERVER_PID=$!
+    
+    # Give server time to start
+    sleep 3
+    
+    # Verify server is running
+    if ! ps -p $SERVER_PID > /dev/null; then
+        echo "ERROR: Server failed to start"
+        cat server_output.tmp
+        return 1
+    fi
+    
+    echo "Server started with PID $SERVER_PID"
+    
+    # Try graceful shutdown first
+    echo "Attempting graceful shutdown with SIGTERM"
+    kill $SERVER_PID
+    sleep 2
+    
+    # If still running, force kill
+    if ps -p $SERVER_PID > /dev/null; then
+        echo "Server didn't respond to SIGTERM, using SIGKILL"
+        kill -9 $SERVER_PID
+        sleep 2
+    fi
+    
+    # Verify server is stopped
+    if ps -p $SERVER_PID > /dev/null; then
+        echo "ERROR: Server failed to shut down even with SIGKILL"
+        ps -f $SERVER_PID
+        return 1
+    else
+        echo "Server successfully shut down"
+    fi
+    
+    # Clean up
+    rm -f server_output.tmp
+}
+
+@test "Client tests with server running" {
+    # Start server in background
+    TEST_PORT=25123
+    ./dsh -s -p $TEST_PORT &
+    SERVER_PID=$!
+    sleep 2  # Give server time to start
+    
+    # Run client tests
+    echo "exit" | ./dsh -c "localhost:$TEST_PORT"
+    
+    # Verify client connected and exited successfully
+    [ "$?" -eq 0 ]
+    
+    # Clean up server
+    kill $SERVER_PID
+    sleep 1
+}
+
+@test "Client connection to server" {
+    # Start server with a fixed port (easier to debug)
+    TEST_PORT=25884
+    
+    # Kill any process using the port (just to be safe)
+    pkill -f "dsh -s -p $TEST_PORT" || true
+    sleep 1
+    
+    # Start server in background with explicit port
+    ./dsh -s -p $TEST_PORT > server_output.log 2>&1 &
+    SERVER_PID=$!
+    
+    # Give server time to start
+    sleep 3
+    
+    # Debug: Check if server is running and on which port
+    ps -f -p $SERVER_PID
+    netstat -tuln | grep $TEST_PORT || echo "No process listening on port $TEST_PORT"
+    
+    # Now for the client - try different formats to connect
+    
+    # Format 1: Try with space between -c and address
+    echo "echo 'Testing connection'" | ./dsh -c 127.0.0.1:$TEST_PORT > client_output.log 2>&1
+    cat client_output.log
+    
+    # Format 2: Try with address and port separately
+    echo "echo 'Testing connection'" | ./dsh -c 127.0.0.1 -p $TEST_PORT > client_output2.log 2>&1
+    cat client_output2.log
+    
+    # Format 3: Try with full address:port in quotes
+    echo "echo 'Testing connection'" | ./dsh -c "127.0.0.1:$TEST_PORT" > client_output3.log 2>&1
+    cat client_output3.log
+    
+    # Grab one that worked, if any
+    if grep -q "Testing connection" client_output.log; then
+        output=$(cat client_output.log)
+    elif grep -q "Testing connection" client_output2.log; then
+        output=$(cat client_output2.log)
+    elif grep -q "Testing connection" client_output3.log; then
+        output=$(cat client_output3.log)
+    else
+        output="None of the client connection attempts succeeded"
+    fi
+    
+    # Output for debugging
+    echo "Final output: $output"
+    
+    # Clean up
+    kill $SERVER_PID || true
+    sleep 2
+    rm -f server_output.log client_output*.log
+    
+    # Check results (output contains success message)
+    [[ "$output" == *"Testing connection"* ]]
+}
+
+@test "Remote: Simple command" {
+    
+    # Start server in background with a unique port
+    TEST_PORT=12346
+    ./dsh -s -p $TEST_PORT &
+    SERVER_PID=$!
+    
+    # Give server time to start
+    sleep 1
+    
+    # Run client command
+    run ./dsh -c -p $TEST_PORT <<EOF
+echo "hello from remote"
+exit
+EOF
+
+    # Stop the server
+    kill $SERVER_PID
+    
+    echo "Output: $output"
+    [[ "$output" == *"hello from remote"* ]]
+    [ "$status" -eq 0 ]
+}
+
+@test "Remote: Pipes" {
+    
+    # Start server in background with a unique port
+    TEST_PORT=12347
+    ./dsh -s -p $TEST_PORT &
+    SERVER_PID=$!
+    
+    # Give server time to start
+    sleep 1
+    
+    # Run client command with pipes
+    run ./dsh -c -p $TEST_PORT <<EOF
+ls | grep dshlib.c
+exit
+EOF
+
+    # Stop the server
+    kill $SERVER_PID
+    
+    echo "Output: $output"
+    [[ "$output" == *"dshlib.c"* ]]
+    [ "$status" -eq 0 ]
+}
+
+@test "Remote: Built-in command cd" {
+    
+    # Start server in background with a unique port
+    TEST_PORT=12348
+    ./dsh -s -p $TEST_PORT &
+    SERVER_PID=$!
+    
+    # Give server time to start
+    sleep 1
+    
+    # Run cd command and then check pwd
+    run ./dsh -c -p $TEST_PORT <<EOF
+cd /tmp
+pwd
+exit
+EOF
+
+    # Stop the server
+    kill $SERVER_PID
+    
+    echo "Output: $output"
+    [[ "$output" == *"/tmp"* ]]
+    [ "$status" -eq 0 ]
+}
+
+@test "Remote: stop-server command" {
+    # Start server in background with a unique port
+    TEST_PORT=12349
+    ./dsh -s -p $TEST_PORT &
+    SERVER_PID=$!
+    
+    # Give server time to start
+    sleep 2
+    
+    # Verify server is running before sending command
+    ps -p $SERVER_PID > /dev/null || {
+        echo "Server failed to start properly"
+        return 1
+    }
+    
+    # Run stop-server command
+    echo "stop-server" | ./dsh -c localhost -p $TEST_PORT
+    
+    # Give more time for server to shut down
+    sleep 3
+    
+    # Check if server process still exists
+    if ps -p $SERVER_PID > /dev/null; then
+        echo "ERROR: Server process $SERVER_PID still running!"
+        kill -9 $SERVER_PID  # Force kill it to clean up
+        return 1
+    else
+        echo "Server successfully terminated"
+    fi
+}
+
+# Network error handling tests
+
+@test "Connection to non-existent server" {
+    # Try to connect to a port where no server is running
+    OUTPUT=$(./dsh -c localhost -p 65432 2>&1 || true)
+    STATUS_CODE=$?
+    
+    echo "Output: $OUTPUT"
+    echo "Status code: $STATUS_CODE"
+    
+    # Check for connection failure message
+    [[ "$OUTPUT" == *"connection failed"* ]]
+}
+
+@test "Shell starts and accepts input" {
+    run "./dsh" <<EOF
+echo "Hello, dsh!"
+EOF
+
+    [ "$status" -eq 0 ]
+    [[ "$output" =~ "Hello, dsh!" ]]
+}
+
+@test "exit command" {
+    run "./dsh" <<EOF
+exit
+EOF
+
+    [ "$status" -eq 0 ]
+}
+
+@test "Pipe with multiple commands" {
+    run ./dsh <<EOF
+printf "line1\nline2\nline3\n" | grep line | wc -l
+EOF
+
+    echo "Command output: $output"
+    [ "$status" -eq 0 ]
+    [[ "$output" == *"3"* ]]
+}
+
+@test "Multiple pipes in command" {
+    run ./dsh <<EOF
+echo "one two three four" | tr ' ' '\n' | sort | grep o
+EOF
+
+    [ "$status" -eq 0 ]
+    [[ "$output" == *"four"* ]]
+    [[ "$output" == *"one"* ]]
+    [[ "$output" != *"three"* ]]
+}
+
+@test "Command with pipe followed by regular command" {
+    run ./dsh <<EOF
+echo hello | grep hello
+echo another command
+EOF
+
+    [ "$status" -eq 0 ]
+    [[ "$output" == *"hello"* ]]
+    [[ "$output" == *"another command"* ]]
+}
\ No newline at end of file
diff --git a/6-RShell/dragon.c b/6-RShell/dragon.c
new file mode 100644
index 0000000..581408b
--- /dev/null
+++ b/6-RShell/dragon.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+#include "dshlib.h"
+// EXTRA CREDIT - print the drexel dragon from the readme.md
+extern void print_dragon(){
+  printf("%s\n", DRAGON_ASCII);
+}
diff --git a/6-RShell/dsh b/6-RShell/dsh
new file mode 100755
index 0000000000000000000000000000000000000000..cad6725181e111cc639ac33783555e82d1b897c1
GIT binary patch
literal 95288
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%0D6(=YDk_2u<FEx4&{9SqXG-X^
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

literal 0
HcmV?d00001

diff --git a/6-RShell/dsh_cli.c b/6-RShell/dsh_cli.c
new file mode 100644
index 0000000..68fab16
--- /dev/null
+++ b/6-RShell/dsh_cli.c
@@ -0,0 +1,149 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <argp.h>
+#include <getopt.h>
+
+#include "dshlib.h"
+#include "rshlib.h"
+
+
+/*
+ * Used to pass startup parameters back to main
+ */
+#define MODE_LCLI   0       //Local client
+#define MODE_SCLI   1       //Socket client
+#define MODE_SSVR   2       //Socket server
+
+typedef struct cmd_args{
+  int   mode;
+  char  ip[16];   //e.g., 192.168.100.101\0
+  int   port;
+  int   threaded_server;
+}cmd_args_t;
+
+
+
+//You dont really need to understand this but the C runtime library provides
+//an getopt() service to simplify handling command line arguments.  This
+//code will help setup dsh to handle triggering client or server mode along
+//with passing optional connection parameters. 
+
+void print_usage(const char *progname) {
+  printf("Usage: %s [-c | -s] [-i IP] [-p PORT] [-x] [-h]\n", progname);
+  printf("  Default is to run %s in local mode\n", progname);
+  printf("  -c            Run as client\n");
+  printf("  -s            Run as server\n");
+  printf("  -i IP         Set IP/Interface address (only valid with -c or -s)\n");
+  printf("  -p PORT       Set port number (only valid with -c or -s)\n");
+  printf("  -x            Enable threaded mode (only valid with -s)\n");
+  printf("  -h            Show this help message\n");
+  exit(0);
+}
+
+void parse_args(int argc, char *argv[], cmd_args_t *cargs) {
+  int opt;
+  memset(cargs, 0, sizeof(cmd_args_t));
+
+  //defaults
+  cargs->mode = MODE_LCLI;
+  cargs->port = RDSH_DEF_PORT;
+
+  while ((opt = getopt(argc, argv, "csi:p:xh")) != -1) {
+      switch (opt) {
+          case 'c':
+              if (cargs->mode != MODE_LCLI) {
+                  fprintf(stderr, "Error: Cannot use both -c and -s\n");
+                  exit(EXIT_FAILURE);
+              }
+              cargs->mode = MODE_SCLI;
+              strncpy(cargs->ip, RDSH_DEF_CLI_CONNECT, sizeof(cargs->ip) - 1);
+              break;
+          case 's':
+              if (cargs->mode != MODE_LCLI) {
+                  fprintf(stderr, "Error: Cannot use both -c and -s\n");
+                  exit(EXIT_FAILURE);
+              }
+              cargs->mode = MODE_SSVR;
+              strncpy(cargs->ip, RDSH_DEF_SVR_INTFACE, sizeof(cargs->ip) - 1);
+              break;
+          case 'i':
+              if (cargs->mode == MODE_LCLI) {
+                  fprintf(stderr, "Error: -i can only be used with -c or -s\n");
+                  exit(EXIT_FAILURE);
+              }
+              strncpy(cargs->ip, optarg, sizeof(cargs->ip) - 1);
+              cargs->ip[sizeof(cargs->ip) - 1] = '\0';  // Ensure null termination
+              break;
+          case 'p':
+              if (cargs->mode == MODE_LCLI) {
+                  fprintf(stderr, "Error: -p can only be used with -c or -s\n");
+                  exit(EXIT_FAILURE);
+              }
+              cargs->port = atoi(optarg);
+              if (cargs->port <= 0) {
+                  fprintf(stderr, "Error: Invalid port number\n");
+                  exit(EXIT_FAILURE);
+              }
+              break;
+          case 'x':
+              if (cargs->mode != MODE_SSVR) {
+                  fprintf(stderr, "Error: -x can only be used with -s\n");
+                  exit(EXIT_FAILURE);
+              }
+              cargs->threaded_server = 1;
+              break;
+          case 'h':
+              print_usage(argv[0]);
+              break;
+          default:
+              print_usage(argv[0]);
+      }
+  }
+
+  if (cargs->threaded_server && cargs->mode != MODE_SSVR) {
+      fprintf(stderr, "Error: -x can only be used with -s\n");
+      exit(EXIT_FAILURE);
+  }
+}
+
+
+
+/* DO NOT EDIT
+ * main() logic fully implemented to:
+ *    1. run locally (no parameters)
+ *    2. start the server with the -s option
+ *    3. start the client with the -c option
+*/
+int main(int argc, char *argv[]){
+  cmd_args_t cargs;
+  int rc;
+
+  memset(&cargs, 0, sizeof(cmd_args_t));
+  parse_args(argc, argv, &cargs);
+
+  switch(cargs.mode){
+    case MODE_LCLI:
+      printf("local mode\n");
+      rc = exec_local_cmd_loop();
+      break;
+    case MODE_SCLI:
+      printf("socket client mode:  addr:%s:%d\n", cargs.ip, cargs.port);
+      rc = exec_remote_cmd_loop(cargs.ip, cargs.port);
+      break;
+    case MODE_SSVR:
+      printf("socket server mode:  addr:%s:%d\n", cargs.ip, cargs.port);
+      if (cargs.threaded_server){
+        printf("-> Multi-Threaded Mode\n");
+      } else {
+        printf("-> Single-Threaded Mode\n");
+      }
+      rc = start_server(cargs.ip, cargs.port, cargs.threaded_server);
+      break;
+    default:
+      printf("error unknown mode\n");
+      exit(EXIT_FAILURE);
+  }
+
+  printf("cmd loop returned %d\n", rc);
+}
\ No newline at end of file
diff --git a/6-RShell/dshlib.c b/6-RShell/dshlib.c
new file mode 100644
index 0000000..2e39f63
--- /dev/null
+++ b/6-RShell/dshlib.c
@@ -0,0 +1,314 @@
+#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()
+ */
+
+int last_rc = 0;
+
+int execute_pipeline(command_list_t *clist) {
+    if (!clist->num) return OK;
+    
+    if (clist->num == 1) {
+        char *cmd = clist->commands[0].argv[0];
+        if (clist->commands[0].argc > 0) {
+            if (!strcmp(cmd, EXIT_CMD)) return OK_EXIT;
+            if (!strcmp(cmd, "cd")) {
+                handle_cd(clist->commands[0].argc > 1 ? clist->commands[0].argv[1] : NULL);
+                return OK;
+            }
+            if (!strcmp(cmd, "rc")) {
+                printf("%d\n", last_rc);
+                return OK;
+            }
+        }
+    }
+    
+    pid_t *child_pids = malloc(clist->num * sizeof(pid_t));
+    if (!child_pids) {
+        fprintf(stderr, "Memory allocation failed\n");
+        return ERR_MEMORY;
+    }
+    
+    int pipes[CMD_MAX - 1][2];
+    for (int i = 0; i < clist->num - 1; i++) {
+        if (pipe(pipes[i]) == -1) {
+            perror("pipe");
+            while (i--) close(pipes[i][0]), close(pipes[i][1]);
+            free(child_pids);
+            return ERR_EXEC_CMD;
+        }
+    }
+    
+    for (int i = 0; i < clist->num; i++) {
+        pid_t pid = fork();
+        if (pid < 0) {
+            perror("fork");
+            for (int j = 0; j < clist->num - 1; j++) close(pipes[j][0]), close(pipes[j][1]);
+            free(child_pids);
+            return ERR_EXEC_CMD;
+        }
+        
+        if (!pid) {
+            if (i > 0) dup2(pipes[i - 1][0], STDIN_FILENO);
+            if (i < clist->num - 1) dup2(pipes[i][1], STDOUT_FILENO);
+            for (int j = 0; j < clist->num - 1; j++) close(pipes[j][0]), close(pipes[j][1]);
+            execvp(clist->commands[i].argv[0], clist->commands[i].argv);
+            perror("execvp");
+            exit(errno);
+        }
+        child_pids[i] = pid;
+    }
+    
+    for (int i = 0; i < clist->num - 1; i++) close(pipes[i][0]), close(pipes[i][1]);
+    
+    for (int i = 0, status; i < clist->num; i++) {
+        waitpid(child_pids[i], &status, 0);
+        if (i == clist->num - 1) last_rc = WEXITSTATUS(status);
+    }
+    
+    free(child_pids);
+    return OK;
+}
+
+int build_cmd_list(char *cmd_line, command_list_t *clist) {
+    int ret = OK;
+    char *cmd_copy = strdup(cmd_line);
+    if (!cmd_copy) {
+        fprintf(stderr, "Memory allocation failed\n");
+        return ERR_MEMORY;
+    }
+
+    clist->num = 0;
+    char *token = NULL, *context = NULL;
+    token = strtok_r(cmd_copy, PIPE_STRING, &context);
+
+    while (token != NULL) {
+        if (clist->num >= CMD_MAX) {
+            ret = ERR_TOO_MANY_COMMANDS;
+            fprintf(stderr, CMD_ERR_PIPE_LIMIT, CMD_MAX);
+            break;
+        }
+
+        if (alloc_cmd_buff(&clist->commands[clist->num]) != OK) {
+            ret = ERR_MEMORY;
+            break;
+        }
+
+        /* Copy token into the command buffer */
+        strncpy(clist->commands[clist->num]._cmd_buffer, token, SH_CMD_MAX);
+        clist->commands[clist->num]._cmd_buffer[SH_CMD_MAX] = '\0';
+
+        if (build_cmd_buff(clist->commands[clist->num]._cmd_buffer,
+                           &clist->commands[clist->num]) != OK) {
+            free_cmd_buff(&clist->commands[clist->num]);
+            ret = ERR_CMD_ARGS_BAD;
+            break;
+        }
+
+        clist->num++;
+        token = strtok_r(NULL, PIPE_STRING, &context);
+    }
+
+    free(cmd_copy);
+
+    if (ret != OK) {
+        for (int i = 0; i < clist->num; i++) {
+            free_cmd_buff(&clist->commands[i]);
+        }
+        return ret;
+    }
+
+    if (clist->num == 0) {
+        fprintf(stderr, CMD_WARN_NO_CMD);
+        return WARN_NO_CMDS;
+    }
+
+    return OK;
+}
+
+
+int free_cmd_list(command_list_t *clist) {
+    if (clist == NULL) {
+        return ERR_MEMORY;
+    }
+    
+    for (int i = 0; i < clist->num; i++) {
+        free_cmd_buff(&clist->commands[i]);
+    }
+    
+    clist->num = 0;
+    return OK;
+}
+
+int exec_local_cmd_loop() {
+    cmd_buff_t cmd;
+    command_list_t cmd_list;
+    int rc;
+
+    if ((rc = alloc_cmd_buff(&cmd)) != OK) {
+        fprintf(stderr, "Memory allocation failed\n");
+        return ERR_MEMORY;
+    }
+
+    for (;;) {
+        printf("%s", SH_PROMPT);
+
+        if (!fgets(cmd._cmd_buffer, SH_CMD_MAX, stdin)) {
+            putchar('\n');
+            break;
+        }
+
+        cmd._cmd_buffer[strcspn(cmd._cmd_buffer, "\n")] = '\0';
+        char *trimmed = cmd._cmd_buffer;
+        while (*trimmed && isspace((unsigned char)*trimmed)) trimmed++;
+        
+        if (!*trimmed) {
+            puts(CMD_WARN_NO_CMD);
+            continue;
+        }
+
+        if (!strcmp(trimmed, EXIT_CMD)) break;
+        if (!strcmp(trimmed, "dragon")) {
+            print_dragon();
+            continue;
+        }
+
+        if ((rc = build_cmd_list(trimmed, &cmd_list)) != OK) {
+            if (rc != WARN_NO_CMDS) fprintf(stderr, "Error parsing command: %d\n", rc);
+            continue;
+        }
+
+        rc = execute_pipeline(&cmd_list);
+        free_cmd_list(&cmd_list);
+        if (rc == OK_EXIT) break;
+    }
+    
+    free_cmd_buff(&cmd);
+    return OK;
+}
+
+int handle_cd(char *path) {
+    if (path == NULL)
+        return 0;
+    if (chdir(path) != 0) {
+        perror("cd");
+        return -1;
+    }
+    return 0;
+}
+
+int alloc_cmd_buff(cmd_buff_t *cmd) {
+    if (cmd == NULL) return ERR_MEMORY;
+    cmd->_cmd_buffer = malloc(SH_CMD_MAX + 1); // +1 for the null terminator
+    if (cmd->_cmd_buffer == NULL) return ERR_MEMORY;
+    return OK;
+}
+
+int free_cmd_buff(cmd_buff_t *cmd) {
+    if (cmd == NULL) return ERR_MEMORY;
+    free(cmd->_cmd_buffer);
+    cmd->_cmd_buffer = NULL;
+    return OK;
+}
+
+int clear_cmd_buff(cmd_buff_t *cmd) {
+    if (cmd == NULL) return ERR_MEMORY;
+    cmd->argc = 0;
+    for (int i = 0; i < CMD_ARGV_MAX; i++) {
+        cmd->argv[i] = NULL;
+    }
+    return OK;
+}
+
+int build_cmd_buff(char *cmd_line, cmd_buff_t *cmd) {
+    if (cmd_line == NULL || cmd == NULL)
+        return ERR_MEMORY;
+    clear_cmd_buff(cmd);
+    int tokenCount = 0;
+    char *ptr = cmd_line;
+    
+    while (*ptr) {
+        while (*ptr && isspace((unsigned char)*ptr))
+            ptr++;
+        if (!*ptr)
+            break;
+        
+        char *token = ptr;
+        if (*ptr == '"' || *ptr == '\'') {
+            char quote = *ptr;
+            ptr++;
+            token = ptr;
+            while (*ptr && *ptr != quote)
+                ptr++;
+            if (*ptr == quote) {
+                *ptr = '\0';
+                ptr++;
+            }
+        } else {
+            while (*ptr && !isspace((unsigned char)*ptr))
+                ptr++;
+            if (*ptr) {
+                *ptr = '\0';
+                ptr++;
+            }
+        }
+        
+        cmd->argv[tokenCount++] = token;
+        if (tokenCount >= CMD_ARGV_MAX - 1)
+            break;
+    }
+    
+    cmd->argv[tokenCount] = NULL;
+    cmd->argc = tokenCount;
+    return tokenCount == 0 ? WARN_NO_CMDS : OK;
+}
diff --git a/6-RShell/dshlib.h b/6-RShell/dshlib.h
new file mode 100644
index 0000000..e859a98
--- /dev/null
+++ b/6-RShell/dshlib.h
@@ -0,0 +1,134 @@
+#ifndef __DSHLIB_H__
+    #define __DSHLIB_H__
+
+
+//Constants for command structure sizes
+#define DRAGON_ASCII "\
+                                                                        @%%%%                       \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"
+
+
+#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 command
+{
+    char exe[EXE_MAX];
+    char args[ARG_MAX];
+} command_t;
+
+#include <stdbool.h>
+
+typedef struct cmd_buff
+{
+    int  argc;
+    char *argv[CMD_ARGV_MAX];
+    char *_cmd_buffer;
+    char *input_file;  // extra credit, stores input redirection file (for `<`)
+    char *output_file; // extra credit, stores output redirection file (for `>`)
+    bool append_mode; // extra credit, sets append mode fomr output_file
+} cmd_buff_t;
+
+typedef struct command_list{
+    int num;
+    cmd_buff_t commands[CMD_MAX];
+}command_list_t;
+
+//Special character #defines
+#define SPACE_CHAR  ' '
+#define PIPE_CHAR   '|'
+#define PIPE_STRING "|"
+
+#define SH_PROMPT       "dsh4> "
+#define EXIT_CMD        "exit"
+#define RC_SC           99
+#define EXIT_SC         100
+
+//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);
+int close_cmd_buff(cmd_buff_t *cmd_buff);
+int build_cmd_list(char *cmd_line, command_list_t *clist);
+int free_cmd_list(command_list_t *cmd_lst);
+int handle_cd(char *path);
+void print_dragon();
+
+//built in command stuff
+typedef enum {
+    BI_CMD_EXIT,
+    BI_CMD_DRAGON,
+    BI_CMD_CD,
+    BI_CMD_RC,              //extra credit command
+    BI_CMD_STOP_SVR,        //new command "stop-server"
+    BI_NOT_BI,
+    BI_EXECUTED,
+} 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);
+int execute_pipeline(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"
+#define BI_NOT_IMPLEMENTED "not implemented"
+
+#endif
\ No newline at end of file
diff --git a/6-RShell/makefile b/6-RShell/makefile
new file mode 100644
index 0000000..b14b072
--- /dev/null
+++ b/6-RShell/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/6-RShell/questions.md b/6-RShell/questions.md
new file mode 100644
index 0000000..63cd9a7
--- /dev/null
+++ b/6-RShell/questions.md
@@ -0,0 +1,19 @@
+1. How does the remote client determine when a command's output is fully received from the server, and what techniques can be used to handle partial reads or ensure complete message transmission?
+
+The remote client determines when command output is complete by detecting the EOF character (RDSH_EOF_CHAR) sent by the server. Since TCP may split messages into multiple packets, the client must use a loop to continuously receive data until the EOF is found, buffer partial reads while appending new data, and check each received chunk for the EOF marker. The command is only considered complete once the EOF is received, ensuring reliable message boundaries even if TCP fragments the data across multiple network packets.
+
+2. This week's lecture on TCP explains that it is a reliable stream protocol rather than a message-oriented one. Since TCP does not preserve message boundaries, how should a networked shell protocol define and detect the beginning and end of a command sent over a TCP connection? What challenges arise if this is not handled correctly?
+
+A networked shell protocol should use null termination ('\0') for commands delivered from the client to the server, a specific EOF character for server responses back to the client, and message length headers as needed. Failure to manage these aspects properly can result in a variety of issues, including commands being merged or split incorrectly, the client hanging while waiting for additional data, buffer overflows due to incomplete message boundaries, and difficulties synchronising requests with their corresponding responses.
+
+3. Describe the general differences between stateful and stateless protocols.
+
+Stateful and stateless protocols vary in the way session information is handled between client and server requests. Stateful protocols retain session information across multiple requests such that the server maintains the client's state, and each request depends on past ones. This approach, used in protocols like FTP and TCP, offers continuity at the expense of additional resources consumed to maintain session information. On the other hand, stateless protocols do not keep any session data, treating each request individually and sending all the data required for processing. This simplifies the design of servers, improves scalability, and reduces memory usage, as in HTTP and UDP. Stateful protocols are optimally used where there is ongoing communication required, such as in online gaming or streaming, but stateless protocols are appropriate for large-scale web services and APIs.
+
+4. Our lecture this week stated that UDP is "unreliable". If that is the case, why would we ever use it?
+
+UDP is great when speed is greater than reliability. It is commonly used in video streaming and online gaming, where losing a few frames is better than latency, and DNS lookups, where cheap and effective retries are fast. In addition, some light network protocols handle reliability themselves, and therefore UDP is a suitable choice. It is also suitable for IoT devices that do not require much overhead. Since UDP forsakes handshaking and acknowledgment, it is significantly faster than TCP where there is no such need for total reliability.
+
+5. What interface/abstraction is provided by the operating system to enable applications to use network communications?
+
+The OS provides network sockets as an abstraction level to enable applications to utilize network communications. A socket is an abstraction level that enables applications to communicate data over a network with protocol aids like TCP and UDP. The OS takes care of the low-level networking details, such as connection establishment, data transfer, and errors, and allows applications to access sockets by means of system calls or APIs. Some of the popular socket interfaces are the Berkeley Sockets API (ported in Unix/Linux and Windows) and Winsock (proprietary of Windows). These interfaces enable programs to communicate on networks without needing to directly handle low-level network operations.
\ No newline at end of file
diff --git a/6-RShell/rsh_cli.c b/6-RShell/rsh_cli.c
new file mode 100644
index 0000000..e3b29e7
--- /dev/null
+++ b/6-RShell/rsh_cli.c
@@ -0,0 +1,244 @@
+
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/un.h>
+#include <fcntl.h>
+
+#include "dshlib.h"
+#include "rshlib.h"
+
+
+
+
+/*
+ * exec_remote_cmd_loop(server_ip, port)
+ *      server_ip:  a string in ip address format, indicating the servers IP
+ *                  address.  Note 127.0.0.1 is the default meaning the server
+ *                  is running on the same machine as the client
+ *              
+ *      port:   The port the server will use.  Note the constant 
+ *              RDSH_DEF_PORT which is 1234 in rshlib.h.  If you are using
+ *              tux you may need to change this to your own default, or even
+ *              better use the command line override -c implemented in dsh_cli.c
+ *              For example ./dsh -c 10.50.241.18:5678 where 5678 is the new port
+ *              number and the server address is 10.50.241.18    
+ * 
+ *      This function basically implements the network version of 
+ *      exec_local_cmd_loop() from the last assignemnt.  It will:
+ *  
+ *          1. Allocate buffers for sending and receiving data over the 
+ *             network
+ *          2. Create a network connection to the server, getting an active
+ *             socket by calling the start_client(server_ip, port) function.
+ *          2. Go into an infinite while(1) loop prompting the user for
+ *             input commands. 
+ * 
+ *             a. Accept a command from the user via fgets()
+ *             b. Send that command to the server using send() - it should
+ *                be a null terminated string
+ *             c. Go into a loop and receive client requests.  Note each
+ *                receive might not be a C string so you need to print it
+ *                out using:
+ *                     printf("%.*s", (int)bytes_received, rsp_buff);
+ *                this version of printf() uses the "%.*s" flag that indicates
+ *                that the rsp_buff might be a null terminated string, or
+ *                it might not be, if its not, print exactly bytes_received
+ *                bytes. 
+ *             d. In the recv() loop described above. Each time you receive
+ *                data from the server, see if the last byte received is the
+ *                EOF character. This indicates the server is done and you can
+ *                send another command by going to the top of the loop.  The
+ *                best way to do this is as follows assuming you are receiving
+ *                data into a buffer called recv_buff, and you received
+ *                recv_bytes in the call to recv:
+ * 
+ *                  recv_bytes = recv(sock, recv_buff, recv_buff_sz, 0)
+ *                  
+ *                if recv_bytes:
+ *                  <negative_number>: communication error
+ *                    0:    Didn't receive anything, likely server down
+ *                  > 0:    Got some data. Check if the last byte is EOF
+ *                          is_eof = (recv_buff[recv_bytes-1] == RDSH_EOF_CHAR) ? 1 : 0;
+ *                    if is_eof is true, this is the last part of the transmission
+ *                    from the server and you can break out of the recv() loop. 
+ * 
+ *   returns:
+ *          OK:      The client executed all of its commands and is exiting
+ *                   either by the `exit` command that terminates the client
+ *                   or the `stop-server` command that terminates both the
+ *                   client and the server. 
+ *          ERR_MEMORY:             If this function cannot allocate memory via
+ *                                  malloc for the send and receive buffers
+ *          ERR_RDSH_CLIENT:        If the client cannot connect to the server. 
+ *                                  AKA the call to start_client() fails.
+ *          ERR_RDSH_COMMUNICATION: If there is a communication error, AKA
+ *                                  any failures from send() or recv().
+ * 
+ *   NOTE:  Since there are several exit points and each exit point must
+ *          call free() on the buffers allocated, close the socket, and
+ *          return an appropriate error code.  Its suggested you use the
+ *          helper function client_cleanup() for these purposes.  For example:
+ * 
+ *   return client_cleanup(cli_socket, request_buff, resp_buff, ERR_RDSH_COMMUNICATION);
+ *   return client_cleanup(cli_socket, request_buff, resp_buff, OK);
+ *
+ *   The above will return ERR_RDSH_COMMUNICATION and OK respectively to the main()
+ *   function after cleaning things up.  See the documentation for client_cleanup()
+ *      
+ */
+int exec_remote_cmd_loop(char *address, int port)
+{
+    char *cmd_buff;
+    char *rsp_buff;
+    int cli_socket;
+    ssize_t io_size;
+    int is_eof;
+
+    // TODO set up cmd and response buffs
+    cmd_buff = (char *)malloc(RDSH_COMM_BUFF_SZ);
+    rsp_buff = (char *)malloc(RDSH_COMM_BUFF_SZ);
+    
+    if (cmd_buff == NULL || rsp_buff == NULL) {
+        perror("memory allocation failed");
+        return client_cleanup(-1, cmd_buff, rsp_buff, ERR_MEMORY);
+    }
+
+    cli_socket = start_client(address,port);
+    if (cli_socket < 0){
+        perror("start client");
+        return client_cleanup(cli_socket, cmd_buff, rsp_buff, ERR_RDSH_CLIENT);
+    }
+    while (1) 
+    {
+        printf(SH_PROMPT);
+        fflush(stdout);
+        
+        if (fgets(cmd_buff, RDSH_COMM_BUFF_SZ, stdin) == NULL) {
+            break;
+        }
+        cmd_buff[strcspn(cmd_buff, "\n")] = '\0';
+        
+        if (*cmd_buff == '\0') {
+            continue;
+        }
+        io_size = send(cli_socket, cmd_buff, strlen(cmd_buff) + 1, 0);
+        if (io_size != (ssize_t)(strlen(cmd_buff) + 1)) {
+            perror("send failed");
+            return client_cleanup(cli_socket, cmd_buff, rsp_buff, ERR_RDSH_COMMUNICATION);
+        }
+        while (1) {
+            memset(rsp_buff, 0, RDSH_COMM_BUFF_SZ);
+            io_size = recv(cli_socket, rsp_buff, RDSH_COMM_BUFF_SZ - 1, 0);
+            
+            if (io_size < 0) {
+                perror("recv failed");
+                return client_cleanup(cli_socket, cmd_buff, rsp_buff, ERR_RDSH_COMMUNICATION);
+            }
+            if (io_size == 0) {
+                printf("Server disconnected\n");
+                return client_cleanup(cli_socket, cmd_buff, rsp_buff, OK);
+            }
+            
+            if (rsp_buff[io_size - 1] == RDSH_EOF_CHAR) {
+                printf("%.*s", (int)io_size - 1, rsp_buff);
+                break;
+            }
+            printf("%.*s", (int)io_size, rsp_buff);
+        }
+        if (strcmp(cmd_buff, EXIT_CMD) == 0 || strcmp(cmd_buff, "stop-server") == 0) {
+            break;
+        }
+    }
+
+return client_cleanup(cli_socket, cmd_buff, rsp_buff, OK);
+
+}
+
+/*
+ * start_client(server_ip, port)
+ *      server_ip:  a string in ip address format, indicating the servers IP
+ *                  address.  Note 127.0.0.1 is the default meaning the server
+ *                  is running on the same machine as the client
+ *              
+ *      port:   The port the server will use.  Note the constant 
+ *              RDSH_DEF_PORT which is 1234 in rshlib.h.  If you are using
+ *              tux you may need to change this to your own default, or even
+ *              better use the command line override -c implemented in dsh_cli.c
+ *              For example ./dsh -c 10.50.241.18:5678 where 5678 is the new port
+ *              number and the server address is 10.50.241.18    
+ * 
+ *      This function basically runs the client by: 
+ *          1. Creating the client socket via socket()
+ *          2. Calling connect()
+ *          3. Returning the client socket after connecting to the server
+ * 
+ *   returns:
+ *          client_socket:      The file descriptor fd of the client socket
+ *          ERR_RDSH_CLIENT:    If socket() or connect() fail
+ * 
+ */
+int start_client(char *server_ip, int port){
+    struct sockaddr_in addr;
+    int cli_socket;
+    int ret;
+
+    cli_socket = socket(AF_INET, SOCK_STREAM, 0);
+    if (cli_socket == -1) {
+        perror("socket");
+        return ERR_RDSH_CLIENT;
+    }
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr = inet_addr(server_ip);
+    addr.sin_port = htons(port);
+    ret = connect(cli_socket, (struct sockaddr *)&addr, sizeof(addr));
+    if (ret == -1) {
+        perror("connect");
+        close(cli_socket);
+        return ERR_RDSH_CLIENT;
+    }
+    return cli_socket;
+}
+
+
+/*
+ * client_cleanup(int cli_socket, char *cmd_buff, char *rsp_buff, int rc)
+ *      cli_socket:   The client socket
+ *      cmd_buff:     The buffer that will hold commands to send to server
+ *      rsp_buff:     The buffer that will hld server responses
+ * 
+ *   This function does the following: 
+ *      1. If cli_socket > 0 it calls close(cli_socket) to close the socket
+ *      2. It calls free() on cmd_buff and rsp_buff
+ *      3. It returns the value passed as rc
+ *  
+ *   Note this function is intended to be helper to manage exit conditions
+ *   from the exec_remote_cmd_loop() function given there are several
+ *   cleanup steps.  We provide it to you fully implemented as a helper.
+ *   You do not have to use it if you want to develop an alternative
+ *   strategy for cleaning things up in your exec_remote_cmd_loop()
+ *   implementation. 
+ * 
+ *   returns:
+ *          rc:   This function just returns the value passed as the 
+ *                rc parameter back to the caller.  This way the caller
+ *                can just write return client_cleanup(...)
+ *      
+ */
+int client_cleanup(int cli_socket, char *cmd_buff, char *rsp_buff, int rc){
+    //If a valid socket number close it.
+    if(cli_socket > 0){
+        close(cli_socket);
+    }
+
+    //Free up the buffers 
+    free(cmd_buff);
+    free(rsp_buff);
+
+    //Echo the return value that was passed as a parameter
+    return rc;
+}
\ No newline at end of file
diff --git a/6-RShell/rsh_server.c b/6-RShell/rsh_server.c
new file mode 100644
index 0000000..db50611
--- /dev/null
+++ b/6-RShell/rsh_server.c
@@ -0,0 +1,754 @@
+
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/un.h>
+#include <fcntl.h>
+#include <errno.h>
+
+//INCLUDES for extra credit
+#include <signal.h>
+//#include <pthread.h>
+//-------------------------
+
+#include "dshlib.h"
+#include "rshlib.h"
+
+int server_socket = -1;
+void handle_signal(int sig) {
+    printf("Received signal %d, shutting down server...\n", sig);
+    if (server_socket != -1) {
+        printf("Closing server socket %d\n", server_socket);
+        close(server_socket);
+    }
+    printf("Server shutdown complete\n");
+    fflush(stdout);
+    exit(0);  // Exit cleanly
+}
+
+void initialize_server(int port) {    
+    // Setup signal handling
+    signal(SIGINT, handle_signal);   // Handle Ctrl+C
+    signal(SIGTERM, handle_signal);  // Handle kill command
+    
+    printf("Signal handlers registered for server\n");
+    fflush(stdout);
+}
+/*
+ * start_server(ifaces, port, is_threaded)
+ *      ifaces:  a string in ip address format, indicating the interface
+ *              where the server will bind.  In almost all cases it will
+ *              be the default "0.0.0.0" which binds to all interfaces.
+ *              note the constant RDSH_DEF_SVR_INTFACE in rshlib.h
+ * 
+ *      port:   The port the server will use.  Note the constant 
+ *              RDSH_DEF_PORT which is 1234 in rshlib.h.  If you are using
+ *              tux you may need to change this to your own default, or even
+ *              better use the command line override -s implemented in dsh_cli.c
+ *              For example ./dsh -s 0.0.0.0:5678 where 5678 is the new port  
+ * 
+ *      is_threded:  Used for extra credit to indicate the server should implement
+ *                   per thread connections for clients  
+ * 
+ *      This function basically runs the server by: 
+ *          1. Booting up the server
+ *          2. Processing client requests until the client requests the
+ *             server to stop by running the `stop-server` command
+ *          3. Stopping the server. 
+ * 
+ *      This function is fully implemented for you and should not require
+ *      any changes for basic functionality.  
+ * 
+ *      IF YOU IMPLEMENT THE MULTI-THREADED SERVER FOR EXTRA CREDIT YOU NEED
+ *      TO DO SOMETHING WITH THE is_threaded ARGUMENT HOWEVER.  
+ */
+int start_server(char *ifaces, int port, int is_threaded) {
+    initialize_server(port);
+    
+    printf("START_SERVER PID: %d\n", getpid());
+    fflush(stdout);
+
+    server_socket = boot_server(ifaces, port);
+    if (server_socket < 0) {
+        printf("Server boot failed with error: %d\n", server_socket);
+        return server_socket;
+    }
+
+    printf("Server successfully booted on socket %d, PID: %d\n", server_socket, getpid());
+    fflush(stdout);
+    
+    int rc = process_cli_requests(server_socket);
+
+    printf("Server shutting down, rc: %d\n", rc);
+    stop_server(server_socket);
+    
+    server_socket = -1;
+    return rc;
+}
+
+
+/*
+ * stop_server(svr_socket)
+ *      svr_socket: The socket that was created in the boot_server()
+ *                  function. 
+ * 
+ *      This function simply returns the value of close() when closing
+ *      the socket.  
+ */
+int stop_server(int svr_socket){
+    return close(svr_socket);
+}
+
+/*
+ * boot_server(ifaces, port)
+ *      ifaces & port:  see start_server for description.  They are passed
+ *                      as is to this function.   
+ * 
+ *      This function "boots" the rsh server.  It is responsible for all
+ *      socket operations prior to accepting client connections.  Specifically: 
+ * 
+ *      1. Create the server socket using the socket() function. 
+ *      2. Calling bind to "bind" the server to the interface and port
+ *      3. Calling listen to get the server ready to listen for connections.
+ * 
+ *      after creating the socket and prior to calling bind you might want to 
+ *      include the following code:
+ * 
+ *      int enable=1;
+ *      setsockopt(svr_socket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
+ * 
+ *      when doing development you often run into issues where you hold onto
+ *      the port and then need to wait for linux to detect this issue and free
+ *      the port up.  The code above tells linux to force allowing this process
+ *      to use the specified port making your life a lot easier.
+ * 
+ *  Returns:
+ * 
+ *      server_socket:  Sockets are just file descriptors, if this function is
+ *                      successful, it returns the server socket descriptor, 
+ *                      which is just an integer.
+ * 
+ *      ERR_RDSH_COMMUNICATION:  This error code is returned if the socket(),
+ *                               bind(), or listen() call fails. 
+ * 
+ */
+int boot_server(char *ifaces, int port){
+    int svr_socket;
+    int ret;
+    
+    struct sockaddr_in addr;
+
+    printf("Booting server on %s:%d\n", ifaces, port);
+
+    svr_socket = socket(AF_INET, SOCK_STREAM, 0);
+    if (svr_socket < 0) {
+        perror("socket creation failed");
+        return ERR_RDSH_COMMUNICATION;
+    }
+    printf("Socket created: %d\n", svr_socket);
+    int enable = 1;
+    if (setsockopt(svr_socket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable)) < 0) {
+        perror("Failed to set socket options");
+        close(svr_socket);
+        return ERR_RDSH_COMMUNICATION;
+    }
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    if (strcmp(ifaces, "0.0.0.0") == 0) {
+        addr.sin_addr.s_addr = INADDR_ANY;
+        printf("Binding to all available interfaces\n");
+    } else if (inet_pton(AF_INET, ifaces, &addr.sin_addr) <= 0) {
+        perror("Invalid IP address format");
+        close(svr_socket);
+        return ERR_RDSH_COMMUNICATION;
+    }
+    printf("Attempting to bind on %s:%d\n", ifaces, port);
+    if (bind(svr_socket, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+        perror("Binding failed");
+        close(svr_socket);
+        return ERR_RDSH_COMMUNICATION;
+    }
+    printf("Binding successful, preparing to listen...\n");
+
+    if (listen(svr_socket, 20) < 0) {
+        perror("Failed to start listening");
+        close(svr_socket);
+        return ERR_RDSH_COMMUNICATION;
+    }
+    printf("Server started successfully, listening on port %d\n", port);
+    return svr_socket;
+
+}
+
+/*
+ * process_cli_requests(svr_socket)
+ *      svr_socket:  The server socket that was obtained from boot_server()
+ *   
+ *  This function handles managing client connections.  It does this using
+ *  the following logic
+ * 
+ *      1.  Starts a while(1) loop:
+ *  
+ *          a. Calls accept() to wait for a client connection. Recall that 
+ *             the accept() function returns another socket specifically
+ *             bound to a client connection. 
+ *          b. Calls exec_client_requests() to handle executing commands
+ *             sent by the client. It will use the socket returned from
+ *             accept().
+ *          c. Loops back to the top (step 2) to accept connecting another
+ *             client.  
+ * 
+ *          note that the exec_client_requests() return code should be
+ *          negative if the client requested the server to stop by sending
+ *          the `stop-server` command.  If this is the case step 2b breaks
+ *          out of the while(1) loop. 
+ * 
+ *      2.  After we exit the loop, we need to cleanup.  Dont forget to 
+ *          free the buffer you allocated in step #1.  Then call stop_server()
+ *          to close the server socket. 
+ * 
+ *  Returns:
+ * 
+ *      OK_EXIT:  When the client sends the `stop-server` command this function
+ *                should return OK_EXIT. 
+ * 
+ *      ERR_RDSH_COMMUNICATION:  This error code terminates the loop and is
+ *                returned from this function in the case of the accept() 
+ *                function failing. 
+ * 
+ *      OTHERS:   See exec_client_requests() for return codes.  Note that positive
+ *                values will keep the loop running to accept additional client
+ *                connections, and negative values terminate the server. 
+ * 
+ */
+int process_cli_requests(int svr_socket){
+    int cli_socket;
+    int rc = OK;    
+    struct sockaddr_in client_addr;
+    socklen_t client_addr_len = sizeof(client_addr);
+
+    while(1){
+        cli_socket = accept(svr_socket, (struct sockaddr *)&client_addr, &client_addr_len);
+        if (cli_socket < 0) {
+            perror("accept failed");
+            return ERR_RDSH_COMMUNICATION;
+        }
+        char client_ip[INET_ADDRSTRLEN];
+        inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, sizeof(client_ip));
+        printf("Client connected from %s:%d\n", client_ip, ntohs(client_addr.sin_port));
+        rc = exec_client_requests(cli_socket);
+        close(cli_socket);
+        
+        if (rc == EXIT_SC || rc < 0) {
+            printf("Exit code %d received, terminating server process\n", rc);
+            close(svr_socket);
+            if (rc == EXIT_SC) {
+                exit(0);
+            }
+            break;
+        }
+    }
+
+    return rc;
+}
+
+/*
+ * exec_client_requests(cli_socket)
+ *      cli_socket:  The server-side socket that is connected to the client
+ *   
+ *  This function handles accepting remote client commands. The function will
+ *  loop and continue to accept and execute client commands.  There are 2 ways
+ *  that this ongoing loop accepting client commands ends:
+ * 
+ *      1.  When the client executes the `exit` command, this function returns
+ *          to process_cli_requests() so that we can accept another client
+ *          connection. 
+ *      2.  When the client executes the `stop-server` command this function
+ *          returns to process_cli_requests() with a return code of OK_EXIT
+ *          indicating that the server should stop. 
+ * 
+ *  Note that this function largely follows the implementation of the
+ *  exec_local_cmd_loop() function that you implemented in the last 
+ *  shell program deliverable. The main difference is that the command will
+ *  arrive over the recv() socket call rather than reading a string from the
+ *  keyboard. 
+ * 
+ *  This function also must send the EOF character after a command is
+ *  successfully executed to let the client know that the output from the
+ *  command it sent is finished.  Use the send_message_eof() to accomplish 
+ *  this. 
+ * 
+ *  Of final note, this function must allocate a buffer for storage to 
+ *  store the data received by the client. For example:
+ *     io_buff = malloc(RDSH_COMM_BUFF_SZ);
+ *  And since it is allocating storage, it must also properly clean it up
+ *  prior to exiting.
+ * 
+ *  Returns:
+ * 
+ *      OK:       The client sent the `exit` command.  Get ready to connect
+ *                another client. 
+ *      OK_EXIT:  The client sent `stop-server` command to terminate the server
+ * 
+ *      ERR_RDSH_COMMUNICATION:  A catch all for any socket() related send
+ *                or receive errors. 
+ */
+int exec_client_requests(int cli_socket) {
+    int io_size;
+    command_list_t cmd_list;
+    int rc;
+    int cmd_rc;
+    int last_rc;
+    char *io_buff;
+    char *command_buffer = NULL;
+    size_t command_buffer_size = 0;
+    int is_last_chunk = 0;
+    int command_complete = 0;
+    int result = OK;
+
+    io_buff = malloc(RDSH_COMM_BUFF_SZ);
+    if (io_buff == NULL) {
+        return ERR_RDSH_SERVER;
+    }
+
+    while (1) {
+        command_complete = 0;
+        free(command_buffer);
+        command_buffer = NULL;
+        command_buffer_size = 0;
+
+        while (!command_complete) {
+            memset(io_buff, 0, RDSH_COMM_BUFF_SZ);
+            io_size = recv(cli_socket, io_buff, RDSH_COMM_BUFF_SZ - 1, 0);
+
+            if (io_size <= 0) {
+                if (io_size == 0) printf("Client disconnected\n");
+                else perror("recv failed");
+                free(io_buff);
+                free(command_buffer);
+                return OK;
+            }
+
+            for (int i = 0; i < io_size; i++) {
+                if (io_buff[i] == '\0') {
+                    is_last_chunk = 1;
+                    io_size = i;
+                    command_complete = 1;
+                    break;
+                }
+            }
+
+            size_t new_size = command_buffer_size + io_size;
+            char *new_buffer = realloc(command_buffer, new_size + 1);
+
+            if (!new_buffer) {
+                perror("memory reallocation failed");
+                free(io_buff);
+                free(command_buffer);
+                return ERR_MEMORY;
+            }
+
+            command_buffer = new_buffer;
+            memcpy(command_buffer + command_buffer_size, io_buff, io_size);
+            command_buffer_size = new_size;
+            command_buffer[command_buffer_size] = '\0';
+
+            if (command_complete) break;
+        }
+
+        rc = build_cmd_list(command_buffer, &cmd_list);
+
+        if (rc < 0) {
+            char err_msg[RDSH_COMM_BUFF_SZ];
+
+            if (rc == WARN_NO_CMDS) {
+                snprintf(err_msg, sizeof(err_msg), CMD_WARN_NO_CMD);
+            } else if (rc == ERR_TOO_MANY_COMMANDS) {
+                snprintf(err_msg, sizeof(err_msg), CMD_ERR_PIPE_LIMIT, CMD_MAX);
+            } else {
+                snprintf(err_msg, sizeof(err_msg), "Error parsing command: %d\n", rc);
+            }
+
+            send_message_string(cli_socket, err_msg);
+            continue;
+        }
+
+        if (cmd_list.num > 0) {
+            Built_In_Cmds cmd_type = rsh_match_command(cmd_list.commands[0].argv[0]);
+
+            switch (cmd_type) {
+                case BI_CMD_EXIT:
+                    send_message_string(cli_socket, "Goodbye!\n");
+                    free_cmd_list(&cmd_list);
+                    free(io_buff);
+                    free(command_buffer);
+                    return OK;
+
+                case BI_CMD_STOP_SVR:
+                    send_message_string(cli_socket, "Stopping server...\n");
+                    free_cmd_list(&cmd_list);
+                    free(io_buff);
+                    free(command_buffer);
+                    return EXIT_SC;
+
+                case BI_CMD_CD:
+                    if (cmd_list.commands[0].argc < 2) {
+                        send_message_string(cli_socket, "cd: missing argument\n");
+                    } else {
+                        if (chdir(cmd_list.commands[0].argv[1]) != 0) {
+                            char error_msg[RDSH_COMM_BUFF_SZ];
+                            snprintf(error_msg, sizeof(error_msg), "cd: %s: %s\n", 
+                                    cmd_list.commands[0].argv[1], strerror(errno));
+                            send_message_string(cli_socket, error_msg);
+                        } else {
+                            send_message_eof(cli_socket);
+                        }
+                    }
+                    free_cmd_list(&cmd_list);
+                    continue;
+
+                case BI_CMD_DRAGON:
+                case BI_CMD_RC:
+                    send_message_string(cli_socket, BI_NOT_IMPLEMENTED);
+                    free_cmd_list(&cmd_list);
+                    continue;
+
+                default:
+                    break;
+            }
+        }
+
+        cmd_rc = rsh_execute_pipeline(cli_socket, &cmd_list);
+        send_message_eof(cli_socket);
+        free_cmd_list(&cmd_list);
+    }
+
+    
+    free(io_buff);
+    if (command_buffer != NULL) {
+        free(command_buffer);
+    }
+    
+    return result;
+}
+
+/*
+ * send_message_eof(cli_socket)
+ *      cli_socket:  The server-side socket that is connected to the client
+
+ *  Sends the EOF character to the client to indicate that the server is
+ *  finished executing the command that it sent. 
+ * 
+ *  Returns:
+ * 
+ *      OK:  The EOF character was sent successfully. 
+ * 
+ *      ERR_RDSH_COMMUNICATION:  The send() socket call returned an error or if
+ *           we were unable to send the EOF character. 
+ */
+int send_message_eof(int cli_socket){
+    int send_len = (int)sizeof(RDSH_EOF_CHAR);
+    int sent_len;
+    sent_len = send(cli_socket, &RDSH_EOF_CHAR, send_len, 0);
+
+    if (sent_len != send_len){
+        return ERR_RDSH_COMMUNICATION;
+    }
+    return OK;
+}
+
+
+/*
+ * send_message_string(cli_socket, char *buff)
+ *      cli_socket:  The server-side socket that is connected to the client
+ *      buff:        A C string (aka null terminated) of a message we want
+ *                   to send to the client. 
+ *   
+ *  Sends a message to the client.  Note this command executes both a send()
+ *  to send the message and a send_message_eof() to send the EOF character to
+ *  the client to indicate command execution terminated. 
+ * 
+ *  Returns:
+ * 
+ *      OK:  The message in buff followed by the EOF character was 
+ *           sent successfully. 
+ * 
+ *      ERR_RDSH_COMMUNICATION:  The send() socket call returned an error or if
+ *           we were unable to send the message followed by the EOF character. 
+ */
+int send_message_string(int cli_socket, char *buff) {
+    int bytes_sent = 0;
+
+    if (buff && *buff) {
+        bytes_sent = send(cli_socket, buff, strlen(buff), 0);
+        if (bytes_sent < 0) return ERR_RDSH_COMMUNICATION;
+    }
+
+    return send_message_eof(cli_socket);
+}
+
+
+/*
+ * rsh_execute_pipeline(int cli_sock, command_list_t *clist)
+ *      cli_sock:    The server-side socket that is connected to the client
+ *      clist:       The command_list_t structure that we implemented in
+ *                   the last shell. 
+ *   
+ *  This function executes the command pipeline.  It should basically be a
+ *  replica of the execute_pipeline() function from the last deliverable. 
+ *  The only thing different is that you will be using the cli_sock as the
+ *  main file descriptor on the first executable in the pipeline for STDIN,
+ *  and the cli_sock for the file descriptor for STDOUT, and STDERR for the
+ *  last executable in the pipeline.  See picture below:  
+ * 
+ *      
+ *┌───────────┐                                                    ┌───────────┐
+ *│ cli_sock  │                                                    │ cli_sock  │
+ *└─────┬─────┘                                                    └────▲──▲───┘
+ *      │   ┌──────────────┐     ┌──────────────┐     ┌──────────────┐  │  │    
+ *      │   │   Process 1  │     │   Process 2  │     │   Process N  │  │  │    
+ *      │   │              │     │              │     │              │  │  │    
+ *      └───▶stdin   stdout├─┬──▶│stdin   stdout├─┬──▶│stdin   stdout├──┘  │    
+ *          │              │ │   │              │ │   │              │     │    
+ *          │        stderr├─┘   │        stderr├─┘   │        stderr├─────┘    
+ *          └──────────────┘     └──────────────┘     └──────────────┘   
+ *                                                      WEXITSTATUS()
+ *                                                      of this last
+ *                                                      process to get
+ *                                                      the return code
+ *                                                      for this function       
+ * 
+ *  Returns:
+ * 
+ *      EXIT_CODE:  This function returns the exit code of the last command
+ *                  executed in the pipeline.  If only one command is executed
+ *                  that value is returned.  Remember, use the WEXITSTATUS()
+ *                  macro that we discussed during our fork/exec lecture to
+ *                  get this value. 
+ */
+int rsh_execute_pipeline(int cli_sock, command_list_t *clist) {
+    int pipes[clist->num - 1][2];  // Array of pipes
+    pid_t pids[clist->num];
+    int pids_st[clist->num];         // Array to store process status
+    int exit_code;
+
+    // Create all necessary pipes
+    for (int i = 0; i < clist->num - 1; i++) {
+        if (pipe(pipes[i]) == -1) {
+            perror("pipe");
+            return ESPIPE;
+        }
+    }
+
+    // Create processes for each command
+    for (int i = 0; i < clist->num; i++) {
+        pids[i] = fork();
+        if (pids[i] < 0) {
+            perror("fork failed");
+            return ERR_MEMORY;
+        }
+        if (pids[i] == 0) { 
+            if (i == 0) { 
+                if (clist->num > 1) close(pipes[0][0]);
+
+                dup2(cli_sock, STDIN_FILENO);
+                dup2((clist->num > 1) ? pipes[0][1] : cli_sock, STDOUT_FILENO);
+                dup2(cli_sock, STDERR_FILENO);
+
+                if (clist->commands[i].input_file) {
+                    int fd = open(clist->commands[i].input_file, O_RDONLY);
+                    if (fd < 0) {
+                        perror(clist->commands[i].input_file);
+                        exit(EXIT_FAILURE);
+                    }
+                    dup2(fd, STDIN_FILENO);
+                    close(fd);
+                }
+
+                for (int j = 1; j < clist->num - 1; j++) {
+                    close(pipes[j][0]);
+                    close(pipes[j][1]);
+                }
+                if (clist->num > 1) close(pipes[0][1]);
+            } 
+            
+            else if (i == clist->num - 1) { 
+                close(pipes[i - 1][1]);
+                dup2(pipes[i - 1][0], STDIN_FILENO);
+                dup2(cli_sock, STDOUT_FILENO);
+                dup2(cli_sock, STDERR_FILENO);
+
+                if (clist->commands[i].output_file) {
+                    int flags = O_WRONLY | O_CREAT | (clist->commands[i].append_mode ? O_APPEND : O_TRUNC);
+                    int fd = open(clist->commands[i].output_file, flags, 0644);
+                    if (fd < 0) {
+                        perror(clist->commands[i].output_file);
+                        exit(EXIT_FAILURE);
+                    }
+                    dup2(fd, STDOUT_FILENO);
+                    close(fd);
+                }
+
+                for (int j = 0; j < clist->num - 2; j++) {
+                    close(pipes[j][0]);
+                    close(pipes[j][1]);
+                }
+                close(pipes[i - 1][0]);
+            } 
+            
+            else { 
+                close(pipes[i][0]);
+                close(pipes[i - 1][1]);
+                dup2(pipes[i - 1][0], STDIN_FILENO);
+                dup2(pipes[i][1], STDOUT_FILENO);
+                dup2(cli_sock, STDERR_FILENO);
+
+                for (int j = 0; j < clist->num - 1; j++) {
+                    if (j != i && j != i - 1) {
+                        close(pipes[j][0]);
+                        close(pipes[j][1]);
+                    }
+                }
+                close(pipes[i - 1][0]);
+                close(pipes[i][1]);
+            }
+
+            execvp(clist->commands[i].argv[0], clist->commands[i].argv);
+            fprintf(stderr, "%s: command not found\n", clist->commands[i].argv[0]);
+            exit(EXIT_FAILURE);
+        }
+    }
+
+
+
+    // Parent process: close all pipe ends
+    for (int i = 0; i < clist->num - 1; i++) {
+        close(pipes[i][0]);
+        close(pipes[i][1]);
+    }
+
+    // Wait for all children
+    for (int i = 0; i < clist->num; i++) {
+        waitpid(pids[i], &pids_st[i], 0);
+    }
+
+    //by default get exit code of last process
+    //use this as the return value
+    exit_code = WEXITSTATUS(pids_st[clist->num - 1]);
+    for (int i = 0; i < clist->num; i++) {
+        //if any commands in the pipeline are EXIT_SC
+        //return that to enable the caller to react
+        if (WEXITSTATUS(pids_st[i]) == EXIT_SC)
+            exit_code = EXIT_SC;
+    }
+    return exit_code;
+}
+
+/**************   OPTIONAL STUFF  ***************/
+/****
+ **** NOTE THAT THE FUNCTIONS BELOW ALIGN TO HOW WE CRAFTED THE SOLUTION
+ **** TO SEE IF A COMMAND WAS BUILT IN OR NOT.  YOU CAN USE A DIFFERENT
+ **** STRATEGY IF YOU WANT.  IF YOU CHOOSE TO DO SO PLEASE REMOVE THESE
+ **** FUNCTIONS AND THE PROTOTYPES FROM rshlib.h
+ **** 
+ */
+
+/*
+ * rsh_match_command(const char *input)
+ *      cli_socket:  The string command for a built-in command, e.g., dragon,
+ *                   cd, exit-server
+ *   
+ *  This optional function accepts a command string as input and returns
+ *  one of the enumerated values from the BuiltInCmds enum as output. For
+ *  example:
+ * 
+ *      Input             Output
+ *      exit              BI_CMD_EXIT
+ *      dragon            BI_CMD_DRAGON
+ * 
+ *  This function is entirely optional to implement if you want to handle
+ *  processing built-in commands differently in your implementation. 
+ * 
+ *  Returns:
+ * 
+ *      BI_CMD_*:   If the command is built-in returns one of the enumeration
+ *                  options, for example "cd" returns BI_CMD_CD
+ * 
+ *      BI_NOT_BI:  If the command is not "built-in" the BI_NOT_BI value is
+ *                  returned. 
+ */
+Built_In_Cmds rsh_match_command(const char *input)
+{
+    if (strcmp(input, "exit") == 0)
+        return BI_CMD_EXIT;
+    if (strcmp(input, "dragon") == 0)
+        return BI_CMD_DRAGON;
+    if (strcmp(input, "cd") == 0)
+        return BI_CMD_CD;
+    if (strcmp(input, "stop-server") == 0)
+        return BI_CMD_STOP_SVR;
+    if (strcmp(input, "rc") == 0)
+        return BI_CMD_RC;
+    return BI_NOT_BI;
+}
+
+/*
+ * rsh_built_in_cmd(cmd_buff_t *cmd)
+ *      cmd:  The cmd_buff_t of the command, remember, this is the 
+ *            parsed version fo the command
+ *   
+ *  This optional function accepts a parsed cmd and then checks to see if
+ *  the cmd is built in or not.  It calls rsh_match_command to see if the 
+ *  cmd is built in or not.  Note that rsh_match_command returns BI_NOT_BI
+ *  if the command is not built in. If the command is built in this function
+ *  uses a switch statement to handle execution if appropriate.   
+ * 
+ *  Again, using this function is entirely optional if you are using a different
+ *  strategy to handle built-in commands.  
+ * 
+ *  Returns:
+ * 
+ *      BI_NOT_BI:   Indicates that the cmd provided as input is not built
+ *                   in so it should be sent to your fork/exec logic
+ *      BI_EXECUTED: Indicates that this function handled the direct execution
+ *                   of the command and there is nothing else to do, consider
+ *                   it executed.  For example the cmd of "cd" gets the value of
+ *                   BI_CMD_CD from rsh_match_command().  It then makes the libc
+ *                   call to chdir(cmd->argv[1]); and finally returns BI_EXECUTED
+ *      BI_CMD_*     Indicates that a built-in command was matched and the caller
+ *                   is responsible for executing it.  For example if this function
+ *                   returns BI_CMD_STOP_SVR the caller of this function is
+ *                   responsible for stopping the server.  If BI_CMD_EXIT is returned
+ *                   the caller is responsible for closing the client connection.
+ * 
+ *   AGAIN - THIS IS TOTALLY OPTIONAL IF YOU HAVE OR WANT TO HANDLE BUILT-IN
+ *   COMMANDS DIFFERENTLY. 
+ */
+Built_In_Cmds rsh_built_in_cmd(cmd_buff_t *cmd)
+{
+    Built_In_Cmds ctype = BI_NOT_BI;
+    ctype = rsh_match_command(cmd->argv[0]);
+
+    switch (ctype)
+    {
+    // case BI_CMD_DRAGON:
+    //     print_dragon();
+    //     return BI_EXECUTED;
+    case BI_CMD_EXIT:
+        return BI_CMD_EXIT;
+    case BI_CMD_STOP_SVR:
+        return BI_CMD_STOP_SVR;
+    case BI_CMD_RC:
+        return BI_CMD_RC;
+    case BI_CMD_CD:
+        chdir(cmd->argv[1]);
+        return BI_EXECUTED;
+    default:
+        return BI_NOT_BI;
+    }
+}
\ No newline at end of file
diff --git a/6-RShell/rshlib.h b/6-RShell/rshlib.h
new file mode 100644
index 0000000..6ae2ca9
--- /dev/null
+++ b/6-RShell/rshlib.h
@@ -0,0 +1,78 @@
+#ifndef __RSH_LIB_H__
+    #define __RSH_LIB_H__
+
+#include "dshlib.h"
+
+//common remote shell client and server constants and definitions
+
+
+//Constants for communication
+//Note that these should work fine in a local VM but you will likely have
+//to change the port number if you are working on tux.
+#define RDSH_DEF_PORT           1234        //Default port #
+#define RDSH_DEF_SVR_INTFACE    "0.0.0.0"   //Default start all interfaces
+#define RDSH_DEF_CLI_CONNECT    "127.0.0.1" //Default server is running on
+                                            //localhost 127.0.0.1
+
+//constants for buffer sizes
+#define RDSH_COMM_BUFF_SZ       (1024*64)   //64K
+#define STOP_SERVER_SC          200         //returned from pipeline excution
+                                            //if the command is to stop the
+                                            //server.  See documentation for 
+                                            //exec_client_requests() for more info
+
+//end of message delimiter.  This is super important.  TCP is a stream, therefore
+//the protocol designer is responsible for managing where messages begin and end
+//there are many common techniques for this, but one of the simplest ways is to
+//use an end of stream marker.  Since rsh is a "shell" program we will be using
+//ascii code 0x04, which is commonly used as the end-of-file (EOF) character in
+//linux based systems. 
+static const char RDSH_EOF_CHAR = 0x04;    
+
+//rdsh specific error codes for functions
+#define ERR_RDSH_COMMUNICATION  -50     //Used for communication errors
+#define ERR_RDSH_SERVER         -51     //General server errors
+#define ERR_RDSH_CLIENT         -52     //General client errors
+#define ERR_RDSH_CMD_EXEC       -53     //RSH command execution errors
+#define WARN_RDSH_NOT_IMPL      -99     //Not Implemented yet warning
+
+//Output message constants for server
+#define CMD_ERR_RDSH_COMM   "rdsh-error: communications error\n"
+#define CMD_ERR_RDSH_EXEC   "rdsh-error: command execution error\n"
+#define CMD_ERR_RDSH_ITRNL  "rdsh-error: internal server error - %d\n"
+#define CMD_ERR_RDSH_SEND   "rdsh-error: partial send.  Sent %d, expected to send %d\n"
+#define RCMD_SERVER_EXITED  "server appeared to terminate - exiting\n"
+
+//Output message constants for client
+#define RCMD_MSG_CLIENT_EXITED  "client exited: getting next connection...\n"
+#define RCMD_MSG_SVR_STOP_REQ   "client requested server to stop, stopping...\n"
+#define RCMD_MSG_SVR_EXEC_REQ   "rdsh-exec:  %s\n"
+#define RCMD_MSG_SVR_RC_CMD     "rdsh-exec:  rc = %d\n"
+
+//client prototypes for rsh_cli.c - - see documentation for each function to
+//see what they do
+int start_client(char *address, int port);
+int client_cleanup(int cli_socket, char *cmd_buff, char *rsp_buff, int rc);
+int exec_remote_cmd_loop(char *address, int port);
+    
+
+//server prototypes for rsh_server.c - see documentation for each function to
+//see what they do
+int start_server(char *ifaces, int port, int is_threaded);
+int boot_server(char *ifaces, int port);
+int stop_server(int svr_socket);
+int send_message_eof(int cli_socket);
+int send_message_string(int cli_socket, char *buff);
+int process_cli_requests(int svr_socket);
+int exec_client_requests(int cli_socket);
+int rsh_execute_pipeline(int socket_fd, command_list_t *clist);
+
+Built_In_Cmds rsh_match_command(const char *input);
+Built_In_Cmds rsh_built_in_cmd(cmd_buff_t *cmd);
+
+//eliminate from template, for extra credit
+void set_threaded_server(int val);
+int exec_client_thread(int main_socket, int cli_socket);
+void *handle_client(void *arg);
+
+#endif
\ No newline at end of file
-- 
GitLab