e576bb2002-10-11Martin Nilsson /* || This file is part of Pike. For copyright information see COPYRIGHT. || Pike is distributed under GPL, LGPL and MPL. See the file COPYING || for more information. */
5267b71995-08-09Fredrik Hübinette (Hubbe)  #ifndef TESTING #include "global.h"
b2d3e42000-12-01Fredrik Hübinette (Hubbe) #include "pike_error.h"
5740881998-01-01Fredrik Hübinette (Hubbe) #include "fdlib.h"
24ddc71998-03-28Henrik Grubbström (Grubba) 
e0aa661998-09-01Fredrik Hübinette (Hubbe) #else /* TESTING */
df87c61999-05-28Henrik Grubbström (Grubba) 
bee7bd2000-07-28Fredrik Hübinette (Hubbe) #define PMOD_EXPORT
32c0811998-07-04Henrik Grubbström (Grubba) #ifndef _LARGEFILE_SOURCE # define _FILE_OFFSET_BITS 64 # define _LARGEFILE_SOURCE 1 # define _LARGEFILE64_SOURCE 1 #endif /* !_LARGERFILE_SOURCE */ /* HPUX needs these too... */ #ifndef __STDC_EXT__ # define __STDC_EXT__ #endif /* !__STDC_EXT__ */
9c50201998-03-26Fredrik Hübinette (Hubbe) #include <sys/types.h>
71f3a21998-11-22Fredrik Hübinette (Hubbe) #undef PIKE_DEBUG
fedf131998-03-25Fredrik Hübinette (Hubbe) #define fd_ioctl ioctl
df87c61999-05-28Henrik Grubbström (Grubba)  #endif /* TESTING */
5267b71995-08-09Fredrik Hübinette (Hubbe) 
bdfb861997-12-22Fredrik Hübinette (Hubbe) #include "fd_control.h" #ifdef HAVE_SYS_IOCTL_H #include <sys/ioctl.h> #endif #ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> #endif
df87c61999-05-28Henrik Grubbström (Grubba) #include <errno.h>
75920f1997-12-28Fredrik Hübinette (Hubbe) #ifdef HAVE_SYS_ERRNO_H
76b47c1999-05-28Mirar (Pontus Hagland) #include <sys/errno.h>
75920f1997-12-28Fredrik Hübinette (Hubbe) #endif
ab926b2003-04-30Henrik Grubbström (Grubba) #ifdef HAVE_WINSOCK2_H #include <winsock2.h> #elif defined(HAVE_WINSOCK_H)
2043ba1998-02-10Fredrik Hübinette (Hubbe) #include <winsock.h>
bdfb861997-12-22Fredrik Hübinette (Hubbe) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef HAVE_FCNTL_H #include <fcntl.h> #endif #ifdef HAVE_SYS_FILIO_H #include <sys/filio.h> #endif #ifdef HAVE_SYS_SOCKIO_H #include <sys/sockio.h> #endif
e0aa661998-09-01Fredrik Hübinette (Hubbe) #ifdef HAVE_NETINET_IN_H #include <netinet/in.h> #endif #ifdef HAVE_ARPA_INET_H #include <arpa/inet.h> #endif
557c051999-09-14Henrik Grubbström (Grubba) #ifdef HAVE_SYS_FILE_H #include <sys/file.h> #endif
e0aa661998-09-01Fredrik Hübinette (Hubbe) 
5267b71995-08-09Fredrik Hübinette (Hubbe) 
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT int set_nonblocking(int fd,int which)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
d887b61999-05-26Fredrik Hübinette (Hubbe)  int ret;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
a753e52000-05-20Per Hedbor  if(fd<0)
b99d882003-05-15Martin Stjernholm  Pike_fatal("File descriptor %d out of range.\n", fd);
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
13670c2015-05-25Martin Nilsson  do
d887b61999-05-26Fredrik Hübinette (Hubbe)  {
fedf131998-03-25Fredrik Hübinette (Hubbe) #if defined(USE_IOCTL_FIONBIO) || defined(__NT__)
d887b61999-05-26Fredrik Hübinette (Hubbe)  ret=fd_ioctl(fd, FIONBIO, &which);
5267b71995-08-09Fredrik Hübinette (Hubbe) #else
3b33f02003-12-08Henrik Grubbström (Grubba) 
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef USE_FCNTL_O_NDELAY
88cd212003-12-08Henrik Grubbström (Grubba) #define FCNTL_NBFLAG O_NDELAY #elif defined(USE_FCNTL_O_NONBLOCK) #define FCNTL_NBFLAG O_NONBLOCK #elif defined(USE_FCNTL_FNDELAY) #define FCNTL_NBFLAG FNDELAY #endif
3b33f02003-12-08Henrik Grubbström (Grubba) 
88cd212003-12-08Henrik Grubbström (Grubba) #ifdef FCNTL_NBFLAG int flags = fcntl(fd, F_GETFL, 0); if (which) { flags |= FCNTL_NBFLAG; } else { flags &= ~FCNTL_NBFLAG; } ret = fcntl(fd, F_SETFL, flags);
3b33f02003-12-08Henrik Grubbström (Grubba) #elif !defined(DISABLE_BINARY)
a4a1722000-12-05Per Hedbor #error Do not know how to set your filedescriptors nonblocking.
def05c2002-01-27Martin Stjernholm #endif
bdfb861997-12-22Fredrik Hübinette (Hubbe)  #endif
d887b61999-05-26Fredrik Hübinette (Hubbe)  } while(ret <0 && errno==EINTR); return ret;
5267b71995-08-09Fredrik Hübinette (Hubbe) }
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT int query_nonblocking(int fd)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
84a36c2015-04-19Henrik Grubbström (Grubba)  int ret = 0;
71f3a21998-11-22Fredrik Hübinette (Hubbe) #ifdef PIKE_DEBUG
a753e52000-05-20Per Hedbor  if(fd<0)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Filedescriptor out of range.\n");
5267b71995-08-09Fredrik Hübinette (Hubbe) #endif
88cd212003-12-08Henrik Grubbström (Grubba) #ifdef FCNTL_NBFLAG
84a36c2015-04-19Henrik Grubbström (Grubba)  do { ret = fcntl(fd, F_GETFL, 0);
d887b61999-05-26Fredrik Hübinette (Hubbe)  } while(ret <0 && errno==EINTR);
84a36c2015-04-19Henrik Grubbström (Grubba)  return ret & FCNTL_NBFLAG; #else
d887b61999-05-26Fredrik Hübinette (Hubbe)  return ret;
84a36c2015-04-19Henrik Grubbström (Grubba) #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) }
bd756b2001-01-21Henrik Grubbström (Grubba) /* The following code doesn't link without help, and * since it isn't needed by the nonblocking test, we * can safely disable it. */ #ifndef TESTING
5539c51998-06-08Henrik Grubbström (Grubba) #ifndef FD_CLOEXEC #define FD_CLOEXEC 1 #endif /* FD_CLOEXEC */ #ifdef HAVE_BROKEN_F_SETFD
a753e52000-05-20Per Hedbor static int *fds_to_close; static int fds_to_close_size = 0;
3a5b1d2000-05-24Fredrik Hübinette (Hubbe) static int num_fds_to_close=0;
a753e52000-05-20Per Hedbor  #define ASSURE_FDS_TO_CLOSE_SIZE(X) \ do{while(fds_to_close_size-1 < X) grow_fds_to_close();}while(0)
3a5b1d2000-05-24Fredrik Hübinette (Hubbe) static void grow_fds_to_close(void)
a753e52000-05-20Per Hedbor { if(!fds_to_close_size) fds_to_close_size = 1; fds_to_close_size *= 2; fds_to_close = realloc( fds_to_close, sizeof( int ) * fds_to_close_size ); if(!fds_to_close)
5aad932002-08-15Marcus Comstedt  Pike_fatal("Out of memory in fd_control::grow_fds_to_close()\n"
a753e52000-05-20Per Hedbor  "Tried to allocate %d fd_datum structs\n", fds_to_close_size);
21b12a2014-09-03Martin Nilsson  memset( fds_to_close+(fds_to_close_size/2), 0, fds_to_close_size*sizeof(int)/2 );
a753e52000-05-20Per Hedbor }
5539c51998-06-08Henrik Grubbström (Grubba)  void do_close_on_exec(void) {
a5cd6a2001-09-24Henrik Grubbström (Grubba)  int i;
5539c51998-06-08Henrik Grubbström (Grubba)  for(i=0; i < num_fds_to_close; i++) {
ec70a72000-07-07Henrik Grubbström (Grubba)  while( fd_close(fds_to_close[i]) <0 && errno==EINTR) ;
5539c51998-06-08Henrik Grubbström (Grubba)  } num_fds_to_close = 0; }
0eb0a02000-05-20Henrik Grubbström (Grubba)  void cleanup_close_on_exec(void) { if (fds_to_close) { free(fds_to_close); fds_to_close = 0; fds_to_close_size = 0; num_fds_to_close = 0; } }
5539c51998-06-08Henrik Grubbström (Grubba) #endif /* HAVE_BROKEN_F_SETFD */
1f21332000-07-28Fredrik Hübinette (Hubbe) PMOD_EXPORT int set_close_on_exec(int fd, int which)
5267b71995-08-09Fredrik Hübinette (Hubbe) {
5539c51998-06-08Henrik Grubbström (Grubba) #ifndef HAVE_BROKEN_F_SETFD
d887b61999-05-26Fredrik Hübinette (Hubbe)  int ret;
61ed5d2004-12-30Henrik Grubbström (Grubba)  if (which) { do { which = fcntl(fd, F_GETFD); } while (which < 0 && errno == EINTR); if (which < 0) which = FD_CLOEXEC; else which |= FD_CLOEXEC; } else { do { which = fcntl(fd, F_GETFD); } while (which < 0 && errno == EINTR); if (which < 0) which = 0; else which &= ~FD_CLOEXEC; }
13670c2015-05-25Martin Nilsson  do
d887b61999-05-26Fredrik Hübinette (Hubbe)  {
61ed5d2004-12-30Henrik Grubbström (Grubba)  ret=fcntl(fd, F_SETFD, which);
d887b61999-05-26Fredrik Hübinette (Hubbe)  } while (ret <0 && errno==EINTR ); return ret;
5539c51998-06-08Henrik Grubbström (Grubba) #else /* HAVE_BROKEN_F_SETFD */ int i; if (which) { for(i = 0; i < num_fds_to_close; i++) { if (fds_to_close[i] == fd) { return(0); /* Already marked */ } }
a753e52000-05-20Per Hedbor  ASSURE_FDS_TO_CLOSE_SIZE((num_fds_to_close+1));
5539c51998-06-08Henrik Grubbström (Grubba)  fds_to_close[num_fds_to_close++] = fd; return(0); } else { for(i = 0; i < num_fds_to_close; i++) { while (fds_to_close[i] == fd && (i < num_fds_to_close)) { fds_to_close[i] = fds_to_close[--num_fds_to_close]; } } return(0); }
bdfb861997-12-22Fredrik Hübinette (Hubbe)  return 0;
5539c51998-06-08Henrik Grubbström (Grubba) #endif /* !HAVE_BROKEN_F_SETFD */
5267b71995-08-09Fredrik Hübinette (Hubbe) }
236e8e2014-09-24Henrik Grubbström (Grubba) #ifndef HAVE_ACCEPT4 int accept4(int fd, struct sockaddr *addr, ACCEPT_SIZE_T *addrlen, int flags) {
ebdec82014-10-03Jonas Walldén  fd = fd_accept(fd, addr, addrlen);
236e8e2014-09-24Henrik Grubbström (Grubba)  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 */
bd756b2001-01-21Henrik Grubbström (Grubba) #endif /* !TESTING */
5267b71995-08-09Fredrik Hübinette (Hubbe) #ifdef TESTING
bdfb861997-12-22Fredrik Hübinette (Hubbe) 
2043ba1998-02-10Fredrik Hübinette (Hubbe) #if defined(HAVE_WINSOCK_H) && defined(USE_IOCTLSOCKET_FIONBIO)
bdfb861997-12-22Fredrik Hübinette (Hubbe) int main() { exit(0); } #else
5267b71995-08-09Fredrik Hübinette (Hubbe) #include <signal.h>
9c50201998-03-26Fredrik Hübinette (Hubbe) #include <stdio.h>
75920f1997-12-28Fredrik Hübinette (Hubbe) #include <errno.h>
3e84d61997-04-16Fredrik Hübinette (Hubbe) #ifdef HAVE_UNISTD_H #include <unistd.h> #endif
5267b71995-08-09Fredrik Hübinette (Hubbe) /* a part of the autoconf thingy */
c19f052002-09-02Henrik Grubbström (Grubba) RETSIGTYPE sigalrm_handler0(int tmp) { signal(SIGALRM, SIG_IGN); alarm(0); _exit(0); }
9c50201998-03-26Fredrik Hübinette (Hubbe) RETSIGTYPE sigalrm_handler1(int tmp) {
c19f052002-09-02Henrik Grubbström (Grubba)  alarm(0);
9c50201998-03-26Fredrik Hübinette (Hubbe)  fprintf(stderr,"Failed in alarm handler 1\n");
c19f052002-09-02Henrik Grubbström (Grubba)  _exit(1);
9c50201998-03-26Fredrik Hübinette (Hubbe) }
bdfb861997-12-22Fredrik Hübinette (Hubbe)  int main()
5267b71995-08-09Fredrik Hübinette (Hubbe) {
3e84d61997-04-16Fredrik Hübinette (Hubbe)  int tmp[2];
5267b71995-08-09Fredrik Hübinette (Hubbe)  char foo[1000];
c19f052002-09-02Henrik Grubbström (Grubba)  int res = 0; int e = 0;
3e84d61997-04-16Fredrik Hübinette (Hubbe)  tmp[0]=0; tmp[1]=0;
9c50201998-03-26Fredrik Hübinette (Hubbe) #ifdef HAVE_SOCKETPAIR if(socketpair(AF_UNIX, SOCK_STREAM, 0, tmp) < 0) tmp[0]=tmp[1]=0; #endif
bdfb861997-12-22Fredrik Hübinette (Hubbe) 
3e84d61997-04-16Fredrik Hübinette (Hubbe)  set_nonblocking(tmp[0],1);
5267b71995-08-09Fredrik Hübinette (Hubbe)  signal(SIGALRM, sigalrm_handler1); alarm(1);
c19f052002-09-02Henrik Grubbström (Grubba)  res = read(tmp[0],foo,999); e = errno; alarm(0);
fad0d52002-09-03Henrik Grubbström (Grubba)  if ((res >= 0) || (e != EAGAIN)) {
c19f052002-09-02Henrik Grubbström (Grubba)  fprintf(stderr, "Unexpected behaviour of nonblocking read() res:%d, errno:%d\n", res, e); exit(1); } #ifdef SHORT_TEST /* Kludge for broken thread libraries. * eg: Solaris 2.4/-lthread */ exit(0); #endif /* SHORT_TEST */
3e84d61997-04-16Fredrik Hübinette (Hubbe)  set_nonblocking(tmp[0],0);
5267b71995-08-09Fredrik Hübinette (Hubbe)  signal(SIGALRM, sigalrm_handler0); alarm(1);
c19f052002-09-02Henrik Grubbström (Grubba)  res = read(tmp[0],foo,999); e = errno; fprintf(stderr,"Failed at end of main; res:%d, errno:%d\n", res, e);
5267b71995-08-09Fredrik Hübinette (Hubbe)  exit(1); } #endif
bdfb861997-12-22Fredrik Hübinette (Hubbe) #endif