Skip to content
Snippets Groups Projects
Select Git revision
  • 14afdd0a99b79f7eefa91f8822746eac68134e7d
  • main default
2 results

dshlib.c

Blame
  • Ziheng Chen's avatar
    Ziheng Chen authored
    badaea57
    History
    dshlib.c 3.59 KiB
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    
    #include "dshlib.h"
    
    /*
     *  build_cmd_list
     *    cmd_line:     the command line from the user
     *    clist *:      pointer to clist structure to be populated
     *
     *  This function builds the command_list_t structure passed by the caller
     *  It does this by first splitting the cmd_line into commands by spltting
     *  the string based on any pipe characters '|'.  It then traverses each
     *  command.  For each command (a substring of cmd_line), it then parses
     *  that command by taking the first token as the executable name, and
     *  then the remaining tokens as the arguments.
     *
     *  NOTE your implementation should be able to handle properly removing
     *  leading and trailing spaces!
     *
     *  errors returned:
     *
     *    OK:                      No Error
     *    ERR_TOO_MANY_COMMANDS:   There is a limit of CMD_MAX (see dshlib.h)
     *                             commands.
     *    ERR_CMD_OR_ARGS_TOO_BIG: One of the commands provided by the user
     *                             was larger than allowed, either the
     *                             executable name, or the arg string.
     *
     *  Standard Library Functions You Might Want To Consider Using
     *      memset(), strcmp(), strcpy(), strtok(), strlen(), strchr()
     */
    
    /*
     * Helper function to trim leading and trailing spaces
     */
    void trim_whitespace(char *str) {
        char *end;
    
        // Trim leading space
        while (isspace((unsigned char)*str)) str++;
    
        if (*str == 0) return; // Empty string
    
        // Trim trailing space
        end = str + strlen(str) - 1;
        while (end > str && isspace((unsigned char)*end)) end--;
    
        // Write new null terminator
        *(end + 1) = '\0';
    }
    
    /*
     *  build_cmd_list
     *    cmd_line:     the command line from the user
     *    clist *:      pointer to clist structure to be populated
     */
    int build_cmd_list(char *cmd_line, command_list_t *clist)
    {
        
        if (cmd_line == NULL || strlen(cmd_line) == 0) {
            return WARN_NO_CMDS;
        }
    
        // Initialize command list
        memset(clist, 0, sizeof(command_list_t));
    
        char *token;
        char *rest = cmd_line;
        int cmd_count = 0;
    
        // Split input line by pipes (`|`)
        while ((token = strtok_r(rest, PIPE_STRING, &rest))) {
            if (cmd_count >= CMD_MAX) {
                return ERR_TOO_MANY_COMMANDS;  // return the error
            }
    
            // Trim leading and trailing spaces
            trim_whitespace(token);
    
            // Check if command is too large
            if (strlen(token) >= SH_CMD_MAX) {
                return ERR_CMD_OR_ARGS_TOO_BIG; // return the error
            }
    
            // Split command into executable and arguments
            char *cmd_part = strtok(token, " ");
            if (cmd_part == NULL) {
                continue;  // Skip empty commands
            }
    
            // Store the executable name
            strncpy(clist->commands[cmd_count].exe, cmd_part, EXE_MAX - 1);
            clist->commands[cmd_count].exe[EXE_MAX - 1] = '\0';
    
            // Store the arguments
            char *arg_buffer = clist->commands[cmd_count].args;
            arg_buffer[0] = '\0';
    
            cmd_part = strtok(NULL, " ");
            while (cmd_part) {
                strncat(arg_buffer, cmd_part, ARG_MAX - strlen(arg_buffer) - 1);
                strncat(arg_buffer, " ", ARG_MAX - strlen(arg_buffer) - 1);
                cmd_part = strtok(NULL, " ");
            }
    
            // Remove trailing space from arguments
            trim_whitespace(arg_buffer);
    
            cmd_count++;
        }
    
        clist->num = cmd_count;
        return OK;
    
        
        //printf(M_NOT_IMPL);
        //return EXIT_NOT_IMPL;
    }