DEV Community

Ertugrul
Ertugrul

Posted on

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

Part 1: Reading User Input in a Custom Shell (C Programming)

In this part of my custom shell project, I will explain how to read user input dynamically in C. Handling user input properly is crucial in a shell environment, as commands can vary in length. Instead of using fixed-size buffers, I implemented a dynamic memory allocation approach for better flexibility.


Understanding the read_command Function

The function read_command() is responsible for:
✅ Reading input from the user dynamically
✅ Handling memory allocation & reallocation to avoid buffer overflow
✅ Ensuring proper termination of the input string

Breaking Down the Code

#ifndef READ_COMMAND_H
#define READ_COMMAND_H

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

#define INT_BUFFER_SIZE 32  // Initial buffer size

char *read_command();

#endif
Enter fullscreen mode Exit fullscreen mode
  • Header Guard (#ifndef READ_COMMAND_H): Prevents multiple inclusions.

  • Constant Definition (INT_BUFFER_SIZE): Sets an initial buffer size for input storage.


Implementation of read_command()

char *read_command()
{
    char *command = malloc(INT_BUFFER_SIZE * sizeof(char));
    if (!command)
    {
        perror("Memory allocation failed");
        exit(EXIT_FAILURE);
    }
Enter fullscreen mode Exit fullscreen mode
  • Memory Allocation (malloc): Initially allocates INT_BUFFER_SIZE bytes for storing user input.

  • Error Handling: If malloc fails, the program prints an error and exits.

int size = INT_BUFFER_SIZE;
    int length = 0;
    int c;
Enter fullscreen mode Exit fullscreen mode
  • size: Keeps track of the current buffer size.
  • length: Tracks the actual number of characters read.
  • c: Stores the input character retrieved from getchar().

Handling Dynamic Input Growth

while ((c = getchar()) != '\n' && c != EOF)
{
    if (length >= (size - 1))
    {
        size *= 2;  // Double the buffer size when needed
        char *new_command = realloc(command, (size + 1));
        if (!new_command)
        {
            free(command);
            perror("Memory reallocation failed");
            exit(EXIT_FAILURE);
        }
        command = new_command;
    }
    command[length++] = c;
}
Enter fullscreen mode Exit fullscreen mode
  1. Expanding Memory Dynamically (realloc)

    • If input exceeds the allocated size, the buffer is doubled (size *= 2).
    • realloc attempts to resize the buffer; if it fails, memory is freed, and an error is displayed.
  2. Storing Characters

    • Each character from getchar() is stored sequentially in command[length++]

Finalizing the Input

command[length] = '\0';  // Null-terminate the string
return command;
Enter fullscreen mode Exit fullscreen mode
  • Null-Termination (\0): Ensures that the string is properly terminated so it can be processed as a valid C string.

  • **Returning the Input: **The function returns the dynamically allocated string for further use.


Why This Approach?

📌 Avoids Buffer Overflow: Unlike scanf or gets, this method expands dynamically as needed.
📌 Efficient Memory Management: realloc optimizes memory allocation instead of pre-allocating a large chunk.
📌 Better Flexibility: Can handle long commands without arbitrary limitations.


Next Part: Parsing Command 🚀

In the next part, I will explain how the shell parses user input and executes commands using system functions. Stay tuned! 😊

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

What do you think about this approach? Would you have handled input differently? Let me know in the comments! 👇

Quadratic AI

Quadratic AI – The Spreadsheet with AI, Code, and Connections

  • AI-Powered Insights: Ask questions in plain English and get instant visualizations
  • Multi-Language Support: Seamlessly switch between Python, SQL, and JavaScript in one workspace
  • Zero Setup Required: Connect to databases or drag-and-drop files straight from your browser
  • Live Collaboration: Work together in real-time, no matter where your team is located
  • Beyond Formulas: Tackle complex analysis that traditional spreadsheets can't handle

Get started for free.

Watch The Demo 📊✨

Top comments (0)

Image of Stellar post

Check out Episode 1: How a Hackathon Project Became a Web3 Startup 🚀

Ever wondered what it takes to build a web3 startup from scratch? In the Stellar Dev Diaries series, we follow the journey of a team of developers building on the Stellar Network as they go from hackathon win to getting funded and launching on mainnet.

Read more

👋 Kindness is contagious

Engage with a wealth of insights in this thoughtful article, valued within the supportive DEV Community. Coders of every background are welcome to join in and add to our collective wisdom.

A sincere "thank you" often brightens someone’s day. Share your gratitude in the comments below!

On DEV, the act of sharing knowledge eases our journey and fortifies our community ties. Found value in this? A quick thank you to the author can make a significant impact.

Okay