1 /* Accept a connection on a socket, with specific opening flags.
2 Copyright (C) 2009-2024 Free Software Foundation, Inc.
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation, either version 3 of the
7 License, or (at your option) any later version.
9 This file is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
20 #include <sys/socket.h>
24 #include "binary-io.h"
25 #if GNULIB_MSVC_NOTHROW
26 # include "msvc-nothrow.h"
32 # define SOCK_CLOEXEC 0
35 # define SOCK_NONBLOCK 0
39 accept4 (int sockfd
, struct sockaddr
*addr
, socklen_t
*addrlen
, int flags
)
45 /* Try the system call first, if it exists. (We may be running with a glibc
46 that has the function but with an older kernel that lacks it.) */
48 /* Cache the information whether the system call really exists. */
49 static int have_accept4_really
; /* 0 = unknown, 1 = yes, -1 = no */
50 if (have_accept4_really
>= 0)
52 int result
= accept4 (sockfd
, addr
, addrlen
, flags
);
53 if (!(result
< 0 && errno
== ENOSYS
))
55 have_accept4_really
= 1;
58 have_accept4_really
= -1;
63 /* Check the supported flags. */
64 if ((flags
& ~(SOCK_CLOEXEC
| SOCK_NONBLOCK
| O_TEXT
| O_BINARY
)) != 0)
70 fd
= accept (sockfd
, addr
, addrlen
);
75 # if defined _WIN32 && ! defined __CYGWIN__
76 /* Native Windows API. */
77 if (flags
& SOCK_CLOEXEC
)
79 HANDLE curr_process
= GetCurrentProcess ();
80 HANDLE old_handle
= (HANDLE
) _get_osfhandle (fd
);
84 if (!DuplicateHandle (curr_process
, /* SourceProcessHandle */
85 old_handle
, /* SourceHandle */
86 curr_process
, /* TargetProcessHandle */
87 (PHANDLE
) &new_handle
, /* TargetHandle */
88 (DWORD
) 0, /* DesiredAccess */
89 FALSE
, /* InheritHandle */
90 DUPLICATE_SAME_ACCESS
)) /* Options */
93 errno
= EBADF
; /* arbitrary */
97 /* Closing fd before allocating the new fd ensures that the new fd will
98 have the minimum possible value. */
100 nfd
= _open_osfhandle ((intptr_t) new_handle
,
101 O_NOINHERIT
| (flags
& (O_TEXT
| O_BINARY
)));
104 CloseHandle (new_handle
);
111 if (flags
& SOCK_CLOEXEC
)
115 if ((fcntl_flags
= fcntl (fd
, F_GETFD
, 0)) < 0
116 || fcntl (fd
, F_SETFD
, fcntl_flags
| FD_CLOEXEC
) == -1)
118 int saved_errno
= errno
;
128 if (flags
& SOCK_NONBLOCK
)
132 if ((fcntl_flags
= fcntl (fd
, F_GETFL
, 0)) < 0
133 || fcntl (fd
, F_SETFL
, fcntl_flags
| O_NONBLOCK
) == -1)
135 int saved_errno
= errno
;
144 if (flags
& O_BINARY
)
145 set_binary_mode (fd
, O_BINARY
);
146 else if (flags
& O_TEXT
)
147 set_binary_mode (fd
, O_TEXT
);