# Assignment: Custom Shell Part 1 - Command Line Parser

This week we will begin the first of a multi-part assignment to build a **custom shell** called `dsh` (Drexel shell).

# What is a Shell?

A "shell" is a type of user interface for interacting with an operating system. You are already familiar with Linux command line shells in this course - the integrated terminal in vscode runs a shell (probably "bash" if you are using any of the Linux virtualization options suggested).

When we say your terminal "runs the bash shell" it means this: a shell is a generalized term for a binary that provides a terminal-based interface; "bash" is the name of a specific shell that you can install and run as a binary. Linux distributions have default shell configurations, and most of them default to `bash`. You can install new shells and use them as your default shell upon login; `zsh` is a popular shell that many users prefer over bash.

The purpose of the shell is to broker inputs and outputs to built-in shell commands, other binaries, and kernel operations like syscalls. When you open a terminal in vscode, the shell is interactive and you must provide inputs by typing in the terminal. Shells are also a part of "headless" processes like cron jobs (in Linux cron jobs run binaries on a schedule automatically, even if you are not logged in); these background jobs still execute in the context of a shell. The shell provides the job the same interface to the operating system, and the job can use the output that the shell brokers.

# Shell built-in vs. external commands

Most "commands" you run are not implemented in the shell logic; they are usually other binaries on the filesystem that are invoked when you refer to them from your shell.

However ... there several (50+) commands that are built in to the logic of the shell itself. Here are some examples:

* cd: change the current working directory
* exit: exit from the shell process
* echo: print text to STDOUT
* export: set environment variable in the current shell

In this assignment, we will implement one "built in" command: `exit`. There is also an optional `dragon` command for extra credit.

Future assignments will generally follow the pattern of other popular shells and implement some of the common builtin commands.

# What else does the shell do?

Beyond implementing built-in commands, a shell acts as a robust broker of input and output. Shells must provide a lot of "glue" to handle streams; for example this is a common sequence you might see in a linux shell: 

```sh
run-some-command | grep "keyword"
```

The `|` symbol is called a pipe, and it serves to stream the output of the first command (`run-some-command`) into the input of the second command (`grep`). We'll implement much of this "glue" logic in future assignments in this course.

# Assignment Details

In this assignment you will implement the first part of `dsh`: a command line parser to interpret commands and their arguments.

You will not implement any command logic, other than exiting when the `exit` command is provided. There is also one optional extra credit for implementing the `dragon` command.

### Step 1 - Review [./starter/dshlib.h](./starter/dshlib.h)

The file [./starter/dshlib.h](./starter/dshlib.h) contains some useful definitions and types. Review the available resources in this file before you start coding - these are intended to make your work easier and more robust!

### Step 2 - Implement [./starter/dsh_cli.c](./starter/dsh_cli.c)

This contains the entrypoint of your shell. Detailed comments are provided to implement `main`.

Shells usually run in a forever loop until a command is issued to exit the shell (usually `exit`); an example is provided in comments to get you started:

```c
    while (1)
    {
        printf("%s", SH_PROMPT);
        if (fgets(cmd_buff, ARG_MAX, stdin) == NULL)
        {
            printf("\n");
            break;
        }
        // remove the trailing \n from cmd_buff
        cmd_buff[strcspn(cmd_buff, "\n")] = '\0';

        // IMPLEMENT THE REST OF THE REQUIREMENTS
    }
```

The libc `fgets` function is a good choice here due to being "lines of input" based. This excerpt from `man 3 fgets` explains why:

> fgets()  reads in at most one less than size characters from stream and stores them into the buffer pointed to by s.  Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer.  A terminating null byte ('\0') is stored after the last character in the buffer.

Key point, `Reading stops after an EOF or a newline` - which makes it essentially a "line by line" processor. This is an important detail for step 3!

### Step 2a - Implement the built-in function `exit`

Inside the main loop in `main()` you can check for and implement the logic for the `exit` command. When this command is issued, your process should exit with a `0` exit code.

This is also similar to how you would implement the extra credit - instead of existing, you would print more output to STDOUT.

### Step 3 - Implement [./starter/dshlib.c](./starter/dshlib.c)

In this file you need to complete the implementation for `build_cmd_list`:

```c
int build_cmd_list(char *cmd_line, command_list_t *clist)
{
    printf(M_NOT_IMPL);
    return EXIT_NOT_IMPL;
}
```

This takes two parameters:

* cmd_line - one complete "line" of user input from the shell; remember `dsh_cli.c` should use EOF / newline (i.e. `fgets()`) to read one line at a time
* clist - pointer to a `command_list_t`; you must populate this structure with parsed commands

Remember - the goal of this assignment is not to implement command logic, but to parse the input string and populate `clist` with parsed commands and their arguments. The comments provide details on logic and references to some helpful definitions.

### Step 4 - Answer Questions

Answer the questions located in [./questions.md](./questions.md).

### Sample Run with Sample Output
The below shows a sample run executing multiple commands and the expected program output:

