rizin/librz/core/rtr_shell.c
2024-11-08 18:46:13 +08:00

244 lines
5.8 KiB
C

// SPDX-FileCopyrightText: 2019 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
static bool rtr_visual(RzCore *core, TextLog T, const char *cmd) {
RzLine *line = core->cons->line;
bool autorefresh = false;
if (cmd) {
rz_cons_break_push(NULL, NULL);
for (;;) {
char *ret;
rz_cons_clear00();
ret = rtrcmd(T, cmd);
rz_cons_println(ret);
free(ret);
rz_cons_flush();
if (rz_cons_is_breaked()) {
break;
}
rz_sys_sleep(1);
}
rz_cons_break_pop();
} else {
const char *cmds[] = { "px", "pd", "pxa", "dr", "sr SP;pxa", NULL };
int cmdidx = 0;
char *ret, ch;
free(rtrcmd(T, "e scr.color=true"));
free(rtrcmd(T, "e scr.html=false"));
for (;;) {
rz_cons_clear00();
ret = rtrcmd(T, cmds[cmdidx]);
if (ret) {
rz_cons_println(ret);
free(ret);
}
rz_cons_flush();
if (autorefresh) {
rz_cons_printf("(auto-refresh)\n");
rz_cons_flush();
rz_cons_break_push(NULL, NULL);
rz_sys_sleep(1);
if (rz_cons_is_breaked()) {
autorefresh = false;
ch = rz_cons_readchar();
} else {
rz_cons_break_pop();
continue;
}
rz_cons_break_pop();
} else {
ch = rz_cons_readchar();
}
// TODO:
// i insert hex/string/asm
// 0-9 follow jumps
switch (ch) {
case '?':
rz_cons_clear00();
rz_cons_printf("Remote Visual keys:\n"
" hjkl : move\n"
" HJKL : move faster\n"
" +-*/ : change block size\n"
" pP : rotate print modes\n"
" T : enter TextLog chat console\n"
" @ : enter auto-refresh mode\n"
" i : insert hexpair\n"
" q : quit this mode and go back to the shell\n"
" sS : step / step over\n"
" . : seek entry or pc\n");
rz_cons_flush();
rz_cons_any_key(NULL);
break;
case 'i': {
#if __UNIX__
#define COLORFLAGS (core->print->flags & RZ_PRINT_FLAGS_COLOR)
#else
#define COLORFLAGS 0
#endif
char buf[1024];
if (COLORFLAGS) {
rz_line_set_prompt(line, Color_RESET ":> ");
} else {
rz_line_set_prompt(line, ":> ");
}
showcursor(core, true);
rz_cons_fgets(buf + 3, sizeof(buf) - 3, 0, NULL);
memcpy(buf, "wx ", 3);
if (buf[3]) {
char *res = rtrcmd(T, buf);
if (res) {
rz_cons_println(res);
free(res);
}
rz_cons_flush();
}
} break;
case 's':
free(rtrcmd(T, "ds;.dr*"));
break;
case 'S':
free(rtrcmd(T, "dso;.dr*"));
break;
case '.':
free(rtrcmd(T, "s entry0;dr?rip;?? sr PC"));
break;
case ':': {
int ret;
eprintf("Press <enter> to return to Visual mode.\n");
do {
char buf[1024];
#if __UNIX__
rz_line_set_prompt(line, Color_RESET ":> ");
#else
rz_line_set_prompt(line, ":> ");
#endif
showcursor(core, true);
rz_cons_fgets(buf, sizeof(buf), 0, NULL);
if (*buf) {
rz_line_hist_add(line, buf);
char *res = rtrcmd(T, buf);
if (res) {
rz_cons_println(res);
free(res);
}
rz_cons_flush();
ret = true;
} else {
ret = false;
// rz_cons_any_key ();
rz_cons_clear00();
showcursor(core, false);
}
} while (ret);
} break;
case '@': autorefresh = true; break;
case 'j':
if (cmdidx == 1) {
free(rtrcmd(T, "so"));
break;
} else {
free(rtrcmd(T, "sd +16"));
break;
}
break;
case 'k': free(rtrcmd(T, "sd -16")); break;
case 'h': free(rtrcmd(T, "sd -1")); break;
case 'l': free(rtrcmd(T, "sd +1")); break;
case 'J':
if (cmdidx == 1) {
free(rtrcmd(T, "4so"));
} else {
free(rtrcmd(T, "sd +32"));
}
break;
case 'K': free(rtrcmd(T, "sd -32")); break;
case 'H': free(rtrcmd(T, "sd -2")); break;
case 'L': free(rtrcmd(T, "sd +2")); break;
case '+': free(rtrcmd(T, "b+1")); break;
case '*': free(rtrcmd(T, "b+16")); break;
case '-': free(rtrcmd(T, "b-1")); break;
case '/': free(rtrcmd(T, "b-16")); break;
case 'p':
cmdidx++;
if (!cmds[cmdidx]) {
cmdidx = 0;
}
break;
case 'P':
cmdidx--;
if (cmdidx < 0) {
cmdidx = 2;
}
break;
case 'q': return false;
}
}
}
return true;
}
// XXX: this needs to be moved to use the standard shell like in !=! and support visual+panels
static void __rtr_shell(RzCore *core, int nth) {
char *proto = "http";
char *host = "";
char *port = "";
char *file = "";
char prompt[64], prompt2[64], *str, *ptr;
int len;
const char *res;
RzSocket *s = NULL;
RzLine *line = core->cons->line;
TextLog T = { host, port, file };
snprintf(prompt, sizeof(prompt), "[%s://%s:%s/%s]> ",
proto, host, port, file);
snprintf(prompt2, sizeof(prompt2), "[%s:%s]$ ", host, port);
for (;;) {
rz_line_set_prompt(line, prompt);
res = rz_line_readline(line);
if (!res || !*res) {
break;
}
if (*res == 'q') {
break;
}
if (!strcmp(res, "!sh")) {
for (;;) {
rz_line_set_prompt(line, prompt2);
res = rz_line_readline(line);
if (!res || !*res || !strcmp(res, "exit")) {
break;
}
ptr = rz_str_uri_encode(res);
char *uri = rz_str_newf("http://%s:%s/%s!%s", host, port, file, res);
str = rz_socket_http_get(uri, NULL, &len);
if (str) {
str[len] = 0;
res = strstr(str, "\n\n");
if (res) {
res = strstr(res + 1, "\n\n");
}
res = res ? res + 2 : str;
const char *tail = (res[strlen(res) - 1] == '\n') ? "" : "\n";
printf("%s%s", res, tail);
rz_line_hist_add(line, str);
free(str);
}
free(ptr);
free(uri);
}
} else if (res[0] == 'v' || res[0] == 'V') {
if (res[1] == ' ') {
rtr_visual(core, T, res + 1);
} else {
rtr_visual(core, T, NULL);
}
} else {
char *cmdline = rz_str_newf("%d %s", nth, res);
rz_core_rtr_cmd(core, cmdline);
rz_cons_flush();
rz_line_hist_add(line, res);
}
}
rz_socket_free(s);
}