/* Original author Alex Dickinson
   Procedures for setting and resetting UNIX tty characteristics.
   Interesting functions are:
      savetty();
      restoretty();
      echoon();
      echooff();
      singlecharon();
      singlecharoff();
      buffercount();
      suspend();
   A side effect of calling savetty() is to set up signal handling to reset
   the terminal characteristics appropriately for the various interrupt
   signals.

   This version converted to C and ported to BSD and System V UNIX by
   some chaps at Kernel Technology up to September 1989.  Contact
   mjh@uk.co.kernel (Mark J. Hewitt) with bug fixes etc.

   Involved were:	Mark J. Hewitt
   			Dave Dixon
			Marc Hadley

*/

#include "def.h"
#include <sgtty.h>
#include <signal.h>

static char *sccsid[] = "@(#)bsdio.c	1.1";

struct sgttyb initchars;	/* store initial terminal characteristics */

/* Save the original tty characteristics and set up the signalling. */
void savetty ()
{
  (void) ioctl (1, TIOCGETP, (char *)&initchars);
  setsignals ();
}

/* Restore the original tty characteristics. */
void restoretty ()
{
  (void) ioctl (1, TIOCSETN, (char *)&initchars);
}

/* Set driver to read characters as they are typed without waiting for a
   terminator. Echo remains unchanged. */
void singlecharon ()
{
  struct sgttyb s;
  (void) ioctl (1, TIOCGETP, (char *)&s);
  s.sg_flags |= CBREAK;
  (void) ioctl (1, TIOCSETN, (char *)&s);
  (void) fflush (stdin);
}

/* Turn off single character read mode. */
void singlecharoff ()
{
  struct sgttyb s;
  (void) ioctl (1, TIOCGETP, (char *)&s);
  s.sg_flags &= ~CBREAK;
  (void) ioctl (1, TIOCSETN, (char *)&s);
}

/* Turn character echoing on. */
void echoon ()
{
  struct sgttyb s;
  (void) ioctl (1, TIOCGETP, (char *)&s);
  s.sg_flags |= ECHO;
  (void) ioctl (1, TIOCSETN, (char *)&s);
}

/* Turn character echoing off. */
void echooff ()
{
  struct sgttyb s;
  (void) ioctl (1, TIOCGETP, (char *)&s);
  s.sg_flags &= ~ECHO;
  (void) ioctl (1, TIOCSETN, (char *)&s);
}

/* Return the number of characters currently in the input buffer. */
int   getcharnowait ()
{
  long  count;
  (void) ioctl (1, FIONREAD, (char *)&count);
  if (count == 0)
    return (EOF);
  else
    return (getchar ());
}

/* Yukko */
realungetc (ch, filed)
char  ch;
int   filed;
{
  (void) ioctl (filed, TIOCSTI, &ch);
}

/* Catch signals from tty.
   If sig is an interrupt, put 0 and terminator into the buffer.
   Otherwise it was a suspend, so we put 1 and terminator into buffer. */
handleint (sig)
int   sig;
{
  (void) fflush (stdin);
  if (sig == SIGINT)
  {
    realungetc (0, 0);
  }
  else
  {
    realungetc (1, 0);
  }
}

/* Signal initialization. */
setsignals ()
{
  (void) signal (SIGINT, handleint);
  (void) signal (SIGTSTP, handleint);
}

/* Suspend the process */
void suspend ()
{
  (void) signal (SIGTSTP, SIG_DFL);
  (void) kill (0, SIGTSTP);
 /* resumed again, goody! */
  setsignals ();
}


