mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-23 07:12:09 +00:00
perf subcmd: Create subcmd library
Move the subcommand-related files from perf to a new library named libsubcmd.a. Since we're moving files anyway, go ahead and rename 'exec_cmd.*' to 'exec-cmd.*' to be consistent with the naming of all the other files. Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/c0a838d4c878ab17fee50998811612b2281355c1.1450193761.git.jpoimboe@redhat.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
2f4ce5ec1d
commit
4b6ab94eab
66 changed files with 129 additions and 68 deletions
227
tools/lib/subcmd/run-command.c
Normal file
227
tools/lib/subcmd/run-command.c
Normal file
|
@ -0,0 +1,227 @@
|
|||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/wait.h>
|
||||
#include "subcmd-util.h"
|
||||
#include "run-command.h"
|
||||
#include "exec-cmd.h"
|
||||
|
||||
#define STRERR_BUFSIZE 128
|
||||
|
||||
static inline void close_pair(int fd[2])
|
||||
{
|
||||
close(fd[0]);
|
||||
close(fd[1]);
|
||||
}
|
||||
|
||||
static inline void dup_devnull(int to)
|
||||
{
|
||||
int fd = open("/dev/null", O_RDWR);
|
||||
dup2(fd, to);
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int start_command(struct child_process *cmd)
|
||||
{
|
||||
int need_in, need_out, need_err;
|
||||
int fdin[2], fdout[2], fderr[2];
|
||||
char sbuf[STRERR_BUFSIZE];
|
||||
|
||||
/*
|
||||
* In case of errors we must keep the promise to close FDs
|
||||
* that have been passed in via ->in and ->out.
|
||||
*/
|
||||
|
||||
need_in = !cmd->no_stdin && cmd->in < 0;
|
||||
if (need_in) {
|
||||
if (pipe(fdin) < 0) {
|
||||
if (cmd->out > 0)
|
||||
close(cmd->out);
|
||||
return -ERR_RUN_COMMAND_PIPE;
|
||||
}
|
||||
cmd->in = fdin[1];
|
||||
}
|
||||
|
||||
need_out = !cmd->no_stdout
|
||||
&& !cmd->stdout_to_stderr
|
||||
&& cmd->out < 0;
|
||||
if (need_out) {
|
||||
if (pipe(fdout) < 0) {
|
||||
if (need_in)
|
||||
close_pair(fdin);
|
||||
else if (cmd->in)
|
||||
close(cmd->in);
|
||||
return -ERR_RUN_COMMAND_PIPE;
|
||||
}
|
||||
cmd->out = fdout[0];
|
||||
}
|
||||
|
||||
need_err = !cmd->no_stderr && cmd->err < 0;
|
||||
if (need_err) {
|
||||
if (pipe(fderr) < 0) {
|
||||
if (need_in)
|
||||
close_pair(fdin);
|
||||
else if (cmd->in)
|
||||
close(cmd->in);
|
||||
if (need_out)
|
||||
close_pair(fdout);
|
||||
else if (cmd->out)
|
||||
close(cmd->out);
|
||||
return -ERR_RUN_COMMAND_PIPE;
|
||||
}
|
||||
cmd->err = fderr[0];
|
||||
}
|
||||
|
||||
fflush(NULL);
|
||||
cmd->pid = fork();
|
||||
if (!cmd->pid) {
|
||||
if (cmd->no_stdin)
|
||||
dup_devnull(0);
|
||||
else if (need_in) {
|
||||
dup2(fdin[0], 0);
|
||||
close_pair(fdin);
|
||||
} else if (cmd->in) {
|
||||
dup2(cmd->in, 0);
|
||||
close(cmd->in);
|
||||
}
|
||||
|
||||
if (cmd->no_stderr)
|
||||
dup_devnull(2);
|
||||
else if (need_err) {
|
||||
dup2(fderr[1], 2);
|
||||
close_pair(fderr);
|
||||
}
|
||||
|
||||
if (cmd->no_stdout)
|
||||
dup_devnull(1);
|
||||
else if (cmd->stdout_to_stderr)
|
||||
dup2(2, 1);
|
||||
else if (need_out) {
|
||||
dup2(fdout[1], 1);
|
||||
close_pair(fdout);
|
||||
} else if (cmd->out > 1) {
|
||||
dup2(cmd->out, 1);
|
||||
close(cmd->out);
|
||||
}
|
||||
|
||||
if (cmd->dir && chdir(cmd->dir))
|
||||
die("exec %s: cd to %s failed (%s)", cmd->argv[0],
|
||||
cmd->dir, strerror_r(errno, sbuf, sizeof(sbuf)));
|
||||
if (cmd->env) {
|
||||
for (; *cmd->env; cmd->env++) {
|
||||
if (strchr(*cmd->env, '='))
|
||||
putenv((char*)*cmd->env);
|
||||
else
|
||||
unsetenv(*cmd->env);
|
||||
}
|
||||
}
|
||||
if (cmd->preexec_cb)
|
||||
cmd->preexec_cb();
|
||||
if (cmd->exec_cmd) {
|
||||
execv_cmd(cmd->argv);
|
||||
} else {
|
||||
execvp(cmd->argv[0], (char *const*) cmd->argv);
|
||||
}
|
||||
exit(127);
|
||||
}
|
||||
|
||||
if (cmd->pid < 0) {
|
||||
int err = errno;
|
||||
if (need_in)
|
||||
close_pair(fdin);
|
||||
else if (cmd->in)
|
||||
close(cmd->in);
|
||||
if (need_out)
|
||||
close_pair(fdout);
|
||||
else if (cmd->out)
|
||||
close(cmd->out);
|
||||
if (need_err)
|
||||
close_pair(fderr);
|
||||
return err == ENOENT ?
|
||||
-ERR_RUN_COMMAND_EXEC :
|
||||
-ERR_RUN_COMMAND_FORK;
|
||||
}
|
||||
|
||||
if (need_in)
|
||||
close(fdin[0]);
|
||||
else if (cmd->in)
|
||||
close(cmd->in);
|
||||
|
||||
if (need_out)
|
||||
close(fdout[1]);
|
||||
else if (cmd->out)
|
||||
close(cmd->out);
|
||||
|
||||
if (need_err)
|
||||
close(fderr[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wait_or_whine(pid_t pid)
|
||||
{
|
||||
char sbuf[STRERR_BUFSIZE];
|
||||
|
||||
for (;;) {
|
||||
int status, code;
|
||||
pid_t waiting = waitpid(pid, &status, 0);
|
||||
|
||||
if (waiting < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
fprintf(stderr, " Error: waitpid failed (%s)",
|
||||
strerror_r(errno, sbuf, sizeof(sbuf)));
|
||||
return -ERR_RUN_COMMAND_WAITPID;
|
||||
}
|
||||
if (waiting != pid)
|
||||
return -ERR_RUN_COMMAND_WAITPID_WRONG_PID;
|
||||
if (WIFSIGNALED(status))
|
||||
return -ERR_RUN_COMMAND_WAITPID_SIGNAL;
|
||||
|
||||
if (!WIFEXITED(status))
|
||||
return -ERR_RUN_COMMAND_WAITPID_NOEXIT;
|
||||
code = WEXITSTATUS(status);
|
||||
switch (code) {
|
||||
case 127:
|
||||
return -ERR_RUN_COMMAND_EXEC;
|
||||
case 0:
|
||||
return 0;
|
||||
default:
|
||||
return -code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int finish_command(struct child_process *cmd)
|
||||
{
|
||||
return wait_or_whine(cmd->pid);
|
||||
}
|
||||
|
||||
int run_command(struct child_process *cmd)
|
||||
{
|
||||
int code = start_command(cmd);
|
||||
if (code)
|
||||
return code;
|
||||
return finish_command(cmd);
|
||||
}
|
||||
|
||||
static void prepare_run_command_v_opt(struct child_process *cmd,
|
||||
const char **argv,
|
||||
int opt)
|
||||
{
|
||||
memset(cmd, 0, sizeof(*cmd));
|
||||
cmd->argv = argv;
|
||||
cmd->no_stdin = opt & RUN_COMMAND_NO_STDIN ? 1 : 0;
|
||||
cmd->exec_cmd = opt & RUN_EXEC_CMD ? 1 : 0;
|
||||
cmd->stdout_to_stderr = opt & RUN_COMMAND_STDOUT_TO_STDERR ? 1 : 0;
|
||||
}
|
||||
|
||||
int run_command_v_opt(const char **argv, int opt)
|
||||
{
|
||||
struct child_process cmd;
|
||||
prepare_run_command_v_opt(&cmd, argv, opt);
|
||||
return run_command(&cmd);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue