From 3bc55551356532c17403508dfd8466beb2b9db1e Mon Sep 17 00:00:00 2001 From: Richard Jones Date: Tue, 22 Sep 2009 19:52:56 +0100 Subject: [PATCH 1/1] Add direct appliance mode flag and implementation. When the g->direct flag is set, the appliance stdin/stdout are not connected to the library. Instead they inherit the stdin/stdout of the caller. This is used to implement virt-rescue. --- src/generator.ml | 25 ++++++++++++++ src/guestfs.c | 102 +++++++++++++++++++++++++++++++++++++------------------ 2 files changed, 94 insertions(+), 33 deletions(-) diff --git a/src/generator.ml b/src/generator.ml index e5e2681..1dd8b20 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -808,6 +808,31 @@ C is defined and set to C<1>."); "\ Return the command trace flag."); + ("set_direct", (RErr, [Bool "direct"]), -1, [FishAlias "direct"], + [InitNone, Always, TestOutputFalse ( + [["set_direct"; "false"]; + ["get_direct"]])], + "enable or disable direct appliance mode", + "\ +If the direct appliance mode flag is enabled, then stdin and +stdout are passed directly through to the appliance once it +is launched. + +One consequence of this is that log messages aren't caught +by the library and handled by C, +but go straight to stdout. + +You probably don't want to use this unless you know what you +are doing. + +The default is disabled."); + + ("get_direct", (RBool "direct", []), -1, [], + [], + "get direct appliance mode flag", + "\ +Return the direct appliance mode flag."); + ] (* daemon_functions are any functions which cause some action diff --git a/src/guestfs.c b/src/guestfs.c index 6eafcf5..03089ea 100644 --- a/src/guestfs.c +++ b/src/guestfs.c @@ -119,6 +119,7 @@ struct guestfs_h int verbose; int trace; int autosync; + int direct; char *path; /* Path to kernel, initrd. */ char *qemu; /* Qemu binary. */ @@ -651,6 +652,19 @@ guestfs__get_trace (guestfs_h *g) return g->trace; } +int +guestfs__set_direct (guestfs_h *g, int d) +{ + g->direct = !!d; + return 0; +} + +int +guestfs__get_direct (guestfs_h *g) +{ + return g->direct; +} + /* Add a string to the current command line. */ static void incr_cmdline_size (guestfs_h *g) @@ -1018,18 +1032,22 @@ guestfs__launch (guestfs_h *g) null_vmchannel_sock = 0; } - if (pipe (wfd) == -1 || pipe (rfd) == -1) { - perrorf (g, "pipe"); - goto cleanup0; + if (!g->direct) { + if (pipe (wfd) == -1 || pipe (rfd) == -1) { + perrorf (g, "pipe"); + goto cleanup0; + } } r = fork (); if (r == -1) { perrorf (g, "fork"); - close (wfd[0]); - close (wfd[1]); - close (rfd[0]); - close (rfd[1]); + if (!g->direct) { + close (wfd[0]); + close (wfd[1]); + close (rfd[0]); + close (rfd[1]); + } goto cleanup0; } @@ -1151,22 +1169,24 @@ guestfs__launch (guestfs_h *g) if (g->verbose) print_cmdline (g); - /* Set up stdin, stdout. */ - close (0); - close (1); - close (wfd[1]); - close (rfd[0]); + if (!g->direct) { + /* Set up stdin, stdout. */ + close (0); + close (1); + close (wfd[1]); + close (rfd[0]); + + if (dup (wfd[0]) == -1) { + dup_failed: + perror ("dup failed"); + _exit (1); + } + if (dup (rfd[1]) == -1) + goto dup_failed; - if (dup (wfd[0]) == -1) { - dup_failed: - perror ("dup failed"); - _exit (1); + close (wfd[0]); + close (rfd[1]); } - if (dup (rfd[1]) == -1) - goto dup_failed; - - close (wfd[0]); - close (rfd[1]); #if 0 /* Set up a new process group, so we can signal this process @@ -1225,18 +1245,32 @@ guestfs__launch (guestfs_h *g) /* Start the clock ... */ time (&g->start_t); - /* Close the other ends of the pipe. */ - close (wfd[0]); - close (rfd[1]); + if (!g->direct) { + /* Close the other ends of the pipe. */ + close (wfd[0]); + close (rfd[1]); - if (fcntl (wfd[1], F_SETFL, O_NONBLOCK) == -1 || - fcntl (rfd[0], F_SETFL, O_NONBLOCK) == -1) { - perrorf (g, "fcntl"); - goto cleanup1; - } + if (fcntl (wfd[1], F_SETFL, O_NONBLOCK) == -1 || + fcntl (rfd[0], F_SETFL, O_NONBLOCK) == -1) { + perrorf (g, "fcntl"); + goto cleanup1; + } - g->fd[0] = wfd[1]; /* stdin of child */ - g->fd[1] = rfd[0]; /* stdout of child */ + g->fd[0] = wfd[1]; /* stdin of child */ + g->fd[1] = rfd[0]; /* stdout of child */ + } else { + g->fd[0] = open ("/dev/null", O_RDWR); + if (g->fd[0] == -1) { + perrorf (g, "open /dev/null"); + goto cleanup1; + } + g->fd[1] = dup (g->fd[0]); + if (g->fd[1] == -1) { + perrorf (g, "dup"); + close (g->fd[0]); + goto cleanup1; + } + } if (null_vmchannel_sock) { int sock = -1; @@ -1346,8 +1380,10 @@ guestfs__launch (guestfs_h *g) return 0; cleanup1: - close (wfd[1]); - close (rfd[0]); + if (!g->direct) { + close (wfd[1]); + close (rfd[0]); + } kill (g->pid, 9); if (g->recoverypid > 0) kill (g->recoverypid, 9); waitpid (g->pid, NULL, 0); -- 1.8.3.1