X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;ds=sidebyside;f=fish%2Ffish.c;h=10f645f5ddea81954b361d2ece62c20f2fd8eea1;hb=d2636b0984830d950423dadd936114ff242c4a00;hp=fbc364fca8114220701a8663c32d8edb51a250c3;hpb=4bcb267a248977c6b044e18a72266d665102de30;p=libguestfs.git diff --git a/fish/fish.c b/fish/fish.c index fbc364f..10f645f 100644 --- a/fish/fish.c +++ b/fish/fish.c @@ -45,6 +45,14 @@ #include "closeout.h" #include "progname.h" +/* Return from parse_command_line. See description below. */ +struct parsed_command { + int status; + char *pipe; + char *cmd; + char *argv[64]; +}; + static void set_up_terminal (void); static void prepare_drives (struct drv *drv); static int launch (void); @@ -52,6 +60,8 @@ static void interactive (void); static void shell_script (void); 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 @@ -605,13 +615,9 @@ static void script (int prompt) { char *buf; - char *cmd; - char *p, *pend; - char *argv[64]; - int len; int global_exit_on_error = !prompt; int exit_on_error; - int tilde_candidate; + struct parsed_command pcmd; if (prompt) { printf (_("\n" @@ -630,8 +636,6 @@ script (int prompt) } while (!quit) { - char *pipe = NULL; - exit_on_error = global_exit_on_error; buf = rl_gets (prompt); @@ -640,171 +644,243 @@ script (int prompt) break; } - /* Skip any initial whitespace before the command. */ - again: - while (*buf && c_isspace (*buf)) - buf++; + pcmd = parse_command_line (buf, &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); + } + } + } + if (prompt) printf ("\n"); +} + +/* Parse a command string, splitting at whitespace, handling '!', '#' etc. + * This destructively updates 'buf'. + * + * 'exit_on_error_rtn' is used to pass in the global exit_on_error + * setting and to return the local setting (eg. if the command begins + * with '-'). + * + * Returns in parsed_command.status: + * 1 = got a guestfish command (returned in cmd_rtn/argv_rtn/pipe_rtn) + * 0 = no guestfish command, but otherwise OK + * -1 = an error + */ +static struct parsed_command +parse_command_line (char *buf, int *exit_on_error_rtn) +{ + struct parsed_command pcmd; + char *p, *pend; + int len; + int tilde_candidate; + int r; + const size_t argv_len = sizeof pcmd.argv / sizeof pcmd.argv[0]; + + /* 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); - if (!*buf) continue; + again: + /* Skip any initial whitespace before the command. */ + while (*buf && c_isspace (*buf)) + buf++; - /* If the next character is '#' then this is a comment. */ - if (*buf == '#') continue; + if (!*buf) { + pcmd.status = 0; + return pcmd; + } - /* If the next character is '!' then pass the whole lot to system(3). */ - if (*buf == '!') { - int r; + /* If the next character is '#' then this is a comment. */ + if (*buf == '#') { + pcmd.status = 0; + return pcmd; + } - r = system (buf+1); - if (exit_on_error) { - if (r == -1 || - (WIFSIGNALED (r) && - (WTERMSIG (r) == SIGINT || WTERMSIG (r) == SIGQUIT)) || - WEXITSTATUS (r) != 0) - exit (EXIT_FAILURE); - } - continue; - } + /* If the next character is '!' then pass the whole lot to system(3). */ + if (*buf == '!') { + r = system (buf+1); + if (r == -1 || + (WIFSIGNALED (r) && + (WTERMSIG (r) == SIGINT || WTERMSIG (r) == SIGQUIT)) || + WEXITSTATUS (r) != 0) + 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). - */ - if (*buf == '-') { - exit_on_error = 0; - buf++; - goto again; - } + /* If the next two characters are " 0 && line[n-1] == '\n') + line[n-1] = '\0'; - got_command: - if (issue_command (cmd, argv, pipe, exit_on_error) == -1) { - if (exit_on_error) exit (EXIT_FAILURE); + 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); + } } + } - next_command:; + free (line); + + if (pclose (pp) == -1) { + perror ("pclose"); + return -1; } - if (prompt) printf ("\n"); + + return 0; } static void