```bash
➜  solution git:(main) ✗ ./dsh
dsh> cmd
PARSED COMMAND LINE - TOTAL COMMANDS 1
<1> cmd
dsh> cmd_args a1 a2 -a3 --a4
PARSED COMMAND LINE - TOTAL COMMANDS 1
<1> cmd_args [a1 a2 -a3 --a4]
dsh> dragon
[DRAGON for extra credit would print here]
dsh> cmd1 | cmd2
PARSED COMMAND LINE - TOTAL COMMANDS 2
<1> cmd1
<2> cmd2
dsh> cmda1 a1 a2 | cmda2 a3 a4 | cmd3 
PARSED COMMAND LINE - TOTAL COMMANDS 3
<1> cmda1 [a1 a2]
<2> cmda2 [a3 a4]
<3> cmd3
dsh> 
warning: no commands provided
dsh> c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
PARSED COMMAND LINE - TOTAL COMMANDS 8
<1> c1
<2> c2
<3> c3
<4> c4
<5> c5
<6> c6
<7> c7
<8> c8
dsh> c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c9
error: piping limited to 8 commands
dsh> pipe1|pipe2|pipe3 |pipe4             
PARSED COMMAND LINE - TOTAL COMMANDS 4
<1> pipe1
<2> pipe2
<3> pipe3
<4> pipe4
dsh> pipe1|pipe2 |pipe3 pipe4| pipe5
PARSED COMMAND LINE - TOTAL COMMANDS 4
<1> pipe1
<2> pipe2
<3> pipe3 [pipe4]
<4> pipe5
dsh> exit
➜  solution git:(main) ✗
```

### Extra Credit: +5

Add logic to detect the command "`dragon`" and print the Drexel dragon in ascii art.

Drexel dragon in ascii with spaces preserved:

```
                                                                        @%%%%                       
                                                                     %%%%%%                         
                                                                    %%%%%%                          
                                                                 % %%%%%%%           @              
                                                                %%%%%%%%%%        %%%%%%%           
                                       %%%%%%%  %%%%@         %%%%%%%%%%%%@    %%%%%%  @%%%%        
                                  %%%%%%%%%%%%%%%%%%%%%%      %%%%%%%%%%%%%%%%%%%%%%%%%%%%          
                                %%%%%%%%%%%%%%%%%%%%%%%%%%   %%%%%%%%%%%% %%%%%%%%%%%%%%%           
                               %%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%     %%%            
                             %%%%%%%%%%%%%%%%%%%%%%%%%%%%@ @%%%%%%%%%%%%%%%%%%        %%            
                            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%                
                            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              
                            %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%@%%%%%%@              
      %%%%%%%%@           %%%%%%%%%%%%%%%%        %%%%%%%%%%%%%%%%%%%%%%%%%%      %%                
    %%%%%%%%%%%%%         %%@%%%%%%%%%%%%           %%%%%%%%%%% %%%%%%%%%%%%      @%                
  %%%%%%%%%%   %%%        %%%%%%%%%%%%%%            %%%%%%%%%%%%%%%%%%%%%%%%                        
 %%%%%%%%%       %         %%%%%%%%%%%%%             %%%%%%%%%%%%@%%%%%%%%%%%                       
%%%%%%%%%@                % %%%%%%%%%%%%%            @%%%%%%%%%%%%%%%%%%%%%%%%%                     
%%%%%%%%@                 %%@%%%%%%%%%%%%            @%%%%%%%%%%%%%%%%%%%%%%%%%%%%                  
%%%%%%%@                   %%%%%%%%%%%%%%%           %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              
%%%%%%%%%%                  %%%%%%%%%%%%%%%          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%      %%%%  
%%%%%%%%%@                   @%%%%%%%%%%%%%%         %%%%%%%%%%%%@ %%%% %%%%%%%%%%%%%%%%%   %%%%%%%%
%%%%%%%%%%                  %%%%%%%%%%%%%%%%%        %%%%%%%%%%%%%      %%%%%%%%%%%%%%%%%% %%%%%%%%%
%%%%%%%%%@%%@                %%%%%%%%%%%%%%%%@       %%%%%%%%%%%%%%     %%%%%%%%%%%%%%%%%%%%%%%%  %%
 %%%%%%%%%%                  % %%%%%%%%%%%%%%@        %%%%%%%%%%%%%%   %%%%%%%%%%%%%%%%%%%%%%%%%% %%
  %%%%%%%%%%%%  @           %%%%%%%%%%%%%%%%%%        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  %%% 
   %%%%%%%%%%%%% %%  %  %@ %%%%%%%%%%%%%%%%%%          %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    %%% 
    %%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%           @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    %%%%%%% 
     %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%              %%%%%%%%%%%%%%%%%%%%%%%%%%%%        %%%   
      @%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                  %%%%%%%%%%%%%%%%%%%%%%%%%               
        %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                      %%%%%%%%%%%%%%%%%%%  %%%%%%%          
           %%%%%%%%%%%%%%%%%%%%%%%%%%                           %%%%%%%%%%%%%%%  @%%%%%%%%%         
              %%%%%%%%%%%%%%%%%%%%           @%@%                  @%%%%%%%%%%%%%%%%%%   %%%        
                  %%%%%%%%%%%%%%%        %%%%%%%%%%                    %%%%%%%%%%%%%%%    %         
                %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%                      %%%%%%%%%%%%%%            
                %%%%%%%%%%%%%%%%%%%%%%%%%%  %%%% %%%                      %%%%%%%%%%  %%%@          
                     %%%%%%%%%%%%%%%%%%% %%%%%% %%                          %%%%%%%%%%%%%@          
                                                                                 %%%%%%%@       
```

### Extra Credit: ++5

Implement the extra credit for the `/dragon` using compressed/binary data in your code to represent the dragon (i.e. not just using strings/defines).

#### Grading Rubric

This assignment will be weighted 50 points.

- 25 points:  Correct implementation of required functionality
- 5 points:  Code quality (how easy is your solution to follow)
- 15 points: Answering the written questions: [questions.md](./questions.md)
- 5 points:  [EXTRA CREDIT] Implementation of the `dragon` command
- 5 points:  [EXTRA CREDIT++] Implementation of the `dragon` command where the representation of the dragon is compressed in your code

Total points achievable is 60/50. 

#### Automated Testing

In order to help you out the starter package provides a testing script called `test.sh`.  You should expect your tests to fail when running the starter and then start to pass as you implement the required functionality.  Also note a few of the test cases are commented out.