From 5202f4ff5465c1903fed4fd9f01015f166703859 Mon Sep 17 00:00:00 2001
From: cxb23 <cxb23@tux2.cci.drexel.edu>
Date: Thu, 13 Mar 2025 23:50:05 -0400
Subject: [PATCH] I completed the assignmeent as much as I could.

---
 6-RShell/bats/assignment_tests.sh |  36 ++
 6-RShell/bats/student_tests.sh    |  14 +
 6-RShell/dragon.txt               |  38 ++
 6-RShell/dsh                      | Bin 0 -> 51472 bytes
 6-RShell/dsh_cli.c                | 149 +++++++
 6-RShell/dshlib.c                 | 448 +++++++++++++++++++++
 6-RShell/dshlib.h                 | 100 +++++
 6-RShell/makefile                 |  31 ++
 6-RShell/rsh_cli.c                | 238 ++++++++++++
 6-RShell/rsh_server.c             | 620 ++++++++++++++++++++++++++++++
 6-RShell/rshlib.h                 |  78 ++++
 11 files changed, 1752 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.txt
 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/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..5246ee4
--- /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 ]
+}
diff --git a/6-RShell/bats/student_tests.sh b/6-RShell/bats/student_tests.sh
new file mode 100644
index 0000000..638bc34
--- /dev/null
+++ b/6-RShell/bats/student_tests.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bats
+
+# File: student_tests.sh
+# 
+# Create your unit tests suit in this file
+
+@test "Example: check ls runs without errors" {
+    run ./dsh <<EOF                
+ls
+EOF
+
+    # Assertions
+    [ "$status" -eq 0 ]
+}
diff --git a/6-RShell/dragon.txt b/6-RShell/dragon.txt
new file mode 100644
index 0000000..a9177fd
--- /dev/null
+++ b/6-RShell/dragon.txt
@@ -0,0 +1,38 @@
+                                                                        @%%%%                       
+                                                                     %%%%%%                         
+                                                                    %%%%%%                          
+                                                                 % %%%%%%%           @              
+                                                                %%%%%%%%%%        %%%%%%%           
+                                       %%%%%%%  %%%%@         %%%%%%%%%%%%@    %%%%%%  @%%%%        
+                                  %%%%%%%%%%%%%%%%%%%%%%      %%%%%%%%%%%%%%%%%%%%%%%%%%%%          
+                                %%%%%%%%%%%%%%%%%%%%%%%%%%   %%%%%%%%%%%% %%%%%%%%%%%%%%%           
+                               %%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%     %%%            
+                             %%%%%%%%%%%%%%%%%%%%%%%%%%%%@ @%%%%%%%%%%%%%%%%%%        %%            
+                            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%                
+                            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              
+                            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@%%%%%%@              
+      %%%%%%%%@           %%%%%%%%%%%%%%%%        %%%%%%%%%%%%%%%%%%%%%%%%%%      %%                
+    %%%%%%%%%%%%%         %%@%%%%%%%%%%%%           %%%%%%%%%%% %%%%%%%%%%%%      @%                
+  %%%%%%%%%%   %%%        %%%%%%%%%%%%%%            %%%%%%%%%%%%%%%%%%%%%%%%                        
+ %%%%%%%%%       %         %%%%%%%%%%%%%             %%%%%%%%%%%%@%%%%%%%%%%%                       
+%%%%%%%%%@                % %%%%%%%%%%%%%            @%%%%%%%%%%%%%%%%%%%%%%%%%                     
+%%%%%%%%@                 %%@%%%%%%%%%%%%            @%%%%%%%%%%%%%%%%%%%%%%%%%%%%                  
+%%%%%%%@                   %%%%%%%%%%%%%%%           %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              
+%%%%%%%%%%                  %%%%%%%%%%%%%%%          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%      %%%%  
+%%%%%%%%%@                   @%%%%%%%%%%%%%%         %%%%%%%%%%%%@ %%%% %%%%%%%%%%%%%%%%%   %%%%%%%%
+%%%%%%%%%%                  %%%%%%%%%%%%%%%%%        %%%%%%%%%%%%%      %%%%%%%%%%%%%%%%%% %%%%%%%%%
+%%%%%%%%%@%%@                %%%%%%%%%%%%%%%%@       %%%%%%%%%%%%%%     %%%%%%%%%%%%%%%%%%%%%%%%  %%
+ %%%%%%%%%%                  % %%%%%%%%%%%%%%@        %%%%%%%%%%%%%%   %%%%%%%%%%%%%%%%%%%%%%%%%% %%
+  %%%%%%%%%%%%  @           %%%%%%%%%%%%%%%%%%        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%% 
+   %%%%%%%%%%%%% %%  %  %@ %%%%%%%%%%%%%%%%%%          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    %%% 
+    %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%           @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    %%%%%%% 
+     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              %%%%%%%%%%%%%%%%%%%%%%%%%%%%        %%%   
+      @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                  %%%%%%%%%%%%%%%%%%%%%%%%%               
+        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                      %%%%%%%%%%%%%%%%%%%  %%%%%%%          
+           %%%%%%%%%%%%%%%%%%%%%%%%%%                           %%%%%%%%%%%%%%%  @%%%%%%%%%         
+              %%%%%%%%%%%%%%%%%%%%           @%@%                  @%%%%%%%%%%%%%%%%%%   %%%        
+                  %%%%%%%%%%%%%%%        %%%%%%%%%%                    %%%%%%%%%%%%%%%    %         
+                %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                      %%%%%%%%%%%%%%            
+                %%%%%%%%%%%%%%%%%%%%%%%%%%  %%%% %%%                      %%%%%%%%%%  %%%@          
+                     %%%%%%%%%%%%%%%%%%% %%%%%% %%                          %%%%%%%%%%%%%@          
+                                                                                 %%%%%%%@       
diff --git a/6-RShell/dsh b/6-RShell/dsh
new file mode 100755
index 0000000000000000000000000000000000000000..4a114e1042aaab4e10a5c2019c72fe1a06536bff
GIT binary patch
literal 51472
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
IK}dA{0Q#wZg8%>k

literal 0
HcmV?d00001

diff --git a/6-RShell/dsh_cli.c b/6-RShell/dsh_cli.c
new file mode 100644
index 0000000..3cf5a24
--- /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);
+}
diff --git a/6-RShell/dshlib.c b/6-RShell/dshlib.c
new file mode 100644
index 0000000..5cc3320
--- /dev/null
+++ b/6-RShell/dshlib.c
@@ -0,0 +1,448 @@
+#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 "dshlib.h"
+
+/**** 
+ **** FOR REMOTE SHELL USE YOUR SOLUTION FROM SHELL PART 3 HERE
+ **** THE MAIN FUNCTION CALLS THIS ONE AS ITS ENTRY POINT TO
+ **** EXECUTE THE SHELL LOCALLY
+ ****
+ */
+
+/*
+ * 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 numInstanceOf(char *str, const char c) {
+    int count = 0;
+    while (*str != '\0') {
+        if (*str == c) count++;
+        str++;
+    }
+    return count;
+}
+
+void print_dragon(){
+    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) {
+            break;
+    }
+    if (nchar == 0) {
+        continue;
+    }
+    if (s == NULL) {
+        exit(1);
+    }
+    if (s[nchar - 1] == '\n') {
+        s[nchar - 1] = '\0';
+        nchar--;
+    }
+
+    printf("%s\n", s);
+    }
+    free(s);
+    fclose(dragon);
+}
+
+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 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) return ERR_MEMORY;
+
+    for (int i = 0; i < CMD_ARGV_MAX; i++) {
+        cmd_buff->argv[i] = (char *)malloc(ARG_MAX * sizeof(char));
+        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 * sizeof(char));
+    if (cmd_buff->_cmd_buffer == NULL) {
+        for (int i = 0; i < CMD_ARGV_MAX; i++) free(cmd_buff->argv[i]);
+        free(cmd_buff->argv);
+        return ERR_MEMORY;
+    }
+
+    return OK;
+}
+
+void free_cmd_buff(cmd_buff_t *cmd_buff) {
+    if (cmd_buff != NULL) {
+                if (cmd_buff->_cmd_buffer != NULL) {
+                free(cmd_buff->_cmd_buffer);
+                cmd_buff->_cmd_buffer = NULL;
+                }
+
+                if (cmd_buff->argv != NULL) {
+                for (int i = 0; i < CMD_ARGV_MAX; i++) {
+                        if (cmd_buff->argv[i] != NULL) {
+                                free(cmd_buff->argv[i]);
+                                cmd_buff->argv[i] = NULL;
+                        }
+                }
+                free(cmd_buff->argv);
+                cmd_buff->argv = NULL;
+        }
+        memset(cmd_buff, 0, sizeof(cmd_buff_t));
+    }
+}
+
+void clear_cmd_buff(cmd_buff_t *cmd_buff) {
+    if (cmd_buff != NULL) {
+        cmd_buff->argc = 0;
+        if (cmd_buff->_cmd_buffer) memset(cmd_buff->_cmd_buffer, 0, strlen(cmd_buff->_cmd_buffer));
+        for (int i = 0; i < CMD_ARGV_MAX; i++) cmd_buff->argv[i] = NULL;
+    }
+}
+
+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;
+
+        if (cmd_buff->_cmd_buffer != NULL) {
+                free(cmd_buff->_cmd_buffer);
+                cmd_buff->_cmd_buffer = strdup(trim_whitespace(cmd_line));
+        } else 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) {
+                if (cmd_buff->argc >= CMD_ARGV_MAX - 1) return ERR_CMD_OR_ARGS_TOO_BIG;
+        cmd_buff->argv[cmd_buff->argc++] = p;
+        }
+
+    cmd_buff->argv[cmd_buff->argc] = NULL;
+    return OK;
+}
+
+int alloc_cmd_list(command_list_t *clist, int rc) {
+        if (clist == NULL) return ERR_MEMORY;
+        clist->num = 0;
+        clist->commands = (cmd_buff_t **)calloc(CMD_MAX, sizeof(cmd_buff_t *));
+        if (clist->commands == NULL) return ERR_MEMORY;
+
+        for (int i = 0; i < CMD_MAX; i++) {
+                cmd_buff_t *cmd = (cmd_buff_t *)malloc(sizeof(cmd_buff_t));
+                if (cmd == NULL) {
+                        rc = ERR_MEMORY;
+                        break;
+                }
+
+                memset(cmd, 0, sizeof(cmd_buff_t));
+
+                if ((rc = alloc_cmd_buff(cmd)) != OK_EXIT) {
+                        free(cmd);
+                        break;
+        }
+        clist->commands[i] = cmd;
+    }
+
+    return rc;
+}
+
+int build_cmd_list(char *cmd_line, command_list_t *clist, int rc) {
+    if (numInstanceOf(cmd_line, PIPE_CHAR) > CMD_MAX-1) return ERR_TOO_MANY_COMMANDS;
+
+    if ((int)strlen(cmd_line) > SH_CMD_MAX) return ERR_CMD_OR_ARGS_TOO_BIG;
+
+    char *outer_saveptr = NULL;
+
+    char *outer_token = strtok_r(cmd_line, PIPE_STRING, &outer_saveptr);
+
+    while (outer_token != NULL) {
+        if (clist->num > CMD_MAX) return ERR_TOO_MANY_COMMANDS;
+
+                cmd_buff_t *cmd = malloc(sizeof(cmd_buff_t));
+
+                if ((rc = alloc_cmd_buff(cmd)) != OK) {
+                        free(cmd);
+                        return rc;
+                }
+
+        if ((rc = build_cmd_buff(outer_token, cmd)) != OK) {
+                free(cmd);
+                return rc;
+        }
+
+        clist->commands[clist->num] = cmd;
+        clist->num++;
+
+        outer_token = strtok_r(NULL, PIPE_STRING, &outer_saveptr);
+    }
+
+    return OK;
+}
+
+void free_cmd_list(command_list_t *clist) {
+        if (clist != NULL) {
+                if (clist->commands != NULL) {
+                        for (int i = 0; i < CMD_MAX; i++) {
+                                if (clist->commands[i] != NULL) {
+                                        free_cmd_buff(clist->commands[i]);
+                                        free(clist->commands[i]);
+                                        clist->commands[i] = NULL;
+                                }
+                        }
+                        free(clist->commands);
+                        clist->commands = NULL;
+                }
+        }
+}
+
+void clear_cmd_list(command_list_t *clist) {
+        if (clist != NULL) {
+                clist->num = 0;
+                for (int i = 0; i < CMD_MAX; i++) clear_cmd_buff(clist->commands[i]);
+        }
+}
+
+int execute_pipeline(command_list_t *clist) {
+        int pipes[clist->num - 1][2];
+    pid_t pids[clist->num];
+
+    for (int i = 0; i < clist->num - 1; i++) {
+        if (pipe(pipes[i]) == -1) {
+            perror("pipe");
+            exit(EXIT_FAILURE);
+        }
+    }
+
+        for (int i = 0; i < clist->num; i++) {
+        pids[i] = fork();
+        if (pids[i] == -1) {
+            perror("fork");
+            exit(EXIT_FAILURE);
+        }
+
+        if (pids[i] == 0) {
+            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(EXIT_FAILURE);
+        }
+    }
+
+    for (int i = 0; i < clist->num - 1; i++) {
+        close(pipes[i][0]);
+        close(pipes[i][1]);
+    }
+
+    for (int i = 0; i < clist->num; i++) waitpid(pids[i], NULL, 0);
+
+        return OK;
+}
+
+int exec_one_cmd(command_list_t *clist, int rc) {
+        cmd_buff_t *cmd = clist->commands[0];
+        if (strcmp(cmd->argv[0], "dragon") == 0) {
+                print_dragon();
+                return OK;
+        }
+
+        if (strcmp(cmd->argv[0], "rc") == 0) {
+                printf("%d\n", rc);
+                return OK;
+        }
+
+        if (strcmp(cmd->argv[0], EXIT_CMD) == 0) {
+                printf("exiting...\n");
+                return(OK_EXIT);
+        }
+
+        cmd->argv[cmd->argc] = 0;
+
+        if (strcmp(cmd->argv[0], "cd") == 0) chdir(cmd->argv[1]);
+        else {
+                int f_result, c_result;
+                f_result = fork();
+
+                if (f_result < 0) perror("fork failed");
+                else if (f_result == 0) {
+                        rc = execvp(cmd->argv[0], cmd->argv);
+                        perror("execvp failed");
+                        exit(EXIT_FAILURE);
+                } else {
+                        wait(&c_result);
+                }
+        }
+        return OK;
+}
+
+int exec_cmd(command_list_t *clist, int rc) {
+        if (clist == NULL) return ERR_MEMORY;
+
+        if (rc == ERR_TOO_MANY_COMMANDS) {
+        printf(CMD_ERR_PIPE_LIMIT, CMD_MAX);
+        return rc;
+    }
+
+        char *cmd = clist->commands[0]->argv[0];
+    if (!cmd) return ERR_MEMORY;
+
+        if (clist->num == 1) {
+                if ((rc = exec_one_cmd(clist, rc)) != OK) {
+                        if (rc == OK_EXIT) {
+                                clear_cmd_list(clist);
+                                return rc;
+                        } else return ERR_EXEC_CMD;
+                }
+        }
+
+        if (clist->num > 1) {
+                if ((rc = execute_pipeline(clist)) != OK) return ERR_EXEC_CMD;
+        }
+
+        return OK;
+}
+
+int exec_local_cmd_loop()
+{
+        char *cmd_line = (char *)malloc(ARG_MAX * sizeof(char));
+        int rc = OK;
+        command_list_t *clist = (command_list_t *)malloc(sizeof(command_list_t));
+
+        if ((rc = alloc_cmd_list(clist, rc)) != OK) {
+                free(cmd_line);
+                return rc;
+        }
+
+        while(1){
+                printf("%s", SH_PROMPT);
+        if (fgets(cmd_line, ARG_MAX, stdin) == NULL){
+                printf("\n");
+            break;
+        }
+        //remove the trailing \n from cmd_buff
+        cmd_line[strcspn(cmd_line,"\n")] = '\0';
+
+        //IMPLEMENT THE REST OF THE REQUIREMENTS
+                if (strlen(cmd_line) == 0) {
+                        printf(CMD_WARN_NO_CMD);
+                        continue;
+                }
+
+                if ((rc = build_cmd_list(cmd_line, clist, rc)) != OK) break;
+
+                if ((rc = exec_cmd(clist, rc)) != OK) {
+                        if (rc == OK_EXIT) rc = OK;
+                        break;
+                }
+
+        clear_cmd_list(clist);
+    }
+
+    free(cmd_line);
+    free_cmd_list(clist);
+    free(clist);
+    return rc;
+}
diff --git a/6-RShell/dshlib.h b/6-RShell/dshlib.h
new file mode 100644
index 0000000..06ef5b9
--- /dev/null
+++ b/6-RShell/dshlib.h
@@ -0,0 +1,100 @@
+#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 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 DOUBLE_QUOTE_CHAR '"'
+
+#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
+
+
+//helpers
+int numInstanceOf(char *str, const char c);
+void print_dragon();
+char* trim_whitesapce(char *str);
+
+//prototypes
+int alloc_cmd_buff(cmd_buff_t *cmd_buff);
+void free_cmd_buff(cmd_buff_t *cmd_buff);
+void 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 alloc_cmd_list(command_list_t *clist, int rc);
+int build_cmd_list(char *cmd_line, command_list_t *clist, int rc);
+void free_cmd_list(command_list_t *cmd_lst);
+void clear_cmd_list(command_list_t *clist);
+
+//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_one_cmd(command_list_t *clist, int rc);
+int exec_cmd(command_list_t *clist, int rc);
+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
diff --git a/6-RShell/makefile b/6-RShell/makefile
new file mode 100644
index 0000000..a079ef4
--- /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
diff --git a/6-RShell/rsh_cli.c b/6-RShell/rsh_cli.c
new file mode 100644
index 0000000..d1dea13
--- /dev/null
+++ b/6-RShell/rsh_cli.c
@@ -0,0 +1,238 @@
+
+#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 || !rsp_buff) {
+		perror("malloc failed");
+		return 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) 
+    {
+        // TODO print prompt
+		printf("%s", SH_PROMPT);
+        // TODO fgets input
+		if (fgets(cmd_buff, ARG_MAX, stdin) == NULL) {
+			printf("\n");
+			break;
+		}
+		cmd_buff[strcspn(cmd_buff,"\n")] = '\0';
+        
+        // TODO send() over cli_socket
+		int send_len = strlen(cmd_buff) + 1;
+		int bytes_sent = send(cli_socket, cmd_buff, send_len, 0);
+		if (bytes_sent < 0) {
+			perror("send failed");
+			return client_cleanup(cli_socket, cmd_buff, rsp_buff, ERR_RDSH_COMMUNICATION);
+		}
+
+        // TODO recv all the results
+		char eof = RDSH_EOF_CHAR;
+		while ((io_size = recv(cli_socket, rsp_buff, RDSH_COMM_BUFF_SZ, 0)) > 0) {
+	 		if (io_size < 0) {
+				perror("recv failed");
+				return client_cleanup(cli_socket, cmd_buff, rsp_buff, ERR_RDSH_COMMUNICATION);
+			}
+			if (io_size == 0) break;
+			is_eof = ((char)rsp_buff[io_size - 1] == eof) ? 1 : 0;
+			if (is_eof) rsp_buff[io_size - 1] = '\0';
+			printf("%.*s", (int)io_size, rsp_buff);
+
+			if (is_eof) break;
+		}
+
+        // TODO break on exit command
+    	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 = socket(AF_INET, SOCK_STREAM, 0);
+    int ret;
+
+    // TODO set up cli_socket
+	if (cli_socket == -1) {
+		perror("socket");
+		return ERR_RDSH_CLIENT; 
+	}
+
+	memset(&addr, 0, sizeof(struct sockaddr_in)); 
+	addr.sin_family = AF_INET; 
+	addr.sin_addr.s_addr = inet_addr(server_ip); 
+	addr.sin_port = htons(port); 
+
+	ret = connect(cli_socket, (const struct sockaddr *) &addr, sizeof(struct sockaddr_in)); 
+	if (ret == -1) {
+		perror("connect");
+		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;
+}
diff --git a/6-RShell/rsh_server.c b/6-RShell/rsh_server.c
new file mode 100644
index 0000000..c49edce
--- /dev/null
+++ b/6-RShell/rsh_server.c
@@ -0,0 +1,620 @@
+#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>
+
+//INCLUDES for extra credit
+//#include <signal.h>
+//#include <pthread.h>
+//-------------------------
+
+#include "dshlib.h"
+#include "rshlib.h"
+
+
+/*
+ * 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){
+    int svr_socket;
+    int rc;
+
+    //
+    //TODO:  If you are implementing the extra credit, please add logic
+    //       to keep track of is_threaded to handle this feature
+    //
+	
+    svr_socket = boot_server(ifaces, port);
+    if (svr_socket < 0){
+        int err_code = svr_socket;  //server socket will carry error code
+        return err_code;
+    }
+
+    rc = process_cli_requests(svr_socket);
+
+    stop_server(svr_socket);
+
+
+    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 = socket(AF_INET, SOCK_STREAM, 0);
+	int ret;
+    
+    struct sockaddr_in addr;
+
+    // TODO set up the socket - this is very similar to the demo code
+
+    /*
+     * Prepare for accepting connections. The backlog size is set
+     * to 20. So while one request is being processed other requests
+     * can be waiting.
+     */
+	if (svr_socket == -1) {
+		perror("socket");
+		return ERR_RDSH_COMMUNICATION;
+	}
+
+	int enable=1;
+	setsockopt(svr_socket, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int));
+	
+	memset(&addr, 0, sizeof(addr));
+	addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr = inet_addr(ifaces);
+    addr.sin_port = htons(port);
+
+    ret = bind(svr_socket, (const struct sockaddr *) &addr, sizeof(struct sockaddr_in));
+	
+	if (ret == -1) {
+		perror("bind");
+		return ERR_RDSH_COMMUNICATION;
+	}
+
+    ret = listen(svr_socket, 20);
+    if (ret == -1) {
+        perror("listen");
+        return ERR_RDSH_COMMUNICATION;
+    }
+
+    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;    
+
+    while(1){
+        // TODO use the accept syscall to create cli_socket 
+        cli_socket  = accept(svr_socket, NULL, NULL);
+        if (cli_socket == -1) {
+			perror("accept");
+			return ERR_RDSH_COMMUNICATION; 
+        }
+
+        // and then exec_client_requests(cli_socket)
+		rc = exec_client_requests(cli_socket); 
+    	if (rc < 0) break;
+    	
+    }
+
+    stop_server(svr_socket);
+    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 = malloc(sizeof(command_list_t));
+    int rc;
+    int cmd_rc;
+    //int last_rc;
+    char *io_buff;
+
+    io_buff = malloc(RDSH_COMM_BUFF_SZ);
+    if (io_buff == NULL){
+        return ERR_RDSH_SERVER;
+    }
+
+    while(1) {
+        // TODO use recv() syscall to get input
+		io_size = recv(cli_socket, io_buff, RDSH_COMM_BUFF_SZ, 0);
+		if (io_size == -1) {
+			perror("read error");
+			return ERR_RDSH_COMMUNICATION;
+		}
+        // TODO build up a cmd_list
+		cmd_list->num = 0;
+		
+		rc = alloc_cmd_list(cmd_list, rc);
+
+		rc = build_cmd_list(io_buff, cmd_list, rc); 
+		if (rc == OK) {
+        	// TODO rsh_execute_pipeline to run your cmd_list
+			cmd_rc = rsh_execute_pipeline(cli_socket, cmd_list);
+		}
+		
+		if (strcmp(io_buff, EXIT_CMD) == 0) {
+            free(io_buff);
+    		free_cmd_list(cmd_list);
+            rc = OK;
+            return OK;
+        } else if (strcmp(io_buff, "stop-server") == 0) {
+            free(io_buff);
+    		free_cmd_list(cmd_list);
+            rc = OK;
+            return OK_EXIT;
+        }
+		
+        // TODO send appropriate respones with send_message_string
+        // - error constants for failures
+        // - buffer contents from execute commands
+        //  - etc.
+		if (cmd_rc == 0) send_message_string(cli_socket, io_buff);
+		else send_message_string(cli_socket, CMD_ERR_RDSH_EXEC);
+
+        // TODO send_message_eof when done
+    	send_message_eof(cli_socket);
+    }
+
+    return WARN_RDSH_NOT_IMPL;
+}
+
+/*
+ * 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 = 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){
+    //TODO implement writing to cli_socket with send()
+    int send_len = strlen(buff) + 1; 
+    int bytes_sent; 
+
+    bytes_sent = send(cli_socket, buff, send_len, 0); 
+    if (bytes_sent == -1) {
+		perror("send failed");
+		return ERR_RDSH_COMMUNICATION; 
+    }
+	
+	int result = send_message_eof(cli_socket); 
+	if (result == OK) return OK; 
+	else {
+		perror("eof send failed");
+		return ERR_RDSH_COMMUNICATION;
+	}
+
+    return WARN_RDSH_NOT_IMPL;
+}
+
+
+/*
+ * 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 IDs
+    //Built_In_Cmds bi_cmd;
+    int exit_code;
+
+    // Create all necessary pipes
+    for (int i = 0; i < clist->num - 1; i++) {
+        if (pipe(pipes[i]) == -1) {
+            perror("pipe");
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    for (int i = 0; i < clist->num; i++) {
+        // TODO this is basically the same as the piped fork/exec assignment, except for where you connect the begin and end of the pipeline (hint: cli_sock)
+        // TODO HINT you can dup2(cli_sock with STDIN_FILENO, STDOUT_FILENO, etc.
+		pids[i] = fork(); 
+		if (pids[i] == -1) {
+            perror("fork");
+            exit(EXIT_FAILURE);
+        }
+	
+		if (pids[i] == 0) {
+		if (pids[i] == 0) { //child process
+            cmd_buff_t *cmd = clist->commands[i];
+            //set up input pipe for all except first process
+            if (i == 0) {
+				dup2(cli_sock, STDIN_FILENO);
+            }
+			if (i == clist->num - 1) {
+				dup2(cli_sock, STDOUT_FILENO);
+                dup2(cli_sock, STDERR_FILENO);
+			}
+
+            if (i > 0) {
+                dup2(pipes[i-1][0], STDIN_FILENO);
+            }
+            //set up output pipes for all except last process
+            if (i < clist->num - 1) {
+                dup2(pipes[i][1], STDOUT_FILENO);
+            }
+            //close all pipe ends in child
+            for (int j = 0; j < clist->num - 1; j++) {
+                close(pipes[j][0]);
+                close(pipes[j][1]);
+            }
+            //execute command
+            execvp(cmd->argv[0], cmd->argv);
+            perror("execvp");
+            exit(EXIT_FAILURE);
+        }	cmd_buff_t *cmd = clist->commands[i];
+        	if (i == 0) dup2(cli_sock, STDIN_FILENO);
+		
+			if (i == clist->num - 1) {
+				dup2(cli_sock, STDOUT_FILENO);
+            	dup2(cli_sock, STDERR_FILENO);
+			}
+
+        	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(cmd->argv[0], cmd->argv);
+        	perror("execvp");
+        	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;
+    }
+}
diff --git a/6-RShell/rshlib.h b/6-RShell/rshlib.h
new file mode 100644
index 0000000..a104cf1
--- /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
-- 
GitLab