+/*
+ * Pseudo-tty backend for pterm.
+ *
+ * Unlike the other backends, data for this one is not neatly
+ * encapsulated into a data structure, because it wouldn't make
+ * sense to do so - the utmp stuff has to be done before a backend
+ * is initialised, and starting a second pterm from the same
+ * process would therefore be infeasible because privileges would
+ * already have been dropped. Hence, I haven't bothered to keep the
+ * data dynamically allocated: instead, the backend handle is just
+ * a null pointer and ignored everywhere.
+ */
+
#define _XOPEN_SOURCE
#define _XOPEN_SOURCE_EXTENDED
#include <features.h>
static int pty_stamped_utmp = 0;
static int pty_child_pid;
static int pty_utmp_helper_pid, pty_utmp_helper_pipe;
+static int pty_term_width, pty_term_height;
static sig_atomic_t pty_child_dead;
+static int pty_exit_code;
#ifndef OMIT_UTMP
static struct utmp utmp_entry;
#endif
char **pty_argv;
-int pty_child_is_dead(void)
-{
- return pty_child_dead;
-}
-
-static void pty_size(void);
-
static void setup_utmp(char *ttyname, char *location)
{
#ifndef OMIT_UTMP
pid_t pid;
int status;
pid = waitpid(-1, &status, WNOHANG);
- if (pid == pty_child_pid && (WIFEXITED(status) || WIFSIGNALED(status)))
- pty_child_dead = TRUE;
+ if (pid == pty_child_pid && (WIFEXITED(status) || WIFSIGNALED(status))) {
+ pty_exit_code = status;
+ pty_child_dead = TRUE;
+ }
}
static void fatal_sig_handler(int signum)
close(pipefd[0]);
pty_utmp_helper_pid = pid;
pty_utmp_helper_pipe = pipefd[1];
+ signal(SIGCHLD, sigchld_handler);
}
#endif
* Also places the canonical host name into `realhost'. It must be
* freed by the caller.
*/
-static char *pty_init(char *host, int port, char **realhost, int nodelay)
+static char *pty_init(void *frontend, void **backend_handle,
+ char *host, int port, char **realhost, int nodelay)
{
int slavefd;
pid_t pid, pgrp;
+ *backend_handle = NULL; /* we can't sensibly use this, sadly */
+
+ pty_term_width = cfg.width;
+ pty_term_height = cfg.height;
+
if (pty_master_fd < 0)
pty_open_master();
/*
* Called to send data down the pty.
*/
-static int pty_send(char *buf, int len)
+static int pty_send(void *handle, char *buf, int len)
{
+ if (pty_master_fd < 0)
+ return 0; /* ignore all writes if fd closed */
+
while (len > 0) {
int ret = write(pty_master_fd, buf, len);
if (ret < 0) {
return 0;
}
+void pty_close(void)
+{
+ if (pty_master_fd >= 0) {
+ close(pty_master_fd);
+ pty_master_fd = -1;
+ }
+ close(pty_utmp_helper_pipe); /* this causes utmp to be cleaned up */
+}
+
/*
* Called to query the current socket sendability status.
*/
-static int pty_sendbuffer(void)
+static int pty_sendbuffer(void *handle)
{
return 0;
}
/*
* Called to set the size of the window
*/
-static void pty_size(void)
+static void pty_size(void *handle, int width, int height)
{
struct winsize size;
- size.ws_row = (unsigned short)rows;
- size.ws_col = (unsigned short)cols;
- size.ws_xpixel = (unsigned short) cols * font_dimension(0);
- size.ws_ypixel = (unsigned short) rows * font_dimension(1);
+ pty_term_width = width;
+ pty_term_height = height;
+
+ size.ws_row = (unsigned short)pty_term_height;
+ size.ws_col = (unsigned short)pty_term_width;
+ size.ws_xpixel = (unsigned short) pty_term_width * font_dimension(0);
+ size.ws_ypixel = (unsigned short) pty_term_height * font_dimension(1);
ioctl(pty_master_fd, TIOCSWINSZ, (void *)&size);
return;
}
/*
* Send special codes.
*/
-static void pty_special(Telnet_Special code)
+static void pty_special(void *handle, Telnet_Special code)
{
/* Do nothing! */
return;
}
-static Socket pty_socket(void)
+static Socket pty_socket(void *handle)
{
return NULL; /* shouldn't ever be needed */
}
-static int pty_sendok(void)
+static int pty_sendok(void *handle)
{
return 1;
}
-static void pty_unthrottle(int backlog)
+static void pty_unthrottle(void *handle, int backlog)
{
/* do nothing */
}
-static int pty_ldisc(int option)
+static int pty_ldisc(void *handle, int option)
{
return 0; /* neither editing nor echoing */
}
-static int pty_exitcode(void)
+static int pty_exitcode(void *handle)
{
- /* Shouldn't ever be required */
- return 0;
+ if (!pty_child_dead)
+ return -1; /* not dead yet */
+ else
+ return pty_exit_code;
}
Backend pty_backend = {