/minishell

A simplified version of a unix shell, implemented as a command-line interpreter.

Primary LanguageCMIT LicenseMIT

Linkedin 42

AboutImportant InformationUtilitiesCommand ExamplesNorminetteContributingLicense

ABOUT

The existence of shells is linked to the very existence of IT. At the time, all developers agreed that communicating with a computer using aligned 1/0 switches was seriously irritating. It was only logical that they came up with the idea of creating software to communicate with a computer using interactive lines of commands in a language somewhat close to the human language.

Thanks to Minishell, I travelled through time and came back to problems people faced when Windows didn’t exist. This project was about creating a simple shell, my own little bash. I learned a lot about processes and file descriptors.

IMPORTANT INFORMATION

BEFORE EVALUATION

Check this list before delivering the project.

  • Check the norminette for any errors.
  • Check for segmentation faults, bus errors, double free, leaks, ...
  • Must compile with -Wall, -Wextra and -Werror.
  • Makefile must contain $(NAME), all, clean, fclean.
  • Check for forbidden functions in your code.
  • Check the subject for any other requirements.

NICE TO KNOW

Some nice-to-know commands that will help the evaluatee and the evaluator.

Important Commands Description
make -n Display the compilation information without actually compiling the code.
echo $? Display the exit status of the last executed command.
nm -g ./minishell | grep " U " Check for forbidden functions.
norminette Checks the code for compliance with the coding style and guidelines.
-R CheckForbiddenSourceHeader Check the code in header files.
cc -g -Wall -Wextra -Werror Compile with the mandatory flags.
-fsanitize=address Check for leaks.
-lreadline Necessary to use the readline library.
ps -e or ps -A See all processes currently running on your computer.
ps -a Check for any dead children.

VALGRIND

Important valgrind flags that are necessary to know every single leak.

Valgrind Flags Description
valgrind ./minishell Check for leaks
-leak-check=full Detailed checking for memory leaks.
--show-leak-kinds=all Display all types of memory leaks.
--track-origins=yes Tracks the origins of uninitialized values.
--verbose Increases the level of verbosity.
--gen-suppressions=all Ignore specific known issues or false positives.
--suppressions=readline.supp Specifies the path to a suppression file.
--log-file=memleaks.log Sets the name of the file.

To ignore leaks related to the readline and add_history functions, create a file called readline.supp with the following content:

{
    leak readline
    Memcheck:Leak
    ...
    fun:readline
}
{
    leak add_history
    Memcheck:Leak
    ...
    fun:add_history
}

valgrind --suppressions=readline.supp --leak-check=full --show-leak-kinds=all ./minishell

UTILITIES

Return Values ($?)

The values that a function returns when it completes.

  • All Linux commands return an error code between 0 and 255.
  • The value 0 represents the value true (command success).
  • Values greater than 0 represent false (command failure).
  • The error code of the last command used is contained in the variable $?.
$? Description
1 Standard for general errors, such as a division by zero.
2 Improper use of built-in commands, per Bash documentation.
126 The command called cannot be executed, rights problem or the command is not executable.
127 Command not found, possible problem with $PATH or typing error.
128 Invalid command argument.
128+n 128 + signal number.
130 Finished with Ctrl + C (130 = 128 + 2).
255 Exit code out of bounds. Example: exit -1.

Command Reminders

More nice-to-know commands that may be useful in the future.

Command Description
yes Writes in an infinite loop yes teste.
ln Bind a file or directory.
chmod Change file permissions chmod 777 (all permissions) chmod 000 (no permissions).
cd Change directory. cd - (last visited directory) cd (user directory) cd / (root).
clear Clear the screen.
diff Compare files line by line.
cmp Write the first line of difference between 2 files.
pc Copying files.
rm Delete file.
rm -rf Delete the directory recursively.
ls -l Show the contents of the directory.
exit Exit current process.
grep Search for strings in files grep "printf" file.
mkdir Create a directory.
rmdir Delete a directory.
more Displays a file page by page as in a man.
mv Move or rename.
$PATH Path to executables.
cat Send the file to stdout.

CHMOD

Change the access permissions and the special mode flags of file system objects.

Rights Number
r (read) 4
w (write) 2
x (execute) 1
Rights Calculation Total
--- 0+0+0 0
r-- 4+0+0 4
-w- 0+2+0 2
--x 0+0+1 1
rw- 4+2+0 6
-wx 0+2+1 3
x-ray 4+0+1 5
rwx 4+2+1 7

DATA TYPES

All data types, their size in bytes and the INT MIN and INT MAX range.

Data Types Qualifiers Size (in byte) Range
char char or signed char 1 -128 to 127
char unsigned char 1 0 to 255
int int or signed int 4 -2147483648 to 2147483647
int unsigned int 4 0 to 4294967295
int short int or short signed int 2 -32768 to 32767
int unsigned short int 2 0 to 65535
int long int or signed long int 4 -2147483648 to 2147483647
int unsigned long int 4 0 to 4294967295
float float 4 1.1754e-38 to 3.4028e+38
float double 8 2.2250e-308 to 1.7976e+308
float long double 10 3.4E-4932 to 3.4E+4932

