Select Git revision
dsh_cli.c 4.59 KiB
#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;
}