How I Built a Simple Shell in C – A Beginner’s Guide to System Programming (2/3)

Part 2: Parsing User Input in a Custom Shell (C Programming)

In this part of my custom shell project, I will explain how to parse user input dynamically in C. Parsing the input correctly is crucial in a shell environment, as commands often i…


This content originally appeared on DEV Community and was authored by Ertugrul

Part 2: Parsing User Input in a Custom Shell (C Programming)

In this part of my custom shell project, I will explain how to parse user input dynamically in C. Parsing the input correctly is crucial in a shell environment, as commands often include multiple arguments. Instead of relying on fixed-size buffers, I implemented a dynamic memory allocation approach for better flexibility.

Understanding the parser Function

The function parser() is responsible for:
✅ Splitting the user command into arguments dynamically

✅ Managing memory allocation and reallocation efficiently

✅ Returning an array of arguments for further processing

Breaking Down the Code

#ifndef PARSER_H
#define PARSER_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define arg_buffer_size 4

char **parser(char *command, int *argc);
void free_args(char **args, int argc);

#endif
  • Header Guard (#ifndef PARSER_H): Prevents multiple inclusions.
  • Constant Definition (arg_buffer_size): Sets an initial buffer size for argument storage.
  • Function Prototypes: Declares the parser() function for splitting the input and free_args() for memory cleanup.

Implementation of parser()

char **parser(char *command, int *argc)
{
    int size = arg_buffer_size;
    int length = 0;
    char **args = malloc(size * sizeof(char *));
  • Memory Allocation (malloc): Allocates memory for an array of strings.
  • Error Handling: Although not explicitly shown, malloc should be checked to prevent failures.
    *argc = 0;
    char *token = strtok(command, " ");
    while (token)
    {
        if (*argc >= size)
        {
            size *= 2;
            args = realloc(args, size * sizeof(char *));
        }
        args[*argc] = strdup(token);
        (*argc)++;
        token = strtok(NULL, " ");
    }
    args[*argc] = NULL;
    return args;
}
  1. Tokenizing the Input

    • Uses strtok() to break the input into separate arguments.
    • Iterates over each token and stores it dynamically.
  2. Expanding Memory Dynamically (realloc)

    • If the argument count exceeds the allocated size, the buffer is doubled.
    • realloc() attempts to resize the buffer safely.
  3. Storing Arguments

    • Each token is duplicated using strdup() to avoid memory corruption.
    • The last argument is set to NULL for proper command execution.

Cleaning Up Memory

void free_args(char **args, int argc)
{
    for (int i = 0; i < argc; i++)
    {
        free(args[i]);
    }
    free(args);
}
  • Prevents Memory Leaks: Frees each argument and the overall array to ensure efficient memory management.

Integrating the Parser with the Shell

The parser() function is integrated into the shell’s main loop, allowing commands to be properly processed.

int main(void)
{
    Command commands[] = {
        {"help", help_action},
        {"clr", clear_action},
        {"say", say_action},
        {"exit", exit_action},
        {"cwp", cwp_command},
        {"date", date_command},
        {"clone", clone_file_command},
        {"cut", cut_file_command},
        {"read", read_file_command},
        {"del", delete_file_command},
        {"open", open_program_command},
        {"list", list_of_directory}};

    int command_count = sizeof(commands) / sizeof(commands[0]);
    while (1)
    {
        int argc;
        printf("shell_of_mine => ");
        char *command = read_command();
        char **args = parser(command, &argc);
        execute_command(args, argc, commands, command_count);
        free_args(args, argc);
        free(command);
    }
    return 0;
}
  • Main Loop: Continuously reads, parses, and executes user commands.
  • Dynamic Parsing: The parser extracts arguments dynamically, allowing flexible command handling.
  • Memory Cleanup: free_args() ensures allocated memory is released after execution.

Why This Approach?

📌 Handles Arbitrary Command Lengths: Unlike static arrays, dynamic allocation ensures flexibility.

📌 Efficient Memory Management: Uses realloc() to optimize memory usage dynamically.

📌 Prevents Buffer Overflow: Eliminates fixed-size limitations that could lead to errors.

Next Part: Executing Commands 🚀

In the next part, I will explain how the shell executes parsed commands using system calls and function pointers. Stay tuned! 😊

📂 GitHub: https://github.com/Ertugrulmutlu/shell_of_mine

What do you think about this approach? Would you handle parsing differently? Let me know in the comments! 👇


This content originally appeared on DEV Community and was authored by Ertugrul


Print Share Comment Cite Upload Translate Updates
APA

Ertugrul | Sciencx (2025-02-18T11:42:37+00:00) How I Built a Simple Shell in C – A Beginner’s Guide to System Programming (2/3). Retrieved from https://www.scien.cx/2025/02/18/how-i-built-a-simple-shell-in-c-a-beginners-guide-to-system-programming-2-3/

MLA
" » How I Built a Simple Shell in C – A Beginner’s Guide to System Programming (2/3)." Ertugrul | Sciencx - Tuesday February 18, 2025, https://www.scien.cx/2025/02/18/how-i-built-a-simple-shell-in-c-a-beginners-guide-to-system-programming-2-3/
HARVARD
Ertugrul | Sciencx Tuesday February 18, 2025 » How I Built a Simple Shell in C – A Beginner’s Guide to System Programming (2/3)., viewed ,<https://www.scien.cx/2025/02/18/how-i-built-a-simple-shell-in-c-a-beginners-guide-to-system-programming-2-3/>
VANCOUVER
Ertugrul | Sciencx - » How I Built a Simple Shell in C – A Beginner’s Guide to System Programming (2/3). [Internet]. [Accessed ]. Available from: https://www.scien.cx/2025/02/18/how-i-built-a-simple-shell-in-c-a-beginners-guide-to-system-programming-2-3/
CHICAGO
" » How I Built a Simple Shell in C – A Beginner’s Guide to System Programming (2/3)." Ertugrul | Sciencx - Accessed . https://www.scien.cx/2025/02/18/how-i-built-a-simple-shell-in-c-a-beginners-guide-to-system-programming-2-3/
IEEE
" » How I Built a Simple Shell in C – A Beginner’s Guide to System Programming (2/3)." Ertugrul | Sciencx [Online]. Available: https://www.scien.cx/2025/02/18/how-i-built-a-simple-shell-in-c-a-beginners-guide-to-system-programming-2-3/. [Accessed: ]
rf:citation
» How I Built a Simple Shell in C – A Beginner’s Guide to System Programming (2/3) | Ertugrul | Sciencx | https://www.scien.cx/2025/02/18/how-i-built-a-simple-shell-in-c-a-beginners-guide-to-system-programming-2-3/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.