A custom Unix-like shell written in C, designed to interpret and execute user commands in both interactive and non-interactive modes, and the shell replicates core functionality of /bin/sh
, demonstrating proficiency in process management, file I/O, memory handling, and environment manipulation.
It's a real-world simulation of how a minimal shell works under the hood. Developed as part of a systems-level programming sprint at ALX Africa
Through this implementation, we explored and applied the following systems programming concepts:
- Architecture and behavior of traditional Unix-based shells.
- The role of process IDs (PID) and parent processes (PPID).
- Execution of external programs using
execve
. - Handling environment variables with
setenv
,unsetenv
, andPATH
resolution. - Differentiating between system calls and C standard library functions.
- Building a responsive prompt that supports both interactive and piped commands.
- Graceful handling of signals and end-of-file (EOF) input.
hsh
currently supports:
- ✅ Interactive shell prompt and non-interactive mode (via piping or file input).
- ✅ Execution of commands with or without arguments.
- ✅ Environment variable resolution using the
PATH
. - ✅ Built-in commands:
exit
,setenv
, andunsetenv
. - ✅ Basic signal handling (e.g.,
Ctrl+D
,Ctrl+C
).
exit
– Close the shell.setenv VARIABLE VALUE
– Set or update environment variables.unsetenv VARIABLE
– Remove environment variables.
All built-ins print a clear error message to
stderr
on failure.
The shell is actively evolving. Key improvements in the pipeline include:
- Built-in
cd
command with full spec support (cd
,cd -
, updatePWD
). - Input/output redirection (
<
,>
) and pipelines (|
). - Support for command chaining using
;
, e.g.,ls /dir1; ls /dir2
. - Command history and basic autocomplete.
elgibbor@ubuntu~$ ./hsh
($) /bin/ls
file1 hsh main.c shell.c
($) exit
elgibbor@ubuntu~$ echo "/bin/ls" | ./hsh
file1 hsh main.c shell.c
elgibbor@ubuntu~$ cat file1
/bin/pwd
elgibbor@ubuntu~$ cat file1 | ./hsh
/home/elgibbor
hsh mirrors /bin/sh
in output and error messaging. The only difference is the name of the executable shown in error messages (i.e., ./hsh
vs /bin/sh
):
$ echo "qwerty" | /bin/sh
/bin/sh: 1: qwerty: not found
$ echo "qwerty" | ./hsh
./hsh: 1: qwerty: not found
Built with passion and frustration by:
We welcome feedback and collaboration. Feel free to fork, open issues, or submit pull requests!