Using execv

Apr 12, 2012 at 8:55pm
I use an std::vector<string> as a container for my command and arguments. And I need to manipulate it somehow in order to use execv.
My problem is that execv receives an array of strings (char**) and not an std::vector<string> like the one I use.
The simple option is just to make a new array and copy the string to it.
I want to do it without allocating new memory.
Is it somehow possible?
Apr 12, 2012 at 10:02pm
closed account (S6k9GNh0)
The data isn't formatted in the way that execv wants it. So you have to create a new area of memory that is formatted the way execv wants it, assign it properly, and pass it to execv.

I wouldn't use std::vector<string> if you're going to use execv directly since it obviously isn't very efficient in this situation.
Apr 12, 2012 at 10:32pm
The code I'm trying to run is this:

1
2
3
4
5
6
7
8
9
void complexCommand(const vector<string>& argv) {
	vector<char*> arg_v;
	arg_v.push_back("/bin/csh");
	arg_v.push_back("-f");
	arg_v.push_back("-c");
	for (unsigned int i = 0; i < argv.size(); i++) arg_v.push_back(const_cast<char*> (argv[i].c_str()));
	execv(arg_v[0], &arg_v[0]);
	//EXECV ERROR
}

Look at this post:
http://cboard.cprogramming.com/cplusplus-programming/71478-converting-vector-strings-into-array.html

According to it, the code should work. The guy there had the exact problem I have, and the solution offered to him there solved it. I don't know why it doesn't work for me.

As I understand it, the problem with this code is not the execv command, it's how it uses the data I give. For example, if I try running this with the command: "ls -l | head -3", it says "Unknown option: -l". If I'm just running ls (for example) it works.

You got a clue?

BTW, This is an assignment I got from school, and I'm using the csh because I was told to.
Last edited on Apr 12, 2012 at 10:36pm
Apr 12, 2012 at 10:37pm
This code has multiple problems, for example:
arg_v can only hold char *, but "/bin/csh", "-f", and "-c" are const char *.
You are casting a const char * to a char * - NEVER cast away from const!
Last edited on Apr 12, 2012 at 10:38pm
Apr 12, 2012 at 11:23pm
Then what do you suggest? If I didn't need all the "/bin/csh", "-f", "-c" I could have just call execv with argv instead of arg_v.

What can I do to solve this?
Thanks.
Apr 13, 2012 at 1:42am
closed account (S6k9GNh0)
You can do something like this:
http://codepad.org/8if5hCzu
http://codepad.org/4vBoODsh


EDIT: Fixed constness, removed unneeded number:

1
2
3
4
5
6
7
#include <cstdio>

int main() { 
    const char* arg_v[] = { "/bin/csh", "-f", "-c" };
    printf("%s, %s, %s\n", arg_v[0], arg_v[1], arg_v[2]);
    return 0;
}


http://codepad.org/a4pOg4RW

EDIT2: Looking at the OP, I no longer know what you want lol.... oh well?
Last edited on Apr 13, 2012 at 2:01am
Apr 13, 2012 at 9:16am
I'm sorry but I don't really understand how this helps me..
Apr 13, 2012 at 10:47am
Your original code looks ok to me, it's just missing the null terminator in the sequence.
1
2
3
4
5
	std::vector<char*> args;
	args.push_back((char*)"/usr/bin/bc");
	args.push_back((char*)"-q");
	args.push_back(0);
	execv(args[0], &args.front());

Apr 13, 2012 at 11:05am
It didn't work for me. Maybe I didn't explain enough:
Maybe I didn't explain enough:
I'm creating a small shell, and I need to receive commands from the user. I have a list of commands to which I create the response, and for the other commands I want to use the csh to execute them.
For example, I implemented the cd, pwd, set etc. commands, and I want to use the csh program to execute the others (which are more complex).
The code a I put there was actually the function I call when I identify the command as complex.
If I use the command "ls -l | head -3", the argv will be:

argv = {"ls", "-l", "|", "head", "-3"}

(But of course as a vector of strings and not an array).

How can I use it to do what I want?
Apr 13, 2012 at 11:38am
You can't just exec "ls -l | head -3". That pipe indicator is handled by the shell, by you in this case. It means you execute "ls -3" and "head -3" as different processes and tie stdout of ls to stdin of head.

The example I posted does work, I tested it on OS X.
Apr 13, 2012 at 11:56am
I think that was the main problem.
But I managed to solve it:
1
2
3
4
5
6
7
8
9
10
11
12
void complexCommand(const vector<string>& argv) {
	vector<char*> arg_v;
	string command;
	for (unsigned int i = 0; i < argv.size(); i++) command.assign(command + argv[i] + " ");
	arg_v.push_back("/bin/csh");
	arg_v.push_back("-f");
	arg_v.push_back("-c");
	arg_v.push_back(const_cast<char*>(command.c_str()));
	arg_v.push_back(0);
	execv(arg_v[0], &arg_v[0]);
	//EXECV ERROR
}


Thanks for the help!
Apr 13, 2012 at 1:47pm
It is still wrong.

vector<char*> arg_v;
Change this to:
vector<const char*> arg_v;

arg_v.push_back(const_cast<char*>(command.c_str()));
Change this to:
arg_v.push_back(command.c_str());
Topic archived. No new replies allowed.