* fhandler_socket.cc: New file.
* Makefile.in: Add fhandler_socket.o to dependencies.
        * fhandler.h: Change comment.
        * net.cc Move all fhandler_socket methods to fhandler_socket.cc.
        * winsup.h: Add declaration for `ws2_32_handle'.
			
			
This commit is contained in:
		| @@ -1,3 +1,11 @@ | |||||||
|  | Fri Oct 27 11:48:00 2000  Corinna Vinschen <corinna@vinschen.de> | ||||||
|  |  | ||||||
|  | 	* fhandler_socket.cc: New file. | ||||||
|  | 	* Makefile.in: Add fhandler_socket.o to dependencies. | ||||||
|  | 	* fhandler.h: Change comment. | ||||||
|  | 	* net.cc Move all fhandler_socket methods to fhandler_socket.cc. | ||||||
|  | 	* winsup.h: Add declaration for `ws2_32_handle'. | ||||||
|  |  | ||||||
| Thu Oct 26 11:51:59 2000  Corinna Vinschen <corinna@vinschen.de> | Thu Oct 26 11:51:59 2000  Corinna Vinschen <corinna@vinschen.de> | ||||||
|  |  | ||||||
| 	* dtable.cc (dtable::release): Check for socket. Change | 	* dtable.cc (dtable::release): Check for socket. Change | ||||||
|   | |||||||
| @@ -115,8 +115,8 @@ DLL_IMPORTS:=$(w32api_lib)/libkernel32.a | |||||||
| DLL_OFILES:=assert.o cygheap.o dcrt0.o debug.o delqueue.o dir.o dlfcn.o \ | DLL_OFILES:=assert.o cygheap.o dcrt0.o debug.o delqueue.o dir.o dlfcn.o \ | ||||||
| 	dll_init.o dtable.o environ.o  errno.o exceptions.o exec.o external.o \ | 	dll_init.o dtable.o environ.o  errno.o exceptions.o exec.o external.o \ | ||||||
| 	fcntl.o fhandler.o fhandler_clipboard.o fhandler_console.o \ | 	fcntl.o fhandler.o fhandler_clipboard.o fhandler_console.o \ | ||||||
| 	fhandler_floppy.o fhandler_mem.o \ | 	fhandler_floppy.o fhandler_mem.o fhandler_random.o fhandler_raw.o \ | ||||||
| 	fhandler_random.o fhandler_raw.o fhandler_serial.o fhandler_tape.o \ | 	fhandler_serial.o fhandler_socket.o fhandler_tape.o \ | ||||||
| 	fhandler_termios.o fhandler_tty.o fhandler_windows.o fhandler_zero.o \ | 	fhandler_termios.o fhandler_tty.o fhandler_windows.o fhandler_zero.o \ | ||||||
| 	fork.o glob.o grp.o heap.o init.o ioctl.o localtime.o malloc.o \ | 	fork.o glob.o grp.o heap.o init.o ioctl.o localtime.o malloc.o \ | ||||||
| 	miscfuncs.o mmap.o \ | 	miscfuncs.o mmap.o \ | ||||||
|   | |||||||
| @@ -29,7 +29,7 @@ details. */ | |||||||
|      fhandler_dev_tape    (fhandler_tape.cc) |      fhandler_dev_tape    (fhandler_tape.cc) | ||||||
|  |  | ||||||
|      fhandler_pipe |      fhandler_pipe | ||||||
|      fhandler_socket      (net.cc) |      fhandler_socket      (fhandler_socket.cc) | ||||||
|  |  | ||||||
|      fhandler_tty_slave   (tty.cc) |      fhandler_tty_slave   (tty.cc) | ||||||
|      fhandler_pty_master  (tty.cc) |      fhandler_pty_master  (tty.cc) | ||||||
|   | |||||||
							
								
								
									
										310
									
								
								winsup/cygwin/fhandler_socket.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										310
									
								
								winsup/cygwin/fhandler_socket.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,310 @@ | |||||||
