From 054d8535f63d153f85667737017d42303176fc1e Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 10 Oct 2002 12:40:05 +0000 Subject: [PATCH] And that's it! pty.c is now a real pty backend rather than a loopback interface; pterm now runs $SHELL and gives every impression of being not a bad terminal emulator. I'm quite pleased with that. :-) git-svn-id: svn://svn.tartarus.org/sgt/putty@2015 cda61777-01e9-0310-a592-d414129be87e --- unix/pterm.c | 31 ++++++++++++++++++++++ unix/pty.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 116 insertions(+), 2 deletions(-) diff --git a/unix/pterm.c b/unix/pterm.c index 97fe6c40..1cf6e6e1 100644 --- a/unix/pterm.c +++ b/unix/pterm.c @@ -8,6 +8,9 @@ #include #include #include +#include +#include +#include #include #include @@ -593,6 +596,32 @@ gint timer_func(gpointer data) return TRUE; } +void pty_input_func(gpointer data, gint sourcefd, GdkInputCondition condition) +{ + /* struct gui_data *inst = (struct gui_data *)data; */ + char buf[4096]; + int ret; + + ret = read(sourcefd, buf, sizeof(buf)); + + /* + * Clean termination condition is that either ret == 0, or ret + * < 0 and errno == EIO. Not sure why the latter, but it seems + * to happen. Boo. + */ + if (ret == 0 || (ret < 0 && errno == EIO)) { + exit(0); + } + + if (ret < 0) { + perror("read pty master"); + exit(1); + } + if (ret > 0) + from_backend(0, buf, ret); + term_out(); +} + void destroy(GtkWidget *widget, gpointer data) { gtk_main_quit(); @@ -793,6 +822,7 @@ void modalfatalbox(char *p, ...) int main(int argc, char **argv) { GtkWidget *window; + extern int pty_master_fd; /* declared in pty.c */ gtk_init(&argc, &argv); @@ -825,6 +855,7 @@ int main(int argc, char **argv) gtk_signal_connect(GTK_OBJECT(inst->area), "expose_event", GTK_SIGNAL_FUNC(expose_area), inst); gtk_timeout_add(20, timer_func, inst); + gdk_input_add(pty_master_fd, GDK_INPUT_READ, pty_input_func, inst); gtk_widget_add_events(GTK_WIDGET(inst->area), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); diff --git a/unix/pty.c b/unix/pty.c index 291247ee..56d7d895 100644 --- a/unix/pty.c +++ b/unix/pty.c @@ -1,5 +1,11 @@ +#define _XOPEN_SOURCE +#include + #include #include +#include +#include +#include #include "putty.h" @@ -10,6 +16,8 @@ #define TRUE 1 #endif +int pty_master_fd; + static void pty_size(void); static void c_write(char *buf, int len) @@ -27,7 +35,74 @@ static void c_write(char *buf, int len) */ static char *pty_init(char *host, int port, char **realhost, int nodelay) { - /* FIXME: do nothing for now */ + int slavefd; + char name[FILENAME_MAX]; + pid_t pid; + + pty_master_fd = open("/dev/ptmx", O_RDWR); + + if (pty_master_fd < 0) { + perror("/dev/ptmx: open"); + exit(1); + } + + if (grantpt(pty_master_fd) < 0) { + perror("grantpt"); + exit(1); + } + + if (unlockpt(pty_master_fd) < 0) { + perror("unlockpt"); + exit(1); + } + + name[FILENAME_MAX-1] = '\0'; + strncpy(name, ptsname(pty_master_fd), FILENAME_MAX-1); + + slavefd = open(name, O_RDWR); + if (slavefd < 0) { + perror("slave pty: open"); + return 1; + } + + /* + * Fork and execute the command. + */ + pid = fork(); + if (pid < 0) { + perror("fork"); + return 1; + } + + if (pid == 0) { + int i; + /* + * We are the child. + */ + close(pty_master_fd); + close(0); + close(1); + close(2); + fcntl(slavefd, F_SETFD, 0); /* don't close on exec */ + dup2(slavefd, 0); + dup2(slavefd, 1); + dup2(slavefd, 2); + setsid(); + setpgrp(); + tcsetpgrp(0, getpgrp()); + /* Close everything _else_, for tidiness. */ + for (i = 3; i < 1024; i++) + close(i); + execl(getenv("SHELL"), getenv("SHELL"), NULL); + /* + * If we're here, exec has gone badly foom. + */ + perror("exec"); + exit(127); + } else { + close(slavefd); + } + return NULL; } @@ -36,7 +111,15 @@ static char *pty_init(char *host, int port, char **realhost, int nodelay) */ static int pty_send(char *buf, int len) { - c_write(buf, len); /* FIXME: diagnostic thingy */ + while (len > 0) { + int ret = write(pty_master_fd, buf, len); + if (ret < 0) { + perror("write pty master"); + exit(1); + } + buf += ret; + len -= ret; + } return 0; } -- 2.11.0