tags:

views:

135

answers:

2

Hello, all.

I am trying to write a microshell in C++ to run in BASH. I am using getline() to read a command and its arguments as input by the user into a holding array. I use strtok() to parse the command array and return the first item (the actual command the the user wants to run) and want to use execlp() to run said command.

My problem is that I can not figure out how to dice up the rest of that command array to get the arguments out of it and pass them to execlp() (or execvp or whatever you guys might suggest in the exec* family). Any ideas?

Thanks!

A: 

There's a function in glib called g_shell_parse_argv that does just that. Should be a good place to start (look at the tokenize_command_line function).

eduffy
+1  A: 

Firstly, if you don't have to use strtok(), you should use a higher-level library that does argument parsing for you.

That being said, here's how you should go about parsing a string like: "command arg1 arg2 arg3..." (separated by spaces).

Short answer: After using strtok() on the string to get the first part of the string (the command name), you can then call strtok() again, this time passing NULL instead of a pointer to a string. strtok() will then return the next string, i.e. the first argument, and each call to strtok() will return the next argument until there are no more arguments to parse.

Explanation: What strtok() actually does is locate the first separator char you give it (in your case, a space mark). After finding it, it turns it into a NULL marker, which means, the string now only goes up to the first space (i.e. you have a pointer to the memory: "command\0arg1 arg2 arg3". Since strings are terminated at the first \0, your pointer now points to a string that says "command".)

What you want to do now is pass a pointer to the place after your string ends, i.e. a pointer pointing at the 'a' char of "arg1", and call strtok again (so that the space between arg1 and arg2 is now turned into a NULL, and you now have a pointer to a string containing the word "command".

But since this is the most common operation, strtok() makes this much easier. If you pass in a NULL pointer, it will assume that that's exactly what you want to do, and treat the NULL pointer as if you had passed a pointer pointing at "arg1".

Note that as another way to make life easier, strtok() will always return the pointer that it thinks you gave it (i.e. when passing a real pointer, that's what you get back, but when passing a NULL pointer, you get the pointer you would have passed in).

Hope that helps.

Edan Maor
This doesn't allow expressions where you want to have white space in one of the arguments, e.g. "echo 'hi there'".
Georg Fritzsche
That's right, but I'm pretty sure this is standard behavior for command-line programs. That's why filenames are always surrounded in quotation marks.Of course, using a higher-level library is much better in any case, I just answered specifically about how to use strtok().
Edan Maor
Ok, i assumed from the term 'microshell' that he wanted sh-like behaviour.
Georg Fritzsche