---
# System prepended metadata

title: 42 Minishell Eval Prep
tags: [42-minishell]

---

# Global Variable
1. Why need global variable? why is it mandotary?
-> [Global Variable Explained](https://hackmd.io/@QBrv51OvRPqs9dJjL2YIig/r1QGZeWfJl)


---

# Absolute path command
```bash
/bin/cat /etc/hostname

/bin/date

/bin/pwd

* (return value: 1)
/bin/mv /home/user/file.txt /home/user/backup/
```


---

# Echo
```bash
echo
echo -n kekekel
echo -nnnnnnnn kekekke
echo -n-n ekekle -n
echo ekekle -n
echo ekekle -nnnn
echo -n "Hello, World!"
echo -n ""
echo "   Hello World   "
echo    Hello World
echo    Hello World""
echo    Hello World"   "yo
echo -n "Hello, World!"
```

---

# Exit

* LONG MAX / LONG MIN
https://learn.microsoft.com/fr-fr/cpp/cpp/integer-limits?view=msvc-170

   ```bash
   exit
   ```
   ```bash
   exit 0
   ```
   **Expected Outcome:** The shell terminates with exit status `0` (indicating successful completion).

   ```bash
   exit 1
   ```
   **Expected Outcome:** The shell terminates with exit status `1` (indicating an error or failure).
   
   ```bash
   # test_script.sh
   exit 2
   ```

   **Expected Outcome:** The script exits with status `2`.
   ```bash
   exit 999
   ```
   **Expected Outcome:** The exit status will be `999 % 256 = 231`.


   ```bash
   exit -1
   ```
   **Expected Outcome:** The negative number will be treated as a positive number by taking modulo 256. So, `-1 % 256 = 255`, meaning the shell will exit with status `255`.


   ```bash
   exit "error"
   ```
   **Expected Outcome:** Bash will raise a syntax error, as `exit` expects an integer argument.

   ```bash
   exit 300
   ```
   **Expected Outcome:** Exit code `300` is treated as `300 % 256 = 44`. The shell exits with status `44`.

   ```bash
   exit 255
   ```
   **Expected Outcome:** The terminal will close and return exit status `255`.


   ```bash
   echo "Hello" | exit 1
   ```
   **Expected Outcome:** The pipeline will terminate with the exit status of `exit`, in this case, `1`.

```bash
//Test Input
exit 1 j


//Expected bash output
➜  minishell git:(master) ✗ bash --posix
bash-5.1$ exit 1 j
exit
bash: exit: too many arguments
bash-5.1$ exit
exit
➜  minishell git:(master) ✗ echo $?
1
```

```bash
//Test input
exit j 1

// Expected bash output
➜  minishell git:(master) ✗ bash --posix
bash-5.1$ exit j 1
exit
bash: exit: j: numeric argument required
➜  minishell git:(master) ✗ echo $?
2

   ```

*NO NEED HANDLE*
#### `exit` when a script is running in the background:
   Tests how `exit` behaves in a background process.
   ```bash
   (exit 99) &
   ```
   **Expected Outcome:** The background process terminates with exit status `99`. You can check the exit status with `echo $?` (from the foreground shell).

#### `exit` in a nested script (exiting a subshell):
   Tests how `exit` behaves when used inside a subshell.
   ```bash
   (exit 5)
   ```
   **Expected Outcome:** The subshell exits with status `5`, but the parent shell remains unaffected (i.e., the parent shell continues execution or remains open).


---

# Double Quotes / Single Quotes

   ```bash
   echo "cat > lol.c  |  cat > lol.c"
   ```
   ```bash
   echo $USER
   ```
   ```bash
   echo "$USER"
   ```

   ```bash
   echo '$USER'
   ```

   ```bash
   echo "It's a sunny day"
   ```

   ```bash
   echo 'The "quick" fox jumps'
   ```

   ```bash
   echo 'It\'s a test'
   ```
   ```bash
   echo "cat > lol.c"
   ```

   ```bash
   echo 'cat > lol.c'
   ```

   ```bash
   echo "$HOME/.bashrc"
   ```

   ```bash
   echo "echo Hello | grep Hello > output.txt"
   ```

   ```bash
   echo "This is a test: It's a success"
   ```

*NO NEED HANDLE*
```bash
bash-5.1$ echo "The \"quick\" fox"
The "quick" fox


bash-5.1$ echo "The current user is $(whoami)"
The current user is yilin

```
```bash
supershell>$ echo "The \"quick\" fox"
The \quick\ fox

supershell>$ echo "The current user is $(whoami)"
The current user is (whoami)

```


---

# env

*Special Notes (some people may ask):*
```bash
SHLVL=2
```

The `SHLVL` environment variable represents the **shell level**. It indicates the depth of the current shell session in terms of how many times a shell has been invoked.

- A value of `1` typically refers to the initial shell session (i.e., the shell you directly log into).
- A value of `2` means that you've started a new shell from the initial shell (e.g., by running `bash` or `zsh` from within the first shell).
- Each time you start a new shell session (whether it's interactive or not), the `SHLVL` variable is incremented by 1.

So  `SHLVL=2` means you're currently in a second-level shell session (e.g., you're running a shell inside another shell).


---

# export / unset / environment variable
```bash
export
export USER=yilin
export NEW=weshwesh
env
export
echo $USER
echo $NEW
```


---

# cd /pwd


  ```bash
  cd documents
  ```

  ```bash
  cd ..
  ```

  ```bash
  cd ../../
  ```

  ```bash
  cd music
  ```

  ```bash
  cd ../music
  ```

### **2. Absolute Path**

  ```bash
  cd /home/user/documents
  ```

  ```bash
  cd /
  ```

  ```bash
  cd /var/log
  ```

  ```bash
  cd $HOME
  ```

  If `/home/user/My Documents` exists, you can use the absolute path:
  ```bash
  cd "/home/user/My Documents"
  ```

  ```bash
  cd /home/user/shortcut
  ```

### **3. Combining Relative and Absolute Path**

  ```bash
  cd /home/user/documents/projects
  ```


---

# redirec / heredoc


- **Valid: Redirecting output to a file**:
  ```bash
  echo "Hello World" > output.txt
  ```
  This writes "Hello World" into `output.txt`, creating the file if it doesn't exist.

- **Valid: Redirecting output to an existing file (overwrite)**:
  ```bash
  echo "New content" > output.txt
  ```

- **Invalid: Trying to redirect to a directory**:
  ```bash
  echo "This will fail" > /home/user/
  ```
  Error: `bash: /home/user/: Is a directory`.

- **Invalid: Redirecting output without write permission**:
  ```bash
  echo "Some content" > /root/output.txt
  ```
  Error: `bash: /root/output.txt: Permission denied`.


## **Redirection with `>>` (Append Output to a File)**
- **Valid: Appending output to a file**:
  ```bash
  echo "Appended content" >> output.txt
  ```

- **Valid: Appending output to an existing file**:
  ```bash
  echo "More content" >> output.txt
  ```

- **Invalid: Appending to a file without write permissions**:
  ```bash
  echo "This will fail" >> /root/output.txt
  ```
  Error: `bash: /root/output.txt: Permission denied`.

## **Input Redirection with `<` (Read Input from a File)**
- **Valid: Redirecting input from a file**:
  ```bash
  cat < input.txt
  ```
  This takes the content of `input.txt` and sends it to the `cat` command.

- **Invalid: Input redirection from a non-existing file**:
  ```bash
  cat < nonexistentfile.txt
  ```
  Error: `bash: nonexistentfile.txt: No such file or directory`.

- **Valid: Using input redirection in a pipeline**:
  ```bash
  grep "pattern" < input.txt
  ```

## **Heredoc (`<<`)**
- **Valid: Using `<<` for multi-line input**:
  ```bash
  cat <<EOF
  This is a multi-line
  string example
  EOF
  ```

- **Invalid: Misusing `<<` with a missing delimiter**:
  ```bash
  cat <<  # No delimiter specified
  ```

- **Valid: Using `<<` to pass a string to a command**:
  ```bash
  sort <<EOF
  banana
  apple
  orange
  EOF
  ```

- **Invalid: Missing closing delimiter for `<<`**:
  ```bash
  cat <<EOF
  This will cause an error
  ```

### **Heredoc with Variable Expansion (`<<-`)**
- **Valid: Using `<<-` with variable expansion**:
  ```bash
  VAR="Variable Expansion"
  cat <<-EOF
  This is a test for $VAR.
  EOF
  ```

---

# **Pipe (`|`)**
- **Valid: Piping output between commands**:
  ```bash
  ls | grep ".txt"
  ```

- **Valid: Multiple commands piped together**:
  ```bash
  ls | grep ".txt" | sort
  ```

- **Valid: Pipe output through `more`**:
  ```bash
  ls | more
  ```

- **Invalid: Pipe to a non-existent command**:
  ```bash
  ls | non_existent_command
  ```
  Error: `bash: non_existent_command: command not found`.

- **Valid: Using `pipe` with `cat` and `grep`**:
  ```bash
  cat file.txt | grep "pattern"
  ```

- **Invalid: Pipe with a command that expects input**:
  ```bash
  echo "hello" | cat > output.txt | more
  ```
  This doesn't work as expected because `cat` takes input from the pipe and sends it to `output.txt`, so `more` won’t receive the content.

## **Edge Cases:**
- **Pipe with an invalid command in between**:
  ```bash
  ls | non_existent_command | more
  ```
  Error: `bash: non_existent_command: command not found`.

- **Redirection to a file and then pipe**:
  ```bash
  ls > output.txt | grep "pattern"
  ```
  This may not work as expected because the pipe (`|`) executes in the background, while the redirection (`>`) runs in the foreground. The pipe will be executed before the redirection completes.

- **Piping commands with mixed valid and invalid commands**:
  ```bash
  ls | non_existent_command | more
  ```
  The first valid command will execute, but the error for `non_existent_command` will halt the pipeline.

- **Redirecting the output of a command to both a file and the pipe**:
  ```bash
  ls > output.txt | grep ".txt"
  ```
  This syntax won't work as expected, since `> output.txt` overwrites the file first, and the pipe won’t take effect until after the file redirection.

## **Complex Examples:**
- **Valid: Pipe with a valid sequence**:
  ```bash
  cat file.txt | grep "pattern" | sort | more
  ```

- **Valid: Combining input/output redirection with pipes**:
  ```bash
  cat < input.txt | grep "pattern" > output.txt
  ```


---

# Other Important Edge cases! 

## cat | ls related
```bash
cat
//infinite loop
//terminate with ctrl+c
exit
echo $?
```
-> Will cause infinite loop, in minishell can be marked as "Syntax Error"
-> Should be Terminated with Ctrl+C
-> Exit the program with "exit" command
-> Exit code should be 130 (Terminated by signal)

*Need to use ctrl+c to terminate "cat"*
```bash
cat | ls

```
-> **Output:** The same as running **ls**. The contents of the current directory will be displayed.

- cat reads from its standard input (stdin) but doesn't receive any input from a file or terminal in this case.
- The pipe sends cat's output (empty in this case) as input to ls, but ls does not consume stdin.
- ls lists the contents of the current directory.

```bash
cat | cat | ls
```
-> **Output:** The same as running **ls**. The contents of the current directory will be displayed.

- The first cat reads from stdin but doesn't receive input, so it produces no output.
- The second cat receives nothing from the first cat, so it also produces no output.
- ls runs independently of the pipe and lists the contents of the current directory.

```bash
ls | cat
```
-> Output: The output of ls, showing the contents of the current directory, will be displayed.

- ls lists the contents of the current directory, sending its output to the pipe.
- cat reads from the pipe and writes the contents to stdout without modification.

```bash
ls | cat | cat

```
-> Output: The output of ls, showing the contents of the current directory, will be displayed. This is equivalent to ls.
- ls lists the contents of the current directory, sending its output to the first cat.
- The first cat passes the data unchanged to the second cat.
- The second cat writes the data to stdout.

## unset PATH

```bash
unset PATH
```
-> Can only run builtin functions (env, export, unset, cd, exit, echo)