42shell is a project in the Codam curriculum requiring you to build a shell with all basic functionality, plus a choice of six extra features.
The seven extra features we have built are:
- Complete management of quoting ✓
- Tab completion for built-ins, command, and files in current directory ✓
- Hash table for executables ✓
- test builtin ✓
- Arithmetic expansion using
$(())
✓ - Command substitution using
$()
✓ - Process substitution using
<()
and>()
✓ (BONUS)
Anything labeled with (BONUS)
is not required by the project subject.
You can download a pre-compiled binary for Arch, Debian or Ubuntu if you trust our CI build jobs:
[DIRECT DOWNLOAD LINKS]
Compilation has been tested on MacOS Mojave, Debian, Ubuntu, and Arch linux, and requires the following dependencies:
To compile the shell, run the following commands:
$> meson build
$> cd build
$> ninja
The compiled executable will be called ./cetushell
.
Optionally, you can install Criterion and run ninja test
to compile and run a limited set of tests.
To start the shell, run ./cetushell
.
42shell will initialize a minimal environment if it receives an empty environment.
This shell currently has the following features:
- Command execution based on
PATH
- Hashing of executable names in hashtable, with corresponding
hash
builtin - Non-interactive mode through redirection of input OR a file as argument (BONUS)
- Support for comments using
#
. Aything after a#
until the next newline is ignored. (BONUS) - Internal shell + environment variables, including assignment through assignment words, expansion (using
$KEY
or${KEY}
) and support for read-only - Changing the shell prompt by modifying the shell variable
PS1
- Pipes (including completion of pipes(BONUS))
- Redirections (>, <, >>, <<, >&, <&)
- Command history using
arrow up
andarrow down
(using$HISTFILE
&$HISTSIZE
, supports newlines(BONUS)) - Contextual
tab
completion with support for files, directories, executables, and shell/environment variables. - Arithmetic expansion using
$((expr))
, with support for variables and nesting with$((40 + $((2))))
and decimal, hex, and octal numbers. - Command substitution using
$(command)
, with full support for anything supported in non-interactive mode. - Process substitution using
>(command)
to redirect to the process or<(command)
to redirect from the command. - Quotes (
"
,'
and\
), including in heredocs and the heredoc end word (i.e.EOF
) - The operators
&&
and||
to chain multiple complete commands - Job control including the required builtins (see below) and
job_spec
which supports these formats:%-
: matches previous job%+
: matches current job%n
matches job with job idn
%string
: matches any job that begins withstring
%?string
: matchs any job that containsstring
- Command line control:
arrow keys
to move left and right,ctrl + arrow keys
to move per word or line- shift + arrow keys left and right to select
ctrl+b
to copy,ctrl+x
to cut,ctrl+v
to paste.
cd [-P|-L|'-'] [PATH]
: change directory toPATH
, or home ifPATH
is not iven.-P
will update$PWD
to absolute path ifPATH
contained symlinks-L
will update$PWD
to relative path ifPATH
contained symlinks default)-
changes to previous directory (stored in$OLDPWD
)
echo
: supports-n
(BONUS) to ommit trailing newlinehash [-r|-i|COMMAND[=PATH]]
: manage the command hash tablejobs [-p|-l] [job_spec ...]
: print status of jobs.-p
only prints the pgid of the job.-l
always print long output with details per process
fg [job_spec]
: but job in foreground. ifjob_spec
is ommited,%+
is assumed.bg [job_spec ...]
: but all given jobs in foreground. ifjob_spec
is ommited, %+` is assumed.set
: print all variables (shell and environment)unset [KEY ...]
: unset all instances of everyKEY
in shell and environment ariablesexport [-p|KEY[=VALUE] ...]
: export everyKEY
from the shell to the nvironment, or add it th the environment withVALUE
if specified.-p
will print all environment variables in a valid format to export all of hem.
setenv
: see--help
for options and syntax (BONUS)unsetenv
: see--help
for options and syntax (BONUS)setshell
: see--help
for options and syntax (BONUS)unsetshell
: see--help
for options and syntax (BONUS)exit [exit_code]
: exit the shell. exit code will beexit_code
if given, or ost recent status code. ($?
)type [COMMAND ...]
: prints type/location of everyCOMMAND
.test
with support for[ expr ]
(BONUS) and!
, and the following operators:-a
: True if file exists. (BONUS)-b
: True if file exists and is a block special file.-c
: True if file exists and is a character special file.-d
: True if file exists and is a directory.-e
: True if file exists.-f
: True if file exists and is a regular file.-g
: True if file exists and its set-group-id bit is set.-h
: True if file exists and is a symbolic link. (BONUS)-L
: True if file exists and is a symbolic link.-p
: True if file exists and is a named pipe (FIFO).-r
: True if file exists and is readable.-S
: True if file exists and is a socket.-s
: True if file exists and has a size greater than zero.-u
: True if file exists and its set-user-id bit is set.-w
: True if file exists and is writable.-x
: True if file exists and is executable.-z
: True if the length of string is zero.-n
: True if the length of string is non-zero. (BONUS) str1 OP str2: Arg1 and arg2 are strings, where OP can be:=
: True if the strings are equal.==
: True if the strings are equal. (BONUS)!=
: True if the strings are not equal. int1 OP int2: Arg1 and arg2 may be positive or negative integers, where OP can e:-eq
: True if arg1 is equal to arg2.-ne
: True if arg1 is not equal to arg2.-gt
: True if arg1 is greater than arg2. (BONUS)-ge
: True if arg1 is greater than or equal to arg2.-lt
: True if arg1 is less than arg2.-le
: True if arg1 is less than or equal to arg2.