0

I'm attempting to run execvp using the data from a char[][] type (aka an array of strings). Now I know that execvp() takes a pointer to a string as its first parameter and then a pointer to an array of strings as its second - in fact I have even used it successfully before as such - however I cannot seem to get the correct combination of pointers & strings to get it to work out below - whatever I try is deemed incompatible!

Any help very grateful :) - I've removed my headers to compact down the code a bit!

struct userinput {
    char anyargs[30][30]; //The tokenised command
};

int main() {

    struct userinput input = { { { 0 } } }; //I believe is valid to set input to 0's
    struct userinput *inPtr = &input; //Pointer to input (direct access will be unavailable)

    strcpy(inPtr->anyargs[0], "ls"); //Hard code anyargs to arbitary values
    strcpy(inPtr->anyargs[1], "-lh");

    char (*arrPointer)[30]; //Pointer to an array of char *
    arrPointer = &(inPtr->anyargs[0]);

    printf("arrPointer[0]: %s, arrPointer[1]: %s\n", arrPointer[0],
            arrPointer[1]);

    printf("At exec case; ");
    execvp( arrPointer[0], arrPointer);
    perror("Command not recognised"); //Prints string then error message from errno

    return 0;
}
2
  • Have you tried arrPointer = (inPtr->anyargs); without & ? Commented Nov 9, 2014 at 17:12
  • Yes - correct me if I'm wrong - the -> operator de-references and returns the value - which we don't want as arrPointer and execvp dont take values directly - they take pointers to values? Commented Nov 9, 2014 at 17:15

2 Answers 2

2

There is no such thing as char[][] in C. execvp requires an array of pointers to const char. This can be written as either char * const * or char * const [].

You however have an array of 30-characters-long arrays, not an array of pointers. The two types are not compatible, not interchangeable, and not convertible one to another in either direction.

In this line

char (*arrPointer)[30]; //Pointer to an array of char *

you attempt to declare a pointer to an array of char*, incorrectly. What you have declared instead is a pointer to char[30], which is very different from what execvp expects.

The next line

arrPointer = &(inPtr->anyargs[0]);

purports to initialize a pointer to an array of char* with a pointer to char[30], which cannot possibly be correct even if you declare a pointer to an array of char*, because the right hand side of the assignment is not a pointer to an array of char*, it's a pointer to char[30] and no sequence of casts, indices, addresses and dereferences will turn one to the other.

An array of 30 pointers to char is declared like this:

char* arguments[30];

A dynamically-sized array of pointers to char is made like this:

char** arguments = calloc (nargs, sizeof(char*));

You need to use one of those if you want to call execvp.

In either case each pointer in the array of pointers must be initialized to point to an individual NUL-terminated character array (possibly to elements of your char[30][30] array) and the last pointer (one after all the argumenrs we want to pass) must be set to NULL. (I wonder how you expected to find a NULL in a char[30][30]).

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

Comments

2

The execvp() expects as second argument a char *const argv[]. This means an array of pointers to char. This is different from a char[30][30] which is represented in memory as 30x30 contiguous chars (so no pointer).

To solve this, define your structure

struct userinput {
    char *anyargs[30]; //space for 30 char* pointers
};

You could as well define anyargs as char** and initalize if dynamically with (char**)calloc(number_of_args+1,sizeof(char*))

Later, assign directly the pointers:

inPtr->anyargs[0] = "ls"; //Hard code (or use strdup() )
inPtr->anyargs[1] = "-lh";
inPtr->anyargs[2] = NULL; // end of the argument list !!!
char **arrPointer; //Pointer to an array of char *
arrPointer = inPtr->anyargs;

Edit: Caution: "The array of pointers must be terminated by a NULL pointer.".

Comments

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.