# 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
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://octave-1.gitbook.io/c-unix/executing-system-commands.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
