aboutsummaryrefslogtreecommitdiff
path: root/win32
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2010-04-14 02:16:38 +0200
committerNguyễn Thái Ngọc Duy <pclouds@gmail.com>2010-04-20 19:14:20 +0200
commit8b54c03f4a6cbabfa91d753592d3404a3d2b11ad (patch)
tree0202203c37a3a72801fda964454bce626c47eb43 /win32
parent485a1984e9ed20de3c997f0fe2d394f651504fe8 (diff)
downloadbusybox-w32-8b54c03f4a6cbabfa91d753592d3404a3d2b11ad.tar.gz
busybox-w32-8b54c03f4a6cbabfa91d753592d3404a3d2b11ad.tar.bz2
busybox-w32-8b54c03f4a6cbabfa91d753592d3404a3d2b11ad.zip
win32: mingw32/termios.c
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Diffstat (limited to 'win32')
-rw-r--r--win32/termios.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/win32/termios.c b/win32/termios.c
new file mode 100644
index 000000000..13adcd522
--- /dev/null
+++ b/win32/termios.c
@@ -0,0 +1,286 @@
1#include "libbb.h"
2#include <windef.h>
3#include <wincon.h>
4#include "strbuf.h"
5
6#if ENABLE_FEATURE_CYGWIN_TTY
7#include <ntdef.h>
8
9/* NtCreateDirectoryObject */
10#define DIRECTORY_QUERY 1
11#define DIRECTORY_TRAVERSE 2
12#define DIRECTORY_CREATE_OBJECT 4
13#define DIRECTORY_CREATE_SUBDIRECTORY 8
14
15#define CYG_SHARED_DIR_ACCESS (DIRECTORY_QUERY \
16 | DIRECTORY_TRAVERSE \
17 | DIRECTORY_CREATE_SUBDIRECTORY \
18 | DIRECTORY_CREATE_OBJECT \
19 | READ_CONTROL)
20
21typedef enum _OBJECT_INFORMATION_CLASS {
22 ObjectNameInformation = 1,
23} OBJECT_INFORMATION_CLASS;
24
25typedef struct _OBJECT_NAME_INFORMATION {
26 UNICODE_STRING Name;
27} OBJECT_NAME_INFORMATION;
28
29VOID NTAPI RtlInitUnicodeString (PUNICODE_STRING, PCWSTR);
30NTSTATUS NTAPI NtOpenSection (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
31NTSTATUS NTAPI NtCreateDirectoryObject (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
32NTSTATUS NTAPI NtQueryObject (HANDLE, OBJECT_INFORMATION_CLASS, VOID *, ULONG, ULONG *);
33
34/* Cygwin's shared_info */
35
36struct winsize {
37 unsigned short ws_row, ws_col;
38 unsigned short ws_xpixel, ws_ypixel;
39};
40
41struct tty_min {
42 pid_t sid; /* Session ID of tty */
43 struct status_flags {
44 unsigned initialized : 1; /* Set if tty is initialized */
45 unsigned rstcons : 1; /* Set if console needs to be set to "non-cooked" */
46 } status;
47
48 pid_t pgid;
49 int output_stopped;
50 int ntty;
51 DWORD last_ctrl_c; /* tick count of last ctrl-c */
52 HWND hwnd; /* Console window handle tty belongs to */
53
54 struct termios ti;
55 struct winsize winsize;
56
57 /* ioctl requests buffer */
58 int cmd;
59 union {
60 struct termios termios;
61 struct winsize winsize;
62 int value;
63 pid_t pid;
64 } arg;
65 /* XXX_retval variables holds master's completion codes. Error are stored as
66 * -ERRNO
67 */
68 int ioctl_retval;
69 int write_error;
70};
71
72struct tty {
73 struct tty_min tty_min;
74 pid_t master_pid; /* PID of tty master process */
75
76 HANDLE from_master, to_master;
77
78 int read_retval;
79 int was_opened; /* True if opened at least once. */
80};
81
82#define NTTYS 128
83struct tty_list {
84 struct tty ttys[NTTYS];
85};
86
87#define CYGWIN_PATH_MAX 4096
88struct shared_info {
89 DWORD version;
90 DWORD cb;
91 unsigned heap_chunk;
92 int heap_slop_inited;
93 unsigned heap_slop;
94 DWORD sys_mount_table_counter;
95 struct tty_list tty;
96 LONG last_used_bindresvport;
97 WCHAR installation_root[CYGWIN_PATH_MAX];
98 DWORD obcaseinsensitive;
99 /* mtinfo mt; */
100};
101
102/* Some magic to recognize shared_info */
103#define CYGWIN_VERSION_SHARED_DATA 5
104#define CYGWIN_VERSION_DLL_IDENTIFIER L"cygwin1"
105#define CYGWIN_VERSION_API_MAJOR 0
106#define CYGWIN_VERSION_API_MINOR 210
107#define SHARED_INFO_CB 39328
108#define CURR_SHARED_MAGIC 0x22f9ff0bU
109
110#define CYGWIN_VERSION_MAGIC(a, b) ((unsigned) ((((unsigned short) a) << 16) | (unsigned short) b))
111#define SHARED_VERSION (unsigned)(CYGWIN_VERSION_API_MAJOR << 8 | CYGWIN_VERSION_API_MINOR)
112#define SHARED_VERSION_MAGIC CYGWIN_VERSION_MAGIC (CURR_SHARED_MAGIC, SHARED_VERSION)
113
114static struct shared_info *get_shared_info()
115{
116 WCHAR buf[32];
117 HANDLE sh;
118 WCHAR base[MAX_PATH];
119 UNICODE_STRING uname;
120 HANDLE dir;
121 NTSTATUS status;
122 OBJECT_ATTRIBUTES attr;
123 static struct shared_info *si = NULL;
124
125 if (si)
126 return si;
127
128 swprintf(base, L"\\BaseNamedObjects\\%sS%d",
129 CYGWIN_VERSION_DLL_IDENTIFIER,
130 CYGWIN_VERSION_SHARED_DATA);
131 RtlInitUnicodeString (&uname, base);
132 InitializeObjectAttributes (&attr, &uname, OBJ_INHERIT | OBJ_OPENIF, NULL, NULL);
133 status = NtCreateDirectoryObject (&dir, CYG_SHARED_DIR_ACCESS, &attr);
134
135 swprintf(buf, L"%s.%d", L"shared", CYGWIN_VERSION_SHARED_DATA);
136 RtlInitUnicodeString(&uname, buf);
137 InitializeObjectAttributes (&attr, &uname, OBJ_CASE_INSENSITIVE, dir, NULL);
138 status = NtOpenSection (&sh, FILE_MAP_READ | FILE_MAP_WRITE, &attr);
139 si = MapViewOfFileEx(sh, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0, NULL);
140 //if (si->version == SHARED_VERSION_MAGIC && si->cb == SHARED_INFO_CB)
141 return si;
142}
143
144static int fd_to_tty(int fd)
145{
146 ULONG len = 0;
147 OBJECT_NAME_INFORMATION dummy_oni, *ntfn;
148 HANDLE h = _get_osfhandle(fd);
149 char buf[PATH_MAX];
150 int tty;
151
152 NtQueryObject (h, ObjectNameInformation, &dummy_oni, sizeof (dummy_oni), &len);
153 ntfn = malloc (len + sizeof (WCHAR));
154 NtQueryObject (h, ObjectNameInformation, ntfn, len, NULL);
155 wcstombs(buf, ntfn->Name.Buffer, 100);
156 tty = -1;
157 swscanf(ntfn->Name.Buffer, L"\\Device\\NamedPipe\\cygwin-tty%d-from-master", &tty);
158 free(ntfn);
159 return tty;
160}
161
162int is_cygwin_tty(int fd)
163{
164 return fd_to_tty(fd) >= 0 && get_shared_info() != NULL;
165}
166
167static int cygwin_tcgetattr(int fd, struct termios *t)
168{
169 int tty = fd_to_tty(fd);
170 struct shared_info *si = get_shared_info();
171 if (tty < 0 || !si)
172 return -1;
173 *t = si->tty.ttys[tty].tty_min.ti;
174 return 0;
175}
176
177
178static int cygwin_tcsetattr(int fd, int mode, const struct termios *t)
179{
180 int tty = fd_to_tty(fd);
181 struct shared_info *si = get_shared_info();
182 if (tty < 0 || !si)
183 return -1;
184 si->tty.ttys[tty].tty_min.ti = *t;
185 return 0;
186}
187
188#else
189
190int is_cygwin_tty(int fd)
191{
192 return 0;
193}
194
195#define cygwin_tcgetattr(fd,t) -1
196#define cygwin_tcsetattr(fd,mode,t) -1
197
198#endif
199
200#undef isatty
201int mingw_isatty(int fd)
202{
203 return isatty(fd) || is_cygwin_tty(fd);
204}
205
206int tcgetattr(int fd, struct termios *t)
207{
208 int ret = cygwin_tcgetattr(fd, t);
209 if (ret >= 0)
210 return ret;
211 /* not cygwin tty, likely windows console */
212 t->c_lflag = ECHO;
213 return 0;
214}
215
216
217int tcsetattr(int fd, int mode, const struct termios *t)
218{
219 return cygwin_tcsetattr(fd, mode, t);
220}
221
222static int get_wincon_width_height(const int fd, int *width, int *height)
223{
224 HANDLE console;
225 CONSOLE_SCREEN_BUFFER_INFO sbi;
226
227 console = GetStdHandle(STD_OUTPUT_HANDLE);
228 if (console == INVALID_HANDLE_VALUE || !console || !GetConsoleScreenBufferInfo(console, &sbi))
229 return -1;
230
231 if (width)
232 *width = sbi.srWindow.Right - sbi.srWindow.Left;
233 if (height)
234 *height = sbi.srWindow.Bottom - sbi.srWindow.Top;
235 return 0;
236}
237
238int FAST_FUNC get_terminal_width_height(int fd, unsigned *width, unsigned *height)
239{
240#if ENABLE_FEATURE_CYGWIN_TTY
241 int tty = fd_to_tty(fd);
242 struct shared_info *si = get_shared_info();
243
244 if (tty >= 0 && si) {
245 if (width)
246 *width = si->tty.ttys[tty].tty_min.winsize.ws_col;
247 if (height)
248 *height = si->tty.ttys[tty].tty_min.winsize.ws_row;
249 return 0;
250 }
251#endif
252 return get_wincon_width_height(fd, width, height);
253}
254
255int wincon_read(int fd, char *buf, int size)
256{
257 static struct strbuf input = STRBUF_INIT;
258 HANDLE cin = GetStdHandle(STD_INPUT_HANDLE);
259 static int initialized = 0;
260
261 if (fd != 0)
262 bb_error_msg_and_die("wincon_read is for stdin only");
263 if (cin == INVALID_HANDLE_VALUE || is_cygwin_tty(fd))
264 return safe_read(fd, buf, size);
265 if (!initialized) {
266 SetConsoleMode(cin, ENABLE_ECHO_INPUT);
267 initialized = 1;
268 }
269 while (input.len < size) {
270 INPUT_RECORD record;
271 DWORD nevent_out;
272 int ch;
273
274 if (!ReadConsoleInput(cin, &record, 1, &nevent_out))
275 return -1;
276 if (record.EventType != KEY_EVENT || !record.Event.KeyEvent.bKeyDown)
277 continue;
278 ch = record.Event.KeyEvent.uChar.AsciiChar;
279 /* Ctrl-X is handled by ReadConsoleInput, Alt-X is not needed anyway */
280 strbuf_addch(&input, ch);
281 }
282 memcpy(buf, input.buf, size);
283 memcpy(input.buf, input.buf+size, input.len-size+1);
284 strbuf_setlen(&input, input.len-size);
285 return size;
286}