Updated README with better build info
[debian/pforth] / csrc / posix / pf_io_posix.c
1 /* $Id$ */
2 /***************************************************************
3 ** I/O subsystem for PForth based on 'C'
4 **
5 ** Author: Phil Burk
6 ** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom
7 **
8 ** Permission to use, copy, modify, and/or distribute this
9 ** software for any purpose with or without fee is hereby granted.
10 **
11 ** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
12 ** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13 ** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
14 ** THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
15 ** CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
16 ** FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
17 ** CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 ** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 **
20 ****************************************************************
21 ** 941004 PLB Extracted IO calls from pforth_main.c
22 ** 090220 PLB Fixed broken sdQueryTerminal on Mac. It always returned true.
23 ***************************************************************/
24
25 #include "../pf_all.h"
26
27 /* Configure console so that characters are not buffered.
28  * This allows KEY and ?TERMINAL to work and also HISTORY.ON
29  */
30
31 #include <unistd.h>
32 #include <sys/time.h>
33 #ifdef sun
34 #include <sys/int_types.h> /* Needed on Solaris for uint32_t in termio.h */
35 #endif
36 #include <termios.h>
37 #include <sys/poll.h>
38
39 static struct termios save_termios;
40 static int stdin_is_tty;
41
42 /* poll() is broken in Mac OS X Tiger OS so use select() instead. */
43 #ifndef PF_USE_SELECT
44 #define PF_USE_SELECT  (1)
45 #endif
46
47 /* Default portable terminal I/O. */
48 int  sdTerminalOut( char c )
49 {
50     return putchar(c);
51 }
52
53 int  sdTerminalEcho( char c )
54 {
55     putchar(c);
56     return 0;
57 }
58
59 int  sdTerminalIn( void )
60 {
61     return getchar();
62 }
63
64 int  sdTerminalFlush( void )
65 {
66 #ifdef PF_NO_FILEIO
67     return -1;
68 #else
69     return fflush(PF_STDOUT);
70 #endif
71 }
72
73 /****************************************************/
74 int sdQueryTerminal( void )
75 {
76 #if PF_USE_SELECT
77     int select_retval;
78     fd_set readfds;
79     struct timeval tv;
80     FD_ZERO(&readfds);
81     FD_SET(STDIN_FILENO, &readfds);
82     /* Set timeout to zero so that we just poll and return. */
83     tv.tv_sec = 0;
84     tv.tv_usec = 0;
85     select_retval = select(STDIN_FILENO+1, &readfds, NULL, NULL, &tv);
86     if (select_retval < 0)
87     {
88         perror("sdTerminalInit: select");
89     }
90     return FD_ISSET(STDIN_FILENO,&readfds) ? FTRUE : FFALSE;
91
92 #else
93     int result;
94     struct pollfd  pfd = { 0 };
95     sdTerminalFlush();
96     pfd.fd = STDIN_FILENO;
97     pfd.events = POLLIN;
98     result = poll( &pfd, 1, 0 );
99     /* On a Mac it may set revents to POLLNVAL because poll() is broken on Tiger. */
100     if( pfd.revents & POLLNVAL )
101     {
102         PRT(("sdQueryTerminal: poll got POLLNVAL, stdin not open\n"));
103         return FFALSE;
104     }
105     else
106     {
107         return (pfd.revents & POLLIN) ? FTRUE : FFALSE;
108     }
109 #endif
110 }
111
112 /****************************************************/
113 void sdTerminalInit(void)
114 {
115     struct termios term;
116
117     stdin_is_tty = isatty(STDIN_FILENO);
118     if (stdin_is_tty)
119     {
120 /* Get current terminal attributes and save them so we can restore them. */
121         tcgetattr(STDIN_FILENO, &term);
122         save_termios = term;
123
124 /* ICANON says to wait upon read until a character is received,
125  * and then to return it immediately (or soon enough....)
126  * ECHOCTL says not to echo backspaces and other control chars as ^H */
127         term.c_lflag &= ~( ECHO | ECHONL | ECHOCTL | ICANON );
128         term.c_cc[VTIME] = 0;
129         term.c_cc[VMIN] = 1;
130         if( tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0 )
131         {
132             perror("sdTerminalInit: tcsetattr");
133         }
134         if (setvbuf(stdout, NULL, _IONBF, (size_t) 0) != 0)
135         {
136             perror("sdTerminalInit: setvbuf");
137         }
138     }
139 }
140
141 /****************************************************/
142 void sdTerminalTerm(void)
143 {
144     if (stdin_is_tty)
145     {
146         tcsetattr(STDIN_FILENO, TCSANOW, &save_termios);
147     }
148 }