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