b456788dcc3c702dd8d6880971baf5219766d778
[debian/pforth] / csrc / posix / pf_io_posix.c
1 /* $Id$ */\r
2 /***************************************************************\r
3 ** I/O subsystem for PForth based on 'C'\r
4 **\r
5 ** Author: Phil Burk\r
6 ** Copyright 1994 3DO, Phil Burk, Larry Polansky, David Rosenboom\r
7 **\r
8 ** The pForth software code is dedicated to the public domain,\r
9 ** and any third party may reproduce, distribute and modify\r
10 ** the pForth software code or any derivative works thereof\r
11 ** without any compensation or license.  The pForth software\r
12 ** code is provided on an "as is" basis without any warranty\r
13 ** of any kind, including, without limitation, the implied\r
14 ** warranties of merchantability and fitness for a particular\r
15 ** purpose and their equivalents under the laws of any jurisdiction.\r
16 **\r
17 ****************************************************************\r
18 ** 941004 PLB Extracted IO calls from pforth_main.c\r
19 ** 090220 PLB Fixed broken sdQueryTerminal on Mac. It always returned true.\r
20 ***************************************************************/\r
21 \r
22 #include "../pf_all.h"\r
23 \r
24 /* Configure console so that characters are not buffered.\r
25  * This allows KEY and ?TERMINAL to work and also HISTORY.ON\r
26  */\r
27 \r
28 #include <unistd.h>\r
29 #include <sys/time.h>\r
30 #ifdef sun\r
31 #include <sys/int_types.h> /* Needed on Solaris for uint32_t in termio.h */\r
32 #endif\r
33 #include <termios.h>\r
34 #include <sys/poll.h>\r
35 \r
36 static struct termios save_termios;\r
37 static int stdin_is_tty;\r
38 \r
39 /* poll() is broken in Mac OS X Tiger OS so use select() instead. */\r
40 #ifndef PF_USE_SELECT\r
41 #define PF_USE_SELECT  (1)\r
42 #endif\r
43 \r
44 /* Default portable terminal I/O. */\r
45 int  sdTerminalOut( char c )\r
46 {\r
47         return putchar(c);\r
48 }\r
49 \r
50 int  sdTerminalEcho( char c )\r
51 {\r
52         putchar(c);\r
53         return 0;\r
54 }\r
55 \r
56 int  sdTerminalIn( void )\r
57 {\r
58         return getchar();\r
59 }\r
60 \r
61 int  sdTerminalFlush( void )\r
62 {\r
63 #ifdef PF_NO_FILEIO\r
64         return -1;\r
65 #else\r
66         return fflush(PF_STDOUT);\r
67 #endif\r
68 }\r
69 \r
70 /****************************************************/\r
71 int sdQueryTerminal( void )\r
72 {\r
73 #if PF_USE_SELECT\r
74         int select_retval;\r
75         fd_set readfds;\r
76         struct timeval tv;\r
77         FD_ZERO(&readfds);\r
78         FD_SET(STDIN_FILENO, &readfds);\r
79         /* Set timeout to zero so that we just poll and return. */\r
80         tv.tv_sec = 0;\r
81         tv.tv_usec = 0;\r
82         select_retval = select(STDIN_FILENO+1, &readfds, NULL, NULL, &tv);\r
83         if (select_retval < 0)\r
84         {\r
85                 perror("sdTerminalInit: select");\r
86         }\r
87         return FD_ISSET(STDIN_FILENO,&readfds) ? FTRUE : FFALSE;\r
88 \r
89 #else\r
90         int result;\r
91         struct pollfd  pfd = { 0 };\r
92         sdTerminalFlush();\r
93         pfd.fd = STDIN_FILENO;\r
94         pfd.events = POLLIN;\r
95         result = poll( &pfd, 1, 0 );\r
96     /* On a Mac it may set revents to POLLNVAL because poll() is broken on Tiger. */\r
97         if( pfd.revents & POLLNVAL )\r
98         {\r
99                 PRT(("sdQueryTerminal: poll got POLLNVAL, stdin not open\n"));\r
100                 return FFALSE;\r
101         }\r
102         else\r
103         {\r
104                 return (pfd.revents & POLLIN) ? FTRUE : FFALSE;\r
105         }\r
106 #endif\r
107 }\r
108 \r
109 /****************************************************/\r
110 void sdTerminalInit(void)\r
111 {\r
112         struct termios term;\r
113 \r
114         stdin_is_tty = isatty(STDIN_FILENO);\r
115         if (stdin_is_tty)\r
116         {               \r
117 /* Get current terminal attributes and save them so we can restore them. */\r
118                 tcgetattr(STDIN_FILENO, &term);\r
119                 save_termios = term;\r
120         \r
121 /* ICANON says to wait upon read until a character is received,\r
122  * and then to return it immediately (or soon enough....)\r
123  * ECHOCTL says not to echo backspaces and other control chars as ^H */\r
124                 term.c_lflag &= ~( ECHO | ECHONL | ECHOCTL | ICANON );\r
125                 term.c_cc[VTIME] = 0;\r
126                 term.c_cc[VMIN] = 1;\r
127                 if( tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0 )\r
128                 {\r
129                         perror("sdTerminalInit: tcsetattr");\r
130                 }\r
131         }\r
132 }\r
133 \r
134 /****************************************************/\r
135 void sdTerminalTerm(void)\r
136 {\r
137         if (stdin_is_tty)\r
138         {\r
139                 tcsetattr(STDIN_FILENO, TCSANOW, &save_termios);\r
140         }\r
141 }\r