|  | /* fhandler_socket.cc. See fhandler.h for a description of the fhandler classes. | ||||||
|  |  | ||||||
|  |    Copyright 2000 Cygnus Solutions. | ||||||
|  |  | ||||||
|  |    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__ | ||||||
|  |  | ||||||
|  | #define Win32_Winsock | ||||||
|  | #include "winsup.h" | ||||||
|  | #include <errno.h> | ||||||
|  | #include <sys/socket.h> | ||||||
|  |  | ||||||
|  | #include <unistd.h> | ||||||
|  | #include <fcntl.h> | ||||||
|  | #include <winsock2.h> | ||||||
|  | #include "cygheap.h" | ||||||
|  | #include "cygerrno.h" | ||||||
|  | #include "fhandler.h" | ||||||
|  | #include "dtable.h" | ||||||
|  | #include "sigproc.h" | ||||||
|  |  | ||||||
|  | /**********************************************************************/ | ||||||
|  | /* fhandler_socket */ | ||||||
|  |  | ||||||
|  | fhandler_socket::fhandler_socket (const char *name) : | ||||||
|  | 	fhandler_base (FH_SOCKET, name) | ||||||
|  | { | ||||||
|  |   set_cb (sizeof *this); | ||||||
|  |   set_need_fork_fixup (); | ||||||
|  |   prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF, | ||||||
|  |   					         sizeof (WSAPROTOCOL_INFOA)); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fhandler_socket::~fhandler_socket () | ||||||
|  | { | ||||||
|  |   if (prot_info_ptr) | ||||||
|  |     cfree (prot_info_ptr); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void | ||||||
|  | fhandler_socket::fixup_before_fork_exec (DWORD win_proc_id) | ||||||
|  | { | ||||||
|  |   int ret = 1; | ||||||
|  |  | ||||||
|  |   if (prot_info_ptr && | ||||||
|  |       (ret = WSADuplicateSocketA (get_socket (), win_proc_id, prot_info_ptr))) | ||||||
|  |     { | ||||||
|  |       debug_printf ("WSADuplicateSocket error"); | ||||||
|  |       set_winsock_errno (); | ||||||
|  |     } | ||||||
|  |   if (!ret && ws2_32_handle) | ||||||
|  |     { | ||||||
|  |       debug_printf ("WSADuplicateSocket went fine, dwServiceFlags1=%d", | ||||||
|  | 		    prot_info_ptr->dwServiceFlags1); | ||||||
|  |     } | ||||||
|  |   else | ||||||
|  |     { | ||||||
|  |       fhandler_base::fixup_before_fork_exec (win_proc_id); | ||||||
|  |       debug_printf ("Without Winsock 2.0"); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void | ||||||
|  | fhandler_socket::fixup_after_fork (HANDLE parent) | ||||||
|  | { | ||||||
|  |   SOCKET new_sock = INVALID_SOCKET; | ||||||
|  |  | ||||||
|  |   debug_printf ("WSASocket begin, dwServiceFlags1=%d", | ||||||
|  | 		prot_info_ptr->dwServiceFlags1); | ||||||
|  |   if (prot_info_ptr && | ||||||
|  |       (new_sock = WSASocketA (FROM_PROTOCOL_INFO, | ||||||
|  |                               FROM_PROTOCOL_INFO, | ||||||
|  |                               FROM_PROTOCOL_INFO, | ||||||
|  |                               prot_info_ptr, 0, 0)) == INVALID_SOCKET) | ||||||
|  |     { | ||||||
|  |       debug_printf ("WSASocket error"); | ||||||
|  |       set_winsock_errno (); | ||||||
|  |     } | ||||||
|  |   if (new_sock != INVALID_SOCKET && ws2_32_handle) | ||||||
|  |     { | ||||||
|  |       debug_printf ("WSASocket went fine"); | ||||||
|  |       set_io_handle ((HANDLE) new_sock); | ||||||
|  |     } | ||||||
|  |   else | ||||||
|  |     { | ||||||
|  |       fhandler_base::fixup_after_fork (parent); | ||||||
|  |       debug_printf ("Without Winsock 2.0"); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int | ||||||
|  | fhandler_socket::dup (fhandler_base *child) | ||||||
|  | { | ||||||
|  |   fhandler_socket *fhs = (fhandler_socket *) child; | ||||||
|  |   fhs->set_io_handle (get_io_handle ()); | ||||||
|  |   fhs->fixup_before_fork_exec (GetCurrentProcessId ()); | ||||||
|  |   if (ws2_32_handle) | ||||||
|  |     { | ||||||
|  |       fhs->fixup_after_fork (hMainProc); | ||||||
|  |       return 0; | ||||||
|  |     } | ||||||
|  |   return fhandler_base::dup (child); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int | ||||||
|  | fhandler_socket::read (void *ptr, size_t len) | ||||||
|  | { | ||||||
|  |   sigframe thisframe (mainthread); | ||||||
|  |   int res = recv (get_socket (), (char *) ptr, len, 0); | ||||||
|  |   if (res == SOCKET_ERROR) | ||||||
|  |     { | ||||||
|  |       set_winsock_errno (); | ||||||
|  |     } | ||||||
|  |   return res; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int | ||||||
|  | fhandler_socket::write (const void *ptr, size_t len) | ||||||
|  | { | ||||||
|  |   sigframe thisframe (mainthread); | ||||||
|  |   int res = send (get_socket (), (const char *) ptr, len, 0); | ||||||
|  |   if (res == SOCKET_ERROR) | ||||||
|  |     { | ||||||
|  |       set_winsock_errno (); | ||||||
|  |       if (get_errno () == ECONNABORTED || get_errno () == ECONNRESET) | ||||||
|  | 	_raise (SIGPIPE); | ||||||
|  |     } | ||||||
|  |   return res; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Cygwin internal */ | ||||||
|  | int | ||||||
|  | fhandler_socket::close () | ||||||
|  | { | ||||||
|  |   int res = 0; | ||||||
|  |   sigframe thisframe (mainthread); | ||||||
|  |  | ||||||
|  |   if (closesocket (get_socket ())) | ||||||
|  |     { | ||||||
|  |       set_winsock_errno (); | ||||||
|  |       res = -1; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |   return res; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #define ASYNC_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT) | ||||||
|  |  | ||||||
|  | /* Cygwin internal */ | ||||||
|  | int | ||||||
|  | fhandler_socket::ioctl (unsigned int cmd, void *p) | ||||||
|  | { | ||||||
|  |   extern int get_ifconf (struct ifconf *ifc, int what); /* net.cc */ | ||||||
|  |   int res; | ||||||
|  |   struct ifconf *ifc; | ||||||
|  |   struct ifreq *ifr; | ||||||
|  |   sigframe thisframe (mainthread); | ||||||
|  |  | ||||||
|  |   switch (cmd) | ||||||
|  |     { | ||||||
|  |     case SIOCGIFCONF: | ||||||
|  |       ifc = (struct ifconf *) p; | ||||||
|  |       if (ifc == 0) | ||||||
|  | 	{ | ||||||
|  | 	  set_errno (EINVAL); | ||||||
|  | 	  return -1; | ||||||
|  | 	} | ||||||
|  |       res = get_ifconf (ifc, cmd); | ||||||
|  |       if (res) | ||||||
|  | 	debug_printf ("error in get_ifconf\n"); | ||||||
|  |       break; | ||||||
|  |     case SIOCGIFFLAGS: | ||||||
|  |       ifr = (struct ifreq *) p; | ||||||
|  |       if (ifr == 0) | ||||||
|  | 	{ | ||||||
|  | 	  set_errno (EINVAL); | ||||||
|  | 	  return -1; | ||||||
|  | 	} | ||||||
|  |       ifr->ifr_flags = IFF_NOTRAILERS | IFF_UP | IFF_RUNNING; | ||||||
|  |       if (((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr | ||||||
|  |           == INADDR_LOOPBACK) | ||||||
|  |         ifr->ifr_flags |= IFF_LOOPBACK; | ||||||
|  |       else | ||||||
|  |         ifr->ifr_flags |= IFF_BROADCAST; | ||||||
|  |       res = 0; | ||||||
|  |       break; | ||||||
|  |     case SIOCGIFBRDADDR: | ||||||
|  |     case SIOCGIFNETMASK: | ||||||
|  |     case SIOCGIFADDR: | ||||||
|  |       { | ||||||
|  | 	char buf[2048]; | ||||||
|  | 	struct ifconf ifc; | ||||||
|  | 	ifc.ifc_len = sizeof (buf); | ||||||
|  | 	ifc.ifc_buf = buf; | ||||||
|  | 	struct ifreq *ifrp; | ||||||
|  |  | ||||||
|  | 	struct ifreq *ifr = (struct ifreq *) p; | ||||||
|  | 	if (ifr == 0) | ||||||
|  | 	  { | ||||||
|  | 	    debug_printf ("ifr == NULL\n"); | ||||||
|  | 	    set_errno (EINVAL); | ||||||
|  | 	    return -1; | ||||||
|  | 	  } | ||||||
|  |  | ||||||
|  | 	res = get_ifconf (&ifc, cmd); | ||||||
|  | 	if (res) | ||||||
|  | 	  { | ||||||
|  | 	    debug_printf ("error in get_ifconf\n"); | ||||||
|  | 	    break; | ||||||
|  | 	  } | ||||||
|  |  | ||||||
|  | 	debug_printf ("    name: %s\n", ifr->ifr_name); | ||||||
|  | 	for (ifrp = ifc.ifc_req; | ||||||
|  | 	     (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len; | ||||||
|  | 	     ++ifrp) | ||||||
|  | 	  { | ||||||
|  | 	    debug_printf ("testname: %s\n", ifrp->ifr_name); | ||||||
|  | 	    if (! strcmp (ifrp->ifr_name, ifr->ifr_name)) | ||||||
|  | 	      { | ||||||
|  | 		switch (cmd) | ||||||
|  | 		  { | ||||||
|  | 		  case SIOCGIFADDR: | ||||||
|  | 		    ifr->ifr_addr = ifrp->ifr_addr; | ||||||
|  | 		    break; | ||||||
|  | 		  case SIOCGIFBRDADDR: | ||||||
|  | 		    ifr->ifr_broadaddr = ifrp->ifr_broadaddr; | ||||||
|  | 		    break; | ||||||
|  | 		  case SIOCGIFNETMASK: | ||||||
|  | 		    ifr->ifr_netmask = ifrp->ifr_netmask; | ||||||
|  | 		    break; | ||||||
|  | 		  } | ||||||
|  | 		break; | ||||||
|  | 	      } | ||||||
|  | 	  } | ||||||
|  | 	if ((caddr_t) ifrp >= ifc.ifc_buf + ifc.ifc_len) | ||||||
|  | 	  { | ||||||
|  | 	    set_errno (EINVAL); | ||||||
|  | 	    return -1; | ||||||
|  | 	  } | ||||||
|  | 	break; | ||||||
|  |       } | ||||||
|  |     case FIOASYNC: | ||||||
|  |       res = WSAAsyncSelect (get_socket (), gethwnd (), WM_ASYNCIO, | ||||||
|  | 	      *(int *) p ? ASYNC_MASK : 0); | ||||||
|  |       syscall_printf ("Async I/O on socket %s", | ||||||
|  | 	      *(int *) p ? "started" : "cancelled"); | ||||||
|  |       set_async (*(int *) p); | ||||||
|  |       break; | ||||||
|  |     default: | ||||||
|  |       /* We must cancel WSAAsyncSelect (if any) before setting socket to | ||||||
|  |        * blocking mode | ||||||
|  |        */ | ||||||
|  |       if (cmd == FIONBIO && *(int *) p == 0) | ||||||
|  | 	WSAAsyncSelect (get_socket (), gethwnd (), 0, 0); | ||||||
|  |       res = ioctlsocket (get_socket (), cmd, (unsigned long *) p); | ||||||
|  |       if (res == SOCKET_ERROR) | ||||||
|  | 	  set_winsock_errno (); | ||||||
|  |       if (cmd == FIONBIO) | ||||||
|  | 	{ | ||||||
|  | 	  syscall_printf ("socket is now %sblocking", | ||||||
|  | 			    *(int *) p ? "un" : ""); | ||||||
|  | 	  /* Start AsyncSelect if async socket unblocked */ | ||||||
|  | 	  if (*(int *) p && get_async ()) | ||||||
|  | 	    WSAAsyncSelect (get_socket (), gethwnd (), WM_ASYNCIO, ASYNC_MASK); | ||||||
|  | 	} | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |   syscall_printf ("%d = ioctl_socket (%x, %x)", res, cmd, p); | ||||||
|  |   return res; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | int | ||||||
|  | fhandler_socket::fcntl (int cmd, void *arg) | ||||||
|  | { | ||||||
|  |   int res = 0; | ||||||
|  |   int request, current; | ||||||
|  |  | ||||||
|  |   switch (cmd) | ||||||
|  |     { | ||||||
|  |     case F_SETFL: | ||||||
|  |       { | ||||||
|  |         /* Care for the old O_NDELAY flag. If one of the flags is set, | ||||||
|  |            both flags are set. */ | ||||||
|  |         int new_flags = (int) arg; | ||||||
|  |         if (new_flags & (O_NONBLOCK | OLD_O_NDELAY)) | ||||||
|  |           new_flags |= O_NONBLOCK | OLD_O_NDELAY; | ||||||
|  |         request = (new_flags & O_NONBLOCK) ? 1 : 0; | ||||||
|  |         current = (get_flags () & O_NONBLOCK) ? 1 : 0; | ||||||
|  |         if (request != current && (res = ioctl (FIONBIO, &request))) | ||||||
|  |           break; | ||||||
|  |         if (request) | ||||||
|  |           set_flags (get_flags () | O_NONBLOCK | OLD_O_NDELAY); | ||||||
|  |         else | ||||||
|  |           set_flags (get_flags () & ~(O_NONBLOCK | OLD_O_NDELAY)); | ||||||
|  |         break; | ||||||
|  |       } | ||||||
|  |     default: | ||||||
|  |       res = fhandler_base::fcntl (cmd, arg); | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |   return res; | ||||||
|  | } | ||||||
|  |  | ||||||
| @@ -44,8 +44,7 @@ int __stdcall rresvport (int *); | |||||||
| int sscanf (const char *, const char *, ...); | int sscanf (const char *, const char *, ...); | ||||||
| } /* End of "C" section */ | } /* End of "C" section */ | ||||||
|  |  | ||||||
| extern HANDLE ws2_32_handle; | static WSADATA wsadata; | ||||||
| WSADATA wsadata; |  | ||||||
|  |  | ||||||
| /* Cygwin internal */ | /* Cygwin internal */ | ||||||
| static SOCKET __stdcall | static SOCKET __stdcall | ||||||
| @@ -1514,7 +1513,7 @@ out: | |||||||
|   ifc->ifc_len = cnt * sizeof (struct ifreq); |   ifc->ifc_len = cnt * sizeof (struct ifreq); | ||||||
| } | } | ||||||
|  |  | ||||||
| static int | int | ||||||
| get_ifconf (struct ifconf *ifc, int what) | get_ifconf (struct ifconf *ifc, int what) | ||||||
| { | { | ||||||
|   unsigned long lip, lnp; |   unsigned long lip, lnp; | ||||||
| @@ -1783,300 +1782,6 @@ endhostent (void) | |||||||
| { | { | ||||||
| } | } | ||||||
|  |  | ||||||
| /**********************************************************************/ |  | ||||||
| /* fhandler_socket */ |  | ||||||
|  |  | ||||||
| fhandler_socket::fhandler_socket (const char *name) : |  | ||||||
| 	fhandler_base (FH_SOCKET, name) |  | ||||||
| { |  | ||||||
|   set_cb (sizeof *this); |  | ||||||
|   set_need_fork_fixup (); |  | ||||||
|   prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF, |  | ||||||
|   					         sizeof (WSAPROTOCOL_INFOA)); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| fhandler_socket::~fhandler_socket () |  | ||||||
| { |  | ||||||
|   if (prot_info_ptr) |  | ||||||
|     cfree (prot_info_ptr); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void |  | ||||||
| fhandler_socket::fixup_before_fork_exec (DWORD win_proc_id) |  | ||||||
| { |  | ||||||
|   int ret = 1; |  | ||||||
|  |  | ||||||
|   if (prot_info_ptr && |  | ||||||
|       (ret = WSADuplicateSocketA (get_socket (), win_proc_id, prot_info_ptr))) |  | ||||||
|     { |  | ||||||
|       debug_printf ("WSADuplicateSocket error"); |  | ||||||
|       set_winsock_errno (); |  | ||||||
|     } |  | ||||||
|   if (!ret && ws2_32_handle) |  | ||||||
|     { |  | ||||||
|       debug_printf ("WSADuplicateSocket went fine, dwServiceFlags1=%d", |  | ||||||
| 		    prot_info_ptr->dwServiceFlags1); |  | ||||||
|     } |  | ||||||
|   else |  | ||||||
|     { |  | ||||||
|       fhandler_base::fixup_before_fork_exec (win_proc_id); |  | ||||||
|       debug_printf ("Without Winsock 2.0"); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void |  | ||||||
| fhandler_socket::fixup_after_fork (HANDLE parent) |  | ||||||
| { |  | ||||||
|   SOCKET new_sock = INVALID_SOCKET; |  | ||||||
|  |  | ||||||
|   debug_printf ("WSASocket begin, dwServiceFlags1=%d", |  | ||||||
| 		prot_info_ptr->dwServiceFlags1); |  | ||||||
|   if (prot_info_ptr && |  | ||||||
|       (new_sock = WSASocketA (FROM_PROTOCOL_INFO, |  | ||||||
|                               FROM_PROTOCOL_INFO, |  | ||||||
|                               FROM_PROTOCOL_INFO, |  | ||||||
|                               prot_info_ptr, 0, 0)) == INVALID_SOCKET) |  | ||||||
|     { |  | ||||||
|       debug_printf ("WSASocket error"); |  | ||||||
|       set_winsock_errno (); |  | ||||||
|     } |  | ||||||
|   if (new_sock != INVALID_SOCKET && ws2_32_handle) |  | ||||||
|     { |  | ||||||
|       debug_printf ("WSASocket went fine"); |  | ||||||
|       set_io_handle ((HANDLE) new_sock); |  | ||||||
|     } |  | ||||||
|   else |  | ||||||
|     { |  | ||||||
|       fhandler_base::fixup_after_fork (parent); |  | ||||||
|       debug_printf ("Without Winsock 2.0"); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int |  | ||||||
| fhandler_socket::dup (fhandler_base *child) |  | ||||||
| { |  | ||||||
|   fhandler_socket *fhs = (fhandler_socket *) child; |  | ||||||
|   fhs->set_io_handle (get_io_handle ()); |  | ||||||
|   fhs->fixup_before_fork_exec (GetCurrentProcessId ()); |  | ||||||
|   if (ws2_32_handle) |  | ||||||
|     { |  | ||||||
|       fhs->fixup_after_fork (hMainProc); |  | ||||||
|       return 0; |  | ||||||
|     } |  | ||||||
|   return fhandler_base::dup (child); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int |  | ||||||
| fhandler_socket::read (void *ptr, size_t len) |  | ||||||
| { |  | ||||||
|   sigframe thisframe (mainthread); |  | ||||||
|   int res = recv (get_socket (), (char *) ptr, len, 0); |  | ||||||
|   if (res == SOCKET_ERROR) |  | ||||||
|     { |  | ||||||
|       set_winsock_errno (); |  | ||||||
|     } |  | ||||||
|   return res; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int |  | ||||||
| fhandler_socket::write (const void *ptr, size_t len) |  | ||||||
| { |  | ||||||
|   sigframe thisframe (mainthread); |  | ||||||
|   int res = send (get_socket (), (const char *) ptr, len, 0); |  | ||||||
|   if (res == SOCKET_ERROR) |  | ||||||
|     { |  | ||||||
|       set_winsock_errno (); |  | ||||||
|       if (get_errno () == ECONNABORTED || get_errno () == ECONNRESET) |  | ||||||
| 	_raise (SIGPIPE); |  | ||||||
|     } |  | ||||||
|   return res; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Cygwin internal */ |  | ||||||
| int |  | ||||||
| fhandler_socket::close () |  | ||||||
| { |  | ||||||
|   int res = 0; |  | ||||||
|   sigframe thisframe (mainthread); |  | ||||||
|  |  | ||||||
|   if (closesocket (get_socket ())) |  | ||||||
|     { |  | ||||||
|       set_winsock_errno (); |  | ||||||
|       res = -1; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|   return res; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Cygwin internal */ |  | ||||||
| /* |  | ||||||
|  * Return the flags settings for an interface. |  | ||||||
|  */ |  | ||||||
| static int |  | ||||||
| get_if_flags (struct ifreq *ifr) |  | ||||||
| { |  | ||||||
|   struct sockaddr_in *sa = (struct sockaddr_in *) &ifr->ifr_addr; |  | ||||||
|  |  | ||||||
|   short flags = IFF_NOTRAILERS | IFF_UP | IFF_RUNNING; |  | ||||||
|   if (sa->sin_addr.s_addr == INADDR_LOOPBACK) |  | ||||||
|       flags |= IFF_LOOPBACK; |  | ||||||
|   else |  | ||||||
|       flags |= IFF_BROADCAST; |  | ||||||
|  |  | ||||||
|   ifr->ifr_flags = flags; |  | ||||||
|   return 0; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| #define ASYNC_MASK (FD_READ|FD_WRITE|FD_OOB|FD_ACCEPT|FD_CONNECT) |  | ||||||
|  |  | ||||||
| /* Cygwin internal */ |  | ||||||
| int |  | ||||||
| fhandler_socket::ioctl (unsigned int cmd, void *p) |  | ||||||
| { |  | ||||||
|   int res; |  | ||||||
|   struct ifconf *ifc; |  | ||||||
|   struct ifreq *ifr; |  | ||||||
|   sigframe thisframe (mainthread); |  | ||||||
|  |  | ||||||
|   switch (cmd) |  | ||||||
|     { |  | ||||||
|     case SIOCGIFCONF: |  | ||||||
|       ifc = (struct ifconf *) p; |  | ||||||
|       if (ifc == 0) |  | ||||||
| 	{ |  | ||||||
| 	  set_errno (EINVAL); |  | ||||||
| 	  return -1; |  | ||||||
| 	} |  | ||||||
|       res = get_ifconf (ifc, cmd); |  | ||||||
|       if (res) |  | ||||||
| 	debug_printf ("error in get_ifconf\n"); |  | ||||||
|       break; |  | ||||||
|     case SIOCGIFFLAGS: |  | ||||||
|       ifr = (struct ifreq *) p; |  | ||||||
|       if (ifr == 0) |  | ||||||
| 	{ |  | ||||||
| 	  set_errno (EINVAL); |  | ||||||
| 	  return -1; |  | ||||||
| 	} |  | ||||||
|       res = get_if_flags (ifr); |  | ||||||
|       break; |  | ||||||
|     case SIOCGIFBRDADDR: |  | ||||||
|     case SIOCGIFNETMASK: |  | ||||||
|     case SIOCGIFADDR: |  | ||||||
|       { |  | ||||||
| 	char buf[2048]; |  | ||||||
| 	struct ifconf ifc; |  | ||||||
| 	ifc.ifc_len = sizeof (buf); |  | ||||||
| 	ifc.ifc_buf = buf; |  | ||||||
| 	struct ifreq *ifrp; |  | ||||||
|  |  | ||||||
| 	struct ifreq *ifr = (struct ifreq *) p; |  | ||||||
| 	if (ifr == 0) |  | ||||||
| 	  { |  | ||||||
| 	    debug_printf ("ifr == NULL\n"); |  | ||||||
| 	    set_errno (EINVAL); |  | ||||||
| 	    return -1; |  | ||||||
| 	  } |  | ||||||
|  |  | ||||||
| 	res = get_ifconf (&ifc, cmd); |  | ||||||
| 	if (res) |  | ||||||
| 	  { |  | ||||||
| 	    debug_printf ("error in get_ifconf\n"); |  | ||||||
| 	    break; |  | ||||||
| 	  } |  | ||||||
|  |  | ||||||
| 	debug_printf ("    name: %s\n", ifr->ifr_name); |  | ||||||
| 	for (ifrp = ifc.ifc_req; |  | ||||||
| 	     (caddr_t) ifrp < ifc.ifc_buf + ifc.ifc_len; |  | ||||||
| 	     ++ifrp) |  | ||||||
| 	  { |  | ||||||
| 	    debug_printf ("testname: %s\n", ifrp->ifr_name); |  | ||||||
| 	    if (! strcmp (ifrp->ifr_name, ifr->ifr_name)) |  | ||||||
| 	      { |  | ||||||
| 		switch (cmd) |  | ||||||
| 		  { |  | ||||||
| 		  case SIOCGIFADDR: |  | ||||||
| 		    ifr->ifr_addr = ifrp->ifr_addr; |  | ||||||
| 		    break; |  | ||||||
| 		  case SIOCGIFBRDADDR: |  | ||||||
| 		    ifr->ifr_broadaddr = ifrp->ifr_broadaddr; |  | ||||||
| 		    break; |  | ||||||
| 		  case SIOCGIFNETMASK: |  | ||||||
| 		    ifr->ifr_netmask = ifrp->ifr_netmask; |  | ||||||
| 		    break; |  | ||||||
| 		  } |  | ||||||
| 		break; |  | ||||||
| 	      } |  | ||||||
| 	  } |  | ||||||
| 	if ((caddr_t) ifrp >= ifc.ifc_buf + ifc.ifc_len) |  | ||||||
| 	  { |  | ||||||
| 	    set_errno (EINVAL); |  | ||||||
| 	    return -1; |  | ||||||
| 	  } |  | ||||||
| 	break; |  | ||||||
|       } |  | ||||||
|     case FIOASYNC: |  | ||||||
|       res = WSAAsyncSelect (get_socket (), gethwnd (), WM_ASYNCIO, |  | ||||||
| 	      *(int *) p ? ASYNC_MASK : 0); |  | ||||||
|       syscall_printf ("Async I/O on socket %s", |  | ||||||
| 	      *(int *) p ? "started" : "cancelled"); |  | ||||||
|       set_async (*(int *) p); |  | ||||||
|       break; |  | ||||||
|     default: |  | ||||||
|       /* We must cancel WSAAsyncSelect (if any) before setting socket to |  | ||||||
|        * blocking mode |  | ||||||
|        */ |  | ||||||
|       if (cmd == FIONBIO && *(int *) p == 0) |  | ||||||
| 	WSAAsyncSelect (get_socket (), gethwnd (), 0, 0); |  | ||||||
|       res = ioctlsocket (get_socket (), cmd, (unsigned long *) p); |  | ||||||
|       if (res == SOCKET_ERROR) |  | ||||||
| 	  set_winsock_errno (); |  | ||||||
|       if (cmd == FIONBIO) |  | ||||||
| 	{ |  | ||||||
| 	  syscall_printf ("socket is now %sblocking", |  | ||||||
| 			    *(int *) p ? "un" : ""); |  | ||||||
| 	  /* Start AsyncSelect if async socket unblocked */ |  | ||||||
| 	  if (*(int *) p && get_async ()) |  | ||||||
| 	    WSAAsyncSelect (get_socket (), gethwnd (), WM_ASYNCIO, ASYNC_MASK); |  | ||||||
| 	} |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|   syscall_printf ("%d = ioctl_socket (%x, %x)", res, cmd, p); |  | ||||||
|   return res; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int |  | ||||||
| fhandler_socket::fcntl (int cmd, void *arg) |  | ||||||
| { |  | ||||||
|   int res = 0; |  | ||||||
|   int request, current; |  | ||||||
|  |  | ||||||
|   switch (cmd) |  | ||||||
|     { |  | ||||||
|     case F_SETFL: |  | ||||||
|       { |  | ||||||
|         /* Care for the old O_NDELAY flag. If one of the flags is set, |  | ||||||
|            both flags are set. */ |  | ||||||
|         int new_flags = (int) arg; |  | ||||||
|         if (new_flags & (O_NONBLOCK | OLD_O_NDELAY)) |  | ||||||
|           new_flags |= O_NONBLOCK | OLD_O_NDELAY; |  | ||||||
|         request = (new_flags & O_NONBLOCK) ? 1 : 0; |  | ||||||
|         current = (get_flags () & O_NONBLOCK) ? 1 : 0; |  | ||||||
|         if (request != current && (res = ioctl (FIONBIO, &request))) |  | ||||||
|           break; |  | ||||||
|         if (request) |  | ||||||
|           set_flags (get_flags () | O_NONBLOCK | OLD_O_NDELAY); |  | ||||||
|         else |  | ||||||
|           set_flags (get_flags () & ~(O_NONBLOCK | OLD_O_NDELAY)); |  | ||||||
|         break; |  | ||||||
|       } |  | ||||||
|     default: |  | ||||||
|       res = fhandler_base::fcntl (cmd, arg); |  | ||||||
|       break; |  | ||||||
|     } |  | ||||||
|   return res; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| static void | static void | ||||||
| wsock_init () | wsock_init () | ||||||
| { | { | ||||||
|   | |||||||
| @@ -173,6 +173,7 @@ void __stdcall window_terminate (void); | |||||||
|  |  | ||||||
| /* Globals that handle initialization of winsock in a child process. */ | /* Globals that handle initialization of winsock in a child process. */ | ||||||
| extern HANDLE wsock32_handle; | extern HANDLE wsock32_handle; | ||||||
|  | extern HANDLE ws2_32_handle; | ||||||
|  |  | ||||||
| /* Globals that handle initialization of netapi in a child process. */ | /* Globals that handle initialization of netapi in a child process. */ | ||||||
| extern HANDLE netapi32_handle; | extern HANDLE netapi32_handle; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user