COMMAND EXAMPLES

Some example commands that can be tested on minishell or break it.

Status Definition
🟢 Working.
🟡 Didn't test yet.
🟣 Leaks or segmentation fault.
Weird behaviour.
🔴 Not working.
🔵 Not mandatory.

BLANK

Exploring fundamental commands in Minishell, unravelling the core of shell interactions.

Status Command
🟢 <empty>
🟢 <spaces>
🟢 ../../
🟢 $

SIGNALS

Understanding system signals, showcasing the shell's adaptability in various scenarios.

Status Command
🟢 Ctrl + C
🟢 Ctrl + D
🟢 Ctrl + \
🟢 write something then press + Ctrl + C
🟢 write something then press + Ctrl + D
🟢 write something then press + Ctrl + \
🟢 cat + Ctrl + C
🟢 cat + Ctrl + D
🟢 cat + Ctrl + \
🟢 sleep 5 + Ctrl + C
🟢 sleep 5 + Ctrl + D
🟢 sleep 5 + Ctrl + \

PATH

Managing executable file access by manipulating the system path in Minishell.

Status Command
🟢 /bin/echo
🟢 /bin/grep
🟢 /bin/ls
🟢 /bin/ls -la
🟢 /bin/cat
🟢 /bin/pwd
🟢 /bin/cd
🟢 /bin/export
🟢 /bin/env
🟢 /bin/exit

PWD

Locating the present directory through the pwd command in Minishell.

Status Command
🟢 pwd
🟢 pwd a
🟢 pwd a b c d

EXPORT, ENV AND UNSET

Harnessing environment variables via export, env, and unset commands in Minishell.

