Git Product home page Git Product logo

simple_shell's Introduction

0x16. C - SIMPLE SHELL

C Group project Syscall

Background Context

Write a simple UNIX command interpreter.

Concepts

Resources

man or help:

  • sh (Run sh as well)

Learning Objectives

General

  • Who designed and implemented the original Unix operating system
    The original Unix operating system was designed and implemented by Ken Thompson, Dennis Ritchie, and others at Bell Labs in the early 1970s.

  • Who wrote the first version of the UNIX shell
    The first version of the Unix shell, known as the "Thompson shell" or "sh", was written by Ken Thompson himself

  • Who invented the B programming language (the direct predecessor to the C programming language)
    The B programming language, which was a direct predecessor to the C programming language, was also created by Ken Thompson.

  • Who is Ken Thompson
    Ken Thompson is a computer scientist and one of the key figures in the development of Unix and the C programming language. He is known for his contributions to the original Unix operating system, the creation of the B programming language, and his work on the development of the Plan 9 operating system and the Go programming language.

  • How does a shell work
    A shell is a command-line interpreter that provides an interface for users to interact with the operating system. It reads commands from the user, interprets them, and executes the corresponding programs or actions. The shell also provides features such as input/output redirection, piping, scripting capabilities, and more.

  • What is a pid and a ppid
    In Unix-like operating systems, a PID (Process IDentifier) is a unique numeric identifier assigned to each running process. It is used by the operating system to track and manage processes. PPID (Parent Process IDentifier) refers to the PID of the parent process that created a particular process.

  • How to manipulate the environment of the current process
    To manipulate the environment of the current process in Unix-like systems, you can use environment variables. These variables store information such as paths, settings, and configuration options. You can modify environment variables using commands like export or by directly assigning values to them in shell scripts or programming languages.

  • What is the difference between a function and a system call
    A function is a block of code that performs a specific task and can be called from different parts of a program. It encapsulates a series of instructions and can optionally accept input parameters and return values. A system call, on the other hand, is a request made by a program to the operating system kernel to perform privileged operations or access system resources that are not directly accessible from user space.

  • How to create processes
    Processes can be created in Unix-like systems using system calls like fork() and exec(). The fork() system call creates a new process by duplicating the existing process, while exec() replaces the current process with a new program.

  • What are the three prototypes of main
    The three prototypes of the main function in C are:
    1. int main(void): This version of main takes no command-line arguments.
    2. int main(int argc, char *argv[]): This version of main takes command-line arguments. argc represents the number of arguments, and argv is an array of strings containing the arguments.
    3. int main(int argc, char *argv[], char *envp[]): This version of main takes command-line arguments as well as the environment variables.

  • How does the shell use the PATH to find the programs
    The shell uses the PATH environment variable to find programs when you enter a command. The PATH variable contains a list of directories separated by colons (in Unix-like systems) or semicolons (in Windows). When you enter a command, the shell searches for the corresponding program in each directory listed in PATH from left to right until it finds the executable file or reports an error if it's not found.

  • How to execute another program with the execve system call
    To execute another program with the execve system call in C, you can use the execve() function. It allows you to specify the path to the program, command-line arguments, and the environment variables. The execve() function replaces the current process with the specified program.

  • How to suspend the execution of a process until one of its children terminates
    To suspend the execution of a process until one of its children terminates, you can use the wait() or waitpid() system calls. These calls block the parent process until a child process exits. They also provide information about the child process's termination status, which can be used for further processing.

  • What is EOF / “end-of-file”?
    EOF stands for "end-of-file" and is a special value used to indicate the end of input in many programming languages. It is commonly associated with input/output operations and is returned when there are no more characters to read from a file or an input stream. Programs can check for EOF to determine when to stop reading input.

Requirements

General

  • Allowed editors: vi, vim, emacs
  • 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
  • A 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?)
  • Write a README with the description of your project
  • You should have an AUTHORS file at the root of your repository, listing all individuals having contributed content to the repository. Format, see Docker

GitHub

*There should be one project repository per group. If you and your partner have a repository with the same name in both your accounts, you risk a 0% score. Add your partner as a collaborator. *

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
$

Checks

The Checker will be released at the end of the project (1-2 days before the deadline). We strongly encourage the entire class to work together to create a suite of checks covering both regular tests and edge cases for each task. See task 8. Test suite.

Tasks

0. Betty would be proud

mandatory

Write a beautiful code that passes the Betty checks

1. Simple shell 0.1

mandatory

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

execve will be the core part of your Shell, don’t forget to pass the environ to it…

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
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$

2. Simple shell 0.2

mandatory

Simple shell 0.1 +

  • Handle command lines with arguments

3. Simple shell 0.3

mandatory

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$ 

4. Simple shell 0.4

