Skip to content

⌨🐚 - A UNIX command interpreter in C language!

Notifications You must be signed in to change notification settings

DevPacho/simple_shell

Repository files navigation

Meow Shell 🐱 - Shell inside Shell! 🤯

In this repository, you will find a project consisting of the closest possible recreation of a simple UNIX command interpreter in C programming language, that is, a shell of its own.


Ok! but, a Shell? 🤨

Basically, a shell is a command line interpreter, which contains an interface that allows users to execute commands and perform different actions such as file manipulation on UNIX-based operating systems.

Img source: https://opensource.com/article/19/9/getting-started-zsh


Importance of each function 🤝🏻

Each of the files you can see plays an important role for the project, because when all of them are finally compressed (compiled) and form an executable file, it will contain the correct shell operation. Here is a brief description of each one:


File Description
_built-in.c Find the built-in or non-built-in command
_env.c Prints a list of environment variables
_execute.c Execute non-built-ins commands
_exit.c Exits the program
_findpath.c Find the PATH in the environment variables
_freestrs.c Frees the memory occupied by any string
_notfound.c Displays an error when the user input is not a valid command
_printnumber.c Prints an integer
_strcat.c Concatenates two strings
_strcmp.c Compares two strings
_strcpy.c Copies a string
_strlen.c Returns the length of a string
_strtok.c Tokenize strings
shell.c Main shell functionality
shell.h All prototypes of the functions used

How the program works? 🤔📊

Let us consider a flowchart that will help us to understand the operation of the program in a logical way:

Simple-Shell-Flowchart.png


Compilation ⚙️

You can compile the program with gcc and different flags that will check for correct operation, which check for errors, warnings and so on. Here is the complete command:

gcc -Wall -Werror -Wextra -pedantic -std=gnu89 *.c -o shell

shell will be the name of the file that will be created as executable.

In addition, after compiling the program, you can run it with the valgrind tool, which helps in debugging memory and performance problems of a program. For this, we will provide you with the command ready with the respective flags, these serve a similar function to those provided for the previous compilation, to help verify the correct operation of the program in general, as well as to make it portable for different devices. Take it below:

valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --vgdb=no ./shell

Execution examples 🔍️

This shell can be executed in two different ways:

Interactive mode

Running the executable file and accessing it directly:

Non-interactive mode

Without directly accessing the executable file:

Shell-Non-Interactive-mode-example.png


Authors 👨‍💻


Detailed project description 📑

Background Context

Write a simple UNIX command interpreter.

Resources

Read or watch:

man or help:

  • sh (Run sh as well)

Learning Objectives

At the end of this project, you are expected to be able to explain to anyonewithout the help of Google:

General

  • Who designed and implemented the original Unix operating system
  • Who wrote the first version of the UNIX shell
  • Who invented the B programming language (the direct predecessor to the C programming language)
  • Who is Ken Thompson
  • How does a shell work
  • What is a pid and a ppid
  • How to manipulate the environment of the current process
  • What is the difference between a function and a system call
  • How to create processes
  • What are the three prototypes of main
  • How does the shell use the PATH to find the programs
  • How to execute another program with the execve system call
  • How to suspend the execution of a process until one of its children terminates
  • What is EOF / “end-of-file”?

Requirements

General

  • Allowed editors: vivimemacs
  • All your files will be compiled on Ubuntu 20.04 LTS using gcc, using the options -Wall -Werror -Wextra -pedantic -std=gnu89
  • All your files should end with a new line
  • README.md file, at the root of the folder of the project is mandatory
  • Your code should use the Betty style. It will be checked using betty-style.pl and betty-doc.pl
  • Your shell should not have any memory leaks
  • No more than 5 functions per file
  • All your header files should be include guarded
  • Use system calls only when you need to (why?)

More Info

Output

  • Unless specified otherwise, your program must have the exact same output as sh (/bin/sh) as well as the exact same error output.
  • The only difference is when you print an error, the name of the program must be equivalent to your argv[0] (See below)

Example of error with sh :

$ echo "qwerty" | /bin/sh
/bin/sh: 1: qwerty: not found
$ echo "qwerty" | /bin/../bin/sh
/bin/../bin/sh: 1: qwerty: not found
$

Same error with your program hsh :

$ echo "qwerty" | ./hsh
./hsh: 1: qwerty: not found
$ echo "qwerty" | ./././hsh
./././hsh: 1: qwerty: not found
$

List of allowed functions and system calls

  • access (man 2 access)
  • chdir (man 2 chdir)
  • close (man 2 close)
  • closedir (man 3 closedir)
  • execve (man 2 execve)
  • exit (man 3 exit)
  • _exit (man 2 _exit)
  • fflush (man 3 fflush)
  • fork (man 2 fork)
  • free (man 3 free)
  • getcwd (man 3 getcwd)
  • getline (man 3 getline)
  • getpid (man 2 getpid)
  • isatty (man 3 isatty)
  • kill (man 2 kill)
  • malloc (man 3 malloc)
  • open (man 2 open)
  • opendir (man 3 opendir)
  • perror (man 3 perror)
  • read (man 2 read)
  • readdir (man 3 readdir)
  • signal (man 2 signal)
  • stat (__xstat) (man 2 stat)
  • lstat (__lxstat) (man 2 lstat)
  • fstat (__fxstat) (man 2 fstat)
  • strtok (man 3 strtok)
  • wait (man 2 wait)
  • waitpid (man 2 waitpid)
  • wait3 (man 2 wait3)
  • wait4 (man 2 wait4)
  • write (man 2 write)

Compilation

Your shell will be compiled this way:

