libc/winsup/cygwin/net.cc

2435 lines
56 KiB
C++
Raw Normal View History

2000-02-17 20:38:33 +01:00
/* net.cc: network-related routines.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
2000-02-17 20:38:33 +01:00
This file is part of Cygwin.
This software is a copyrighted work licensed under the terms of the
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
details. */
/* #define DEBUG_NEST_ON 1 */
#define __INSIDE_CYGWIN_NET__
#include "winsup.h"
2000-02-17 20:38:33 +01:00
#include <errno.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <iphlpapi.h>
2000-02-17 20:38:33 +01:00
#include <stdlib.h>
* include/cygwin/version.h: Bump DLL minor version number to 5 due to all of the changes below. Redefine process structure to avoid a fixed size table. Redefine pinfo/_pinfo classes. Use these throughout. * dcrt0.cc (dll_crt0_1): Accomodate set_myself argument change. (__api_fatal): Accomodate _pinfo::record_death argument change. * exceptions.cc (really_exit): Ditto. (sig_handle_tty_stop): Use pinfo constructor to access process info. (events_init): Don't create pinfo_mutex since it is no longer required. * external.cc (fillout_pinfo): Use winpids class to iterate over all system pids. (cygwin_internal): lock_pinfo_for_update and unlock_pinfo are now noops. * fhandler_termios.cc (fhandler_termios::set_ctty): Use pinfo constructor to access process info. * fork.cc (fork): Reorganize to initialize child info after the child has started since that is when we know the child's winpid, which is necessary to allocate the pinfo shared memory. * mmap.cc (recreate_mmaps_after_fork): Change arg type to _pinfo. * pinfo.cc: Rename pinfo methods to _pinfo throughout. Eliminate pinfo_list stuff. (set_myself): Accept a pid argument now. Call pinfo initializer to initialize myself. Detect when this is an "execed" process and create an "indirect" pid block. (pinfo_init): Accomodate set_myself arg change. (procinfo): Remove. (pinfo::lock_pinfo): Remove. (pinfo::unlock_pinfo): Remove. (pinfo::init): New method. Allocates shared memory space for process pinfo structure. (pinfo::record_death): Don't call locking functions. (cygwin_winpid_to_pid): Simplify by using new pinfo constructor. (EnumProcessesW95): New function for iterating over processes on Windows 95. (winpids::winpids): New constructor for winpids class. Sets up a list of process ids. (enum_init): Initialize w95/wnt pid enumerators. * shared.cc (shared-info::initialize): Remove pid initialization. * shared.h: Move pinfo stuff into pinfo.h. (class shared_info): Remove pinfo_list element. * signal.cc (kill_worker): Use pinfo constructor to access process info. (kill_pgrp): Ditto. Use winpids methods to access list of processes. * sigproc.cc: Throughout, modify to use _pinfo where appropriate. (proc_exists (pid_t)): New function. Determines if a process exists based on the pid. (proc_exists (_pinfo *p): Use new proc_exists function above. (proc_subproc): Copy pinfo stuff around rather than _pinfo pointers. Try to be careful about releasing shared memory when we don't need it anymore. Remove pinfo locks. (remove_zombies): Remove pinfo memory when zombie is going away. * sigproc.h: Reflect _pinfo/pinfo changes in sigproc.cc. * spawn.cc (spawn_guts): Eliminate pinfo *child argument. Reorganize to only initialize child pinfo after process has been started and we know the windows pid. (_spawnve): Reflect spawn_guts changes. * syscalls.cc (setpgid): Use pinfo constructor to access process info. (getpgid): Ditto. (internal_getlogin): Use _pinfo. * winsup.h: Eliminate pinfo_mutex. Eliminate spawn_guts declaration since it is static now. Reflect set_myself argument change. * include/sys/cygwin.h: Add some PID_* enums to accomodate new pinfo stuff. * include/cygwin/version.h: Update minor version for cygdrive changes below.
2000-07-29 18:24:59 +02:00
#include <unistd.h>
2000-02-17 20:38:33 +01:00
#include <netdb.h>
#include <fcntl.h>
#define USE_SYS_TYPES_FD_SET
* dtable.cc (dtable::release): Check for socket. Change cnt_need_fixup_before accordingly. (dtable::dup2): Ditto. (dtable::fixup_before_fork): New method. (dtable::fixup_before_exec): Ditto. * dtable.h (class dtable): Add member `cnt_need_fixup_before'. Add definition for methods `dec_need_fixup_before', `inc_need_fixup_before', `need_fixup_before', `fixup_before_exec' and `fixup_before_fork'. * fhandler.h (class fhandler_base): Slight rearrangements. Add definitions for methods `fixup_before_fork_exec'. (class fhandler_socket): Eliminate superfluous constructor. Add member `prot_info_ptr'. Add destructor. Add definitions for methods `dup', `fixup_before_fork_exec', `fixup_after_fork' and `fixup_after_exec'. * fork.cc (fork_parent): Care for file types which need a fixup before fork. Start child in suspended state then. * net.cc: New global variable `ws2_32_handle' and `wsadata'. (fdsock): Check for Winsock version. Call `set_socket_inheritance' only if Winsock version < 2.0. Care for `need_fixup' count in fdtab. (cygwin_socket): Eliminate call to `set_socket_inheritance'. (cygwin_accept): Ditto. (cygwin_rcmd): Ditto. (cygwin_rresvport): Ditto. (cygwin_rexec): Ditto. (socketpair): Ditto. (fhandler_socket::fhandler_socket): Set `need_fork_fixup'. Allocate space for the WSAPROTOCOL_INFOA struct used in fixup. (fhandler_socket::~fhandler_socket): New destructor. (fhandler_socket::fixup_before_fork_exec): New method. (fhandler_socket::fixup_after_fork): Ditto. (fhandler_socket::dup): Ditto. (wsock_init): New static function. (LoadDLLinitfunc (wsock32)): Rearranged. (LoadDLLinitfunc (ws2_32)): New function. (dummy_autoload): Add autoload statemants for `WSADuplicateSocketA' and `WSASocketA'. * spawn.cc (spawn_guts): Care for file types which need a fixup before exec. Start child in suspended state then.
2000-10-26 12:13:41 +02:00
#include <winsock2.h>
#include "cygerrno.h"
#include "security.h"
#include "fhandler.h"
#include "path.h"
#include "dtable.h"
#include "cygheap.h"
#include "sync.h"
#include "sigproc.h"
#include "pinfo.h"
#include "registry.h"
2000-02-17 20:38:33 +01:00
extern "C" {
2000-02-17 20:38:33 +01:00
int h_errno;
int __stdcall rcmd (char **ahost, unsigned short inport, char *locuser,
char *remuser, char *cmd, SOCKET *fd2p);
int __stdcall rexec (char **ahost, unsigned short inport, char *locuser,
char *password, char *cmd, SOCKET *fd2p);
int __stdcall rresvport (int *);
int sscanf (const char *, const char *, ...);
} /* End of "C" section */
class wsock_event
{
WSAEVENT event;
WSAOVERLAPPED ovr;
public:
wsock_event () : event (NULL) {};
~wsock_event ()
{
if (event)
WSACloseEvent (event);
event = NULL;
};
LPWSAOVERLAPPED prepare ();
int wait (int socket, LPDWORD flags);
};
LPWSAOVERLAPPED
wsock_event::prepare ()
{
LPWSAOVERLAPPED ret = NULL;
SetLastError (0);
if ((event = WSACreateEvent ()) != WSA_INVALID_EVENT)
{
memset (&ovr, 0, sizeof ovr);
ovr.hEvent = event;
ret = &ovr;
}
else if (GetLastError () == ERROR_PROC_NOT_FOUND) /* winsock2 not available */
WSASetLastError (0);
debug_printf ("%d = wsock_event::prepare ()", ret);
return ret;
}
int
wsock_event::wait (int socket, LPDWORD flags)
{
int ret = -1;
WSAEVENT ev[2] = { event, signal_arrived };
switch (WSAWaitForMultipleEvents(2, ev, FALSE, WSA_INFINITE, FALSE))
{
case WSA_WAIT_EVENT_0:
DWORD len;
if (WSAGetOverlappedResult(socket, &ovr, &len, FALSE, flags))
ret = (int) len;
break;
case WSA_WAIT_EVENT_0 + 1:
if (!CancelIo ((HANDLE)socket))
{
debug_printf ("CancelIo() %E, fallback to blocking io");
WSAGetOverlappedResult(socket, &ovr, &len, TRUE, flags);
}
else
WSASetLastError (WSAEINTR);
break;
case WSA_WAIT_FAILED:
break;
default: /* Should be impossible. *LOL* */
WSASetLastError (WSAEFAULT);
break;
}
WSACloseEvent (event);
event = NULL;
return ret;
}
WSADATA wsadata;
* dtable.cc (dtable::release): Check for socket. Change cnt_need_fixup_before accordingly. (dtable::dup2): Ditto. (dtable::fixup_before_fork): New method. (dtable::fixup_before_exec): Ditto. * dtable.h (class dtable): Add member `cnt_need_fixup_before'. Add definition for methods `dec_need_fixup_before', `inc_need_fixup_before', `need_fixup_before', `fixup_before_exec' and `fixup_before_fork'. * fhandler.h (class fhandler_base): Slight rearrangements. Add definitions for methods `fixup_before_fork_exec'. (class fhandler_socket): Eliminate superfluous constructor. Add member `prot_info_ptr'. Add destructor. Add definitions for methods `dup', `fixup_before_fork_exec', `fixup_after_fork' and `fixup_after_exec'. * fork.cc (fork_parent): Care for file types which need a fixup before fork. Start child in suspended state then. * net.cc: New global variable `ws2_32_handle' and `wsadata'. (fdsock): Check for Winsock version. Call `set_socket_inheritance' only if Winsock version < 2.0. Care for `need_fixup' count in fdtab. (cygwin_socket): Eliminate call to `set_socket_inheritance'. (cygwin_accept): Ditto. (cygwin_rcmd): Ditto. (cygwin_rresvport): Ditto. (cygwin_rexec): Ditto. (socketpair): Ditto. (fhandler_socket::fhandler_socket): Set `need_fork_fixup'. Allocate space for the WSAPROTOCOL_INFOA struct used in fixup. (fhandler_socket::~fhandler_socket): New destructor. (fhandler_socket::fixup_before_fork_exec): New method. (fhandler_socket::fixup_after_fork): Ditto. (fhandler_socket::dup): Ditto. (wsock_init): New static function. (LoadDLLinitfunc (wsock32)): Rearranged. (LoadDLLinitfunc (ws2_32)): New function. (dummy_autoload): Add autoload statemants for `WSADuplicateSocketA' and `WSASocketA'. * spawn.cc (spawn_guts): Care for file types which need a fixup before exec. Start child in suspended state then.
2000-10-26 12:13:41 +02:00
/* Cygwin internal */
static fhandler_socket *
get (int fd)
{
cygheap_fdget cfd (fd);
if (cfd < 0)
return 0;
return cfd->is_socket ();
}
2000-02-17 20:38:33 +01:00
/* Cygwin internal */
static SOCKET __stdcall
set_socket_inheritance (SOCKET sock)
2000-02-17 20:38:33 +01:00
{
SOCKET osock = sock;
if (!DuplicateHandle (hMainProc, (HANDLE) sock, hMainProc, (HANDLE *) &sock,
0, TRUE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
system_printf ("DuplicateHandle failed %E");
else
debug_printf ("DuplicateHandle succeeded osock %p, sock %p", osock, sock);
2000-02-17 20:38:33 +01:00
return sock;
}
/* htonl: standards? */
extern "C" unsigned long int
2000-02-17 20:38:33 +01:00
htonl (unsigned long int x)
{
return ((((x & 0x000000ffU) << 24) |
((x & 0x0000ff00U) << 8) |
((x & 0x00ff0000U) >> 8) |
((x & 0xff000000U) >> 24)));
}
/* ntohl: standards? */
extern "C" unsigned long int
2000-02-17 20:38:33 +01:00
ntohl (unsigned long int x)
{
return htonl (x);
}
/* htons: standards? */
extern "C" unsigned short
2000-02-17 20:38:33 +01:00
htons (unsigned short x)
{
return ((((x & 0x000000ffU) << 8) |
((x & 0x0000ff00U) >> 8)));
}
/* ntohs: standards? */
extern "C" unsigned short
2000-02-17 20:38:33 +01:00
ntohs (unsigned short x)
{
return htons (x);
}
/* Cygwin internal */
static void
dump_protoent (struct protoent *p)
{
if (p)
debug_printf ("protoent %s %x %x", p->p_name, p->p_aliases, p->p_proto);
}
/* exported as inet_ntoa: BSD 4.3 */
extern "C" char *
2000-02-17 20:38:33 +01:00
cygwin_inet_ntoa (struct in_addr in)
{
#ifdef _MT_SAFE
#define ntoa_buf _reent_winsup ()->_ntoa_buf
#else
static char *ntoa_buf = NULL;
#endif
2000-02-17 20:38:33 +01:00
char *res = inet_ntoa (in);
if (ntoa_buf)
{
free (ntoa_buf);
ntoa_buf = NULL;
}
if (res)
ntoa_buf = strdup (res);
return ntoa_buf;
2000-02-17 20:38:33 +01:00
}
/* exported as inet_addr: BSD 4.3 */
extern "C" unsigned long
2000-02-17 20:38:33 +01:00
cygwin_inet_addr (const char *cp)
{
if (check_null_str_errno (cp))
return INADDR_NONE;
2000-02-17 20:38:33 +01:00
unsigned long res = inet_addr (cp);
return res;
}
/* exported as inet_aton: BSD 4.3
inet_aton is not exported by wsock32 and ws2_32,
so it has to be implemented here. */
extern "C" int
cygwin_inet_aton (const char *cp, struct in_addr *inp)
{
if (check_null_str_errno (cp) || check_null_invalid_struct_errno (inp))
return 0;
unsigned long res = inet_addr (cp);
if (res == INADDR_NONE && strcmp (cp, "255.255.255.255"))
return 0;
if (inp)
inp->s_addr = res;
return 1;
}
/* undocumented in wsock32.dll */
extern "C" unsigned int WINAPI inet_network (const char *);
extern "C" unsigned int
cygwin_inet_network (const char *cp)
{
if (check_null_str_errno (cp))
return INADDR_NONE;
unsigned int res = inet_network (cp);
return res;
}
2000-02-17 20:38:33 +01:00
/* inet_netof is in the standard BSD sockets library. It is useless
for modern networks, since it assumes network values which are no
longer meaningful, but some existing code calls it. */
extern "C" unsigned long
2000-02-17 20:38:33 +01:00
inet_netof (struct in_addr in)
{
unsigned long i, res;
i = ntohl (in.s_addr);
if (IN_CLASSA (i))
res = (i & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT;
else if (IN_CLASSB (i))
res = (i & IN_CLASSB_NET) >> IN_CLASSB_NSHIFT;
else
res = (i & IN_CLASSC_NET) >> IN_CLASSC_NSHIFT;
return res;
}
/* inet_makeaddr is in the standard BSD sockets library. It is
useless for modern networks, since it assumes network values which
are no longer meaningful, but some existing code calls it. */
extern "C" struct in_addr
2000-02-17 20:38:33 +01:00
inet_makeaddr (int net, int lna)
{
unsigned long i;
struct in_addr in;
2000-02-17 20:38:33 +01:00
if (net < IN_CLASSA_MAX)
i = (net << IN_CLASSA_NSHIFT) | (lna & IN_CLASSA_HOST);
else if (net < IN_CLASSB_MAX)
i = (net << IN_CLASSB_NSHIFT) | (lna & IN_CLASSB_HOST);
else if (net < 0x1000000)
i = (net << IN_CLASSC_NSHIFT) | (lna & IN_CLASSC_HOST);
else
i = net | lna;
in.s_addr = htonl (i);
return in;
}
struct tl
{
int w;
const char *s;
int e;
};
static NO_COPY struct tl errmap[] =
2000-02-17 20:38:33 +01:00
{
{WSAEINTR, "WSAEINTR", EINTR},
2000-02-17 20:38:33 +01:00
{WSAEWOULDBLOCK, "WSAEWOULDBLOCK", EWOULDBLOCK},
{WSAEINPROGRESS, "WSAEINPROGRESS", EINPROGRESS},
{WSAEALREADY, "WSAEALREADY", EALREADY},
{WSAENOTSOCK, "WSAENOTSOCK", ENOTSOCK},
{WSAEDESTADDRREQ, "WSAEDESTADDRREQ", EDESTADDRREQ},
{WSAEMSGSIZE, "WSAEMSGSIZE", EMSGSIZE},
{WSAEPROTOTYPE, "WSAEPROTOTYPE", EPROTOTYPE},
{WSAENOPROTOOPT, "WSAENOPROTOOPT", ENOPROTOOPT},
{WSAEPROTONOSUPPORT, "WSAEPROTONOSUPPORT", EPROTONOSUPPORT},
{WSAESOCKTNOSUPPORT, "WSAESOCKTNOSUPPORT", ESOCKTNOSUPPORT},
{WSAEOPNOTSUPP, "WSAEOPNOTSUPP", EOPNOTSUPP},
{WSAEPFNOSUPPORT, "WSAEPFNOSUPPORT", EPFNOSUPPORT},
{WSAEAFNOSUPPORT, "WSAEAFNOSUPPORT", EAFNOSUPPORT},
{WSAEADDRINUSE, "WSAEADDRINUSE", EADDRINUSE},
{WSAEADDRNOTAVAIL, "WSAEADDRNOTAVAIL", EADDRNOTAVAIL},
{WSAENETDOWN, "WSAENETDOWN", ENETDOWN},
{WSAENETUNREACH, "WSAENETUNREACH", ENETUNREACH},
{WSAENETRESET, "WSAENETRESET", ENETRESET},
{WSAECONNABORTED, "WSAECONNABORTED", ECONNABORTED},
{WSAECONNRESET, "WSAECONNRESET", ECONNRESET},
{WSAENOBUFS, "WSAENOBUFS", ENOBUFS},
{WSAEISCONN, "WSAEISCONN", EISCONN},
{WSAENOTCONN, "WSAENOTCONN", ENOTCONN},
{WSAESHUTDOWN, "WSAESHUTDOWN", ESHUTDOWN},
{WSAETOOMANYREFS, "WSAETOOMANYREFS", ETOOMANYREFS},
{WSAETIMEDOUT, "WSAETIMEDOUT", ETIMEDOUT},
{WSAECONNREFUSED, "WSAECONNREFUSED", ECONNREFUSED},
{WSAELOOP, "WSAELOOP", ELOOP},
{WSAENAMETOOLONG, "WSAENAMETOOLONG", ENAMETOOLONG},
{WSAEHOSTDOWN, "WSAEHOSTDOWN", EHOSTDOWN},
{WSAEHOSTUNREACH, "WSAEHOSTUNREACH", EHOSTUNREACH},
{WSAENOTEMPTY, "WSAENOTEMPTY", ENOTEMPTY},
{WSAEPROCLIM, "WSAEPROCLIM", EPROCLIM},
{WSAEUSERS, "WSAEUSERS", EUSERS},
{WSAEDQUOT, "WSAEDQUOT", EDQUOT},
{WSAESTALE, "WSAESTALE", ESTALE},
{WSAEREMOTE, "WSAEREMOTE", EREMOTE},
{WSAEINVAL, "WSAEINVAL", EINVAL},
{WSAEFAULT, "WSAEFAULT", EFAULT},
{0, "NOERROR", 0},
{0, NULL, 0}
2000-02-17 20:38:33 +01:00
};
static int
find_winsock_errno (int why)
{
for (int i = 0; errmap[i].s != NULL; ++i)
if (why == errmap[i].w)
return errmap[i].e;
return EPERM;
}
2000-02-17 20:38:33 +01:00
/* Cygwin internal */
void
__set_winsock_errno (const char *fn, int ln)
2000-02-17 20:38:33 +01:00
{
DWORD werr = WSAGetLastError ();
int err = find_winsock_errno (werr);
set_errno (err);
syscall_printf ("%s:%d - winsock error %d -> errno %d", fn, ln, werr, err);
2000-02-17 20:38:33 +01:00
}
/*
* Since the member `s' isn't used for debug output we can use it
* for the error text returned by herror and hstrerror.
*/
static NO_COPY struct tl host_errmap[] =
2000-02-17 20:38:33 +01:00
{
{WSAHOST_NOT_FOUND, "Unknown host", HOST_NOT_FOUND},
{WSATRY_AGAIN, "Host name lookup failure", TRY_AGAIN},
{WSANO_RECOVERY, "Unknown server error", NO_RECOVERY},
{WSANO_DATA, "No address associated with name", NO_DATA},
{0, NULL, 0}
2000-02-17 20:38:33 +01:00
};
/* Cygwin internal */
static void
set_host_errno ()
{
int i;
int why = WSAGetLastError ();
for (i = 0; host_errmap[i].w != 0; ++i)
2000-02-17 20:38:33 +01:00
if (why == host_errmap[i].w)
break;
if (host_errmap[i].w != 0)
h_errno = host_errmap[i].e;
else
h_errno = NETDB_INTERNAL;
}
static void
free_char_list (char **clist)
{
if (clist)
{
for (char **cl = clist; *cl; ++cl)
free (*cl);
free (clist);
}
}
static char **
dup_char_list (char **src)
{
char **dst;
int cnt = 0;
for (char **cl = src; *cl; ++cl)
++cnt;
if (!(dst = (char **) calloc (cnt + 1, sizeof *dst)))
return NULL;
while (cnt-- > 0)
if (!(dst[cnt] = strdup (src[cnt])))
return NULL;
return dst;
}
#define free_addr_list(addr_list) free_char_list (addr_list)
static char **
dup_addr_list (char **src, unsigned int size)
{
char **dst;
int cnt = 0;
for (char **cl = src; *cl; ++cl)
++cnt;
if (!(dst = (char **) calloc (cnt + 1, sizeof *dst)))
return NULL;
while (cnt-- > 0)
{
if (!(dst[cnt] = (char *) malloc(size)))
return NULL;
memcpy(dst[cnt], src[cnt], size);
}
return dst;
}
static void
free_protoent_ptr (struct protoent *&p)
{
if (p)
{
debug_printf ("protoent: %s", p->p_name);
if (p->p_name)
free (p->p_name);
free_char_list (p->p_aliases);
p = NULL;
}
}
static struct protoent *
dup_protoent_ptr (struct protoent *src)
{
if (!src)
return NULL;
struct protoent *dst = (struct protoent *) calloc (1, sizeof *dst);
if (!dst)
return NULL;
debug_printf ("protoent: %s", src->p_name);
dst->p_proto = src->p_proto;
if (src->p_name && !(dst->p_name = strdup (src->p_name)))
goto out;
if (src->p_aliases && !(dst->p_aliases = dup_char_list (src->p_aliases)))
goto out;
debug_printf ("protoent: copied %s", dst->p_name);
return dst;
out:
free_protoent_ptr (dst);
return NULL;
}
#ifdef _MT_SAFE
#define protoent_buf _reent_winsup ()->_protoent_buf
#else
static struct protoent *protoent_buf = NULL;
#endif
2000-02-17 20:38:33 +01:00
/* exported as getprotobyname: standards? */
extern "C" struct protoent *
2000-02-17 20:38:33 +01:00
cygwin_getprotobyname (const char *p)
{
if (check_null_str_errno (p))
return NULL;
free_protoent_ptr (protoent_buf);
protoent_buf = dup_protoent_ptr (getprotobyname (p));
if (!protoent_buf)
2000-02-17 20:38:33 +01:00
set_winsock_errno ();
dump_protoent (protoent_buf);
return protoent_buf;
2000-02-17 20:38:33 +01:00
}
/* exported as getprotobynumber: standards? */
extern "C" struct protoent *
2000-02-17 20:38:33 +01:00
cygwin_getprotobynumber (int number)
{
free_protoent_ptr (protoent_buf);
protoent_buf = dup_protoent_ptr (getprotobynumber (number));
if (!protoent_buf)
2000-02-17 20:38:33 +01:00
set_winsock_errno ();
dump_protoent (protoent_buf);
return protoent_buf;
2000-02-17 20:38:33 +01:00
}
fhandler_socket *
fdsock (int& fd, const char *name, SOCKET soc)
2000-02-17 20:38:33 +01:00
{
if (!winsock2_active)
* dtable.cc (dtable::release): Check for socket. Change cnt_need_fixup_before accordingly. (dtable::dup2): Ditto. (dtable::fixup_before_fork): New method. (dtable::fixup_before_exec): Ditto. * dtable.h (class dtable): Add member `cnt_need_fixup_before'. Add definition for methods `dec_need_fixup_before', `inc_need_fixup_before', `need_fixup_before', `fixup_before_exec' and `fixup_before_fork'. * fhandler.h (class fhandler_base): Slight rearrangements. Add definitions for methods `fixup_before_fork_exec'. (class fhandler_socket): Eliminate superfluous constructor. Add member `prot_info_ptr'. Add destructor. Add definitions for methods `dup', `fixup_before_fork_exec', `fixup_after_fork' and `fixup_after_exec'. * fork.cc (fork_parent): Care for file types which need a fixup before fork. Start child in suspended state then. * net.cc: New global variable `ws2_32_handle' and `wsadata'. (fdsock): Check for Winsock version. Call `set_socket_inheritance' only if Winsock version < 2.0. Care for `need_fixup' count in fdtab. (cygwin_socket): Eliminate call to `set_socket_inheritance'. (cygwin_accept): Ditto. (cygwin_rcmd): Ditto. (cygwin_rresvport): Ditto. (cygwin_rexec): Ditto. (socketpair): Ditto. (fhandler_socket::fhandler_socket): Set `need_fork_fixup'. Allocate space for the WSAPROTOCOL_INFOA struct used in fixup. (fhandler_socket::~fhandler_socket): New destructor. (fhandler_socket::fixup_before_fork_exec): New method. (fhandler_socket::fixup_after_fork): Ditto. (fhandler_socket::dup): Ditto. (wsock_init): New static function. (LoadDLLinitfunc (wsock32)): Rearranged. (LoadDLLinitfunc (ws2_32)): New function. (dummy_autoload): Add autoload statemants for `WSADuplicateSocketA' and `WSASocketA'. * spawn.cc (spawn_guts): Care for file types which need a fixup before exec. Start child in suspended state then.
2000-10-26 12:13:41 +02:00
soc = set_socket_inheritance (soc);
else
debug_printf ("not setting socket inheritance since winsock2_active %d", winsock2_active);
fhandler_socket *fh = (fhandler_socket *) cygheap->fdtab.build_fhandler (fd, FH_SOCKET, name);
2000-02-17 20:38:33 +01:00
fh->set_io_handle ((HANDLE) soc);
fh->set_flags (O_RDWR);
fh->set_name (name, name);
debug_printf ("fd %d, name '%s', soc %p", fd, name, soc);
return fh;
2000-02-17 20:38:33 +01:00
}
/* exported as socket: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_socket (int af, int type, int protocol)
{
int res = -1;
SOCKET soc = 0;
2000-02-17 20:38:33 +01:00
cygheap_fdnew fd;
2000-02-17 20:38:33 +01:00
if (fd >= 0)
2000-02-17 20:38:33 +01:00
{
debug_printf ("socket (%d, %d, %d)", af, type, protocol);
soc = socket (AF_INET, type, af == AF_UNIX ? 0 : protocol);
2000-02-17 20:38:33 +01:00
if (soc == INVALID_SOCKET)
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
{
set_winsock_errno ();
goto done;
}
2000-02-17 20:38:33 +01:00
const char *name;
if (af == AF_INET)
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
name = (type == SOCK_STREAM ? "/dev/tcp" : "/dev/udp");
2000-02-17 20:38:33 +01:00
else
name = (type == SOCK_STREAM ? "/dev/streamsocket" : "/dev/dgsocket");
2000-02-17 20:38:33 +01:00
fdsock (fd, name, soc)->set_addr_family (af);
2000-02-17 20:38:33 +01:00
res = fd;
}
done:
syscall_printf ("%d = socket (%d, %d, %d)", res, af, type, protocol);
return res;
}
/* cygwin internal: map sockaddr into internet domain address */
static int get_inet_addr (const struct sockaddr *in, int inlen,
struct sockaddr_in *out, int *outlen, int* secret = 0)
2000-02-17 20:38:33 +01:00
{
int secret_buf [4];
int* secret_ptr = (secret ? : secret_buf);
2000-02-17 20:38:33 +01:00
if (in->sa_family == AF_INET)
{
*out = * (sockaddr_in *)in;
*outlen = inlen;
return 1;
}
else if (in->sa_family == AF_UNIX)
{
int fd = _open (in->sa_data, O_RDONLY);
2000-02-17 20:38:33 +01:00
if (fd == -1)
return 0;
int ret = 0;
char buf[128];
memset (buf, 0, sizeof buf);
if (read (fd, buf, sizeof buf) != -1)
{
sockaddr_in sin;
sin.sin_family = AF_INET;
sscanf (buf + strlen (SOCKET_COOKIE), "%hu %08x-%08x-%08x-%08x",
&sin.sin_port,
secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3);
sin.sin_port = htons (sin.sin_port);
sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
*out = sin;
*outlen = sizeof sin;
ret = 1;
}
_close (fd);
return ret;
2000-02-17 20:38:33 +01:00
}
else
{
set_errno (EAFNOSUPPORT);
return 0;
}
}
/* exported as sendto: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_sendto (int fd,
const void *buf,
int len,
unsigned int flags,
const struct sockaddr *to,
int tolen)
2000-02-17 20:38:33 +01:00
{
int res;
wsock_event wsock_evt;
LPWSAOVERLAPPED ovr;
fhandler_socket *h = get (fd);
2000-02-17 20:38:33 +01:00
if ((len && __check_invalid_read_ptr_errno (buf, (unsigned) len))
|| __check_null_invalid_struct_errno (to, tolen)
|| !h)
res = -1;
else
2000-02-17 20:38:33 +01:00
{
sockaddr_in sin;
sigframe thisframe (mainthread);
if (get_inet_addr (to, tolen, &sin, &tolen) == 0)
return -1;
if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
{
debug_printf ("Fallback to winsock 1 sendto call");
if ((res = sendto (h->get_socket (), (const char *) buf, len, flags,
(sockaddr *) &sin, tolen)) == SOCKET_ERROR)
{
set_winsock_errno ();
res = -1;
}
}
else
{
WSABUF wsabuf = { len, (char *) buf };
DWORD ret = 0;
if (WSASendTo (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags,
(sockaddr *) &sin, tolen, ovr, NULL) != SOCKET_ERROR)
res = ret;
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
{
set_winsock_errno ();
res = -1;
}
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
set_winsock_errno ();
}
2000-02-17 20:38:33 +01:00
}
syscall_printf ("%d = sendto (%d, %x, %x, %x)", res, fd, buf, len, flags);
2000-02-17 20:38:33 +01:00
return res;
}
/* exported as recvfrom: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_recvfrom (int fd,
char *buf,
int len,
int flags,
struct sockaddr *from,
int *fromlen)
{
int res;
wsock_event wsock_evt;
LPWSAOVERLAPPED ovr;
fhandler_socket *h = get (fd);
2000-02-17 20:38:33 +01:00
if (__check_null_invalid_struct_errno (buf, (unsigned) len)
|| check_null_invalid_struct_errno (fromlen)
|| (from && __check_null_invalid_struct_errno (from, (unsigned) *fromlen))
|| !h)
res = -1;
else
2000-02-17 20:38:33 +01:00
{
sigframe thisframe (mainthread);
if (h->is_nonblocking () ||!(ovr = wsock_evt.prepare ()))
{
debug_printf ("Fallback to winsock 1 recvfrom call");
if ((res = recvfrom (h->get_socket (), buf, len, flags, from, fromlen))
== SOCKET_ERROR)
{
set_winsock_errno ();
res = -1;
}
}
else
{
WSABUF wsabuf = { len, (char *) buf };
DWORD ret = 0;
if (WSARecvFrom (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags,
from, fromlen, ovr, NULL) != SOCKET_ERROR)
res = ret;
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
{
set_winsock_errno ();
res = -1;
}
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
set_winsock_errno ();
}
2000-02-17 20:38:33 +01:00
}
syscall_printf ("%d = recvfrom (%d, %x, %x, %x)", res, fd, buf, len, flags);
2000-02-17 20:38:33 +01:00
return res;
}
/* exported as setsockopt: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_setsockopt (int fd,
int level,
int optname,
const void *optval,
int optlen)
{
fhandler_socket *h = get (fd);
int res = -1;
const char *name = "error";
if ((!optval || !__check_invalid_read_ptr_errno (optval, optlen)) && h)
2000-02-17 20:38:33 +01:00
{
/* For the following debug_printf */
switch (optname)
{
case SO_DEBUG:
name="SO_DEBUG";
break;
case SO_ACCEPTCONN:
name="SO_ACCEPTCONN";
break;
case SO_REUSEADDR:
name="SO_REUSEADDR";
break;
case SO_KEEPALIVE:
name="SO_KEEPALIVE";
break;
case SO_DONTROUTE:
name="SO_DONTROUTE";
break;
case SO_BROADCAST:
name="SO_BROADCAST";
break;
case SO_USELOOPBACK:
name="SO_USELOOPBACK";
break;
case SO_LINGER:
name="SO_LINGER";
break;
case SO_OOBINLINE:
name="SO_OOBINLINE";
break;
case SO_ERROR:
name="SO_ERROR";
break;
2000-02-17 20:38:33 +01:00
}
res = setsockopt (h->get_socket (), level, optname,
(const char *) optval, optlen);
if (optlen == 4)
syscall_printf ("setsockopt optval=%x", *(long *) optval);
if (res)
set_winsock_errno ();
}
syscall_printf ("%d = setsockopt (%d, %d, %x (%s), %x, %d)",
res, fd, level, optname, name, optval, optlen);
return res;
}
/* exported as getsockopt: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_getsockopt (int fd,
int level,
int optname,
void *optval,
int *optlen)
{
fhandler_socket *h = get (fd);
int res = -1;
const char *name = "error";
if (!check_null_invalid_struct_errno (optlen)
&& (!optval || !__check_null_invalid_struct_errno (optval, (unsigned) *optlen))
&& h)
2000-02-17 20:38:33 +01:00
{
/* For the following debug_printf */
switch (optname)
{
case SO_DEBUG:
name="SO_DEBUG";
break;
case SO_ACCEPTCONN:
name="SO_ACCEPTCONN";
break;
case SO_REUSEADDR:
name="SO_REUSEADDR";
break;
case SO_KEEPALIVE:
name="SO_KEEPALIVE";
break;
case SO_DONTROUTE:
name="SO_DONTROUTE";
break;
case SO_BROADCAST:
name="SO_BROADCAST";
break;
case SO_USELOOPBACK:
name="SO_USELOOPBACK";
break;
case SO_LINGER:
name="SO_LINGER";
break;
case SO_OOBINLINE:
name="SO_OOBINLINE";
break;
case SO_ERROR:
name="SO_ERROR";
break;
2000-02-17 20:38:33 +01:00
}
res = getsockopt (h->get_socket (), level, optname,
(char *) optval, (int *) optlen);
if (optname == SO_ERROR)
{
int *e = (int *) optval;
*e = find_winsock_errno (*e);
}
2000-02-17 20:38:33 +01:00
if (res)
set_winsock_errno ();
}
syscall_printf ("%d = getsockopt (%d, %d, %x (%s), %x, %d)",
res, fd, level, optname, name, optval, optlen);
return res;
}
/* exported as connect: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_connect (int fd,
const struct sockaddr *name,
int namelen)
{
int res;
BOOL secret_check_failed = FALSE;
BOOL in_progress = FALSE;
2000-02-17 20:38:33 +01:00
fhandler_socket *sock = get (fd);
sockaddr_in sin;
int secret [4];
sigframe thisframe (mainthread);
2000-02-17 20:38:33 +01:00
if (__check_invalid_read_ptr_errno (name, namelen))
return -1;
if (get_inet_addr (name, namelen, &sin, &namelen, secret) == 0)
2000-02-17 20:38:33 +01:00
return -1;
if (!sock)
res = -1;
2000-02-17 20:38:33 +01:00
else
{
res = connect (sock->get_socket (), (sockaddr *) &sin, namelen);
if (res)
{
/* Special handling for connect to return the correct error code
when called on a non-blocking socket. */
if (sock->is_nonblocking ())
{
DWORD err = WSAGetLastError ();
if (err == WSAEWOULDBLOCK || err == WSAEALREADY)
{
WSASetLastError (WSAEINPROGRESS);
in_progress = TRUE;
}
else if (err == WSAEINVAL)
WSASetLastError (WSAEISCONN);
}
set_winsock_errno ();
}
if (sock->get_addr_family () == AF_UNIX)
{
if (!res || in_progress)
{
if (!sock->create_secret_event (secret))
{
secret_check_failed = TRUE;
}
else if (in_progress)
sock->signal_secret_event ();
}
if (!secret_check_failed && !res)
{
if (!sock->check_peer_secret_event (&sin, secret))
{
debug_printf ( "accept from unauthorized server" );
secret_check_failed = TRUE;
}
}
if (secret_check_failed)
{
sock->close_secret_event ();
if (res)
closesocket (res);
set_errno (ECONNREFUSED);
res = -1;
}
}
2000-02-17 20:38:33 +01:00
}
return res;
}
static void
free_servent_ptr (struct servent *&p)
{
if (p)
{
debug_printf ("servent: %s", p->s_name);
if (p->s_name)
free (p->s_name);
if (p->s_proto)
free (p->s_proto);
free_char_list (p->s_aliases);
p = NULL;
}
}
#pragma pack(push,2)
struct pservent
{
char *s_name;
char **s_aliases;
short s_port;
char *s_proto;
};
#pragma pack(pop)
static struct servent *
dup_servent_ptr (struct servent *src)
{
if (!src)
return NULL;
struct servent *dst = (struct servent *) calloc (1, sizeof *dst);
if (!dst)
return NULL;
debug_printf ("servent: %s", src->s_name);
dst->s_port = src->s_port;
if (src->s_name && !(dst->s_name = strdup (src->s_name)))
goto out;
if (src->s_aliases && !(dst->s_aliases = dup_char_list (src->s_aliases)))
goto out;
char *s_proto;
if (IsBadReadPtr (src->s_proto, sizeof (src->s_proto))
&& !IsBadReadPtr (((pservent *) src)->s_proto, sizeof (src->s_proto)))
s_proto = ((pservent *)src)->s_proto;
else
s_proto = src->s_proto;
if (s_proto && !(dst->s_proto = strdup (s_proto)))
goto out;
debug_printf ("servent: copied %s", dst->s_name);
return dst;
out:
free_servent_ptr (dst);
return NULL;
}
#ifdef _MT_SAFE
#define servent_buf _reent_winsup ()->_servent_buf
#else
static struct servent *servent_buf = NULL;
#endif
2000-02-17 20:38:33 +01:00
/* exported as getservbyname: standards? */
extern "C" struct servent *
2000-02-17 20:38:33 +01:00
cygwin_getservbyname (const char *name, const char *proto)
{
if (check_null_str_errno (name)
|| (proto != NULL && check_null_str_errno (proto)))
return NULL;
free_servent_ptr (servent_buf);
servent_buf = dup_servent_ptr (getservbyname (name, proto));
if (!servent_buf)
2000-02-17 20:38:33 +01:00
set_winsock_errno ();
syscall_printf ("%x = getservbyname (%s, %s)", servent_buf, name, proto);
return servent_buf;
2000-02-17 20:38:33 +01:00
}
/* exported as getservbyport: standards? */
extern "C" struct servent *
2000-02-17 20:38:33 +01:00
cygwin_getservbyport (int port, const char *proto)
{
if (proto != NULL && check_null_str_errno (proto))
return NULL;
free_servent_ptr (servent_buf);
servent_buf = dup_servent_ptr (getservbyport (port, proto));
if (!servent_buf)
2000-02-17 20:38:33 +01:00
set_winsock_errno ();
syscall_printf ("%x = getservbyport (%d, %s)", servent_buf, port, proto);
return servent_buf;
2000-02-17 20:38:33 +01:00
}
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_gethostname (char *name, size_t len)
{
int PASCAL win32_gethostname (char*, int);
2000-02-17 20:38:33 +01:00
if (__check_null_invalid_struct_errno (name, len))
return -1;
2000-02-17 20:38:33 +01:00
if (wsock32_handle == NULL ||
win32_gethostname (name, len) == SOCKET_ERROR)
{
DWORD local_len = len;
if (!GetComputerNameA (name, &local_len))
{
set_winsock_errno ();
return -1;
}
}
debug_printf ("name %s\n", name);
h_errno = 0;
return 0;
}
static void
free_hostent_ptr (struct hostent *&p)
{
if (p)
{
debug_printf ("hostent: %s", p->h_name);
if (p->h_name)
free ((void *)p->h_name);
free_char_list (p->h_aliases);
free_addr_list (p->h_addr_list);
p = NULL;
}
}
static struct hostent *
dup_hostent_ptr (struct hostent *src)
{
if (!src)
return NULL;
struct hostent *dst = (struct hostent *) calloc (1, sizeof *dst);
if (!dst)
return NULL;
debug_printf ("hostent: %s", src->h_name);
dst->h_addrtype = src->h_addrtype;
dst->h_length = src->h_length;
if (src->h_name && !(dst->h_name = strdup (src->h_name)))
goto out;
if (src->h_aliases && !(dst->h_aliases = dup_char_list (src->h_aliases)))
goto out;
if (src->h_addr_list
&& !(dst->h_addr_list = dup_addr_list(src->h_addr_list, src->h_length)))
goto out;
debug_printf ("hostent: copied %s", dst->h_name);
return dst;
out:
free_hostent_ptr (dst);
return NULL;
}
#ifdef _MT_SAFE
#define hostent_buf _reent_winsup ()->_hostent_buf
#else
static struct hostent *hostent_buf = NULL;
#endif
2000-02-17 20:38:33 +01:00
/* exported as gethostbyname: standards? */
extern "C" struct hostent *
2000-02-17 20:38:33 +01:00
cygwin_gethostbyname (const char *name)
{
static unsigned char tmp_addr[4];
static struct hostent tmp;
static char *tmp_aliases[1];
static char *tmp_addr_list[2];
2000-02-17 20:38:33 +01:00
static int a, b, c, d;
if (check_null_str_errno (name))
return NULL;
if (sscanf (name, "%d.%d.%d.%d", &a, &b, &c, &d) == 4)
2000-02-17 20:38:33 +01:00
{
/* In case you don't have DNS, at least x.x.x.x still works */
memset (&tmp, 0, sizeof (tmp));
2000-02-17 20:38:33 +01:00
tmp_addr[0] = a;
tmp_addr[1] = b;
tmp_addr[2] = c;
tmp_addr[3] = d;
tmp_addr_list[0] = (char *)tmp_addr;
tmp.h_name = name;
tmp.h_aliases = tmp_aliases;
tmp.h_addrtype = 2;
tmp.h_length = 4;
tmp.h_addr_list = tmp_addr_list;
return &tmp;
}
free_hostent_ptr (hostent_buf);
hostent_buf = dup_hostent_ptr (gethostbyname (name));
if (!hostent_buf)
2000-02-17 20:38:33 +01:00
{
set_winsock_errno ();
set_host_errno ();
}
else
{
debug_printf ("h_name %s", hostent_buf->h_name);
2000-02-17 20:38:33 +01:00
h_errno = 0;
}
return hostent_buf;
}
/* exported as gethostbyaddr: standards? */
extern "C" struct hostent *
cygwin_gethostbyaddr (const char *addr, int len, int type)
{
if (__check_null_invalid_struct_errno (addr, len))
return NULL;
free_hostent_ptr (hostent_buf);
hostent_buf = dup_hostent_ptr (gethostbyaddr (addr, len, type));
if (!hostent_buf)
{
set_winsock_errno ();
set_host_errno ();
}
else
{
debug_printf ("h_name %s", hostent_buf->h_name);
h_errno = 0;
}
return hostent_buf;
2000-02-17 20:38:33 +01:00
}
/* exported as accept: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_accept (int fd, struct sockaddr *peer, int *len)
{
if (peer != NULL
&& (check_null_invalid_struct_errno (len)
|| __check_null_invalid_struct_errno (peer, (unsigned) *len)))
return -1;
2000-02-17 20:38:33 +01:00
int res = -1;
BOOL secret_check_failed = FALSE;
BOOL in_progress = FALSE;
sigframe thisframe (mainthread);
2000-02-17 20:38:33 +01:00
fhandler_socket *sock = get (fd);
if (sock)
{
/* Allows NULL peer and len parameters. */
struct sockaddr_in peer_dummy;
int len_dummy;
if (!peer)
peer = (struct sockaddr *) &peer_dummy;
if (!len)
{
len_dummy = sizeof (struct sockaddr_in);
len = &len_dummy;
}
2000-02-17 20:38:33 +01:00
/* accept on NT fails if len < sizeof (sockaddr_in)
* some programs set len to
* sizeof (name.sun_family) + strlen (name.sun_path) for UNIX domain
2000-02-17 20:38:33 +01:00
*/
if (len && ((unsigned) *len < sizeof (struct sockaddr_in)))
*len = sizeof (struct sockaddr_in);
res = accept (sock->get_socket (), peer, len); // can't use a blocking call inside a lock
if ((SOCKET) res == (SOCKET) INVALID_SOCKET &&
WSAGetLastError () == WSAEWOULDBLOCK)
in_progress = TRUE;
if (sock->get_addr_family () == AF_UNIX)
{
if ((SOCKET) res != (SOCKET) INVALID_SOCKET || in_progress)
{
if (!sock->create_secret_event ())
secret_check_failed = TRUE;
else if (in_progress)
sock->signal_secret_event ();
}
if (!secret_check_failed &&
(SOCKET) res != (SOCKET) INVALID_SOCKET)
{
if (!sock->check_peer_secret_event ((struct sockaddr_in*) peer))
{
debug_printf ("connect from unauthorized client");
secret_check_failed = TRUE;
}
}
if (secret_check_failed)
{
sock->close_secret_event ();
if ((SOCKET) res != (SOCKET) INVALID_SOCKET)
closesocket (res);
set_errno (ECONNABORTED);
res = -1;
goto done;
}
}
2000-02-17 20:38:33 +01:00
cygheap_fdnew res_fd;
if (res_fd < 0)
/* FIXME: what is correct errno? */;
else if ((SOCKET) res == (SOCKET) INVALID_SOCKET)
2000-02-17 20:38:33 +01:00
set_winsock_errno ();
else
{
fhandler_socket* res_fh = fdsock (res_fd, sock->get_name (), res);
res_fh->set_addr_family (sock->get_addr_family ());
2000-02-17 20:38:33 +01:00
res = res_fd;
}
}
done:
2000-02-17 20:38:33 +01:00
syscall_printf ("%d = accept (%d, %x, %x)", res, fd, peer, len);
return res;
}
/* exported as bind: standards? */
extern "C" int
cygwin_bind (int fd, const struct sockaddr *my_addr, int addrlen)
2000-02-17 20:38:33 +01:00
{
if (__check_null_invalid_struct_errno (my_addr, addrlen))
return -1;
2000-02-17 20:38:33 +01:00
int res = -1;
fhandler_socket *sock = get (fd);
if (sock)
{
if (my_addr->sa_family == AF_UNIX)
{
#define un_addr ((struct sockaddr_un *) my_addr)
struct sockaddr_in sin;
int len = sizeof sin;
int fd;
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
if (strlen (un_addr->sun_path) >= UNIX_PATH_LEN)
{
set_errno (ENAMETOOLONG);
goto out;
}
2000-02-17 20:38:33 +01:00
sin.sin_family = AF_INET;
sin.sin_port = 0;
sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
if (bind (sock->get_socket (), (sockaddr *) &sin, len))
{
syscall_printf ("AF_UNIX: bind failed %d", get_errno ());
set_winsock_errno ();
goto out;
}
if (getsockname (sock->get_socket (), (sockaddr *) &sin, &len))
{
syscall_printf ("AF_UNIX: getsockname failed %d", get_errno ());
set_winsock_errno ();
goto out;
}
sin.sin_port = ntohs (sin.sin_port);
debug_printf ("AF_UNIX: socket bound to port %u", sin.sin_port);
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
/* bind must fail if file system socket object already exists
so _open () is called with O_EXCL flag. */
2000-02-17 20:38:33 +01:00
fd = _open (un_addr->sun_path,
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
O_WRONLY | O_CREAT | O_EXCL | O_BINARY,
0);
2000-02-17 20:38:33 +01:00
if (fd < 0)
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
{
if (get_errno () == EEXIST)
set_errno (EADDRINUSE);
2000-02-17 20:38:33 +01:00
goto out;
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
}
2000-02-17 20:38:33 +01:00
sock->set_connect_secret ();
char buf[sizeof (SOCKET_COOKIE) + 80];
__small_sprintf (buf, "%s%u ", SOCKET_COOKIE, sin.sin_port);
sock->get_connect_secret (strchr (buf, '\0'));
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
len = strlen (buf) + 1;
2000-02-17 20:38:33 +01:00
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
/* Note that the terminating nul is written. */
if (_write (fd, buf, len) != len)
{
2000-02-17 20:38:33 +01:00
save_errno here;
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
_close (fd);
_unlink (un_addr->sun_path);
}
else
{
_close (fd);
chmod (un_addr->sun_path,
(S_IFSOCK | S_IRWXU | S_IRWXG | S_IRWXO) & ~cygheap->umask);
sock->set_sun_path (un_addr->sun_path);
2000-02-17 20:38:33 +01:00
res = 0;
* Makefile.in: Add cygheap.o. * child_info.h: Add specific exec class. * cygheap.h: New file. Contains declarations for cygwin heap. * cygheap.cc: New file. Implements cygwin heap functions. * dcrt0.cc (quoted): Simplify due to new method for passing arguments between cygwin programs. (alloc_stack_hard_way): Attempt to handle overlapped stack. (dll_crt0_1): Move child_info processing here. Accomodate new method for passing arguments between cygwin programs. Initialize cygwin heap. Establish __argc and __argv variables. (_dll_crt0): Move most of child_info processing to dll_crt0_1. (cygwin_dll_init): Remove duplication. * dtable.cc (dtable::extend): Allocate dtable using cygwin heap. (dtable::build_fhandler): Ditto for fhandler type being constructed. (dtable::dup_worker): Free new fhandler from cygwin heap on error. (dtable::select_*): Don't assume that this == fdtab. (dtable::linearize_fd_array): Delete. (dtable::delinearize_fd_array): Delete. (dtable::fixup_after_exec): New file. (dtable::vfork_child_dup): Use cygwin heap. (dtable::vfork_parent_restore): Ditto. * dtable.h: Remove obsolete methods. Add new method. * environ.cc (posify): Eliminate already_posix parameter and logic. (envsize): New function. (_addenv): Use envsize. (environ_init): Accept an argument pointing to an existing environment list. If supplied, allocate space for this in the the program's heap. * fhandler.cc (fhandler_base::operator =): Move here from fhandler.h. Use cygwin heap to allocate filenames. (fhandler_base::set_name): Allocate/free names from cygwin heap. (fhandler_base::linearize): Delete. (fhandler_base::de_linearize): Delete. (fhandler_base::operator delete): Free from cygwin heap. (fhandler_base::~fhandler_base): Ditto. * fhandler.h: Accomodate elimination of *linearize and other changes above. * fhandler_console.cc (fhandler_console::fixup_after_exec): Rename from de_linearize. * heap.h: New file. * fhandler_tty.cc (fhandler_tty_slave::fhandler_tty_slave): Use cygwin heap for name. fhandler_tty::fixup_after_exec): Rename from de_linearize. * fork.cc (fork): Call cygheap_fixup_in_child. * heap.cc: Use declarations in heap.h. * malloc.cc: Sprinkle assertions throughout to catch attempts to free/realloc something from the cygwin heap. * path.cc: Throughout, eliminate use of per-thread cache for cwd. Use cwd_* functions rather than cwd_* variables to access cwd_win32 and cwd_posix. (cwd_win32): New function. (cwd_posix): New function. (cwd_hash): New function. (cwd_fixup_after_exec): New function. * path.h: Accomodate path.cc changes. * pinfo.cc (pinfo_init): Accept a pointer to an environment table. Pass this to environ_init. Eliminate old 'title' tests. * pinfo.h: Accomodate above change in argument. * spawn.cc (struct av): New method for building argv list. (av::unshift): New method. (spawn_guts): Allocate everything that the child process needs in the cygwin heap and pass a pointer to this to the child. Build argv list using new method. Eliminate delinearize stuff. * thread.h: Eliminate _cwd_win32 and _cwd_posix buffers. * winsup.h: Eliminate obsolete functions. Add envsize() declaration.
2000-09-03 06:16:35 +02:00
}
2000-02-17 20:38:33 +01:00
#undef un_addr
}
else if (bind (sock->get_socket (), my_addr, addrlen))
set_winsock_errno ();
else
res = 0;
}
out:
syscall_printf ("%d = bind (%d, %x, %d)", res, fd, my_addr, addrlen);
return res;
}
/* exported as getsockname: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_getsockname (int fd, struct sockaddr *addr, int *namelen)
{
if (check_null_invalid_struct_errno (namelen)
|| __check_null_invalid_struct_errno (addr, (unsigned) *namelen))
return -1;
2000-02-17 20:38:33 +01:00
int res = -1;
fhandler_socket *sock = get (fd);
if (sock)
{
if (sock->get_addr_family () == AF_UNIX)
{
struct sockaddr_un *sun = (struct sockaddr_un *) addr;
memset (sun, 0, *namelen);
sun->sun_family = AF_UNIX;
/* According to SUSv2 "If the actual length of the address is greater
than the length of the supplied sockaddr structure, the stored
address will be truncated." We play it save here so that the
path always has a trailing 0 even if it's truncated. */
strncpy (sun->sun_path, sock->get_sun_path (),
*namelen - sizeof *sun + sizeof sun->sun_path - 1);
*namelen = sizeof *sun - sizeof sun->sun_path
+ strlen (sun->sun_path) + 1;
res = 0;
}
else
{
res = getsockname (sock->get_socket (), addr, namelen);
if (res)
set_winsock_errno ();
}
2000-02-17 20:38:33 +01:00
}
syscall_printf ("%d = getsockname (%d, %x, %d)", res, fd, addr, namelen);
return res;
}
/* exported as listen: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_listen (int fd, int backlog)
{
int res = -1;
fhandler_socket *sock = get (fd);
if (sock)
{
res = listen (sock->get_socket (), backlog);
if (res)
set_winsock_errno ();
}
syscall_printf ("%d = listen (%d, %d)", res, fd, backlog);
return res;
}
/* exported as shutdown: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_shutdown (int fd, int how)
{
int res = -1;
sigframe thisframe (mainthread);
2000-02-17 20:38:33 +01:00
fhandler_socket *sock = get (fd);
if (sock)
{
res = shutdown (sock->get_socket (), how);
if (res)
set_winsock_errno ();
else
switch (how)
{
case SHUT_RD:
sock->set_shutdown_read ();
break;
case SHUT_WR:
sock->set_shutdown_write ();
break;
case SHUT_RDWR:
sock->set_shutdown_read ();
sock->set_shutdown_write ();
break;
}
2000-02-17 20:38:33 +01:00
}
syscall_printf ("%d = shutdown (%d, %d)", res, fd, how);
return res;
}
/* exported as hstrerror: BSD 4.3 */
extern "C" const char *
cygwin_hstrerror (int err)
{
int i;
for (i = 0; host_errmap[i].e != 0; ++i)
if (err == host_errmap[i].e)
break;
return host_errmap[i].s;
}
/* exported as herror: BSD 4.3 */
extern "C" void
cygwin_herror (const char *s)
2000-02-17 20:38:33 +01:00
{
if (s && check_null_str (s))
return;
if (cygheap->fdtab.not_open (2))
return;
if (s)
{
write (2, s, strlen (s));
write (2, ": ", 2);
}
const char *h_errstr = cygwin_hstrerror (h_errno);
if (!h_errstr)
switch (h_errno)
{
case NETDB_INTERNAL:
h_errstr = "Resolver internal error";
break;
case NETDB_SUCCESS:
h_errstr = "Resolver error 0 (no error)";
break;
default:
h_errstr = "Unknown resolver error";
break;
}
write (2, h_errstr, strlen (h_errstr));
write (2, "\n", 1);
2000-02-17 20:38:33 +01:00
}
/* exported as getpeername: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_getpeername (int fd, struct sockaddr *name, int *len)
{
int res;
if (check_null_invalid_struct_errno (len)
|| __check_null_invalid_struct_errno (name, (unsigned) *len))
return -1;
2000-02-17 20:38:33 +01:00
fhandler_socket *h = get (fd);
if (!h)
res = -1;
else
{
res = getpeername (h->get_socket (), name, len);
if (res)
set_winsock_errno ();
}
2000-02-17 20:38:33 +01:00
debug_printf ("%d = getpeername %d", res, h->get_socket ());
return res;
}
/* exported as recv: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_recv (int fd, void *buf, int len, unsigned int flags)
{
int res;
wsock_event wsock_evt;
LPWSAOVERLAPPED ovr;
fhandler_socket *h = get (fd);
2000-02-17 20:38:33 +01:00
if (__check_null_invalid_struct_errno (buf, len) || !h)
res = -1;
else
2000-02-17 20:38:33 +01:00
{
sigframe thisframe (mainthread);
if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
{
debug_printf ("Fallback to winsock 1 recv call");
if ((res = recv (h->get_socket (), (char *) buf, len, flags))
== SOCKET_ERROR)
{
set_winsock_errno ();
res = -1;
}
}
else
{
WSABUF wsabuf = { len, (char *) buf };
DWORD ret = 0;
if (WSARecv (h->get_socket (), &wsabuf, 1, &ret, (DWORD *)&flags,
ovr, NULL) != SOCKET_ERROR)
res = ret;
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
{
set_winsock_errno ();
res = -1;
}
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
set_winsock_errno ();
}
2000-02-17 20:38:33 +01:00
}
syscall_printf ("%d = recv (%d, %x, %x, %x)", res, fd, buf, len, flags);
return res;
}
/* exported as send: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_send (int fd, const void *buf, int len, unsigned int flags)
{
int res;
wsock_event wsock_evt;
LPWSAOVERLAPPED ovr;
fhandler_socket *h = get (fd);
2000-02-17 20:38:33 +01:00
if (__check_invalid_read_ptr_errno (buf, len) || !h)
res = -1;
else
2000-02-17 20:38:33 +01:00
{
sigframe thisframe (mainthread);
if (h->is_nonblocking () || !(ovr = wsock_evt.prepare ()))
{
debug_printf ("Fallback to winsock 1 send call");
if ((res = send (h->get_socket (), (const char *) buf, len, flags))
== SOCKET_ERROR)
{
set_winsock_errno ();
res = -1;
}
}
else
{
WSABUF wsabuf = { len, (char *) buf };
DWORD ret = 0;
if (WSASend (h->get_socket (), &wsabuf, 1, &ret, (DWORD)flags,
ovr, NULL) != SOCKET_ERROR)
res = ret;
else if ((res = WSAGetLastError ()) != WSA_IO_PENDING)
{
set_winsock_errno ();
res = -1;
}
else if ((res = wsock_evt.wait (h->get_socket (), (DWORD *)&flags)) == -1)
set_winsock_errno ();
}
2000-02-17 20:38:33 +01:00
}
syscall_printf ("%d = send (%d, %x, %d, %x)", res, fd, buf, len, flags);
return res;
}
/* getdomainname: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
getdomainname (char *domain, int len)
{
/*
* This works for Win95 only if the machine is configured to use MS-TCP.
* If a third-party TCP is being used this will fail.
* FIXME: On Win95, is there a way to portably check the TCP stack
* in use and include paths for the Domain name in each ?
* Punt for now and assume MS-TCP on Win95.
*/
if (__check_null_invalid_struct_errno (domain, len))
return -1;
2000-02-17 20:38:33 +01:00
reg_key r (HKEY_LOCAL_MACHINE, KEY_READ,
(!wincap.is_winnt ()) ? "System" : "SYSTEM",
2000-02-17 20:38:33 +01:00
"CurrentControlSet", "Services",
(!wincap.is_winnt ()) ? "MSTCP" : "Tcpip",
2000-02-17 20:38:33 +01:00
NULL);
/* FIXME: Are registry keys case sensitive? */
if (r.error () || r.get_string ("Domain", domain, len, "") != ERROR_SUCCESS)
{
__seterrno ();
return -1;
}
return 0;
}
/* Cygwin internal */
/* Fill out an ifconf struct. */
/*
* IFCONF 98/ME, NTSP4, W2K:
* Use IP Helper Library
2000-02-17 20:38:33 +01:00
*/
static void
get_2k_ifconf (struct ifconf *ifc, int what)
2000-02-17 20:38:33 +01:00
{
int cnt = 0;
char eth[2] = "/", ppp[2] = "/", slp[2] = "/", sub[2] = "0";
/* Union maps buffer to correct struct */
struct ifreq *ifr = ifc->ifc_req;
DWORD if_cnt, ip_cnt, lip, lnp;
DWORD siz_if_table = 0;
DWORD siz_ip_table = 0;
PMIB_IFTABLE ift;
PMIB_IPADDRTABLE ipt;
struct sockaddr_in *sa = NULL;
struct sockaddr *so = NULL;
if (GetIfTable(NULL, &siz_if_table, TRUE) == ERROR_INSUFFICIENT_BUFFER &&
GetIpAddrTable(NULL, &siz_ip_table, TRUE) == ERROR_INSUFFICIENT_BUFFER &&
(ift = (PMIB_IFTABLE) alloca (siz_if_table)) &&
(ipt = (PMIB_IPADDRTABLE) alloca (siz_ip_table)) &&
!GetIfTable(ift, &siz_if_table, TRUE) &&
!GetIpAddrTable(ipt, &siz_ip_table, TRUE))
2000-02-17 20:38:33 +01:00
{
/* Iterate over all known interfaces */
for (if_cnt = 0; if_cnt < ift->dwNumEntries; ++if_cnt)
2001-11-05 07:09:15 +01:00
{
*sub = '0';
/* Iterate over all configured IP-addresses */
2001-11-05 07:09:15 +01:00
for (ip_cnt = 0; ip_cnt < ipt->dwNumEntries; ++ip_cnt)
{
/* Does the IP address belong to the interface? */
if (ipt->table[ip_cnt].dwIndex == ift->table[if_cnt].dwIndex)
{
/* Setup the interface name */
switch (ift->table[if_cnt].dwType)
{
case MIB_IF_TYPE_ETHERNET:
if (*sub == '0')
++*eth;
strcpy (ifr->ifr_name, "eth");
strcat (ifr->ifr_name, eth);
break;
case MIB_IF_TYPE_PPP:
++*ppp;
strcpy (ifr->ifr_name, "ppp");
strcat (ifr->ifr_name, ppp);
break;
case MIB_IF_TYPE_SLIP:
++*slp;
strcpy (ifr->ifr_name, "slp");
strcat (ifr->ifr_name, slp);
break;
case MIB_IF_TYPE_LOOPBACK:
strcpy (ifr->ifr_name, "lo");
break;
default:
continue;
}
if (*sub > '0')
{
strcat (ifr->ifr_name, ":");
strcat (ifr->ifr_name, sub);
}
++*sub;
/* setup sockaddr struct */
switch (what)
{
case SIOCGIFCONF:
case SIOCGIFADDR:
sa = (struct sockaddr_in *) &ifr->ifr_addr;
sa->sin_addr.s_addr = ipt->table[ip_cnt].dwAddr;
sa->sin_family = AF_INET;
sa->sin_port = 0;
break;
case SIOCGIFBRDADDR:
sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
#if 0
/* Unfortunately, the field returns only crap. */
sa->sin_addr.s_addr = ipt->table[ip_cnt].dwBCastAddr;
#else
lip = ipt->table[ip_cnt].dwAddr;
lnp = ipt->table[ip_cnt].dwMask;
sa->sin_addr.s_addr = lip & lnp | ~lnp;
sa->sin_family = AF_INET;
sa->sin_port = 0;
#endif
break;
case SIOCGIFNETMASK:
sa = (struct sockaddr_in *) &ifr->ifr_netmask;
sa->sin_addr.s_addr = ipt->table[ip_cnt].dwMask;
sa->sin_family = AF_INET;
sa->sin_port = 0;
break;
case SIOCGIFHWADDR:
so = &ifr->ifr_hwaddr;
for (UINT i = 0; i < IFHWADDRLEN; ++i)
if (i >= ift->table[if_cnt].dwPhysAddrLen)
so->sa_data[i] = '\0';
else
so->sa_data[i] = ift->table[if_cnt].bPhysAddr[i];
so->sa_family = AF_INET;
break;
case SIOCGIFMETRIC:
ifr->ifr_metric = 1;
break;
case SIOCGIFMTU:
ifr->ifr_mtu = ift->table[if_cnt].dwMtu;
break;
}
++cnt;
if ((caddr_t) ++ifr >
ifc->ifc_buf + ifc->ifc_len - sizeof (struct ifreq))
goto done;
}
}
}
}
done:
/* Set the correct length */
ifc->ifc_len = cnt * sizeof (struct ifreq);
}
2000-02-17 20:38:33 +01:00
/*
* IFCONF Windows NT < SP4:
* Look at the Bind value in
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Linkage\
* This is a REG_MULTI_SZ with strings of the form:
* \Device\<Netcard>, where netcard is the name of the net device.
* Then look under:
* HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\<NetCard>\
* Parameters\Tcpip
* at the IPAddress, Subnetmask and DefaultGateway values for the
* required values.
*/
static void
get_nt_ifconf (struct ifconf *ifc, int what)
{
HKEY key;
unsigned long lip, lnp;
struct sockaddr_in *sa = NULL;
struct sockaddr *so = NULL;
DWORD size;
int cnt = 1;
char *binding = (char *) 0;
/* Union maps buffer to correct struct */
struct ifreq *ifr = ifc->ifc_req;
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE,
"SYSTEM\\"
"CurrentControlSet\\"
"Services\\"
"Tcpip\\"
"Linkage",
0, KEY_READ, &key) == ERROR_SUCCESS)
{
if (RegQueryValueEx (key, "Bind",
NULL, NULL,
NULL, &size) == ERROR_SUCCESS)
{
binding = (char *) alloca (size);
if (RegQueryValueEx (key, "Bind",
NULL, NULL,
(unsigned char *) binding,
&size) != ERROR_SUCCESS)
{
binding = NULL;
}
}
RegCloseKey (key);
}
2000-02-17 20:38:33 +01:00
if (binding)
{
char *bp, eth[2] = "/";
char cardkey[256], ipaddress[256], netmask[256];
for (bp = binding; *bp; bp += strlen (bp) + 1)
{
bp += strlen ("\\Device\\");
strcpy (cardkey, "SYSTEM\\CurrentControlSet\\Services\\");
strcat (cardkey, bp);
strcat (cardkey, "\\Parameters\\Tcpip");
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, cardkey,
0, KEY_READ, &key) != ERROR_SUCCESS)
continue;
if (RegQueryValueEx (key, "IPAddress",
NULL, NULL,
(unsigned char *) ipaddress,
(size = 256, &size)) == ERROR_SUCCESS
&& RegQueryValueEx (key, "SubnetMask",
NULL, NULL,
(unsigned char *) netmask,
(size = 256, &size)) == ERROR_SUCCESS)
{
char *ip, *np;
char dhcpaddress[256], dhcpnetmask[256];
for (ip = ipaddress, np = netmask;
*ip && *np;
ip += strlen (ip) + 1, np += strlen (np) + 1)
{
if ((caddr_t) ++ifr > ifc->ifc_buf
+ ifc->ifc_len
- sizeof (struct ifreq))
break;
if (! strncmp (bp, "NdisWan", 7))
{
strcpy (ifr->ifr_name, "ppp");
strcat (ifr->ifr_name, bp + 7);
}
else
{
++*eth;
strcpy (ifr->ifr_name, "eth");
strcat (ifr->ifr_name, eth);
}
memset (&ifr->ifr_addr, '\0', sizeof ifr->ifr_addr);
if (cygwin_inet_addr (ip) == 0L
&& RegQueryValueEx (key, "DhcpIPAddress",
NULL, NULL,
(unsigned char *) dhcpaddress,
(size = 256, &size))
== ERROR_SUCCESS
&& RegQueryValueEx (key, "DhcpSubnetMask",
NULL, NULL,
(unsigned char *) dhcpnetmask,
(size = 256, &size))
== ERROR_SUCCESS)
{
switch (what)
{
case SIOCGIFCONF:
case SIOCGIFADDR:
sa = (struct sockaddr_in *) &ifr->ifr_addr;
sa->sin_addr.s_addr = cygwin_inet_addr (dhcpaddress);
sa->sin_family = AF_INET;
sa->sin_port = 0;
break;
case SIOCGIFBRDADDR:
lip = cygwin_inet_addr (dhcpaddress);
lnp = cygwin_inet_addr (dhcpnetmask);
sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
sa->sin_addr.s_addr = lip & lnp | ~lnp;
sa->sin_family = AF_INET;
sa->sin_port = 0;
break;
case SIOCGIFNETMASK:
sa = (struct sockaddr_in *) &ifr->ifr_netmask;
sa->sin_addr.s_addr =
cygwin_inet_addr (dhcpnetmask);
sa->sin_family = AF_INET;
sa->sin_port = 0;
break;
case SIOCGIFHWADDR:
so = &ifr->ifr_hwaddr;
memset (so->sa_data, 0, IFHWADDRLEN);
so->sa_family = AF_INET;
break;
case SIOCGIFMETRIC:
ifr->ifr_metric = 1;
break;
case SIOCGIFMTU:
ifr->ifr_mtu = 1500;
break;
}
}
else
{
switch (what)
{
case SIOCGIFCONF:
case SIOCGIFADDR:
sa = (struct sockaddr_in *) &ifr->ifr_addr;
sa->sin_addr.s_addr = cygwin_inet_addr (ip);
sa->sin_family = AF_INET;
sa->sin_port = 0;
break;
case SIOCGIFBRDADDR:
lip = cygwin_inet_addr (ip);
lnp = cygwin_inet_addr (np);
sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
sa->sin_addr.s_addr = lip & lnp | ~lnp;
sa->sin_family = AF_INET;
sa->sin_port = 0;
break;
case SIOCGIFNETMASK:
sa = (struct sockaddr_in *) &ifr->ifr_netmask;
sa->sin_addr.s_addr = cygwin_inet_addr (np);
sa->sin_family = AF_INET;
sa->sin_port = 0;
break;
case SIOCGIFHWADDR:
so = &ifr->ifr_hwaddr;
memset (so->sa_data, 0, IFHWADDRLEN);
so->sa_family = AF_INET;
break;
case SIOCGIFMETRIC:
ifr->ifr_metric = 1;
break;
case SIOCGIFMTU:
ifr->ifr_mtu = 1500;
break;
}
}
++cnt;
}
}
RegCloseKey (key);
}
}
2000-02-17 20:38:33 +01:00
/* Set the correct length */
ifc->ifc_len = cnt * sizeof (struct ifreq);
}
2000-02-17 20:38:33 +01:00
/*
* IFCONF Windows 95:
* HKLM/Enum/Network/MSTCP/"*"
* -> Value "Driver" enth<EFBFBD>lt Subkey relativ zu
* HKLM/System/CurrentControlSet/Class/
* -> In Subkey "Bindings" die Values aufz<EFBFBD>hlen
* -> Enth<EFBFBD>lt Subkeys der Form "VREDIR\*"
* Das * ist ein Subkey relativ zu
* HKLM/System/CurrentControlSet/Class/Net/
* HKLM/System/CurrentControlSet/Class/"Driver"
* -> Value "IPAddress"
* -> Value "IPMask"
* HKLM/System/CurrentControlSet/Class/Net/"*"(aus "VREDIR\*")
* -> Wenn Value "AdapterName" == "MS$PPP" -> ppp interface
* -> Value "DriverDesc" enth<EFBFBD>lt den Namen
*
*/
static void
get_95_ifconf (struct ifconf *ifc, int what)
{
HKEY key;
unsigned long lip, lnp;
struct sockaddr_in *sa = NULL;
struct sockaddr *so = NULL;
FILETIME update;
LONG res;
DWORD size;
int cnt = 1;
char ifname[256];
char eth[2] = "/";
char ppp[2] = "/";
/* Union maps buffer to correct struct */
struct ifreq *ifr = ifc->ifc_req;
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Enum\\Network\\MSTCP",
0, KEY_READ, &key) != ERROR_SUCCESS)
{
/* Set the correct length */
ifc->ifc_len = cnt * sizeof (struct ifreq);
return;
}
for (int i = 0;
(res = RegEnumKeyEx (key, i, ifname,
(size = sizeof ifname, &size),
0, 0, 0, &update)) != ERROR_NO_MORE_ITEMS;
++i)
2000-02-17 20:38:33 +01:00
{
HKEY ifkey, subkey;
char driver[256], classname[256], netname[256];
char adapter[256], ip[256], np[256];
if (res != ERROR_SUCCESS
|| RegOpenKeyEx (key, ifname, 0,
KEY_READ, &ifkey) != ERROR_SUCCESS)
continue;
if (RegQueryValueEx (ifkey, "Driver", 0,
NULL, (unsigned char *) driver,
(size = sizeof driver, &size)) != ERROR_SUCCESS)
{
RegCloseKey (ifkey);
continue;
}
strcpy (classname, "System\\CurrentControlSet\\Services\\Class\\");
strcat (classname, driver);
if ((res = RegOpenKeyEx (HKEY_LOCAL_MACHINE, classname,
0, KEY_READ, &subkey)) != ERROR_SUCCESS)
{
RegCloseKey (ifkey);
continue;
}
if (RegQueryValueEx (subkey, "IPAddress", 0,
NULL, (unsigned char *) ip,
(size = sizeof ip, &size)) == ERROR_SUCCESS
&& RegQueryValueEx (subkey, "IPMask", 0,
NULL, (unsigned char *) np,
(size = sizeof np, &size)) == ERROR_SUCCESS)
{
if ((caddr_t)++ifr > ifc->ifc_buf
+ ifc->ifc_len
- sizeof (struct ifreq))
goto out;
switch (what)
{
case SIOCGIFCONF:
case SIOCGIFADDR:
sa = (struct sockaddr_in *) &ifr->ifr_addr;
sa->sin_addr.s_addr = cygwin_inet_addr (ip);
sa->sin_family = AF_INET;
sa->sin_port = 0;
break;
case SIOCGIFBRDADDR:
lip = cygwin_inet_addr (ip);
lnp = cygwin_inet_addr (np);
sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
sa->sin_addr.s_addr = lip & lnp | ~lnp;
sa->sin_family = AF_INET;
sa->sin_port = 0;
break;
case SIOCGIFNETMASK:
sa = (struct sockaddr_in *) &ifr->ifr_netmask;
sa->sin_addr.s_addr = cygwin_inet_addr (np);
sa->sin_family = AF_INET;
sa->sin_port = 0;
break;
case SIOCGIFHWADDR:
so = &ifr->ifr_hwaddr;
memset (so->sa_data, 0, IFHWADDRLEN);
so->sa_family = AF_INET;
break;
case SIOCGIFMETRIC:
ifr->ifr_metric = 1;
break;
case SIOCGIFMTU:
ifr->ifr_mtu = 1500;
break;
}
}
RegCloseKey (subkey);
strcpy (netname, "System\\CurrentControlSet\\Services\\Class\\Net\\");
strcat (netname, ifname);
if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, netname,
2001-11-05 07:09:15 +01:00
0, KEY_READ, &subkey) != ERROR_SUCCESS)
{
2001-11-05 07:09:15 +01:00
RegCloseKey (ifkey);
--ifr;
continue;
}
if (RegQueryValueEx (subkey, "AdapterName", 0,
2001-11-05 07:09:15 +01:00
NULL, (unsigned char *) adapter,
(size = sizeof adapter, &size)) == ERROR_SUCCESS
&& strcasematch (adapter, "MS$PPP"))
{
2001-11-05 07:09:15 +01:00
++*ppp;
strcpy (ifr->ifr_name, "ppp");
strcat (ifr->ifr_name, ppp);
}
else
{
2001-11-05 07:09:15 +01:00
++*eth;
strcpy (ifr->ifr_name, "eth");
strcat (ifr->ifr_name, eth);
}
2001-11-05 07:09:15 +01:00
RegCloseKey (subkey);
RegCloseKey (ifkey);
++cnt;
}
2000-02-17 20:38:33 +01:00
out:
RegCloseKey (key);
/* Set the correct length */
ifc->ifc_len = cnt * sizeof (struct ifreq);
}
2000-02-17 20:38:33 +01:00
int
get_ifconf (struct ifconf *ifc, int what)
{
unsigned long lip, lnp;
struct sockaddr_in *sa;
2000-02-17 20:38:33 +01:00
if (check_null_invalid_struct_errno (ifc))
return -1;
/* Union maps buffer to correct struct */
struct ifreq *ifr = ifc->ifc_req;
2000-02-17 20:38:33 +01:00
/* Ensure we have space for two struct ifreqs, fail if not. */
if (ifc->ifc_len < (int) (2 * sizeof (struct ifreq)))
{
set_errno (EFAULT);
return -1;
}
2000-02-17 20:38:33 +01:00
/* Set up interface lo0 first */
strcpy (ifr->ifr_name, "lo");
memset (&ifr->ifr_addr, '\0', sizeof (ifr->ifr_addr));
switch (what)
{
case SIOCGIFCONF:
case SIOCGIFADDR:
sa = (struct sockaddr_in *) &ifr->ifr_addr;
sa->sin_addr.s_addr = htonl (INADDR_LOOPBACK);
sa->sin_family = AF_INET;
sa->sin_port = 0;
break;
case SIOCGIFBRDADDR:
lip = htonl (INADDR_LOOPBACK);
lnp = cygwin_inet_addr ("255.0.0.0");
sa = (struct sockaddr_in *) &ifr->ifr_broadaddr;
sa->sin_addr.s_addr = lip & lnp | ~lnp;
sa->sin_family = AF_INET;
sa->sin_port = 0;
break;
case SIOCGIFNETMASK:
sa = (struct sockaddr_in *) &ifr->ifr_netmask;
sa->sin_addr.s_addr = cygwin_inet_addr ("255.0.0.0");
sa->sin_family = AF_INET;
sa->sin_port = 0;
break;
case SIOCGIFHWADDR:
ifr->ifr_hwaddr.sa_family = AF_INET;
memset (ifr->ifr_hwaddr.sa_data, 0, IFHWADDRLEN);
break;
case SIOCGIFMETRIC:
ifr->ifr_metric = 1;
break;
case SIOCGIFMTU:
/* This funny value is returned by `ifconfig lo' on Linux 2.2 kernel. */
ifr->ifr_mtu = 3924;
break;
default:
set_errno (EINVAL);
return -1;
2000-02-17 20:38:33 +01:00
}
OSVERSIONINFO os_version_info;
memset (&os_version_info, 0, sizeof os_version_info);
os_version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
GetVersionEx (&os_version_info);
if (wincap.has_ip_helper_lib ())
get_2k_ifconf (ifc, what);
else if (wincap.is_winnt ())
get_nt_ifconf (ifc, what);
else
get_95_ifconf (ifc, what);
2000-02-17 20:38:33 +01:00
return 0;
}
/* exported as rcmd: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_rcmd (char **ahost, unsigned short inport, char *locuser,
char *remuser, char *cmd, int *fd2p)
{
int res = -1;
SOCKET fd2s;
sigframe thisframe (mainthread);
2000-02-17 20:38:33 +01:00
if (check_null_invalid_struct_errno (ahost) ||
check_null_empty_str_errno (*ahost) ||
(locuser && check_null_empty_str_errno (locuser)) ||
(remuser && check_null_str_errno (remuser)))
return (int) INVALID_SOCKET;
cygheap_fdnew res_fd;
if (res_fd < 0)
2000-02-17 20:38:33 +01:00
goto done;
if (fd2p)
{
cygheap_fdnew newfd (res_fd, false);
if (*fd2p < 0)
2000-02-17 20:38:33 +01:00
goto done;
*fd2p = newfd;
2000-02-17 20:38:33 +01:00
}
res = rcmd (ahost, inport, locuser, remuser, cmd, fd2p ? &fd2s : NULL);
2000-02-17 20:38:33 +01:00
if (res == (int) INVALID_SOCKET)
goto done;
else
{
fdsock (res_fd, "/dev/tcp", res);
res = res_fd;
}
2000-02-17 20:38:33 +01:00
if (fd2p)
fdsock (*fd2p, "/dev/tcp", fd2s);
2000-02-17 20:38:33 +01:00
done:
syscall_printf ("%d = rcmd (...)", res);
return res;
}
/* exported as rresvport: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_rresvport (int *port)
{
int res;
sigframe thisframe (mainthread);
2000-02-17 20:38:33 +01:00
if (check_null_invalid_struct_errno (port))
return -1;
cygheap_fdnew res_fd;
if (res_fd < 0)
res = -1;
2000-02-17 20:38:33 +01:00
else
{
res = rresvport (port);
if (res != (int) INVALID_SOCKET)
{
fdsock (res_fd, "/dev/tcp", res);
res = res_fd;
}
2000-02-17 20:38:33 +01:00
}
2000-02-17 20:38:33 +01:00
syscall_printf ("%d = rresvport (%d)", res, port ? *port : 0);
return res;
}
/* exported as rexec: standards? */
extern "C" int
2000-02-17 20:38:33 +01:00
cygwin_rexec (char **ahost, unsigned short inport, char *locuser,
char *password, char *cmd, int *fd2p)
{
int res = -1;
SOCKET fd2s;
sigframe thisframe (mainthread);
2000-02-17 20:38:33 +01:00
if (check_null_invalid_struct_errno (ahost) ||
check_null_empty_str_errno (*ahost) ||
(locuser && check_null_empty_str_errno (locuser)) ||
(password && check_null_str_errno (password)))
return (int) INVALID_SOCKET;
cygheap_fdnew res_fd;
if (res_fd < 0)
2000-02-17 20:38:33 +01:00
goto done;
if (fd2p)
{
cygheap_fdnew newfd (res_fd);
if (newfd < 0)
2000-02-17 20:38:33 +01:00
goto done;
*fd2p = newfd;
2000-02-17 20:38:33 +01:00
}
res = rexec (ahost, inport, locuser, password, cmd, fd2p ? &fd2s : NULL);
if (res == (int) INVALID_SOCKET)
goto done;
else
{
fdsock (res_fd, "/dev/tcp", res);
res = res_fd;
}
if (fd2p)
fdsock (*fd2p, "/dev/tcp", fd2s);
2000-02-17 20:38:33 +01:00
done:
syscall_printf ("%d = rexec (...)", res);
return res;
}
/* socketpair: standards? */
/* Win32 supports AF_INET only, so ignore domain and protocol arguments */
extern "C" int
2000-02-17 20:38:33 +01:00
socketpair (int, int type, int, int *sb)
{
int res = -1;
SOCKET insock, outsock, newsock;
struct sockaddr_in sock_in;
int len = sizeof (sock_in);
if (__check_null_invalid_struct_errno (sb, 2 * sizeof(int)))
return -1;
cygheap_fdnew sb0;
if (sb0 < 0)
goto done;
else
2000-02-17 20:38:33 +01:00
{
sb[0] = sb0;
cygheap_fdnew sb1 (sb0, false);
if (sb1 < 0)
goto done;
2000-02-17 20:38:33 +01:00
sb[1] = sb1;
}
2000-02-17 20:38:33 +01:00
/* create a listening socket */
newsock = socket (AF_INET, type, 0);
if (newsock == INVALID_SOCKET)
{
debug_printf ("first socket call failed");
2000-02-17 20:38:33 +01:00
set_winsock_errno ();
goto done;
}
/* bind the socket to any unused port */
sock_in.sin_family = AF_INET;
sock_in.sin_port = 0;
sock_in.sin_addr.s_addr = INADDR_ANY;
if (bind (newsock, (struct sockaddr *) &sock_in, sizeof (sock_in)) < 0)
{
debug_printf ("bind failed");
2000-02-17 20:38:33 +01:00
set_winsock_errno ();
closesocket (newsock);
goto done;
}
if (getsockname (newsock, (struct sockaddr *) &sock_in, &len) < 0)
{
debug_printf ("getsockname error");
set_winsock_errno ();
closesocket (newsock);
goto done;
}
listen (newsock, 2);
/* create a connecting socket */
outsock = socket (AF_INET, type, 0);
if (outsock == INVALID_SOCKET)
{
debug_printf ("second socket call failed");
2000-02-17 20:38:33 +01:00
set_winsock_errno ();
closesocket (newsock);
goto done;
}
sock_in.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
/* Do a connect and accept the connection */
if (connect (outsock, (struct sockaddr *) &sock_in,
sizeof (sock_in)) < 0)
{
debug_printf ("connect error");
set_winsock_errno ();
closesocket (newsock);
closesocket (outsock);
goto done;
}
insock = accept (newsock, (struct sockaddr *) &sock_in, &len);
if (insock == INVALID_SOCKET)
{
debug_printf ("accept error");
set_winsock_errno ();
closesocket (newsock);
closesocket (outsock);
goto done;
}
closesocket (newsock);
res = 0;
fdsock (sb[0], "/dev/tcp", insock);
fdsock (sb[1], "/dev/tcp", outsock);
done:
syscall_printf ("%d = socketpair (...)", res);
return res;
}
* dtable.cc (dtable::release): Check for socket. Change cnt_need_fixup_before accordingly. (dtable::dup2): Ditto. (dtable::fixup_before_fork): New method. (dtable::fixup_before_exec): Ditto. * dtable.h (class dtable): Add member `cnt_need_fixup_before'. Add definition for methods `dec_need_fixup_before', `inc_need_fixup_before', `need_fixup_before', `fixup_before_exec' and `fixup_before_fork'. * fhandler.h (class fhandler_base): Slight rearrangements. Add definitions for methods `fixup_before_fork_exec'. (class fhandler_socket): Eliminate superfluous constructor. Add member `prot_info_ptr'. Add destructor. Add definitions for methods `dup', `fixup_before_fork_exec', `fixup_after_fork' and `fixup_after_exec'. * fork.cc (fork_parent): Care for file types which need a fixup before fork. Start child in suspended state then. * net.cc: New global variable `ws2_32_handle' and `wsadata'. (fdsock): Check for Winsock version. Call `set_socket_inheritance' only if Winsock version < 2.0. Care for `need_fixup' count in fdtab. (cygwin_socket): Eliminate call to `set_socket_inheritance'. (cygwin_accept): Ditto. (cygwin_rcmd): Ditto. (cygwin_rresvport): Ditto. (cygwin_rexec): Ditto. (socketpair): Ditto. (fhandler_socket::fhandler_socket): Set `need_fork_fixup'. Allocate space for the WSAPROTOCOL_INFOA struct used in fixup. (fhandler_socket::~fhandler_socket): New destructor. (fhandler_socket::fixup_before_fork_exec): New method. (fhandler_socket::fixup_after_fork): Ditto. (fhandler_socket::dup): Ditto. (wsock_init): New static function. (LoadDLLinitfunc (wsock32)): Rearranged. (LoadDLLinitfunc (ws2_32)): New function. (dummy_autoload): Add autoload statemants for `WSADuplicateSocketA' and `WSASocketA'. * spawn.cc (spawn_guts): Care for file types which need a fixup before exec. Start child in suspended state then.
2000-10-26 12:13:41 +02:00
/* sethostent: standards? */
extern "C" void
sethostent (int)
{
}
/* endhostent: standards? */
extern "C" void
endhostent (void)
{
}