If you have to call execvp()
, then you will need to split up those strings into an executable name and an array of arguments (the first being the "name" of the program and the last being a NULL pointer).
That means something like:
char cmd1[] = "ls"; char *args1[] = {"ls", "-l", NULL};
char cmd1[] = "rm"; char *args1[] = {"rm", "*.txt", NULL}; // but see
// globbing below.
char cmd1[] = "cat"; char *args1[] = {"cat", "makefile", NULL};
This is a non-trivial exercise, especially if you want to allow for quoting, globbing, escaping and so forth.
Quoting means you'll have to be careful with commands like:
rm "file with spaces.txt"
in that you can't simply break on the spaces - you'll have to interpret items in the command much the same as the shell does. Simplistic breaking on spaces would give you a command with three arguments for that string above, rather than the correct one.
By globbing, I mean you'll almost certainly have problems with something like *.txt
since it's typically the shell which expands these arguments. Passing that directly to execvp()
will result in a single argument of literally *.txt
rather than many arguments matching all the text files in your current directory.
Quoting means that you'll have to handle things like:
ls -l "file with spaces and \" quote in it"
which will further complicate your parser.
Don't get me wrong, it can be done, but it's probably a damn sight easier just using system()
.
If you're still thinking of going the execvp()
route, you'll have to:
- split the string into separate tokens (rather hard, since you have to handle quotes and escapes).
- glob all the arguments, meaning that those with wildcards in them (and only ones that aren't escaped or protected by virtue of being inside quotes) are expanded into multiple arguments.
- construct the argument array, with the command at the front and a NULL at the end.
- call
execvp()
with the parameters being first element in that array and the address of the array.