diff --git a/src/configure.in b/src/configure.in index 03f08ac1151c94630ac50e26d0250326429cf195..cb9c5fa8bd586631bfd9b34b33db7296a2736ef4 100644 --- a/src/configure.in +++ b/src/configure.in @@ -4510,6 +4510,7 @@ fi AC_CHECK_FUNCS( \ _crypt \ poll \ + accept4 \ closefrom \ crypt \ fdwalk \ diff --git a/src/fd_control.c b/src/fd_control.c index 90ac7acee555444d89d7401b4b3c2d824bb4b87f..2e9295657ff98bb5cb8f3a8be1afc041baf8d917 100644 --- a/src/fd_control.c +++ b/src/fd_control.c @@ -224,6 +224,22 @@ PMOD_EXPORT int set_close_on_exec(int fd, int which) #endif /* !HAVE_BROKEN_F_SETFD */ } +#ifndef HAVE_ACCEPT4 +int accept4(int fd, struct sockaddr *addr, ACCEPT_SIZE_T *addrlen, int flags) +{ + int fd = fd_accept(fd, addr, addrlen); + if (!flags || (fd < 0)) return fd; + if (((flags & SOCK_NONBLOCK) && (set_nonblocking(fd, 1) < 0)) || + ((flags & SOCK_CLOEXEC) && (set_close_on_exec(fd, 1) < 0))) { + int e = errno; + fd_close(fd); + errno = e; + return -1; + } + return fd; +} +#endif /* !HAVE_ACCEPT4 */ + #endif /* !TESTING */ #ifdef TESTING diff --git a/src/fd_control.h b/src/fd_control.h index 11d27bf4a04d750b7f26cec1436f5c261702cb80..f1f0d35830bf0166d3f4d0219ba4563a6a5b7c90 100644 --- a/src/fd_control.h +++ b/src/fd_control.h @@ -7,6 +7,33 @@ #ifndef FD_CONTROL_H #define FD_CONTROL_H +#ifndef HAVE_ACCEPT4 +/* NB: The default values are compatible with Linux, + * but should work on other OSs as well, since + * accept4(2) is emulated by us anyway. + */ +enum pike_sock_flags { +#ifndef SOCK_CLOEXEC +#if !defined(SOCK_NONBLOCK) || (SOCK_NONBLOCK != 0x80000) + SOCK_CLOEXEC = 0x80000, +#else + /* Unlikely, but... */ + SOCK_CLOEXEC = 0x40000, +#endif /* !SOCK_NONBLOCK || SOCK_NONBLOCK != 0x80000 */ +#define SOCK_CLOEXEC SOCK_CLOEXEC +#endif +#ifndef SOCK_NONBLOCK +#if (SOCK_CLOEXEC != 0x00800) + SOCK_NONBLOCK = 0x00800, +#else + /* Unlikely, but... */ + SOCK_NONBLOCK = 0x00400, +#endif +#define SOCK_NONBLOCK SOCK_NONBLOCK +#endif +}; +#endif /* !HAVE_ACCEPT4 */ + /* Prototypes begin here */ PMOD_EXPORT int set_nonblocking(int fd,int which); PMOD_EXPORT int query_nonblocking(int fd); @@ -16,6 +43,9 @@ PMOD_EXPORT int set_close_on_exec(int fd, int which); void do_close_on_exec(void); void cleanup_close_on_exec(void); #endif /* HAVE_BROKEN_F_SETFD */ +#ifndef HAVE_ACCEPT4 +int accept4(int fd, struct sockaddr *addr, ACCEPT_SIZE_T *addrlen, int flags) +#endif /* !HAVE_ACCEPT4 */ /* Prototypes end here */ #endif diff --git a/src/fdlib.h b/src/fdlib.h index 3b653652b10b706b40c61b0718b60e05e8b0ae99..d3775fffa5fbed1e803ff96fffffb80c3708e613 100644 --- a/src/fdlib.h +++ b/src/fdlib.h @@ -90,6 +90,7 @@ typedef off_t PIKE_OFF_T; #define fd_socket(X,Y,Z) dmalloc_register_fd(debug_fd_socket((X),(Y),(Z))) #define fd_pipe(X) debug_fd_pipe( (X) DMALLOC_POS ) #define fd_accept(X,Y,Z) dmalloc_register_fd(debug_fd_accept((X),(Y),(Z))) +#define fd_accept4(X,Y,Z,F) dmalloc_register_fd(accept4((X),(Y),(Z),(F))) #define fd_bind(fd,X,Y) debug_fd_bind(dmalloc_touch_fd(fd), (X), (Y)) #define fd_getsockopt(fd,X,Y,Z,Q) debug_fd_getsockopt(dmalloc_touch_fd(fd), (X),(Y),(Z),(Q)) @@ -340,6 +341,7 @@ typedef off_t PIKE_OFF_T; #define fd_socket(X,Y,Z) dmalloc_register_fd(socket((X),(Y),(Z))) #define fd_pipe pipe /* FIXME */ #define fd_accept(X,Y,Z) dmalloc_register_fd(accept((X),(Y),(Z))) +#define fd_accept4(X,Y,Z,F) dmalloc_register_fd(accept4((X),(Y),(Z),(F))) #define fd_bind(fd,X,Y) bind(dmalloc_touch_fd(fd), (X), (Y)) #define fd_getsockopt(fd,X,Y,Z,Q) getsockopt(dmalloc_touch_fd(fd), (X),(Y),(Z),(Q))