From 4143e2cddf3ed35f2caafcd4041cc1fef88b853e Mon Sep 17 00:00:00 2001
From: jl4589 <jl4589@drexel.edu>
Date: Thu, 13 Mar 2025 15:50:08 -0400
Subject: [PATCH] Fixed a bunch of the functions. Hopefully it works now

---
 Assignment-06/starter/dshlib.c     | 126 +++++++++++-------------
 Assignment-06/starter/rsh_cli.c    |  78 +++++++++++----
 Assignment-06/starter/rsh_server.c | 153 +++++++++++++++++------------
 3 files changed, 205 insertions(+), 152 deletions(-)

diff --git a/Assignment-06/starter/dshlib.c b/Assignment-06/starter/dshlib.c
index 9fa4c8b..b911537 100644
--- a/Assignment-06/starter/dshlib.c
+++ b/Assignment-06/starter/dshlib.c
@@ -263,94 +263,80 @@ static void start_server() {
  *      fork(), execvp(), exit(), chdir()
  */
 
-
-
-int exec_local_cmd_loop() {
-    char cmd_buff[SH_CMD_MAX];
-    int rc = OK;
+ int exec_remote_cmd_loop(char *address, int port) {
+    char cmd_buff[RDSH_COMM_BUFF_SZ];
+    char rsp_buff[RDSH_COMM_BUFF_SZ];
+    int cli_socket;
+    ssize_t recv_bytes;
+    int is_eof;
+
+    // Connect to the server
+    cli_socket = start_client(address, port);
+    if (cli_socket < 0) {
+        perror("start client");
+        return client_cleanup(cli_socket, NULL, NULL, ERR_RDSH_CLIENT);
+    }
 
     while (1) {
-        printf("%s", SH_PROMPT);
-
-        if (fgets(cmd_buff, SH_CMD_MAX, stdin) == NULL) {
-            printf("\n");
-            break;
+        printf("rsh> ");
+        if (!fgets(cmd_buff, RDSH_COMM_BUFF_SZ, stdin)) {
+            break;  // Exit on input error or EOF
         }
 
-        cmd_buff[strcspn(cmd_buff, "\n")] = '\0';
-
-        if (strlen(cmd_buff) == 0) {
-            printf("%s\n", CMD_WARN_NO_CMD);
-            rc = WARN_NO_CMDS;
-            continue;
+        // Remove the newline character from the command
+        size_t cmd_len = strlen(cmd_buff);
+        if (cmd_len > 0 && cmd_buff[cmd_len - 1] == '\n') {
+            cmd_buff[cmd_len - 1] = '\0';
         }
 
-        if (strstr(cmd_buff, "|") != NULL) {
-            command_list_t cmd_list;
-            if (parse_pipeline(cmd_buff, &cmd_list) != OK) {
-                fprintf(stderr, "%s\n", CMD_ERR_PIPE_LIMIT);
-                rc = ERR_TOO_MANY_COMMANDS;
-                continue;
-            }
-
-            // Execute the pipeline
-
-            execute_pipeline(&cmd_list);
-
-            // Free memory for each command's buffer
-            for (int i = 0; i < cmd_list.num; i++) {
-                free(cmd_list.commands[i]._cmd_buffer);
-            }
-        } else {
+        // Handle local commands (e.g., cd, exit)
+        if (strncmp(cmd_buff, "cd", 2) == 0) {
+            // Handle cd locally
             cmd_buff_t cmd;
             if (build_cmd_buff(cmd_buff, &cmd) != OK) {
                 fprintf(stderr, "%s\n", CMD_ERR_PIPE_LIMIT);
-                rc = ERR_MEMORY;
                 continue;
             }
-
-            if (strcmp(cmd.argv[0], EXIT_CMD) == 0) {
-                free(cmd._cmd_buffer);
-                break;
-            }
-
-            if (strcmp(cmd.argv[0], "cd") == 0) {
-                if (cmd.argc == 1) {
-                    chdir(getenv("HOME"));
-                } else if (cmd.argc == 2) {
-                    if (chdir(cmd.argv[1]) != 0) {
-                        perror("cd");
-                    }
-                } else {
-                    fprintf(stderr, "%s\n", CMD_ERR_PIPE_LIMIT);
+            if (cmd.argc == 1) {
+                chdir(getenv("HOME"));
+            } else if (cmd.argc == 2) {
+                if (chdir(cmd.argv[1]) != 0) {
+                    perror("cd");
                 }
-                free(cmd._cmd_buffer);
-                continue;
+            } else {
+                fprintf(stderr, "%s\n", CMD_ERR_PIPE_LIMIT);
             }
+            free(cmd._cmd_buffer);
+            continue;
+        } else if (strncmp(cmd_buff, "exit", 4) == 0) {
+            break;  // Exit the remote shell
+        }
 
-            pid_t pid = fork();
-            if (pid < 0) {
-                perror("fork failed");
-                rc = ERR_MEMORY;
-            } else if (pid == 0) {
-                execvp(cmd.argv[0], cmd.argv);
-                perror("execvp failed");
-                exit(EXIT_FAILURE);
-            } else {
-                int status;
-                wait(&status);
+        // Send the command to the server
+        ssize_t sent_bytes = send(cli_socket, cmd_buff, strlen(cmd_buff), 0);
+        if (sent_bytes < 0) {
+            perror("send");
+            return client_cleanup(cli_socket, NULL, NULL, ERR_RDSH_COMMUNICATION);
+        }
 
-                if (WIFEXITED(status)) {
-                    if (WEXITSTATUS(status) != 0) {
-                        fprintf(stderr, "Command failed with exit code %d\n", WEXITSTATUS(status));
-                    }
-                }
+        // Receive the server's response
+        is_eof = 0;
+        while ((recv_bytes = recv(cli_socket, rsp_buff, RDSH_COMM_BUFF_SZ, 0)) > 0) {
+            printf("%.*s", (int)recv_bytes, rsp_buff);
+            if (rsp_buff[recv_bytes - 1] == RDSH_EOF_CHAR) {
+                is_eof = 1;
+                break;
             }
+        }
 
-            free(cmd._cmd_buffer);
+        if (recv_bytes < 0) {
+            perror("recv");
+            return client_cleanup(cli_socket, NULL, NULL, ERR_RDSH_COMMUNICATION);
+        } else if (recv_bytes == 0) {
+            printf("Server closed the connection\n");
+            break;
         }
     }
 
-    return rc;
+    return client_cleanup(cli_socket, NULL, NULL, OK);
 }
-
diff --git a/Assignment-06/starter/rsh_cli.c b/Assignment-06/starter/rsh_cli.c
index 70a1bdb..1ce6b5b 100644
--- a/Assignment-06/starter/rsh_cli.c
+++ b/Assignment-06/starter/rsh_cli.c
@@ -92,33 +92,50 @@
  */
 int exec_remote_cmd_loop(char *address, int port)
 {
-    char *cmd_buff;
-    char *rsp_buff;
+    char cmd_buff[RDSH_COMM_BUFF_SZ];  // Use the buffer size from rshlib.h
+    char rsp_buff[RDSH_COMM_BUFF_SZ];
     int cli_socket;
-    ssize_t io_size;
+    ssize_t recv_bytes;
     int is_eof;
 
-    // TODO set up cmd and response buffs
-
-    cli_socket = start_client(address,port);
-    if (cli_socket < 0){
+    // Connect to the server
+    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);
+        return client_cleanup(cli_socket, NULL, NULL, ERR_RDSH_CLIENT);
     }
 
-    while (1) 
-    {
-        // TODO print prompt
-
-        // TODO fgets input
-
-        // TODO send() over cli_socket
-
-        // TODO recv all the results
-
-        // TODO break on exit command
+    while (1) {
+        printf("rsh> ");
+        if (!fgets(cmd_buff, RDSH_COMM_BUFF_SZ, stdin)) {
+            break;  
+        }
+
+        if (send(cli_socket, cmd_buff, strlen(cmd_buff), 0) < 0) {
+            perror("send");
+            return client_cleanup(cli_socket, NULL, NULL, ERR_RDSH_COMMUNICATION);
+        }
+
+        is_eof = 0;
+        while ((recv_bytes = recv(cli_socket, rsp_buff, RDSH_COMM_BUFF_SZ, 0)) > 0) {
+            printf("%.*s", (int)recv_bytes, rsp_buff);  // Print the received data
+            if (rsp_buff[recv_bytes - 1] == RDSH_EOF_CHAR) {
+                is_eof = 1;  // Check for EOF character
+                break;
+            }
+        }
+
+        if (recv_bytes < 0) {
+            perror("recv");
+            return client_cleanup(cli_socket, NULL, NULL, ERR_RDSH_COMMUNICATION);
+        }
+
+        if (strncmp(cmd_buff, "exit", 4) == 0 || strncmp(cmd_buff, "stop-server", 11) == 0) {
+            break;
+        }
     }
 
+
     return client_cleanup(cli_socket, cmd_buff, rsp_buff, OK);
 }
 
@@ -151,6 +168,29 @@ int start_client(char *server_ip, int port){
     int ret;
 
     // TODO set up cli_socket
+    cli_socket = socket(AF_INET, SOCK_STREAM, 0);
+    if (cli_socket < 0) {
+        perror("socket");
+        return ERR_RDSH_CLIENT;
+    }
+
+    // Set up the server address structure
+    memset(&addr, 0, sizeof(addr));
+    addr.sin_family = AF_INET;
+    addr.sin_port = htons(port);
+    if (inet_pton(AF_INET, server_ip, &addr.sin_addr) <= 0) {
+        perror("inet_pton");
+        close(cli_socket);
+        return ERR_RDSH_CLIENT;
+    }
+
+    // Connect to the server
+    ret = connect(cli_socket, (struct sockaddr *)&addr, sizeof(addr));
+    if (ret < 0) {
+        perror("connect");
+        close(cli_socket);
+        return ERR_RDSH_CLIENT;
+    }
 
 
     return cli_socket;
diff --git a/Assignment-06/starter/rsh_server.c b/Assignment-06/starter/rsh_server.c
index 648d2c7..f34ddf3 100644
--- a/Assignment-06/starter/rsh_server.c
+++ b/Assignment-06/starter/rsh_server.c
@@ -302,73 +302,109 @@ int boot_server(char *ifaces, int port){
  */
 
 int exec_client_requests(int cli_socket) {
-    char *io_buff;
-    int io_size;
-    command_list_t cmd_list;
+    char cmd_buff[RDSH_COMM_BUFF_SZ];
+    ssize_t recv_bytes;
     int rc = OK;
 
-    // Allocate a buffer for I/O operations
-    io_buff = malloc(RDSH_COMM_BUFF_SZ);
-    if (io_buff == NULL) {
-        return ERR_RDSH_SERVER; // Return server error if allocation fails
-    }
-
     while (1) {
-        // Receive input from the client
-        io_size = recv(cli_socket, io_buff, RDSH_COMM_BUFF_SZ, 0);
-        if (io_size < 0) {
-            perror("recv");
-            free(io_buff);
-            return ERR_RDSH_COMMUNICATION; // Return communication error
-        } else if (io_size == 0) {
-            // Client disconnected
-            free(io_buff);
-            return OK; // Return OK to accept another client
+        recv_bytes = recv(cli_socket, cmd_buff, RDSH_COMM_BUFF_SZ, 0);
+        if (recv_bytes <= 0) {
+            close(cli_socket);
+            printf("Client disconnected\n");
+            return OK;
         }
 
-        // Null-terminate the received data
-        io_buff[io_size] = '\0';
+        cmd_buff[recv_bytes] = '\0';
 
-        // Check for special commands
-        if (strncmp(io_buff, "exit", strlen("exit")) == 0) {
-            // Client sent the `exit` command
-            free(io_buff);
-            return OK; // Return OK to accept another client
-        } else if (strncmp(io_buff, "stop-server", strlen("stop-server")) == 0) {
-            // Client sent the `stop-server` command
-            free(io_buff);
-            return OK_EXIT; // Return OK_EXIT to stop the server
-        }
+        cmd_buff[strcspn(cmd_buff, "\n")] = '\0';
 
-        // Parse the input into a command list
-        rc = parse_pipeline(io_buff, &cmd_list);
-        if (rc != OK) {
-            // Handle parsing error
-            send_message_string(cli_socket, CMD_ERR_RDSH_EXEC);
+        if (strlen(cmd_buff) == 0) {
+            send_message_string(cli_socket, CMD_WARN_NO_CMD);
             send_message_eof(cli_socket);
-            continue; // Continue to the next iteration
+            rc = WARN_NO_CMDS;
+            continue;
         }
 
-        // Execute the command pipeline
-        rc = rsh_execute_pipeline(cli_socket, &cmd_list);
-        if (rc < 0) {
-            // Handle execution error
-            send_message_string(cli_socket, CMD_ERR_RDSH_EXEC);
-            send_message_eof(cli_socket);
-            continue; // Continue to the next iteration
-        }
+        if (strstr(cmd_buff, "|") != NULL) {
+            command_list_t cmd_list;
+            if (parse_pipeline(cmd_buff, &cmd_list) != OK) {
+                send_message_string(cli_socket, CMD_ERR_PIPE_LIMIT);
+                send_message_eof(cli_socket);
+                rc = ERR_TOO_MANY_COMMANDS;
+                continue;
+            }
+
+            rc = rsh_execute_pipeline(cli_socket, &cmd_list);
+
+            for (int i = 0; i < cmd_list.num; i++) {
+                free(cmd_list.commands[i]._cmd_buffer);
+            }
+        } else {
+            cmd_buff_t cmd;
+            if (build_cmd_buff(cmd_buff, &cmd) != OK) {
+                send_message_string(cli_socket, CMD_ERR_PIPE_LIMIT);
+                send_message_eof(cli_socket);
+                rc = ERR_MEMORY;
+                continue;
+            }
+
+            if (strcmp(cmd.argv[0], EXIT_CMD) == 0) {
+                free(cmd._cmd_buffer);
+                send_message_string(cli_socket, "Exiting...\n");
+                send_message_eof(cli_socket);
+                return OK;
+            } else if (strcmp(cmd.argv[0], "stop-server") == 0) {
+                free(cmd._cmd_buffer);
+                send_message_string(cli_socket, "Stopping server...\n");
+                send_message_eof(cli_socket);
+                return OK_EXIT;
+            } else if (strcmp(cmd.argv[0], "cd") == 0) {
+                if (cmd.argc == 1) {
+                    chdir(getenv("HOME"));
+                } else if (cmd.argc == 2) {
+                    if (chdir(cmd.argv[1]) != 0) {
+                        char error_msg[256];
+                        snprintf(error_msg, sizeof(error_msg), "cd: %s\n", strerror(errno));
+                        send_message_string(cli_socket, error_msg);
+                    }
+                } else {
+                    send_message_string(cli_socket, CMD_ERR_PIPE_LIMIT);
+                }
+                send_message_eof(cli_socket);
+                free(cmd._cmd_buffer);
+                continue;
+            }
 
-        // Free memory for each command's buffer
-        for (int i = 0; i < cmd_list.num; i++) {
-            free(cmd_list.commands[i]._cmd_buffer);
+            pid_t pid = fork();
+            if (pid < 0) {
+                perror("fork failed");
+                rc = ERR_MEMORY;
+            } else if (pid == 0) {
+                execvp(cmd.argv[0], cmd.argv);
+                perror("execvp failed");
+                exit(EXIT_FAILURE);
+            } else {
+                int status;
+                wait(&status);
+
+                if (WIFEXITED(status)) {
+                    if (WEXITSTATUS(status) != 0) {
+                        char error_msg[256];
+                        snprintf(error_msg, sizeof(error_msg), "Command failed with exit code %d\n", WEXITSTATUS(status));
+                        send_message_string(cli_socket, error_msg);
+                    }
+                }
+            }
+            free(cmd._cmd_buffer);
         }
+        send_message_eof(cli_socket);
     }
 
-    // Clean up (this will never be reached due to the while(1) loop)
-    free(io_buff);
-    return WARN_RDSH_NOT_IMPL; // Default return value
+    return rc;
 }
 
+
+
 /*
  * send_message_eof(cli_socket)
  *      cli_socket:  The server-side socket that is connected to the client
@@ -384,25 +420,16 @@ int exec_client_requests(int cli_socket) {
  *           we were unable to send the EOF character. 
  */
 
-int send_message_string(int cli_socket, char *buff) {
-    int bytes_sent;
-
-    // Send the message
-    bytes_sent = send(cli_socket, buff, strlen(buff), 0);
-    if (bytes_sent < 0) {
+int send_message_eof(int cli_socket) {
+    if (send(cli_socket, &RDSH_EOF_CHAR, 1, 0) < 0) {
         perror("send");
         return ERR_RDSH_COMMUNICATION;
     }
-
-    // Send the EOF character
-    if (send_message_eof(cli_socket) != OK) {
-        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
-- 
GitLab