fixed subprocess execution and redirect. now supports curses, ssh clients, and more.

master
Phanes 2017-12-02 22:01:09 -05:00
parent 6fd80a31c5
commit c92be3f4be
3 changed files with 13 additions and 136 deletions

View File

@ -18,7 +18,7 @@
}, },
{ {
"name": "A DEFINITION THAT IS NOT USED", "name": "A DEFINITION THAT IS NOT USED",
"target": "/usr/bin/false", "target": "/usr/bin/dialog --yesno test 50 50",
"rectifier": "/usr/bin/false", "rectifier": "/usr/bin/false",
"active": true, "active": true,
"required": true, "required": true,
@ -26,10 +26,10 @@
}, },
{ {
"name": "dependent test", "name": "dependent test",
"target": "/usr/bin/false", "target": "ssh root@phanes.silogroup.org",
"rectifier": "/usr/bin/false", "rectifier": "/usr/bin/false",
"active": true, "active": true,
"required": true, "required": false,
"rectify": true "rectify": true
} }
] ]

View File

@ -114,17 +114,17 @@ void Plan::load_definitions( Suite unit_definitions, bool verbose )
void Plan::execute( bool verbose ) void Plan::execute( bool verbose )
{ {
// for each task in this plan // for each task in this plan
// for ( int i = 0; i < this->tasks.size(); i++ ) for ( int i = 0; i < this->tasks.size(); i++ )
// { {
// if ( verbose ) { if ( verbose ) {
// std::cout << "Executing task \"" << this->tasks[i].get_name() << "\"." << std::endl; std::cout << "Executing task \"" << this->tasks[i].get_name() << "\"." << std::endl;
std::cout << "Executing task \"" << this->tasks[0].get_name() << "\"." << std::endl; // std::cout << "Executing task \"" << this->tasks[0].get_name() << "\"." << std::endl;
// } }
// this->tasks[i].execute( verbose ); this->tasks[i].execute( verbose );
this->tasks[0].execute( verbose ); // this->tasks[0].execute( verbose );
// for testing a logic issue in Task.execute(), remove when done // for testing a logic issue in Task.execute(), remove when done
// throw Plan_InvalidTaskIndex(); // throw Plan_InvalidTaskIndex();
// } }
} }

View File

@ -8,131 +8,8 @@
/// \param input - The commandline input to execute. /// \param input - The commandline input to execute.
/// \return - The return code of the execution of input in the calling shell. /// \return - The return code of the execution of input in the calling shell.
int Sproc::execute(std::string input) { int Sproc::execute(std::string input) {
int PIPE_READ = 0;
int PIPE_WRITE = 1;
int stdin_pipe[2];
int stderr_pipe[2];
int stdout_pipe[2];
pid_t child_pid, w;
char nChar;
int child_exit_code = -666; int child_exit_code = -666;
child_exit_code = system( input.c_str() );
// experimental
int status;
if ( pipe(stdin_pipe) < 0 )
{
perror("allocating pipe for child input redirect");
exit(-1);
}
if ( pipe(stdout_pipe) < 0 )
{
close(stdin_pipe[PIPE_READ]);
close(stdin_pipe[PIPE_WRITE]);
perror("allocating pipe for child output redirect");
exit(-1);
}
if ( pipe(stderr_pipe) < 0 ) {
close(stderr_pipe[PIPE_READ]);
close(stderr_pipe[PIPE_WRITE]);
perror("allocating pipe for error redirect");
exit(-1);
}
child_pid = fork();
if (0 == child_pid)
{
// child continues here
// redirect stdin
if (dup2(stdin_pipe[PIPE_READ], STDIN_FILENO) == -1) {
exit(errno);
}
// redirect stdout
if (dup2(stdout_pipe[PIPE_WRITE], STDOUT_FILENO) == -1) {
exit(errno);
}
// redirect stderr
if (dup2(stderr_pipe[PIPE_WRITE], STDERR_FILENO) == -1) {
exit(errno);
}
// all these are for use by parent only
close(stdin_pipe[PIPE_READ]);
close(stdin_pipe[PIPE_WRITE]);
close(stdout_pipe[PIPE_READ]);
close(stdout_pipe[PIPE_WRITE]);
close(stderr_pipe[PIPE_READ]);
close(stderr_pipe[PIPE_WRITE]);
// run child process image
// replace this with any exec* function find easier to use ("man exec")
child_exit_code = system( input.c_str() );
// if we get here at all, an error occurred, but we are in the child
// process, so just exit
exit(WEXITSTATUS(child_exit_code));
} else if (child_pid > 0) {
// parent continues here
do {
w = waitpid(child_pid, &child_exit_code, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(child_exit_code)) {
;;
//printf("exited, status=%d\n", WEXITSTATUS(child_exit_code));
} else if (WIFSIGNALED(child_exit_code)) {
printf("killed by signal %d\n", WTERMSIG(child_exit_code));
} else if (WIFSTOPPED(child_exit_code)) {
printf("stopped by signal %d\n", WSTOPSIG(child_exit_code));
} else if (WIFCONTINUED(child_exit_code)) {
printf("continued\n");
}
} while (!WIFEXITED(child_exit_code) && !WIFSIGNALED(child_exit_code));
// close unused file descriptors, these are for child only
close(stdin_pipe[PIPE_READ]);
close(stdout_pipe[PIPE_WRITE]);
close(stderr_pipe[PIPE_WRITE]);
// Just a char by char read here, you can change it accordingly
while ( read( stdout_pipe[PIPE_READ], &nChar, 1 ) == 1 )
{
// does this loop also need to involve STDERR? -CP
write(STDOUT_FILENO, &nChar, 1);
}
// done with these in this example program, you would normally keep these
// open of course as long as you want to talk to the child
close(stdin_pipe[PIPE_WRITE]);
close(stdout_pipe[PIPE_READ]);
close(stderr_pipe[PIPE_READ]);
} else {
// failed to create child
std::cout << "Failed to create child." << std::endl;
close(stdin_pipe[PIPE_READ]);
close(stdin_pipe[PIPE_WRITE]);
close(stdout_pipe[PIPE_READ]);
close(stdout_pipe[PIPE_WRITE]);
close(stderr_pipe[PIPE_READ]);
close(stderr_pipe[PIPE_WRITE]);
}
child_exit_code = WEXITSTATUS( child_exit_code ); child_exit_code = WEXITSTATUS( child_exit_code );
return child_exit_code; return child_exit_code;
} }