(root)/
glibc-2.38/
sysdeps/
mach/
hurd/
accept4.c
       1  /* Copyright (C) 1992-2023 Free Software Foundation, Inc.
       2  
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; see the file COPYING.LIB.  If
      17     not, see <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <fcntl.h>
      21  #include <fcntl-internal.h>
      22  #include <string.h>
      23  #include <sys/socket.h>
      24  #include <hurd.h>
      25  #include <hurd/fd.h>
      26  #include <hurd/socket.h>
      27  #include <sysdep-cancel.h>
      28  
      29  /* Await a connection on socket FD.
      30     When a connection arrives, open a new socket to communicate with it,
      31     set *ADDRARG (which is *ADDR_LEN bytes long) to the address of the connecting
      32     peer and *ADDR_LEN to the address's actual length, and return the
      33     new socket's descriptor, or -1 for errors.  The operation can be influenced
      34     by the FLAGS parameter.  */
      35  int
      36  __libc_accept4 (int fd, __SOCKADDR_ARG addrarg, socklen_t *addr_len, int flags)
      37  {
      38    error_t err;
      39    socket_t new;
      40    addr_port_t aport;
      41    struct sockaddr *addr = addrarg.__sockaddr__;
      42    char *buf = (char *) addr;
      43    mach_msg_type_number_t buflen;
      44    int type;
      45    int cancel_oldtype;
      46  
      47    flags = sock_to_o_flags (flags);
      48  
      49    if (flags & ~(O_CLOEXEC | O_NONBLOCK))
      50      return __hurd_fail (EINVAL);
      51  
      52    cancel_oldtype = LIBC_CANCEL_ASYNC();
      53    err = HURD_DPORT_USE_CANCEL (fd, __socket_accept (port, &new, &aport));
      54    LIBC_CANCEL_RESET (cancel_oldtype);
      55    if (err)
      56      return __hurd_dfail (fd, err);
      57  
      58    if (addr != NULL)
      59      {
      60        buflen = *addr_len;
      61        err = __socket_whatis_address (aport, &type, &buf, &buflen);
      62        if (err == EOPNOTSUPP)
      63  	/* If the protocol server can't tell us the address, just return a
      64  	   zero-length one.  */
      65  	{
      66  	  buf = (char *)addr;
      67  	  buflen = 0;
      68  	  err = 0;
      69  	}
      70      }
      71    __mach_port_deallocate (__mach_task_self (), aport);
      72  
      73    if (! err)
      74      {
      75        if (flags & O_NONBLOCK)
      76  	err = __io_set_some_openmodes (new, O_NONBLOCK);
      77        /* TODO: do we need special ERR massaging after the previous call?  */
      78      }
      79  
      80    if (err)
      81      {
      82        __mach_port_deallocate (__mach_task_self (), new);
      83        return __hurd_dfail (fd, err);
      84      }
      85  
      86    if (addr != NULL)
      87      {
      88        if (*addr_len > buflen)
      89  	*addr_len = buflen;
      90  
      91        if (buf != (char *) addr)
      92  	{
      93  	  memcpy (addr, buf, *addr_len);
      94  	  __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen);
      95  	}
      96  
      97        if (buflen > 0)
      98  	addr->sa_family = type;
      99      }
     100  
     101    return _hurd_intern_fd (new, O_IGNORE_CTTY | flags, 1);
     102  }
     103  weak_alias (__libc_accept4, accept4)