#include <termios.h>
#include <unistd.h>
#include <stdio.h>
/* #define _XOPEN_SOURCE Do we need this?  grantpt and ulockpt seem to ask for it in their man pages */
#include <stdlib.h>


/* basic strategy:

CONNECTION SETUP
----------------

* ? close stdin and stdout. (we will be logging to stderr)

* open the device itself for reading and writing.  use termios() and
  related functions to set it to raw, and use cfsetspeed() to set the
  baud rate.

* open a pseudo terminal with getpt or equivalent (such as
  open("/dev/ptmx", O_RDWR|O_NOCTTY|O_NONBLOCK)).

* enable the slave side of the pty with grantpt() and ulockpt().

* chgrp the slave side to the specified group

* change mode g+rw to slave side

* create a symlink to the slave device in the specified location.

* create two queues of buffers: todev and fromdev

* create a self-pipe for clean signal handling (see SIGNALS below)

TRANSFER MODE:
--------------

loop:

   build the set of selectable file descriptors: both fds are tested
   for reading, and any fd with an outbound buffer in the queue is
   tested for writability.  We also test for readability from the
   self-pipe (see SIGNALS below).

   On wake from the select(), check if the self-pipe is readable.  if
   it is, exit the loop and initiate a clean shutdown.
  
   For each writable fd, try to write a buffer from the queue, in
   non-blocking mode.  if the buffer is fully written, de-allocate it.
   If it is only partially-written, put it back in the head of the queue.

   For each readable fd, allocate a buffer, and try to read in to it
   from the fd.  Write the contents of the buffer to stderr (with
   appropriate prefix to indicate direction), and push it into the
   appropriate queue.


SHUTDOWN
--------

  log all remaining data that hasn't been logged (there shouldn't be any, right?), and de-allocate the buffers.

  close the tty

  close the pty

  remove the symlink



SIGNALS
-------

on reciept of a SIGTERM, we should shutdown cleanly. (what about SIGHUP?)

we handle this by opening an internal pipe, and select()ing on it as
well as the standard file descriptors.  When a SIGTERM is received, we
write a byte to that pipe and return from the handler.

If that pipe is readable on wakeup from select(), we abort the
transfer and initiate the shutdown process.

*/

void usage(const char* progname, FILE* stream) {
  fprintf(stream, "%s: </path/to/device> <baud> <group>\n", progname);
}

speed_t getBaud(const char* arg) {
  const int i = atoi(arg);
  switch (i) {
    50: 
      return B50;
    75: 
      return B75;
    110:
      return B110;
    134:
      return B134;
    150:
      return B150;
    200:
      return B200;
    300: 
      return B300;
    600: 
      return B600;
    1200:
      return B1200;
    1800:
      return B1800;
    2400:
      return B2400;
    4800:
      return B4800;
    9600:
      return B9600;
    19200:
      return B19200;
    38400:
      return B38400;
    57600:
      return B57600;
    115200:
      return B115200;
    230400:
      return B230400;
  default:
    return B0;
  }
}

int
main(int argc, const char* argv[]) {

  if (argc != 4) {
    usage(argv[0], stderr);
    return 1;
  }

  const char* device = argv[1];
  const int baud = atoi(argv[2]);
  const char* group = argv[3];
  
  
  return 0;
}

