summaryrefslogtreecommitdiffstats
path: root/private/crt32/lowio/dup2.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/crt32/lowio/dup2.c')
-rw-r--r--private/crt32/lowio/dup2.c200
1 files changed, 200 insertions, 0 deletions
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;
+}