/* guestfish - the filesystem interactive shell
- * Copyright (C) 2009-2010 Red Hat Inc.
+ * Copyright (C) 2009-2011 Red Hat 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
static void script (int prompt);
static void cmdline (char *argv[], int optind, int argc);
static struct parsed_command parse_command_line (char *buf, int *exit_on_error_rtn);
+static int execute_and_inline (const char *cmd, int exit_on_error);
static void initialize_readline (void);
static void cleanup_readline (void);
#ifdef HAVE_LIBREADLINE
guestfs_h *g;
int read_only = 0;
+int live = 0;
int quit = 0;
int verbose = 0;
int remote_control_listen = 0;
" -i|--inspector Automatically mount filesystems\n"
" --keys-from-stdin Read passphrases from stdin\n"
" --listen Listen for remote commands\n"
+ " --live Connect to a live virtual machine\n"
" -m|--mount dev[:mnt] Mount dev on mnt (if omitted, /)\n"
" -n|--no-sync Don't autosync\n"
" -N|--new type Create prepared disk (test1.img, ...)\n"
{ "inspector", 0, 0, 'i' },
{ "keys-from-stdin", 0, 0, 0 },
{ "listen", 0, 0, 0 },
+ { "live", 0, 0, 0 },
{ "mount", 1, 0, 'm' },
{ "new", 1, 0, 'N' },
{ "no-dest-paths", 0, 0, 'D' },
format = optarg;
} else if (STREQ (long_options[option_index].name, "csh")) {
remote_control_csh = 1;
+ } else if (STREQ (long_options[option_index].name, "live")) {
+ live = 1;
} else {
fprintf (stderr, _("%s: unknown long option: %s (%d)\n"),
program_name, long_options[option_index].name, option_index);
: (optind >= argc && isatty (0));
if (progress_bars)
- guestfs_set_progress_callback (g, progress_callback, NULL);
+ guestfs_set_event_callback (g, progress_callback,
+ GUESTFS_EVENT_PROGRESS, 0, NULL);
/* Interactive, shell script, or command(s) on the command line? */
if (optind >= argc) {
int r;
const size_t argv_len = sizeof pcmd.argv / sizeof pcmd.argv[0];
- pcmd.pipe = NULL;
+ /* Note that pcmd.pipe must be set to NULL for correct usage. Other
+ * fields do not need to be, but this silences a gcc warning.
+ */
+ memset (&pcmd, 0, sizeof pcmd);
again:
/* Skip any initial whitespace before the command. */
return pcmd;
}
+ /* If the next two characters are "<!" then pass the command to
+ * popen(3), read the result and execute it as guestfish commands.
+ */
+ if (buf[0] == '<' && buf[1] == '!') {
+ int r = execute_and_inline (&buf[2], *exit_on_error_rtn);
+ if (r == -1)
+ pcmd.status = -1;
+ else
+ pcmd.status = 0;
+ return pcmd;
+ }
+
/* If the next character is '-' allow the command to fail without
* exiting on error (just for this one command though).
*/
return pcmd;
}
+/* Used to handle "<!" (execute command and inline result). */
+static int
+execute_and_inline (const char *cmd, int global_exit_on_error)
+{
+ FILE *pp;
+ char *line = NULL;
+ size_t len = 0;
+ ssize_t n;
+ int exit_on_error;
+ struct parsed_command pcmd;
+
+ pp = popen (cmd, "r");
+ if (!pp) {
+ perror ("popen");
+ return -1;
+ }
+
+ while ((n = getline (&line, &len, pp)) != -1) {
+ exit_on_error = global_exit_on_error;
+
+ /* Chomp final line ending which parse_command_line would not expect. */
+ if (n > 0 && line[n-1] == '\n')
+ line[n-1] = '\0';
+
+ pcmd = parse_command_line (line, &exit_on_error);
+ if (pcmd.status == -1 && exit_on_error)
+ exit (EXIT_FAILURE);
+ if (pcmd.status == 1) {
+ if (issue_command (pcmd.cmd, pcmd.argv, pcmd.pipe, exit_on_error) == -1) {
+ if (exit_on_error) exit (EXIT_FAILURE);
+ }
+ }
+ }
+
+ free (line);
+
+ if (pclose (pp) == -1) {
+ perror ("pclose");
+ return -1;
+ }
+
+ return 0;
+}
+
static void
cmdline (char *argv[], int optind, int argc)
{