42's project, minimal shell
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Fabien Stadelwieser e1eed84ab9
2 years ago
inc pars: ' and \ with $ expantion work 4 years ago
lib/libft lib: norm fix for operator 4 years ago
src pars: separator can now be escapted and quoted 4 years ago
.function_whitelist.txt all: Structure prototyped 4 years ago
.gitignore build: seperate obj files for debug 4 years ago
Makefile build: lib makefile addapted & lib pedantic 4 years ago
README.md Readme 2 years ago
author all: Structure prototyped 4 years ago
bonuslist.txt pars: separator can now be escapted and quoted 4 years ago



A simple posix shell.

$> # type you command here
$> ls
file1 file2
$> ls nofile
$> echo $?
$> cd ..
$> echo $TEST
$> setenv $TEST value
$> echo $TEST
$> exit

A simple workshop for what's to come in 21sh and 42sh.


Compatible Linux and MacOS

git clone ssh://git@git.42l.fr:42084/Fabien/minishell.git
cd minishell

How it works


Normally almost each shell has a script is loaded from a file named : ~/.<shell_name>rc, like .zshrc or .bashrc.

It's not part of this project, and so are the arguments.


In this project the input is fairly simple. You use a function from another project, the infamous get_next_line, 42's getline.

You need a solid get_next_line, many bugs can come from a bad one that have not been written with interactive input in mind.

So you loop over the input (fd -> 0 sometime called stdin). And for each line you do a strsplit on each line, where you split on <space>.

The first "word" is the command for this project, the rest is the argument, you just keep them for later.


If the command have a '/' in it the path is checked, if correct you skip the next step.

Otherwise, you search in the env for a variable called $PATH.

$> echo $PATH

Then for each command search in each directory listed in $PATH.

For ls :

  • No ls in /bin/ls
  • ls is in /usr/bin/ls
  • /home/user/.bin is not checked because ls have already been found

When the executable has been found, a new process is created with fork, the command is run with its argument thanks to execve and the main process wait for its child to finish with wait.

man fork
man execve
man wait


Some command cannot have the desired result in a child process.

One example of this is exiting the shell or modifying the env. Each of those would only affect the child and then return to the parent leaving nothing.

For those cases, shells have something called "builtins" that are not run in the main process.

In our case they are :

  • exit
  • setenv
  • unsetenv
  • cd

These are a builtin for the sake of the exercise, but don't need to be.

  • echo
  • env

Builtin are checked before the command, so if you want to exec /usr/bin/env you need to type /usr/bin/env and simply env for the builtin. man env give you informations about the executable whereas help env, give you info about the builtins. (No help in our case)

Don't forget to store the return value in $? and return this when the shell exit.


  • Non-interactive input (ei: pipe as input)
  • Simple and double quotes [' and "]
  • Backslash [\]
  • Multiline input
  • Signal management (<Ctrl + C> and <Ctrl + \>)
  • Proper signal message and "core dumped"
  • Run on Linux
  • tcsh compatible on the feature-set


Student project for School 42.

Realized by myself in about a week.

Final Grade: 120/125