Reputation: 163
I have a problem with execvp()
in C++. Here is my code:
char * argv[]={};
command_counter = 0;
char line[255];
fgets(line,255,stdin);
argv[0] = strtok(line, TOKEN);//seperate the command with TOKEN
while (arg = strtok(NULL, TOKEN)) {
++command_counter;
cout << command_counter << endl;
argv[command_counter] = arg;
cout << argv[command_counter] << endl;
}
argv[++command_counter] = (char *) NULL;
execvp(argv[0],argv);
But the problem is, multiple arguments are not working when I use execvp()
like this.
Like ls -a -l
, it is only executing the ls -a
as a result.
What's wrong with this program?
With the help of you guys the problem was solved by changing the statement of char * argv[128]
Upvotes: 0
Views: 2138
Reputation: 882028
The first thing that's wrong with it is that you're creating a zero-sized array to store the arguments:
char * argv[]={};
then populating it.
That's a big undefined behaviour red flag right there.
A quick and dirty fix would be ensuring you have some space there:
char * argv[1000];
but, to be honest, that has its own problems if you ever get to the point where you may have more than a thousand arguments.
Bottom line is, you should ensure there's enough space in the array for storing your arguments.
One way of doing this is with dynamic memory allocation, which expands the array of arguments as needed, so as to ensure there's always enough space:
using namespace std;
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>
#define TOKEN " "
static char **addArg (char **argv, size_t *pSz, size_t *pUsed, char *str) {
// Make sure enough space for another one.
if (*pUsed == *pSz) {
*pSz = *pSz + 25;
argv = (char **) realloc (argv, *pSz * sizeof (char*));
if (argv == 0) {
cerr << "Out of memory\n";
exit (1);
}
}
// Add it and return (possibly new) array.
argv[(*pUsed)++] = (str == 0) ? 0 : strdup (str);
return argv;
}
int main (void) {
Initial size, used and array.
size_t sz = 0, used = 0;
char **argv = 0;
// Temporary pointer and command.
char *str, line[] = "ls -a -l";
// Add the command itself.
argv = addArg (argv, &sz, &used, strtok (line, TOKEN));
// Add each argument in turn, then the terminator.
while ((str = strtok (0, TOKEN)) != 0)
argv = addArg (argv, &sz, &used, str);
argv = addArg (argv, &sz, &used, 0);
// Then execute it.
execvp (argv[0], argv);
// Shouldn't reach here.
return 0;
}
Upvotes: 2