This is a shell implementation called Minishell. It is a command-line interpreter that provides a basic shell environment and supports various features such as command execution, input parsing, redirections, pipes, environment variables, built-in commands, and signal handling.
This project was developed in colaboration with teroVF.
Please implement only what the subject explicitly requests. Anything that is not requested is not a requirement, and each additional implementation increases development time and adds unnecessary complexity to the project.
This project has many points of attention that have arisen during development. All of these points have been included in the tests on this page. While not exhaustive, they provide a starting point for things that should work and things that should not. Check the tests
Our reference shell is Bash, but running certain commands in other shells may produce different results and help us better understand why certain things happen. Use Bash as a reference, but be open to examining the workings of other shells.
- Prompt display: Minishell displays a prompt when waiting for a new command.
- Command history: It has a working history feature that allows navigating and reusing previous commands.
- Command execution: Minishell can search and launch the appropriate executable based on the PATH variable or using a relative or absolute path.
- Quoting: It handles single quotes
', preventing the interpretation of meta-characters within the quoted sequence. Double quotes"prevent the interpretation of meta-characters except for the dollar sign$. - Redirections: Minishell supports input
<, output>and append output>>redirections. It also handles here documents<<where input is read until a line containing the specified delimiter. - Pipes: It implements pipes
|to connect the output of one command to the input of the next command in a pipeline. - Environment variables: Minishell handles the expansion of environment variables (
$followed by a sequence of characters) to their respective values. - Special variables: It supports the special variable
$?which expands to the exit status of the most recently executed foreground pipeline. - Signal handling: Minishell handles signals such as
ctrl-C(SIGINT),ctrl-D(EOF), andctrl-\(SIGQUIT) according to the specified behavior in the subject. - Built-in commands: It provides several built-in commands, including
echo,cd,pwd,export,unset,env, andexit, with their respective options and arguments.
- The shell uses the readline library to provide line editing capabilities and command history.
- Input parsing is done using a combination of string manipulation and state tracking to handle quotes and command boundaries.
- Command execution is managed through a commands_manager function that handles the execution of commands, including pipe setup and file descriptor management.
- Built-in commands are implemented as separate functions and are executed within the shell process itself.
- Error handling and reporting are done through a combination of error codes, error messages, and signal handling.
To compile the Minishell program, use the provided Makefile by running make in the project directory. This will generate an executable named minishell.
make
To run the Minishell program, simply execute the generated minishell binary.
./minishell
Once running, you can enter commands and interact with the shell.
- The Libft library is required and provided along with the project files.
- The program was developed and tested on a Unix-based system. Compatibility with other platforms may vary.
- Minishell does not interpret unclosed quotes or special characters that are not required by the subject, such as backslashes
\or semicolons;. - The readline() function used in Minishell may cause memory leaks, but the code written specifically for this project should not have memory leaks.
make -ngcc -Wall -Wextra -Werror -c src/main.c -o obj/main.o
/bin/lsinclude libft Makefile minishell minishell_tester src
dateWed 7 Jul 2021 11:00:00 AM -03
ifconfignetwork information
whowcorrea- tty2 2023-06-20 10:46 (tty2)
[empty]print a new line
[space]print a new line
[tab]do nothing
touch 1 2 3create 3 files
/bin/ls -llist files with details
rm 1 2 3remove 3 files
cat Makefileprint the content of the Makefile
cat -e Makefileprint the content of the Makefile with $ at the end of each line
wc -l Makefile55 Makefile
echoprint a new line
echo This is a testThis is a test
echo -n Hello WorldHello World/home/wcorrea-$
exitexit the minishell
exit 1exit the minishell with return code 1
exit 42exit the minishell with return code 42
exit -42exit the minishell with return code 214
exit 42 10minishell: exit: too many arguments
exit 42schollminishell: exit: numeric argument required; then exit with error code 2
echo $?0
/bin/lsthen run echo $?; the return code is 0
ls notexistthen run echo $?; the return code is 2
/bin/notexistthen run echo $?; the return code is 127
expr $? + $?then run echo $?; the return code is 2
ctrl-C on empty prompt
display a new line with a new prompt
echo $? must display 130
ctrl-\ on empty prompt
do nothing
ctrl-D on empty prompt
quit minishell
echo $? must display 0
ctrl-C after write some stuff
display a new line with a new prompt
echo $? must display 130
ctrl-\ after write some stuff
do nothing
ctrl-D after write some stuff
do nothing
ctrl-C in cat without arguments
^C
echo $? must display 130
ctrl-\ in cat without arguments
\Quit (core dumped)
echo $? must display 131
ctrl-D in cat without arguments
close interactive mode
echo $? must display 0
"/bin/ls"execute ls
""ls""execute ls
""ls -l""execute ls with details
"""ls -l"""minishell: ls -l: command not found
"echo Hello World"minishell: echo Hello World: command not found
echo "Hello World"Hello World
echo "with spaces"Hello World
echo "test with %specials *chars"test with %specials *chars
echo "cat lol.c cat > Iol.c"cat lol.c cat > Iol.c
echo "minishell: unclosed quotes
'/bin/ls'execute ls
''ls''execute ls
''ls -l''execute ls with details
'''ls -l'''minishell: ls -l: command not found
'echo Hello World'minishell: echo Hello World: command not found
echo 'Hello World'Hello World
echo 'with spaces'Hello World
echo '$USER'$USER
echo 'minishell: unclosed quotes
echo '$HOME > home.txt'$HOME > home.txt
echo '$?'$?
envprint the environment variables
env PATHminishell: env: Arguments and options aren't supported
exportprint the exported environment variables
export NEW_VAR=42add NEW_VAR with content 42
export NEW_VAR="A little change"replace the value of NEW_VAR
export NEW_VAR=replace the content of NEW_VAR to empty
export NEW_VAR=$USERreplace the value of NEW_VAR
export NEW_VAR="with unclosed quotesminishell: unclosed quotes
export -p NEW_VARminishell: export: options aren't supported
export NEW_VAR=" -l |"replace the content of NEW_VAR to ' -l |'
unset NEW_VARremove the environment variable
unset -n NEW_VARminishell: unset: options aren't supported
cd .stay in the same directory
cd . lsminishell: cd: too many arguments
cd ..go to the parent directory
cd /usr/bingo to the /usr/bin directory
cdgo to the home directory
cd notexistminishell: cd: notexist: No such file or directory
pwd/home/wcorrea-/workplace/common_core/minishell/minishell
pwd -Lminishell: pwd: options aren't supported
./minishellexecute the minishell inside minishell
../../../../../../bin/lsinclude libft Makefile minishell minishell_tester src
echo $PATH/home/wcorrea-/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
unset PATHremove the PATH environment variable
lsminishell: ls: command not found
export PATH=/bin:/usr/binset the PATH environment variable with the basic path again
ls -l > testcreate a file with the files list inside
cat Makefile >> testappend the content of the Makefile to the file
wc -l < test63
wc -c < test > test_outtest_out receive the number of characters in the file test
cat << EOFstart the here document
cat << EOF | wc -lprint the number of lines in the here document
cat Makefile | grep NAME | wc -l5
cat notexist | wc -lcat: notexist: No such file or directory 0
< Makefile grep NAME | wc -l > output the result in out
up down to navigate in the history
dsfdfdfdminishell: command not found
wc -l < /etc/passwd > file1 > file2 > file3 > file4write the result in the last redirection
cat | cat | lsprint list files and open the interactive mode
echo $USERwcorrea-
echo $notexistprint an empty line
echo "$HOME"/home/wcorrea-
echo ~/home/wcorrea-
echo ~test~test
echo test~test~
echo ~/test/home/wcorrea-/test
$EMPTYVARshow a new prompt line
echo -n -n -n -n -n Hello WorldHello World/home/wcorrea-$
echo -nnnnnnnnn Hello WorldHello World/home/wcorrea-$
echo $HOME.test/home/wcorrea-.test
echo $HOME/test/home/wcorrea-/test
;minishell: no support for operator `;'
*minishell: no support for operator `*'
>minishell: syntax error near unexpected token `newline'
<minishell: syntax error near unexpected token `newline'
< .minishell: syntax error near unexpected token `newline'
>>minishell: syntax error near unexpected token `newline'
<<minishell: syntax error near unexpected token `newline'
|minishell: syntax error near unexpected token `|'
d|minishell: no support for pipe prompt
ls | wc |minishell: no support for pipe prompt
ls | wc >minishell: syntax error near unexpected token `newline'
ls | wc <minishell: syntax error near unexpected token `newline'
ls | wc <<minishell: syntax error near unexpected token `newline'
ls | wc >>minishell: syntax error near unexpected token `newline'
ls | cat << > | wcminishell: syntax error near unexpected token `<< '
export =minishell: export: `=': not a valid identifier
export =testminishell: export: `=test': not a valid identifier
export TEST.=testminishell: export: `TEST.=test': not a valid identifier
export 1TEST=testminishell: export: `1TEST=test': not a valid identifier
export TEST=ABCDcreate a var TEST with content ABCD
export $TEST=1234create a var ABCD with content 1234
export $ABCD=moreminishell: export: `1234=more': not a valid identifier
export a_test b_testcreate tmp vars without content
unset a_testremove the tmp var a_test
export b_test=1234transform the tmp var b_test in a environment var with content 1234
unset b_testremove the environment var b_test
export TEST1="withdouble" TEST2 TEST3=wihoutquotes TEST4="with spaces and expand $USER" TEST5="ok, but it has more" TEST6= TEST7='with single $PATH' = TEST8 9TEST9 TEST10="" TEST11=too=many=equals TEST.12=" " TEST13='withsingle' TEST14/This test will try to create environment vars and tmp vars with different cases. Check the difference with env and export commands
unset TEST1 TEST2 TEST3 TEST4 TEST5 TEST6 TEST7 TEST8 9TEST9 TEST10 TEST11 TEST.12 TEST13 TEST14/unset all these variables that were valid
cd -go to the previous directory
<< EOFstart the here document
> filecreate a file
>> fileappend to a file
- minishell_tester: https://github.com/kichkiro/minishell_tester