static int stdin_input () { char buf[MAXLINE]; size_t size; size_t i; int masterfd = pty_pair_get_masterfd (pty_pair); if (masterfd == -1) { logger_write_pos ( logger, __FILE__, __LINE__, "pty_pair_get_masterfd error"); return -1; } size = read (STDIN_FILENO, buf, MAXLINE-1); if (size == -1){ logger_write_pos ( logger, __FILE__, __LINE__, "read error"); return -1; } buf[size] = 0; /* Display GDB output * The strlen check is here so that if_print does not get called * when displaying the filedlg. If it does get called, then the * gdb window gets displayed when the filedlg is up */ for(i = 0; i < size; ++i) if(write(masterfd, &(buf[i]), 1) != 1 ){ logger_write_pos ( logger, __FILE__, __LINE__, "could not write byte"); return -1; } return 0; return 0; }
int init_readline(void) { int slavefd, masterfd; int length; slavefd = pty_pair_get_slavefd(pty_pair); if (slavefd == -1) return -1; masterfd = pty_pair_get_masterfd(pty_pair); if (masterfd == -1) return -1; if (tty_off_xon_xoff(slavefd) == -1) return -1; /* The 16 is because I don't know how many char's the directory separator * is going to be, I expect it to be 1, but who knows. */ length = strlen(cgdb_home_dir) + strlen(readline_history_filename) + 16; readline_history_path = (char *) malloc(sizeof (char) * length); fs_util_get_path(cgdb_home_dir, readline_history_filename, readline_history_path); rline = rline_initialize(slavefd, rlctx_send_user_command, tab_completion, "dumb"); rline_read_history(rline, readline_history_path); return 0; }
int a2_open_new_tty(struct annotate_two *a2, int *inferior_stdin, int *inferior_stdout) { close_inferior_connection(a2); a2->pty_pair = pty_pair_create(); if (!a2->pty_pair) { logger_write_pos(logger, __FILE__, __LINE__, "pty_pair_create failed"); return -1; } *inferior_stdin = pty_pair_get_masterfd(a2->pty_pair); *inferior_stdout = pty_pair_get_masterfd(a2->pty_pair); a2_set_inferior_tty(a2); return 0; }
int a2_open_new_tty(struct annotate_two *a2, int *inferior_stdin, int *inferior_stdout) { if (a2->pty_pair) pty_pair_destroy(a2->pty_pair); a2->pty_pair = pty_pair_create(); if (!a2->pty_pair) { logger_write_pos(logger, __FILE__, __LINE__, "pty_pair_create failed"); return -1; } *inferior_stdin = pty_pair_get_masterfd(a2->pty_pair); *inferior_stdout = pty_pair_get_masterfd(a2->pty_pair); commands_issue_command(a2, ANNOTATE_TTY, pty_pair_get_slavename(a2->pty_pair), 1); return 0; }
static int tgdb_open_new_tty(struct tgdb *tgdb, int *inferior_stdin, int *inferior_stdout) { if (tgdb->pty_pair) pty_pair_destroy(tgdb->pty_pair); tgdb->pty_pair = pty_pair_create(); if (!tgdb->pty_pair) { clog_error(CLOG_CGDB, "pty_pair_create failed"); return -1; } *inferior_stdin = pty_pair_get_masterfd(tgdb->pty_pair); *inferior_stdout = pty_pair_get_masterfd(tgdb->pty_pair); tgdb_request_ptr request_ptr; request_ptr = (tgdb_request_ptr)cgdb_malloc(sizeof (struct tgdb_request)); request_ptr->header = TGDB_REQUEST_TTY; request_ptr->choice.tty_command.slavename = pty_pair_get_slavename(tgdb->pty_pair); tgdb_run_or_queue_request(tgdb, request_ptr, true); return 0; }
static void send_key(int focus, char key) { if (focus == 1) { int size; int masterfd; masterfd = pty_pair_get_masterfd(pty_pair); if (masterfd == -1) logger_write_pos(logger, __FILE__, __LINE__, "send_key error"); size = write(masterfd, &key, sizeof (char)); if (size != 1) logger_write_pos(logger, __FILE__, __LINE__, "send_key error"); } else if (focus == 2) { tgdb_send_inferior_char(tgdb, key); } }
static int readline_input() { const int MAX = 1024; char *buf = malloc(MAX + 1); int size; int masterfd = pty_pair_get_masterfd(pty_pair); if (masterfd == -1) { logger_write_pos(logger, __FILE__, __LINE__, "pty_pair_get_masterfd error"); return -1; } size = read(masterfd, buf, MAX); if (size == -1) { logger_write_pos(logger, __FILE__, __LINE__, "read error"); free(buf); buf = NULL; return -1; } buf[size] = 0; /* Display GDB output * The strlen check is here so that if_print does not get called * when displaying the filedlg. If it does get called, then the * gdb window gets displayed when the filedlg is up */ if (size > 0) if_print(buf); free(buf); buf = NULL; return 0; }
static int main_loop(void) { fd_set rset; int max; int masterfd, slavefd; masterfd = pty_pair_get_masterfd(pty_pair); if (masterfd == -1) { logger_write_pos(logger, __FILE__, __LINE__, "pty_pair_get_masterfd error"); return -1; } slavefd = pty_pair_get_slavefd(pty_pair); if (slavefd == -1) { logger_write_pos(logger, __FILE__, __LINE__, "pty_pair_get_slavefd error"); return -1; } max = (gdb_fd > STDIN_FILENO) ? gdb_fd : STDIN_FILENO; max = (max > tty_fd) ? max : tty_fd; max = (max > resize_pipe[0]) ? max : resize_pipe[0]; max = (max > slavefd) ? max : slavefd; max = (max > masterfd) ? max : masterfd; /* Main (infinite) loop: * Sits and waits for input on either stdin (user input) or the * GDB file descriptor. When input is received, wrapper functions * are called to process the input, and handle it appropriately. * This will result in calls to the curses interface, typically. */ for (;;) { /* Reset the fd_set, and watch for input from GDB or stdin */ FD_ZERO(&rset); FD_SET(STDIN_FILENO, &rset); FD_SET(gdb_fd, &rset); FD_SET(tty_fd, &rset); FD_SET(resize_pipe[0], &rset); /* No readline activity allowed while displaying tab completion */ if (!is_tab_completing) { FD_SET(slavefd, &rset); FD_SET(masterfd, &rset); } /* Wait for input */ if (select(max + 1, &rset, NULL, NULL, NULL) == -1) { if (errno == EINTR) continue; else { logger_write_pos(logger, __FILE__, __LINE__, "select failed: %s", strerror(errno)); return -1; } } /* Input received through the pty: Handle it * Wrote to masterfd, now slavefd is ready, tell readline */ if (FD_ISSET(slavefd, &rset)) rline_rl_callback_read_char(rline); /* Input received through the pty: Handle it * Readline read from slavefd, and it wrote to the masterfd. */ if (FD_ISSET(masterfd, &rset)) if (readline_input() == -1) return -1; /* Input received: Handle it */ if (FD_ISSET(STDIN_FILENO, &rset)) { int val = user_input_loop(); /* The below condition happens on cygwin when user types ctrl-z * select returns (when it shouldn't) with the value of 1. the * user input loop gets called, the kui gets called and does a * non blocking read which returns EAGAIN. The kui then passes * the -1 up the stack with out making any more system calls. */ if (val == -1 && errno == EAGAIN) continue; else if (val == -1) return -1; } /* child's ouptut -> stdout * The continue is important I think. It allows all of the child * output to get written to stdout before tgdb's next command. * This is because sometimes they are both ready. */ if (FD_ISSET(tty_fd, &rset)) { if (child_input() == -1) return -1; continue; } /* gdb's output -> stdout */ if (FD_ISSET(gdb_fd, &rset)) { if (gdb_input() == -1) { return -1; } /* When the file dialog is opened, the user input is blocked, * until GDB returns all the files that should be displayed, * and the file dialog can open, and be prepared to receive * input. So, if we are in the file dialog, and are no longer * waiting for the gdb command, then read the input. */ if (kui_manager_cangetkey(kui_ctx)) { user_input_loop(); } } /* A resize signal occured */ if (FD_ISSET(resize_pipe[0], &rset)) if (cgdb_resize_term(resize_pipe[0]) == -1) return -1; } return 0; }
int main(int argc, char **argv) { int gdb_fd, child_fd, slavefd, masterfd; #if 0 int c; read(0, &c, 1); #endif if (tty_cbreak(STDIN_FILENO, &term_attributes) == -1) logger_write_pos(logger, __FILE__, __LINE__, "tty_cbreak error"); pty_pair = pty_pair_create(); if (!pty_pair) { fprintf(stderr, "%s:%d Unable to create PTY pair", __FILE__, __LINE__); exit(-1); } slavefd = pty_pair_get_slavefd(pty_pair); if (slavefd == -1) { fprintf(stderr, "%s:%d Unable to get slavefd", __FILE__, __LINE__); exit(-1); } masterfd = pty_pair_get_masterfd(pty_pair); if (masterfd == -1) { fprintf(stderr, "%s:%d Unable to get masterfd", __FILE__, __LINE__); exit(-1); } if (tty_off_xon_xoff(masterfd) == -1) exit(-1); rline = rline_initialize(slavefd, rlctx_send_user_command, tab_completion, getenv("TERM")); if ((tgdb = tgdb_initialize(NULL, argc - 1, argv + 1, &gdb_fd, &child_fd)) == NULL) { logger_write_pos(logger, __FILE__, __LINE__, "tgdb_start error"); goto driver_end; } if (tgdb_set_verbose_error_handling(tgdb, 1) != 1) { logger_write_pos(logger, __FILE__, __LINE__, "driver error"); goto driver_end; } /* Ask TGDB to print error messages */ if (tgdb_set_verbose_gui_command_output(tgdb, 1) != 1) { logger_write_pos(logger, __FILE__, __LINE__, "driver error"); goto driver_end; } set_up_signal(); main_loop(gdb_fd, child_fd); if (tgdb_shutdown(tgdb) == -1) logger_write_pos(logger, __FILE__, __LINE__, "could not shutdown"); driver_end: if (tty_set_attributes(STDIN_FILENO, &term_attributes) == -1) logger_write_pos(logger, __FILE__, __LINE__, "tty_reset error"); return 0; }
int main_loop(int gdbfd, int childfd) { int max; fd_set rfds; int result; int masterfd, slavefd; masterfd = pty_pair_get_masterfd(pty_pair); if (masterfd == -1) { logger_write_pos(logger, __FILE__, __LINE__, "pty_pair_get_masterfd error"); return -1; } slavefd = pty_pair_get_slavefd(pty_pair); if (slavefd == -1) { logger_write_pos(logger, __FILE__, __LINE__, "pty_pair_get_slavefd error"); return -1; } /* When TGDB is ready, we read from STDIN, otherwise, leave the data buffered. */ /* get max fd for select loop */ max = (gdbfd > STDIN_FILENO) ? gdbfd : STDIN_FILENO; max = (max > childfd) ? max : childfd; max = (max > slavefd) ? max : slavefd; max = (max > masterfd) ? max : masterfd; while (1) { /* Clear the set and * * READ FROM: * stdin (user or gui) * master (gdb's stdout) * gui_stdout (gui's stdout sending new info) * */ FD_ZERO(&rfds); /* Let the terminal emulate the char's when TGDB is busy */ FD_SET(STDIN_FILENO, &rfds); FD_SET(gdbfd, &rfds); FD_SET(slavefd, &rfds); FD_SET(masterfd, &rfds); if (childfd != -1) FD_SET(childfd, &rfds); result = select(max + 1, &rfds, NULL, NULL, NULL); /* if the signal interuppted system call keep going */ if (result == -1 && errno == EINTR) continue; else if (result == -1) /* on error ... must die -> stupid OS */ logger_write_pos(logger, __FILE__, __LINE__, "select failed"); /* Input received through the pty: Handle it * Readline read from slavefd, and it wrote to the masterfd. */ if (FD_ISSET(masterfd, &rfds)) if (readline_input() == -1) return -1; if (FD_ISSET(slavefd, &rfds)) rline_rl_callback_read_char(rline); /* stdin -> readline input */ if (FD_ISSET(STDIN_FILENO, &rfds)) { stdin_input(); } /* child's output -> stdout */ if (childfd != -1 && FD_ISSET(childfd, &rfds)) { tty_input(); continue; } /* gdb's output -> stdout */ if (FD_ISSET(gdbfd, &rfds)) if (gdb_input() == -1) return -1; } return 0; }