Skip to content
Snippets Groups Projects
Select Git revision
  • 22cc652fc63d46a09e214305a5f163559be7daf4
  • main default
  • master
3 results

dshlib.c

Blame
  • vyvyvyThao's avatar
    Wendy Nguyen authored
    22cc652f
    History
    dshlib.c 9.76 KiB
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    #include <stdbool.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/wait.h>
    #include <errno.h>
    #include "dshlib.h"
    
    /*
     * 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()
     */
    
     void printDragon(){
        const char dragon[39][103] = {
    "                                                                        @%%%%                       \n",                       
    "                                                                     %%%%%%                         \n",                         
    "                                                                    %%%%%%                          \n",                          
    "                                                                 % %%%%%%%           @              \n",              
    "                                                                %%%%%%%%%%        %%%%%%%           \n",           
    "                                       %%%%%%%  %%%%@         %%%%%%%%%%%%@    %%%%%%  @%%%%        \n",        
    "                                  %%%%%%%%%%%%%%%%%%%%%%      %%%%%%%%%%%%%%%%%%%%%%%%%%%%          \n",          
    "                                %%%%%%%%%%%%%%%%%%%%%%%%%%   %%%%%%%%%%%% %%%%%%%%%%%%%%%           \n",           
    "                               %%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%     %%%            \n",            
    "                             %%%%%%%%%%%%%%%%%%%%%%%%%%%%@ @%%%%%%%%%%%%%%%%%%        %%            \n",            
    "                            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%                \n",                
    "                            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              \n",              
    "                            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@%%%%%%@              \n",              
    "      %%%%%%%%@           %%%%%%%%%%%%%%%%        %%%%%%%%%%%%%%%%%%%%%%%%%%      %%                \n",                
    "    %%%%%%%%%%%%%         %%@%%%%%%%%%%%%           %%%%%%%%%%% %%%%%%%%%%%%      @%                \n",                
    "  %%%%%%%%%%   %%%        %%%%%%%%%%%%%%            %%%%%%%%%%%%%%%%%%%%%%%%                        \n",                        
    " %%%%%%%%%       %         %%%%%%%%%%%%%             %%%%%%%%%%%%@%%%%%%%%%%%                       \n",                   
    "%%%%%%%%%@                % %%%%%%%%%%%%%            @%%%%%%%%%%%%%%%%%%%%%%%%%                     \n",              
    "%%%%%%%%@                 %%@%%%%%%%%%%%%            @%%%%%%%%%%%%%%%%%%%%%%%%%%%%                  \n",         
    "%%%%%%%@                   %%%%%%%%%%%%%%%           %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              \n",    
    "%%%%%%%%%%                  %%%%%%%%%%%%%%%          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%      %%%%  \n",
    "%%%%%%%%%@                   @%%%%%%%%%%%%%%         %%%%%%%%%%%%@ %%%% %%%%%%%%%%%%%%%%%   %%%%%%%%\n",
    "%%%%%%%%%%                  %%%%%%%%%%%%%%%%%        %%%%%%%%%%%%%      %%%%%%%%%%%%%%%%%% %%%%%%%%%\n",
    "%%%%%%%%%@%%@                %%%%%%%%%%%%%%%%@       %%%%%%%%%%%%%%     %%%%%%%%%%%%%%%%%%%%%%%%  %%\n",
    " %%%%%%%%%%                  % %%%%%%%%%%%%%%@        %%%%%%%%%%%%%%   %%%%%%%%%%%%%%%%%%%%%%%%%% %%\n",
    "  %%%%%%%%%%%%  @           %%%%%%%%%%%%%%%%%%        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%% \n",
    "   %%%%%%%%%%%%% %%  %  %@ %%%%%%%%%%%%%%%%%%          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    %%% \n",
    "    %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%           @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    %%%%%%% \n",
    "     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              %%%%%%%%%%%%%%%%%%%%%%%%%%%%        %%%   \n",
    "      @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                  %%%%%%%%%%%%%%%%%%%%%%%%%               \n",
    "        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                      %%%%%%%%%%%%%%%%%%%  %%%%%%%          \n",
    "           %%%%%%%%%%%%%%%%%%%%%%%%%%                           %%%%%%%%%%%%%%%  @%%%%%%%%%         \n",
    "              %%%%%%%%%%%%%%%%%%%%           @%@%                  @%%%%%%%%%%%%%%%%%%   %%%        \n",
    "                  %%%%%%%%%%%%%%%        %%%%%%%%%%                    %%%%%%%%%%%%%%%    %         \n",
    "                %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                      %%%%%%%%%%%%%%            \n",
    "                %%%%%%%%%%%%%%%%%%%%%%%%%%  %%%% %%%                      %%%%%%%%%%  %%%@          \n",
    "                     %%%%%%%%%%%%%%%%%%% %%%%%% %%                          %%%%%%%%%%%%%@          \n",
    "                                                                                 %%%%%%%@           \n"
        };
    
    
        for (int i = 0; i < sizeof(dragon) / sizeof(dragon[0]); i++) {
            for (int j = 0; j < sizeof(dragon[0]) / sizeof(dragon[0][0]); j++) {
                if (dragon[i][j] == 0) break;
                putchar((char)dragon[i][j]);
            }
        }
    }
    
    int exec_local_cmd_loop()
    {
        char *cmd_buff;
        int rc = 0;
        cmd_buff_t cmd;
    
        // TODO IMPLEMENT MAIN LOOP
    
        // TODO IMPLEMENT parsing input to cmd_buff_t *cmd_buff
        cmd_buff = malloc(SH_CMD_MAX);
        if (!cmd_buff) return ERR_MEMORY;
    
        while(1) {
            printf("%s", SH_PROMPT);
            
            if (fgets(cmd_buff, ARG_MAX, stdin) == NULL) {
                printf("\n");
                break;
            }
    
            // Remove trailing newline
            cmd_buff[strcspn(cmd_buff, "\n")] = '\0';
    
            // Skip empty commands
            if (strlen(cmd_buff) == 0) {
                printf(CMD_WARN_NO_CMD);
                continue;
            }
    
            // Parse command and arguments
            char *exe = strtok(cmd_buff, " ");
            char *args = strtok(NULL, "");
    
    
            if (exe) {
                cmd.argc = 0;
                cmd.argv[cmd.argc++] = exe;
    
                if (args) {
                    char* lastChar = args + strlen(args) - 1;
    
                    // removing space after the
                    while (*lastChar == ' ') {
                        *lastChar = '\0';
                        lastChar--;
                    }
    
                    char *argsNoQuotes = malloc(ARG_MAX);
                    int numQuotes = 0;
                    int argQuoteLength = strlen(args);
                    int argLength = 0;
                    
                    while (*args != '\0') {
                        if (*args == '\"') {
                            numQuotes++;
                            args++;
                        } else {
                            *argsNoQuotes = *args;
                            argLength++;
                            args++;
                            argsNoQuotes++;
                        }
                    }
        
                    argsNoQuotes -= argLength;
                    cmd.argv[cmd.argc++] = argsNoQuotes;
                }
    
                else {
                    cmd.argv[cmd.argc] = NULL;
                }
            }
    
    
            // TODO IMPLEMENT if built-in command, execute builtin logic for exit, cd (extra credit: dragon)
            // the cd command should chdir to the provided directory; if no directory is provided, do nothing
    
            if (strcmp(cmd.argv[0], EXIT_CMD) == 0) {
                break;
    
            } else if (strcmp(cmd.argv[0], "cd") == 0) {
                if (cmd.argv[1]) {
                    if (chdir(cmd.argv[1]) != 0) {
                        perror("cd");
                        rc = ERR_CMD_ARGS_BAD;
                    }
                }
                continue;
    
            } else if (strcmp(cmd.argv[0], "dragon") == 0) {
                printDragon();
                continue;
            }
            else if (strcmp(cmd.argv[0], "rc") == 0) {
                printf("%d\n", rc);
                continue;
            }
            // TODO IMPLEMENT if not built-in command, fork/exec as an external command
            // for example, if the user input is "ls -l", you would fork/exec the command "ls" with the arg "-l"
    
            pid_t pid = fork();
            
            if (pid < 0) {
                // printf(CMD_ERR_EXECUTE);
                return ERR_MEMORY;
            } else if (pid == 0) {
                execvp(cmd.argv[0], cmd.argv);
                // printf(CMD_ERR_EXECUTE);
                exit(errno);
            } else {
                // parent process
                wait(&rc);
                if (WIFEXITED(rc)) {
                    rc = WEXITSTATUS(rc);  // Store last return code
                } else {
                    rc = ERR_EXEC_CMD;
                }
                // wait(NULL);
            }
        }
    }