/* * Check whether or not a character is ready to be read, or time out. * This version uses a select call. * * Args: time_out -- number of seconds before it will time out. * * Result: NO_OP_IDLE: timed out before any chars ready, time_out > 25 * NO_OP_COMMAND: timed out before any chars ready, time_out <= 25 * READ_INTR: read was interrupted * READY_TO_READ: input is available * BAIL_OUT: reading input failed, time to bail gracefully * PANIC_NOW: system call error, die now */ int input_ready(time_out) int time_out; { struct timeval tmo; fd_set readfds, errfds; int res; fflush(stdout); if(time_out > 0){ /* Check to see if there are bytes to read with a timeout */ FD_ZERO(&readfds); FD_ZERO(&errfds); FD_SET(STDIN_FD, &readfds); FD_SET(STDIN_FD, &errfds); tmo.tv_sec = time_out; tmo.tv_usec = 0; res = select(STDIN_FD+1, &readfds, 0, &errfds, &tmo); if(res < 0){ if(errno == EINTR || errno == EAGAIN) return(READ_INTR); return(BAIL_OUT); } if(res == 0){ /* the select timed out */ if(getppid() == 1){ /* Parent is init! */ return(BAIL_OUT); } /* * "15" is the minimum allowed mail check interval. * Anything less, and we're being told to cycle thru * the command loop because some task is pending... */ return(time_out < 15 ? NO_OP_COMMAND : NO_OP_IDLE); } } return(READY_TO_READ); } /* * Read one character from STDIN. * * Result: -- the single character read * READ_INTR -- read was interrupted * BAIL_OUT -- read error of some sort */ int read_one_char() { int res; unsigned char c; res = read(STDIN_FD, &c, 1); if(res <= 0){ /* * Error reading from terminal! * The only acceptable failure is being interrupted. If so, * return a value indicating such... */ if(res < 0 && errno == EINTR) return(READ_INTR); else return(BAIL_OUT); } return((int)c); }