1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
/*
**********************************************************************
* File io.c
**********************************************************************
*
* Non blocking input routine
* Works by puttng the terminal in CBREAK mode and using the FIONREAD
* ioctl call to determine the number of characters in the input queue
*/
#include "stdio.h"
#include "stdlib.h"
#include "unistd.h"
#include <sys/types.h>
#include <sys/time.h>
#include <signal.h>
#include <sgtty.h>
#include "cmtio.h"
//#include "cext.h"
int IOinputfd; /* input file descriptor (usually 0) */
int IOnochar; /* Value to be returned by IOgetchar()
where there is no input to be had */
static struct sgttyb IOoldmodes, IOcurrentmodes;
/* Initial and current tty modes */
/*
* IOsetup(inputfd)
* Args:
* inputfd - input file descriptor (should be zero for standard input)
* Returns:
* 0 - if all goes well
* -1 - if an ioctl fails (also calls perror)
* Side Effects:
* Puts the terminal in CBREAK mode - before process termination
* IOcleanup() should be called to restore old terminal modes
* Catch's interrupts (if they are not already being caught) and
* calls IOcleanup before exiting
*
*/
#define ERROR(s) return (perror(s), -1)
/*
* IOcleanup()
* Returns:
* 0 - if all goes well
* -1 - if an ioctl fails (also calls perror)
* Side Effects:
* Restores initial terminal modes
*/
int IOcleanup()
{
if(ioctl(IOinputfd, TIOCSETP, &IOoldmodes) < 0)
ERROR("IOclean");
return 0;
}
static void IOdiegracefully()
{
write(2, "\nBye\n", 5);
IOcleanup();
exit(2);
}
int IOsetup(inputfd)
{
void (*interrupt_handler)(int);
IOinputfd = inputfd;
IOnochar = NOCHAR;
if(ioctl(IOinputfd, TIOCGETP, &IOoldmodes) < 0)
ERROR("IOsetup");
IOcurrentmodes = IOoldmodes;
IOcurrentmodes.sg_flags |= CBREAK;
IOcurrentmodes.sg_flags &= ~ECHO;
if(ioctl(IOinputfd, TIOCSETP, &IOcurrentmodes))
ERROR("IOsetup-2");
if( (interrupt_handler = signal(SIGINT, IOdiegracefully)) != 0)
signal(SIGINT, interrupt_handler);
return 0;
}
/*
* IOgetchar()
* Returns:
* A character off the input queue if there is one,
* IOnochar if there is no character waiting to be read,
* -1 if an ioctl fails (shouldn't happen if IOsetup went OK)
*/
int IOgetchar()
{
int n;
char c;
if(ioctl(IOinputfd, FIONREAD, &n) < 0)
ERROR("IOgetchar");
if(n <= 0)
return IOnochar;
switch(read(IOinputfd, &c, 1)) {
case 1:
return c;
case 0:
return EOF;
default:
ERROR("IOgetchar-read");
}
}
#ifdef IOGETCHAR2
int IOgetchar2()
{
int nfds, readfds = 1 << IOinputfd;
char c;
static struct timeval zero;
if(IOinputfd < 0 || IOinputfd >= 32) {
printf("IOgetchar2: bad IOinputfd (%d)%s\n", IOinputfd,
IOinputfd == -1 ? "Did you call IOsetup(fd)?" : "");
}
nfds = select(32, &readfds, 0, 0, &zero);
if(nfds > 0) {
switch(read(IOinputfd, &c, 1)) {
case 0:
return EOF;
case 1:
return c;
default:
printf("IOgetchar2: read failed!\n");
return NOCHAR;
}
}
else if(nfds < 0)
printf("IOgetchar2: select failed!\n");
return NOCHAR;
}
#endif
/*
* IOwaitchar()
* Returns:
* A character off the input queue. Waits if necessary.
*/
int IOwaitchar()
{
char c;
if (read(IOinputfd, &c, 1) == 1) return c;
else return EOF;
}
|