Status Command
🟢 ENV
🟢 eNv
🟢 env
🟢 env
🟢 env
🟢 env
🟢 UNSET
🟢 uNsEt
🟢 unset
🟢 unset
🟢 unset
🟢 unset
🟢 unset [variable]
🟢 unset [variable] [variable]
🟢 unset [all variables]
🟢 EXPORT
🟢 eXpOrT
🟢 export
🟢 export
🟢 export
🟢 export
🟢 export a=42
🟢 export a=24
🟢 export b=42
🟢 export a = 42
🟢 export a=" 42 "
🟢 export a=' 42 '
🟢 export a = 42
🟢 export a
🟢 export a=''
🟢 export a='"'
🟢 export a='\'
🟢 export a='$'
🟢 export a='\t'
🟢 export a='''
🟢 export =
🟢 export ==
🟢 export a=
🟢 export a=42=
🟢 export =a=42
🟢 export a==42
🟢 export "a=42"
🟢 export a="42"
🟢 export _=42
🟢 export 42=42
🟢 export a b = 42
🟢 export a= b= 42
🟢 export a=42 % b=42 @ c=42
🟢 export a=42 b=42 c=42
🟢 export A=a B=b C=c D=d E=e
🟢 export F=f G=g H=h I=i J=j
🟢 export K=k L=l M=m N=n O=o
🟢 export P=p Q=q R=r S=s T=t
🟢 export U=u V=v W=w X=x Y=y Z=z
🟢 export _=a; echo $_a

EXIT

Concluding Minishell's operations gracefully using the exit command.

Status Command
🟢 EXIT
🟢 eXiT
🟢 exit
🟢 exit
🟢 exit
🟢 exit
🟢 exit test
🟢 exit "test"
🟢 "exit test"
🟢 "exit"
🟢 exit1
🟢 exita
🟢 exit exit
🟢 exit a
🟢 exit abc
🟢 exit a b c
🟢 exit a b c d
🟢 exit #
🟢 exit *
🟢 exit 0
🟢 exit 1
🟢 exit 123
🟢 exit 1234
🟢 exit 1 2 3 4
🟢 exit +
🟢 exit -
🟢 exit +10
🟢 exit -10
🟢 exit +2000
🟢 exit -2000
🟢 exit +-2000
🟢 exit -+2000
🟢 exit ++2000
🟢 exit --2000
🟢 exit -2147483649
🟢 exit 2147483648
🟢 exit 00000000000000000000
🟢 exit 11111111111111111111
🟢 exit'42'
🟢 exit '\t42'
🟢 exit '\t\f\r 42'
🟢 exit '42 '
🟢 exit '42\t'
🟢 exit '42\r'
🟢 exit '42\t\f\r '
🟢 exit '42 a'
🟢 exit '42\t\t\ta'

CD

Traversing directories seamlessly using the cd command in Minishell.

Status Command
🟢 CD
🟢 cd
🟢 cd
🟢 cd
🟢 cd
🟢 cd .
🟢 cd ~
🟢 cd no_file
🟢 cd1
🟢 cd 0
🟢 cd 1
🟢 cd 123
🟢 cd 1234
🟢 cd 1 2 3 4
🟢 cd cd
🟢 cd a
🟢 cd abc
🟢 cd a b c
🟢 cd a b c d
🟢 cd ../../
🟢 cd ../../../../../../
🟢 cd ../../...
🟢 cd .../../..
🟢 cd .../../...
🟢 cd \
🟢 cd /
🟢 cd //
🟢 cd ///
🟢 cd -
🟢 cd $[VAR]

ECHO

Rendering text and variables in the terminal with the versatile echo command in Minishell.

Status Command
🟢 ECHO
🟢 echO
🟢 ECHo
🟢 echo
🟢 echo echo
🟢 echo
🟢 echo
🟢 echo
🟢 echo .
🟢 echo ~
🟢 echo echo ~
🟢 "echo test"
🟢 echo "~"
🟢 echo '~'
🟢 echo ~123
🟢 echo 123~
🟢 echo ~/123
🟢 echo ~/123/456
🟢 echo #
🟢 echofile
🟢 echo file
🟢 echo no_file
🟢 echo file test
🟢 echo file test
🟢 echo file test file test
🟢 echo a"b"c
🟢 echo "a'b'c
🟢 echo "test"
🟢 echo test
🟢 echo 'test'
🟢 echo -n
🟢 echo -n -n -n -n
🟢 echo -nnnnnnnnnnnnnnnnnnnnnnnn
🟢 echo -n test -n
🟢 "echo" "-n"
🟢 echo -n test
🟢 echo -nn test
🟢 echo -n -n -n test
🟢 echo "-n" test
🟢 echo -n"-n" test
🟢 echo "-nnnn" test
🟢 echo "-n -n -n"-n test
🟢 echo "-n '-n'" test
🟢 echo -n file test
🟢 echo -n -n -n file test
🟢 echo $USER
🟢 echo "$USER"
🟢 echo "'$USER'"
🟢 echo " '$USER' "
🟢 echo text"$USER"
🟢 echo text"'$USER'" ' $USER '
🟢 echo "text" "$USER" "$USER"
🟢 echo ' $USER '
🟢 echo text "$USER" "$USER"text
🟢 echo ''''''''''$USER''''''''''
🟢 echo """"""""$USER""""""""
🟢 echo $USER'$USER'text oui oui oui oui $USER oui $USER ''
🟢 echo $USER '' $USER $USER '' $USER '' $USER -n $USER
🟢 echo ' \' ' \'
🟢 echo '\" ' " \"\""
🟢 echo \\\" \\\" \\\" \\\"\\\"\\\" \\\'\\\'\\\'
🟢 echo "$USER""$USER""$USER"
🟢 echo text"$USER"test
🟢 echo '$USER' "$USER" "text \' text"
🟢 echo '$USER'
🟢 echo $USER " "
🟢 echo "$USER""Users/$USER/file""'$USER'"'$USER'
🟢 echo "$USER$USER$USER"
🟢 echo '$USER'"$USER"'$USER'
🟢 echo '"$USER"''$USER'"""$USER"
🟢 echo " $USER "'$PWD'
🟢 echo " $USER \$ "'$PWD'
🟢 echo $USER=4
🟢 echo $USER=thallard
🟢 echo $USER
🟢 echo $?
🟢 echo $USER213
🟢 echo $USER$12USER$USER=4$USER12
🟢 echo $USER $123456789USER $USER123456789
🟢 echo $USER $9999USER $8888USER $7777USER
🟢 echo $USER $USER9999 $USER8888 $USER7777
🟢 echo $USER $USER9999 $USER8888 $USER7777 "$USER"
🟢 echo "$USER=12$USER"
🟢 echo "$9USER" "'$USER=12$SOMETHING'"
🟢 echo $PWD/file
🟢 echo "$PWD/file
🟢 echo "text" "text$USER" ... "$USER
🟢 echo $PW
🟢 echo "'"'ola'"'"
🟢 echo "'"' ola '"'"

NORMINETTE

At 42 School, it is expected that almost every project is written following the Norm, which is the coding standard of the school.

- No for, do...while, switch, case, goto, ternary operators, or variable-length arrays allowed;
- Each function must be a maximum of 25 lines, not counting the function's curly brackets;
- Each line must be at most 80 columns wide, with comments included;
- A function can take 4 named parameters maximum;
- No assigns and declarations in the same line (unless static);
- You can't declare more than 5 variables per function;
- ...
  • 42 Norms - Information about 42 code norms. PDF
  • Norminette - Tool to respect the code norm, made by 42. GitHub
  • 42 Header - 42 header for Vim. GitHub

CONTRIBUTING

If you find any issues or have suggestions for improvements, feel free to fork the repository and open an issue or submit a pull request.

LICENSE

This project is available under the MIT License. For further details, please refer to the LICENSE file.