gint ide_vte_pty_create_slave (VtePty *pty) { gint master_fd; #ifdef HAVE_PTSNAME_R char name[PATH_MAX + 1]; #else const char *name; #endif g_assert (VTE_IS_PTY (pty)); if (-1 == (master_fd = vte_pty_get_fd (pty))) return -1; if (grantpt (master_fd) != 0) return -1; if (unlockpt (master_fd) != 0) return -1; #ifdef HAVE_PTSNAME_R if (ptsname_r (master_fd, name, sizeof name - 1) != 0) return -1; name[sizeof name - 1] = '\0'; #else if (NULL == (name = ptsname (master_fd))) return -1; #endif return open (name, O_RDWR | O_CLOEXEC); }
static void *proc_allvte(void *p) { int master = vte_pty_get_fd((VtePty*)p); int slave = open(ptsname(master), O_RDWR); // raw 模式 struct termios tio; tcgetattr(slave, &tio); cfmakeraw(&tio); tcsetattr(slave, TCSADRAIN, &tio); fd_set set; while (1) { FD_ZERO(&set); FD_SET(slave, &set); struct timeval tv = {0, 100}; if (select(slave+1, &set, NULL, NULL, &tv) > 0) { char buf[256]; int len = read(slave, buf, sizeof(buf)); if (len > 0) { buf[len] = '\0'; page_foreach_send_string(buf); } } usleep(1000); } return NULL; }
/** * vte_pty_get_size: * @pty: a #VtePty * @rows: (out) (allow-none): a location to store the number of rows, or %NULL * @columns: (out) (allow-none): a location to store the number of columns, or %NULL * @error: return location to store a #GError, or %NULL * * Reads the pseudo terminal's window size. * * If getting the window size failed, @error will be set to a #GIOError. * * Returns: %TRUE on success, %FALSE on failure with @error filled in */ gboolean vte_pty_get_size(VtePty *pty, int *rows, int *columns, GError **error) { struct winsize size; int master; int ret; g_return_val_if_fail(VTE_IS_PTY(pty), FALSE); master = vte_pty_get_fd(pty); memset(&size, 0, sizeof(size)); ret = ioctl(master, TIOCGWINSZ, &size); if (ret == 0) { if (columns != NULL) { *columns = size.ws_col; } if (rows != NULL) { *rows = size.ws_row; } _vte_debug_print(VTE_DEBUG_PTY, "Size on fd %d is (%d,%d).\n", master, size.ws_col, size.ws_row); return TRUE; } else { int errsv = errno; g_set_error(error, G_IO_ERROR, g_io_error_from_errno(errsv), "Failed to get window size: %s", g_strerror(errsv)); _vte_debug_print(VTE_DEBUG_PTY, "Failed to read size from fd %d: %s\n", master, g_strerror(errsv)); errno = errsv; return FALSE; } }
/** * vte_pty_set_size: * @pty: a #VtePty * @rows: the desired number of rows * @columns: the desired number of columns * @error: (allow-none): return location to store a #GError, or %NULL * * Attempts to resize the pseudo terminal's window size. If successful, the * OS kernel will send #SIGWINCH to the child process group. * * If setting the window size failed, @error will be set to a #GIOError. * * Returns: %TRUE on success, %FALSE on failure with @error filled in */ gboolean vte_pty_set_size(VtePty *pty, int rows, int columns, GError **error) { struct winsize size; int master; int ret; g_return_val_if_fail(VTE_IS_PTY(pty), FALSE); master = vte_pty_get_fd(pty); memset(&size, 0, sizeof(size)); size.ws_row = rows > 0 ? rows : 24; size.ws_col = columns > 0 ? columns : 80; _vte_debug_print(VTE_DEBUG_PTY, "Setting size on fd %d to (%d,%d).\n", master, columns, rows); ret = ioctl(master, TIOCSWINSZ, &size); if (ret != 0) { int errsv = errno; g_set_error(error, G_IO_ERROR, g_io_error_from_errno(errsv), "Failed to set window size: %s", g_strerror(errsv)); _vte_debug_print(VTE_DEBUG_PTY, "Failed to set size on %d: %s.\n", master, g_strerror(errsv)); errno = errsv; return FALSE; } return TRUE; }
static void vte_pty_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { VtePty *pty = VTE_PTY (object); VtePtyPrivate *priv = pty->priv; switch (property_id) { case PROP_FLAGS: g_value_set_flags(value, priv->flags); break; case PROP_FD: g_value_set_int(value, vte_pty_get_fd(pty)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); } }