+ switch (arg)
+ {
+ case 127:
+ return Application::INVALID;
+
+ case 0:
+ return Application::SUCCESS;
+
+ default:
+ case 1:
+ return Application::FAILURE;
+ }
+ }
+}
+
+namespace libtest {
+
+Application::Application(const std::string& arg, const bool _use_libtool_arg) :
+ _use_libtool(_use_libtool_arg),
+ _use_valgrind(false),
+ _use_gdb(false),
+ _argc(0),
+ _exectuble(arg),
+ built_argv(NULL),
+ _pid(-1)
+ {
+ if (_use_libtool)
+ {
+ if (libtool() == NULL)
+ {
+ throw "libtool requested, but know libtool was found";
+ }
+ }
+
+ // Find just the name of the application with no path
+ {
+ size_t found= arg.find_last_of("/\\");
+ if (found)
+ {
+ _exectuble_name= arg.substr(found +1);
+ }
+ else
+ {
+ _exectuble_name= arg;
+ }
+ }
+
+ if (_use_libtool and getenv("PWD"))
+ {
+ _exectuble_with_path+= getenv("PWD");
+ _exectuble_with_path+= "/";
+ }
+ _exectuble_with_path+= _exectuble;
+ }
+
+Application::~Application()
+{
+ delete_argv();
+}
+
+Application::error_t Application::run(const char *args[])
+{
+ stdin_fd.reset();
+ stdout_fd.reset();
+ stderr_fd.reset();
+ _stdout_buffer.clear();
+ _stderr_buffer.clear();
+
+ posix_spawn_file_actions_t file_actions;
+ posix_spawn_file_actions_init(&file_actions);
+
+ stdin_fd.dup_for_spawn(Application::Pipe::READ, file_actions, STDIN_FILENO);
+ stdout_fd.dup_for_spawn(Application::Pipe::WRITE, file_actions, STDOUT_FILENO);
+ stderr_fd.dup_for_spawn(Application::Pipe::WRITE, file_actions, STDERR_FILENO);
+
+ create_argv(args);
+
+ int spawn_ret;
+ if (_use_gdb)
+ {
+ std::string gdb_run_file= create_tmpfile(_exectuble_name);
+ std::fstream file_stream;
+ file_stream.open(gdb_run_file.c_str(), std::fstream::out | std::fstream::trunc);
+
+ _gdb_filename= create_tmpfile(_exectuble_name);
+ file_stream
+ << "set logging redirect on" << std::endl
+ << "set logging file " << _gdb_filename << std::endl
+ << "set logging overwrite on" << std::endl
+ << "set logging on" << std::endl
+ << "set environment LIBTEST_IN_GDB=1" << std::endl
+ << "run " << arguments() << std::endl
+ << "thread apply all bt" << std::endl
+ << "quit" << std::endl;
+
+ fatal_assert(file_stream.good());
+ file_stream.close();
+
+ if (_use_libtool)
+ {
+ // libtool --mode=execute gdb -f -x binary
+ char *argv[]= {
+ const_cast<char *>(libtool()),
+ const_cast<char *>("--mode=execute"),
+ const_cast<char *>("gdb"),
+ const_cast<char *>("-batch"),
+ const_cast<char *>("-f"),
+ const_cast<char *>("-x"),
+ const_cast<char *>(gdb_run_file.c_str()),
+ const_cast<char *>(_exectuble_with_path.c_str()),
+ 0};
+
+ spawn_ret= posix_spawnp(&_pid, libtool(), &file_actions, NULL, argv, NULL);
+ }
+ else
+ {
+ // gdb binary
+ char *argv[]= {
+ const_cast<char *>("gdb"),
+ const_cast<char *>("-batch"),
+ const_cast<char *>("-f"),
+ const_cast<char *>("-x"),
+ const_cast<char *>(gdb_run_file.c_str()),
+ const_cast<char *>(_exectuble_with_path.c_str()),
+ 0};
+ spawn_ret= posix_spawnp(&_pid, "gdb", &file_actions, NULL, argv, NULL);
+ }