mandatory

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

5. Simple shell 1.0

mandatory

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$ 

6. Simple shell 0.1.1

#advanced

Simple shell 0.1 +

  • Write your own getline function
  • Use a buffer to read many chars at once and call the least possible the read system call
  • You will need to use static variables
  • You are not allowed to use getline

You don’t have to:

  • be able to move the cursor

7. Simple shell 0.2.1

#advanced

Simple shell 0.2 +

  • You are not allowed to use strtok

8. Simple shell 0.4.1

#advanced

Simple shell 0.4 +

  • handle arguments for the built-in exit
  • Usage: exit status, where status is an integer used to exit the shell
julien@ubuntu:~/shell$ ./shell_0.4.1
$ exit 98
julien@ubuntu:~/shell$ echo $?
98
julien@ubuntu:~/shell$ 

9. setenv, unsetenv

#advanced

Simple shell 1.0 +

Implement the setenv and unsetenv builtin commands

  • setenv
    • Initialize a new environment variable, or modify an existing one
    • Command syntax: setenv VARIABLE VALUE
    • Should print something on stderr on failure
  • unsetenv
    • Remove an environment variable
    • Command syntax: unsetenv VARIABLE
    • Should print something on stderr on failure

10. cd

#advanced

Simple shell 1.0 +

Implement the builtin command cd:

  • Changes the current directory of the process.
  • Command syntax: cd [DIRECTORY]
  • If no argument is given to cd the command must be interpreted like cd $HOME
  • You have to handle the command cd -
  • You have to update the environment variable PWD when you change directory

man chdir, man getcwd

11. ;

#advanced

Simple shell 1.0 +

  • Handle the commands separator ;
alex@~$ ls /var ; ls /var
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
alex@~$ ls /hbtn ; ls /var
ls: cannot access /hbtn: No such file or directory
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
alex@~$ ls /var ; ls /hbtn
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
ls: cannot access /hbtn: No such file or directory
alex@~$ ls /var ; ls /hbtn ; ls /var ; ls /var
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
ls: cannot access /hbtn: No such file or directory
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
alex@~$

12. && and ||

#advanced

Simple shell 1.0 +

  • Handle the && and || shell logical operators
alex@~$ ls /var && ls /var
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
alex@~$ ls /hbtn && ls /var
ls: cannot access /hbtn: No such file or directory
alex@~$ ls /var && ls /var && ls /var && ls /hbtn
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
ls: cannot access /hbtn: No such file or directory
alex@~$ ls /var && ls /var && ls /var && ls /hbtn && ls /hbtn
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
ls: cannot access /hbtn: No such file or directory
alex@~$
alex@~$ ls /var || ls /var
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
alex@~$ ls /hbtn || ls /var
ls: cannot access /hbtn: No such file or directory
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
alex@~$ ls /hbtn || ls /hbtn || ls /hbtn || ls /var
ls: cannot access /hbtn: No such file or directory
ls: cannot access /hbtn: No such file or directory
ls: cannot access /hbtn: No such file or directory
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
alex@~$ ls /hbtn || ls /hbtn || ls /hbtn || ls /var || ls /var
ls: cannot access /hbtn: No such file or directory
ls: cannot access /hbtn: No such file or directory
ls: cannot access /hbtn: No such file or directory
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  spool  tmp
alex@~$

13. alias

#advanced

Simple shell 1.0 +

  • Implement the alias builtin command
  • Usage: alias [name[='value'] ...]
    • alias: Prints a list of all aliases, one per line, in the form name='value'
    • alias name [name2 ...]: Prints the aliases name, name2, etc 1 per line, in the form name='value'
    • alias name='value' [...]: Defines an alias for each name whose value is given. If name is already an alias, replaces its value with value

14. Variables

#advanced

Simple shell 1.0 +

  • Handle variables replacement
  • Handle the $? variable
  • Handle the $$ variable
julien@ubuntu:~/shell$ ./hsh
$ ls /var
backups  cache  crash  lib  local  lock  log  mail  metrics  opt  run  snap  spool  tmp
$ echo $?
0
$ echo $$
5104
$ echo $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
$ exit 
julien@ubuntu:~/shell$ 

15. Comments

#advanced

Simple shell 1.0 +

  • Handle comments (#)
julien@ubuntu:~/shell$ sh
$ echo $$ # ls -la
5114
$ exit
julien@ubuntu:~/shell$ 

16. File as input

#advanced

Simple shell 1.0 +

  • Usage: simple_shell [filename]
  • Your shell can take a file as a command line argument
  • The file contains all the commands that your shell should run before exiting
  • The file should contain one command per line
  • In this mode, the shell should not print a prompt and should not read from stdin

simple_shell's People

Contributors

codenvibes avatar tamaralumumba avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.