]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - win32/io.c
Import of tcsh-6.18.01
[FreeBSD/FreeBSD.git] / win32 / io.c
1 /*$Header: /p/tcsh/cvsroot/tcsh/win32/io.c,v 1.9 2006/04/13 00:59:02 amold Exp $*/
2 /*-
3  * Copyright (c) 1980, 1991 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. Neither the name of the University nor the names of its contributors
15  *    may be used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 /*
32  * io.c
33  * wrapper functions for some i/o routines.
34  * -amol
35  *
36  */
37 #define WIN32_LEAN_AND_MEAN
38 #include <windows.h>
39 #include <stdio.h>
40 #include <fcntl.h>
41 #include <memory.h>
42 #include <errno.h>
43 #include "sh.h"
44 #include "ntport.h"
45 #include "signal.h"
46
47
48 #pragma warning(disable:4127) //conditional expr is constant
49
50 #define CR 0x0d
51
52
53 extern void make_err_str(unsigned int ,char *,int ) ;
54 extern void generic_handler(int);
55 extern int console_write(HANDLE,unsigned char*,int);
56
57 int consoleread(HANDLE , unsigned char * ,size_t ) ;
58
59 INPUT_RECORD girec[2048];
60
61 unsigned short __nt_want_vcode=0,__nt_vcode=0;
62 HANDLE __h_con_alarm=0;
63 HANDLE __h_con_int=0;
64 HANDLE __h_con_hup=0;
65
66 extern int NoNLSRebind;
67
68 extern int OLDSTD, SHIN;
69 /* 
70  * force_read: Forces a ReadFile, instead of ReadConsole 
71  *
72  */
73 int force_read(int fd, unsigned char * buf, size_t howmany) {
74     DWORD numread=0,err=0;
75     HANDLE hRead ;
76
77
78     hRead= (HANDLE)__nt_get_osfhandle(fd);
79     if (hRead == INVALID_HANDLE_VALUE) {
80         return 0;
81     }
82 again:
83     if (!ReadFile(hRead, buf,(DWORD)howmany,&numread, NULL ) ){
84         err = GetLastError();
85         switch(err) {
86             case ERROR_IO_PENDING:
87                 break;
88             case ERROR_ACCESS_DENIED:
89             case ERROR_INVALID_HANDLE:
90                 errno = EBADF;
91                 return -1;
92                 break;
93             case ERROR_HANDLE_EOF:
94             case ERROR_BROKEN_PIPE:
95                 errno = 0;
96                 return 0;
97             default:
98                 errno = EBADF;
99                 return 0;
100         }
101     }
102     if (numread == 1 && buf[0] == CR)
103         goto again;
104     return numread;
105 }
106 int nt_read(int fd, unsigned char * buf, size_t howmany) {
107
108     DWORD numread=0,err=0;
109     HANDLE hRead ;
110     DWORD ftype;
111     //
112
113     hRead= (HANDLE)__nt_get_osfhandle(fd);
114     if (hRead == INVALID_HANDLE_VALUE) {
115         return 0;
116     }
117
118     ftype = GetFileType(hRead);
119
120
121     if ((ftype == FILE_TYPE_CHAR) /*&& (fd != OLDSTD) && (fd != SHIN)*/)
122         return consoleread(hRead,buf,howmany);
123 again:
124     if (!ReadFile(hRead, buf,(DWORD)howmany,&numread, NULL ) ){
125         err = GetLastError();
126         switch(err) {
127             case ERROR_IO_PENDING:
128                 break;
129             case ERROR_ACCESS_DENIED:
130             case ERROR_INVALID_HANDLE:
131                 errno = EBADF;
132                 return -1;
133                 break;
134             case ERROR_HANDLE_EOF:
135             case ERROR_BROKEN_PIPE:
136                 errno = 0;
137                 return 0;
138             default:
139                 errno = EBADF;
140                 return 0;
141         }
142     }
143     if (numread) {
144         if (buf[numread-1] == CR) 
145             numread--;
146         if (numread == 0)
147             goto again;
148     }
149     return numread;
150 }
151
152 /* color-ls patches from TAGA nayuta (nayuta@is.s.u-tokyo.ac.jp) */
153 #ifdef COLOR_LS_F
154
155 int nt_write_(int , const unsigned char * , size_t );
156 int nt_write(int fd, const unsigned char * buf, size_t howmany) {
157     static unsigned char color_buf[256];
158     static char len = 0;
159
160     ssize_t i;
161     ssize_t start = 0;
162     int rc,wrote = 0;
163
164     if (!isatty(fd) || (varval(STRcolor) == NULL))
165         return nt_write_(fd, buf, howmany);
166
167     for (i = 0; i < howmany; i++) {
168         switch (len) {
169             case 0:
170                 if (buf[i] == '\x1b') {
171                     color_buf[len++] = buf[i];
172                     if (0 < i - start){
173                         if ((rc=nt_write_(fd, &(buf[start]), i - start)) <0)
174                             return -1;
175                         else
176                             wrote += rc;
177                     }
178                     start = -1;
179                 }
180                 break;
181
182             case 1:
183                 if (buf[i] != '[')
184                     goto set_color;
185                 color_buf[len++] = buf[i];
186                 break;
187
188             default:
189                 if (buf[i] == 'm' || (!isdigit(buf[i]) && buf[i] != ';'))
190                     goto set_color;
191                 color_buf[len++] = buf[i];
192                 break;
193
194             case sizeof(color_buf) - 1:
195 set_color:
196                 color_buf[len] = '\0';
197                 set_attributes(color_buf);
198                 len = 0;
199                 start = i + 1;
200                 break;
201         }
202     }
203
204     if (0 < i - start && 0 <= start) {
205         if ((rc=nt_write_(fd, &(buf[start]), i - start)) < 0)
206             return -1;
207         else
208             wrote += rc;
209     }
210     return wrote;
211 }
212 int nt_write_(int fd, const unsigned char * buf, size_t howmany)
213 #else /* if !COLOR_LS_F */
214 int nt_write(int fd, const unsigned char * buf, size_t howmany)
215 #endif /* COLOR_LS_F */
216 {
217     int bytes_rtn,err;
218     HANDLE hout;
219
220
221     hout = (HANDLE)__nt_get_osfhandle(fd);
222     /*
223        if (isatty(fd)) 
224        ;//              return console_write(hout,buf,howmany);
225      */
226
227     if(!WriteFile(hout, buf,(DWORD)howmany,(ULONG*)&bytes_rtn,
228                 NULL)){
229         err = GetLastError();
230         switch(err) {
231             case ERROR_ACCESS_DENIED:
232             case ERROR_INVALID_HANDLE:
233                 errno = EBADF;
234                 return -1;
235                 break;
236             case ERROR_BROKEN_PIPE:
237                 errno = EPIPE;
238                 return -1;
239             default:
240                 errno = EBADF;
241                 return -1;
242         }
243
244     }
245     return bytes_rtn?bytes_rtn:-1;
246
247 }
248
249 #define IS_CTRL_COMBO(a) ( (a) & ( RIGHT_CTRL_PRESSED |  LEFT_CTRL_PRESSED) ) 
250 #define IS_ALT_COMBO(a) ( /*(a) &*/ alt_pressed ) 
251 #define IS_SHIFT_COMBO(a) ( (a) & SHIFT_PRESSED)
252
253 int consoleread(HANDLE hInput, unsigned char * buf,size_t howmany) {
254
255         INPUT_RECORD *irec = NULL;
256         DWORD numread,controlkey,i;
257         WORD vcode;
258         unsigned char ch;
259         int rc;
260         size_t where=0;
261         int alt_pressed = 0,memfree=0;
262         HANDLE hevents[4];
263         static int pre_ch = -1;
264
265         if (0 <= pre_ch) {
266                 buf[0] = (unsigned char)pre_ch;
267                 pre_ch = -1;
268                 return 1;
269         }
270
271         howmany /= 2; // [ALT + KEY] is expanded ESC KEY, so we need more buffer
272         if (howmany == 0)
273                 howmany = 1;
274
275         if (howmany > 2048){
276                 irec = heap_alloc(howmany*sizeof(INPUT_RECORD));
277                 memfree=1;
278         }
279         else
280                 irec = &(girec[0]);
281         if (!irec){
282                 errno = ENOMEM;
283                 return -1;
284         }
285         while(1) {
286                 hevents[0] = __h_con_alarm;
287                 hevents[1] = __h_con_int;
288                 hevents[2] = __h_con_hup;
289                 hevents[3] = hInput;
290                 rc = WaitForMultipleObjects(sizeof(hevents)/sizeof(hevents[0]),
291                                             hevents,FALSE,INFINITE);
292                 if (rc == WAIT_OBJECT_0) {
293                         generic_handler(SIGALRM);
294                 }
295                 if (rc == (WAIT_OBJECT_0 +1) ) {
296                         errno = EINTR;
297                         generic_handler(SIGINT);
298                         break;
299                 }
300                 if (rc == (WAIT_OBJECT_0 +2) ) {
301                         errno = EINTR;
302                         generic_handler(SIGHUP);
303                         break;
304                 }
305                 rc = ReadConsoleInput(hInput,irec,(DWORD)howmany,&numread);
306                 if (!rc) {
307                         rc = GetLastError();
308                         switch (rc) {
309                                 case ERROR_INVALID_HANDLE:
310                                 case ERROR_ACCESS_DENIED:
311                                         errno = EBADF;
312                                         break;
313                         }
314                         if (memfree)
315                                 heap_free(irec);
316                         return -1;
317                 }
318                 __nt_vcode=0;
319                 for(i=0;i<numread;i++) {
320                         switch(irec[i].EventType) {
321                                 case KEY_EVENT:
322                                         if (irec[i].Event.KeyEvent.bKeyDown) {
323                                                 vcode=(irec[i].Event.KeyEvent.wVirtualKeyCode);
324                                                 ch=(irec[i].Event.KeyEvent.uChar.AsciiChar);
325                                                 controlkey=(irec[i].Event.KeyEvent.dwControlKeyState);
326                                                 if (controlkey & LEFT_ALT_PRESSED)
327                                                         alt_pressed=1;
328                                                 else if (controlkey & RIGHT_ALT_PRESSED){
329                                                         if (NoNLSRebind)
330                                                                 alt_pressed=1;
331                                                 }
332
333                                                 if (__nt_want_vcode != 1)
334                                                         goto skippy;
335
336                                                 if (vcode >= VK_F1 && vcode <= VK_F24) {
337
338                                                         __nt_vcode=NT_SPECIFIC_BINDING_OFFSET ;
339                                                         __nt_vcode += (vcode- VK_F1) + SINGLE_KEY_OFFSET;
340
341                                                         if (IS_CTRL_COMBO(controlkey))
342                                                                 __nt_vcode += CTRL_KEY_OFFSET;
343
344                                                         else if (IS_ALT_COMBO(controlkey))
345                                                                 __nt_vcode += ALT_KEY_OFFSET;
346                                                         else if (IS_SHIFT_COMBO(controlkey))
347                                                                 __nt_vcode += SHIFT_KEY_OFFSET;
348
349                                                         __nt_want_vcode=2;
350
351                                                         return 1;
352                                                 }
353                                                 else if (vcode>= VK_PRIOR && vcode <= VK_DOWN) {
354
355                                                         __nt_vcode  = NT_SPECIFIC_BINDING_OFFSET ;
356                                                         __nt_vcode += KEYPAD_MAPPING_BEGIN;
357                                                         __nt_vcode += (vcode -VK_PRIOR);        
358
359                                                         __nt_vcode += SINGLE_KEY_OFFSET ;
360
361                                                         if (IS_CTRL_COMBO(controlkey))
362                                                                 __nt_vcode += CTRL_KEY_OFFSET;
363
364                                                         else if (IS_ALT_COMBO(controlkey))
365                                                                 __nt_vcode += ALT_KEY_OFFSET;
366                                                         else if (IS_SHIFT_COMBO(controlkey))
367                                                                 __nt_vcode += SHIFT_KEY_OFFSET;
368
369                                                         __nt_want_vcode=2;
370                                                         return 1;
371                                                 }
372                                                 else if (vcode == VK_INSERT) {
373                                                         __nt_vcode  = NT_SPECIFIC_BINDING_OFFSET ;
374                                                         __nt_vcode += INS_DEL_MAPPING_BEGIN;
375
376                                                         if (IS_CTRL_COMBO(controlkey))
377                                                                 __nt_vcode += CTRL_KEY_OFFSET;
378
379                                                         else if (IS_ALT_COMBO(controlkey))
380                                                                 __nt_vcode += ALT_KEY_OFFSET;
381
382                                                         else if (IS_SHIFT_COMBO(controlkey))
383                                                                 __nt_vcode += SHIFT_KEY_OFFSET;
384
385                                                         __nt_want_vcode=2;
386                                                         return 1;
387                                                 }
388                                                 else if (vcode == VK_DELETE) {
389                                                         __nt_vcode  = NT_SPECIFIC_BINDING_OFFSET ;
390                                                         __nt_vcode += INS_DEL_MAPPING_BEGIN + 1;
391
392                                                         if (IS_CTRL_COMBO(controlkey))
393                                                                 __nt_vcode += CTRL_KEY_OFFSET;
394
395                                                         else if (IS_ALT_COMBO(controlkey))
396                                                                 __nt_vcode += ALT_KEY_OFFSET;
397
398                                                         else if (IS_SHIFT_COMBO(controlkey))
399                                                                 __nt_vcode += SHIFT_KEY_OFFSET;
400
401                                                         __nt_want_vcode=2;
402
403                                                         return 1;
404                                                 }
405 skippy:
406                                                 switch(vcode) {
407                                                         case VK_ESCAPE:
408                                                                 buf[where++]='\033';
409                                                                 break;
410                                                         default:
411                                                                 if(ch ){
412                                                                         /* 
413                                                                          * Looks like win95 has a spurious
414                                                                          * newline left over
415                                                                          */
416                                                                         if (gdwPlatform ==
417                                                                                         VER_PLATFORM_WIN32_WINDOWS && 
418                                                                                         ch == '\r'){
419                                                                                 DWORD bread;
420                                                                                 (void)ReadFile(hInput,&ch,1,&bread,NULL);
421                                                                         }
422                                                                         /* patch from TAGA nayuta */
423                                                                         if ( NoNLSRebind  &&
424                                                                                         (ch == ' ' || ch == '@') &&
425                                                                                         IS_CTRL_COMBO(controlkey)
426                                                                                         /*(controlkey & LEFT_CTRL_PRESSED ||
427                                                                                           controlkey & RIGHT_CTRL_PRESSED)*/
428                                                                            )
429                                                                                 ch = 0;
430                                                                         if (alt_pressed) {
431 #ifdef DSPMBYTE
432                                                                                 buf[where++] = '\033';
433                                                                                 if (howmany == 1)
434                                                                                         pre_ch = ch;
435                                                                                 else
436                                                                                         buf[where++] = ch;
437 #else /* !DSPMBYTE */
438                                                                                 buf[where++] = ch | 0200;
439 #endif /* !DSPMBYTE */
440                                                                         }
441                                                                         else
442                                                                                 buf[where++] = ch;
443                                                                 }
444                                                                 break;
445                                                 }
446
447                                                 alt_pressed=0;
448                                         }
449                                         break;
450                                 default:
451                                         break;
452                         }
453                 }
454                 if (where == 0)
455                         continue;
456                 if (howmany < where) // avoid trashing memory. -amol 4/16/97
457                         buf[where]=0;
458                 break;
459         }
460         if (memfree)
461                 heap_free(irec);
462         if (!where)
463                 return -1;
464         return (int)(where );
465 }
466 int console_write(HANDLE hout, unsigned char * buf,int howmany) {
467     int bytes,rc;
468
469     bytes = -1;
470
471     rc = WriteConsole(hout,buf,howmany,(DWORD*)&bytes,NULL);
472     if (!rc) {
473         errno = EBADF;
474         bytes = -1;
475         rc = GetLastError();
476     }
477
478     return bytes;
479 }