mirror of
https://github.com/radareorg/radare2.git
synced 2025-01-19 12:22:43 +00:00
[rarun2] Added pseudo tty for listen and connect (#6328)
* [rarun2] added pseudo tty for listen and connect * Fixed the socket connect error message * [rarun2] moved pseudo tty under pty option
This commit is contained in:
parent
3ca5f5f1f7
commit
79a609630f
@ -205,6 +205,7 @@ typedef struct r_run_profile_t {
|
||||
char *_input;
|
||||
char *_connect;
|
||||
char *_listen;
|
||||
int _pty;
|
||||
int _timeout;
|
||||
int _timeout_sig;
|
||||
int _nice;
|
||||
|
@ -46,6 +46,8 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define HAVE_PTY __UNIX__ && !__ANDROID__ && LIBC_HAVE_FORK
|
||||
|
||||
R_API RRunProfile *r_run_new(const char *str) {
|
||||
RRunProfile *p = R_NEW (RRunProfile);
|
||||
if (p) {
|
||||
@ -221,7 +223,7 @@ static void setASLR(int enabled) {
|
||||
}
|
||||
|
||||
static int handle_redirection_proc (const char *cmd, bool in, bool out, bool err) {
|
||||
#if __UNIX__ && !__ANDROID__ && LIBC_HAVE_FORK
|
||||
#if HAVE_PTY
|
||||
// use PTY to redirect I/O because pipes can be problematic in
|
||||
// case of interactive programs.
|
||||
int fdm;
|
||||
@ -352,6 +354,7 @@ R_API int r_run_parseline (RRunProfile *p, char *b) {
|
||||
else if (!strcmp (b, "pidfile")) p->_pidfile = strdup (e);
|
||||
else if (!strcmp (b, "connect")) p->_connect = strdup (e);
|
||||
else if (!strcmp (b, "listen")) p->_listen = strdup (e);
|
||||
else if (!strcmp (b, "pty")) p->_pty = parseBool (e);
|
||||
else if (!strcmp (b, "stdio")) {
|
||||
if (e[0] == '!') {
|
||||
p->_stdio = strdup (e);
|
||||
@ -448,6 +451,7 @@ R_API const char *r_run_help() {
|
||||
"timeout=3\n"
|
||||
"# connect=localhost:8080\n"
|
||||
"# listen=8080\n"
|
||||
"# pty=false\n"
|
||||
"# fork=true\n"
|
||||
"# bits=32\n"
|
||||
"# pid=0\n"
|
||||
@ -475,6 +479,116 @@ R_API const char *r_run_help() {
|
||||
"# nice=5\n";
|
||||
}
|
||||
|
||||
#if __UNIX__
|
||||
static int fd_forward(int in_fd, int out_fd, char **buff) {
|
||||
int size = 0;
|
||||
|
||||
if (ioctl (in_fd, FIONREAD, &size) == -1) {
|
||||
perror ("ioctl");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (size == 0) { // child process exited or socket is closed
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *new_buff = realloc (*buff, size);
|
||||
if (new_buff == NULL) {
|
||||
eprintf ("Failed to allocate buffer for redirection");
|
||||
return -1;
|
||||
}
|
||||
*buff = new_buff;
|
||||
|
||||
read (in_fd, *buff, size);
|
||||
|
||||
if (write (out_fd, *buff, size) != size) {
|
||||
perror ("write");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int redirect_socket_to_stdio(RSocket *sock) {
|
||||
close (0);
|
||||
close (1);
|
||||
close (2);
|
||||
|
||||
dup2 (sock->fd, 0);
|
||||
dup2 (sock->fd, 1);
|
||||
dup2 (sock->fd, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int redirect_socket_to_pty(RSocket *sock) {
|
||||
#if HAVE_PTY
|
||||
// directly duplicating the fds using dup2() creates problems
|
||||
// in case of interactive applications
|
||||
int fdm;
|
||||
|
||||
pid_t child_pid = forkpty (&fdm, NULL, NULL, NULL);
|
||||
if (child_pid == -1) {
|
||||
perror ("forking pty");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (child_pid == 0) {
|
||||
// child process
|
||||
r_socket_close_fd (sock);
|
||||
|
||||
// disable the echo on slave stdin
|
||||
struct termios t;
|
||||
tcgetattr (0, &t);
|
||||
cfmakeraw (&t);
|
||||
tcsetattr (0, TCSANOW, &t);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// parent
|
||||
char *buff = NULL;
|
||||
int sockfd = sock->fd;
|
||||
int max_fd = fdm > sockfd ? fdm : sockfd;
|
||||
|
||||
while (true) {
|
||||
fd_set readfds;
|
||||
FD_ZERO (&readfds);
|
||||
FD_SET (fdm, &readfds);
|
||||
FD_SET (sockfd, &readfds);
|
||||
|
||||
int activity = select (max_fd + 1, &readfds, NULL, NULL, NULL);
|
||||
|
||||
if (activity < 0) {
|
||||
perror ("select error");
|
||||
break;
|
||||
}
|
||||
|
||||
if (FD_ISSET (fdm, &readfds)) {
|
||||
if (fd_forward (fdm, sockfd, &buff) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET (sockfd, &readfds)) {
|
||||
if (fd_forward (sockfd, fdm, &buff) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free (buff);
|
||||
close (fdm);
|
||||
r_socket_free (sock);
|
||||
|
||||
_exit (0);
|
||||
#else
|
||||
// Fallback to socket to I/O redirection
|
||||
return redirect_socket_to_stdio (sock);
|
||||
#endif
|
||||
}
|
||||
|
||||
R_API int r_run_config_env(RRunProfile *p) {
|
||||
int ret;
|
||||
|
||||
@ -521,12 +635,15 @@ R_API int r_run_config_env(RRunProfile *p) {
|
||||
return 1;
|
||||
}
|
||||
eprintf ("connected\n");
|
||||
close (0);
|
||||
close (1);
|
||||
close (2);
|
||||
dup2 (fd->fd, 0);
|
||||
dup2 (fd->fd, 1);
|
||||
dup2 (fd->fd, 2);
|
||||
if (p->_pty) {
|
||||
if (redirect_socket_to_pty (fd) != 0) {
|
||||
eprintf ("socket redirection failed\n");
|
||||
r_socket_free (fd);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
redirect_socket_to_stdio (fd);
|
||||
}
|
||||
} else {
|
||||
eprintf ("Invalid format for connect. missing ':'\n");
|
||||
return 1;
|
||||
@ -561,12 +678,16 @@ R_API int r_run_config_env(RRunProfile *p) {
|
||||
if (is_child) {
|
||||
r_socket_close_fd (fd);
|
||||
eprintf ("connected\n");
|
||||
close (0);
|
||||
close (1);
|
||||
close (2);
|
||||
dup2 (child->fd, 0);
|
||||
dup2 (child->fd, 1);
|
||||
dup2 (child->fd, 2);
|
||||
if (p->_pty) {
|
||||
if (redirect_socket_to_pty (child) != 0) {
|
||||
eprintf ("socket redirection failed\n");
|
||||
r_socket_free (child);
|
||||
r_socket_free (fd);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
redirect_socket_to_stdio (child);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
r_socket_close_fd (child);
|
||||
|
@ -253,7 +253,7 @@ R_API bool r_socket_connect (RSocket *s, const char *host, const char *port, int
|
||||
}
|
||||
freeaddrinfo (res);
|
||||
if (!rp) {
|
||||
eprintf ("Could not resolve address '%s'\n", host);
|
||||
eprintf ("Could not resolve address '%s' or failed to connect\n", host);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,8 @@ unset the whole environment
|
||||
set no limit the core file size
|
||||
.It Ar connect
|
||||
connect stdin/stdout/stderr to a socket
|
||||
.It Ar pty
|
||||
use a pty for connection over socket (with connect/listen)
|
||||
.It Ar envfile
|
||||
set a file with lines like `var=value` to be used as env
|
||||
.It Ar fork
|
||||
|
Loading…
x
Reference in New Issue
Block a user