summaryrefslogtreecommitdiffstats
path: root/src/CLI/run-command.cpp
diff options
context:
space:
mode:
authorKarel Klic <kklic@redhat.com>2009-10-20 15:54:05 +0200
committerKarel Klic <kklic@redhat.com>2009-10-20 15:54:05 +0200
commit9e8a1ba0c9ddfa0108050f6fedc88de63b4b7c3f (patch)
tree93e418dedf9864edbdfcfbe69ba5b444d9704812 /src/CLI/run-command.cpp
parentb7f40a3f601e60fc342cad87cf40849ee4e2c153 (diff)
downloadabrt-9e8a1ba0c9ddfa0108050f6fedc88de63b4b7c3f.tar.gz
abrt-9e8a1ba0c9ddfa0108050f6fedc88de63b4b7c3f.tar.xz
abrt-9e8a1ba0c9ddfa0108050f6fedc88de63b4b7c3f.zip
Initial implementation of crash report editor. Splitted CLI.cpp into multiple files for clarity.
Diffstat (limited to 'src/CLI/run-command.cpp')
-rw-r--r--src/CLI/run-command.cpp87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/CLI/run-command.cpp b/src/CLI/run-command.cpp
new file mode 100644
index 00000000..df29b0e1
--- /dev/null
+++ b/src/CLI/run-command.cpp
@@ -0,0 +1,87 @@
+/*
+ Copyright (C) 2009 RedHat inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include "run-command.h"
+#include "abrtlib.h"
+
+/*
+ Inspired by git code.
+ http://git.kernel.org/?p=git/git.git;a=blob;f=run-command.c;hb=HEAD
+*/
+
+struct child_process
+{
+ const char **argv;
+ pid_t pid;
+};
+
+static int start_command(struct child_process *cmd)
+{
+ cmd->pid = fork();
+ if (cmd->pid == 0)
+ { // new process
+ execvp(cmd->argv[0], (char *const*)cmd->argv);
+ exit(127);
+ }
+ if (cmd->pid < 0)
+ {
+ error_msg_and_die("Unable to fork for %s: %s", cmd->argv[0], strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+static int finish_command(struct child_process *cmd)
+{
+ pid_t waiting;
+ int status, code = -1;
+ while ((waiting = waitpid(cmd->pid, &status, 0)) < 0 && errno == EINTR)
+ ; /* nothing */
+
+ if (waiting < 0)
+ error_msg_and_die("waitpid for %s failed: %s", cmd->argv[0], strerror(errno));
+ else if (waiting != cmd->pid)
+ error_msg_and_die("waitpid is confused (%s)", cmd->argv[0]);
+ else if (WIFSIGNALED(status))
+ {
+ code = WTERMSIG(status);
+ error_msg("%s died of signal %d", cmd->argv[0], code);
+ }
+ else if (WIFEXITED(status))
+ {
+ code = WEXITSTATUS(status);
+ if (code == 127)
+ {
+ code = -1;
+ error_msg_and_die("cannot run %s: %s", cmd->argv[0], strerror(ENOENT));
+ }
+ }
+ else
+ error_msg_and_die("waitpid is confused (%s)", cmd->argv[0]);
+
+ return code;
+}
+
+int run_command(const char **argv)
+{
+ struct child_process cmd;
+ cmd.argv = argv;
+ int code = start_command(&cmd);
+ if (code)
+ return code;
+ return finish_command(&cmd);
+}