#include <stdio.h> #include <stdlib.h> #include <string.h> #include <zlib.h> // For decompression #include "dshlib.h" /* * Implement your main 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. Since we want fgets to also handle * end of file so we can run this headless for testing we need to check * the return code of fgets. I have provided an example below of how * to do this assuming you are storing user input inside of the cmd_buff * variable. * * 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 * * Expected output: * * CMD_OK_HEADER if the command parses properly. You will * follow this by the command details * * CMD_WARN_NO_CMD if the user entered a blank command * CMD_ERR_PIPE_LIMIT if the user entered too many commands using * the pipe feature, e.g., cmd1 | cmd2 | ... | * * See the provided test cases for output expectations. */ #define DRAGON_FILE "dragon.bin" #define DRAGON_BUFFER_SIZE 100000 void print_dragon_from_file() { FILE *file = fopen(DRAGON_FILE, "rb"); if (!file) { fprintf(stderr, "Error: Could not open %s\n", DRAGON_FILE); return; } // Determine the size of the compressed file fseek(file, 0, SEEK_END); long file_size = ftell(file); rewind(file); unsigned char *compressed_data = (unsigned char *)malloc(file_size); if (!compressed_data) { fprintf(stderr, "Memory allocation failed!\n"); fclose(file); return; } // Read the compressed data from the file fread(compressed_data, 1, file_size, file); fclose(file); unsigned char *decompressed_data = (unsigned char *)malloc(DRAGON_BUFFER_SIZE); if (!decompressed_data) { fprintf(stderr, "Memory allocation failed!\n"); free(compressed_data); return; } // Decompress the data uLongf decompressed_size = DRAGON_BUFFER_SIZE; if (uncompress(decompressed_data, &decompressed_size, compressed_data, file_size) != Z_OK) { fprintf(stderr, "Decompression failed!\n"); free(compressed_data); free(decompressed_data); return; } printf("%s", decompressed_data); free(compressed_data); free(decompressed_data); } int main() { char *cmd_buff = (char *)malloc(SH_CMD_MAX * sizeof(char)); if (cmd_buff == NULL) { fprintf(stderr, "Memory allocation failed!\n"); return -1; } command_list_t clist; while (1) { printf("%s", SH_PROMPT); if (fgets(cmd_buff, SH_CMD_MAX, stdin) == NULL) { printf("\n"); break; } // Remove the trailing newline character cmd_buff[strcspn(cmd_buff, "\n")] = '\0'; // Check for empty command if (strlen(cmd_buff) == 0) { printf(CMD_WARN_NO_CMD); continue; } // Exit command if (strcmp(cmd_buff, EXIT_CMD) == 0) { break; } // Check for dragon command if (strcmp(cmd_buff, "dragon") == 0) { print_dragon_from_file(); continue; } // Parse the command line int rc = build_cmd_list(cmd_buff, &clist); if (rc == ERR_TOO_MANY_COMMANDS) { printf(CMD_ERR_PIPE_LIMIT, CMD_MAX); continue; } else if (rc == ERR_CMD_OR_ARGS_TOO_BIG) { fprintf(stderr, "Error: Command or arguments too big.\n"); continue; } // Display parsed commands printf(CMD_OK_HEADER, clist.num); for (int i = 0; i < clist.num; i++) { printf("<%d> %s", i + 1, clist.commands[i].exe); if (strlen(clist.commands[i].args) > 0) { printf(" [%s]", clist.commands[i].args); } printf("\n"); } } free(cmd_buff); return OK; }