Skip to content

crackedmob/miniShellInC

Repository files navigation

miniShellInC

A custom Unix shell implemented in C from scratch, supporting both interactive and non-interactive execution modes. Built to replicate core Bash shell behaviour using low-level POSIX system calls.


Features

  • Interactive & Non-Interactive modes — detects whether input is coming from a terminal or a script/pipe and behaves accordingly via isatty()
  • External command execution — runs any system command (ls, cat, gcc, etc.) by forking a child process and using execvp()
  • Built-in commands — implements cd, env, help, and exit natively without spawning a child process
  • Process management — uses fork() + waitpid() with WUNTRACED to correctly wait for child processes and handle termination via exit or signal
  • Error handling — graceful error reporting for invalid commands, failed forks, failed execvp(), and missing cd arguments

Limitations

  • Piping (|) is not supported
  • Output redirection (>) is not supported
  • These are planned for a future implementation

Architecture

miniShellInC/
├── main.c                    # Entry point — detects interactive vs non-interactive mode
├── shell.h                   # Header — all prototypes, macros, and includes
├── shell_interactive.c       # REPL loop — prompt, read, parse, execute, repeat
├── shell_no_interactive.c    # Script mode — reads stdin line by line until EOF
├── execute_args.c            # Dispatcher — routes to built-ins or new_process()
├── new_process.c             # Process creation — fork(), execvp(), waitpid()
├── own_cd.c                  # Built-in cd — wraps chdir() with error handling
├── own_exit.c                # Built-in exit — exits shell with optional status code
├── own_env.c                 # Built-in env — prints all environment variables
└── own_help.c                # Built-in help — prints usage information

Execution flow:

User Input → read_line() → split_line() → execute_args() → built-in OR new_process()

How to Compile and Run

Requirements: GCC, Linux/Unix environment (or WSL on Windows)

# Clone the repository
git clone https://github.com/crackedmob/miniShellInC.git
cd miniShellInC

# Compile
gcc -Wall -Wextra -Werror *.c -o myshell

# Run interactively
./myshell

# Run non-interactively (script mode)
echo "ls" | ./myshell

Usage Examples

# Navigate directories
$ cd /home/user/documents
$ cd ..

# Run external commands
$ ls -la
$ cat file.txt
$ gcc main.c -o program

# View environment variables
$ env

# Get help
$ help

# Exit the shell
$ exit
$ exit 1

Implementation Notes

  • Built-in commands are dispatched via two parallel arrays — one of command name strings, one of function pointers — keeping the dispatcher clean and easily extensible
  • cd must be a built-in because a child process changing its directory would not affect the parent shell's working directory
  • waitpid() with WUNTRACED ensures the parent shell correctly waits for child processes that exit normally or are killed by a signal
  • execvp() is used over execve() to leverage PATH resolution automatically
  • getline() is used over fgets() for dynamic buffer allocation, handling input of any length safely
  • Tokenization uses strtok() with TOK_DELIM to handle spaces, tabs, and newlines

What I Learned

  • Low-level process lifecycle management using fork(), exec(), and waitpid()
  • Why certain commands like cd must be built into the shell at the OS level
  • How shells distinguish between interactive and non-interactive input via isatty()
  • Function pointer arrays as a clean dispatch pattern in C
  • Dynamic memory management with getline() and realloc()

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages