summaryrefslogtreecommitdiffstats
path: root/otherlibs/win32unix/close_on.c
diff options
context:
space:
mode:
Diffstat (limited to 'otherlibs/win32unix/close_on.c')
-rw-r--r--otherlibs/win32unix/close_on.c70
1 files changed, 52 insertions, 18 deletions
diff --git a/otherlibs/win32unix/close_on.c b/otherlibs/win32unix/close_on.c
index ba32350a2..324c16209 100644
--- a/otherlibs/win32unix/close_on.c
+++ b/otherlibs/win32unix/close_on.c
@@ -48,42 +48,76 @@ value win_clear_close_on_exec(fd) /* ML */
#else
-extern int _set_osfhnd(int fd, long value);
+/* This works on Win 95, but is a terrible hack.
+ Bug: the opening flags of the file descriptor (O_APPEND, O_TEXT) are lost. */
-static int win_realloc_handle(fd, inherit)
- int fd;
- BOOL inherit;
+static int win_open_osfhandle2(handle, flags, reqd_fd)
+ HANDLE handle;
+ int flags;
+ int reqd_fd;
{
- HANDLE oldh, newh;
+ int fd, retcode;
+ HANDLE new_handle;
+ fd = _open_osfhandle((long)handle, flags);
+ if (fd == -1)
+ return -1;
+ if (fd == reqd_fd)
+ return 0; /* Got it! */
+ /* Make a copy of the handle, since we're going to close "handle" when
+ we close "fd". */
+ if (! DuplicateHandle(GetCurrentProcess(), handle,
+ GetCurrentProcess(), &new_handle,
+ 0L, FALSE, DUPLICATE_SAME_ACCESS)) {
+ _dosmaperr(GetLastError());
+ return -1;
+ }
+ /* Keep fd open during the recursive call, thus forcing _open_osfhandle
+ to return reqd_fd eventually. */
+ retcode = win_open_osfhandle2(new_handle, flags, reqd_fd);
+ close(fd); /* Also closes "handle" */
+ return retcode;
+}
+
+static int win_set_noninherit(fd)
+ int fd;
+{
+ HANDLE oldh, newh;
oldh = (HANDLE) _get_osfhandle(fd);
if (oldh == (HANDLE) -1) return -1;
if (! DuplicateHandle(GetCurrentProcess(), oldh,
- GetCurrentProcess(), &newh,
- 0L, inherit, DUPLICATE_SAME_ACCESS)) {
- _dosmaperr(GetLastError());
+ GetCurrentProcess(), &newh,
+ 0L, FALSE, DUPLICATE_SAME_ACCESS)) {
+ _dosmaperr(GetLastError());
return -1;
}
- _close(fd);
- _set_osfhnd(fd, (long) newh);
- return 0;
+ if (close(fd) == -1) return -1;
+ return win_open_osfhandle2(newh, 0, fd);
}
-value win_set_close_on_exec(fd) /* ML */
- value fd;
+value win_set_close_on_exec(vfd) /* ML */
+ value vfd;
{
- if (win_realloc_handle(Int_val(fd), FALSE) == -1) {
+ if (win_set_noninherit(Int_val(vfd)) == -1)
uerror("set_close_on_exec", Nothing);
- }
return Val_unit;
}
-value win_clear_close_on_exec(fd) /* ML */
- value fd;
+value win_clear_close_on_exec(vfd) /* ML */
+ value vfd;
{
- if (win_realloc_handle(Int_val(fd), TRUE) == -1) {
+ int fd, newfd;
+
+ fd = Int_val(vfd);
+ newfd = dup(fd);
+ if (newfd == -1) {
+ uerror("clear_close_on_exec", Nothing);
+ }
+ if (dup2(newfd, fd) == -1) {
+ close(newfd);
uerror("clear_close_on_exec", Nothing);
}
+ close(newfd);
return Val_unit;
}