开发者

C++ - Linux/shell script run child processes & get their return statuses

I'm looking for a solution to writing a piece of program in C++ on Linux that parses a file which contains programs with a set arguments, then runs those programs with their arguments arguments.

Each program (line) is executed one at a time and then the parent process waits for each child to exit and inspects it's exit status (i'm only interested if it is 0).

Example of text to be parsed:

prog1 -a arg1 -m arg2 -c arg3 prog2 arg1 arg2 arg3 arg4 ....

开发者_开发技巧

I believe it is best to store everything in a vector of strings, eg:

vector <std::string> p_vector;
while (getline(file, line))
    p_vector.push_back(line);

then, for each element i from 0 to p_vector.size() I need to do something like the example I found on the net:

if(fork() = 0) //? shouldn't here be == ?
{
    execv(fullpath,argv);//does full path mean my p_vector[i]? or the child process and then argv is a list of space delimited arguments?
    exit(1);
}
else
{
    int *status;
    wait(status);
    if(*status == 0)
    printf("%s exited correctly", fullpath);//fullpath, right?
    else
    //other printf error
}

or, should I better use for this

string command = p_vector[i]; // eg: ls -l -a -l folder_one , put more arguments because I do not know the exact number of them for each parsed line

int exitCode = system(command.c_str());

If anyone has also an idea of how to do this using a script, that would be welcome too, although the scope of my question is C++!

I could have used Qt's QProcess as I know how to use that one but that might raise some legal issues of which I'm now aware right now (there's no problem with sharing the code however, the company I work for may not allow that)

Thanks and looking forward to getting some answers from you!


I agree with Ignacio. But if you have to do it , then I would prefer you using System/popen command.

BUT MAKE SURE YOU ARE NOT RUNNING ANY COMMAND THAT WOULD LAND YOU TO TROUBLE.. like " rm -rf * ".

This is very likely to happen if you are going to read from a file which cannot be trusted with.

And no need to copy it to new string you can do "system(p_vector[i].c_str());"


in bash:

echo file | while read command
do
   eval $command
done

where file is the file containing, for each line, a program with his arguments


To use the exec family you are going to have to parse your p_vector[i] into tokens. The zeroth token identifies the program to be executed; the remaining specify arguments to the program. execvp emulates what your shell does: It searches for the program in the search path. execv expects you to go one step further. You need to specify the path to the program, but not necessarily full path; relative paths work just fine. One other little gotcha with regard to exec: The zeroth argument is supposed to be a replica of the program name. That's a lot of work in this case.

Essentially, system does the following:

int pid, status, wait_pid;
char * shell;

shell = getenv ("SHELL");
if (shell == 0) {
   // Deal with missing SHELL environment variable problem
   return -1;
}

pid = fork();
if (pid < 0) {
    return -1;
}

else if (pid == 0) {
   execl (shell, shell, string_to_execute);
   return -1;
}

waited_pid = waitpid (pid, &status, wait_options);
if (waited_pid != pid) {
   return -1;
}

return status;

In other words, pretty much what you want.

Edit 1
One gotcha with system: It insecure as all get out. ArunMu already mentioned rm -rf /. What if some line contains do_something_benign; rm -rf / If you can trust the content of the file, using system is fine. If not, it is much better to use something like perl or some other scripting language that can be made to run in a safe mode.

Edit 2
Given the commentary, what is the driving factor that led you to want to write this in C or C++? A scripting language, or even better, a test target in your makefile is a better fit to this problem.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