char *mountpoint;
};
+struct drv {
+ struct drv *next;
+ char *filename;
+};
+
+static void add_drives (struct drv *drv);
static void mount_mps (struct mp *mp);
static void interactive (void);
static void shell_script (void);
static void script (int prompt);
static void cmdline (char *argv[], int optind, int argc);
-static int issue_command (const char *cmd, char *argv[]);
static void initialize_readline (void);
static void cleanup_readline (void);
static void add_history_line (const char *);
"Copyright (C) 2009 Red Hat Inc.\n"
"Usage:\n"
" guestfish [--options] cmd [: cmd : cmd ...]\n"
+ " guestfish -i libvirt-domain\n"
+ " guestfish -i disk-image(s)\n"
"or for interactive use:\n"
" guestfish\n"
"or from a shell script:\n"
" -h|--cmd-help List available commands\n"
" -h|--cmd-help cmd Display detailed help on 'cmd'\n"
" -a|--add image Add image\n"
+ " -D|--no-dest-paths Don't tab-complete paths from guest fs\n"
+ " -f|--file file Read commands from file\n"
+ " -i|--inspector Run virt-inspector to get disk mountpoints\n"
" -m|--mount dev[:mnt] Mount dev on mnt (if omitted, /)\n"
" -n|--no-sync Don't autosync\n"
" -r|--ro Mount read-only\n"
int
main (int argc, char *argv[])
{
- static const char *options = "a:h::m:nrv?V";
+ static const char *options = "a:f:h::im:nrv?V";
static struct option long_options[] = {
{ "add", 1, 0, 'a' },
{ "cmd-help", 2, 0, 'h' },
+ { "file", 1, 0, 'f' },
{ "help", 0, 0, '?' },
+ { "inspector", 0, 0, 'i' },
{ "mount", 1, 0, 'm' },
+ { "no-dest-paths", 0, 0, 'D' },
{ "no-sync", 0, 0, 'n' },
{ "ro", 0, 0, 'r' },
{ "verbose", 0, 0, 'v' },
{ "version", 0, 0, 'V' },
{ 0, 0, 0, 0 }
};
+ struct drv *drvs = NULL;
+ struct drv *drv;
struct mp *mps = NULL;
struct mp *mp;
- char *p;
- int c;
+ char *p, *file = NULL;
+ int c, inspector = 0;
initialize_readline ();
perror (optarg);
exit (1);
}
- if (guestfs_add_drive (g, optarg) == -1)
+ drv = malloc (sizeof (struct drv));
+ if (!drv) {
+ perror ("malloc");
+ exit (1);
+ }
+ drv->filename = optarg;
+ drv->next = drvs;
+ drvs = drv;
+ break;
+
+ case 'D':
+ complete_dest_paths = 0;
+ break;
+
+ case 'f':
+ if (file) {
+ fprintf (stderr, _("guestfish: only one -f parameter can be given\n"));
exit (1);
+ }
+ file = optarg;
break;
case 'h':
list_commands ();
exit (0);
+ case 'i':
+ inspector = 1;
+ break;
+
case 'm':
mp = malloc (sizeof (struct mp));
if (!mp) {
}
}
+ /* Inspector mode invalidates most of the other arguments. */
+ if (inspector) {
+ char cmd[1024];
+ int r;
+
+ if (drvs || mps) {
+ fprintf (stderr, _("guestfish: cannot use -i option with -a or -m\n"));
+ exit (1);
+ }
+ if (optind >= argc) {
+ fprintf (stderr, _("guestfish -i requires a libvirt domain or path(s) to disk image(s)\n"));
+ exit (1);
+ }
+
+ strcpy (cmd, "a=`virt-inspector");
+ while (optind < argc) {
+ if (strlen (cmd) + strlen (argv[optind]) + strlen (argv[0]) + 60
+ >= sizeof cmd) {
+ fprintf (stderr, _("guestfish: virt-inspector command too long for fixed-size buffer\n"));
+ exit (1);
+ }
+ strcat (cmd, " '");
+ strcat (cmd, argv[optind]);
+ strcat (cmd, "'");
+ optind++;
+ }
+
+ if (read_only)
+ strcat (cmd, " --ro-fish");
+ else
+ strcat (cmd, " --fish");
+
+ sprintf (&cmd[strlen(cmd)], "` && %s $a", argv[0]);
+
+ if (guestfs_get_verbose (g))
+ strcat (cmd, " -v");
+ if (!guestfs_get_autosync (g))
+ strcat (cmd, " -n");
+
+ /*printf ("%s\n", cmd);*/
+
+ r = system (cmd);
+ if (r == -1) {
+ perror ("system");
+ exit (1);
+ }
+ exit (WEXITSTATUS (r));
+ }
+
+ /* If we've got drives to add, add them now. */
+ add_drives (drvs);
+
/* If we've got mountpoints, we must launch the guest and mount them. */
if (mps != NULL) {
if (launch (g) == -1) exit (1);
mount_mps (mps);
}
+ /* -f (file) parameter? */
+ if (file) {
+ close (0);
+ if (open (file, O_RDONLY) == -1) {
+ perror (file);
+ exit (1);
+ }
+ }
+
/* Interactive, shell script, or command(s) on the command line? */
if (optind >= argc) {
if (isatty (0))
}
static void
+add_drives (struct drv *drv)
+{
+ int r;
+
+ if (drv) {
+ add_drives (drv->next);
+ if (!read_only)
+ r = guestfs_add_drive (g, drv->filename);
+ else
+ r = guestfs_add_drive_ro (g, drv->filename);
+ if (r == -1)
+ exit (1);
+ }
+}
+
+static void
interactive (void)
{
script (1);
}
}
-static int
+int
issue_command (const char *cmd, char *argv[])
{
int argc;
strcasecmp (cmd, "vi") == 0 ||
strcasecmp (cmd, "emacs") == 0)
return do_edit (cmd, argc, argv);
+ else if (strcasecmp (cmd, "lcd") == 0)
+ return do_lcd (cmd, argc, argv);
+ else if (strcasecmp (cmd, "glob") == 0)
+ return do_glob (cmd, argc, argv);
else
return run_action (cmd, argc, argv);
}
"echo", _("display a line of text"));
printf ("%-20s %s\n",
"edit", _("edit a file in the image"));
+ printf ("%-20s %s\n",
+ "lcd", _("local change directory"));
+ printf ("%-20s %s\n",
+ "glob", _("expand wildcards in command"));
/* actions are printed after this (see list_commands) */
}
"\n"
" NOTE: This will not work reliably for large files\n"
" (> 2 MB) or binary files containing \\0 bytes.\n"));
+ else if (strcasecmp (cmd, "lcd") == 0)
+ printf (_("lcd - local change directory\n"
+ " lcd <directory>\n"
+ "\n"
+ " Change guestfish's current directory. This command is\n"
+ " useful if you want to download files to a particular\n"
+ " place.\n"));
+ else if (strcasecmp (cmd, "glob") == 0)
+ printf (_("glob - expand wildcards in command\n"
+ " glob <command> [<args> ...]\n"
+ "\n"
+ " Glob runs <command> with wildcards expanded in any\n"
+ " command args. Note that the command is run repeatedly\n"
+ " once for each expanded argument.\n"));
else if (strcasecmp (cmd, "help") == 0)
printf (_("help - display a list of commands or help on a command\n"
" help cmd\n"
free (argv);
}
+int
+count_strings (char * const * const argv)
+{
+ int c;
+
+ for (c = 0; argv[c]; ++c)
+ ;
+ return c;
+}
+
void
print_strings (char * const * const argv)
{