> For the complete documentation index, see [llms.txt](https://octave-1.gitbook.io/c-unix/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://octave-1.gitbook.io/c-unix/executing-system-commands.md).

# Executing system commands

[Link to exec function manual](https://man7.org/linux/man-pages/man3/exec.3.html)

Before we begin

{% code fullWidth="false" %}

```c
#include <errno.h>

int main(int argc, char* argv[], char* envp[]){

    // argc = argument count
    // argv = argument vector
    // envp = environment pointer
    
    // errno stores the error code (if any) of the process in which the main thread is running

    return errno;
}
```

{% endcode %}

Let's first create a program to add any number of integers that are passed as arguments.

{% code title="add.c" fullWidth="false" %}

```c
#include <stdio.h>
#include <math.h>
#include <string.h>

int str_to_int(char* c){
    int x = 0;
    int n = strlen(c);
    for(int i=0;i<n;i++)
        x += (c[i] - 48)*pow(10,n-i-1);
    return x;
}

int main(int argc, char* argv[]){
    int sum = 0;
    for(int i=1;i<argc;i++)
        sum += str_to_int(argv[i]);
    printf("Sum = %d",sum);
    return 0;
}
```

{% endcode %}

Now let's execute this program using certain arguments that are specified within the program itself.

{% code fullWidth="false" %}

```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(){
    // this command is for compilation purpose only
    system("gcc add.c -o add -lm");

    // returns the status code of the process
    int exc = execl(
        "./add",  // path to the executable
        "./add",  // path to the executable (again)
        // now we pass all the arguments
        "11",
        "22",
        "7",
        "120",
        NULL  // don't forget to pass the NULL pointer (mandatory)
    );
    
    // if the exec function runs properly without any exceptions, then this line will not be executed and the program will terminate
    printf("Process finished with code %d\n",exc);
    return 0;
}
```

{% endcode %}

## Output

```
Sum = 160
```

Note: We can't have more than one exec command in a program since the program will terminate on successful execution of the first exec function call that it encounters.

Another way we can do this is using the **execvp** function where we pass the list of arguments as an array.

```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(){
    // this command is for compilation purpose only
    system("gcc add.c -o add -lm");

    char* args[] = {"./add","11", "22", "7", "120", NULL};

    // returns the status code of the process
    int exc = execvp(
        "./add",  // path to the executable
        args  // now we pass all the arguments
    );
    
    // if the exec function runs properly without any exceptions, then this line will not be executed and the program will terminate
    printf("Process finished with code %d\n",exc);
    return 0;
}
```

## Output

```
Sum = 160
```

In case we want to execute a program from a path stored in ENVIRONMENT variables, we can use the **execvp** function.

Example:

```c
#include <stdio.h>
#include <unistd.h>

int main(){
    char* args[] = {"ping","google.com"};

    // returns the status code of the process
    int exc = execvp("ping",args);
    
    // if the exec function runs properly without any exceptions, then this line will not be executed and the program will terminate
    printf("Process finished with code %d\n",exc);
    return 0;
}
```

Or we can just use the **execl** function

```c
#include <stdio.h>
#include <unistd.h>

int main(){
    int exc2 = execl(
        "/usr/bin/ping",
        "/usr/bin/ping",
        "google.com",
        NULL
    );
    printf("Process finished with code %d\n",exc2);
    return 0;
}
```

## Output

In all cases the outputs are the same

```
PING google.com (172.217.166.78) 56(84) bytes of data.
64 bytes from bom05s15-in-f14.1e100.net (172.217.166.78): icmp_seq=1 ttl=112 time=48.9 ms
64 bytes from bom05s15-in-f14.1e100.net (172.217.166.78): icmp_seq=2 ttl=112 time=48.7 ms
64 bytes from bom05s15-in-f14.1e100.net (172.217.166.78): icmp_seq=3 ttl=112 time=49.5 ms
64 bytes from bom05s15-in-f14.1e100.net (172.217.166.78): icmp_seq=4 ttl=112 time=86.9 ms
^C
--- google.com ping statistics ---
11 packets transmitted, 11 received, 0% packet loss, time 10014ms
rtt min/avg/max/mdev = 48.659/56.520/91.104/15.352 ms
```