gcc -Wall -Werror -Wextra -pedantic -std=gnu89 *.c -o hsh

Testing

Your shell should work like this in interactive mode:

$ ./hsh
($) /bin/ls
hsh main.c shell.c
($)
($) exit
$

But also in non-interactive mode:

$ echo "/bin/ls" | ./hsh
hsh main.c shell.c test_ls_2
$
$ cat test_ls_2
/bin/ls
/bin/ls
$
$ cat test_ls_2 | ./hsh
hsh main.c shell.c test_ls_2
hsh main.c shell.c test_ls_2
$

Tasks

0. README, man, AUTHORS

  • Write a README
  • Write a man for your shell.
  • You should have an AUTHORS file at the root of your repository, listing all individuals having contributed content to the repository. Format, see Docker
  • Files: README.md, man_1_simple_shell, AUTHORS

  • 1. Betty would be proud

    Write a beautiful code that passes the Betty checks


    2. Simple shell 0.1

    Write a UNIX command line interpreter.

    • Usage: simple_shell

    Your Shell should:

    • Display a prompt and wait for the user to type a command. A command line always ends with a new line.
    • The prompt is displayed again each time a command has been executed.
    • The command lines are simple, no semicolons, no pipes, no redirections or any other advanced features.
    • The command lines are made only of one word. No arguments will be passed to programs.
    • If an executable cannot be found, print an error message and display the prompt again.
    • Handle errors.
    • You have to handle the “end of file” condition (Ctrl+D)

    You don’t have to:

    • use the PATH
    • implement built-ins
    • handle special characters : "'`\*&#
    • be able to move the cursor
    • handle commands with arguments
    julien@ubuntu:~/shell$ ./shell 
    #cisfun$ ls
    ./shell: No such file or directory
    #cisfun$ /bin/ls
    barbie_j       env-main.c  exec.c  fork.c  pid.c  ppid.c    prompt   prompt.c  shell.c  stat.c         wait
    env-environ.c  exec    fork    mypid   ppid   printenv  promptc  shell     stat test_scripting.sh  wait.c
    #cisfun$ /bin/ls -l
    ./shell: No such file or directory
    #cisfun$ ^[[D^[[D^[[D
    ./shell: No such file or directory
    #cisfun$ ^[[C^[[C^[[C^[[C
    ./shell: No such file or directory
    #cisfun$ exit
    ./shell: No such file or directory
    #cisfun$ ^C
    julien@ubuntu:~/shell$ echo "/bin/ls" | ./shell
    #cisfun$ barbie_j       env-main.c  exec.c  fork.c  pid.c  ppid.c    prompt   prompt.c  shell.c stat.c         wait
    env-environ.c  exec    fork    mypid   ppid   printenv  promptc  shell     stat test_scripting.sh  wait.c
    #cisfun$ julien@ubuntu:~/shell$

    3. Simple shell 0.2

    Simple shell 0.1 +

    • Handle command lines with arguments

    4. Simple shell 0.3

    Simple shell 0.2 +

    • Handle the PATH
    • fork must not be called if the command doesn’t exist
    julien@ubuntu:~/shell$ ./shell_0.3
    :) /bin/ls
    barbie_j       env-main.c  exec.c  fork.c  pid.c  ppid.c    prompt   prompt.c  shell_0.3  stat    test_scripting.sh  wait.c
    env-environ.c  exec    fork    mypid   ppid   printenv  promptc  shell     shell.c    stat.c  wait
    :) ls
    barbie_j       env-main.c  exec.c  fork.c  pid.c  ppid.c    prompt   prompt.c  shell_0.3  stat    test_scripting.sh  wait.c
    env-environ.c  exec    fork    mypid   ppid   printenv  promptc  shell     shell.c    stat.c  wait
    :) ls -l /tmp 
    total 20
    -rw------- 1 julien julien    0 Dec  5 12:09 config-err-aAMZrR
    drwx------ 3 root   root   4096 Dec  5 12:09 systemd-private-062a0eca7f2a44349733e78cb4abdff4-colord.service-V7DUzr
    drwx------ 3 root   root   4096 Dec  5 12:09 systemd-private-062a0eca7f2a44349733e78cb4abdff4-rtkit-daemon.service-ANGvoV
    drwx------ 3 root   root   4096 Dec  5 12:07 systemd-private-062a0eca7f2a44349733e78cb4abdff4-systemd-timesyncd.service-CdXUtH
    -rw-rw-r-- 1 julien julien    0 Dec  5 12:09 unity_support_test.0
    :) ^C
    julien@ubuntu:~/shell$

    5. Simple shell 0.4

    Simple shell 0.3 +

    • Implement the exit built-in, that exits the shell
    • Usage: exit
    • You don’t have to handle any argument to the built-in exit

    6. Simple shell 1.0

    Simple shell 0.4 +

    • Implement the env built-in, that prints the current environment
    julien@ubuntu:~/shell$ ./simple_shell
    $ env
    USER=julien
    LANGUAGE=en_US
    SESSION=ubuntu
    COMPIZ_CONFIG_PROFILE=ubuntu
    SHLVL=1
    HOME=/home/julien
    C_IS=Fun_:)
    DESKTOP_SESSION=ubuntu
    LOGNAME=julien
    TERM=xterm-256color
    PATH=/home/julien/bin:/home/julien/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
    DISPLAY=:0
    $ exit
    julien@ubuntu:~/shell$

    About

    ⌨🐚 - A UNIX command interpreter in C language!

    Topics

    Resources

    Stars

    Watchers

    Forks

    Releases

    No releases published

    Packages

    No packages published

    Languages