#include <assert.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <locale.h>
#ifdef HAVE_LIBREADLINE
#include <readline/readline.h>
static void cmdline (char *argv[], int optind, int argc);
static void initialize_readline (void);
static void cleanup_readline (void);
+#ifdef HAVE_LIBREADLINE
static void add_history_line (const char *);
+#endif
/* Currently open libguestfs handle. */
guestfs_h *g;
int read_only = 0;
int quit = 0;
int verbose = 0;
-int echo_commands = 0;
int remote_control_listen = 0;
int remote_control = 0;
int exit_on_error = 1;
+int command_num = 0;
int
launch (guestfs_h *_g)
file = optarg;
break;
- case 'h':
+ case 'h': {
+ int r = 0;
+
if (optarg)
- display_command (optarg);
+ r = display_command (optarg);
else if (argv[optind] && argv[optind][0] != '-')
- display_command (argv[optind++]);
+ r = display_command (argv[optind++]);
else
list_commands ();
- exit (EXIT_SUCCESS);
+
+ exit (r == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
+ }
case 'i':
inspector = 1;
exit (EXIT_SUCCESS);
case 'x':
- echo_commands = 1;
+ guestfs_set_trace (g, 1);
break;
case HELP_OPTION:
strcat (cmd, " -v");
if (!guestfs_get_autosync (g))
strcat (cmd, " -n");
+ if (guestfs_get_trace (g))
+ strcat (cmd, " -x");
if (verbose)
fprintf (stderr,
fprintf (stderr, _("%s: empty command on command line\n"), program_name);
exit (EXIT_FAILURE);
}
+
+ /* Allow -cmd on the command line to mean (temporarily) override
+ * the normal exit on error (RHBZ#578407).
+ */
+ if (cmd[0] == '-') {
+ exit_on_error = 0;
+ cmd++;
+ }
+
params = &argv[optind];
/* Search for end of command list or ":" ... */
optind++;
if (optind == argc) {
- if (issue_command (cmd, params, NULL) == -1) exit (EXIT_FAILURE);
+ if (issue_command (cmd, params, NULL) == -1 && exit_on_error)
+ exit (EXIT_FAILURE);
} else {
argv[optind] = NULL;
- if (issue_command (cmd, params, NULL) == -1) exit (EXIT_FAILURE);
+ if (issue_command (cmd, params, NULL) == -1 && exit_on_error)
+ exit (EXIT_FAILURE);
cmdline (argv, optind+1, argc);
}
}
int pid = 0;
int i, r;
- if (echo_commands) {
- printf ("%s", cmd);
- for (i = 0; argv[i] != NULL; ++i)
- printf (" %s", argv[i]);
- printf ("\n");
- }
+ /* This counts the commands issued, starting at 1. */
+ command_num++;
/* For | ... commands. Annoyingly we can't use popen(3) here. */
if (pipecmd) {
/* Otherwise execute it locally. */
else if (STRCASEEQ (cmd, "help")) {
- if (argc == 0)
+ if (argc == 0) {
list_commands ();
- else
- display_command (argv[0]);
- r = 0;
+ r = 0;
+ } else
+ r = display_command (argv[0]);
}
else if (STRCASEEQ (cmd, "quit") ||
STRCASEEQ (cmd, "exit") ||
/* actions are printed after this (see list_commands) */
}
-void
+int
display_builtin_command (const char *cmd)
{
/* help for actions is auto-generated, see display_command */
if (STRCASEEQ (cmd, "alloc") ||
- STRCASEEQ (cmd, "allocate"))
+ STRCASEEQ (cmd, "allocate")) {
printf (_("alloc - allocate an image\n"
" alloc <filename> <size>\n"
"\n"
" <nn>P or <nn>PB number of petabytes\n"
" <nn>E or <nn>EB number of exabytes\n"
" <nn>sects number of 512 byte sectors\n"));
- else if (STRCASEEQ (cmd, "echo"))
+ return 0;
+ }
+ else if (STRCASEEQ (cmd, "echo")) {
printf (_("echo - display a line of text\n"
" echo [<params> ...]\n"
"\n"
" This echos the parameters to the terminal.\n"));
+ return 0;
+ }
else if (STRCASEEQ (cmd, "edit") ||
STRCASEEQ (cmd, "vi") ||
- STRCASEEQ (cmd, "emacs"))
+ STRCASEEQ (cmd, "emacs")) {
printf (_("edit - edit a file in the image\n"
" edit <filename>\n"
"\n"
"\n"
" NOTE: This will not work reliably for large files\n"
" (> 2 MB) or binary files containing \\0 bytes.\n"));
- else if (STRCASEEQ (cmd, "lcd"))
+ return 0;
+ }
+ else if (STRCASEEQ (cmd, "lcd")) {
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 (STRCASEEQ (cmd, "glob"))
+ return 0;
+ }
+ else if (STRCASEEQ (cmd, "glob")) {
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 (STRCASEEQ (cmd, "help"))
+ return 0;
+ }
+ else if (STRCASEEQ (cmd, "help")) {
printf (_("help - display a list of commands or help on a command\n"
" help cmd\n"
" help\n"));
+ return 0;
+ }
else if (STRCASEEQ (cmd, "more") ||
- STRCASEEQ (cmd, "less"))
+ STRCASEEQ (cmd, "less")) {
printf (_("more - view a file in the pager\n"
" more <filename>\n"
"\n"
"\n"
" NOTE: This will not work reliably for large files\n"
" (> 2 MB) or binary files containing \\0 bytes.\n"));
+ return 0;
+ }
else if (STRCASEEQ (cmd, "quit") ||
STRCASEEQ (cmd, "exit") ||
- STRCASEEQ (cmd, "q"))
+ STRCASEEQ (cmd, "q")) {
printf (_("quit - quit guestfish\n"
" quit\n"));
- else if (STRCASEEQ (cmd, "reopen"))
+ return 0;
+ }
+ else if (STRCASEEQ (cmd, "reopen")) {
printf (_("reopen - close and reopen the libguestfs handle\n"
" reopen\n"
"\n"
"Close and reopen the libguestfs handle. It is not necessary to use\n"
"this normally, because the handle is closed properly when guestfish\n"
"exits. However this is occasionally useful for testing.\n"));
- else if (STRCASEEQ (cmd, "sparse"))
+ return 0;
+ }
+ else if (STRCASEEQ (cmd, "sparse")) {
printf (_("sparse - allocate a sparse image file\n"
" sparse <filename> <size>\n"
"\n"
" <nn>P or <nn>PB number of petabytes\n"
" <nn>E or <nn>EB number of exabytes\n"
" <nn>sects number of 512 byte sectors\n"));
- else if (STRCASEEQ (cmd, "time"))
+ return 0;
+ }
+ else if (STRCASEEQ (cmd, "time")) {
printf (_("time - measure time taken to run command\n"
" time <command> [<args> ...]\n"
"\n"
" This runs <command> as usual, and prints the elapsed\n"
" time afterwards.\n"));
- else
+ return 0;
+ }
+ else {
fprintf (stderr, _("%s: command not known, use -h to list all commands\n"),
cmd);
+ return -1;
+ }
+}
+
+/* This is printed when the user types in an unknown command for the
+ * first command issued. A common case is the user doing:
+ * guestfish disk.img
+ * expecting guestfish to open 'disk.img' (in fact, this tried to
+ * run a command 'disk.img').
+ */
+void
+extended_help_message (void)
+{
+ fprintf (stderr,
+ _("Did you mean to open a disk image? guestfish -a disk.img\n"
+ "For a list of commands: guestfish -h\n"
+ "For complete documentation: man guestfish\n"));
}
void
rl_readline_name = "guestfish";
rl_attempted_completion_function = do_completion;
+
+ /* Note that .inputrc (or /etc/inputrc) is not read until the first
+ * call the readline(), which happens later. Therefore, these
+ * provide default values which can be overridden by the user if
+ * they wish.
+ */
+ (void) rl_variable_bind ("completion-ignore-case", "on");
#endif
}
}
close (fd);
+#ifdef HAVE_APPEND_HISTORY
(void) append_history (nr_history_lines, histfile);
+#else
+ (void) write_history (histfile);
+#endif
}
#endif
}
+#ifdef HAVE_LIBREADLINE
static void
add_history_line (const char *line)
{
-#ifdef HAVE_LIBREADLINE
add_history (line);
nr_history_lines++;
-#endif
}
+#endif
int
xwrite (int fd, const void *v_buf, size_t len)