I think you might be overthinking this problem. Based on the parsing code at the top of your question, you have already solved the problem.
parsed = parsed_arguments;
/* parsed now points to the first element parsed_arguments */
*parsed++ = strtok(newcommand,SEPARATORS); // tokenize input
while ((*parsed++ = strtok(NULL,SEPARATORS)))
; /* habit of mine */
/* At this point, parsed_arguments should be now populated with each
token from newcommand by strtok
Minus a few caveats, the following call should be valid */
execvp(parsed_arguments[0], parsed_arguments);
Before I describe the caveats that I mentioned (that I know of), I'll quickly explain why this should work:
strtok
returns the pointer of the last token found in its first argument. This pointer is then written in this variable: *parsed++
(which is an expression that evaluates into an l-value). This dereferences the address pointed to by parsed
(which is an element of parsed_arguments
). Finally, the post-fix ++
operator simply makes parsed
point to the next element of parsed_arguments
after the full expression is evaluated.
The important thing to note, is parsed
points to the same block of memory occupied by parsed_arguments
. By setting parsed = parsed_arguments
, *parsed = token
is equivalent to parsed_arguments[some_index] = token
.
You could express your code (not quite as elegantly) without pointer arithmetic as such:
int argc = 0;
/* declarations, etc *SNIP* */
parsed_arguments[argc] = strtok(newcommand, delim);
while (parsed_arguments[argc++]) {
parsed_arguments[argc] = strtok(NULL, delim);
}
I hope this is the answer you were looking for, or at least helps point you in the right direction, based on the actual code provided (since a lot is missing, for obvious reasons), and there is a parsed_buf
, buf
that seem to mimic parsed
and parsed_arguments
, but those also exist in the code, I am not 100% sure if I completely understand what you are trying to do.
Caveats
execvp(...)
's documentation states that by convention, the first element of the arguments should be the file name (I see that you already know this), but nonetheless, make sure the program name is the first element--either have your file's content have the program name first, or just start from the second element.
execvp(...)
also states that the last argument should be a NULL pointer. You can ensure this by a call to memset(parsed_arguments, 0, sizeof(parsed_arguments));
and ensuring the file never specifies more than 64 arguments.
http://linux.die.net/man/3/execvp
Lastly, (possibly nit-picking), while (pointer)
works on the premise that NULL == 0
(in most cases, it is (void *) 0
AFAIK), I don't know how important it is to you, but if you ever run into an implementation where NULL
is not defined as 0, it might cause some issues. So, it would be safer to write while ((*parsed++ = strtok(NULL, SEPARATORS)) != NULL)
. My two cents anyway.