* src/fdstream.c (virFDStreamOpenFile, virFDStreamCreateFile): Use VIR_FORCE_CLOSE instead of close. * tests/commandtest.c (mymain): Likewise. * tools/virsh.c (editFile): Use virCommand instead of system. * src/util/util.c (__virExec): Special case preservation of std file descriptors to child. ---
v2: make virCommand behave more like system. So I didn't do any signal handling like system, but at least now you can actually edit interactively. virCommandRun doesn't like interactive sessions, so I have to use virCommandRunAsync followed by virCommandWait. I also had to fix virExec. src/fdstream.c | 6 ++-- src/util/util.c | 12 +++++---- tests/commandtest.c | 12 ++++++--- tools/virsh.c | 65 ++++++++++++++++++++++++++------------------------ 4 files changed, 52 insertions(+), 43 deletions(-) diff --git a/src/fdstream.c b/src/fdstream.c index 952bd69..701fafc 100644 --- a/src/fdstream.c +++ b/src/fdstream.c @@ -1,7 +1,7 @@ /* * fdstream.h: generic streams impl for file descriptors * - * Copyright (C) 2009-2010 Red Hat, Inc. + * Copyright (C) 2009-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -452,7 +452,7 @@ int virFDStreamOpenFile(virStreamPtr st, return 0; error: - close(fd); + VIR_FORCE_CLOSE(fd); return -1; } @@ -498,6 +498,6 @@ int virFDStreamCreateFile(virStreamPtr st, return 0; error: - close(fd); + VIR_FORCE_CLOSE(fd); return -1; } diff --git a/src/util/util.c b/src/util/util.c index f412a83..af14b2e 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -593,14 +593,16 @@ __virExec(const char *const*argv, goto fork_error; } - VIR_FORCE_CLOSE(infd); + if (infd != STDIN_FILENO) + VIR_FORCE_CLOSE(infd); VIR_FORCE_CLOSE(null); - tmpfd = childout; /* preserve childout value */ - VIR_FORCE_CLOSE(tmpfd); - if (childerr > 0 && + if (childout != STDOUT_FILENO) { + tmpfd = childout; /* preserve childout value */ + VIR_FORCE_CLOSE(tmpfd); + } + if (childerr > STDERR_FILENO && childerr != childout) { VIR_FORCE_CLOSE(childerr); - childout = -1; } /* Initialize full logging for a while */ diff --git a/tests/commandtest.c b/tests/commandtest.c index 38a7816..7157c51 100644 --- a/tests/commandtest.c +++ b/tests/commandtest.c @@ -1,7 +1,7 @@ /* * commandtest.c: Test the libCommand API * - * Copyright (C) 2010 Red Hat, Inc. + * Copyright (C) 2010-2011 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -714,6 +714,7 @@ mymain(int argc, char **argv) { int ret = 0; char cwd[PATH_MAX]; + int fd; abs_srcdir = getenv("abs_srcdir"); if (!abs_srcdir) @@ -731,9 +732,12 @@ mymain(int argc, char **argv) /* Kill off any inherited fds that might interfere with our * testing. */ - close(3); - close(4); - close(5); + fd = 3; + VIR_FORCE_CLOSE(fd); + fd = 4; + VIR_FORCE_CLOSE(fd); + fd = 5; + VIR_FORCE_CLOSE(fd); virInitialize(); diff --git a/tools/virsh.c b/tools/virsh.c index d411381..59d099e 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -56,6 +56,7 @@ #include "../daemon/event.h" #include "configmake.h" #include "threads.h" +#include "command.h" static char *progname; @@ -9354,50 +9355,52 @@ static int editFile (vshControl *ctl, const char *filename) { const char *editor; - char *command; - int command_ret; + virCommandPtr cmd; + int ret = -1; + int outfd = STDOUT_FILENO; + int errfd = STDERR_FILENO; editor = getenv ("VISUAL"); - if (!editor) editor = getenv ("EDITOR"); - if (!editor) editor = "vi"; /* could be cruel & default to ed(1) here */ + if (!editor) + editor = getenv ("EDITOR"); + if (!editor) + editor = "vi"; /* could be cruel & default to ed(1) here */ /* Check that filename doesn't contain shell meta-characters, and * if it does, refuse to run. Follow the Unix conventions for * EDITOR: the user can intentionally specify command options, so * we don't protect any shell metacharacters there. Lots more * than virsh will misbehave if EDITOR has bogus contents (which - * is why sudo scrubs it by default). + * is why sudo scrubs it by default). Conversely, if the editor + * is safe, we can run it directly rather than wasting a shell. */ - if (strspn (filename, ACCEPTED_CHARS) != strlen (filename)) { - vshError(ctl, - _("%s: temporary filename contains shell meta or other " - "unacceptable characters (is $TMPDIR wrong?)"), - filename); - return -1; + if (strspn (editor, ACCEPTED_CHARS) != strlen (editor)) { + if (strspn (filename, ACCEPTED_CHARS) != strlen (filename)) { + vshError(ctl, + _("%s: temporary filename contains shell meta or other " + "unacceptable characters (is $TMPDIR wrong?)"), + filename); + return -1; + } + cmd = virCommandNewArgList("sh", "-c", NULL); + virCommandAddArgFormat(cmd, "%s %s", editor, filename); + } else { + cmd = virCommandNewArgList(editor, filename, NULL); } - if (virAsprintf(&command, "%s %s", editor, filename) == -1) { - vshError(ctl, - _("virAsprintf: could not create editing command: %s"), - strerror(errno)); - return -1; + virCommandSetInputFD(cmd, STDIN_FILENO); + virCommandSetOutputFD(cmd, &outfd); + virCommandSetErrorFD(cmd, &errfd); + if (virCommandRunAsync(cmd, NULL) < 0 || + virCommandWait(cmd, NULL) < 0) { + virshReportError(ctl); + goto cleanup; } + ret = 0; - command_ret = system (command); - if (command_ret == -1) { - vshError(ctl, - _("%s: edit command failed: %s"), command, strerror(errno)); - VIR_FREE(command); - return -1; - } - if (WEXITSTATUS(command_ret) != 0) { - vshError(ctl, - _("%s: command exited with non-zero status"), command); - VIR_FREE(command); - return -1; - } - VIR_FREE(command); - return 0; +cleanup: + virCommandFree(cmd); + return ret; } static char * -- 1.7.3.5 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list