summaryrefslogtreecommitdiff
path: root/otherlibs/win32unix/close_on.c
blob: 179a5ae481d27344f94318d7dc83b10acb7e7c27 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/***********************************************************************/
/*                                                                     */
/*                           Objective Caml                            */
/*                                                                     */
/*  Xavier Leroy and Pascal Cuoq, projet Cristal, INRIA Rocquencourt   */
/*                                                                     */
/*  Copyright 1996 Institut National de Recherche en Informatique et   */
/*  Automatique.  Distributed only by permission.                      */
/*                                                                     */
/***********************************************************************/

/* $Id$ */

#include <mlvalues.h>
#include <windows.h>
#include "unixsupport.h"

#if 0

/* This works only under Windows NT, but not 95 */

value win_set_close_on_exec(fd)             /* ML */
     value fd;
{
  HANDLE h;

  h = (HANDLE) _get_osfhandle(Int_val(fd)) ;
  if (h == (HANDLE) -1 ||
      ! SetHandleInformation(h, HANDLE_FLAG_INHERIT, 0)) {
    _dosmaperr(GetLastError());
    uerror("set_close_on_exec", Nothing);
  }
  return Val_unit;
}

value win_clear_close_on_exec(fd)             /* ML */
     value fd;
{
  HANDLE h;
  h = (HANDLE) _get_osfhandle(Int_val(fd)) ;
  if (h == (HANDLE) -1 ||
      ! SetHandleInformation(h, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
    _dosmaperr(GetLastError());
    uerror("clear_close_on_exec", Nothing);
  }
  return Val_unit;
}

#else

/* 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_open_osfhandle2(handle, flags, reqd_fd)
     HANDLE handle;
     int flags;
     int reqd_fd;
{
  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, FALSE, DUPLICATE_SAME_ACCESS)) {
    _dosmaperr(GetLastError());
    return -1;
  }
  if (close(fd) == -1) return -1;
  return win_open_osfhandle2(newh, 0, fd);
}

value win_set_close_on_exec(vfd)             /* ML */
     value vfd;
{
  if (win_set_noninherit(Int_val(vfd)) == -1)
    uerror("set_close_on_exec", Nothing);
  return Val_unit;
}

value win_clear_close_on_exec(vfd)             /* ML */
     value vfd;
{
  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;
}

#endif