Blame sysdeps/mach/hurd/socketpair.c

Packit Service 82fcde
/* Copyright (C) 1992-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <errno.h>
Packit Service 82fcde
#include <fcntl.h>
Packit Service 82fcde
#include <fcntl-internal.h>
Packit Service 82fcde
#include <sys/socket.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
Packit Service 82fcde
#include <hurd.h>
Packit Service 82fcde
#include <hurd/fd.h>
Packit Service 82fcde
#include <hurd/socket.h>
Packit Service 82fcde
Packit Service 82fcde
/* Create two new sockets, of type TYPE in domain DOMAIN and using
Packit Service 82fcde
   protocol PROTOCOL, which are connected to each other, and put file
Packit Service 82fcde
   descriptors for them in FDS[0] and FDS[1].  If PROTOCOL is zero,
Packit Service 82fcde
   one will be chosen automatically.  Returns 0 on success, -1 for errors.  */
Packit Service 82fcde
int
Packit Service 82fcde
__socketpair (int domain, int type, int protocol, int fds[2])
Packit Service 82fcde
{
Packit Service 82fcde
  error_t err;
Packit Service 82fcde
  socket_t server, sock1, sock2;
Packit Service 82fcde
  int d1, d2;
Packit Service 82fcde
  int flags = sock_to_o_flags (type & ~SOCK_TYPE_MASK);
Packit Service 82fcde
  type &= SOCK_TYPE_MASK;
Packit Service 82fcde
Packit Service 82fcde
  if (flags & ~(O_CLOEXEC | O_NONBLOCK))
Packit Service 82fcde
    return __hurd_fail (EINVAL);
Packit Service 82fcde
Packit Service 82fcde
  if (fds == NULL)
Packit Service 82fcde
    return __hurd_fail (EINVAL);
Packit Service 82fcde
Packit Service 82fcde
  /* Find the domain's socket server.  */
Packit Service 82fcde
  server = _hurd_socket_server (domain, 0);
Packit Service 82fcde
  if (server == MACH_PORT_NULL)
Packit Service 82fcde
    return -1;
Packit Service 82fcde
Packit Service 82fcde
  /* Create two sockets and connect them together.  */
Packit Service 82fcde
Packit Service 82fcde
  err = __socket_create (server, type, protocol, &sock1);
Packit Service 82fcde
  if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED
Packit Service 82fcde
      || err == MIG_BAD_ID || err == EOPNOTSUPP)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* On the first use of the socket server during the operation,
Packit Service 82fcde
	 allow for the old server port dying.  */
Packit Service 82fcde
      server = _hurd_socket_server (domain, 1);
Packit Service 82fcde
      if (server == MACH_PORT_NULL)
Packit Service 82fcde
	return -1;
Packit Service 82fcde
      err = __socket_create (server, type, protocol, &sock1);
Packit Service 82fcde
    }
Packit Service 82fcde
  /* TODO: do we need special ERR massaging here, like it is done in
Packit Service 82fcde
     __socket?  */
Packit Service 82fcde
  if (! err)
Packit Service 82fcde
    {
Packit Service 82fcde
      if (flags & O_NONBLOCK)
Packit Service 82fcde
	err = __io_set_some_openmodes (sock1, O_NONBLOCK);
Packit Service 82fcde
      /* TODO: do we need special ERR massaging after the previous call?  */
Packit Service 82fcde
    }
Packit Service 82fcde
  if (err)
Packit Service 82fcde
    return __hurd_fail (err);
Packit Service 82fcde
  if (err = __socket_create (server, type, protocol, &sock2))
Packit Service 82fcde
    {
Packit Service 82fcde
      __mach_port_deallocate (__mach_task_self (), sock1);
Packit Service 82fcde
      return __hurd_fail (err);
Packit Service 82fcde
    }
Packit Service 82fcde
  if (flags & O_NONBLOCK)
Packit Service 82fcde
    err = __io_set_some_openmodes (sock2, O_NONBLOCK);
Packit Service 82fcde
  /* TODO: do we need special ERR massaging after the previous call?  */
Packit Service 82fcde
  if (! err)
Packit Service 82fcde
    err = __socket_connect2 (sock1, sock2);
Packit Service 82fcde
  if (err)
Packit Service 82fcde
    {
Packit Service 82fcde
      __mach_port_deallocate (__mach_task_self (), sock1);
Packit Service 82fcde
      __mach_port_deallocate (__mach_task_self (), sock2);
Packit Service 82fcde
      return __hurd_fail (err);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Put the sockets into file descriptors.  */
Packit Service 82fcde
Packit Service 82fcde
  d1 = _hurd_intern_fd (sock1, O_IGNORE_CTTY | flags, 1);
Packit Service 82fcde
  if (d1 < 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      __mach_port_deallocate (__mach_task_self (), sock2);
Packit Service 82fcde
      return -1;
Packit Service 82fcde
    }
Packit Service 82fcde
  d2 = _hurd_intern_fd (sock2, O_IGNORE_CTTY | flags, 1);
Packit Service 82fcde
  if (d2 < 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      err = errno;
Packit Service 82fcde
      (void) __close (d1);
Packit Service 82fcde
      return __hurd_fail (err);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  fds[0] = d1;
Packit Service 82fcde
  fds[1] = d2;
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
weak_alias (__socketpair, socketpair)