diff options
Diffstat (limited to 'src/tty.c')
| -rw-r--r-- | src/tty.c | 215 | 
1 files changed, 215 insertions, 0 deletions
| diff --git a/src/tty.c b/src/tty.c new file mode 100644 index 0000000..adee8bf --- /dev/null +++ b/src/tty.c @@ -0,0 +1,215 @@ +/* + * testtty.c: + * + * Copyright (c) 2008 James McKenzie <james@fishsoup.dhs.org>, + * All rights reserved. + * + */ + +static char rcsid[] = "$Id$"; + +/* + * $Log$ + * Revision 1.1  2008/02/07 01:02:52  james + * *** empty log message *** + * + * Revision 1.3  2008/02/06 17:53:28  james + * *** empty log message *** + * + * Revision 1.2  2008/02/04 02:05:06  james + * *** empty log message *** + * + * Revision 1.1  2008/02/04 01:32:39  james + * *** empty log message *** + * + */ + +#include "project.h" + +static void +set_nonblocking (int fd) +{ +  long arg; +  arg = fcntl (fd, F_GETFL, arg); +  arg |= O_NONBLOCK; +  fcntl (fd, F_SETFL, arg); +} + +static void +set_blocking (int fd) +{ +  long arg; +  arg = fcntl (fd, F_GETFL, arg); +  arg &= ~O_NONBLOCK; +  fcntl (fd, F_SETFL, arg); +} + +static void +default_termios (struct termios *termios) +{ + +  memset (termios, 0, sizeof (termios)); + +  termios->c_iflag = ICRNL | IXON; +  termios->c_oflag = OPOST | ONLCR | NL0 | CR0 | TAB0 | BS0 | VT0 | FF0; +  termios->c_lflag = +    ISIG | ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE; + +  termios->c_cc[VINTR] = 003; +  termios->c_cc[VQUIT] = 034; +  termios->c_cc[VERASE] = 0177; +  termios->c_cc[VKILL] = 025; +  termios->c_cc[VEOF] = 004; +  termios->c_cc[VEOL] = 0; +  termios->c_cc[VEOL2] = 0; +  termios->c_cc[VSTART] = 021; +  termios->c_cc[VSTOP] = 023; +  termios->c_cc[VSUSP] = 032; +  termios->c_cc[VLNEXT] = 026; +  termios->c_cc[VWERASE] = 027; +  termios->c_cc[VREPRINT] = 022; +  termios->c_cc[VDISCARD] = 017; + +  termios->c_cflag = CS8 | CREAD | CLOCAL; + +  cfsetispeed (termios, B9600); +  cfsetospeed (termios, B9600); +} + + +static int +open_fd_to_bash (void)          /*thump */ +{ +  pid_t child; +  int fd; +  struct winsize winsize = { 0 }; +  struct termios termios; + +  default_termios (&termios); + +  winsize.ws_row = VT102_ROWS; +  winsize.ws_col = VT102_COLS; + +  child = forkpty (&fd, NULL, &termios, &winsize); + +  switch (child) +    { +    case -1:                   /*boo hiss */ +      return -1; +    case 0:                    /*waaah */ +      setenv ("TERM", "vt102", 1); +      execl ("/bin/sh", "-", (char *) 0); +      _exit (-1); +    } + +  return fd; +} + + +TTY * +tty_new_test (void) +{ +  TTY *t; +  t = (TTY *) malloc (sizeof (TTY)); +  t->fd = open_fd_to_bash (); + +  set_nonblocking (t->fd); + +  return t; +} + +static int +wrap_read (int fd, void *buf, int len) +{ +  int red; + +  red = read (fd, buf, len); +  if (!red) +    return -1; + +  if ((red < 0) && (errno == EAGAIN)) +    red = 0; + +  return red; +} + +static int +wrap_write (int fd, void *buf, int len) +{ +  int writ; + +  writ = write (fd, buf, len); +  if (!writ) +    return -1; + +  if ((writ < 0) && (errno == -EAGAIN)) +    writ = 0; + +  return writ; +} + +int +tty_read (TTY * t, void *buf, int len) +{ +  int red, done = 0; + + +  do +    { + +      red = wrap_read (t->fd, buf, len); +      if (red < 0) +        return -1; +      if (!red) +        return done; + +      buf += red; +      len -= red; +      done += red; +    } +  while (len); + + +  return done; +} + + +int +tty_write (TTY * t, void *buf, int len) +{ +  int writ, done = 0; + +#if 0 +  { +    int i; +    uint8_t *p = buf; +    for (i = 0; i < len; ++i) +      fprintf (stderr, "vw: %03o %c\n", p[i], p[i] > 31 ? p[i] : 32); +  } +#endif + +  do +    { + +      writ = wrap_write (t->fd, buf, len); +      if (writ < 0) +        return -1; +      if (!writ) +        sleep (1); + +      buf += writ; +      len -= writ; +      done += writ; +    } +  while (len); + + +  return done; +} + +void +tty_free (TTY * t) +{ +  close (t->fd); +  free (t); +} | 
