summaryrefslogtreecommitdiff
path: root/pico/osdep/read.c
diff options
context:
space:
mode:
Diffstat (limited to 'pico/osdep/read.c')
-rw-r--r--pico/osdep/read.c223
1 files changed, 223 insertions, 0 deletions
diff --git a/pico/osdep/read.c b/pico/osdep/read.c
new file mode 100644
index 00000000..52fe92e5
--- /dev/null
+++ b/pico/osdep/read.c
@@ -0,0 +1,223 @@
+#if !defined(lint) && !defined(DOS)
+static char rcsid[] = "$Id: read.c 763 2007-10-23 23:37:34Z hubert@u.washington.edu $";
+#endif
+
+/*
+ * ========================================================================
+ * Copyright 2006 University of Washington
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * ========================================================================
+ */
+
+/*
+ * Keyboard input test and read functions
+ */
+
+#include <system.h> /* os-dep defs/includes */
+#include <general.h> /* generally useful definitions */
+
+#include "../keydefs.h"
+
+#ifndef _WINDOWS
+#include "raw.h"
+#endif /* !_WINDOWS */
+
+#include "read.h"
+
+
+static time_t _time_of_last_input;
+
+time_t
+time_of_last_input(void)
+{
+ if(_time_of_last_input == 0)
+ _time_of_last_input = time((time_t *) 0);
+
+ return(_time_of_last_input);
+}
+
+#ifndef _WINDOWS
+#if HAVE_SELECT
+
+#ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+#endif
+
+
+/*
+ * 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
+ */
+UCS
+input_ready(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 */
+#ifndef __CYGWIN__
+ if(getppid() == 1){
+ /* Parent is init! */
+ return(BAIL_OUT);
+ }
+#endif
+
+ /*
+ * "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 < IDLE_TIMEOUT ? NO_OP_COMMAND : NO_OP_IDLE);
+ }
+ }
+
+ _time_of_last_input = time((time_t *) 0);
+ return(READY_TO_READ);
+}
+
+
+#elif HAVE_POLL
+
+
+#ifdef HAVE_STROPTS_H
+# include <stropts.h>
+#endif
+
+#ifdef HAVE_SYS_POLL_H
+# include <poll.h>
+#endif
+
+/*
+ * Check whether or not a character is ready to be read, or time out.
+ * This version uses a poll 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
+ */
+UCS
+input_ready(int time_out)
+{
+ struct pollfd pollfd;
+ int res;
+
+ fflush(stdout);
+
+ if(time_out > 0){
+ /* Check to see if there are bytes to read with a timeout */
+ pollfd.fd = STDIN_FD;
+ pollfd.events = POLLIN;
+ res = poll (&pollfd, 1, time_out * 1000);
+ if(res >= 0){ /* status bits OK? */
+ if(pollfd.revents & (POLLERR | POLLNVAL))
+ res = -1; /* bad news, exit below! */
+ else if(pollfd.revents & POLLHUP)
+ return(BAIL_OUT);
+ }
+
+ if(res < 0){
+ if(errno == EINTR || errno == EAGAIN)
+ return(READ_INTR);
+
+ return(PANIC_NOW);
+ }
+
+ 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 < IDLE_TIMEOUT ? NO_OP_COMMAND : NO_OP_IDLE);
+ }
+ }
+
+ _time_of_last_input = time((time_t *) 0);
+ return(READY_TO_READ);
+}
+
+#endif /* HAVE_POLL */
+
+
+/*
+ * 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(void)
+{
+ 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);
+}
+
+#else /* _WINDOWS */
+int
+set_time_of_last_input(void)
+{
+ _time_of_last_input = time(0L);
+ return(0);
+}
+#endif /* _WINDOWS */