diff options
Diffstat (limited to 'private/crt32/lowio')
32 files changed, 5570 insertions, 0 deletions
diff --git a/private/crt32/lowio/cgets.c b/private/crt32/lowio/cgets.c new file mode 100644 index 000000000..ad2a7f1c0 --- /dev/null +++ b/private/crt32/lowio/cgets.c @@ -0,0 +1,129 @@ +/*** +*cgets.c - buffered keyboard input +* +* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _cgets() - read a string directly from console +* +*Revision History: +* 06-09-89 PHG Module created, based on asm version +* 03-12-90 GJF Made calling type _CALLTYPE1, added #include +* <cruntime.h> and fixed copyright. Also, cleaned +* up the formatting a bit. +* 06-05-90 SBM Recoded as pure 32-bit, using new file handle state bits +* 07-24-90 SBM Removed '32' from API names +* 08-13-90 SBM Compiles cleanly with -W3 +* 09-28-90 GJF New-style function declarator. +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-13-90 GJF Fixed a couple of bugs. +* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. +* 01-16-91 GJF ANSI naming. +* 01-25-91 SRW Get/SetConsoleMode parameters changed (_WIN32_) +* 02-18-91 SRW Get/SetConsoleMode required read/write access (_WIN32_) +* 02-19-91 SRW Adapt to OpenFile/CreateFile changes (_WIN32_) +* 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_) +* 07-26-91 GJF Took out init. stuff and cleaned up the error +* handling [_WIN32_]. +* 04-19-93 GJF Use ReadConsole instead of ReadFile. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <os2dll.h> +#include <conio.h> +#include <stdlib.h> + +/* + * mask to clear the bits required to be 0 in the handle state passed to + * DOSSETFHSTATE. + */ +#define FHSTATEMASK 0xffd07888 + +/* + * declaration for console handle + */ + +extern int _coninpfh; + +/*** +*char *_cgets(string) - read string from console +* +*Purpose: +* Reads a string from the console via DOSREAD on a cooked console +* handle. string[0] must contain the maximum length of the +* string. Returns pointer to str[2]. +* +* NOTE: _cgets() does NOT check the pushback character buffer (i.e., +* _chbuf). Thus, _cgets() will not return any character that is +* pushed back by the _ungetch() call. +* +*Entry: +* char *string - place to store read string, str[0] = max length. +* +*Exit: +* returns pointer to str[2], where the string starts. +* returns NULL if error occurs +* +*Exceptions: +* +*******************************************************************************/ + +char * __cdecl _cgets ( + char *string + ) +{ + ULONG oldstate; + ULONG num_read; + char *result; + + _mlock(_CONIO_LOCK); /* lock the console */ + + string[1] = 0; /* no chars read yet */ + result = &string[2]; + + if ( _coninpfh == -1 ) { + _munlock(_CONIO_LOCK); /* unlock the console */ + return(NULL); /* return failure */ + } + + GetConsoleMode( (HANDLE)_coninpfh, &oldstate ); + SetConsoleMode( (HANDLE)_coninpfh, ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | + ENABLE_ECHO_INPUT ); + + if ( !ReadConsole( (HANDLE)_coninpfh, + (LPVOID)result, + (unsigned char)string[0], + &num_read, + NULL ) + ) + result = NULL; + + if ( result != NULL ) { + + /* set length of string and null terminate it */ + + if (string[num_read] == '\r') { + string[1] = (char)(num_read - 2); + string[num_read] = '\0'; + } else if ( (num_read == (ULONG)(unsigned char)string[0]) && + (string[num_read + 1] == '\r') ) { + /* special case 1 - \r\n straddles the boundary */ + string[1] = (char)(num_read -1); + string[1 + num_read] = '\0'; + } else if ( (num_read == 1) && (string[2] == '\n') ) { + /* special case 2 - read a single '\n'*/ + string[1] = string[2] = '\0'; + } else { + string[1] = (char)num_read; + string[2 + num_read] = '\0'; + } + } + + SetConsoleMode( (HANDLE)_coninpfh, oldstate ); + + _munlock(_CONIO_LOCK); /* unlock the console */ + + return result; +} diff --git a/private/crt32/lowio/chsize.c b/private/crt32/lowio/chsize.c new file mode 100644 index 000000000..d25278023 --- /dev/null +++ b/private/crt32/lowio/chsize.c @@ -0,0 +1,231 @@ +/*** +*chsize.c - OS/2 change size of a file +* +* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* contains the _chsize() function - changes the size of a file. +* +*Revision History: +* 03-13-84 RN initial version +* 05-17-86 SKS ported to OS/2 +* 07-07-87 JCR Added (_doserrno == 5) check that is in DOS 3.2 version +* 10-29-87 JCR Multi-thread support; also, re-wrote for efficiency +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 05-25-88 PHG Merged DLL and normal versions +* 10-03-88 GJF Changed DOSNEWSIZE to SYSNEWSIZE +* 10-10-88 GJF Made API names match DOSCALLS.H +* 04-13-89 JCR New syscall interface +* 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention +* 03-12-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* <cruntime.h>, removed #include <register.h> and fixed +* the copyright. Also, cleaned up the formatting a bit. +* 04-04-90 GJF Added #include <string.h>, removed #include <dos.h>. +* 05-21-90 GJF Fixed stack checking pragma syntax. +* 07-24-90 SBM Replaced <assertm.h> by <assert.h>, removed '32' +* from API names +* 09-28-90 GJF New-style function declarator. +* 12-03-90 GJF Appended Win32 version of the function. It is based +* on the Cruiser version and probably could be merged +* in later (much later). +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo +* 12-28-90 SRW Added _CRUISER_ conditional around check_stack pragma +* 01-16-91 GJF ANSI naming. Also, fixed _chsize_lk parameter decls. +* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_] +* 04-09-91 PNT Added _MAC_ conditional +* 02-13-92 GJF Replaced _nfile by _nhandle for Win32. +* 05-01-92 GJF Fixed embarrassing bug (didn't work for Win32)! +* +*******************************************************************************/ + +#include <cruntime.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <fcntl.h> +#include <msdos.h> +#include <io.h> +#include <string.h> +#include <oscalls.h> +#include <internal.h> +#include <os2dll.h> + +#ifdef _CRUISER_ +#pragma check_stack(on) /* turn stack probes on */ +#endif /* ndef _CRUISER_ */ + +/*** +*int _chsize(filedes, size) - change size of a file +* +*Purpose: +* Change file size. Assume file is open for writing, or we can't do it. +* The DOS way to do this is to go to the right spot and write 0 bytes. The +* Xenix way to do this is to make a system call. We write '\0' bytes because +* DOS won't do this for you if you lseek beyond eof, though Xenix will. +* +*Entry: +* int filedes - file handle to change size of +* long size - new size of file +* +*Exit: +* return 0 if successful +* returns -1 and sets errno if fails +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef MTHREAD + +/* define normal version that locks/unlocks, validates fh */ + +int _CALLTYPE1 _chsize ( + REG1 int filedes, + long size + ) +{ + int r; /* return value */ + +#ifdef _WIN32_ + if ( (unsigned)filedes >= (unsigned)_nhandle ) { +#else + if (filedes < 0 || filedes >= _nfile) { +#endif + errno = EBADF; + return(-1); + } + _lock_fh(filedes); + r = _chsize_lk(filedes,size); + _unlock_fh(filedes); + + return r; +} + +/* now define version that doesn't lock/unlock, validate fh */ +int _CALLTYPE1 _chsize_lk ( + REG1 int filedes, + long size + ) +{ + long filend; + long extend; + long place; + int cnt; + char blanks[BUFSIZ]; + REG2 char *bl = blanks; + int oldmode; + int retval = 0; /* assume good return */ + +#else + +/* now define normal version */ + +int _CALLTYPE1 _chsize ( + REG1 int filedes, + long size + ) +{ + long filend; + long extend; + long place; + int cnt; + char blanks[BUFSIZ]; + REG2 char *bl = blanks; + int oldmode; + int retval = 0; /* assume good return */ + +#ifdef _WIN32_ + if ( (unsigned)filedes >= (unsigned)_nhandle ) { +#else + if (filedes < 0 || filedes >= _nfile) { +#endif + errno = EBADF; + return(-1); + } + +#endif + assert(size >= 0); + + /* Get current file position and seek to end */ + if ( ((place = _lseek_lk(filedes, 0L, SEEK_CUR)) == -1L) || + ((filend = _lseek_lk(filedes, 0L, SEEK_END)) == -1L) ) + return -1; + + extend = size - filend; + + /* Grow or shrink the file as necessary */ + + if (extend > 0L) { + + /* extending the file */ + + memset(bl, '\0', BUFSIZ); + oldmode = _setmode_lk(filedes, _O_BINARY); + + /* pad out with nulls */ + do { + cnt = (extend >= (long)BUFSIZ ) ? BUFSIZ : (int)extend; + if ( ( cnt = _write_lk( filedes, bl, (extend >= + (long)BUFSIZ ) ? BUFSIZ : (int)extend)) == -1 ) { + /* Error on write */ + if (_doserrno == ERROR_ACCESS_DENIED) + errno = EACCES; + retval = cnt; + break; /* leave write loop */ + } + } + while ((extend -= (long)cnt) > 0L); + + _setmode_lk(filedes, oldmode); + /* retval set correctly */ + } + + else if (extend < 0L) { + /* shortening the file */ +#ifdef _CRUISER_ + + retval = ( DOSSETFILESIZE(filedes, size) ? -1 : 0 ); + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + /* + * Set file pointer to new eof...and truncate it there. + */ + _lseek_lk(filedes, size, SEEK_SET); + + if ( (retval = SetEndOfFile((HANDLE)_get_osfhandle(filedes)) ? + 0 : -1) == -1 ) { + errno = EACCES; + _doserrno = GetLastError(); + } + +#else /* ndef _WIN32_ */ + +#ifdef _MAC_ + + TBD(); + +#else /* ndef _MAC_ */ + +#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED! + +#endif /* _MAC_ */ + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + } + + /* else */ + /* no file change needed */ + /* retval = 0; */ + + +/* Common return code */ + + _lseek_lk(filedes, place, SEEK_SET); + return retval; +} diff --git a/private/crt32/lowio/close.c b/private/crt32/lowio/close.c new file mode 100644 index 000000000..c96a8a4b9 --- /dev/null +++ b/private/crt32/lowio/close.c @@ -0,0 +1,135 @@ +/*** +*close.c - close file handle for Windows NT +* +* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _close() - close a file handle +* +*Revision History: +* 06-09-89 PHG Module created, based on asm version +* 03-12-90 GJF Made calling type _CALLTYPE2 (for now), added #include +* <cruntime.h> and fixed the copyright. Also, cleaned up +* the formatting a bit. +* 04-03-90 GJF Now CALLTYPE1. +* 07-24-90 SBM Removed '32' from API names +* 08-14-90 SBM Compiles cleanly with -W3 +* 09-28-90 GJF New-style function declarator. +* 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s. +* It is enough different that there is little point in +* trying to more closely merge the two versions. +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo +* 01-16-91 GJF ANSI naming. +* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_] +* 04-09-91 PNT Added _MAC_ conditional +* 07-17-91 GJF Syntax error in multi-thread build [_WIN32_] +* 02-13-92 GJF Replaced _nfile by _nhandle for Win32. +* 02-21-92 GJF Removed bogus _unlock_fh() call. +* 03-22-93 GJF Check for STDOUT and STDERR being mapped to the same +* OS file handle. Also, purged Cruiser support. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <io.h> +#include <os2dll.h> +#include <errno.h> +#include <stdlib.h> +#include <internal.h> + +/*** +*int _close(fh) - close a file handle +* +*Purpose: +* Closes the file associated with the file handle fh. +* +*Entry: +* int fh - file handle to close +* +*Exit: +* returns 0 if successful, -1 (and sets errno) if fails +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef MTHREAD + +/* define normal version that locks/unlocks, validates fh */ + +int _CRTAPI1 _close ( + int fh + ) +{ + int r; /* return value */ + + /* validate file handle */ + if ( (unsigned)fh >= (unsigned)_nhandle ) { + /* bad file handle, set errno and abort */ + errno = EBADF; + _doserrno = 0; /* no OS/2 error */ + return -1; + } + + _lock_fh(fh); /* lock file */ + r = _close_lk(fh); + _unlock_fh(fh); /* unlock the file */ + + return r; +} + +/* now define version that doesn't lock/unlock, validate fh */ +int _CRTAPI1 _close_lk ( + int fh + ) +{ + DWORD dosretval; + +#else + +/* now define normal version */ +int _CRTAPI1 _close ( + int fh + ) +{ + DWORD dosretval; + + /* validate file handle */ + if ( (unsigned)fh >= (unsigned)_nhandle ) { + /* bad file handle, set errno and abort */ + errno = EBADF; + _doserrno = 0; /* no OS/2 error */ + return -1; + } +#endif + /* + * Close the underlying OS file handle. Note that if fh is STDOUT + * or STDERR, and if STDOUT and STDERR are mapped to the same OS + * file handle, the close is skipped (without error). STDOUT and + * STDERR are the only handles for which this support is provided. + * Other handles are mapped to the same OS file handle only at the + * programmer's risk. + */ + if ( ( ((fh == 1) || (fh == 2)) && + (_get_osfhandle(1) == _get_osfhandle(2)) ) || + CloseHandle( (HANDLE)_get_osfhandle(fh) ) ) + { + + dosretval = 0L; + } + else + dosretval = GetLastError(); + + _free_osfhnd(fh); + + if (dosretval) { + /* OS error */ + _dosmaperr(dosretval); + return -1; + } + _osfile[fh] = 0; /* clear file flags */ + + return 0; /* good return */ +} diff --git a/private/crt32/lowio/commit.c b/private/crt32/lowio/commit.c new file mode 100644 index 000000000..1393907f4 --- /dev/null +++ b/private/crt32/lowio/commit.c @@ -0,0 +1,115 @@ +/*** +*commit.c - flush buffer to disk +* +* Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* contains _commit() - flush buffer to disk +* +*Revision History: +* 05-25-90 SBM initial version +* 07-24-90 SBM Removed '32' from API names +* 09-28-90 GJF New-style function declarator. +* 12-03-90 GJF Appended Win32 version onto the source with #ifdef-s. +* It is close enough to the Cruiser version that it +* should be more closely merged with it later on (much +* later on). +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo +* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_] +* 04-09-91 PNT Added _MAC_ conditional +* 02-13-92 GJF Replaced _nfile by _nhandle for Win32. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> /* for RESETBUFFER */ +#include <errno.h> +#include <io.h> +#include <internal.h> +#include <msdos.h> /* for FOPEN */ +#include <os2dll.h> +#include <stdlib.h> /* for _doserrno */ + +/*** +*int _commit(filedes) - flush buffer to disk +* +*Purpose: +* Flushes cache buffers for the specified file handle to disk +* +*Entry: +* int filedes - file handle of file +/* +*Exit: +* returns success code +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _commit ( + REG1 int filedes + ) +{ + REG2 int retval; + + /* if filedes out of range, complain */ +#ifdef _WIN32_ + if ( (unsigned)filedes >= (unsigned)_nhandle ) { +#else + if (filedes < 0 || filedes >= _nfile) { +#endif + errno = EBADF; + return (-1); + } + + _lock_fh(filedes); + + /* if filedes open, try to commit, else fall through to bad */ + if (_osfile[filedes] & FOPEN) { + +#ifdef _CRUISER_ + + retval = DOSRESETBUFFER(filedes); + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + if ( !FlushFileBuffers((HANDLE)_get_osfhandle(filedes)) ) { + retval = GetLastError(); + } else { + retval = 0; /* return success */ + } +#else /* ndef _WIN32_ */ + +#ifdef _MAC_ + + TBD(); + +#else /* ndef _MAC_ */ + +#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED! + +#endif /* _MAC_ */ + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + /* map the OS return code to C errno value and return code */ + if (retval == 0) { + goto good; + } else { + _doserrno = retval; + goto bad; + } + + } + +bad : + errno = EBADF; + retval = -1; +good : + _unlock_fh(filedes); + return (retval); +} diff --git a/private/crt32/lowio/cputs.c b/private/crt32/lowio/cputs.c new file mode 100644 index 000000000..cc19b79a3 --- /dev/null +++ b/private/crt32/lowio/cputs.c @@ -0,0 +1,100 @@ +/*** +*cputs.c - direct console output +* +* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _cputs() - write string directly to console +* +*Revision History: +* 06-09-89 PHG Module created, based on asm version +* 03-12-90 GJF Made calling type _CALLTYPE2 (for now), added #include +* <cruntime.h> and fixed the copyright. Also, cleaned up +* the formatting a bit. +* 04-10-90 GJF Now _CALLTYPE1. +* 06-05-90 SBM Recoded as pure 32-bit, using new file handle state bits +* 07-24-90 SBM Removed '32' from API names +* 09-28-90 GJF New-style function declarator. +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. +* 01-16-91 GJF ANSI naming. +* 02-19-91 SRW Adapt to OpenFile/CreateFile changes (_WIN32_) +* 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_) +* 07-26-91 GJF Took out init. stuff and cleaned up the error +* handling [_WIN32_]. +* 04-19-93 GJF Use WriteConsole instead of WriteFile. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <os2dll.h> +#include <conio.h> +#include <stdio.h> +#include <string.h> + +/* + * declaration for console handle + */ +extern int _confh; + +/*** +*int _cputs(string) - put a string to the console +* +*Purpose: +* Writes the string directly to the console. No newline +* is appended. +* +*Entry: +* char *string - string to write +* +*Exit: +* Good return = 0 +* Error return = !0 +* +*Exceptions: +* +*******************************************************************************/ + +int _CRTAPI1 _cputs ( + const char *string + ) +{ + ULONG num_written; + int error = 0; /* error occurred? */ + + _mlock(_CONIO_LOCK); /* acquire console lock */ + + /* write string to console file handle */ + +#ifdef _CRUISER_ + + if (DOSWRITE(_confh, (char*)string, strlen(string), &num_written)) { + /* OS/2 error, return error indicator */ + error = -1; + } +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + if ( (_confh == -1) || !WriteConsole( (HANDLE)_confh, + (LPVOID)string, + strlen(string), + &num_written, + NULL ) + ) + /* return error indicator */ + error = -1; + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + _munlock(_CONIO_LOCK); /* release console lock */ + + return error; +} diff --git a/private/crt32/lowio/creat.c b/private/crt32/lowio/creat.c new file mode 100644 index 000000000..fe1437989 --- /dev/null +++ b/private/crt32/lowio/creat.c @@ -0,0 +1,52 @@ +/*** +*creat.c - create a new file or truncate existing file +* +* Copyright (c) 1989-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _creat() - create new file +* +*Revision History: +* 06-08-89 PHG Module created, based on asm version +* 03-12-90 GJF Made calling type _CALLTYPE1, added #include +* <cruntime.h>, fixed compiler warning and fixed the +* copyright. Also, cleaned up the formatting a bit. +* 09-28-90 GJF New-style function declarator. +* 01-16-91 GJF ANSI naming. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <io.h> +#include <fcntl.h> + +/*** +*int _creat(path, pmode) - create a new file +* +*Purpose: +* If file specified does not exist, _creat creates a new file +* with the given permission setting and opens it for writing. +* If the file already exists and its permission allows writing, +* _creat truncates it to 0 length and open it for writing. +* The only Xenix mode bit supprted by DOS is user write (S_IWRITE). +* +*Entry: +* char *path - filename to create +* int pmode - permission mode setting for new file +* +*Exit: +* returns handle for created file +* returns -1 and sets errno if fails. +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _creat ( + const char *path, + int pmode + ) +{ + /* creat is just the same as open... */ + return _open(path, _O_CREAT + _O_TRUNC + _O_RDWR, pmode); +} diff --git a/private/crt32/lowio/dup.c b/private/crt32/lowio/dup.c new file mode 100644 index 000000000..1eaa12597 --- /dev/null +++ b/private/crt32/lowio/dup.c @@ -0,0 +1,156 @@ +/*** +*dup.c - OS/2 duplicate file handles +* +* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _dup() - duplicate file handles +* +*Revision History: +* 06-09-89 PHG Module created, based on asm version +* 03-12-90 GJF Made calling type _CALLTYPE2 (for now), added #include +* <cruntime.h> and fixed the copyright. Also, cleaned up +* the formatting a bit. +* 04-03-90 GJF Now _CALLTYPE1. +* 07-24-90 SBM Removed '32' from API names +* 08-14-90 SBM Compiles cleanly with -W3 +* 09-28-90 GJF New-style function declarator. +* 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s. +* It is enough different that there is little point in +* trying to more closely merge the two versions. +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo +* 01-16-91 GJF ANSI naming. +* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_] +* 02-18-91 SRW Changed to call _free_osfhnd [_WIN32_] +* 02-25-91 SRW Renamed _get_free_osfhnd to be _alloc_osfhnd [_WIN32_] +* 02-13-92 GJF Replaced _nfile by _nhandle for Win32. +* 09-03-92 GJF Added explicit check for unopened handles [_WIN32_]. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <errno.h> +#include <os2dll.h> +#include <io.h> +#include <msdos.h> +#include <internal.h> +#include <stdlib.h> + +/*** +*int _dup(fh) - duplicate a file handle +* +*Purpose: +* Assigns another file handle to the file associated with the +* handle fh. The next available file handle is assigned. +* +* Multi-thread: Be sure not to hold two file handle locks +* at the same time! +* +*Entry: +* int fh - file handle to duplicate +* +*Exit: +* returns new file handle if successful +* returns -1 (and sets errno) if fails +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _dup ( + int fh + ) +{ + ULONG dosretval; /* OS/2 return value */ + int newfh; /* variable for new file handle */ + char fileinfo; /* _osfile info for file */ + + /* validate file handle */ +#ifdef _WIN32_ + if ( ((unsigned)fh >= (unsigned)_nhandle) || + !(_osfile[fh] & FOPEN) ) { +#else + if ((unsigned)fh >= (unsigned)_nfile) { +#endif + errno = EBADF; + _doserrno = 0; /* no OS/2 error */ + return -1; + } + + _lock_fh(fh); /* lock file handle */ + fileinfo = _osfile[fh]; /* get file info for file */ + + /* create duplicate handle */ + +#ifdef _CRUISER_ + + newfh = -1; /* ask for new handle */ + dosretval = DOSDUPHANDLE(fh, &newfh); + + /* validate range of new handle */ + if (dosretval == 0 && (unsigned)newfh >= (unsigned)_nfile) { + /* file handle is not in range -- close it and return error */ + _doserrno = DOSCLOSE(newfh); + errno = EMFILE; + _unlock_fh(fh); + return -1; + } + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + { + long new_osfhandle; + + if ( (newfh = _alloc_osfhnd()) == -1 ) { + errno = EMFILE; /* too many files error */ + _doserrno = 0L; /* not an OS error */ + _unlock_fh(fh); + return -1; /* return error to caller */ + } + + /* + * duplicate the file handle + */ + + if ( !(DuplicateHandle(GetCurrentProcess(), + (HANDLE)_get_osfhandle(fh), + GetCurrentProcess(), + (PHANDLE)&new_osfhandle, + 0L, + TRUE, + DUPLICATE_SAME_ACCESS)) ) + { + dosretval = GetLastError(); + } + else { + _set_osfhnd(newfh, new_osfhandle); + dosretval = 0; + } + } + + _unlock_fh(newfh); + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + _unlock_fh(fh); /* unlock file handle */ + + if (dosretval) { + /* OS/2 error -- map and return */ + _dosmaperr(dosretval); + return -1; + } + + /* copy _osfile info */ + _osfile[newfh] = fileinfo; + + return newfh; +} diff --git a/private/crt32/lowio/dup2.c b/private/crt32/lowio/dup2.c new file mode 100644 index 000000000..dfa6724ec --- /dev/null +++ b/private/crt32/lowio/dup2.c @@ -0,0 +1,200 @@ +/*** +*dup2.c - Duplicate file handles +* +* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _dup2() - duplicate file handles +* +*Revision History: +* 06-09-89 PHG Module created, based on asm version +* 03-12-90 GJF Made calling type _CALLTYPE2 (for now), added #include +* <cruntime.h> and fixed the copyright. Also, cleaned up +* the formatting a bit. +* 04-03-90 GJF Now _CALLTYPE1. +* 07-24-90 SBM Removed '32' from API names +* 08-14-90 SBM Compiles cleanly with -W3 +* 09-28-90 GJF New-style function declarator. +* 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s. +* It is enough different that there is little point in +* trying to more closely merge the two versions. +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo +* 01-16-91 GJF ANSI naming. +* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_] +* 02-18-91 SRW Changed to call _free_osfhnd [_WIN32_] +* 02-25-91 SRW Renamed _get_free_osfhnd to be _alloc_osfhnd [_WIN32_] +* 02-13-92 GJF Replaced _nfile by _nhandle for Win32. +* 09-04-92 GJF Check for unopened fh1 and gracefully handle fh1 == +* fh2. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <io.h> +#include <oscalls.h> +#include <msdos.h> +#include <os2dll.h> +#include <errno.h> +#include <stdlib.h> +#include <internal.h> + +/*** +*int _dup2(fh1, fh2) - force handle 2 to refer to handle 1 +* +*Purpose: +* Forces file handle 2 to refer to the same file as file +* handle 1. If file handle 2 referred to an open file, that file +* is closed. +* +* Multi-thread: We must hold 2 lowio locks at the same time +* to ensure multi-thread integrity. In order to prevent deadlock, +* we always get the lower file handle lock first. Order of unlocking +* does not matter. If you modify this routine, make sure you don't +* cause any deadlocks! Scary stuff, kids!! +* +*Entry: +* int fh1 - file handle to duplicate +* int fh2 - file handle to assign to file handle 1 +* +*Exit: +* returns 0 if successful, -1 (and sets errno) if fails. +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _dup2 ( + int fh1, + int fh2 + ) +{ + ULONG dosretval; /* OS/2 return code */ + + /* validate file handles */ +#ifdef _WIN32_ + if ( ((unsigned)fh1 >= (unsigned)_nhandle) || + ((unsigned)fh2 >= (unsigned)_nhandle) ) { +#else + if ((unsigned)fh1 >= (unsigned)_nfile || + (unsigned)fh2 >= (unsigned)_nfile ) { +#endif + /* handle out of range */ + errno = EBADF; + _doserrno = 0; /* not an OS error */ + return -1; + } + +#ifdef MTHREAD + /* get the two file handle locks; in order to prevent deadlock, + get the lowest handle lock first. */ + if ( fh1 < fh2 ) { + _lock_fh(fh1); + _lock_fh(fh2); + } + else if ( fh1 > fh2 ) { + _lock_fh(fh2); + _lock_fh(fh1); + } +#endif + + /* + * Take care of case of equal handles. + */ + if ( fh1 == fh2 ) { + /* + * Two handles are the same. Return success or failure + * depending on whether or not the handle is open. This is + * conformance with the POSIX specification for dup2(). + */ + if ( _osfile[fh1] & FOPEN ) + return 0; + else + return -1; + } + + /* + * Take care of case of unopened source handle. + */ + if ( !(_osfile[fh1] & FOPEN) ) { + /* + * Source handle isn't open, release locks and bail out with + * an error. Note that the DuplicateHandle API will not detect + * this error since it implies that _osfhnd[fh1] == + * INVALID_HANDLE_VALUE, and this is a legal HANDLE value (it's + * the HANDLE for the current process). + */ + _unlock_fh(fh1); + _unlock_fh(fh2); + errno = EBADF; + _doserrno = 0; /* not an OS error */ + return -1; + } + + + /* + * if fh2 is open, close it. + */ + if ( _osfile[fh2] & FOPEN ) + /* + * close the handle. ignore the possibility of an error - an + * error simply means that an OS handle value may remain bound + * for the duration of the process. Use _close_lk as we + * already own lock + */ + (void) _close_lk(fh2); + + + /* Duplicate source file onto target file */ +#ifdef _CRUISER_ + + dosretval = DOSDUPHANDLE(fh1, &fh2); + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + { + long new_osfhandle; + + if ( !(DuplicateHandle(GetCurrentProcess(), + (HANDLE)_get_osfhandle(fh1), + GetCurrentProcess(), + (PHANDLE)&new_osfhandle, + 0L, + TRUE, + DUPLICATE_SAME_ACCESS) + ) ) { + + dosretval = GetLastError(); + } else { + _set_osfhnd(fh2, new_osfhandle); + dosretval = 0; + } + } + + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + if (dosretval) { + _dosmaperr(dosretval); + _unlock_fh(fh1); + _unlock_fh(fh2); + return -1; + } + + /* copy _osfile information */ + _osfile[fh2] = _osfile[fh1]; + + /* unlock file handles */ + _unlock_fh(fh1); + _unlock_fh(fh2); + + return 0; +} diff --git a/private/crt32/lowio/eof.c b/private/crt32/lowio/eof.c new file mode 100644 index 000000000..e4e2f7a2c --- /dev/null +++ b/private/crt32/lowio/eof.c @@ -0,0 +1,90 @@ +/*** +*eof.c - test a handle for end of file +* +* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _eof() - determine if a file is at eof +* +*Revision History: +* 09-07-83 RN initial version +* 10-28-87 JCR Multi-thread support +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 05-25-88 PHG DLL replaces normal version +* 07-11-88 JCR Added REG allocation to declarations +* 03-12-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* <cruntime.h>, removed #include <register.h> and fixed +* the copyright. Also, cleaned up the formatting a bit. +* 09-28-90 GJF New-style function declarator. +* 12-04-90 GJF Improved range check of file handle. +* 01-16-91 GJF ANSI naming. +* 02-13-92 GJF Replaced _nfile by _nhandle for Win32. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <io.h> +#include <errno.h> +#include <stddef.h> +#include <stdlib.h> +#include <stdio.h> +#include <internal.h> +#include <os2dll.h> + +/*** +*int _eof(filedes) - test a file for eof +* +*Purpose: +* see if the file length is the same as the present position. if so, return +* 1. if not, return 0. if an error occurs, return -1 +* +*Entry: +* int filedes - handle of file to test +* +*Exit: +* returns 1 if at eof +* returns 0 if not at eof +* returns -1 and sets errno if fails +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _eof ( + REG1 int filedes + ) +{ + long here; + long end; + REG2 int retval; +#ifdef _WIN32_ + if ( (unsigned)filedes >= (unsigned)_nhandle ) { +#else + if ( (unsigned)filedes >= (unsigned)_nfile ) { +#endif + errno = EBADF; + _doserrno = 0; + return(-1); + } + + /* Lock the file */ + _lock_fh(filedes); + + /* See if the current position equals the end of the file. */ + + if ( ((here = _lseek_lk(filedes, 0L, SEEK_CUR)) == -1L) + || ((end = _lseek_lk(filedes, 0L, SEEK_END)) == -1L) ) + retval = -1; + else if ( here == end ) + retval = 1; + else { + _lseek_lk(filedes, here, SEEK_SET); + retval = 0; + } + + /* Unlock the file */ + _unlock_fh(filedes); + + /* Done */ + return(retval); +} diff --git a/private/crt32/lowio/flength.c b/private/crt32/lowio/flength.c new file mode 100644 index 000000000..9b81ced8c --- /dev/null +++ b/private/crt32/lowio/flength.c @@ -0,0 +1,84 @@ +/*** +*flength.c - find length of a file +* +* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _filelength() - find the length of a file +* +*Revision History: +* 10-22-84 RN initial version +* 10-27-87 JCR Multi-thread support; also, cleaned up code to save +* an lseek() in some cases. +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 05-25-88 PHG Merged DLL and normal versions +* 03-12-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* <cruntime.h>, removed #include <register.h> and fixed +* the copyright. Also, cleaned up the formatting a bit. +* 07-23-90 SBM Removed #include <assertm.h> +* 09-28-90 GJF New-style function declarator. +* 12-04-90 GJF Improved range check of file handle. Also, replaced +* numeric values with symbolic constants for seek +* methods. +* 01-16-91 GJF ANSI naming. +* 02-13-92 GJF Replaced _nfile by _nhandle for Win32. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <stdio.h> +#include <errno.h> +#include <io.h> +#include <internal.h> +#include <os2dll.h> +#include <stddef.h> +#include <stdlib.h> + +/*** +*long _filelength(filedes) - find length of a file +* +*Purpose: +* Returns the length in bytes of the specified file. +* +*Entry: +* int filedes - handle referring to file to find length of +* +*Exit: +* returns length of file in bytes +* returns -1L if fails +* +*Exceptions: +* +*******************************************************************************/ + +long _CALLTYPE1 _filelength ( + REG1 int filedes + ) +{ + long length; + long here; +#ifdef _WIN32_ + if ( (unsigned)filedes >= (unsigned)_nhandle ) { +#else + if ( (unsigned)filedes >= (unsigned)_nfile ) { +#endif + errno = EBADF; + _doserrno = 0L; /* not an OS error */ + return(-1L); + } + + _lock_fh(filedes); + + /* Seek to end to get length of file. */ + if ( (here = _lseek_lk(filedes, 0L, SEEK_CUR)) == -1L ) + length = -1L; /* return error */ + else { + length = _lseek_lk(filedes, 0L, SEEK_END); + if ( here != length ) + _lseek_lk(filedes, here, SEEK_SET); + } + + _unlock_fh(filedes); + + return(length); +} diff --git a/private/crt32/lowio/fstat.c b/private/crt32/lowio/fstat.c new file mode 100644 index 000000000..dcb013203 --- /dev/null +++ b/private/crt32/lowio/fstat.c @@ -0,0 +1,352 @@ +/*** +*fstat.c - OS/2 return file status info +* +* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines fstat() - return file status info +* +*Revision History: +* 03-??-84 RLB Module created +* 05-??-84 DCW Added register variables +* 05-19-86 SKS Ported to OS/2 +* 05-21-87 SKS Cleaned up declarations and include files +* 11-01-87 JCR Multi-thread support +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 05-25-88 PHG Merged DLL and normal version +* 10-03-88 GJF Adapted for new DOSCALLS.H, DOSTYPES.H. +* 10-04-88 JCR 386: Removed 'far' keyword +* 10-10-88 GJF Made API names match DOSCALLS.H +* 11-07-88 GJF Cleanup, now specific to 386 +* 04-13-89 JCR New syscall interface +* 05-23-89 PHG Added mask to ignore network bit when testing handle +* type +* 05-25-89 JCR 386 OS/2 calls use '_syscall' calling convention +* 03-12-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* <cruntime.h>, removed #include <register.h> and fixed +* the copyright. Also, cleaned up the formatting a bit. +* 04-04-90 GJF Removed #include <dos.h>. +* 07-24-90 SBM Removed '32' from API names +* 08-13-90 SBM Compiles cleanly with -W3 +* 09-28-90 GJF New-style function declarator. +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. +* 01-21-91 GJF ANSI naming. +* 04-26-91 SRW Implemented fstat for _WIN32_ and removed level 3 +* warnings. +* 02-13-92 GJF Replaced _nfile by _nhandle for Win32. +* 05-27-92 SKS File Creation and File Last Access timestamps may be 0 +* on some file systems (e.g. FAT) in which case the +* File Last Write time should be used instead. +* 06-04-92 SKS Changed comment that used to say "This is a BUG!" +* to explain that this value cannot be computed on +* OS/2 or NT. Only MS-DOS provides this functionality. +* The drive number is not valid for UNC names. +* 06-25-92 GJF Use GetFileInformationByHandle API, also cleaned up +* formatting of Win32 verson [_WIN32_]. +* 08-18-92 SKS Add a call to FileTimeToLocalFileTime +* as a temporary fix until _dtoxtime takes UTC +* 08-20-92 GJF Merged two changes above. +* 12-16-92 GJF Win32 GetFileInformationByHandle API doesn't like +* device or pipe handles. Use _S_IFIFO for pipes. +* 04-06-93 GJF Made computation of file times consistent with _stat(). +* +*******************************************************************************/ + +#include <cruntime.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <msdos.h> +#include <dostypes.h> +#include <io.h> +#include <internal.h> +#include <stddef.h> +#include <oscalls.h> +#include <stdio.h> +#include <os2dll.h> + +#ifndef _CRUISER_ +#include <time.h> +#endif + +#define IO_DEVNBR 0x3f + +/*** +*int _fstat(fildes, buf) - fills supplied buffer with status info +* +*Purpose: +* Fills the supplied buffer with status information on the +* file represented by the specified file designator. +* WARNING: the dev/rdev fields are zero for files. This is +* incompatible with DOS 3 version of this routine. +* +*Entry: +* int fildes - file descriptor +* struct stat *buf - buffer to store result in +* +*Exit: +* fills in buffer pointed to by buf +* returns 0 if successful +* returns -1 and sets errno if unsuccessful +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef _CRUISER_ + +int _CRTAPI1 _fstat ( + REG2 int fildes, + REG1 struct _stat *buf + ) +{ + + long cpos; + int isdev; /* 0 for a file, 1 for a device */ + int retval = 0; /* assume good return */ + if (fildes < 0 || fildes >= _nfile) { + errno = EBADF; + return(-1); + } + + /* Lock the file */ + + _lock_fh(fildes); + + /* Issue the get-device-info call. */ + { + int descrip; /* device descriptor word */ + + if (DOSQUERYHTYPE(fildes, (unsigned *)&isdev, (unsigned *)&descrip)) + { + errno = EBADF; + retval = -1; /* error from DOS call - bad file designator */ + goto done; /* join common return code */ + } + + /* set the common fields */ + + buf->st_ino = buf->st_uid = buf->st_gid = buf->st_mode = 0; + buf->st_nlink = 1; + + buf->st_mode |= (_osfile[fildes] & FRDONLY) + ? (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6)) + : ((_S_IREAD|_S_IWRITE) + + ((_S_IREAD|_S_IWRITE) >> 3) + + ((_S_IREAD|_S_IWRITE) >> 6)); + + /* set file date fields - NOTE for code below, it should be + * remembered that calls to QFILEINFO cannot fail since the file + * handle is known to be good since we got by the QHANDTYPE call. + */ + + { + FILESTATUS fs; + + (void)DOSQUERYFILEINFO(fildes, 1, (FILESTATUS *) & fs, sizeof(fs)); + + buf->st_mtime = XTIME(fs.fdateLastWrite, fs.ftimeLastWrite); + + if ( _DATECAST(fs.fdateLastAccess) || _TIMECAST(fs.ftimeLastAccess) ) + buf->st_atime = XTIME(fs.fdateLastAccess, fs.ftimeLastAccess); + else + buf->st_atime = buf->st_mtime ; + + if ( _DATECAST(fs.fdateCreation) || _TIMECAST(fs.ftimeCreation) ) + buf->st_ctime = XTIME(fs.fdateCreation, fs.ftimeCreation); + else + buf->st_ctime = buf->st_mtime ; + + buf->st_mtime = XTIME(fs.fdateLastWrite, fs.ftimeLastWrite); + } + + /* check for device or file */ + + if (isdev & 0xFF) { + /* file designator refers to a device - set file size to 0 */ + + buf->st_size = 0; + buf->st_mode |= _S_IFCHR; + buf->st_rdev = buf->st_dev = (_dev_t)fildes; + } + else { + /* file designator refers to a file - set actual file size */ + + cpos = _lseek_lk(fildes, 0L, 1); + buf->st_size = _lseek_lk(fildes, 0L, 2); + _lseek_lk(fildes, cpos, 0); + + buf->st_mode |= _S_IFREG; + + /* + * On DOS, this field contains the drive number, but + * the drive number is not available on this platform. + * Also, for UNC network names, there is no drive number. + */ + buf->st_rdev = buf->st_dev = 0; + } + +/* Common return code */ + +done: + _unlock_fh(fildes); + return(retval); +} + + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + +int _CRTAPI1 _fstat ( + int fildes, + struct _stat *buf + ) +{ + int isdev; /* 0 for a file, 1 for a device */ + int retval = 0; /* assume good return */ + BY_HANDLE_FILE_INFORMATION bhfi; + SYSTEMTIME SystemTime; + + if ( (unsigned)fildes >= (unsigned)_nhandle ) { + errno = EBADF; + return(-1); + } + + /* Lock the file */ + + _lock_fh(fildes); + + /* Find out what kind of handle underlies filedes + */ + isdev = GetFileType((HANDLE)_osfhnd[fildes]) & ~FILE_TYPE_REMOTE; + + if ( isdev != FILE_TYPE_DISK ) { + + /* not a disk file. probably a device or pipe + */ + if ( (isdev == FILE_TYPE_CHAR) || (isdev == FILE_TYPE_PIPE) ) { + /* treat pipes and devices similarly. no further info is + * available from any API, so set the fields as reasonably + * as possible and return. + */ + if ( isdev == FILE_TYPE_CHAR ) + buf->st_mode = _S_IFCHR; + else + buf->st_mode = _S_IFIFO; + + buf->st_rdev = buf->st_dev = (_dev_t)fildes; + buf->st_nlink = 1; + buf->st_uid = buf->st_gid = buf->st_ino = 0; + buf->st_atime = buf->st_mtime = buf->st_ctime = buf->st_size + = 0; + + goto done; + + } + else if ( isdev == FILE_TYPE_UNKNOWN ) { + errno = EBADF; + retval = -1; + goto done; /* join common return code */ + } + else { + /* according to the documentation, this cannot happen, but + * play it safe anyway. + */ + _dosmaperr(GetLastError()); + retval = -1; + goto done; + } + } + + + /* set the common fields + */ + buf->st_ino = buf->st_uid = buf->st_gid = buf->st_mode = 0; + buf->st_nlink = 1; + + /* use the file handle to get all the info about the file + */ + if ( !GetFileInformationByHandle((HANDLE)_osfhnd[fildes], &bhfi) ) { + _dosmaperr(GetLastError()); + retval = -1; + goto done; + } + + if ( bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY ) + buf->st_mode |= (_S_IREAD + (_S_IREAD >> 3) + (_S_IREAD >> 6)); + else + buf->st_mode |= ((_S_IREAD|_S_IWRITE) + ((_S_IREAD|_S_IWRITE) >> 3) + + ((_S_IREAD|_S_IWRITE) >> 6)); + + /* set file date fields + */ + FileTimeToSystemTime( &(bhfi.ftLastWriteTime), &SystemTime ); + + buf->st_mtime = __gmtotime_t(SystemTime.wYear, + SystemTime.wMonth, + SystemTime.wDay, + SystemTime.wHour, + SystemTime.wMinute, + SystemTime.wSecond + ); + + if ( bhfi.ftLastAccessTime.dwLowDateTime || bhfi.ftLastAccessTime. + dwHighDateTime ) { + + FileTimeToSystemTime( &(bhfi.ftLastAccessTime), &SystemTime ); + + buf->st_atime = __gmtotime_t(SystemTime.wYear, + SystemTime.wMonth, + SystemTime.wDay, + SystemTime.wHour, + SystemTime.wMinute, + SystemTime.wSecond + ); + } + else + buf->st_atime = buf->st_mtime; + + if ( bhfi.ftCreationTime.dwLowDateTime || bhfi.ftCreationTime. + dwHighDateTime ) { + + FileTimeToSystemTime( &(bhfi.ftCreationTime), &SystemTime ); + + buf->st_ctime = __gmtotime_t(SystemTime.wYear, + SystemTime.wMonth, + SystemTime.wDay, + SystemTime.wHour, + SystemTime.wMinute, + SystemTime.wSecond + ); + } + else + buf->st_ctime = buf->st_mtime; + + + buf->st_size = bhfi.nFileSizeLow; + + buf->st_mode |= _S_IFREG; + + /* On DOS, this field contains the drive number, but + * the drive number is not available on this platform. + * Also, for UNC network names, there is no drive number. + */ + buf->st_rdev = buf->st_dev = 0; + +/* Common return code */ + +done: + _unlock_fh(fildes); + return(retval); +} + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ diff --git a/private/crt32/lowio/getch.c b/private/crt32/lowio/getch.c new file mode 100644 index 000000000..db7d2c585 --- /dev/null +++ b/private/crt32/lowio/getch.c @@ -0,0 +1,672 @@ +/*** +*getch.c - contains _getch(), _getche(), _ungetch() and kbhit for Windows NT +* +* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Defines the "direct console" functions listed above. +* +* NOTE: The real-mode DOS versions of these functions read from +* standard input and are therefore redirected when standard input +* is redirected. However, these versions ALWAYS read from the console, +* even when standard input is redirected. +* +*Revision History: +* 06-08-89 PHG Module created, based on asm version +* 03-12-90 GJF Made calling type _CALLTYPE1, added #include +* <cruntime.h> and fixed the copyright. Also, cleaned +* up the formatting a bit. +* 06-05-90 SBM Recoded as pure 32-bit, using new file handle state bits +* 07-24-90 SBM Removed '32' from API names +* 10-03-90 GJF New-style function declarators. +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. +* 01-16-91 GJF ANSI naming. +* 01-25-91 SRW Get/SetConsoleMode parameters changed (_WIN32_) +* 02-18-91 SRW Get/SetConsoleMode required read/write access (_WIN32_) +* 02-19-91 SRW Adapt to OpenFile/CreateFile changes (_WIN32_) +* 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_) +* 07-26-91 GJF Took out init. stuff and cleaned up the error +* handling [_WIN32_]. +* 12-11-92 GJF Initialize character buffer to 0 (int ch = 0;) and +* use ReadConsole instead of ReadFile. +* 03-20-93 GJF Completely rewritten, Cruiser support purged, _kbhit +* (also rewritten) and _ungetch also merged in. +* 05-10-93 GJF Fixed bug in _kbhit, pointer passed to free no +* longer pointed to the allocated block. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <conio.h> +#include <os2dll.h> +#include <stdio.h> +#include <stdlib.h> + +typedef struct { + unsigned char LeadChar; + unsigned char SecondChar; + } CharPair; + +typedef struct { + unsigned short ScanCode; + CharPair RegChars; + CharPair ShiftChars; + CharPair CtrlChars; + CharPair AltChars; + } EnhKeyVals; + +typedef struct { + CharPair RegChars; + CharPair ShiftChars; + CharPair CtrlChars; + CharPair AltChars; + } NormKeyVals; + +/* + * Table of key values for enhanced keys + */ +static EnhKeyVals EnhancedKeys[] = { + { 28, { 13, 0 }, { 13, 0 }, { 10, 0 }, { 0, 166 } }, + { 53, { 47, 0 }, { 63, 0 }, { 0, 149 }, { 0, 164 } }, + { 71, { 224, 71 }, { 224, 71 }, { 224, 119 }, { 0, 151 } }, + { 72, { 224, 72 }, { 224, 72 }, { 224, 141 }, { 0, 152 } }, + { 73, { 224, 73 }, { 224, 73 }, { 224, 134 }, { 0, 153 } }, + { 75, { 224, 75 }, { 224, 75 }, { 224, 115 }, { 0, 155 } }, + { 77, { 224, 77 }, { 224, 77 }, { 224, 116 }, { 0, 157 } }, + { 79, { 224, 79 }, { 224, 79 }, { 224, 117 }, { 0, 159 } }, + { 80, { 224, 80 }, { 224, 80 }, { 224, 145 }, { 0, 160 } }, + { 81, { 224, 81 }, { 224, 81 }, { 224, 118 }, { 0, 161 } }, + { 82, { 224, 82 }, { 224, 82 }, { 224, 146 }, { 0, 162 } }, + { 83, { 224, 83 }, { 224, 83 }, { 224, 147 }, { 0, 163 } } + }; + +/* + * macro for the number of elements of in EnhancedKeys[] + */ +#define NUM_EKA_ELTS ( sizeof( EnhancedKeys ) / sizeof( EnhKeyVals ) ) + +/* + * Table of key values for normal keys. Note that the table is padded so + * that the key scan code serves as an index into the table. + */ +static NormKeyVals NormalKeys[] = { + + /* padding */ + { /* 0 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + + { /* 1 */ { 27, 0 }, { 27, 0 }, { 27, 0 }, { 0, 1 } }, + { /* 2 */ { 49, 0 }, { 33, 0 }, { 0, 0 }, { 0, 120 } }, + { /* 3 */ { 50, 0 }, { 64, 0 }, { 0, 3 }, { 0, 121 } }, + { /* 4 */ { 51, 0 }, { 35, 0 }, { 0, 0 }, { 0, 122 } }, + { /* 5 */ { 52, 0 }, { 36, 0 }, { 0, 0 }, { 0, 123 } }, + { /* 6 */ { 53, 0 }, { 37, 0 }, { 0, 0 }, { 0, 124 } }, + { /* 7 */ { 54, 0 }, { 94, 0 }, { 30, 0 }, { 0, 125 } }, + { /* 8 */ { 55, 0 }, { 38, 0 }, { 0, 0 }, { 0, 126 } }, + { /* 9 */ { 56, 0 }, { 42, 0 }, { 0, 0 }, { 0, 127 } }, + { /* 10 */ { 57, 0 }, { 40, 0 }, { 0, 0 }, { 0, 128 } }, + { /* 11 */ { 48, 0 }, { 41, 0 }, { 0, 0 }, { 0, 129 } }, + { /* 12 */ { 45, 0 }, { 95, 0 }, { 31, 0 }, { 0, 130 } }, + { /* 13 */ { 61, 0 }, { 43, 0 }, { 0, 0 }, { 0, 131 } }, + { /* 14 */ { 8, 0 }, { 8, 0 }, { 127, 0 }, { 0, 14 } }, + { /* 15 */ { 9, 0 }, { 0, 15 }, { 0, 148 }, { 0, 15 } }, + { /* 16 */ { 113, 0 }, { 81, 0 }, { 17, 0 }, { 0, 16 } }, + { /* 17 */ { 119, 0 }, { 87, 0 }, { 23, 0 }, { 0, 17 } }, + { /* 18 */ { 101, 0 }, { 69, 0 }, { 5, 0 }, { 0, 18 } }, + { /* 19 */ { 114, 0 }, { 82, 0 }, { 18, 0 }, { 0, 19 } }, + { /* 20 */ { 116, 0 }, { 84, 0 }, { 20, 0 }, { 0, 20 } }, + { /* 21 */ { 121, 0 }, { 89, 0 }, { 25, 0 }, { 0, 21 } }, + { /* 22 */ { 117, 0 }, { 85, 0 }, { 21, 0 }, { 0, 22 } }, + { /* 23 */ { 105, 0 }, { 73, 0 }, { 9, 0 }, { 0, 23 } }, + { /* 24 */ { 111, 0 }, { 79, 0 }, { 15, 0 }, { 0, 24 } }, + { /* 25 */ { 112, 0 }, { 80, 0 }, { 16, 0 }, { 0, 25 } }, + { /* 26 */ { 91, 0 }, { 123, 0 }, { 27, 0 }, { 0, 26 } }, + { /* 27 */ { 93, 0 }, { 125, 0 }, { 29, 0 }, { 0, 27 } }, + { /* 28 */ { 13, 0 }, { 13, 0 }, { 10, 0 }, { 0, 28 } }, + + /* padding */ + { /* 29 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + + { /* 30 */ { 97, 0 }, { 65, 0 }, { 1, 0 }, { 0, 30 } }, + { /* 31 */ { 115, 0 }, { 83, 0 }, { 19, 0 }, { 0, 31 } }, + { /* 32 */ { 100, 0 }, { 68, 0 }, { 4, 0 }, { 0, 32 } }, + { /* 33 */ { 102, 0 }, { 70, 0 }, { 6, 0 }, { 0, 33 } }, + { /* 34 */ { 103, 0 }, { 71, 0 }, { 7, 0 }, { 0, 34 } }, + { /* 35 */ { 104, 0 }, { 72, 0 }, { 8, 0 }, { 0, 35 } }, + { /* 36 */ { 106, 0 }, { 74, 0 }, { 10, 0 }, { 0, 36 } }, + { /* 37 */ { 107, 0 }, { 75, 0 }, { 11, 0 }, { 0, 37 } }, + { /* 38 */ { 108, 0 }, { 76, 0 }, { 12, 0 }, { 0, 38 } }, + { /* 39 */ { 59, 0 }, { 58, 0 }, { 0, 0 }, { 0, 39 } }, + { /* 40 */ { 39, 0 }, { 34, 0 }, { 0, 0 }, { 0, 40 } }, + { /* 41 */ { 96, 0 }, { 126, 0 }, { 0, 0 }, { 0, 41 } }, + + /* padding */ + { /* 42 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + + { /* 43 */ { 92, 0 }, { 124, 0 }, { 28, 0 }, { 0, 0 } }, + { /* 44 */ { 122, 0 }, { 90, 0 }, { 26, 0 }, { 0, 44 } }, + { /* 45 */ { 120, 0 }, { 88, 0 }, { 24, 0 }, { 0, 45 } }, + { /* 46 */ { 99, 0 }, { 67, 0 }, { 3, 0 }, { 0, 46 } }, + { /* 47 */ { 118, 0 }, { 86, 0 }, { 22, 0 }, { 0, 47 } }, + { /* 48 */ { 98, 0 }, { 66, 0 }, { 2, 0 }, { 0, 48 } }, + { /* 49 */ { 110, 0 }, { 78, 0 }, { 14, 0 }, { 0, 49 } }, + { /* 50 */ { 109, 0 }, { 77, 0 }, { 13, 0 }, { 0, 50 } }, + { /* 51 */ { 44, 0 }, { 60, 0 }, { 0, 0 }, { 0, 51 } }, + { /* 52 */ { 46, 0 }, { 62, 0 }, { 0, 0 }, { 0, 52 } }, + { /* 53 */ { 47, 0 }, { 63, 0 }, { 0, 0 }, { 0, 53 } }, + + /* padding */ + { /* 54 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + + { /* 55 */ { 42, 0 }, { 0, 0 }, { 114, 0 }, { 0, 0 } }, + + /* padding */ + { /* 56 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + + { /* 57 */ { 32, 0 }, { 32, 0 }, { 32, 0 }, { 32, 0 } }, + + /* padding */ + { /* 58 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + + { /* 59 */ { 0, 59 }, { 0, 84 }, { 0, 94 }, { 0, 104 } }, + { /* 60 */ { 0, 60 }, { 0, 85 }, { 0, 95 }, { 0, 105 } }, + { /* 61 */ { 0, 61 }, { 0, 86 }, { 0, 96 }, { 0, 106 } }, + { /* 62 */ { 0, 62 }, { 0, 87 }, { 0, 97 }, { 0, 107 } }, + { /* 63 */ { 0, 63 }, { 0, 88 }, { 0, 98 }, { 0, 108 } }, + { /* 64 */ { 0, 64 }, { 0, 89 }, { 0, 99 }, { 0, 109 } }, + { /* 65 */ { 0, 65 }, { 0, 90 }, { 0, 100 }, { 0, 110 } }, + { /* 66 */ { 0, 66 }, { 0, 91 }, { 0, 101 }, { 0, 111 } }, + { /* 67 */ { 0, 67 }, { 0, 92 }, { 0, 102 }, { 0, 112 } }, + { /* 68 */ { 0, 68 }, { 0, 93 }, { 0, 103 }, { 0, 113 } }, + + /* padding */ + { /* 69 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { /* 70 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + + { /* 71 */ { 0, 71 }, { 55, 0 }, { 0, 119 }, { 0, 0 } }, + { /* 72 */ { 0, 72 }, { 56, 0 }, { 0, 141 }, { 0, 0 } }, + { /* 73 */ { 0, 73 }, { 57, 0 }, { 0, 132 }, { 0, 0 } }, + { /* 74 */ { 0, 0 }, { 45, 0 }, { 0, 0 }, { 0, 0 } }, + { /* 75 */ { 0, 75 }, { 52, 0 }, { 0, 115 }, { 0, 0 } }, + { /* 76 */ { 0, 0 }, { 53, 0 }, { 0, 0 }, { 0, 0 } }, + { /* 77 */ { 0, 77 }, { 54, 0 }, { 0, 116 }, { 0, 0 } }, + { /* 78 */ { 0, 0 }, { 43, 0 }, { 0, 0 }, { 0, 0 } }, + { /* 79 */ { 0, 79 }, { 49, 0 }, { 0, 117 }, { 0, 0 } }, + { /* 80 */ { 0, 80 }, { 50, 0 }, { 0, 145 }, { 0, 0 } }, + { /* 81 */ { 0, 81 }, { 51, 0 }, { 0, 118 }, { 0, 0 } }, + { /* 82 */ { 0, 82 }, { 48, 0 }, { 0, 146 }, { 0, 0 } }, + { /* 83 */ { 0, 83 }, { 46, 0 }, { 0, 147 }, { 0, 0 } }, + + /* padding */ + { /* 84 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { /* 85 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { /* 86 */ { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + + { /* 87 */ { 224, 133 }, { 224, 135 }, { 224, 137 }, { 224, 139 } }, + { /* 88 */ { 224, 134 }, { 224, 136 }, { 224, 138 }, { 224, 140 } } + +}; + + +/* + * This is the one character push-back buffer used by _getch(), _getche() + * and _ungetch(). + */ +static int chbuf = EOF; + + +/* + * Declaration for console handle + */ +extern int _coninpfh; + +/* + * Function that looks up the extended key code for a given event. + */ +static CharPair * _CRTAPI3 GetExtendedKeyCode(KEY_EVENT_RECORD *); + + +/*** +*int _getch(), _getche() - read one char. from console (without and with echo) +* +*Purpose: +* If the "_ungetch()" push-back buffer is not empty (empty==-1) Then +* Mark it empty (-1) and RETURN the value that was in it +* Read a character using DOSREAD in RAW mode +* Return the Character Code +* _getche(): Same as _getch() except that the character value returned +* is echoed (via "_putch()") +* +* No _ext_code buffer is required (unlike the DOS & 16 bit OS/2 world,) +* since OS/2 buffers the extended code for us. +* +*Entry: +* None, reads from console. +* +*Exit: +* If an error is returned from the API +* Then EOF +* Otherwise +* next byte from console +* Static variable "chbuf" may be altered +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef MTHREAD + +int _CRTAPI1 _getch ( + void + ) +{ + int ch; + + _mlock(_CONIO_LOCK); /* secure the console lock */ + ch = _getch_lk(); /* input the character */ + _munlock(_CONIO_LOCK); /* release the console lock */ + + return ch; +} + +int _CRTAPI1 _getche ( + void + ) +{ + int ch; + + _mlock(_CONIO_LOCK); /* secure the console lock */ + ch = _getche_lk(); /* input and echo the character */ + _munlock(_CONIO_LOCK); /* unlock the console */ + + return ch; +} + +#endif /* MTHREAD */ + + +#ifdef MTHREAD +int _CRTAPI1 _getch_lk ( +#else +int _CRTAPI1 _getch ( +#endif + void + ) +{ + INPUT_RECORD ConInpRec; + DWORD NumRead; + CharPair *pCP; + int ch = 0; /* single character buffer */ + DWORD oldstate; + + /* + * check pushback buffer (chbuf) a for character + */ + if ( chbuf != EOF ) { + /* + * something there, clear buffer and return the character. + */ + ch = (unsigned char)(chbuf & 0xFF); + chbuf = EOF; + return ch; + } + + if (_coninpfh == -1) + return EOF; + + /* + * Switch to raw mode (no line input, no echo input) + */ + GetConsoleMode( (HANDLE)_coninpfh, &oldstate ); + SetConsoleMode( (HANDLE)_coninpfh, 0L ); + + for ( ; ; ) { + + /* + * Get a console input event. + */ + if ( !ReadConsoleInput( (HANDLE)_coninpfh, + &ConInpRec, + 1L, + &NumRead ) + || (NumRead == 0L) ) + { + ch = EOF; + break; + } + + /* + * Look for, and decipher, key events. + */ + if ( (ConInpRec.EventType == KEY_EVENT) && + ConInpRec.Event.KeyEvent.bKeyDown ) { + /* + * Easy case: if uChar.AsciiChar is non-zero, just stuff it + * into ch and quit. + */ + if ( ch = (unsigned char)ConInpRec.Event.KeyEvent.uChar.AsciiChar ) + break; + + /* + * Hard case: either an extended code or an event which should + * not be recognized. let GetExtendedKeyCode() do the work... + */ + if ( pCP = GetExtendedKeyCode( &(ConInpRec.Event.KeyEvent) ) ) { + ch = pCP->LeadChar; + chbuf = pCP->SecondChar; + break; + } + } + } + + + /* + * Restore previous console mode. + */ + SetConsoleMode( (HANDLE)_coninpfh, oldstate ); + + return ch; +} + + +/* + * getche is just getch followed by a putch if no error occurred + */ + +#ifdef MTHREAD +int _CRTAPI1 _getche_lk ( +#else +int _CRTAPI1 _getche ( +#endif + void + ) +{ + int ch; /* character read */ + + ch = _getch_lk(); /* read character */ + if (ch != EOF) { + if (_putch_lk(ch) != EOF) { + return ch; /* if no error, return char */ + } + } + return EOF; /* get or put failed, return EOF */ +} + + +/*** +*int _kbhit() - return flag if a keystroke is already waiting to be read +* +*Purpose: +* If the "_ungetch()" push-back buffer is not empty (empty==-1) Then +* Return TRUE +* Otherwise get the Keyboard Status (via DOSQUERYFHSTATE) +* No _ext_code buffer is required (unlike the DOS & 16 bit OS/2 world,) +* since OS/2 buffers the extended code for us. +* +*Entry: +* None, tests console. +* +*Exit: +* returns 0 if no key waiting +* = !0 if key waiting +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef MTHREAD + +int _CRTAPI1 _kbhit_lk(void); + +int _CRTAPI1 _kbhit ( + void + ) +{ + int retval; + + _mlock(_CONIO_LOCK); /* secure the console lock */ + retval = _kbhit_lk(); /* determine if a key is waiting */ + _munlock(_CONIO_LOCK); /* release the console lock */ + + return retval; +} + +int _CRTAPI1 _kbhit_lk ( + +#else + +int _CRTAPI1 _kbhit ( + +#endif + void + ) +{ + void *pblk; + PINPUT_RECORD pIRBuf; + DWORD NumPending; + DWORD NumPeeked; + + /* + * if a character has been pushed back, return TRUE + */ + if ( chbuf != -1 ) + return TRUE; + + /* + * Peek all pending console events + */ + if ( (_coninpfh == -1) || + + !GetNumberOfConsoleInputEvents((HANDLE)_coninpfh, &NumPending) || + + ((pblk = malloc( NumPending * sizeof(INPUT_RECORD) )) == NULL) ) + { + return FALSE; + } + + /* + * Keep pblk unmodified, for use in a later call to free() + */ + pIRBuf = (PINPUT_RECORD)pblk; + + if ( PeekConsoleInput( (HANDLE)_coninpfh, + pIRBuf, + NumPending, + &NumPeeked ) && + + (NumPeeked != 0L) && + + (NumPeeked <= NumPending) ) + { + + /* + * Scan all of the peeked events to determine if any is a key event + * which should be recognized. + */ + for ( ; NumPeeked > 0 ; NumPeeked--, pIRBuf++ ) { + + if ( (pIRBuf->EventType == KEY_EVENT) && + + (pIRBuf->Event.KeyEvent.bKeyDown) && + + ( pIRBuf->Event.KeyEvent.uChar.AsciiChar || + GetExtendedKeyCode( &(pIRBuf->Event.KeyEvent) ) ) ) + { + /* + * Key event corresponding to an ASCII character or an + * extended code. In either case, success! + */ + free(pblk); + return TRUE; + } + } + } + + free(pblk); + return FALSE; +} + + +/*** +*int _ungetch(c) - push back one character for "_getch()" or "_getche()" +* +*Purpose: +* If the Push-back buffer "chbuf" is -1 Then +* Set "chbuf" to the argument and return the argument +* Else +* Return EOF to indicate an error +* +*Entry: +* int c - Character to be pushed back +* +*Exit: +* If successful +* returns character that was pushed back +* Else if error +* returns EOF +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef MTHREAD + +int _CRTAPI1 _ungetch ( + int c + ) +{ + int retval; + + _mlock(_CONIO_LOCK); /* lock the console */ + retval = _ungetch_lk(c); /* pushback character */ + _munlock(_CONIO_LOCK); /* unlock the console */ + + return retval; +} +int _CRTAPI1 _ungetch_lk ( + +#else + +int _CRTAPI1 _ungetch ( + +#endif + int c + ) +{ + /* + * Fail if the char is EOF or the pushback buffer is non-empty + */ + if ( (c == EOF) || (chbuf != EOF) ) + return EOF; + + chbuf = (c & 0xFF); + return chbuf; +} + + + + +/*** +* static CharPair * GetExtendedKeyCode(pKE) - return extended code (if any) +* for key event. +* +*Purpose: +* Core function for _getch (and getche) and essential to _kbhit. This +* is the function that determines whether or not a key event NOT +* accompanied by an ASCII character has an extended code and returns +* that code. +* +*Entry: +* None, tests console. +* +*Exit: +* if successful, returns a pointer to a CharPair value holding the lead +* and second characters of the extended code. +* +* if unsuccesful, returns NULL +* +*Exceptions: +* +*******************************************************************************/ + + +static CharPair * _CRTAPI3 GetExtendedKeyCode ( + KEY_EVENT_RECORD *pKE + ) +{ + DWORD CKS; /* hold dwControlKeyState value */ + CharPair *pCP; /* pointer to CharPair containing extended + code */ + int i; + + // printf("pKE->wVirtualScanCode = %d\n", (int) (pKE->wVirtualScanCode) ); + // printf("pKE->dwControlKeyState = %lx\n\n", pKE->dwControlKeyState); + + if ( (CKS = pKE->dwControlKeyState) & ENHANCED_KEY ) { + + /* + * Find the appropriate entry in EnhancedKeys[] + */ + for ( pCP = NULL, i = 0 ; i < NUM_EKA_ELTS ; i++ ) { + + if ( EnhancedKeys[i].ScanCode == pKE->wVirtualScanCode ) { + + if ( CKS & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) ) + + pCP = &(EnhancedKeys[i].AltChars); + + else if ( CKS & (LEFT_CTRL_PRESSED | LEFT_CTRL_PRESSED) ) + + pCP = &(EnhancedKeys[i].CtrlChars); + + else if ( CKS & SHIFT_PRESSED) + + pCP = &(EnhancedKeys[i].ShiftChars); + + else + + pCP = &(EnhancedKeys[i].RegChars); + + break; + + } + } + + } + + else { + + /* + * Regular key or a keyboard event which shouldn't be recognized. + * Determine which by getting the proper field of the proper + * entry in NormalKeys[], and examining the extended code. + */ + if ( CKS & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED) ) + + pCP = &(NormalKeys[pKE->wVirtualScanCode].AltChars); + + else if ( CKS & (LEFT_CTRL_PRESSED | LEFT_CTRL_PRESSED) ) + + pCP = &(NormalKeys[pKE->wVirtualScanCode].CtrlChars); + + else if ( CKS & SHIFT_PRESSED) + + pCP = &(NormalKeys[pKE->wVirtualScanCode].ShiftChars); + + else + + pCP = &(NormalKeys[pKE->wVirtualScanCode].RegChars); + + if ( ((pCP->LeadChar != 0) && (pCP->LeadChar != 224)) || + (pCP->SecondChar == 0) ) + /* + * Must be a keyboard event which should not be recognized + * (e.g., shift key was pressed) + */ + pCP = NULL; + + } + + return(pCP); +} diff --git a/private/crt32/lowio/i386/_initcon.asm b/private/crt32/lowio/i386/_initcon.asm new file mode 100644 index 000000000..3ec35d9b6 --- /dev/null +++ b/private/crt32/lowio/i386/_initcon.asm @@ -0,0 +1,17 @@ + page ,132 + +;******* +; +; Alternate form of CINITCON.ASM +; +; The MIPS C Compiler does not prepend underscores to C +; variables and functions like the I386 C Compiler does. +; +; The EQUate below will yield an object file +; which will be appropriate for MIPS COFF format. +; +;******* + +NO_UNDERSCORE equ 1 + +include i386\cinitcon.asm diff --git a/private/crt32/lowio/i386/cinitcon.asm b/private/crt32/lowio/i386/cinitcon.asm new file mode 100644 index 000000000..aa6f8074a --- /dev/null +++ b/private/crt32/lowio/i386/cinitcon.asm @@ -0,0 +1,99 @@ + page ,132 + title cinitcon - C Run-Time Startup Initialization for Console I/O +;*** +;cinitcon.asm - C Run-Time Startup Initialization for WIN32 +; +; Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved. +; +;Purpose: +; Initialization and Termination for console I/O +; +;Notes: +; _confh and _coninpfh are defined in this module to force the +; inclusion of this module if any console I/O is performed. +; This module places the address of _initcon() in the initializer +; table and the address of _termcon() in the pre-terminator table. +; +;Revision History: +; 03-19-92 SKS Module created. +; 03-24-92 SKS Added MIPS support (NO_UNDERSCORE) +; 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs +; 08-06-92 SKS Revised to use new section names and macros +; +;******************************************************************************* + +.xlist +include cruntime.inc +include defsects.inc +.list + +ifndef _WIN32_ +.err +%out _WIN32_ MUST be defined! +endif + + +ifndef NO_UNDERSCORE ; I386 VERSION ************************* + + + extrn _initcon:NEAR + extrn _termcon:NEAR + + +beginSection XIC + + dd offset FLAT: _initcon + +endSection XIC + + +beginSection XPX + + dd offset FLAT: _termcon + +endSection XPX + + + .DATA + + public _coninpfh + public _confh + +_coninpfh dd -1 ; console input +_confh dd -1 ; console output + + +else ; NO_UNDERSCORE ; MIPS VERSION ************************* + + + extrn initcon:NEAR + extrn termcon:NEAR + + +beginSection XIC + + dd offset FLAT: initcon + +endSection XIC + + +beginSection XPX + + dd offset FLAT: termcon + +endSection XPX + + + .DATA + + public coninpfh + public confh + +coninpfh dd -1 ; console input +confh dd -1 ; console output + + +endif ; NO_UNDERSCORE ; **** VERSION ************************* + + + end diff --git a/private/crt32/lowio/initcon.c b/private/crt32/lowio/initcon.c new file mode 100644 index 000000000..0302e5d84 --- /dev/null +++ b/private/crt32/lowio/initcon.c @@ -0,0 +1,113 @@ +/*** +*_initcon.c - direct console I/O initialization and termination for Win32 +* +* Copyright (c) 1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Defines _initcon() and _termcon() routines. +* +* NOTE: The _initcon() and _termcon() routines are called indirectly +* by the startup and termination code, thru the pointers _pinitcon +* and _ptermcon. +* +*Revision History: +* 07-26-91 GJF Module created. Based on the original code by Stevewo +* (which was distributed across several sources). +* 03-12-92 SKS Split out initializer +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> + +void __cdecl _initcon(void); +void __cdecl _termcon(void); + +#ifdef _MSC_VER + +#pragma data_seg(".CRT$XIC") +static void (__cdecl *pinit)(void) = _initcon; + +#pragma data_seg(".CRT$XPX") +static void (__cdecl *pterm)(void) = _termcon; + +#pragma data_seg() + +#endif /* _MSC_VER */ + +/* + * define console handles. these definitions cause this file to be linked + * in if one of the direct console I/O functions is referenced. + */ +int _coninpfh = -1; /* console input */ +int _confh = -1; /* console output */ + +/*** +*void _initcon(void) - open handles for console I/O +* +*Purpose: +* Opens handles for console input and output. +* +*Entry: +* None. +* +*Exit: +* No return value. If successful, handle values are copied into the +* global variables _coninpfh and _confh. +* +*Exceptions: +* +*******************************************************************************/ + +void __cdecl _initcon ( + void + ) +{ + _coninpfh = (int)CreateFile( "CONIN$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL + ); + + _confh = (int)CreateFile( "CONOUT$", + GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL + ); +} + + +/*** +*void _termcon(void) - close console I/O handles +* +*Purpose: +* Closes _coninpfh and _confh. +* +*Entry: +* None. +* +*Exit: +* No return value. +* +*Exceptions: +* +*******************************************************************************/ + +void __cdecl _termcon ( + void + ) +{ + if ( _confh != -1 ) { + CloseHandle( (HANDLE)_confh ); + } + + if ( _coninpfh != -1 ) { + CloseHandle( (HANDLE)_coninpfh ); + } +} diff --git a/private/crt32/lowio/ioinit.c b/private/crt32/lowio/ioinit.c new file mode 100644 index 000000000..d359f9686 --- /dev/null +++ b/private/crt32/lowio/ioinit.c @@ -0,0 +1,242 @@ +/*** +*ioinit.c - Initialization for lowio functions +* +* Copyright (c) 1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Contains all initialization for lowio functions. Currently, this +* includes: +* 1. Definitions of _nhandle, _osfhnd[], _osfile[] and _pipech[], +* including initial values. +* 2. Processing of inherited file info from parent process. +* 3. Initialization of _osfhnd[] and _osfile[] entries for +* standard input/output/error. +* +*Revision History: +* 02-14-92 GJF Module created. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <internal.h> +#include <msdos.h> +#include <stdlib.h> +#include <string.h> + +/* + * Number of allowable file handles. The static initialization of the + * _osfhnd[] and _pipech[] arrays (below) supports only two values of + * _NHANDLE, 64 (for single-thread) and 256 (for multi-thread)! + */ +int _nhandle = _NHANDLE_; + +/* + * File handle database + */ +char _osfile[_NHANDLE_] = { 0 }; + +/* + * Array of OS file handles. Statically initialized to INVALID_HANDLE_VALUE. + * Note that if _NHANDLE_ differs from 64 for single-thread, or differs from + * 256 for multi-thread, this initialization needs to be revised. + */ +#define NOHNDL (long)INVALID_HANDLE_VALUE + +long _osfhnd[_NHANDLE_] = { + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, +#ifdef MTHREAD + NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, + NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, NOHNDL, +#endif + NOHNDL }; + +/* + * Peek-ahead buffers for pipes, each initialized to a newline. Note that if + * _NHANDLE_ differs from 64 for single-thread, or differs from 256 for + * multi-thread, this initialization needs to be revised. + */ +char _pipech[_NHANDLE_] = { + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, +#ifdef MTHREAD + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, +#endif + 10 }; + +/* + * macro used to map 0, 1 and 2 to right value for call to GetStdHandle + */ +#define stdhndl(fh) ( (fh == 0) ? STD_INPUT_HANDLE : ((fh == 1) ? \ + STD_OUTPUT_HANDLE : STD_ERROR_HANDLE) ) + +/*** +*_ioinit() - +* +*Purpose: +* First, _ioinit() obtains and processes information on inherited file +* handles from the parent process (e.g., cmd.exe) +* +* Obtains the StartupInfo structure from the OS. The inherited file +* handle information is pointed to by the lpReserved2 field. The format +* of the information is as follows: +* +* bytes 0 thru 3 - integer value, say N, which is the number of handles +* information is passed about. +* +* bytes 4 thru N+3 - values for _osfile[0] thru _osfile[N-1] +* +* bytes N+4 thru 5*N+3 - N double-words, the N OS handle values being +* passed. +* +* Next, _osfhnd[i] and _osfile[i] are initialized for i = 0, 1, 2, as +* follows: +* +* If the value in _osfhnd[i] is INVALID_HANDLE_VALUE, then try to +* obtain a handle by calling GetStdHandle, and call GetFileType to +* help set _osfile[i]. Otherwise, assume _osfhndl[i] and _osfile[i] +* are valid, but force it to text mode (standard input/output/error +* are to always start out in text mode). +* +* Notes: +* 1. In general, not all of the passed info from the parent process +* will describe open handles! If, for example, only C handle 1 +* (STDOUT) and C handle 6 are open in the parent, info for C +* handles 0 thru 6 is passed to the the child. +* +* 2. Care is taken not to 'overflow' _osfhnd[] and _osfile[]. Only +* info on the first _NHANDLE_ handles from the parent process is +* used. +* +* 3. See exec\dospawn.c for the encodes of the file handle info +* to be passed to a child process. +* +*Entry: +* No parameters: reads the environment. +* +*Exit: +* No return value. +* +*Exceptions: +* +*******************************************************************************/ + +void _CALLTYPE1 _ioinit ( + void + ) +{ + STARTUPINFO StartupInfo; + int cfi_len; + int fh; + DWORD htype; + + /* + * Process inherited file handle information, if any + */ + + GetStartupInfo( &StartupInfo ); + + if ( StartupInfo.cbReserved2 != 0 && StartupInfo.lpReserved2 != NULL ) { + /* + * Get the number of handles inherited. + */ + memcpy( &cfi_len, + StartupInfo.lpReserved2, + sizeof( int ) + ); + /* + * Now, get one byte of info (_osfile[] entry) for each + * inherited handle. Be careful not to overflow the _osfile[] + * array. + */ + memcpy( _osfile, + StartupInfo.lpReserved2 + sizeof( int ), + __min(_NHANDLE_, cfi_len) * sizeof( char ) + ); + /* + * Finally, copy each each inherited handle into _osfhnd[]. + * Be careful not to overflow _osfile[]. + */ + memcpy( _osfhnd, + StartupInfo.lpReserved2 + sizeof( int ) + + (cfi_len * sizeof( char )), + __min(_NHANDLE_, cfi_len) * sizeof( long ) + ); + } + + /* + * If handles for standard input, output and error were not inherited, + * try to obtain them directly from the OS. Also, set appropriate bits + * in _osfile[0], _osfile[1] and _osfile[2]. + */ + + for ( fh = 0 ; fh <= 2 ; ++fh ) { + + if ( _osfhnd[fh] == (long)INVALID_HANDLE_VALUE ) { + if ( (_osfhnd[fh] = (long)GetStdHandle( stdhndl(fh) )) + != (long)INVALID_HANDLE_VALUE ) { + /* + * mark the stream as open in text mode. + * determine if it isa char device or pipe. + */ + _osfile[fh] = (char)(FOPEN | FTEXT); + htype = GetFileType( (HANDLE)_osfhnd[fh] ); + if ( (htype & 0xFF) == FILE_TYPE_CHAR ) + _osfile[fh] |= FDEV; + else if ( (htype & 0xFF) == FILE_TYPE_PIPE ) + _osfile[fh] |= FPIPE; + } + } + else + /* + * handle was passed to us by parent process. make + * sure it is text mode. + */ + _osfile[fh] |= FTEXT; + } + + +} diff --git a/private/crt32/lowio/isatty.c b/private/crt32/lowio/isatty.c new file mode 100644 index 000000000..9bb931d18 --- /dev/null +++ b/private/crt32/lowio/isatty.c @@ -0,0 +1,62 @@ +/*** +*isatty.c - check if file handle refers to a device +* +* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _isatty() - check if file handle refers to a device +* +*Revision History: +* 06-08-89 PHG Module created +* 03-12-90 GJF Made calling type _CALLTYPE1, added #include +* <cruntime.h> and fixed the copyright. Also, cleaned +* up the formatting a bit. +* 08-14-90 SBM Compiles cleanly with -W3, minor optimization +* 09-28-90 GJF New-style function declarator. +* 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s. +* It's not worth it to try to merge the versions more +* closely. +* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo +* 01-16-91 GJF ANSI naming. +* 02-13-92 GJF Replaced _nfile by _nhandle for Win32. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <msdos.h> +#include <internal.h> +#include <io.h> + +/*** +*int _isatty(handle) - check if handle is a device +* +*Purpose: +* Checks if the given handle is associated with a character device +* (terminal, console, printer, serial port) +* +*Entry: +* int handle - handle of file to be tested +* +*Exit: +* returns non-0 if handle refers to character device, +* returns 0 otherwise +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _isatty ( + int fh + ) +{ + /* see if file handle is valid, otherwise return FALSE */ +#ifdef _WIN32_ + if ( (unsigned)fh >= (unsigned)_nhandle ) +#else + if ((unsigned)fh >= (unsigned)_nfile) +#endif + return 0; + + /* check file handle database to see if device bit set */ + return (int)(_osfile[fh] & FDEV); +} diff --git a/private/crt32/lowio/locking.c b/private/crt32/lowio/locking.c new file mode 100644 index 000000000..8eca84b29 --- /dev/null +++ b/private/crt32/lowio/locking.c @@ -0,0 +1,187 @@ +/*** +*locking.c - OS/2 file locking function +* +* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Defined the _locking() function - file locking and unlocking +* +*Revision History: +* 06-09-89 PHG Module created, based on asm version +* 08-10-89 JCR Changed DOS32FILELOCKS to DOS32SETFILELOCKS +* 03-12-90 GJF Made calling type _CALLTYPE2 (for now), added #include +* <cruntime.h> and fixed the copyright. Also, cleaned up +* the formatting a bit. +* 04-03-90 GJF Now _CALLTYPE1. +* 07-24-90 SBM Removed '32' from API names +* 08-14-90 SBM Compiles cleanly with -W3 +* 09-28-90 GJF New-style function declarator. +* 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s. +* It is enough different that there is little point in +* trying to more closely merge the two versions. +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo +* 01-16-91 GJF ANSI naming. +* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_] +* 12-05-91 GJF Fixed usage of [Un]LockFile APIs [_WIN32_]. +* 02-13-92 GJF Replaced _nfile by _nhandle for Win32. +* 05-06-92 SRW WIN32 LockFile API changed. [_WIN32_]. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <errno.h> +#include <sys\locking.h> +#include <io.h> +#include <stdlib.h> +#include <internal.h> +#include <os2dll.h> + +/*** +*int _locking(fh,lmode,nbytes) - file record locking function +* +*Purpose: +* Locks or unlocks nbytes of a specified file +* +* Multi-thread - Must lock/unlock the file handle to prevent +* other threads from working on the file at the same time as us. +* [NOTE: We do NOT release the lock during the 1 second delays +* since some other thread could get in and do something to the +* file. The DOSFILELOCK call locks out other processes, not +* threads, so there is no multi-thread deadlock at the DOS file +* locking level.] +* +*Entry: +* int fh - file handle +* int lmode - locking mode: +* _LK_LOCK/_LK_RLCK -> lock, retry 10 times +* _LK_NBLCK/_LK_N_BRLCK -> lock, don't retry +* _LK_UNLCK -> unlock +* long nbytes - number of bytes to lock/unlock +* +*Exit: +* returns 0 if successful +* returns -1 and sets errno if unsuccessful +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _locking ( + int fh, + int lmode, + long nbytes + ) +{ + ULONG dosretval; /* OS/2 return code */ + LONG lockoffset; + int retry; /* retry count */ + + /* validate file handle */ +#ifdef _WIN32_ + if ( (unsigned)fh >= (unsigned)_nhandle ) { +#else + if ((unsigned)fh >= (unsigned)_nfile) { +#endif + /* fh out of range */ + errno = EBADF; + _doserrno = 0; /* not an OS/2 error */ + return -1; + } + + _lock_fh(fh); /* acquire file handle lock */ + + /* obtain current position in file by calling _lseek */ + /* Use _lseek_lk as we already own lock */ + lockoffset = _lseek_lk(fh, 0L, 1); + if (lockoffset == -1) { + _unlock_fh(fh); + return -1; + } + + + /* set retry count based on mode */ + if (lmode == _LK_LOCK || lmode == _LK_RLCK) + retry = 9; /* retry 9 times */ + else + retry = 0; /* don't retry */ + + /* ask OS/2 to lock the file until success or retry count finished */ + /* note that the only error possible is a locking violation, since */ + /* an invalid handle would have already failed above */ + for (;;) { +#ifdef _CRUISER_ + FILELOCK filelock; /* OS/2 file locking structure */ + + filelock.lOffset = lockoffset; + filelock.lRange = nbytes; + + if (lmode == _LK_UNLCK) + dosretval = DOSSETFILELOCKS(fh, &filelock, NULL); + else + dosretval = DOSSETFILELOCKS(fh, NULL, &filelock); + + if (retry <= 0 || dosretval == 0) + break; /* exit loop on success or retry exhausted */ + + DOSSLEEP(1000); /* wait 1 sec until try again */ + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + dosretval = 0; + if (lmode == _LK_UNLCK) { + if ( !(UnlockFile((HANDLE)_get_osfhandle(fh), + lockoffset, + 0L, + nbytes, + 0L)) + ) + dosretval = GetLastError(); + + } else { + if ( !(LockFile((HANDLE)_get_osfhandle(fh), + lockoffset, + 0L, + nbytes, + 0L)) + ) + dosretval = GetLastError(); + } + + if (retry <= 0 || dosretval == 0) + break; /* exit loop on success or retry exhausted */ + + Sleep(1000L); + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + --retry; + } + + _unlock_fh(fh); /* release the file handle lock */ + + if (dosretval != 0) { + /* OS/2 error occurred -- file was already locked; if a + blocking call, then return EDEADLOCK, otherwise map + error normally */ + if (lmode == _LK_LOCK || lmode == _LK_RLCK) { + errno = EDEADLOCK; + _doserrno = dosretval; + } + else { + _dosmaperr(dosretval); + } + return -1; + } + else + return 0; +} diff --git a/private/crt32/lowio/lseek.c b/private/crt32/lowio/lseek.c new file mode 100644 index 000000000..bf3524e5f --- /dev/null +++ b/private/crt32/lowio/lseek.c @@ -0,0 +1,187 @@ +/*** +*lseek.c - OS/2 change file position +* +* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _lseek() - move the file pointer +* +*Revision History: +* 06-20-89 PHG Module created, based on asm version +* 03-12-90 GJF Made calling type _CALLTYPE2 (for now), added #include +* <cruntime.h> and fixed the copyright. Also, cleaned up +* the formatting a bit. +* 04-03-90 GJF Now _CALLTYPE1. +* 07-24-90 SBM Removed '32' from API names +* 08-14-90 SBM Compiles cleanly with -W3 +* 09-28-90 GJF New-style function declarators. +* 12-04-90 GJF Appended Win32 version with #ifdef-s. It's probably +* worth coming back and doing a more complete merge later +* (much later). +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo +* 01-16-91 GJF ANSI naming. +* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_] +* 04-09-91 PNT Added _MAC_ conditional +* 02-13-92 GJF Replaced _nfile by _nhandle for Win32. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <os2dll.h> +#include <io.h> +#include <internal.h> +#include <stdlib.h> +#include <errno.h> +#include <msdos.h> +#include <stdio.h> + +/*** +*long _lseek(fh,pos,mthd) - move the file pointer +* +*Purpose: +* Moves the file pointer associated with fh to a new position. +* The new position is pos bytes (pos may be negative) away +* from the origin specified by mthd. +* +* If mthd == SEEK_SET, the origin in the beginning of file +* If mthd == SEEK_CUR, the origin is the current file pointer position +* If mthd == SEEK_END, the origin is the end of the file +* +* Multi-thread: +* _lseek() = locks/unlocks the file +* _lseek_lk() = does NOT lock/unlock the file (it is assumed that +* the caller has the aquired the file lock,if needed). +* +*Entry: +* int fh - file handle to move file pointer on +* long pos - position to move to, relative to origin +* int mthd - specifies the origin pos is relative to (see above) +* +*Exit: +* returns the offset, in bytes, of the new position from the beginning +* of the file. +* returns -1L (and sets errno) if fails. +* Note that seeking beyond the end of the file is not an error. +* (although seeking before the beginning is.) +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef MTHREAD + +/* define locking/validating lseek */ +long _CALLTYPE1 _lseek ( + int fh, + long pos, + int mthd + ) +{ + int r; + + /* validate fh */ +#ifdef _WIN32_ + if ( (unsigned)fh >= (unsigned)_nhandle ) { +#else + if ((unsigned)fh >= (unsigned)_nfile) { +#endif + /* bad file handle */ + errno = EBADF; + _doserrno = 0; /* not OS/2 error */ + return -1; + } + + _lock_fh(fh); /* lock file handle */ + r = _lseek_lk(fh, pos, mthd); /* seek */ + _unlock_fh(fh); /* unlock file handle */ + + return r; +} + +/* define core _lseek -- doesn't lock or validate fh */ +long _CALLTYPE1 _lseek_lk ( + int fh, + long pos, + int mthd + ) +{ + ULONG newpos; /* new file position */ + ULONG dosretval; /* OS/2 return value */ + +#else + +/* define normal _lseek */ +long _CALLTYPE1 _lseek ( + int fh, + long pos, + int mthd + ) +{ + ULONG newpos; /* new file position */ + ULONG dosretval; /* OS/2 return value */ + + /* validate fh */ +#ifdef _WIN32_ + if ( (unsigned)fh >= (unsigned)_nhandle ) { +#else + if ((unsigned)fh >= (unsigned)_nfile) { +#endif + /* bad file handle */ + errno = EBADF; + _doserrno = 0; /* not OS/2 error */ + return -1; + } + +#endif + + /* tell OS/2 to seek */ + +#ifdef _CRUISER_ + +#if SEEK_SET != FILE_BEGIN || SEEK_CUR != FILE_CURRENT || SEEK_END != FILE_END + #error Xenix and OS/2 seek constants not compatible +#endif + + dosretval = DOSSETFILEPTR(fh, pos, mthd, &newpos); + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + +#if SEEK_SET != FILE_BEGIN || SEEK_CUR != FILE_CURRENT || SEEK_END != FILE_END + #error Xenix and Win32 seek constants not compatible +#endif + + if ((newpos = SetFilePointer((HANDLE)_get_osfhandle(fh), + pos, NULL, mthd)) == -1) + dosretval = GetLastError(); + else + dosretval = 0; + +#else /* ndef _WIN32_ */ + +#ifdef _MAC_ + + TBD(); + +#else /* ndef _MAC_ */ + +#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED! + +#endif /* _MAC_ */ + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + if (dosretval) { + /* OS/2 error */ + _dosmaperr(dosretval); + return -1; + } + + _osfile[fh] &= ~FEOFLAG; /* clear the ctrl-z flag on the file */ + return newpos; /* return */ +} diff --git a/private/crt32/lowio/makefile b/private/crt32/lowio/makefile new file mode 100644 index 000000000..6ee4f43fa --- /dev/null +++ b/private/crt32/lowio/makefile @@ -0,0 +1,6 @@ +# +# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source +# file to this component. This file merely indirects to the real make file +# that is shared by all the components of NT OS/2 +# +!INCLUDE $(NTMAKEENV)\makefile.def diff --git a/private/crt32/lowio/mktemp.c b/private/crt32/lowio/mktemp.c new file mode 100644 index 000000000..a4d827ecf --- /dev/null +++ b/private/crt32/lowio/mktemp.c @@ -0,0 +1,115 @@ +/*** +*mktemp.c - create a unique file name +* +* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _mktemp() - create a unique file name +* +*Revision History: +* 06-02-86 JMB eliminated unneccesary routine exits +* 05-26-87 JCR fixed bug where mktemp was incorrectly modifying +* the errno value. +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 07-11-88 JCR Optimized REG allocation +* 03-12-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* <cruntime.h>, removed #include <register.h> and +* fixed the copyright. Also, cleaned up the formatting +* a bit. +* 04-04-90 GJF Added #include <process.h> and #include <io.h>. Removed +* #include <sizeptr.h>. +* 07-23-90 SBM Replaced <assertm.h> by <assert.h> +* 08-13-90 SBM Compiles cleanly with -W3 +* 09-28-90 GJF New-style function declarator. +* 01-16-91 GJF ANSI naming. +* 11-30-92 KRS Ported _MBCS code from 16-bit tree. +* 06-18-93 KRS MBCS-only bug fix ported from 16-bit tree. +* 08-03-93 KRS Call _ismbstrail instead of isdbcscode. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <stdio.h> +#include <io.h> +#include <process.h> +#include <errno.h> +#include <assert.h> +#include <stddef.h> +#ifdef _MBCS +#include <mbctype.h> +#include <mbdata.h> +#endif + +/*** +*char *_mktemp(template) - create a unique file name +* +*Purpose: +* given a template of the form "fnamXXXXXX", insert number on end +* of template, insert unique letter if needed until unique filename +* found or run out of letters +#ifdef OS2_COMMENT +* Note: this version can be used for both DOS 3 and OS/2 +#endif +* +*Entry: +* char *template - template of form "fnamXXXXXX" +* +*Exit: +* return pointer to modifed template +* returns NULL if template malformed or no more unique names +* +*Exceptions: +* +*******************************************************************************/ + +char * _CALLTYPE1 _mktemp ( + char *template + ) +{ + REG1 char *string = template; + REG3 unsigned number; + int letter = 'a'; + REG2 int xcount = 0; + int olderrno; + + assert(template != NULL); + assert(*template != '\0'); + + number = _getpid(); + + while (*string) + string++; + +#ifdef _MBCS + while ((--string>=template) && (!_ismbstrail(template,string)) + && (*string == 'X')) +#else + while (*--string == 'X') +#endif + { + xcount++; + *string = (char)((number % 10) + '0'); + number /= 10; + } + + if (*++string == '\0' || xcount != 6 ) + return(NULL); + + olderrno = errno; /* save current errno */ + errno = 0; /* make sure errno isn't EACCESS */ + + while ((_access(template,0) == 0) || (errno == EACCES)) + /* while file exists */ + { + errno = 0; + if (letter == 'z'+1) { + errno = olderrno; + return(NULL); + } + + *string = (char)letter++; + } + + errno = olderrno; + return(template); +} diff --git a/private/crt32/lowio/open.c b/private/crt32/lowio/open.c new file mode 100644 index 000000000..a365f4aac --- /dev/null +++ b/private/crt32/lowio/open.c @@ -0,0 +1,590 @@ +/*** +*open.c - file open +* +* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _open() and _sopen() - open or create a file +* +*Revision History: +* 06-13-89 PHG Module created, based on asm version +* 11-11-89 JCR Replaced DOS32QUERYFILEMODE with DOS32QUERYPATHINFO +* 03-13-90 GJF Made calling type _CALLTYPE2 (for now), added #include +* <cruntime.h>, fixed some compiler warnings and fixed +* copyright. Also, cleaned up the formatting a bit. +* 07-24-90 SBM Removed '32' from API names +* 08-14-90 SBM Compiles cleanly with -W3 +* 09-07-90 SBM Added stdarg code (inside #if 0..#endif) to make +* open and sopen match prototypes. Test and use this +* someday. +* 10-01-90 GJF New-style function declarators. +* 11-16-90 GJF Wrote version for Win32 API and appended it via an +* #ifdef. The Win32 version is similar to the old DOS +* version (though in C) and far different from either +* the Cruiser or OS/2 versions. +* 12-03-90 GJF Fixed a dozen or so minor errors in the Win32 version. +* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo +* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler +* 12-31-90 SRW Fixed spen to call CreateFile instead of OpenFile +* 01-16-91 GJF ANSI naming. +* 02-07-91 SRW Changed to call _get_osfhandle [_WIN32_] +* 02-19-91 SRW Adapt to OpenFile/CreateFile changes [_WIN32_] +* 02-25-91 SRW Renamed _get_free_osfhnd to be _alloc_osfhnd [_WIN32_] +* 04-09-91 PNT Added _MAC_ conditional +* 07-10-91 GJF Store fileflags into _osfile array before call to +* _lseek_lk (bug found by LarryO) [_WIN32_]. +* 01-02-92 GJF Fixed Win32 version (not Cruiser!) so that pmode is not +* referenced unless _O_CREAT has been specified. +* 02-04-92 GJF Make better use of CreateFile options. +* 04-06-92 SRW Pay attention to _O_NOINHERIT flag in oflag parameter +* 05-02-92 SRW Add support for _O_TEMPORARY flag in oflag parameter. +* Causes FILE_ATTRIBUTE_TEMPORARY flag to be set in call +* to the Win32 CreateFile API. +* 07-01-92 GJF Close handle in case of error. Also, don't try to set +* FRDONLY bit anymore - no longer needed/used. [_WIN32_]. +* 01-03-93 SRW Fix va_arg/va_end usage +* 05-24-93 PML Add support for _O_SEQUENTIAL, _O_RANDOM, +* and _O_SHORT_LIVED +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <msdos.h> +#include <errno.h> +#include <fcntl.h> +#include <internal.h> +#include <io.h> +#include <share.h> +#include <stdlib.h> +#include <sys\types.h> +#include <sys\stat.h> +#include <os2dll.h> +#include <stdarg.h> + +/*** +*int _open(path, flag, pmode) - open or create a file +* +*Purpose: +* Opens the file and prepares for subsequent reading or writing. +* the flag argument specifies how to open the file: +* _O_APPEND - reposition file ptr to end before every write +* _O_BINARY - open in binary mode +* _O_CREAT - create a new file* no effect if file already exists +* _O_EXCL - return error if file exists, only use with O_CREAT +* _O_RDONLY - open for reading only +* _O_RDWR - open for reading and writing +* _O_TEXT - open in text mode +* _O_TRUNC - open and truncate to 0 length (must have write permission) +* _O_WRONLY - open for writing only +* _O_NOINHERIT -handle will not be inherited by child processes. +* exactly one of _O_RDONLY, _O_WRONLY, _O_RDWR must be given +* +* The pmode argument is only required when _O_CREAT is specified. Its +* flag settings: +* _S_IWRITE - writing permitted +* _S_IREAD - reading permitted +* _S_IREAD | _S_IWRITE - both reading and writing permitted +* The current file-permission maks is applied to pmode before +* setting the permission (see umask). +* +* The oflag and mode parameter have different meanings under DOS. See +* the A_xxx attributes in msdos.inc +* +* Note, the _creat() function also uses this function but setting up the +* correct arguments and calling _open(). _creat() sets the __creat_flag +* to 1 prior to calling _open() so _open() can return correctly. _open() +* returns the file handle in eax in this case. +* +*Entry: +* char *path - file name +* int flag - flags for _open() +* int pmode - permission mode for new files +* +*Exit: +* returns file handle of open file if successful +* returns -1 (and sets errno) if fails +* +*Exceptions: +* +*******************************************************************************/ + +int _CRTAPI2 _open ( + const char *path, + int oflag, + ... + ) +{ + va_list ap; + int pmode; + + va_start(ap, oflag); + pmode = va_arg(ap, int); + va_end(ap); + + /* default sharing mode is DENY NONE */ + return _sopen(path, oflag, _SH_DENYNO, pmode); +} + +/*** +*int _sopen(path, oflag, shflag, pmode) - opne a file with sharing +* +*Purpose: +* Opens the file with possible file sharing. +* shflag defines the sharing flags: +* _SH_COMPAT - set compatability mode +* _SH_DENYRW - deny read and write access to the file +* _SH_DENYWR - deny write access to the file +* _SH_DENYRD - deny read access to the file +* _SH_DENYNO - permit read and write access +* +* Other flags are the same as _open(). +* +* SOPEN is the routine used when file sharing is desired. +* +*Entry: +* char *path - file to open +* int oflag - open flag +* int shflag - sharing flag +* int pmode - permission mode (needed only when creating file) +* +*Exit: +* returns file handle for the opened file +* returns -1 and sets errno if fails. +* +*Exceptions: +* +*******************************************************************************/ + +int _CRTAPI2 _sopen ( + const char *path, + int oflag, + int shflag, + ... + ) +{ + + int fh; /* handle of opened file */ + int filepos; /* length of file - 1 */ + char ch; /* character at end of file */ + char fileflags; /* _osfile flags */ + va_list ap; /* variable argument (pmode) */ + int pmode; + +#ifdef _CRUISER_ + int t; /* temp */ + int dosretval; /* OS/2 return value */ + int isdev; /* device indicator in low byte */ + int attrib; /* attribute */ + int openflag; /* OS/2 open flag */ + int openmode; /* OS/2 open mode */ +#endif /* _CRUISER_ */ + +#ifdef _WIN32_ + HANDLE osfh; /* OS handle of opened file */ + DWORD fileaccess; /* OS file access (requested) */ + DWORD fileshare; /* OS file sharing mode */ + DWORD filecreate; /* OS method of opening/creating */ + DWORD fileattrib; /* OS file attribute flags */ + DWORD isdev; /* device indicator in low byte */ + SECURITY_ATTRIBUTES SecurityAttributes; + + SecurityAttributes.nLength = sizeof( SecurityAttributes ); + SecurityAttributes.lpSecurityDescriptor = NULL; + if (oflag & _O_NOINHERIT) { + SecurityAttributes.bInheritHandle = FALSE; + } + else { + SecurityAttributes.bInheritHandle = TRUE; + } + +#endif /* _WIN32_ */ +#ifdef _CRUISER_ +/* Set up variable argument list stuff */ + + va_start(ap, shflag); + pmode = va_arg(ap, int); + va_end(ap); +#endif + + /* figure out binary/text mode */ + if (oflag & _O_BINARY) + fileflags = 0; + else if (oflag & _O_TEXT) + fileflags = (char)FTEXT; + else if (_fmode == _O_BINARY) /* check default mode */ + fileflags = 0; + else + fileflags = (char)FTEXT; + +#ifdef _CRUISER_ /* CRUISER TARGET */ + +/* code requires below conditions */ +#if _O_RDONLY != OPEN_ACCESS_READONLY || _O_WRONLY != OPEN_ACCESS_WRITEONLY || _O_RDWR != OPEN_ACCESS_READWRITE + #error OS/2 and XENIX flags not compatible +#endif +#if _O_RDWR != 2 || _O_RDONLY != 0 || _O_WRONLY != 1 + #error access flags are wrong +#endif + +/* + Set up the OpenMode and OpenFlag parameters for the DOSOPEN call + + OpenMode fields will be set as follows: + high byte + DASD 0 (normal file) + File Write-through 0 (use buffer cache) + Fail-Errors 0 (use hard error handler) + low byte + Inheritance 0 (child inherits files) + Sharing Mode <from shflag param> + Access Mode <from oflag parameter> + + OpenFlag bytes are set as follows: + high byte + 0x00 + low byte - low nibble + 0x0 _O_EXCL specified + 0x2 _O_TRUNC specified + 0x1 otherwise + low byte - high nibble + 0x1 _O_CREAT specified + 0x0 otherwise +*/ + + + /* first, convert the permission mode to the DOS attribute byte */ + if ((pmode & ~_umaskval) & _S_IWRITE) + attrib = 0; /* writable */ + else + attrib = FILE_READONLY; /* read-only */ + + if ((oflag & _O_EXCL) && !(oflag & _O_CREAT)) + oflag &= ~_O_EXCL; /* _O_EXCL only works with _O_CREAT */ + + if (oflag & _O_EXCL) { + openflag = 0; /* just create */ + } + else if (oflag & _O_TRUNC) { + FILESTATUS fs; /* File Status structure */ + + openflag = FILE_TRUNCATE; /* truncate file */ + + /* if the file exists, don't change its attribute */ + if (!DOSQUERYPATHINFO((char *)path, 1, &fs, sizeof(fs))) + /* file exists, use current attribute */ + attrib = fs.attrFile; + } + else + openflag = FILE_OPEN; /* open the file */ + + if (oflag & _O_CREAT) + openflag |= FILE_CREATE; + + /* here we take advantage of the fact that OS/2 and XENIX access flags + are the same bits -- the bottom two */ + openmode = shflag | (oflag & 3); + + /* OK, we're now ready to open the file */ + if (dosretval = DOSOPEN((char *)path, &fh, &t, 0, attrib, openflag, + openmode, 0, 0)) { + /* OS/2 error occured */ + if (dosretval == ERROR_OPEN_FAILED) { + _doserrno = dosretval; + if (openflag & FILE_CREATE) + errno = EEXIST; /* file existed */ + else + errno = ENOENT; /* file didn't exist */ + return -1; + } + else { + _dosmaperr(dosretval); /* map error */ + return -1; + } + } + + if ((unsigned)fh >= (unsigned)_nfile) { + /* handle is out of range; close and return EMFILE */ + DOSCLOSE(fh); + errno = EMFILE; + _doserrno = 0; /* not OS/2 error */ + return -1; + } + + _lock_fh(fh); /* lock the file handle */ + + /* find out what type of file (file/device/pipe) */ + if (dosretval = DOSQUERYHTYPE(fh, &isdev, &t)) { + /* OS/2 error */ + _unlock_fh(fh); + _dosmaperr(dosretval); /* map error */ + return -1; + } + + /* is isdev value to set flags */ + if ((isdev & 0xFF) == HANDTYPE_DEVICE) + fileflags |= FDEV; + else if ((isdev & 0xFF) == HANDTYPE_PIPE) + fileflags |= FPIPE; + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + /* + * decode the access flags + */ + switch( oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR) ) { + + case _O_RDONLY: /* read access */ + fileaccess = GENERIC_READ; + break; + case _O_WRONLY: /* write access */ + fileaccess = GENERIC_WRITE; + break; + case _O_RDWR: /* read and write access */ + fileaccess = GENERIC_READ | GENERIC_WRITE; + break; + default: /* error, bad oflag */ + errno = EINVAL; + _doserrno = 0L; /* not an OS error */ + return -1; + } + + /* + * decode sharing flags + */ + switch ( shflag ) { + + case _SH_DENYRW: /* exclusive access */ + fileshare = 0L; + break; + + case _SH_DENYWR: /* share read access */ + fileshare = FILE_SHARE_READ; + break; + + case _SH_DENYRD: /* share write access */ + fileshare = FILE_SHARE_WRITE; + break; + + case _SH_DENYNO: /* share read and write access */ + fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE; + break; + + default: /* error, bad shflag */ + errno = EINVAL; + _doserrno = 0L; /* not an OS error */ + return -1; + } + + /* + * decode open/create method flags + */ + switch ( oflag & (_O_CREAT | _O_EXCL | _O_TRUNC) ) { + case 0: + filecreate = OPEN_EXISTING; + break; + + case _O_CREAT: + filecreate = OPEN_ALWAYS; + break; + + case _O_CREAT | _O_EXCL: + filecreate = CREATE_NEW; + break; + + case _O_TRUNC: + filecreate = TRUNCATE_EXISTING; + break; + + case _O_CREAT | _O_TRUNC: + filecreate = CREATE_ALWAYS; + break; + + default: + errno = EINVAL; + _doserrno = 0L; + return -1; + } + + /* + * decode file attribute flags if _O_CREAT was specified + */ + fileattrib = FILE_ATTRIBUTE_NORMAL; /* default */ + + if ( oflag & _O_CREAT ) { + /* + * set up variable argument list stuff + */ + va_start(ap, shflag); + pmode = va_arg(ap, int); + va_end(ap); + + if ( !((pmode & ~_umaskval) & _S_IWRITE) ) + fileattrib = FILE_ATTRIBUTE_READONLY; + } + + /* + * Set temporary file (delete-on-close) attribute if requested. + */ + if ( oflag & _O_TEMPORARY ) { + fileattrib |= FILE_FLAG_DELETE_ON_CLOSE; + fileaccess |= DELETE; + } + + /* + * Set temporary file (delay-flush-to-disk) attribute if requested. + */ + if ( oflag & _O_SHORT_LIVED ) + fileattrib |= FILE_ATTRIBUTE_TEMPORARY; + + /* + * Set sequential or random access attribute if requested. + */ + if ( oflag & _O_SEQUENTIAL ) + fileattrib |= FILE_FLAG_SEQUENTIAL_SCAN; + else if ( oflag & _O_RANDOM ) + fileattrib |= FILE_FLAG_RANDOM_ACCESS; + + /* + * get an available handle. + * + * multi-thread note: the returned handle is locked! + */ + if ( (fh = _alloc_osfhnd()) == -1 ) { + errno = EMFILE; /* too many open files */ + _doserrno = 0L; /* not an OS error */ + return -1; /* return error to caller */ + } + + /* + * try to open/create the file + */ + if ( (osfh = CreateFile((LPSTR)path, + fileaccess, + fileshare, + &SecurityAttributes, + filecreate, + fileattrib, + NULL + )) + == (HANDLE)0xffffffff ) { + /* + * OS call to open/create file failed! map the error, release + * the lock, and return -1. note that it's not necessary to + * call _free_osfhnd (it hasn't been used yet). + */ + _dosmaperr(GetLastError()); /* map error */ + _unlock_fh(fh); + return -1; /* return error to caller */ + } + + /* find out what type of file (file/device/pipe) */ + if ( (isdev = GetFileType(osfh)) == FILE_TYPE_UNKNOWN ) { + CloseHandle(osfh); + _dosmaperr(GetLastError()); /* map error */ + _unlock_fh(fh); + return -1; + } + + /* is isdev value to set flags */ + if (isdev == FILE_TYPE_CHAR) + fileflags |= FDEV; + else if (isdev == FILE_TYPE_PIPE) + fileflags |= FPIPE; + + /* + * the file is open. now, set the info in _osfhnd array + */ + _set_osfhnd(fh, (long)osfh); + +#else /* ndef _WIN32_ */ + +#ifdef _MAC_ + + TBD(); + +#else /* ndef _MAC_ */ + +#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED! + +#endif /* _MAC_ */ + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + /* + * mark the handle as open. store flags gathered so far in _osfile + * array. + */ + fileflags |= FOPEN; + _osfile[fh] = fileflags; + + if (!(fileflags & (FDEV|FPIPE)) && (fileflags & FTEXT) && + (oflag & _O_RDWR)) { + /* We have a text mode file. If it ends in CTRL-Z, we wish to + remove the CTRL-Z character, so that appending will work. + We do this by seeking to the end of file, reading the last + byte, and shortening the file if it is a CTRL-Z. */ + + if ((filepos = _lseek_lk(fh, -1, FILE_END)) == -1) { + /* OS error -- should ignore negative seek error, + since that means we had a zero-length file. */ + if (_doserrno != ERROR_NEGATIVE_SEEK) { + _close(fh); + _unlock_fh(fh); + return -1; + } + } + else { + /* seek was OK, read the last char in file */ + if (_read_lk(fh, &ch, 1) == 1 && ch == 26) { + /* read was OK and we got CTRL-Z! Wipe it + out! */ + if (_chsize_lk(fh,filepos) == -1) + { + _close(fh); + _unlock_fh(fh); + return -1; + } + } + + /* now rewind the file to the beginning */ + if ((filepos = _lseek_lk(fh, 0, FILE_BEGIN)) == -1) { + _close(fh); + _unlock_fh(fh); + return -1; + } + } + } + +#ifdef _CRUISER_ + /* We want to know if we have write access to set the FRDONLY flag + in the _osfile entry. We also set the FAPPEND flag. + Don't do this for pipes or devices. */ + + if (!(fileflags & (FDEV|FPIPE))) { + if (_access((char *)path, 2) == -1) + _osfile[fh] |= FRDONLY; + + if (oflag & _O_APPEND) + _osfile[fh] |= FAPPEND; + } +#else /* ndef _CRUISER_ */ +#ifdef _WIN32_ + + /* + * Set FAPPEND flag if appropriate. Don't do this for devices or pipes. + */ + if ( !(fileflags & (FDEV|FPIPE)) && (oflag & _O_APPEND) ) + _osfile[fh] |= FAPPEND; + +#endif /* _WIN32_ */ +#endif /* _CRUISER_*/ + + _unlock_fh(fh); /* unlock handle */ + + return fh; /* return handle */ +} diff --git a/private/crt32/lowio/osfinfo.c b/private/crt32/lowio/osfinfo.c new file mode 100644 index 000000000..8ccff39c4 --- /dev/null +++ b/private/crt32/lowio/osfinfo.c @@ -0,0 +1,319 @@ +/*** +*osfinfo.c - Win32 _osfhnd[] support routines +* +* Copyright (c) 1990-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Defines the internally used routine _alloc_osfhnd() +* and the user visible routine _get_osfhandle(). +* +*Revision History: +* 11-16-90 GJF What can I say? The custom heap business was getting +* a little slow... +* 12-03-90 GJF Fixed my stupid syntax errors. +* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo +* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler +* 02-18-91 SRW Fixed bug in _alloc_osfhnd with setting FOPEN bit +* (only caller should do that) [_WIN32_] +* 02-18-91 SRW Fixed bug in _alloc_osfhnd with checking against +* _NFILE_ instead of _nfile [_WIN32_] +* 02-18-91 SRW Added debug output to _alloc_osfhnd if out of +* file handles. [_WIN32_] +* 02-25-91 SRW Renamed _get_free_osfhnd to be _alloc_osfhnd [_WIN32_] +* 02-25-91 SRW Exposed _get_osfhandle and _open_osfhandle [_WIN32_] +* 08-08-91 GJF Use ANSI-fied form of constant names. +* 11-25-91 GJF Lock fh before checking whether it's free. +* 12-31-91 GJF Improved multi-thread lock usage [_WIN32_]. +* 02-13-92 GJF Replaced _nfile with _nhandle +* 07-15-92 GJF Fixed setting of flags in _open_osfhnd. +* 02-19-93 GJF If GetFileType fails in _open_osfhandle, don't unlock +* fh (it wasn't locked)! +* +*******************************************************************************/ + +#ifdef _WIN32_ + +#include <cruntime.h> +#include <errno.h> +#include <internal.h> +#include <fcntl.h> +#include <msdos.h> +#include <os2dll.h> +#include <stdlib.h> +#include <oscalls.h> + +/*** +*int _alloc_osfhnd() - get free _osfhnd[] entry +* +*Purpose: +* Finds the first free entry in _osfhnd[], mark it in use and return +* the index of the entry to the caller. +* +*Entry: +* none +* +*Exit: +* returns index of entry in fh, if successful +* return -1, if no free entry is found in _osfhnd[]. +* +* MULTITHREAD NOTE: IF SUCCESSFUL, THE HANDLE IS LOCKED WHEN IT IS +* RETURNED TO THE CALLER! +* +*Exceptions: +* +*******************************************************************************/ + +int _CRTAPI1 _alloc_osfhnd( + void + ) +{ + int fh; /* _osfhnd[] index */ + + _mlock(_OSFHND_LOCK); /* lock the _osfhnd[] table */ + + /* + * search _osfhnd[] for an entry that is not currently being used. + * if one is found, mark it in use and set the _osfhandle field to + * INVALID_HANDLE_VALUE. + */ + for ( fh = 0 ; fh < _nhandle ; fh++ ) { + if ( (_osfile[fh] & FOPEN) == 0 ) { +#ifdef MTHREAD + _lock_fh(fh); + + /* + * make sure the entry is still free + */ + if ( (_osfile[fh] & FOPEN) != 0 ) { + /* + * entry now in use! release the lock and + * continue looping. + */ + _unlock_fh(fh); + continue; + } +#endif + + /* + * free entry found! initialize it and + * break out of the loop + */ + _osfhnd[fh] = (long)INVALID_HANDLE_VALUE; + break; + } + } + + _munlock(_OSFHND_LOCK); /* unlock the _osfhnd[] table */ + +#if defined(DEBUG) && defined(_WIN32_) + if (fh >= _nhandle) { + DbgPrint( "WINCRT: more than %d open files\n", _nhandle ); + } +#endif + + /* + * return the index of the previously free table entry, if one was + * found. return -1 otherwise. + */ + return( (fh >= _nhandle) ? -1 : fh ); +} + + +/*** +*int _set_osfhnd(int fh) - set OS file handle table value +* +*Purpose: +* If fh is in range and if _osfhnd[fh] is marked with +* INVALID_HANDLE_VALUE then set _osfhnd[fh] to the passed value. +* +*Entry: +* int fh - index of _osfhnd[] entry +* long fh - new value of this handle entry +* +*Exit: +* Returns zero if successful. +* Returns -1 and sets errno to EBADF otherwise. +* +*Exceptions: +* +*******************************************************************************/ + +int _CRTAPI1 _set_osfhnd ( + int fh, /* index into _osfhnd[] (user's file handle) */ + long value + ) +{ + if ( ((unsigned)fh < (unsigned)_nhandle) && + (_osfhnd[fh] == (long)INVALID_HANDLE_VALUE) + ) { + switch (fh) { + case 0: SetStdHandle( STD_INPUT_HANDLE, (HANDLE)value ); break; + case 1: SetStdHandle( STD_OUTPUT_HANDLE, (HANDLE)value ); break; + case 2: SetStdHandle( STD_ERROR_HANDLE, (HANDLE)value ); break; + } + + _osfhnd[fh] = value; + return(0); + } else { + errno = EBADF; /* bad handle */ + _doserrno = 0L; /* not an OS error */ + return -1; + } +} + + +/*** +*int _free_osfhnd(int fh) - free OS file handle table entry +* +*Purpose: +* If fh is in range and if _osfhnd[fh] is in use and NOT marked +* with 0xfffffff +* +*Entry: +* int fh - index of _osfhnd[] entry +* +*Exit: +* Returns zero if successful. +* Returns -1 and sets errno to EBADF otherwise. +* +*Exceptions: +* +*******************************************************************************/ + +int _CRTAPI1 _free_osfhnd ( + int fh /* index into _osfhnd[] (user's file handle) */ + ) +{ + if ( ((unsigned)fh < (unsigned)_nhandle) && + (_osfile[fh] & FOPEN) && + (_osfhnd[fh] != (long)INVALID_HANDLE_VALUE) + ) { + switch (fh) { + case 0: SetStdHandle( STD_INPUT_HANDLE, NULL ); break; + case 1: SetStdHandle( STD_OUTPUT_HANDLE, NULL ); break; + case 2: SetStdHandle( STD_ERROR_HANDLE, NULL ); break; + } + + _osfhnd[fh] = (long)INVALID_HANDLE_VALUE; + return(0); + } else { + errno = EBADF; /* bad handle */ + _doserrno = 0L; /* not an OS error */ + return -1; + } +} + + +/*** +*long _get_osfhandle(int fh) - get OS file handle +* +*Purpose: +* If fh is in range and if _osfhnd[fh] is marked free, return +* _osfhnd[fh] +* +*Entry: +* int fh - index of _osfhnd[] entry +* +*Exit: +* Returns the OS file handle if successful. +* Returns -1 and sets errno to EBADF otherwise. +* +*Exceptions: +* +*******************************************************************************/ + +long _CRTAPI1 _get_osfhandle ( + int fh /* index into _osfhnd[] (user's file handle) */ + ) +{ + if ( ((unsigned)fh < (unsigned)_nhandle) && (_osfile[fh] & FOPEN) ) + return(_osfhnd[fh]); + else { + errno = EBADF; /* bad handle */ + _doserrno = 0L; /* not an OS error */ + return -1; + } +} + +/*** +*int _open_osfhandle(long osfhandle, int flags) - open C Runtime file handle +* +*Purpose: +* This function allocates a free C Runtime file handle and sets it +* to point to the Win32 file handle specified by the first parameter. +* +*Entry: +* long osfhandle -Win32 file handle to associate with C Runtime file handle. +* int flags - flags to associate with C Runtime file handle. +* +*Exit: +* returns index of entry in fh, if successful +* return -1, if no free entry is found in _osfhnd[]. +* +*Exceptions: +* +*******************************************************************************/ + +int _CRTAPI1 _open_osfhandle( + long osfhandle, + int flags + ) +{ + int fh; + char fileflags; /* _osfile flags */ + DWORD isdev; /* device indicator in low byte */ + + /* copy relevant flags from second parameter */ + + fileflags = 0; + + if ( flags & _O_APPEND ) + fileflags |= FAPPEND; + + if ( flags & _O_TEXT ) + fileflags |= FTEXT; + + /* find out what type of file (file/device/pipe) */ + + isdev = GetFileType((HANDLE)osfhandle); + if (isdev == FILE_TYPE_UNKNOWN) { + /* OS error */ + _dosmaperr( GetLastError() ); /* map error */ + return -1; + } + + /* is isdev value to set flags */ + if (isdev == FILE_TYPE_CHAR) + fileflags |= FDEV; + else if (isdev == FILE_TYPE_PIPE) + fileflags |= FPIPE; + + + /* attempt to allocate a C Runtime file handle */ + + if ( (fh = _alloc_osfhnd()) == -1 ) { + errno = EMFILE; /* too many open files */ + _doserrno = 0L; /* not an OS error */ + return -1; /* return error to caller */ + } + + /* + * the file is open. now, set the info in _osfhnd array + */ + + _set_osfhnd(fh, osfhandle); + + fileflags |= FOPEN; /* mark as open */ + + _osfile[fh] = fileflags; /* set osfile entry */ + + _unlock_fh(fh); /* unlock handle */ + + return fh; /* return handle */ +} + +#else + +#error ERROR - WIN32 TARGET ONLY! + +#endif diff --git a/private/crt32/lowio/pipe.c b/private/crt32/lowio/pipe.c new file mode 100644 index 000000000..a414d1c40 --- /dev/null +++ b/private/crt32/lowio/pipe.c @@ -0,0 +1,180 @@ +/*** +*pipe.c - create a pipe +* +* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _pipe() - creates a pipe (i.e., an I/O channel for interprocess +* communication) +* +*Revision History: +* 06-20-89 PHG Module created, based on asm version +* 03-13-90 GJF Made calling type _CALLTYPE2 (for now), added #include +* <cruntime.h> and fixed copyright. Also, cleaned up the +* formatting a bit. +* 04-03-90 GJF Now _CALLTYPE1. +* 07-24-90 SBM Removed '32' from API names +* 08-14-90 SBM Compiles cleanly with -W3 +* 10-01-90 GJF New-style function declarator. +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. +* 01-18-91 GJF ANSI naming. +* 02-18-91 SRW Added _WIN32_ implementation [_WIN32_] +* 02-25-91 SRW Renamed _get_free_osfhnd to be _alloc_osfhnd [_WIN32_] +* 03-13-91 SRW Fixed _pipe so it works [_WIN32_] +* 03-18-91 SRW Fixed _pipe NtCreatePipe handles are inherited [_WIN32_] +* 04-06-92 SRW Pay attention to _O_NOINHERIT flag in oflag parameter +* 01-10-93 GJF Fixed bug in checking for _O_BINARY (inadvertently +* introduced by SRW's change above). +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <os2dll.h> +#include <io.h> +#include <internal.h> +#include <stdlib.h> +#include <errno.h> +#include <msdos.h> +#include <fcntl.h> + +/*** +*int _pipe(phandles, psize, textmode) - open a pipe +* +*Purpose: +* Checks if the given handle is associated with a character device +* (terminal, console, printer, serial port) +* +* Multi-thread notes: No locking is performed or deemed necessary. The +* handles returned by DOSCREATEPIPE are newly opened and, therefore, +* should not be referenced by any thread until after the _pipe call is +* complete. The function is not protected from some thread of the caller +* doing, say, output to a previously invalid handle that becomes one of +* the pipe handles. However, any such program is doomed anyway and +* protecting the _pipe function such a case would be of little value. +* +*Entry: +* int phandle[2] - array to hold returned read (phandle[0]) and write +* (phandle[1]) handles +* +* unsigned psize - amount of memory, in bytes, to ask OS/2 to reserve +* for the pipe +* +* int textmode - _O_TEXT, _O_BINARY, _O_NOINHERIT, or 0 (use default) +* +*Exit: +* returns 0 if successful +* returns -1 if an error occurs in which case, errno is set to: +* +*Exceptions: +* +*******************************************************************************/ + +int _CRTAPI1 _pipe ( + int phandles[2], + unsigned psize, + int textmode + ) +{ + ULONG dosretval; /* OS/2 return value */ + +#ifdef _CRUISER_ + + if (dosretval = DOSCREATEPIPE(&phandles[0], &phandles[1], psize)) { + /* OS/2 error */ + _dosmaperr(dosretval); + return -1; + } + + if ((unsigned)phandles[0] >= (unsigned)_nfile || + (unsigned)phandles[1] >= (unsigned)_nfile) + { + /* one or both of the handles are too large -- close both */ + DOSCLOSE(phandles[0]); + DOSCLOSE(phandles[1]); + errno = EMFILE; /* too many files */ + _doserrno = 0; /* not an OS/2 error */ + return -1; + } + + /* now we must set the _osfile values */ + if (textmode == _O_BINARY || (textmode == 0 && _fmode == _O_BINARY)) { + /* binary mode */ + _osfile[phandles[0]] = _osfile[phandles[1]] = FOPEN | FPIPE; + } + else { + /* text mode */ + _osfile[phandles[0]] = _osfile[phandles[1]] = FOPEN | FPIPE | + FTEXT; + } + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + HANDLE ReadHandle, WriteHandle; + SECURITY_ATTRIBUTES SecurityAttributes; + + SecurityAttributes.nLength = sizeof(SecurityAttributes); + SecurityAttributes.lpSecurityDescriptor = NULL; + if (textmode & _O_NOINHERIT) { + SecurityAttributes.bInheritHandle = FALSE; + } + else { + SecurityAttributes.bInheritHandle = TRUE; + } + if (!CreatePipe(&ReadHandle, &WriteHandle, &SecurityAttributes, psize)) { + /* OS/2 error */ + dosretval = GetLastError(); + _dosmaperr(dosretval); + return -1; + } + + /* now we must allocate C Runtime handles for Read and Write handles */ + if ((phandles[0] = _alloc_osfhnd()) != -1) { + _osfile[phandles[0]] = (char)(FOPEN | FPIPE | FTEXT); + if ((phandles[1] = _alloc_osfhnd()) != -1) { + _osfile[phandles[1]] = (char)(FOPEN | FPIPE | FTEXT); + if ( (textmode & _O_BINARY) || + ((textmode & _O_TEXT == 0) && + (_fmode == _O_BINARY)) ) { + /* binary mode */ + _osfile[phandles[0]] &= ~FTEXT; + _osfile[phandles[1]] &= ~FTEXT; + } + + _set_osfhnd(phandles[0], (long)ReadHandle); + _set_osfhnd(phandles[1], (long)WriteHandle); + errno = 0; + + _unlock_fh(phandles[1]); /* unlock handle */ + } + else { + _osfile[phandles[0]] = 0; + errno = EMFILE; /* too many files */ + } + + _unlock_fh(phandles[0]); /* unlock handle */ + } + else { + errno = EMFILE; /* too many files */ + } + + /* If error occurred, close Win32 handles and return -1 */ + if (errno != 0) { + CloseHandle(ReadHandle); + CloseHandle(WriteHandle); + _doserrno = 0; /* not an OS/2 error */ + return -1; + } + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + return 0; +} diff --git a/private/crt32/lowio/ppc/cinitcon.s b/private/crt32/lowio/ppc/cinitcon.s new file mode 100644 index 000000000..5e5b71e6b --- /dev/null +++ b/private/crt32/lowio/ppc/cinitcon.s @@ -0,0 +1,53 @@ +// page ,132 +// title cinitcon - C Run-Time Startup Initialization for Console I/O +// +//cinitcon.asm - C Run-Time Startup Initialization for WIN32 +// +// Copyright (c) 1990-1992, Microsoft Corporation. All rights reserved. +// +//Purpose: +// Initialization and Termination for console I/O +// +//Notes: +// _confh and _coninpfh are defined in this module to force the +// inclusion of this module if any console I/O is performed. +// This module places the address of _initcon() in the initializer +// table and the address of _termcon() in the pre-terminator table. +// +//Revision History: +// 03-19-92 SKS Module created. +// 03-24-92 SKS Added MIPS support (NO_UNDERSCORE) +// 04-30-92 SKS Add "offset FLAT:" to get correct fixups for OMF objs +// 08-06-92 SKS Revised to use new section names and macros +// +// **************************************************************************** + +#include "kxppc.h" + + .extern _initcon + .extern _termcon + + +beginSection(XIC) + + .long _initcon + +endSection(XIC) + + +beginSection(XPX) + + .long _termcon + +endSection(XPX) + + + .data + .align 2 + + .globl _coninpfh + .globl _confh + +_coninpfh: .long -1 // console input +_confh: .long -1 // console output + diff --git a/private/crt32/lowio/putch.c b/private/crt32/lowio/putch.c new file mode 100644 index 000000000..addd0c6b2 --- /dev/null +++ b/private/crt32/lowio/putch.c @@ -0,0 +1,129 @@ +/*** +*putch.c - contains the _putch() routine for OS/2 Protected Mode +* +* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved +* +*Purpose: +* The routine "_putch()" writes a single character to the console. +* +* NOTE: In real-mode DOS the character is actually written to standard +* output, and is therefore redirected when standard output is redirected. +* However, in Protected-Mode OS/2 the character is ALWAYS written +* to the console, even when standard output has been redirected. +* +*Revision History: +* 06-08-89 PHG Module created, based on asm version +* 03-13-90 GJF Made calling type _CALLTYPE1, added #include +* <cruntime.h> and fixed copyright. Also, cleaned up +* the formatting a bit. +* 06-05-90 SBM Recoded as pure 32-bit, using new file handle state bits +* 07-24-90 SBM Removed '32' from API names +* 10-01-90 GJF New-style function declarators. +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Added _CRUISER_ and _WIN32 conditionals. +* 01-16-91 GJF ANSI naming. +* 02-19-91 SRW Adapt to OpenFile/CreateFile changes (_WIN32_) +* 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_) +* 07-26-91 GJF Took out init. stuff and cleaned up the error +* handling [_WIN32_]. +* 03-20-93 GJF Use WriteConsole instead of WriteFile. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <conio.h> +#include <os2dll.h> +#include <stdio.h> + +/* + * declaration for console handle + */ +extern int _confh; + +/*** +*int _putch(c) - write a character to the console +* +*Purpose: +* Calls DOSWRITE to output the character +* Note: in OS/2 protect mode always writes to console even +* when stdout redirected +* +*Entry: +* c - Character to be output +* +*Exit: +* If an error is returned from DOSWRITE +* Then returns EOF +* Otherwise +* returns character that was output +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef MTHREAD +/* normal version lock and unlock the console, and then call the _lk version + which directly accesses the console without locking. */ + +int _CRTAPI1 _putch ( + int c + ) +{ + int ch; + + _mlock(_CONIO_LOCK); /* secure the console lock */ + ch = _putch_lk(c); /* output the character */ + _munlock(_CONIO_LOCK); /* release the console lock */ + + return ch; +} +#endif /* MTHREAD */ + +/* define version which accesses the console directly - normal version in + non-MTHREAD situations, special _lk version in MTHREAD */ + +#ifdef MTHREAD +int _CRTAPI1 _putch_lk ( +#else +int _CRTAPI1 _putch ( +#endif + int c + ) +{ + /* can't use ch directly unless sure we have a big-endian machine */ + unsigned char ch = (unsigned char)c; + ULONG num_written; + + /* write character to console file handle */ + +#ifdef _CRUISER_ + + if (DOSWRITE(_confh, &ch, 1L, &num_written)) { + /* OS/2 error, return error indicator */ + return EOF; + } + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + if ( (_confh == -1) || !WriteConsole( (HANDLE)_confh, + (LPVOID)&ch, + 1, + &num_written, + NULL ) + ) + /* return error indicator */ + return EOF; + +#else /* ndef _WIN32_ */ + +#error ERROR - ONLY CRUISER OR WIN32 TARGET SUPPORTED! + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + return ch; +} diff --git a/private/crt32/lowio/read.c b/private/crt32/lowio/read.c new file mode 100644 index 000000000..d11805761 --- /dev/null +++ b/private/crt32/lowio/read.c @@ -0,0 +1,349 @@ +/*** +*read.c - OS/2 read from a file handle +* +* Copyright (c) 1989-1993, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _read() - read from a file handle +* +*Revision History: +* 06-19-89 PHG Module created, based on asm version +* 03-13-90 GJF Made calling type _CALLTYPE2 (for now), added #include +* <cruntime.h> and fixed compiler warnings. Also, fixed +* the copyright. +* 04-03-90 GJF Now _CALLTYPE1. +* 07-24-90 SBM Removed '32' from API names +* 08-14-90 SBM Compiles cleanly with -W3 +* 10-01-90 GJF New-style function declarator. +* 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s. +* It is enough different that there is little point in +* trying to more closely merge the two versions. +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo +* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler +* 01-16-91 GJF ANSI naming. +* 01-29-91 SRW Changed to not read ahead on char devices [_WIN32_] +* 02-01-91 SRW Changed to use ERROR_HANDLE_EOF error code (_WIN32_) +* 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_) +* 04-09-91 PNT Added _MAC_ conditional +* 04-16-91 SRW Character device bug fix [_WIN32_] +* 05-23-91 GJF Don't set FEOFLAG if handle corresponds to a device. +* 10-24-91 GJF Added LPDWORD casts to make MIPS compiler happy. +* ASSUMES THAT sizeof(int) == sizeof(DWORD). +* 02-13-92 GJF Replaced _nfile by _nhandle for Win32. +* 06-16-92 GJF Bug fix - if CR was the very last char read, and the +* last char in the file, CRLF was getting written to +* user's buffer. +* 12-18-93 GJF Don't treat ERROR_BROKEN_PIPE as an error. Instead, +* just return 0. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <os2dll.h> +#include <io.h> +#include <internal.h> +#include <stdlib.h> +#include <errno.h> +#include <msdos.h> + +#define LF 10 /* line feed */ +#define CR 13 /* carriage return */ +#define CTRLZ 26 /* ctrl-z means eof for text */ + +/*** +*int _read(fh, buf, cnt) - read bytes from a file handle +* +*Purpose: +* Attempts to read cnt bytes from fh into a buffer. +* If the file is in text mode, CR-LF's are mapped to LF's, thus +* affecting the number of characters read. This does not +* affect the file pointer. +* +* NOTE: The stdio _IOCTRLZ flag is tied to the use of FEOFLAG. +* Cross-reference the two symbols before changing FEOFLAG's use. +* +*Entry: +* int fh - file handle to read from +* char *buf - buffer to read into +* int cnt - number of bytes to read +* +*Exit: +* Returns number of bytes read (may be less than the number requested +* if the EOF was reached or the file is in text mode). +* returns -1 (and sets errno) if fails. +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef MTHREAD + +/* define normal version that locks/unlocks, validates fh */ +int _CALLTYPE1 _read ( + int fh, + void *buf, + unsigned cnt + ) +{ + int r; /* return value */ + + /* validate handle */ +#ifdef _WIN32_ + if ( (unsigned)fh >= (unsigned)_nhandle ) { +#else + if ((unsigned)fh >= (unsigned)_nfile) { +#endif + /* out of range -- return error */ + errno = EBADF; + _doserrno = 0; /* not OS/2 error */ + return -1; + } + + _lock_fh(fh); /* lock file */ + r = _read_lk(fh, buf, cnt); /* read bytes */ + _unlock_fh(fh); /* unlock file */ + + return r; +} + +/* now define version that doesn't lock/unlock, validate fh */ +int _CALLTYPE1 _read_lk ( + int fh, + void *buf, + unsigned cnt + ) +{ + int bytes_read; /* number of bytes read */ + char *buffer; /* buffer to read to */ + int os_read; /* bytes read on OS call */ + char *p, *q; /* pointers into buffer */ + char peekchr; /* peek-ahead character */ + ULONG filepos; /* file position after seek */ + ULONG dosretval; /* OS/2 return value */ + + +#else + +/* now define normal version */ +int _CALLTYPE1 _read ( + int fh, + void *buf, + unsigned cnt + ) +{ + int bytes_read; /* number of bytes read */ + char *buffer; /* buffer to read to */ + int os_read; /* bytes read on OS call */ + char *p, *q; /* pointers into buffer */ + char peekchr; /* peek-ahead character */ + ULONG filepos; /* file position after seek */ + ULONG dosretval; /* OS/2 return value */ + + /* validate fh */ +#ifdef _WIN32_ + if ( (unsigned)fh >= (unsigned)_nhandle ) { +#else + if ((unsigned)fh >= (unsigned)_nfile) { +#endif + /* bad file handle */ + errno = EBADF; + _doserrno = 0; /* not OS/2 error */ + return -1; + } + +#endif + + bytes_read = 0; /* nothing read yet */ + buffer = buf; + + if (cnt == 0 || (_osfile[fh] & FEOFLAG)) { + /* nothing to read or at EOF, so return 0 read */ + return 0; + } + + if ((_osfile[fh] & (FPIPE|FDEV)) && _pipech[fh] != LF) { + /* a pipe/device and pipe lookahead non-empty: read the lookahead char */ + *buffer++ = _pipech[fh]; + ++bytes_read; + --cnt; + _pipech[fh] = LF; /* mark as empty */ + } + + /* read the data */ +#ifdef _CRUISER_ + + if ( dosretval = DOSREAD(fh, buffer, cnt, &os_read) ) { + /* OS error, map it and return */ + if (dosretval == ERROR_ACCESS_DENIED) { + /* wrong read/write mode should return EBADF, not EACCES */ + errno = EBADF; + _doserrno = dosretval; + } + else + _dosmaperr(dosretval); + return -1; + } + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + if ( !ReadFile((HANDLE)_osfhnd[fh], buffer, cnt, (LPDWORD)&os_read, + NULL) ) { + + /* ReadFile has reported an error. recognize two special cases. + * + * 1. map ERROR_ACCESS_DENIED to EBADF + * + * 2. just return 0 if ERROR_BROKEN_PIPE has occurred. it + * means the handle is a read-handle on a pipe for which + * all write-handles have been closed and all data has been + * read. */ + + if ( (dosretval = GetLastError()) == ERROR_ACCESS_DENIED ) { + /* wrong read/write mode should return EBADF, not EACCES */ + errno = EBADF; + _doserrno = dosretval; + return -1; + } + else if ( dosretval == ERROR_BROKEN_PIPE ) { + return 0; + } + else { + _dosmaperr(dosretval); + return -1; + } + } + +#else /* ndef _WIN32_ */ + +#ifdef _MAC_ + + TBD(); + +#else /* ndef _MAC_ */ + +#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED! + +#endif /* _MAC_ */ + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + bytes_read += os_read; /* update bytes read */ + + if (_osfile[fh] & FTEXT) { + /* now must translate CR-LFs to LFs in the buffer */ + + /* set CRLF flag to indicate LF at beginning of buffer */ + if (*(char *)buf == LF) + _osfile[fh] |= FCRLF; + else + _osfile[fh] &= ~FCRLF; + + /* convert chars in the buffer: p is src, q is dest */ + p = q = buf; + while (p < (char *)buf + bytes_read) { + if (*p == CTRLZ) { + /* if fh is not a device, set ctrl-z flag */ + if ( !(_osfile[fh] & FDEV) ) + _osfile[fh] |= FEOFLAG; + break; /* stop translating */ + } + else if (*p != CR) + *q++ = *p++; + else { + /* *p is CR, so must check next char for LF */ + if (p < (char *)buf + bytes_read - 1) { + if (*(p+1) == LF) { + p += 2; + *q++ = LF; /* convert CR-LF to LF */ + } + else + *q++ = *p++; /* store char normally */ + } + else { + /* This is the hard part. We found a CR at end of + buffer. We must peek ahead to see if next char + is an LF. */ + ++p; +#ifdef _CRUISER_ + + dosretval = DOSREAD(fh, &peekchr, 1, &os_read); + +#else /* ndef _CRUISER_ */ + +#ifdef _WIN32_ + + dosretval = 0; + if ( !ReadFile((HANDLE)_osfhnd[fh], &peekchr, 1, + (LPDWORD)&os_read, NULL) ) + dosretval = GetLastError(); + +#else /* ndef _WIN32_ */ + +#ifdef _MAC_ + + TBD(); + +#else /* ndef _MAC_ */ + +#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED! + +#endif /* _MAC_ */ + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + if (dosretval != 0 || os_read == 0) { + /* couldn't read ahead, store CR */ + *q++ = CR; + } + else { + /* peekchr now has the extra character -- we now have + several possibilities: + 1. disk file and char is not LF; just seek back + and copy CR + 2. disk file and char is LF; seek back and discard CR + 3. disk file, char is LF but this is a one-byte read: + store LF, don't seek back + 4. pipe/device and char is LF; store LF. + 5. pipe/device and char isn't LF, store CR and put + char in pipe lookahead buffer. */ + if (_osfile[fh] & (FDEV|FPIPE)) { + /* non-seekable device */ + if (peekchr == LF) + *q++ = LF; + else { + *q++ = CR; + _pipech[fh] = peekchr; + } + } + else { + /* disk file */ + if (q == buf && peekchr == LF) { + /* nothing read yet; must make some progress */ + *q++ = LF; + } + else { + /* seek back */ + filepos = _lseek_lk(fh, -1, FILE_CURRENT); + if (peekchr != LF) + *q++ = CR; + } + } + } + } + } + } + + /* we now change bytes_read to reflect the true number of chars + in the buffer */ + bytes_read = q - (char *)buf; + } + + return bytes_read; /* and return */ +} diff --git a/private/crt32/lowio/setmode.c b/private/crt32/lowio/setmode.c new file mode 100644 index 000000000..a9bf34e8e --- /dev/null +++ b/private/crt32/lowio/setmode.c @@ -0,0 +1,155 @@ +/*** +*setmode.c - set file translation mode +* +* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defined _setmode() - set file translation mode of a file +* +*Revision History: +* 08-16-84 RN initial version +* 10-29-87 JCR Multi-thread support +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 05-25-88 PHG Merged DLL and normal versions +* 03-13-90 GJF Made calling type _CALLTYPE1, added #include +* <cruntime.h>, removed #include <register.h> and +* fixed the copyright. Also, cleaned up the formatting +* a bit. +* 04-04-90 GJF Added #include <io.h>. +* 10-01-90 GJF New-style function declarators. +* 12-04-90 GJF Appended Win32 version onto the source with #ifdef-s. +* Two versions should be merged together, the differences +* are trivial. +* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo +* 01-17-91 GJF ANSI naming. +* 02-13-92 GJF Replaced _nfile by _nhandle for Win32. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <stdio.h> +#include <io.h> +#include <fcntl.h> +#include <errno.h> +#include <msdos.h> +#include <os2dll.h> +#include <stddef.h> +#include <internal.h> + +/*** +*int _setmode(fh, mode) - set file translation mode +* +*Purpose: +* changes file mode to text/binary, depending on mode arg. this affects +* whether read's and write's on the file translate between CRLF and LF +* or is untranslated +* +*Entry: +* int fh - file handle to change mode on +* int mode - file translation mode (one of O_TEXT and O_BINARY) +* +*Exit: +* returns old file translation mode +* returns -1 and sets errno if fails +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef MTHREAD /* multi-thread code calls _lk_setmode() */ + +int _CALLTYPE1 _setmode ( + int fh, + int mode + ) +{ + int retval; +#ifdef _WIN32_ + if ( (unsigned)fh >= (unsigned)_nhandle ) { +#else + if (fh < 0 || fh >= _nfile) { +#endif + errno = EBADF; + return(-1); + } + + /* lock the file */ + _lock_fh(fh); + + /* set the text/binary mode */ + retval = _setmode_lk(fh, mode); + + /* unlock the file */ + _unlock_fh(fh); + + /* Return to user (_setmode_lk sets errno, if needed) */ + return(retval); + +} + +/*** +*_setmode_lk() - Perform core setmode operation +* +*Purpose: +* Core setmode code. Assumes: +* (1) Caller has validated fh to make sure it's in range. +* (2) Caller has locked the file handle. +* +* [See _setmode() description above.] +* +*Entry: [Same as _setmode()] +* +*Exit: [Same as _setmode()] +* +*Exceptions: +* +*******************************************************************************/ + +int _CALLTYPE1 _setmode_lk ( + REG1 int fh, + int mode + ) +{ + int oldmode; + +#else /* non multi-thread code */ + +int _CALLTYPE1 _setmode ( + REG1 int fh, + int mode + ) +{ + int oldmode; + +#ifdef _WIN32_ + if ( (unsigned)fh >= (unsigned)_nhandle ) { +#else + if (fh < 0 || fh >= _nfile) { +#endif + errno = EBADF; + return(-1); + } + +#endif /* now join common code */ + + if (!(_osfile[fh] & FOPEN)) { + errno = EBADF; + return(-1); + } + + else { + oldmode = _osfile[fh] & FTEXT; + + if (mode == _O_BINARY) + _osfile[fh] &= ~FTEXT; + else if (mode == _O_TEXT) + _osfile[fh] |= FTEXT; + else { + errno = EINVAL; + return(-1); + } + } + + return(oldmode ? _O_TEXT : _O_BINARY); + +} diff --git a/private/crt32/lowio/sources b/private/crt32/lowio/sources new file mode 100644 index 000000000..6c95035f2 --- /dev/null +++ b/private/crt32/lowio/sources @@ -0,0 +1,62 @@ +!IF 0 + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + sources. + +Abstract: + + This file specifies the target component being built and the list of + sources files needed to build that component. Also specifies optional + compiler switches and libraries that are unique for the component being + built. + + +Author: + + Steve Wood (stevewo) 12-Apr-1990 + jeffrob 29-sep-1990, use crt32.def + +NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl + +!ENDIF + +MAJORCOMP=crt +MINORCOMP=lowio + +TARGETNAME=lowio +TARGETPATH=..\obj +TARGETTYPE=LIBRARY +386_STDCALL=0 + +!INCLUDE ..\crt32.def + +SOURCES=chsize.c \ + close.c \ + commit.c \ + creat.c \ + dup.c \ + dup2.c \ + eof.c \ + flength.c \ + fstat.c \ + initcon.c \ + ioinit.c \ + isatty.c \ + locking.c \ + lseek.c \ + mktemp.c \ + open.c \ + osfinfo.c \ + pipe.c \ + read.c \ + setmode.c \ + tell.c \ + txtmode.c \ + write.c \ + cgets.c \ + cputs.c \ + getch.c \ + putch.c diff --git a/private/crt32/lowio/tell.c b/private/crt32/lowio/tell.c new file mode 100644 index 000000000..0f8a2a497 --- /dev/null +++ b/private/crt32/lowio/tell.c @@ -0,0 +1,46 @@ +/*** +*tell.c - find file position +* +* Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. +* +*Purpose: +* contains _tell() - find file position +* +*Revision History: +* 09-02-83 RN initial version +* 12-11-87 JCR Added "_LOAD_DS" to declaration +* 03-13-90 GJF Replaced _LOAD_DS with _CALLTYPE1, added #include +* <cruntime.h> and fixed the copyright. Also, cleaned +* up the formatting a bit. +* 10-01-90 GJF New-style function declarator. +* 01-17-91 GJF ANSI naming. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <io.h> + +/*** +*long _tell(filedes) - find file position +* +*Purpose: +* Gets the current position of the file pointer (no adjustment +* for buffering). +* +*Entry: +* int filedes - file handle of file +* +*Exit: +* returns file position or -1L (sets errno) if bad file descriptor or +* pipe +* +*Exceptions: +* +*******************************************************************************/ + +long _CALLTYPE1 _tell ( + int filedes + ) +{ + return(_lseek(filedes,0L,1)); +} diff --git a/private/crt32/lowio/txtmode.c b/private/crt32/lowio/txtmode.c new file mode 100644 index 000000000..b40b0db61 --- /dev/null +++ b/private/crt32/lowio/txtmode.c @@ -0,0 +1,19 @@ +/*** +*txtmode.c - set global text mode flag +* +* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* Sets the global file mode to text. This is the default. +* +*Revision History: +* 06-08-89 PHG Module created, based on asm version. +* 04-04-90 GJF Added #include <cruntime.h>. Also, fixed the copyright. +* 01-23-92 GJF Added #include <stdlib.h> (contains decl of _fmode). +* +*******************************************************************************/ + +#include <cruntime.h> +#include <stdlib.h> + +int _fmode = 0; /* set text mode */ diff --git a/private/crt32/lowio/write.c b/private/crt32/lowio/write.c new file mode 100644 index 000000000..73d57bba1 --- /dev/null +++ b/private/crt32/lowio/write.c @@ -0,0 +1,324 @@ +/*** +*write.c - write to a file handle +* +* Copyright (c) 1989-1992, Microsoft Corporation. All rights reserved. +* +*Purpose: +* defines _write() - write to a file handle +* +*Revision History: +* 06-14-89 PHG Module created, based on asm version +* 03-13-90 GJF Made calling type _CALLTYPE2 (for now), added #include +* <cruntime.h>, fixed compiler warnings and fixed the +* copyright. Also, cleaned up the formatting a bit. +* 04-03-90 GJF Now _CALLTYPE1. +* 07-24-90 SBM Removed '32' from API names +* 08-14-90 SBM Compiles cleanly with -W3 +* 10-01-90 GJF New-style function declarators. +* 12-04-90 GJF Appended Win32 version onto source with #ifdef-s. +* Should come back latter and do a better merge. +* 12-04-90 SRW Changed to include <oscalls.h> instead of <doscalls.h> +* 12-06-90 SRW Changed to use _osfile and _osfhnd instead of _osfinfo +* 12-28-90 SRW Added _CRUISER_ conditional around check_stack pragma +* 12-28-90 SRW Added cast of void * to char * for Mips C Compiler +* 01-17-91 GJF ANSI naming. +* 02-25-91 MHL Adapt to ReadFile/WriteFile changes (_WIN32_) +* 04-09-91 PNT Added _MAC_ conditional +* 07-18-91 GJF Removed unreferenced local variable from _write_lk +* routine [_WIN32_]. +* 10-24-91 GJF Added LPDWORD casts to make MIPS compiler happy. +* ASSUMES THAT sizeof(int) == sizeof(DWORD). +* 02-13-92 GJF Replaced _nfile by _nhandle for Win32. +* 02-15-92 GJF Increased BUF_SIZE and simplified LF translation code +* for Win32. +* +*******************************************************************************/ + +#include <cruntime.h> +#include <oscalls.h> +#include <io.h> +#include <errno.h> +#include <msdos.h> +#include <os2dll.h> +#include <stdlib.h> +#include <string.h> +#include <internal.h> + +#ifdef _WIN32_ +#define BUF_SIZE 1025 /* size of LF translation buffer */ +#else /* ndef _WIN32_ */ +#define BUF_SIZE 513 /* size of LF translation buffer, sector size+1 is ok */ +#endif /* _WIN32_ */ + +#define LF '\n' /* line feed */ +#define CR '\r' /* carriage return */ +#define CTRLZ 26 /* ctrl-z */ + +#ifdef _CRUISER_ +#pragma check_stack(on) +#endif /* ndef _CRUISER_ */ + +/*** +*int _write(fh, buf, cnt) - write bytes to a file handle +* +*Purpose: +* Writes count bytes from the buffer to the handle specified. +* If the file was opened in text mode, each LF is translated to +* CR-LF. This does not affect the return value. In text +* mode ^Z indicates end of file. +* +* Multi-thread notes: +* (1) _write() - Locks/unlocks file handle +* _write_lk() - Does NOT lock/unlock file handle +* +*Entry: +* int fh - file handle to write to +* char *buf - buffer to write from +* unsigned int cnt - number of bytes to write +* +*Exit: +* returns number of bytes actually written. +* This may be less than cnt, for example, if out of disk space. +* returns -1 (and set errno) if fails. +* +*Exceptions: +* +*******************************************************************************/ + +#ifdef MTHREAD + +/* define normal version that locks/unlocks, validates fh */ +int _CALLTYPE1 _write ( + int fh, + const void *buf, + unsigned cnt + ) +{ + int r; /* return value */ + + /* validate handle */ +#ifdef _WIN32_ + if ( (unsigned)fh >= (unsigned)_nhandle ) { +#else + if ((unsigned)fh >= (unsigned)_nfile) { +#endif + /* out of range -- return error */ + errno = EBADF; + _doserrno = 0; /* not OS/2 error */ + return -1; + } + + _lock_fh(fh); /* lock file */ + r = _write_lk(fh, buf, cnt); /* write bytes */ + _unlock_fh(fh); /* unlock file */ + + return r; +} + +/* now define version that doesn't lock/unlock, validate fh */ +int _CALLTYPE1 _write_lk ( + int fh, + const void *buf, + unsigned cnt + ) +{ + int lfcount; /* count of line feeds */ + int charcount; /* count of chars written so far */ + int written; /* count of chars written on this write */ +#ifdef _CRUISER_ + int error; /* error occured */ +#endif + ULONG dosretval; /* OS/2 return value */ + char ch; /* current character */ + char *p, *q; /* pointers into buf and lfbuf resp. */ + char lfbuf[BUF_SIZE]; /* lf translation buffer */ + +#else + +/* now define normal version */ +int _CALLTYPE1 _write ( + int fh, + const void *buf, + unsigned cnt + ) +{ + int lfcount; /* count of line feeds */ + int charcount; /* count of chars written so far */ + int written; /* count of chars written on this write */ +#ifdef _CRUISER_ + int error; /* error occured */ +#endif + ULONG dosretval; /* OS/2 return value */ + char ch; /* current character */ + char *p, *q; /* pointers into buf and lfbuf resp. */ + char lfbuf[BUF_SIZE]; /* lf translation buffer */ + + /* validate handle */ +#ifdef _WIN32_ + if ( (unsigned)fh >= (unsigned)_nhandle ) { +#else + if ((unsigned)fh >= (unsigned)_nfile) { +#endif + /* out of range -- return error */ + errno = EBADF; + _doserrno = 0; /* not OS/2 error */ + return -1; + } + +#endif + + lfcount = charcount = 0; /* nothing written yet */ + + if (cnt == 0) + return 0; /* nothing to do */ + + + if (_osfile[fh] & FAPPEND) { + /* appending - seek to end of file; ignore error, because maybe + file doesn't allow seeking */ + (void)_lseek_lk(fh, 0, FILE_END); + } + + /* check for text mode with LF's in the buffer */ + +#ifdef _CRUISER_ + if ((_osfile[fh] & FTEXT) && memchr(buf, LF, cnt)) { + /* text mode, translate LF's to CR/LF's on output */ + + p = (char *)buf; /* start at beginning of buffer */ + error = 0; /* no error yet */ + + while ((unsigned)(p - (char *)buf) < cnt && !error) { + q = lfbuf; /* start at beginning of lfbuf */ + + /* fill the lf buf, except maybe last char */ + while (q - lfbuf < BUF_SIZE - 1 && (unsigned)(p - (char *)buf) < cnt) { + ch = *p++; + if (ch == LF) { + ++lfcount; + *q++ = CR; + *q++ = LF; /* store CR-LF */ + } + else + *q++ = ch; + } + + /* write the lf buf and update total */ + if (dosretval = DOSWRITE(fh, lfbuf, q - lfbuf, + &written)) + error = 1; + else { + charcount += written; + if (written < q - lfbuf) + error = 1; + } + } + } + else { + /* binary mode, no translation */ + if (!(dosretval = DOSWRITE(fh, (char *)buf, cnt, &written))) + charcount = written; + } + +#else /* _CRUISER_ */ + +#ifdef _WIN32_ + if ( _osfile[fh] & FTEXT ) { + /* text mode, translate LF's to CR/LF's on output */ + + p = (char *)buf; /* start at beginning of buffer */ + dosretval = 0; /* no OS error yet */ + + while ( (unsigned)(p - (char *)buf) < cnt ) { + q = lfbuf; /* start at beginning of lfbuf */ + + /* fill the lf buf, except maybe last char */ + while ( q - lfbuf < BUF_SIZE - 1 && + (unsigned)(p - (char *)buf) < cnt ) { + ch = *p++; + if ( ch == LF ) { + ++lfcount; + *q++ = CR; + } + *q++ = ch; + } + + /* write the lf buf and update total */ + if ( WriteFile( (HANDLE)_osfhnd[fh], + lfbuf, + q - lfbuf, + (LPDWORD)&written, + NULL) ) + { + charcount += written; + if (written < q - lfbuf) + break; + } + else { + dosretval = GetLastError(); + break; + } + } + } + else { + /* binary mode, no translation */ + if ( WriteFile( (HANDLE)_osfhnd[fh], + (LPVOID)buf, + cnt, + (LPDWORD)&written, + NULL) ) + { + dosretval = 0; + charcount = written; + } + else + dosretval = GetLastError(); + } + +#else /* ndef _WIN32_ */ + +#ifdef _MAC_ + + } + } + + TBD(); + +#else /* ndef _MAC_ */ + +#error ERROR - ONLY CRUISER, WIN32, OR MAC TARGET SUPPORTED! + +#endif /* _MAC_ */ + +#endif /* _WIN32_ */ + +#endif /* _CRUISER_ */ + + if (charcount == 0) { + /* If nothing was written, first check if an OS/2 error, + otherwise we return -1 and set errno to ENOSPC, + unless a device and first char was CTRL-Z */ + if (dosretval != 0) { + /* OS/2 error happened, map error */ + if (dosretval == ERROR_ACCESS_DENIED) { + /* wrong read/write mode should return EBADF, not + EACCES */ + errno = EBADF; + _doserrno = dosretval; + } + else + _dosmaperr(dosretval); + return -1; + } + else if ((_osfile[fh] & FDEV) && *(char *)buf == CTRLZ) + return 0; + else { + errno = ENOSPC; + _doserrno = 0; /* no OS/2 error */ + return -1; + } + } + else + /* return adjusted bytes written */ + return charcount - lfcount; +} |