211c5168cd6097fb069ab5011f27641bfb6bb92f
[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 #ifdef sun\r
30 #include <sys/int_types.h> /* Needed on Solaris for uint32_t in termio.h */\r
31 #endif\r
32 #include <termios.h>\r
33 #include <sys/poll.h>\r
34 \r
35 static struct termios save_termios;\r
36 static int stdin_is_tty;\r
37 \r
38 /* poll() is broken in Mac OS X Tiger OS so use select() instead. */\r
39 #define PF_USE_SELECT  (1)\r
40 \r
41 /* Default portable terminal I/O. */\r
42 int  sdTerminalOut( char c )\r
43 {\r
44         return putchar(c);\r
45 }\r
46 \r
47 int  sdTerminalEcho( char c )\r
48 {\r
49         putchar(c);\r
50         return 0;\r
51 }\r
52 \r
53 int  sdTerminalIn( void )\r
54 {\r
55         return getchar();\r
56 }\r
57 \r
58 int  sdTerminalFlush( void )\r
59 {\r
60 #ifdef PF_NO_FILEIO\r
61         return -1;\r
62 #else\r
63         return fflush(PF_STDOUT);\r
64 #endif\r
65 }\r
66 \r
67 /****************************************************/\r
68 int sdQueryTerminal( void )\r
69 {\r
70 #if PF_USE_SELECT\r
71         fd_set readfds;\r
72         struct timeval tv;\r
73         FD_ZERO(&readfds);\r
74         FD_SET(STDIN_FILENO, &readfds);\r
75         /* Set timeout to zero so that we just poll and return. */\r
76         tv.tv_sec = 0;\r
77         tv.tv_usec = 0;\r
78         int select_retval = select(STDIN_FILENO+1, &readfds, NULL, NULL, &tv);\r
79         if (select_retval < 0)\r
80         {\r
81                 perror("sdTerminalInit: select");\r
82         }\r
83         return FD_ISSET(STDIN_FILENO,&readfds) ? FTRUE : FFALSE;\r
84 \r
85 #else\r
86         struct pollfd  pfd = { 0 };\r
87         sdTerminalFlush();\r
88         pfd.fd = STDIN_FILENO;\r
89         pfd.events = POLLIN;\r
90         int result = poll( &pfd, 1, 0 );\r
91     /* On a Mac it may set revents to POLLNVAL because poll() is broken on Tiger. */\r
92         if( pfd.revents & POLLNVAL )\r
93         {\r
94                 PRT(("sdQueryTerminal: poll got POLLNVAL, stdin not open\n"));\r
95                 return FFALSE;\r
96         }\r
97         else\r
98         {\r
99                 return (pfd.revents & POLLIN) ? FTRUE : FFALSE;\r
100         }\r
101 #endif\r
102 }\r
103 \r
104 /****************************************************/\r
105 void sdTerminalInit(void)\r
106 {\r
107         struct termios term;\r
108 \r
109         stdin_is_tty = isatty(STDIN_FILENO);\r
110         if (stdin_is_tty)\r
111         {               \r
112 /* Get current terminal attributes and save them so we can restore them. */\r
113                 tcgetattr(STDIN_FILENO, &term);\r
114                 save_termios = term;\r
115         \r
116 /* ICANON says to wait upon read until a character is received,\r
117  * and then to return it immediately (or soon enough....)\r
118  * ECHOCTL says not to echo backspaces and other control chars as ^H */\r
119                 term.c_lflag &= ~( ECHO | ECHONL | ECHOCTL | ICANON );\r
120                 term.c_cc[VTIME] = 0;\r
121                 term.c_cc[VMIN] = 1;\r
122                 if( tcsetattr(STDIN_FILENO, TCSANOW, &term) < 0 )\r
123                 {\r
124                         perror("sdTerminalInit: tcsetattr");\r
125                 }\r
126         }\r
127 }\r
128 \r
129 /****************************************************/\r
130 void sdTerminalTerm(void)\r
131 {\r
132         if (stdin_is_tty)\r
133         {\r
134                 tcsetattr(STDIN_FILENO, TCSANOW, &save_termios);\r
135         }\r
136 }\r