From c1bc7ef982d1021579a141b119762fb3c36ca4b1 Mon Sep 17 00:00:00 2001 From: Bomin Zhang Date: Tue, 26 May 2020 16:51:26 +0800 Subject: [PATCH] shell suport multiple commands in single statement --- src/kit/shell/src/shellDarwin.c | 9 +- src/kit/shell/src/shellEngine.c | 191 +++++++++++++++++-------------- src/kit/shell/src/shellLinux.c | 10 +- src/kit/shell/src/shellWindows.c | 7 +- 4 files changed, 111 insertions(+), 106 deletions(-) diff --git a/src/kit/shell/src/shellDarwin.c b/src/kit/shell/src/shellDarwin.c index e4ef06c403..987087d71f 100644 --- a/src/kit/shell/src/shellDarwin.c +++ b/src/kit/shell/src/shellDarwin.c @@ -335,17 +335,14 @@ void *shellLoopQuery(void *arg) { tscError("failed to malloc command"); return NULL; } - while (1) { - // Read command from shell. + do { + // Read command from shell. memset(command, 0, MAX_COMMAND_SIZE); set_terminal_mode(); shellReadCommand(con, command); reset_terminal_mode(); - - // Run the command - shellRunCommand(con, command); - } + } while (shellRunCommand(con, command) == 0); pthread_cleanup_pop(1); diff --git a/src/kit/shell/src/shellEngine.c b/src/kit/shell/src/shellEngine.c index 93818d7d73..4ef51eaa5a 100644 --- a/src/kit/shell/src/shellEngine.c +++ b/src/kit/shell/src/shellEngine.c @@ -82,20 +82,15 @@ TAOS *shellInit(SShellArguments *args) { // Check if it is temperory run if (args->commands != NULL || args->file[0] != 0) { if (args->commands != NULL) { - char *token; - token = strtok(args->commands, ";"); - while (token != NULL) { - printf("%s%s\n", PROMPT_HEADER, token); - shellRunCommand(con, token); - token = strtok(NULL, ";"); - } + printf("%s%s\n", PROMPT_HEADER, args->commands); + shellRunCommand(con, args->commands); } if (args->file[0] != 0) { source_file(con, args->file); } - taos_close(con); + taos_close(con); write_history(); exit(EXIT_SUCCESS); } @@ -111,96 +106,37 @@ TAOS *shellInit(SShellArguments *args) { return con; } -void shellReplaceCtrlChar(char *str) { - _Bool ctrlOn = false; - char *pstr = NULL; - char quote = 0; - for (pstr = str; *str != '\0'; ++str) { - if (ctrlOn) { - switch (*str) { - case 'n': - *pstr = '\n'; - pstr++; - break; - case 'r': - *pstr = '\r'; - pstr++; - break; - case 't': - *pstr = '\t'; - pstr++; - break; - case 'G': - *pstr++ = '\\'; - *pstr++ = *str; - break; - case '\\': - *pstr = '\\'; - pstr++; - break; - case '\'': - case '"': - if (quote) { - *pstr++ = '\\'; - *pstr++ = *str; - } - break; - default: - *pstr = *str; - pstr++; - break; - } - ctrlOn = false; - } else { - if (*str == '\\') { - ctrlOn = true; - } else { - if (quote == *str) { - quote = 0; - } else if (*str == '\'' || *str == '"') { - quote = *str; - } - *pstr = *str; - pstr++; - } +static bool isEmptyCommand(const char* cmd) { + for (char c = *cmd++; c != 0; c = *cmd++) { + if (c != ' ' && c != '\t' && c != ';') { + return false; } } - *pstr = '\0'; + return true; } -int32_t shellRunCommand(TAOS *con, char *command) { + +static int32_t shellRunSingleCommand(TAOS *con, char *command) { /* If command is empty just return */ - if (regex_match(command, "^[ \t;]*$", REG_EXTENDED)) { + if (isEmptyCommand(command)) { return 0; } - /* Update the history vector. */ - if (history.hstart == history.hend || - history.hist[(history.hend + MAX_HISTORY_SIZE - 1) % MAX_HISTORY_SIZE] == NULL || - strcmp(command, history.hist[(history.hend + MAX_HISTORY_SIZE - 1) % MAX_HISTORY_SIZE]) != 0) { - if (history.hist[history.hend] != NULL) { - tfree(history.hist[history.hend]); - } - history.hist[history.hend] = strdup(command); - - history.hend = (history.hend + 1) % MAX_HISTORY_SIZE; - if (history.hend == history.hstart) { - history.hstart = (history.hstart + 1) % MAX_HISTORY_SIZE; - } - } - - shellReplaceCtrlChar(command); - // Analyse the command. if (regex_match(command, "^[ \t]*(quit|q|exit)[ \t;]*$", REG_EXTENDED | REG_ICASE)) { taos_close(con); write_history(); return -1; - } else if (regex_match(command, "^[\t ]*clear[ \t;]*$", REG_EXTENDED | REG_ICASE)) { + } + + if (regex_match(command, "^[\t ]*clear[ \t;]*$", REG_EXTENDED | REG_ICASE)) { // If clear the screen. system("clear"); - } else if (regex_match(command, "^[\t ]*set[ \t]+max_binary_display_width[ \t]+(default|[1-9][0-9]*)[ \t;]*$", REG_EXTENDED | REG_ICASE)) { + return 0; + } + + if (regex_match(command, "^[\t ]*set[ \t]+max_binary_display_width[ \t]+(default|[1-9][0-9]*)[ \t;]*$", REG_EXTENDED | REG_ICASE)) { strtok(command, " \t"); strtok(NULL, " \t"); char* p = strtok(NULL, " \t"); @@ -209,21 +145,102 @@ int32_t shellRunCommand(TAOS *con, char *command) { } else { tsMaxBinaryDisplayWidth = atoi(p); } - } else if (regex_match(command, "^[ \t]*source[\t ]+[^ ]+[ \t;]*$", REG_EXTENDED | REG_ICASE)) { + return 0; + } + + if (regex_match(command, "^[ \t]*source[\t ]+[^ ]+[ \t;]*$", REG_EXTENDED | REG_ICASE)) { /* If source file. */ char *c_ptr = strtok(command, " ;"); assert(c_ptr != NULL); c_ptr = strtok(NULL, " ;"); assert(c_ptr != NULL); - source_file(con, c_ptr); - } else { - shellRunCommandOnServer(con, command); + return 0; } - + + shellRunCommandOnServer(con, command); return 0; } + +int32_t shellRunCommand(TAOS* con, char* command) { + /* If command is empty just return */ + if (isEmptyCommand(command)) { + return 0; + } + + /* Update the history vector. */ + if (history.hstart == history.hend || + history.hist[(history.hend + MAX_HISTORY_SIZE - 1) % MAX_HISTORY_SIZE] == NULL || + strcmp(command, history.hist[(history.hend + MAX_HISTORY_SIZE - 1) % MAX_HISTORY_SIZE]) != 0) { + if (history.hist[history.hend] != NULL) { + tfree(history.hist[history.hend]); + } + history.hist[history.hend] = strdup(command); + + history.hend = (history.hend + 1) % MAX_HISTORY_SIZE; + if (history.hend == history.hstart) { + history.hstart = (history.hstart + 1) % MAX_HISTORY_SIZE; + } + } + + bool esc = false; + char quote = 0, *cmd = command, *p = command; + for (char c = *command++; c != 0; c = *command++) { + if (esc) { + switch (c) { + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'G': + *p++ = '\\'; + break; + case '\'': + case '"': + if (quote) { + *p++ = '\\'; + } + break; + } + *p++ = c; + esc = false; + continue; + } + + if (c == '\\') { + esc = true; + continue; + } + + if (quote == c) { + quote = 0; + } else if (c == '\'' || c == '"') { + quote = c; + } + + *p++ = c; + if (c == ';') { + c = *p; + *p = 0; + if (shellRunSingleCommand(con, cmd) < 0) { + return -1; + } + *p = c; + p = cmd; + } + } + + *p = 0; + return shellRunSingleCommand(con, cmd); +} + + void shellRunCommandOnServer(TAOS *con, char command[]) { int64_t st, et; wordexp_t full_path; diff --git a/src/kit/shell/src/shellLinux.c b/src/kit/shell/src/shellLinux.c index 856e011a78..d8b3e9bb4d 100644 --- a/src/kit/shell/src/shellLinux.c +++ b/src/kit/shell/src/shellLinux.c @@ -307,19 +307,13 @@ void *shellLoopQuery(void *arg) { return NULL; } - while (1) { + do { // Read command from shell. - memset(command, 0, MAX_COMMAND_SIZE); set_terminal_mode(); shellReadCommand(con, command); reset_terminal_mode(); - - // Run the command - if (shellRunCommand(con, command) != 0) { - break; - } - } + } while (shellRunCommand(con, command) == 0); tfree(command); exitShell(); diff --git a/src/kit/shell/src/shellWindows.c b/src/kit/shell/src/shellWindows.c index c446677276..440aa508ab 100644 --- a/src/kit/shell/src/shellWindows.c +++ b/src/kit/shell/src/shellWindows.c @@ -203,16 +203,13 @@ void *shellLoopQuery(void *arg) { char *command = malloc(MAX_COMMAND_SIZE); if (command == NULL) return NULL; - while (1) { + do { memset(command, 0, MAX_COMMAND_SIZE); shellPrintPrompt(); // Read command from shell. shellReadCommand(con, command); - - // Run the command - shellRunCommand(con, command); - } + } while (shellRunCommand(con, command) == 0); return NULL; } -- GitLab