* 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> | ||||
|  | ||||
| 	* 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_init.o dtable.o environ.o  errno.o exceptions.o exec.o external.o \ | ||||
| 	fcntl.o fhandler.o fhandler_clipboard.o fhandler_console.o \ | ||||
| 	fhandler_floppy.o fhandler_mem.o \ | ||||
| 	fhandler_random.o fhandler_raw.o fhandler_serial.o fhandler_tape.o \ | ||||
| 	fhandler_floppy.o fhandler_mem.o fhandler_random.o fhandler_raw.o \ | ||||
| 	fhandler_serial.o fhandler_socket.o fhandler_tape.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 \ | ||||
| 	miscfuncs.o mmap.o \ | ||||
|   | ||||
| @@ -29,7 +29,7 @@ details. */ | ||||
|      fhandler_dev_tape    (fhandler_tape.cc) | ||||
|  | ||||
|      fhandler_pipe | ||||
|      fhandler_socket      (net.cc) | ||||
|      fhandler_socket      (fhandler_socket.cc) | ||||
|  | ||||
|      fhandler_tty_slave   (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 *, ...); | ||||
| } /* End of "C" section */ | ||||
|  | ||||
| extern HANDLE ws2_32_handle; | ||||
| WSADATA wsadata; | ||||
| static WSADATA wsadata; | ||||
|  | ||||
| /* Cygwin internal */ | ||||
| static SOCKET __stdcall | ||||
| @@ -1514,7 +1513,7 @@ out: | ||||
|   ifc->ifc_len = cnt * sizeof (struct ifreq); | ||||
| } | ||||
|  | ||||
| static int | ||||
| int | ||||
| get_ifconf (struct ifconf *ifc, int what) | ||||
| { | ||||
|   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 | ||||
| wsock_init () | ||||
| { | ||||
|   | ||||
| @@ -173,6 +173,7 @@ void __stdcall window_terminate (void); | ||||
|  | ||||
| /* Globals that handle initialization of winsock in a child process. */ | ||||
| extern HANDLE wsock32_handle; | ||||
| extern HANDLE ws2_32_handle; | ||||
|  | ||||
| /* Globals that handle initialization of netapi in a child process. */ | ||||
| extern HANDLE netapi32_handle; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user