1

I'm trying to save my arguments and their parameters from the command line as follows

./run cat hello.txt : grep left : wc -c

I want to seperate each argument in an array as follows withouth knowing the number of :

char *cat_args[] = {"cat", "tests/nevermind", NULL};
char *grep_args[] = {"grep", "left", NULL};
char *cut_args[] = {"wc", "-c", NULL};

How can I achieve this ?

int nbProc = 2;
for (int i = 0; i < argc; i++){
        if (strcmp(argv[i], ":") == 0){
            nbProc++;
        }
    }

int indice_debut[nbProc-2];
int j = 0;
for (int i = 1; i < argc; i++){
        if (strcmp(argv[i], ":") == 0){
            argv[i] = NULL;
            indice_debut[j] = i + 1;
            j++;
        }
    }

With this i'm able to get indice_debut = {4,7} because there is : in 4th and 7th position.

I tried to run it as this but no luck, i'm doing this so i can use execvp.

execvp(argv[indice_debut[0]], argv + indice_debut[0]);

Thanks

8
  • 1
    Allocate the arrays dynamically using malloc() Commented Dec 8, 2021 at 0:30
  • @Barmar the issue is i dont know how many arrays im going to make Commented Dec 8, 2021 at 0:30
  • You need at most argc/2 arrays. So allocate that many. Commented Dec 8, 2021 at 0:31
  • can you show me in code please ? what about naming the arrays ? how will i name them if i dont know how many there is Commented Dec 8, 2021 at 0:34
  • You only need one name for the array of pointers. Commented Dec 8, 2021 at 0:35

1 Answer 1

2

Allocate an array of pointers dynamically with malloc(). There can be at most argc/2 commands, since the worst case is alternating word : word : word : ..., so allocate that many elements. The array elements can point to the elements of argv, and you can replace the : argument with a null pointer to end each subcommand.

int main(int argc, char **argv) {
    if (argc < 2) {
        printf("At least one command is required\n");
        exit(1);
    }

    char **arg_arrays = malloc(argc/2 * sizeof *arg_arrays);
    int array_index = 0;
    int arg_index = 0;
    while (arg_index < argc) {
        arg_arrays[array_index++] = &argv[arg_index];
        for (; arg_index < argc && strcmp(argv[arg_index], ":") != 0; arg_index++) {}
        argv[arg_index] = NULL;
    }

    // Execute each of the subcommands
    for (int i = 0; i < array_index; i++) {
        pid_t pid = fork();
        if (pid == 0) {
            execvp(arg_arrays[i][0], arg_arrays[i]);
        } else if (pid < 0) {
            perror("fork");
            exit(1);
        }
    }
    // wait for all the subcommands to finish
    while (wait(NULL) > 0) {}
}

This is just a simple example of how to parse the subcommands and execute them. If you want to pipe from one command to the next one you'll need to add that code.

Sign up to request clarification or add additional context in comments.

6 Comments

I get these messages incompatible pointer to integer conversion assigning to 'char' from 'void *' [-Wint-conversion] argv[arg_index] = NULL;
warning: incompatible integer to pointer conversion passing 'char' to parameter of type 'const char *'; take the address with & [-Wint-conversion] execvp(arg_arrays[i][0], arg_arrays[i]); ^~~~~~~~~~~~~~~~
test.c:26:38: warning: incompatible pointer types passing 'char *' to parameter of type 'char *const *'; take the address with & [-Wincompatible-pointer-types] execvp(arg_arrays[i][0], arg_arrays[i]);
can you add the pipe example as well, just for information and general knowledge
Sorry, it should be char **argv
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.