Skip to content
Snippets Groups Projects
Commit 236e46c2 authored by Konstantin Osipov's avatar Konstantin Osipov
Browse files

Merge remote-tracking branch 'origin/tc-newline-fix'

Conflicts:
	client/tarantool/tc_cli.c
parents 00ba6cbc ace8cfff
No related branches found
No related tags found
No related merge requests found
...@@ -37,9 +37,10 @@ ...@@ -37,9 +37,10 @@
/* Strip trailing ws from (char*) */ /* Strip trailing ws from (char*) */
size_t strip_end_ws(char *str) { size_t strip_end_ws(char *str) {
size_t last = 0; size_t last = 0;
for (size_t i = 0; str[i] != 0; ++i) for (size_t i = 0; str[i] != 0; ++i) {
if (!isspace(str[i])) if (!isspace(str[i]))
last = i + 1; last = i + 1;
}
str[last] = '\0'; str[last] = '\0';
return last; return last;
} }
...@@ -49,16 +50,18 @@ int tc_buf(struct tc_buf *buf) { ...@@ -49,16 +50,18 @@ int tc_buf(struct tc_buf *buf) {
buf->size = TC_BUF_INIT_SIZE; buf->size = TC_BUF_INIT_SIZE;
buf->used = 0; buf->used = 0;
buf->data = (char *)malloc(buf->size); buf->data = (char *)malloc(buf->size);
if (buf->data == NULL) if (buf->data == NULL) {
return -1; return -1;
}
return 0; return 0;
} }
/* Append len bytes of memory from str pointed memory */ /* Append len bytes of memory from str pointed memory */
int tc_buf_append(struct tc_buf *buf, void *str, size_t len) { int tc_buf_append(struct tc_buf *buf, void *str, size_t len) {
if (buf->size - buf->used < len) { if (buf->size - buf->used < len) {
if (buf->size < len) if (buf->size < len) {
buf->size = len; buf->size = len;
}
buf->size *= TC_BUF_MULTIPLIER; buf->size *= TC_BUF_MULTIPLIER;
char *nd = (char *)realloc(buf->data, buf->size); char *nd = (char *)realloc(buf->data, buf->size);
if (nd == NULL) if (nd == NULL)
...@@ -112,6 +115,26 @@ int tc_buf_str_append(struct tc_buf *buf, char *str, size_t len) { ...@@ -112,6 +115,26 @@ int tc_buf_str_append(struct tc_buf *buf, char *str, size_t len) {
return 0; return 0;
} }
/* Remove last num symbols from STR */
size_t tc_buf_str_delete(struct tc_buf *buf, size_t len) {
size_t ret = tc_buf_delete(buf, len + 1); /* Remove '\0' + len */
if (tc_buf_append(buf, (void *)"\0", 1))
return 0;
return ret;
}
/*
* Make admin command from multiline command
* and delete delimiter (last num bytes)
*/
void tc_buf_cmdfy(struct tc_buf *buf, size_t num) {
tc_buf_str_delete(buf, num);
for (int i = 0; i < buf->used; ++i) {
if (buf->data[i] == '\n')
buf->data[i] = ' ';
}
}
/* Remove trailing ws from STR */ /* Remove trailing ws from STR */
int tc_buf_str_stripws(struct tc_buf *buf) { int tc_buf_str_stripws(struct tc_buf *buf) {
if (buf->data) { if (buf->data) {
......
...@@ -40,12 +40,15 @@ struct tc_buf { ...@@ -40,12 +40,15 @@ struct tc_buf {
int tc_buf(struct tc_buf *buf); int tc_buf(struct tc_buf *buf);
void *tc_buf_realloc(void *data, size_t size); void *tc_buf_realloc(void *data, size_t size);
int tc_buf_append(struct tc_buf *buf, void *str, size_t len); int tc_buf_append(struct tc_buf *buf, void *str, size_t len);
size_t tc_buf_delete(struct tc_buf *buf, size_t len); size_t tc_buf_delete(struct tc_buf *buf, size_t num);
int tc_buf_isempty(struct tc_buf *buf); int tc_buf_isempty(struct tc_buf *buf);
void tc_buf_clear(struct tc_buf *buf); void tc_buf_clear(struct tc_buf *buf);
void tc_buf_free(struct tc_buf *buf); void tc_buf_free(struct tc_buf *buf);
int tc_buf_str(struct tc_buf *buf); int tc_buf_str(struct tc_buf *buf);
int tc_buf_str_append(struct tc_buf *buf, char *str, size_t len); int tc_buf_str_append(struct tc_buf *buf, char *str, size_t len);
size_t tc_buf_str_delete(struct tc_buf *buf, size_t num);
int tc_buf_str_stripws(struct tc_buf *buf); int tc_buf_str_stripws(struct tc_buf *buf);
int tc_buf_str_isempty(struct tc_buf *buf); int tc_buf_str_isempty(struct tc_buf *buf);
void tc_buf_cmdfy(struct tc_buf *buf, size_t num);
...@@ -124,13 +124,13 @@ tc_cmd_usage(void) ...@@ -124,13 +124,13 @@ tc_cmd_usage(void)
{ {
char usage[] = char usage[] =
"---\n" "---\n"
"- console client commands\n" "console client commands:\n"
"- - help\n" " - help\n"
" - tee 'path'\n" " - tee 'path'\n"
" - notee\n" " - notee\n"
" - loadfile 'path'\n" " - loadfile 'path'\n"
" - setopt key=val\n" " - setopt key val\n"
" - (possible pairs: delim[iter]=\'string\')\n" " - (possible pairs: delimiter 'string')\n"
"...\n"; "...\n";
tc_printf("%s", usage); tc_printf("%s", usage);
} }
...@@ -224,6 +224,17 @@ tc_cmd_loadfile(char *path, int *reconnect) ...@@ -224,6 +224,17 @@ tc_cmd_loadfile(char *path, int *reconnect)
return rc; return rc;
} }
static void replace_newline(char *cmd) {
int len = strlen(cmd);
int offset = 0;
for (int i = 0; i < len - 1; ++i)
if (cmd[i] == '\\' && cmd[i + 1] == 'n')
cmd[i++ - offset++] = '\n';
else if (offset != 0)
cmd[i - offset] = cmd[i];
cmd[len - offset] = '\0';
}
static enum tc_cli_cmd_ret static enum tc_cli_cmd_ret
tc_cmd_try(char *cmd, size_t size, int *reconnect) tc_cmd_try(char *cmd, size_t size, int *reconnect)
{ {
...@@ -262,8 +273,10 @@ tc_cmd_try(char *cmd, size_t size, int *reconnect) ...@@ -262,8 +273,10 @@ tc_cmd_try(char *cmd, size_t size, int *reconnect)
case TC_SETOPT: case TC_SETOPT:
switch (tnt_lex(&lex, &tk)) { switch (tnt_lex(&lex, &tk)) {
case TC_SETOPT_DELIM: case TC_SETOPT_DELIM:
if (tnt_lex(&lex, &tk) == '=' && if (tnt_lex(&lex, &tk) != '=') {
tnt_lex(&lex, &tk) == TNT_TK_STRING) { tnt_lex_push(&lex, tk);
}
if (tnt_lex(&lex, &tk) == TNT_TK_STRING) {
if (!TNT_TK_S(tk)->size) { if (!TNT_TK_S(tk)->size) {
tc.opt.delim = ""; tc.opt.delim = "";
tc.opt.delim_len = 0; tc.opt.delim_len = 0;
...@@ -276,11 +289,12 @@ tc_cmd_try(char *cmd, size_t size, int *reconnect) ...@@ -276,11 +289,12 @@ tc_cmd_try(char *cmd, size_t size, int *reconnect)
strncpy(temp, strncpy(temp,
(const char *)TNT_TK_S(tk)->data, (const char *)TNT_TK_S(tk)->data,
TNT_TK_S(tk)->size + 1); TNT_TK_S(tk)->size + 1);
replace_newline(temp);
tc.opt.delim = temp; tc.opt.delim = temp;
tc.opt.delim_len = strlen(tc.opt.delim); tc.opt.delim_len = strlen(tc.opt.delim);
} else { } else {
tc_printf("---\n"); tc_printf("---\n");
tc_printf(" - Expected: setopt delim[iter]='string'\n"); tc_printf(" - Expected `setopt delimiter 'string'`\n");
tc_printf("---\n"); tc_printf("---\n");
} }
break; break;
...@@ -380,9 +394,9 @@ static char* tc_cli_readline_pipe() { ...@@ -380,9 +394,9 @@ static char* tc_cli_readline_pipe() {
ungetc(c_t, stdin); ungetc(c_t, stdin);
wctomb(str + pos++, 0); wctomb(str + pos++, 0);
break; break;
} } else {
else
pos += wctomb(str + pos, c); pos += wctomb(str + pos, c);
}
} }
if (pos == 1 && c == WEOF) { if (pos == 1 && c == WEOF) {
free(str); free(str);
...@@ -393,7 +407,6 @@ static char* tc_cli_readline_pipe() { ...@@ -393,7 +407,6 @@ static char* tc_cli_readline_pipe() {
static int check_delim(char* str, size_t len, size_t sep_len) { static int check_delim(char* str, size_t len, size_t sep_len) {
const char *sep = tc.opt.delim; const char *sep = tc.opt.delim;
len = strip_end_ws(str);
if (sep_len == 0) if (sep_len == 0)
return 1; return 1;
if (len < sep_len) if (len < sep_len)
...@@ -402,8 +415,6 @@ static int check_delim(char* str, size_t len, size_t sep_len) { ...@@ -402,8 +415,6 @@ static int check_delim(char* str, size_t len, size_t sep_len) {
for (i = len; sep_len > 0; --sep_len, --i) for (i = len; sep_len > 0; --sep_len, --i)
if (str[i - 1] != sep[sep_len - 1]) if (str[i - 1] != sep[sep_len - 1])
return 0; return 0;
str[i] = '\0';
len = strip_end_ws(str);
return 1; return 1;
} }
...@@ -433,44 +444,44 @@ int tc_cli(void) ...@@ -433,44 +444,44 @@ int tc_cli(void)
if (isatty(STDIN_FILENO)) { if (isatty(STDIN_FILENO)) {
snprintf(prompt_delim, sizeof(prompt_delim), snprintf(prompt_delim, sizeof(prompt_delim),
"%*s> ", prompt_len, "-"); "%*s> ", prompt_len, "-");
part_cmd = readline(!tc_buf_str_isempty(&cmd) ? prompt_delim part_cmd = readline(! tc_buf_str_isempty(&cmd)
: prompt); ? prompt_delim
: prompt);
} else { } else {
clearerr(stdin); clearerr(stdin);
part_cmd = tc_cli_readline_pipe(); part_cmd = tc_cli_readline_pipe();
} }
if (!part_cmd) if (!part_cmd)
break; break;
size_t part_cmd_len = strlen(part_cmd);
int delim_exists = check_delim(part_cmd,
part_cmd_len,
tc.opt.delim_len);
if (tc_buf_str_append(&cmd, part_cmd, strlen(part_cmd))) if (tc_buf_str_append(&cmd, part_cmd, strlen(part_cmd)))
tc_error(TC_REALLOCATION_ERROR, tc_error(TC_REALLOCATION_ERROR,
cmd.size); cmd.size);
int delim_exists = check_delim( cmd.data,
cmd.used - 1,
tc.opt.delim_len);
if (tc_buf_str_append(&cmd, "\n", 1)) /* Append '\n' to the STR */
tc_error(TC_REALLOCATION_ERROR,
cmd.size);
free(part_cmd); free(part_cmd);
if (!delim_exists && !feof(stdin)) { if (!delim_exists && !feof(stdin)) /* If still without delimiter and not EOF */
if (tc_buf_str_append(&cmd, " ", 1))
tc_error(TC_REALLOCATION_ERROR,
cmd.size);
continue; continue;
} tc_buf_str_delete(&cmd, 1); /* Delete last appended '\n' */
tc_buf_str_stripws(&cmd); if (isatty(STDIN_FILENO)) /* Enable history on readline use only */
add_history(cmd.data);
tc_buf_cmdfy(&cmd, tc.opt.delim_len); /* Create admin cmd from STR */
if (delim_exists && tc_buf_str_isempty(&cmd)) if (delim_exists && tc_buf_str_isempty(&cmd))
goto next; goto next; /* If empty - don't send to server, it crashes */
tc_print_cmd2tee(cmd.used != 1 ? prompt_delim : prompt, tc_print_cmd2tee(cmd.used != 1 ? prompt_delim : prompt,
cmd.data, cmd.used - 1); cmd.data, cmd.used - 1);
enum tc_cli_cmd_ret ret = tc_cli_cmd(cmd.data, enum tc_cli_cmd_ret ret = tc_cli_cmd(cmd.data,
cmd.used - 1); cmd.used - 1);
if (isatty(STDIN_FILENO))
add_history(cmd.data);
next: next:
tc_buf_clear(&cmd); tc_buf_clear(&cmd);
if (ret == TC_CLI_EXIT || feof(stdin)) { if (ret == TC_CLI_EXIT || feof(stdin)) {
tc_buf_free(&cmd); tc_buf_free(&cmd);
break; break;
} }
} }
/* updating history file */ /* updating history file */
write_history(history); write_history(history);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment