Skip to content
Snippets Groups Projects
Commit 966b801e authored by Joey Le's avatar Joey Le
Browse files

Fixed dshlib.c

parent 4143e2cd
No related branches found
No related tags found
No related merge requests found
...@@ -6,10 +6,11 @@ ...@@ -6,10 +6,11 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <errno.h>
#include "dshlib.h" #include "dshlib.h"
// Function to build a command buffer from a command line
int build_cmd_buff(char *cmd_line, cmd_buff_t *cmd_buff) { int build_cmd_buff(char *cmd_line, cmd_buff_t *cmd_buff) {
if (cmd_line == NULL || cmd_buff == NULL) { if (cmd_line == NULL || cmd_buff == NULL) {
return ERR_CMD_OR_ARGS_TOO_BIG; return ERR_CMD_OR_ARGS_TOO_BIG;
...@@ -29,7 +30,7 @@ int build_cmd_buff(char *cmd_line, cmd_buff_t *cmd_buff) { ...@@ -29,7 +30,7 @@ int build_cmd_buff(char *cmd_line, cmd_buff_t *cmd_buff) {
char quote_char = '\0'; char quote_char = '\0';
while (*ptr != '\0') { while (*ptr != '\0') {
if ((isspace((unsigned char)*ptr) && !in_quotes)) { if ((isspace((unsigned char)*ptr) && !in_quotes) {
if (arg_start != NULL) { if (arg_start != NULL) {
*ptr = '\0'; *ptr = '\0';
cmd_buff->argv[cmd_buff->argc++] = arg_start; cmd_buff->argv[cmd_buff->argc++] = arg_start;
...@@ -59,18 +60,11 @@ int build_cmd_buff(char *cmd_line, cmd_buff_t *cmd_buff) { ...@@ -59,18 +60,11 @@ int build_cmd_buff(char *cmd_line, cmd_buff_t *cmd_buff) {
cmd_buff->argv[cmd_buff->argc] = NULL; cmd_buff->argv[cmd_buff->argc] = NULL;
// Debugging output to verify parsing
// printf("Parsed command:\n");
// for (int i = 0; i < cmd_buff->argc; i++) {
// printf(" argv[%d]: %s\n", i, cmd_buff->argv[i]);
// }
return OK; return OK;
} }
char *trim_whitespace(char *str) { //Had to make a new function for readability // Function to trim whitespace from a string
char *trim_whitespace(char *str) {
char *end; char *end;
while (isspace((unsigned char)*str)) str++; while (isspace((unsigned char)*str)) str++;
...@@ -82,15 +76,13 @@ char *trim_whitespace(char *str) { //Had to make a new function for readability ...@@ -82,15 +76,13 @@ char *trim_whitespace(char *str) { //Had to make a new function for readability
end = str + strlen(str) - 1; end = str + strlen(str) - 1;
while (end > str && isspace((unsigned char)*end)) end--; while (end > str && isspace((unsigned char)*end)) end--;
// new null terminator // New null terminator
*(end + 1) = '\0'; *(end + 1) = '\0';
return str; return str;
} }
// Function to parse a pipeline of commands
int parse_pipeline(const char *cmd_line, command_list_t *clist) { int parse_pipeline(const char *cmd_line, command_list_t *clist) {
if (cmd_line == NULL || clist == NULL) { if (cmd_line == NULL || clist == NULL) {
return ERR_CMD_OR_ARGS_TOO_BIG; return ERR_CMD_OR_ARGS_TOO_BIG;
...@@ -100,7 +92,8 @@ int parse_pipeline(const char *cmd_line, command_list_t *clist) { ...@@ -100,7 +92,8 @@ int parse_pipeline(const char *cmd_line, command_list_t *clist) {
if (line_copy == NULL) { if (line_copy == NULL) {
return ERR_MEMORY; return ERR_MEMORY;
} }
//Parsing using pipe.
// Parsing using pipe
clist->num = 0; clist->num = 0;
char *saveptr; char *saveptr;
char *command = strtok_r(line_copy, "|", &saveptr); char *command = strtok_r(line_copy, "|", &saveptr);
...@@ -126,23 +119,12 @@ int parse_pipeline(const char *cmd_line, command_list_t *clist) { ...@@ -126,23 +119,12 @@ int parse_pipeline(const char *cmd_line, command_list_t *clist) {
return OK; return OK;
} }
// Function to execute a pipeline of commands
int execute_pipeline(command_list_t *clist) { int execute_pipeline(command_list_t *clist) {
int num_commands = clist->num; int num_commands = clist->num;
int pipefd[2 * (num_commands - 1)]; int pipefd[2 * (num_commands - 1)];
pid_t pids[num_commands]; pid_t pids[num_commands];
// for (int i = 0; i < clist->num; i++) {
// printf("Command %d:\n", i);
// for (int j = 0; clist->commands[i].argv[j] != NULL; j++) {
// printf(" argv[%d]: %s\n", j, clist->commands[i].argv[j]);
// }
// }
for (int i = 0; i < num_commands - 1; i++) { for (int i = 0; i < num_commands - 1; i++) {
if (pipe(pipefd + 2 * i) == -1) { if (pipe(pipefd + 2 * i) == -1) {
perror("pipe"); perror("pipe");
...@@ -159,7 +141,7 @@ int execute_pipeline(command_list_t *clist) { ...@@ -159,7 +141,7 @@ int execute_pipeline(command_list_t *clist) {
} }
if (pids[i] == 0) { // Child process if (pids[i] == 0) { // Child process
// if not first moves input // Redirect input if not the first command
if (i > 0) { if (i > 0) {
if (dup2(pipefd[2 * (i - 1)], STDIN_FILENO) == -1) { if (dup2(pipefd[2 * (i - 1)], STDIN_FILENO) == -1) {
perror("dup2 stdin"); perror("dup2 stdin");
...@@ -175,7 +157,7 @@ int execute_pipeline(command_list_t *clist) { ...@@ -175,7 +157,7 @@ int execute_pipeline(command_list_t *clist) {
} }
} }
// Close all pipe file descriptors. Very important stuff // Close all pipe file descriptors
for (int j = 0; j < 2 * (num_commands - 1); j++) { for (int j = 0; j < 2 * (num_commands - 1); j++) {
close(pipefd[j]); close(pipefd[j]);
} }
...@@ -187,12 +169,12 @@ int execute_pipeline(command_list_t *clist) { ...@@ -187,12 +169,12 @@ int execute_pipeline(command_list_t *clist) {
} }
} }
// Closes all pipe // Close all pipe file descriptors in the parent
for (int i = 0; i < 2 * (num_commands - 1); i++) { for (int i = 0; i < 2 * (num_commands - 1); i++) {
close(pipefd[i]); close(pipefd[i]);
} }
// waitpid so everyhting is smooth // Wait for all child processes to finish
for (int i = 0; i < num_commands; i++) { for (int i = 0; i < num_commands; i++) {
int status; int status;
waitpid(pids[i], &status, 0); waitpid(pids[i], &status, 0);
...@@ -206,97 +188,55 @@ int execute_pipeline(command_list_t *clist) { ...@@ -206,97 +188,55 @@ int execute_pipeline(command_list_t *clist) {
return OK; return OK;
} }
static void start_server() { // Main loop for executing local commands
int listen_socket; int exec_local_cmd_loop() {
int ret; char cmd_buff[SH_CMD_MAX];
int rc = OK;
}
/****
**** 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 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) { while (1) {
printf("rsh> "); printf("%s", SH_PROMPT);
if (!fgets(cmd_buff, RDSH_COMM_BUFF_SZ, stdin)) {
break; // Exit on input error or EOF if (fgets(cmd_buff, SH_CMD_MAX, stdin) == NULL) {
printf("\n");
break;
} }
// Remove the newline character from the command cmd_buff[strcspn(cmd_buff, "\n")] = '\0';
size_t cmd_len = strlen(cmd_buff);
if (cmd_len > 0 && cmd_buff[cmd_len - 1] == '\n') { if (strlen(cmd_buff) == 0) {
cmd_buff[cmd_len - 1] = '\0'; printf("%s\n", CMD_WARN_NO_CMD);
rc = WARN_NO_CMDS;
continue;
} }
// Handle local commands (e.g., cd, exit) if (strstr(cmd_buff, "|") != NULL) {
if (strncmp(cmd_buff, "cd", 2) == 0) { command_list_t cmd_list;
// Handle cd locally if (parse_pipeline(cmd_buff, &cmd_list) != OK) {
fprintf(stderr, "%s\n", CMD_ERR_PIPE_LIMIT);
rc = ERR_TOO_MANY_COMMANDS;
continue;
}
rc = 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 {
cmd_buff_t cmd; cmd_buff_t cmd;
if (build_cmd_buff(cmd_buff, &cmd) != OK) { if (build_cmd_buff(cmd_buff, &cmd) != OK) {
fprintf(stderr, "%s\n", CMD_ERR_PIPE_LIMIT); fprintf(stderr, "%s\n", CMD_ERR_PIPE_LIMIT);
rc = ERR_MEMORY;
continue; 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) { if (cmd.argc == 1) {
chdir(getenv("HOME")); chdir(getenv("HOME"));
} else if (cmd.argc == 2) { } else if (cmd.argc == 2) {
...@@ -308,35 +248,30 @@ static void start_server() { ...@@ -308,35 +248,30 @@ static void start_server() {
} }
free(cmd._cmd_buffer); free(cmd._cmd_buffer);
continue; continue;
} else if (strncmp(cmd_buff, "exit", 4) == 0) {
break; // Exit the remote shell
} }
// Send the command to the server pid_t pid = fork();
ssize_t sent_bytes = send(cli_socket, cmd_buff, strlen(cmd_buff), 0); if (pid < 0) {
if (sent_bytes < 0) { perror("fork failed");
perror("send"); rc = ERR_MEMORY;
return client_cleanup(cli_socket, NULL, NULL, ERR_RDSH_COMMUNICATION); } else if (pid == 0) {
} execvp(cmd.argv[0], cmd.argv);
perror("execvp failed");
exit(EXIT_FAILURE);
} else {
int status;
wait(&status);
// Receive the server's response if (WIFEXITED(status)) {
is_eof = 0; if (WEXITSTATUS(status) != 0) {
while ((recv_bytes = recv(cli_socket, rsp_buff, RDSH_COMM_BUFF_SZ, 0)) > 0) { fprintf(stderr, "Command failed with exit code %d\n", WEXITSTATUS(status));
printf("%.*s", (int)recv_bytes, rsp_buff); }
if (rsp_buff[recv_bytes - 1] == RDSH_EOF_CHAR) {
is_eof = 1;
break;
} }
} }
if (recv_bytes < 0) { free(cmd._cmd_buffer);
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 client_cleanup(cli_socket, NULL, NULL, OK); return rc;
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment