Allowed functions:
Library | Functions | Use |
---|---|---|
libreadline |
readline, rl_clear_history, rl_on_new_line, rl_replace_line, rl_redisplay, add_history | Functions for command line editing and history manipulation, enhancing user interactivity. |
libc |
printf, malloc, free, write, access, open, read, close, fork, wait, waitpid, wait3, wait4, signal, sigaction, kill, exit | Core functions for process handling and input/output operations. |
libc |
getcwd, chdir, stat, lstat, fstat, unlink, execve, dup, dup2, pipe | Functions for file and directory manipulation, as well as program execution. |
libc |
opendir, readdir, closedir | Functions for directory manipulation. |
libc |
strerror, perror | Functions for error management, translating error codes into readable messages. |
libc |
isatty, ttyname, ttyslot, ioctl | Functions for terminal device manipulation. |
libc |
getenv | Retrieves the value of an environment variable. |
libc |
tcsetattr, tcgetattr | Functions for configuring and obtaining terminal attributes. |
libc |
tgetent, tgetflag, tgetnum, tgetstr, tgoto, tputs | Functions for advanced terminal manipulation, useful in creating text-based user interfaces. |
Shell should:
- Display a prompt for user input while awaiting a new command.
- Implement a functional history mechanism.
- Search for and execute the appropriate executable, considering the PATH variable or specifying a relative or absolute path.
- Limit the use of global variables to a single instance for signal reception. This approach ensures that the signal handler does not access primary data structures.
- Exercise caution; the global variable should only convey the received signal number, providing no other information or data access. Thus, incorporating "norm" type structures in the global scope is forbidden.
- Refrain from interpreting unclosed quotes or unnecessary special characters like \ (backslash) or ; (semicolon).
- Manage ' (single quote) to prevent the shell from interpreting meta-characters within the quoted sequence.
- Manage " (double quote) to prevent the shell from interpreting meta-characters within the quoted sequence, with the exception of $ (dollar sign).
Implement redirections:
<
should redirect input.>
should redirect output.<<
should be given a delimiter, then read the input until a line containing the delimiter is seen. However, it doesn’t have to update the history!>>
should redirect output in append mode.
Implement pipes |
:
- The output of each command in the pipeline is connected to the input of the next command via a pipe
Environment variables $
:
- ($ followed by a sequence of characters) which should expand to their values.
Handle $?
:
- Should expand to the exit status of the most recently executed foreground pipeline.
Handle ctrl-C, ctrl-D and ctrl-:
- Behave like in bash. If interactive mode:
- ctrl-C displays a new prompt on a new line.
- ctrl-D exits the shell.
- ctrl-\ does nothing.
Builtins:
- echo with option -n
- cd with only a relative or absolute path
Absolute path -> $ cat /home/user/documents/file.txt
Relative path -> $ cd /home/user $ cat documents/file.txt
- pwd with no options
- export with no options
- unset with no options
- env with no options or arguments
- exit with no options
Builtin | Description | Options | Parameters | Helpful Functions |
---|---|---|---|---|
echo |
Prints arguments separated with a space followed by a new line | -n |
✔️ | write |
cd |
Changes current working directory, updating PWD and OLDPWD |
❌ | ✔️ | chdir |
pwd |
Prints current working directory | ❌ | ❌ | getcwd |
export |
Adds/replaces variable in environment | ❌ | ✔️ | ❌ |
unset |
Removes variable from environment | ❌ | ✔️ | ❌ |
env |
Prints environment | ❌ | ❌ | write |
@madebypixel02 credits for the table info!
@m4nnb3ll credits for the image!
What is Bash? How does it work?
A shell is a program that allows users to interact with the services of an operating system. Bash, the GNU shell, is presently the most widely used shell program. We approached the task of recreating bash quite literally, and our initial step involved understanding the inner workings of bash.
To do so, these are recommended readings.
Great examples of shell building.
Awesome videos to check.
- Bash in 100 Seconds
- What Happens When You Type a Command in Your Terminal
- Where GREP Came From
- Parsing
- UNIX Pipeline
Essentially it breaks down the process into 4 steps: lexer → parser → expander → executor, which we replicated in our project.
@maiadegraaf credits for the image!
1. Lexer aka tokenizer
Reads the line word by word, utilizing white space as delimiters. Initially, it verifies whether the word is a token, such as |, <, <<, >, or >>
. Otherwise, it assumes the string is a regular word.
2. Parser
Then parser recieves the parameters, and distributes the different nodes together based on the tokens. Each group becomes a command.
@maiadegraaf credits for the image!
With a loop we will go through the previous arguments given by the Lexer until it finds a pipe (|
). It then takes all the nodes before the pipe as one command, and creates a node in the struct. If it doesn't find a pipe it takes all the (remaining) nodes as one command.
- Separations
- Pipes
- Command and arguments
- Protections
- Redirections
<, >, >>
- Environment variables
3. Expander
Before a node from t_simple_cmds is handled it is expanded. The expander takes variables, identified by $, and replaces them with their value from the environment variables. Such that $USER becomes mgraaf
, and $?
is replaced with the exit code.
4. executor
- Redirections
- Env, export, unset
- Exit and
$?
- Pipe/signal/process links
include/
Libs.srcs/
Our program.main/
The sauce!utils/
Supporting cast.