Skip to content

Commit

Permalink
i/o: use pty by default
Browse files Browse the repository at this point in the history
(closes #24)
  • Loading branch information
ndrewh committed Jul 23, 2024
1 parent 720deee commit 4ff0a5f
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 18 deletions.
64 changes: 52 additions & 12 deletions pyda_core/pyda_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "pyda_threads.h"
#include "util.h"
#include <fcntl.h>
#include <pty.h>



#ifndef PYDA_DYNAMORIO_CLIENT
Expand Down Expand Up @@ -69,29 +71,67 @@ pyda_process* pyda_mk_process() {
}

extern file_t our_stderr;
void pyda_capture_io(pyda_process *proc) {

// NOTE: This is called from thread_init_event on the main app thread
void pyda_capture_io(pyda_process *proc, int use_pty, int pty_raw) {
int orig_in = dup(0);
int orig_out = dup(1);
int orig_err = dup(2);

int pipe1[2], pipe2[2], pipe3[2];
if (pipe(pipe1) || pipe(pipe2) || pipe(pipe3)) {
dr_fprintf(STDERR, "Failed to create pipes\n");
dr_abort();
if (use_pty) {
int master, slave;

if (openpty(&master, &slave, NULL, NULL, NULL)) {
// Failed to open TTY
DEBUG_PRINTF("Failed to open TTY err %s\n", strerror(errno));
use_pty = false;
} else {
dup2(slave, 0);
dup2(slave, 1);
dup2(slave, 2);
proc->stdin_fd = dup(master);
proc->stdout_fd = dup(master);
proc->stderr_fd = dup(master);

// Modify tty attributes
struct termios tmios;
if (tcgetattr(master, &tmios)) {
DEBUG_PRINTF("Failed to get termios\n");
} else {
if (pty_raw)
cfmakeraw(&tmios);

// Always: no echo
tmios.c_lflag &= ~(ECHO);

if (tcsetattr(master, TCSANOW, &tmios)) {
DEBUG_PRINTF("Failed to set termios\n");
}
}
}
}

if (!use_pty) { // We were asked not to use a pty, or pty init failed
int pipe1[2], pipe2[2], pipe3[2];
if (pipe(pipe1) || pipe(pipe2) || pipe(pipe3)) {
dr_fprintf(STDERR, "Failed to create pipes\n");
dr_abort();
}

dup2(pipe1[0], 0);
dup2(pipe2[1], 1);
dup2(pipe3[1], 2);

proc->stdin_fd = pipe1[1];
proc->stdout_fd = pipe2[0];
proc->stderr_fd = pipe3[0];
}

dup2(pipe1[0], 0);
dup2(pipe2[1], 1);
dup2(pipe3[1], 2);

stdin = fdopen(orig_in, "r");
stdout = fdopen(orig_out, "w");
stderr = fdopen(orig_err, "w");

proc->stdin_fd = pipe1[1];
proc->stdout_fd = pipe2[0];
proc->stderr_fd = pipe3[0];

our_stderr = orig_err;

// nonblocking
Expand Down
2 changes: 1 addition & 1 deletion pyda_core/pyda_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ struct pyda_thread_s {
pyda_process* pyda_mk_process();
pyda_thread* pyda_mk_thread(pyda_process*);

void pyda_capture_io(pyda_process *p);
void pyda_capture_io(pyda_process *p, int use_pty, int pty_raw);

void pyda_process_destroy(pyda_process *p);
void pyda_thread_destroy(pyda_thread *t);
Expand Down
7 changes: 5 additions & 2 deletions pyda_core/tool.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,11 @@ void thread_init_event(void *drcontext) {
if (!global_proc) {
global_proc = pyda_mk_process();

if (!getenv("PYDA_NO_CAPTURE") || getenv("PYDA_NO_CAPTURE")[0] != '1')
pyda_capture_io(global_proc);
if (!getenv("PYDA_NO_CAPTURE") || getenv("PYDA_NO_CAPTURE")[0] != '1') {
int no_pty = (getenv("PYDA_NO_PTY") && getenv("PYDA_NO_PTY")[0] == '1');
int no_raw = (getenv("PYDA_NO_RAW") && getenv("PYDA_NO_RAW")[0] == '1');
pyda_capture_io(global_proc, !no_pty, !no_raw);
}

t = global_proc->main_thread;
} else {
Expand Down
3 changes: 0 additions & 3 deletions tests/test_io.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#include <stdio.h>
int main() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
printf("hello there. please enter your name:\n");
char name[100];
scanf("%s", name);
Expand Down

0 comments on commit 4ff0a5f

Please sign in to comment.