> For the complete documentation index, see [llms.txt](https://documentation.hak5.org/packet-squirrel-mark-ii/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.hak5.org/packet-squirrel-mark-ii/advanced-payloads/return-codes-and-success.md).

# Return codes & success

## Checking command success

When commands exit, they set a hidden variable called the `return code`. &#x20;

Typically, a return code of `0` indicates success, while a return code of any other number indicates failure.

This mechanism is used by most command-line tools in Linux, not just the Ducky Script commands!

Some commands may use return code values to indicate the exact error, while others may simply return `0` or non-zero to indicate success or failure.

### Running multiple commands

To run multiple commands, requiring each command succeeds, the `&&` operator can be used.

Each of these commands will only run if the previous command completed successfully.

```bash
#!/bin/bash

BUTTON 5 && LED G SOLID
```

The `LED` command will only be run if the user presses the button within 5 seconds.

### Handling success and failure

To take actions based on success or failure of a command, you can combine the `&&` and `||` options.

When a command succeeds, the code in the `&&` block is executed.  When a command fails, the code in the `||` block is executed.

To demonstrate this, we'll use the `BUTTON` Ducky Script command.  `BUTTON` takes an optional number of seconds to wait; if the user presses the button within that timeout, a successful return code is set, if the user does not press the button within that timeout, an error return code is set.

```bash
#!/bin/bash

BUTTON 5 && {
    echo "The button was pressed!";
    LED G SOLID;
} || {
    echo "The button wasn't pressed!";
    LED R SOLID;
}
```

Notice how we are able to chain `&&` and `||` to handle both success and failure.

The `{` and `}` blocks allow us to group multiple commands.

### Reading the return code

The return code of the last command run is stored in the Bash variable `$?`

```bash
#!/bin/bash

# Try to list a directory that doesn't exist
ls /i-dont-exist

# Echo the return code (which will be 1)
echo $?

# List a file that does exist
ls /root

# The return code is now 0
echo $?
```

### Setting a return code

Return codes are set in scripts and functions via the `exit` or `return` codes.  When creating your own helper scripts and functions, you can use this to propagate an error code up to the caller.  When writing a *script* use the `exit` call, but when writing a *function* use the `return` call!

```bash
function do_something() {
    if [ "$1" != "do-the-thing" ]; then
        # Non-zero means error
        return 1
    else
        # Do the things
        return 0
    fi
}

do_something && echo "This will never print"
do_something do-the-thing && echo "This will print now"
```

We're now able to determine if a function succeeded or failed.  We can also use error codes within the function itself to determine if a command we ran succeeded or failed, for example:

```bash
function check_dir() {
    if [ ! -d "$1" ]; then
        return 1
    else
        return 0
    fi
}

check_dir "/usb/some_data_dir" || LED R SINGLE
```

{% hint style="warning" %}
Make sure to use `return` in a function, otherwise the entire script will exit!
{% endhint %}
