Using execv

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?
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.
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
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
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.
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
I'm sorry but I don't really understand how this helps me..
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());

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?
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.
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!
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.