diff options
author | Richard Jones <rjones@trick.home.annexia.org> | 2009-09-22 19:52:56 +0100 |
---|---|---|
committer | Richard Jones <rjones@trick.home.annexia.org> | 2009-09-23 11:18:45 +0100 |
commit | 3bc55551356532c17403508dfd8466beb2b9db1e (patch) | |
tree | 7c92379351e2087adc1cfaca550318e6e60b7bc4 | |
parent | d186e9d3d371162774d026f85823d9615ac3bbbc (diff) | |
download | libguestfs-3bc55551356532c17403508dfd8466beb2b9db1e.tar.gz libguestfs-3bc55551356532c17403508dfd8466beb2b9db1e.tar.xz libguestfs-3bc55551356532c17403508dfd8466beb2b9db1e.zip |
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.
-rwxr-xr-x | src/generator.ml | 25 | ||||
-rw-r--r-- | src/guestfs.c | 102 |
2 files changed, 94 insertions, 33 deletions
diff --git a/src/generator.ml b/src/generator.ml index e5e2681f..1dd8b206 100755 --- a/src/generator.ml +++ b/src/generator.ml @@ -808,6 +808,31 @@ C<LIBGUESTFS_TRACE> 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<guestfs_set_log_message_callback>, +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 6eafcf5b..03089ea0 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); |