/* unixio.c - 16:05 GMT + 10:00 Wed 4 Aug 1993 - modifier Geoffrey Tobin */ /* Add a global structure so we don't need BSD specific stuff * and remove that BSD specific stuff. * -- Ian Dall */ #include "config.h" #include "globals.h" #include "screenio.h" /* for MesgString, MesgLine */ #define IN_UNIXIO_C #include "unixio.h" /* Set DV_FD (ioctl file descriptor) to 0 or 1 ? */ #define DV_FD 0 struct { unsigned int intr, tstop : 1;} sig_flags = {0, 0}; struct { unsigned int cbreak, raw, echo : 1;} cmode_flags = {0, 0, 0}; /* GT - For the purpose of this file, Aix is BSD - see the headers taken from Berkeley in /usr/include and /usr/include/sys ! */ #ifdef AIX # define BSD 1 #endif /* AIX */ /* Alex Dickinson Procedures for setting and resetting UNIX tty characteristics. Interesting functions are: save_init_tty; restore_init_tty; save_temp_tty; restore_temp_tty; echoon; echooff; singlecharon; singlecharoff; buffercount; suspend; A side effect of calling save_temp_tty is to set up signal handling to reset the terminal characteristics appropriately for the various interrupt signals. */ #ifdef BSD # include typedef struct sgttyb dv_tty; # define DV_GTTY TIOCGETP # define DV_STTY TIOCSETN #else /* not BSD; System V ? */ # include # include typedef struct termio dv_tty; # define DV_GTTY TCGETA # define DV_STTY TCSETAW #endif /* BSD */ #include #include static dv_tty init_tty_state; /* store initial terminal characteristics */ static dv_tty temp_tty_state; /* current terminal characteristics */ #ifndef BSD /* Not BSD */ unsigned char saved_cc[NCC]; #endif /* Not BSD */ /* locally defined and used functions and data */ static Void setsignals (VOID); static Void reportio __((int iostat)); static int iostatus; /* return status of ioctl system function */ #ifdef __STDC__ static Void reportio (int iostat) #else static Void reportio (iostat) int iostat; #endif { if (iostat < 0) /* an ioctl error */ { char * str = ""; string cstr; switch (errno) { /* generic errors */ #ifdef EBADF case EBADF: str = "Not a valid, open, file descriptor!"; break; #endif #ifdef EINTR case EINTR: str = "Signal caught."; break; #endif #ifdef ENOTTY case ENOTTY: str = "No device driver, or doesn't accept control functions!"; break; #endif /* specialised errors */ #ifdef EFAULT case EFAULT: str = "Illegal data transfer address!"; break; #endif #ifdef EINVAL case EINVAL: str = "Driver ignorant of this request or arg!"; break; #endif #ifdef EIO case EIO: str = "Physical I/O error!"; break; #endif #ifdef ENOLINK case ENOLINK: str = "Remote machine link no longer active!"; break; #endif #ifdef ENXIO case ENXIO: str = "Subdevice cannot perform requested service!"; break; #endif /* gt - should be ample space in cstr. */ default: sprintf (cstr, "Unknown error %d !", errno); str = cstr; break; } MesgString ("ioctl: "); MesgString (str); MesgLine(); } } /* reportio */ Void save_init_tty (VOID) { /* Save the original tty characteristics and set up the signalling. */ save_temp_tty(); init_tty_state = temp_tty_state; } /* save_init_tty */ Void restore_init_tty (VOID) { /* Restore the original tty characteristics. */ temp_tty_state = init_tty_state; restore_temp_tty(); } /* restore_init_tty */ Void save_temp_tty (VOID) { /* Save the current tty characteristics and set up the signalling. */ iostatus = ioctl (DV_FD, DV_GTTY, &temp_tty_state); reportio (iostatus); setsignals(); } /* save_temp_tty */ Void restore_temp_tty (VOID) { /* Restore the recent tty characteristics. */ iostatus = ioctl (DV_FD, DV_STTY, &temp_tty_state); reportio (iostatus); } /* restore_temp_tty */ Void singlecharon (VOID) { /* Set driver to read characters as they are typed without waiting for a terminator. Echo remains unchanged. */ dv_tty s; if (cmode_flags.cbreak != 1) { /* First argument to ioctl is a file descriptor; */ /* our sysadm, Kevin Pye, says it should be standard input; */ /* so 0, not 1. */ iostatus = ioctl (DV_FD, DV_GTTY, &s); reportio (iostatus); #ifdef BSD s.sg_flags |= CBREAK; #else /* not BSD */ saved_cc[VEOL] = s.c_cc[VEOL]; saved_cc[VEOF] = s.c_cc[VEOF]; s.c_lflag &= ~ICANON; /* Disable erase/kill processing */ s.c_cc[VMIN] = 1; /* Input should wait for at least 1 char */ s.c_cc[VTIME] = 0; /* no matter how long that takes. */ #endif /* BSD */ iostatus = ioctl (DV_FD, DV_STTY, &s); reportio (iostatus); #ifdef FLUSH_STDIN fflush (stdin); #endif /* FLUSH_STDIN */ cmode_flags.cbreak = 1; } } /* singlecharon */ Void singlecharoff (VOID) { /* Turn off single character read mode. */ dv_tty s; if (cmode_flags.cbreak != 0) { iostatus = ioctl (DV_FD, DV_GTTY, &s); reportio (iostatus); #ifdef BSD s.sg_flags &= ~CBREAK; #else /* not BSD */ s.c_lflag |= ICANON; /* Enable erase/kill processing */ s.c_cc[VEOL] = saved_cc[VEOL]; s.c_cc[VEOF] = saved_cc[VEOF]; #endif /* BSD */ iostatus = ioctl (DV_FD, DV_STTY, &s); reportio (iostatus); cmode_flags.cbreak = 0; } } /* singlecharoff */ Void echoon (VOID) { /* Turn character echoing on. */ dv_tty s; iostatus = ioctl (DV_FD, DV_GTTY, &s); reportio (iostatus); #ifdef BSD s.sg_flags |= ECHO; #else /* not BSD */ s.c_lflag |= ECHO; #endif /* BSD */ iostatus = ioctl (DV_FD, DV_STTY, &s); reportio (iostatus); cmode_flags.echo = 1; } /* echoon */ Void echooff (VOID) { /* Turn character echoing off. */ dv_tty s; iostatus = ioctl (DV_FD, DV_GTTY, &s); reportio (iostatus); #ifdef BSD s.sg_flags &= ~ECHO; #else /* not BSD */ s.c_lflag &= ~ECHO; #endif /* BSD */ iostatus = ioctl (DV_FD, DV_STTY, &s); reportio (iostatus); cmode_flags.echo = 0; } /* echooff */ Void rawouton (VOID) { dv_tty s; iostatus = ioctl (DV_FD, DV_GTTY, &s); reportio (iostatus); #ifndef BSD /* Not BSD */ s.c_oflag &= ~OPOST; /* Disables tab interpretation etc. */ #endif /* Not BSD */ iostatus = ioctl (DV_FD, DV_STTY, &s); reportio (iostatus); cmode_flags.raw = 1; } /* rawouton */ Void rawoutoff (VOID) { dv_tty s; iostatus = ioctl (DV_FD, DV_GTTY, &s); reportio (iostatus); #ifndef BSD /* Not BSD */ s.c_oflag |= OPOST; #endif /* Not BSD */ iostatus = ioctl (DV_FD, DV_STTY, &s); reportio (iostatus); cmode_flags.raw = 0; } /* rawoutoff */ int buffercount (VOID) { /* Return true if there are any characters currently in the input buffer. */ #ifdef BSD long count; iostatus = ioctl (DV_FD, FIONREAD, &count); reportio (iostatus); return (count > 0); #else /* not BSD */ int c, flags, ret; /* Save the current fcntl flags and make reads return without waiting */ flags = fcntl (0, F_GETFL, 0); fcntl (0, F_SETFL, flags | O_NDELAY); /* This might be SysV specific */ if ((c = getchar()) != EOF) { ungetc (c, stdin); ret = 1; } else { ret = 0; } fcntl (0, F_SETFL, flags); /* This might be SysV specific */ return ret; #endif /* BSD */ } /* buffercount */ #ifdef __STDC__ Void handleint (int sig) #else Void handleint (sig) int sig; #endif { /* Catch signals from tty. If sig is an interrupt, set the intr flag, Otherwise it was a suspend, so set the tstop flag. */ fflush (stdin); if (sig == SIGINT) { sig_flags.intr = 1; } else { sig_flags.tstop = 1; } #ifndef BSD /* Not BSD */ setsignals(); /* Because SysV forgets its handlers */ #endif /* Not BSD */ } /* handleint */ static Void setsignals (VOID) { /* Signal initialization. */ signal (SIGINT, handleint); #ifdef BSD signal (SIGTSTP, handleint); #endif /* BSD */ } /* setsignals */ Void suspend (VOID) { /* Suspend the process */ #ifdef BSD signal (SIGTSTP, SIG_DFL); kill (0, SIGTSTP); /* resumed again, goody! */ setsignals(); #else /* don't know what to do */ #endif /* BSD */ } /* suspend */ #undef IN_UNIXIO_C