mirror of
				https://github.com/PowerShell/Win32-OpenSSH.git
				synced 2025-10-31 11:44:38 +01:00 
			
		
		
		
	ssh-agent.exe and ssh-add.exe code updated and fixed to work in Windows. For convenience of users, ssh-agent.exe starts a cmd shell with the "SSH_AUTH_SOCK" and "SSH_AGENT_PID" environment variables set. ssh-add.exe can be run immediately from the cmd shell. 'ssh-add -L" and "ssh-add id_rsa" and "ssh-add -d id_rsa" are 3 useful commands to list, add and delete keys from ssh-agent cache.
		
			
				
	
	
		
			2953 lines
		
	
	
		
			52 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2953 lines
		
	
	
		
			52 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Author: NoMachine <developers@nomachine.com>
 | |
|  *
 | |
|  * Copyright (c) 2009, 2012 NoMachine
 | |
|  * All rights reserved
 | |
|  *
 | |
|  * Support functions and system calls' replacements needed to let the
 | |
|  * software run on Win32 based operating systems.
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions
 | |
|  * are met:
 | |
|  *
 | |
|  * 1. Redistributions of source code must retain the above copyright
 | |
|  * notice, this list of conditions and the following disclaimer.
 | |
|  * 2. Redistributions in binary form must reproduce the above copyright
 | |
|  * notice, this list of conditions and the following disclaimer in the
 | |
|  * documentation and/or other materials provided with the distribution.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 | |
|  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 | |
|  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 | |
|  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 | |
|  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | |
|  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | |
|  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | |
|  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | |
|  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 | |
|  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| #include <winsock2.h>
 | |
| #include <errno.h>
 | |
| #include <stdio.h>
 | |
| #include <fcntl.h>
 | |
| #include <sys/types.h>
 | |
| #include <sys/stat.h>
 | |
| #ifndef __MINGW32__
 | |
| #include <Crtdbg.h>
 | |
| #endif
 | |
| 
 | |
| #include "sfds.h"
 | |
| 
 | |
| #define FAIL(X) if (X) goto fail
 | |
| 
 | |
| #undef  DEBUG
 | |
| 
 | |
| #ifdef WIN32
 | |
| #ifdef DEBUG
 | |
|   #define DBG_MSG(FMT, ...) debug3(FMT, ## ARGS)
 | |
| #else
 | |
|   #define DBG_MSG(FMT, ...)
 | |
| #endif
 | |
| #else
 | |
| #ifdef DEBUG
 | |
| #define DBG_MSG(FMT, ARGS...) debug3(FMT, ## ARGS)
 | |
| #else
 | |
| #define DBG_MSG(FMT, ARGS...)
 | |
| #endif
 | |
| #endif
 | |
| extern void debug(const char *fmt,...);
 | |
| extern void debug2(const char *fmt,...);
 | |
| extern void debug3(const char *fmt,...);
 | |
| extern void error(const char *fmt,...);
 | |
| extern void fatal(const char *fmt,...);
 | |
| 
 | |
| int glob_itissshclient = 0; // ssh client turns it to 1
 | |
| static int winsock_initialized = 0;
 | |
| 
 | |
| extern int logfd;
 | |
| 
 | |
| static FD_SET debug_sfds;
 | |
| static FD_SET crlf_sfds;
 | |
| 
 | |
| static fd_set read_sfd_set;
 | |
| static fd_set write_sfd_set;
 | |
| 
 | |
| #define MAX_THREADS 256
 | |
| #define TEST_READ   1
 | |
| #define TEST_WRITE  0
 | |
| 
 | |
| #define MSG_WAITALL 0x8
 | |
| 
 | |
| #ifdef WIN32
 | |
| #define STDIN_FILENO 0
 | |
| #define STDOUT_FILENO 1
 | |
| #define STDERR_FILENO 2
 | |
| #endif
 | |
| 
 | |
| int PassInputFd  = STDIN_FILENO;
 | |
| int PassOutputFd = STDOUT_FILENO;
 | |
| int PassErrorFd = STDERR_FILENO;
 | |
| 
 | |
| /*
 | |
|  * We store cookies for authorize 
 | |
|  * connections on AF_UNIX sockets here.
 | |
|  */
 | |
|  
 | |
| struct _SocketCookie
 | |
| { 
 | |
|   FILE *f;
 | |
|   int socket;
 | |
|   char *cookie;
 | |
| } SocketCookieMap[SFD_MAP_SIZE] = {0};
 | |
| 
 | |
| DWORD WINAPI selectThread(LPVOID lpParam);
 | |
| 
 | |
| typedef struct 
 | |
| {
 | |
|   HANDLE thread;
 | |
|   
 | |
|   DWORD thread_id;
 | |
|   
 | |
|   HANDLE semaphore1;
 | |
|   HANDLE semaphore2;
 | |
| 
 | |
|   int sfd;
 | |
|   int thread_no;
 | |
|   int test_type;
 | |
|   int signaled;
 | |
|   int exit;
 | |
|   int exited;
 | |
| } thread_data_t, *thread_data_p;
 | |
| 
 | |
| static thread_data_p thread_data_set[MAX_THREADS];
 | |
| 
 | |
| #define IS_WINSOCK_INITIALIZED() (winsock_initialized != 0)
 | |
| 
 | |
| void WSHELPinitialize();
 | |
| 
 | |
| /*
 | |
|  * FIXME. This function forces stopping all socket threads 
 | |
|  * at next select. This workaround nivelates problem with
 | |
|  * infinite hangs up in below scenario:
 | |
|  * 
 | |
|  * a) read select start.
 | |
|  * b) write select start.
 | |
|  * c) read select ends: SSH2_MSG_CHANNEL_CLOSE received.
 | |
|  * d) close input channel.
 | |
|  * e) now write select may never ends.
 | |
|  *
 | |
|  * We call this function after (d).
 | |
|  */
 | |
| 
 | |
| void StopSocketThreads()
 | |
| {
 | |
|   DBG_MSG("-> StopSocketThreads()...");
 | |
| 
 | |
|   FD_ZERO(&write_sfd_set);
 | |
|   FD_ZERO(&read_sfd_set);
 | |
|   
 | |
|   DBG_MSG("<- StopSocketThreads()...");
 | |
| }
 | |
| 
 | |
| 
 | |
| void read_sfd_set_add(int sfd)
 | |
| {
 | |
|   static int do_init = 1;
 | |
| 
 | |
|   if (do_init)
 | |
|   {
 | |
|     FD_ZERO(&read_sfd_set);
 | |
|     
 | |
|     do_init = 0;
 | |
|   }
 | |
| 
 | |
|   FD_SET((SOCKET) sfd, &read_sfd_set);
 | |
| }
 | |
| 
 | |
| 
 | |
| void write_sfd_set_add(int sfd)
 | |
| {
 | |
|   static int do_init = 1;
 | |
| 
 | |
|   if (do_init)
 | |
|   {
 | |
|     FD_ZERO(&write_sfd_set);
 | |
| 
 | |
|     do_init = 0;
 | |
|   }
 | |
| 
 | |
|   FD_SET((SOCKET) sfd, &write_sfd_set);
 | |
| }
 | |
| 
 | |
| 
 | |
| void debug_sfd(int sfd)
 | |
| {
 | |
|   static int do_init = 1;
 | |
| 
 | |
|   if (do_init)
 | |
|   {
 | |
|     FD_ZERO(&debug_sfds);
 | |
|     
 | |
|     do_init = 0;
 | |
|   }
 | |
| 
 | |
|   FD_SET((SOCKET) sfd, &debug_sfds);
 | |
| }
 | |
| 
 | |
| 
 | |
| void crlf_sfd(int sfd)
 | |
| {
 | |
|   static int do_init = 1;
 | |
| 
 | |
|   if (do_init)
 | |
|   {
 | |
|     FD_ZERO(&crlf_sfds);
 | |
|   
 | |
|     do_init = 0;
 | |
|   }
 | |
| 
 | |
|   FD_SET((SOCKET) sfd, &crlf_sfds);
 | |
| }
 | |
| 
 | |
| 
 | |
| static int getWSAErrno()
 | |
| {
 | |
|   int wsaerrno = WSAGetLastError();
 | |
| 
 | |
|   if (wsaerrno == WSAEWOULDBLOCK)
 | |
|   {
 | |
|     return EAGAIN;
 | |
|   }  
 | |
|   
 | |
|   if (wsaerrno == WSAEFAULT)
 | |
|   {
 | |
|     return EFAULT;
 | |
|   }
 | |
|   
 | |
|   if (wsaerrno == WSAEINVAL)
 | |
|   {
 | |
|     return EINVAL;
 | |
|   }  
 | |
|   
 | |
|   return wsaerrno;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPisatty(int sfd)
 | |
| {
 | |
|   int ret;
 | |
|   
 | |
|   /*
 | |
|    * We can only do this for console fds.
 | |
|    */
 | |
|   
 | |
|   if (sfd_is_console(sfd) && sfd >= 0)
 | |
|   {
 | |
|     //ret = _isatty(sfd_to_fd(sfd));
 | |
| 
 | |
|     return 1 ; //ret;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Not a tty.
 | |
|    */
 | |
|   
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPfstat(int sfd, struct stat *buf)
 | |
| {
 | |
|   int ret;
 | |
| 
 | |
|   struct _stat tmp;
 | |
|   
 | |
|   DBG_MSG("WSHELPfstat(sfd = %d, buf = %p)", sfd, buf);
 | |
| 
 | |
|   ret = _fstat(sfd_to_fd(sfd), &tmp);
 | |
| 
 | |
|   /*
 | |
|    * Handle errors.
 | |
|    */
 | |
|   
 | |
|   if (ret == -1)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
|     
 | |
|     debug("fstat() returned error, errno [%d]", errno);
 | |
|   
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   buf -> st_gid   = tmp.st_gid;
 | |
|   buf -> st_atime = tmp.st_atime;
 | |
|   buf -> st_ctime = tmp.st_ctime;
 | |
|   buf -> st_dev   = tmp.st_dev;
 | |
|   buf -> st_ino   = tmp.st_ino;
 | |
|   buf -> st_mode  = tmp.st_mode;
 | |
|   buf -> st_mtime = tmp.st_mtime;
 | |
|   buf -> st_nlink = tmp.st_nlink;
 | |
|   buf -> st_rdev  = tmp.st_rdev;
 | |
|   buf -> st_size  = tmp.st_size;
 | |
|   buf -> st_uid   = tmp.st_uid;
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| FILE* WSHELPfdopen(int sfd, const char *mode)
 | |
| {
 | |
|   FILE* ret;
 | |
| 
 | |
|   ret = fdopen(sfd_to_fd(sfd), mode);
 | |
| 
 | |
|   /*
 | |
|    * Handle errors.
 | |
|    */
 | |
|   
 | |
|   if (ret == NULL)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
| 
 | |
|     debug("fdopen() returned error, errno [%d]", errno);
 | |
|   
 | |
|     return NULL;
 | |
|   }
 | |
|   
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPpipe(int pfds[2])
 | |
| {
 | |
|   int ret;
 | |
| 
 | |
|   ret = _pipe(pfds, 1024, _O_BINARY);
 | |
| 
 | |
|   /*
 | |
|    * Handle errors.
 | |
|    */
 | |
|   
 | |
|   if (ret == -1)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
| 
 | |
|     debug("_pipe() returned error, errno [%d]", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   pfds[0] = allocate_sfd((int)pfds[0]);
 | |
| 
 | |
|   pfds[1] = allocate_sfd((int)pfds[1]);
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPdup(int oldsfd)
 | |
| {
 | |
|   int oldfd;
 | |
| 
 | |
|   int newfd;
 | |
|   
 | |
|   int newsfd;
 | |
| 
 | |
|   oldfd = sfd_to_fd(oldsfd);
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|   
 | |
|   errno = 0;
 | |
| 
 | |
|   /*
 | |
|    * Pass through to base layer.
 | |
|    */
 | |
|   
 | |
|   newfd = _dup(oldfd);
 | |
| 
 | |
|   /*
 | |
|    * Handle errors.
 | |
|    */
 | |
|   
 | |
|   if (newfd == -1)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
| 
 | |
|     debug("_dup() returned error, errno [%d]", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Map the socket.
 | |
|    */
 | |
|   
 | |
|   newsfd = allocate_sfd(newfd);
 | |
| 
 | |
|   return newsfd;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPdup2(int oldsfd, int newsfd)
 | |
| {
 | |
|   int oldfd;
 | |
|   int newfd;
 | |
| 
 | |
|   oldfd = sfd_to_fd(oldsfd);
 | |
|   newfd = sfd_to_fd(newsfd);
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|   
 | |
|   errno = 0;
 | |
| 
 | |
|   /*
 | |
|    * Pass through to base layer.
 | |
|    */
 | |
|   
 | |
|   newfd = _dup2(oldfd, newfd);
 | |
| 
 | |
|   /*
 | |
|    * Handle errors.
 | |
|    */
 | |
|   
 | |
|   if (newfd == -1)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
|     
 | |
|     debug("_dup2() returned error, errno [%d]", errno);
 | |
|   
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Map the socket.
 | |
|    */
 | |
|   
 | |
|   newsfd = allocate_sfd(newfd);
 | |
| 
 | |
|   return newsfd;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPopen(const char *pathname, int flags, ...)
 | |
| {
 | |
|   DBG_MSG("WSHELPopen(path = [%s], flags = [%d])", pathname, flags);
 | |
|   
 | |
|   va_list arguments;
 | |
|   int newfd;
 | |
|   int newsfd;
 | |
| 
 | |
|   va_start(arguments, flags);
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|   
 | |
|   errno = 0;
 | |
| 
 | |
|   /*
 | |
|    * Pass through to base layer.
 | |
|    */
 | |
|   
 | |
|   newfd = _open(pathname, flags, arguments);
 | |
| 
 | |
|   va_end(arguments);
 | |
| 
 | |
|   /*
 | |
|    * Handle errors.
 | |
|    */
 | |
|   
 | |
|   if (newfd == -1)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
| 
 | |
|     debug("_open() returned error, errno [%d]", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Map the socket.
 | |
|    */
 | |
|   
 | |
|   newsfd = allocate_sfd(newfd);
 | |
| 
 | |
| 
 | |
|   return newsfd;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPwopen(const wchar_t *pathname, int flags, ...)
 | |
| {
 | |
|   va_list arguments;
 | |
|   int newfd;
 | |
|   int newsfd;
 | |
| 
 | |
|   va_start(arguments, flags);
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|   
 | |
|   errno = 0;
 | |
| 
 | |
|   /*
 | |
|    * Pass through to base layer.
 | |
|    */
 | |
|   
 | |
|   newfd = _wopen(pathname, flags, arguments);
 | |
| 
 | |
|   va_end(arguments);
 | |
| 
 | |
|   /*
 | |
|    * Handle errors.
 | |
|    */
 | |
|   
 | |
|   if (newfd == -1)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
| 
 | |
|     debug("_wopen() returned error, errno [%d]", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Map the socket.
 | |
|    */
 | |
|   
 | |
|   newsfd = allocate_sfd(newfd);
 | |
| 
 | |
|   return newsfd;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPcreat(const char *pathname, int mode)
 | |
| {
 | |
|   int newfd;
 | |
|   int newsfd;
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|   
 | |
|   errno = 0;
 | |
| 
 | |
|   /*
 | |
|    * Pass through to base layer.
 | |
|    */
 | |
|   
 | |
|   newfd = _creat(pathname, mode);
 | |
| 
 | |
|   /*
 | |
|    * Handle errors.
 | |
|    */
 | |
|   
 | |
|   if (newfd == -1)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
| 
 | |
|     debug("_creat() returned error, errno [%d]", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Map the socket.
 | |
|    */
 | |
|   
 | |
|   newsfd = allocate_sfd(newfd);
 | |
| 
 | |
|   return newsfd;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPsocket(int af, int type, int protocol)
 | |
| {
 | |
|   SOCKET sock = -1;
 | |
|   
 | |
|   int sfd;
 | |
|   
 | |
|   /*
 | |
|    * Verify that winsock has been initialized.
 | |
|    */
 | |
|   
 | |
|   if (!IS_WINSOCK_INITIALIZED())
 | |
|   {
 | |
|     WSHELPinitialize();
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|   
 | |
|   errno = 0;
 | |
| 
 | |
|   switch(af)
 | |
|   {
 | |
|     /*
 | |
|      * AF_UNIX. We emulate unix socket by localhost tcp here.
 | |
|      */
 | |
|     
 | |
|     case AF_UNIX:
 | |
|     {
 | |
|       DBG_MSG("Creating AF_UNIX socket...");
 | |
|       
 | |
|       sock = socket(AF_INET, type, 0);
 | |
|       
 | |
|       break;
 | |
|     }
 | |
|     
 | |
|     /*
 | |
|      * We pass through to base layer as default.
 | |
|      */
 | |
|     
 | |
|     default:
 | |
|     {
 | |
|       DBG_MSG("Creating AF_INET socket...");
 | |
|       
 | |
|       sock = socket(af, type, protocol);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Handle errors.
 | |
|    */
 | |
|   
 | |
|   if (sock == INVALID_SOCKET)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
|     
 | |
|     debug("socket() returned error, errno [%d]", errno);
 | |
|     
 | |
|     DBG_MSG("Cannot create socket : errno = %u", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   DBG_MSG("Socket %u created.", sock);
 | |
|   
 | |
|   /*
 | |
|    * Map the socket to our fd.
 | |
|    */
 | |
|   
 | |
|   sfd = allocate_sfd((int) sock);
 | |
| 
 | |
|   return sfd;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPsetsockopt(int sfd, int level, int optname, const char* optval, int optlen)
 | |
| {
 | |
|   SOCKET sock;
 | |
|   
 | |
|   int ret;
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|   
 | |
|   errno = 0;
 | |
| 
 | |
|   /*
 | |
|    * Get the SOCKET.
 | |
|    */
 | |
|   
 | |
|   sock = (SOCKET) sfd_to_handle(sfd);
 | |
| 
 | |
|   /*
 | |
|    * Call the underlying function.
 | |
|    */
 | |
|   
 | |
|   ret = setsockopt(sock, level, optname, optval, optlen);
 | |
| 
 | |
|   /*
 | |
|    * Check for errors.
 | |
|    */
 | |
|   
 | |
|   if (ret == SOCKET_ERROR)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
|     
 | |
|     debug("setsockopt() returned error, errno [%d]", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPgetsockopt(int sfd, int level, int optname, char* optval, int* optlen)
 | |
| {
 | |
|   SOCKET sock;
 | |
|   
 | |
|   int ret;
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|   
 | |
|   errno = 0;
 | |
| 
 | |
|   /*
 | |
|    * Get the SOCKET.
 | |
|    */
 | |
|   
 | |
|   sock = (SOCKET) sfd_to_handle(sfd);
 | |
| 
 | |
|   /* 
 | |
|    * Call the underlying function.
 | |
|    */
 | |
|   
 | |
|   ret = getsockopt(sock, level, optname, optval, optlen);
 | |
| 
 | |
|   /*
 | |
|    * Check for errors.
 | |
|    */
 | |
|   
 | |
|   if (ret == SOCKET_ERROR)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
|    
 | |
|     debug("getsockopt() returned error, errno [%d]", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPgetsockname(int sfd, struct sockaddr* name, int* namelen)
 | |
| {
 | |
|   SOCKET sock;
 | |
|   
 | |
|   int ret;
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|   
 | |
|   errno = 0;
 | |
| 
 | |
|   /*
 | |
|    * Get the SOCKET.
 | |
|    */
 | |
|   
 | |
|   sock = (SOCKET) sfd_to_handle(sfd);
 | |
| 
 | |
|   /*
 | |
|    * Call the underlying function.
 | |
|    */
 | |
|   
 | |
|   ret = getsockname(sock, name, namelen);
 | |
| 
 | |
|   /*
 | |
|    * Check for errors.
 | |
|    */
 | |
|   
 | |
|   if (ret == SOCKET_ERROR)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
|    
 | |
|     debug("getsockname() returned error, errno [%d]", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPgetpeername(int sfd, struct sockaddr* name, int* namelen)
 | |
| {
 | |
|   SOCKET sock;
 | |
|   
 | |
|   int ret;
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|   
 | |
|   errno = 0;
 | |
| 
 | |
|   /*
 | |
|    * Get the SOCKET.
 | |
|    */
 | |
|   
 | |
|   sock = (SOCKET) sfd_to_handle(sfd);
 | |
| 
 | |
|   /*
 | |
|    * Call the underlying function.
 | |
|    */
 | |
| 
 | |
|   ret = getpeername(sock, name, namelen);
 | |
| 
 | |
|   /*
 | |
|    * Check for errors.
 | |
|    */
 | |
|   
 | |
|   if (ret == SOCKET_ERROR)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
|     
 | |
|     debug("getpeername() returned error, errno [%d]", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPioctlsocket(int sfd, long cmd, u_long* argp)
 | |
| {
 | |
|   SOCKET sock;
 | |
|   
 | |
|   int ret;
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|   
 | |
|   errno = 0;
 | |
| 
 | |
|   /*
 | |
|    * Get the SOCKET.
 | |
|    */
 | |
|   
 | |
|   sock = (SOCKET) sfd_to_handle(sfd);
 | |
| 
 | |
|   /*
 | |
|    * Call the underlying function.
 | |
|    */
 | |
|   
 | |
|   ret = ioctlsocket(sock, cmd, argp);
 | |
| 
 | |
|   /*
 | |
|    * Check for errors.
 | |
|    */
 | |
|   
 | |
|   if (ret == SOCKET_ERROR)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
|     
 | |
|     debug("ioctlsocket() returned error, errno [%d]", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPlisten(int sfd, int backlog)
 | |
| {
 | |
|   SOCKET sock;
 | |
|   
 | |
|   int ret;
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|   
 | |
|   errno = 0;
 | |
| 
 | |
|   /*
 | |
|    * Get the SOCKET.
 | |
|    */
 | |
|   
 | |
|   sock = (SOCKET) sfd_to_handle(sfd);
 | |
| 
 | |
|   /*
 | |
|    * Call the underlying function.
 | |
|    */
 | |
|  
 | |
|   ret = listen(sock, backlog);
 | |
| 
 | |
|   /*
 | |
|    * Check for errors.
 | |
|    */
 | |
|   
 | |
|   if (ret == SOCKET_ERROR)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
|    
 | |
|     debug("listen() returned error, errno [%d]", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPbind(int sfd, const struct sockaddr *name, int namelen)
 | |
| {
 | |
|   SOCKET sock = -1;
 | |
|   
 | |
|   int ret = SOCKET_ERROR;
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|  
 | |
|   errno = 0;
 | |
| 
 | |
|   /*
 | |
|    * Get the SOCKET.
 | |
|    */
 | |
|   
 | |
|   sock = (SOCKET) sfd_to_handle(sfd);
 | |
| 
 | |
|   switch(name -> sa_family)
 | |
|   {
 | |
|     /*
 | |
|      * We emulate unix socket here, by tcp socket binded to localhost.
 | |
|      */
 | |
|     
 | |
|     case AF_UNIX:
 | |
|     {
 | |
|       int len = 0;
 | |
| 
 | |
|       unsigned int i = 0;
 | |
|   
 | |
|       FILE *f = NULL;
 | |
|       
 | |
|       char cookie[64 + 1] = {0};
 | |
|   
 | |
|       struct sockaddr_in sin = {0};
 | |
|   
 | |
|       struct sockaddr_un *unixName = (struct sockaddr_un *) name;
 | |
| 
 | |
|       /*
 | |
|        * Bind socket to localhost:0.
 | |
|        */
 | |
|   
 | |
|       DBG_MSG("Binding socket %u to localhost:0...", (unsigned int) sock);
 | |
|   
 | |
|       sin.sin_family = AF_INET;
 | |
|       sin.sin_port = 0;
 | |
|       sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
 | |
| 
 | |
|       FAIL(bind(sock, (struct sockaddr *) &sin, sizeof(sin)));
 | |
|   
 | |
|       /*
 | |
|        * Retreave local name for socket.
 | |
|        */
 | |
|   
 | |
|       DBG_MSG("Retreaving socket's local name...");
 | |
|   
 | |
|       len = sizeof(sin);
 | |
|   
 | |
|       FAIL(getsockname(sock, (struct sockaddr *) &sin, &len));
 | |
| 
 | |
|       sin.sin_port = ntohs(sin.sin_port);
 | |
|   
 | |
|       DBG_MSG("family = %u", sin.sin_family);
 | |
|       DBG_MSG("port   = %u", sin.sin_port);
 | |
| 
 | |
|       /*
 | |
|        * Check is socket file already exists.
 | |
|        */
 | |
|   
 | |
|       DBG_MSG("Checking is socket file free...");
 | |
|   
 | |
|       WSASetLastError(WSAEADDRINUSE);
 | |
|       
 | |
|       f = fopen(unixName -> sun_path, "rt");
 | |
|   
 | |
|       FAIL(f);
 | |
|   
 | |
|       /*
 | |
|        * Create file with retrieved port and cookie.
 | |
|        * This file emulates unix socket itself.
 | |
|        */
 | |
|   
 | |
|       DBG_MSG("Creating socket file [%s]...", unixName -> sun_path);
 | |
|   
 | |
|       f = fopen(unixName -> sun_path, "wt+");
 | |
|  
 | |
|       FAIL(f == NULL);
 | |
|   
 | |
|       /*
 | |
|        * Write tcp port to soket file.
 | |
|        */
 | |
|       
 | |
|       fprintf(f, "%d ", sin.sin_port);
 | |
|    
 | |
|       /*
 | |
|        * Write 64-byte cookie to socket file.
 | |
|        * We add port number to rand() to avoid generating the same
 | |
|        * cookie until next second reached.
 | |
|        *
 | |
|        */
 | |
|       
 | |
|       for (i = 0; i < 64; i++)
 | |
|       {
 | |
|         cookie[i] = 33 + (rand() + sin.sin_port) % (128 - 33);
 | |
|       }
 | |
|       
 | |
|       cookie[64] = 0;
 | |
|       
 | |
|       fputs(cookie, f);
 | |
|       
 | |
|       fflush(f);
 | |
|       
 | |
|       /*
 | |
|        * Cache cookie and file handle in SocketCookieMap var.
 | |
|        */
 | |
|       
 | |
|       for (i = 0; i < SFD_MAP_SIZE; i++)
 | |
|       {
 | |
|         /*
 | |
|          * Find first empty row.
 | |
|          */
 | |
|         
 | |
|         if (SocketCookieMap[i].socket == 0)
 | |
|         {
 | |
|           SocketCookieMap[i].socket = sock;
 | |
|           SocketCookieMap[i].cookie = strdup(cookie);
 | |
|           SocketCookieMap[i].f      = f;
 | |
| 
 | |
|           /*
 | |
|           for (int i = 0; i < 64; j++)
 | |
|           {
 | |
|             printf("%02x ", SocketCookieMap[i].cookie[j]);
 | |
|           }
 | |
|           */
 | |
| 
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|  
 | |
|       /*
 | |
|        * Clear error.
 | |
|        */
 | |
|       
 | |
|       ret = 0;
 | |
|       
 | |
|       WSASetLastError(0);
 | |
|       
 | |
|       break;
 | |
|     }
 | |
|     
 | |
|     /*
 | |
|      * As default, we call underlying function.
 | |
|      */
 | |
|   
 | |
|     default:
 | |
|     {
 | |
|       ret = bind(sock, name, namelen);
 | |
|     }
 | |
|   }
 | |
| 
 | |
| fail:
 | |
|   
 | |
|   /*
 | |
|    * Check for errors.
 | |
|    */
 | |
|   
 | |
|   if (ret == SOCKET_ERROR)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
|    
 | |
|     debug("bind() returned error, errno [%d]", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPconnect(int sfd, const struct sockaddr* name, int namelen)
 | |
| {
 | |
|   SOCKET sock = -1;
 | |
| 
 | |
|   int ret = SOCKET_ERROR;
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|   
 | |
|   errno = 0;
 | |
|   
 | |
|   /*
 | |
|    * Get the SOCKET.
 | |
|    */
 | |
|   
 | |
|   sock = (SOCKET) sfd_to_handle(sfd);
 | |
| 
 | |
|   switch(name -> sa_family)
 | |
|   {
 | |
|     /*
 | |
|      * We emulate unix socket here, by tcp socket binded to localhost.
 | |
|      */
 | |
|     
 | |
|     case AF_UNIX:
 | |
|     {
 | |
|       int len  = 0;
 | |
|       int port = -1;
 | |
| 
 | |
|       char cookie[64 + 1] = {0};
 | |
| 
 | |
|       unsigned int i = 0;
 | |
|   
 | |
|       FILE *f = NULL;
 | |
|   
 | |
|       struct sockaddr_in sin = {0};
 | |
|   
 | |
|       struct sockaddr_un *unixName = (struct sockaddr_un *) name;
 | |
| 
 | |
|       /*
 | |
|        * Open socket file.
 | |
|        */
 | |
|       
 | |
|       DBG_MSG("Opening socket file [%s] for socket %u...",
 | |
|                   unixName -> sun_path, (unsigned int) sock);
 | |
|       
 | |
|       f = fopen(unixName -> sun_path, "rt");
 | |
|       
 | |
|       FAIL(f == NULL);
 | |
|       
 | |
|       /*
 | |
|        * Read tcp port and cokie from socket file.
 | |
|        */
 | |
|       
 | |
|       fscanf(f, "%d ", &port);
 | |
|       fgets(cookie, 64 + 1, f);
 | |
|       
 | |
|       fclose(f);
 | |
| 
 | |
|       /*
 | |
|        * Connect to localhost on given port.
 | |
|        */
 | |
|   
 | |
|       DBG_MSG("Connecting to localhost:%u on socket %u...", 
 | |
|                   port, (unsigned int) sock);
 | |
|   
 | |
|       sin.sin_family = AF_INET;
 | |
|       sin.sin_port = htons(port);
 | |
|       sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
 | |
| 
 | |
|       FAIL(connect(sock, (struct sockaddr *) &sin, sizeof(sin)));
 | |
|       
 | |
|       /*
 | |
|        * Send authorization cookie.
 | |
|        * If cookie doesn't match to cookie stored on server side
 | |
|        * server shutdown connection.
 | |
|        */
 | |
| 
 | |
|       DBG_MSG("Sending authorization cookie...\n");
 | |
|       
 | |
|       for (i = 0; i < 64; i++)
 | |
|       {
 | |
|         DBG_MSG("%02x ", cookie[i]);
 | |
|       }
 | |
|       
 | |
|       DBG_MSG("\n");
 | |
|       
 | |
|       
 | |
|       ret = send(sock, cookie, 64, MSG_DONTROUTE);
 | |
|     
 | |
|       FAIL(ret != 64);
 | |
| 
 | |
|       /*
 | |
|        * Clear error.
 | |
|        */
 | |
|       
 | |
|       ret = 0;
 | |
|       
 | |
|       break;
 | |
|     }
 | |
|     
 | |
|     /*
 | |
|      * As default, we call underlying function.
 | |
|      */
 | |
| 
 | |
|     default:
 | |
|     {
 | |
|       /*
 | |
|        * Call the underlying function as default.
 | |
|        */
 | |
|   
 | |
|       ret = connect(sock, name, namelen);
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   /*
 | |
|    * Check for errors.
 | |
|    */
 | |
|   
 | |
| fail:
 | |
| 
 | |
|   if (ret == SOCKET_ERROR)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
|    
 | |
|     debug("connect() returned error, errno [%d]", errno);
 | |
| 
 | |
|     DBG_MSG("connect() returned error, errno [%d]\n", errno);
 | |
|   
 | |
|     /*
 | |
|      * Re-map EAGAIN for connect() semantics.
 | |
|      */
 | |
|     
 | |
|     if (errno == EAGAIN)
 | |
|     {
 | |
|       errno = WSAEINPROGRESS;
 | |
|     }  
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPshutdown(int sfd, int how)
 | |
| {
 | |
|   SOCKET sock;
 | |
|   
 | |
|   int ret;
 | |
| 
 | |
|   /*
 | |
|    * Clear errno.
 | |
|    */
 | |
|   
 | |
|   errno = 0;
 | |
| 
 | |
|   /*
 | |
|    * Get the SOCKET.
 | |
|    */
 | |
|   
 | |
|   sock = (SOCKET) sfd_to_handle(sfd);
 | |
| 
 | |
|   /*
 | |
|    * Call the underlying function.
 | |
|    */
 | |
|   
 | |
|   ret = shutdown(sock, how);
 | |
| 
 | |
|   /*
 | |
|    * Check for errors.
 | |
|    */
 | |
|   
 | |
|   if (ret == SOCKET_ERROR)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
|    
 | |
|     debug("shutdown() returned error, errno [%d]", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPaccept(int sfd, struct sockaddr* addr, int* addrlen)
 | |
| {
 | |
|   SOCKET sock;
 | |
|   
 | |
|   SOCKET new_sock;
 | |
|   
 | |
|   int new_sfd;
 | |
|   
 | |
|   int i = 0;
 | |
|   int j = 0;
 | |
|   int ret = -1;
 | |
| 
 | |
|   int expectedFamily = addr -> sa_family;
 | |
|   
 | |
|   /*
 | |
|    * Clear errno
 | |
|    */
 | |
| 
 | |
|   errno = 0;
 | |
| 
 | |
|   /*
 | |
|    * Get the SOCKET
 | |
|    */
 | |
| 
 | |
|   sock = (SOCKET) sfd_to_handle(sfd);
 | |
| 
 | |
|   /*
 | |
|    * Call the underlying function
 | |
|    */
 | |
| 
 | |
|   new_sock = accept(sock, addr, addrlen);
 | |
| 
 | |
|   switch(expectedFamily)  
 | |
|   {
 | |
|     /*
 | |
|      * Cookie authorization for AF_UNIX.
 | |
|      */
 | |
|     
 | |
|     case AF_UNIX:
 | |
|     {
 | |
|       fd_set readsocks;
 | |
| 
 | |
|       struct timeval timeout = {10, 0};
 | |
| 
 | |
|       char remoteCookie[64 + 1] = {0};
 | |
| 
 | |
|       int authorized = 0;
 | |
|       
 | |
|       /*
 | |
|        * Retrieave 64-byte authorization cookie from client.
 | |
|        */
 | |
| 
 | |
|       DBG_MSG("Waiting for 64-byte cookie...\n");
 | |
| 
 | |
|       FD_ZERO(&readsocks);
 | |
|       FD_SET((SOCKET) new_sock, &readsocks);
 | |
| 
 | |
|       select(0, &readsocks, NULL, NULL, &timeout);
 | |
| 
 | |
|       ret = recv(new_sock, remoteCookie, 64, 0);
 | |
| 
 | |
| 
 | |
|       #ifdef DEBUG
 | |
| 
 | |
|       DBG_MSG("\nRemoteCookie = [");
 | |
| 
 | |
|       for (i = 0; remoteCookie[i]; i++)
 | |
|       {
 | |
|         DBG_MSG("%02x ", remoteCookie[i]);
 | |
|       }
 | |
| 
 | |
|       DBG_MSG("]\n\n");
 | |
| 
 | |
|       #endif
 | |
| 
 | |
|       /*
 | |
|        * Find correct cookie in SocketCookieMap.
 | |
|        */
 | |
| 
 | |
|       for (i = 0; i < SFD_MAP_SIZE; i++)
 | |
|       {
 | |
|         /*
 | |
|          * Find socket.
 | |
|          */
 | |
| 
 | |
|         if (SocketCookieMap[i].socket == sock)
 | |
|         {
 | |
|           #ifdef DEBUG
 | |
| 
 | |
|           DBG_MSG("\nServerCookie = [");
 | |
| 
 | |
|           for (j = 0; SocketCookieMap[i].cookie[j]; j++)
 | |
|           {
 | |
|             DBG_MSG("%02x ", SocketCookieMap[i].cookie[j]);
 | |
|           }
 | |
| 
 | |
|           DBG_MSG("]\n\n");
 | |
| 
 | |
|           #endif
 | |
| 
 | |
|           /*
 | |
|            * Compare cookies.
 | |
|            */
 | |
| 
 | |
|           if (strncmp(SocketCookieMap[i].cookie, remoteCookie, 64) == 0)
 | |
|           {
 | |
|             authorized = 1;
 | |
|           }
 | |
| 
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
|       
 | |
|       /*
 | |
|        * Cookies doesn't match. Shutdown connection.
 | |
|        */
 | |
| 
 | |
|       if (authorized == 0)
 | |
|       {
 | |
|         DBG_MSG("ERROR. Accept from unathorized client."
 | |
|                     " I'm going to shutdown connection.\n");
 | |
| 
 | |
|         shutdown(new_sock, SD_BOTH);
 | |
| 
 | |
|         new_sock = INVALID_SOCKET;
 | |
|       }  
 | |
| 
 | |
|       break;
 | |
|     }
 | |
|     
 | |
|     default:
 | |
|     {
 | |
|     }
 | |
|   }
 | |
|   
 | |
|   /*
 | |
|    * Handle errors
 | |
|    */
 | |
| 
 | |
|   if (new_sock == INVALID_SOCKET)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
|     
 | |
|     debug("accept() returned error, errno [%d]", errno);
 | |
|     
 | |
|     return -1;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Map the socket
 | |
|    */
 | |
|   
 | |
|   new_sfd = allocate_sfd((int)new_sock);
 | |
| 
 | |
|   return new_sfd;
 | |
| }
 | |
| 
 | |
| 
 | |
| int socketpair(int socks[2])
 | |
| {
 | |
|   struct sockaddr_in addr;
 | |
| 
 | |
|   SOCKET listener;
 | |
| 
 | |
|   int e;
 | |
| 
 | |
|   int addrlen = sizeof(addr);
 | |
| 
 | |
|   /*
 | |
|    * Clear out last error.
 | |
|    */
 | |
| 
 | |
|   errno = 0;
 | |
| 
 | |
|   if (socks == 0)
 | |
|   {
 | |
|     WSASetLastError(WSAEINVAL);
 | |
| 
 | |
|     errno = getWSAErrno();
 | |
|     
 | |
|     return SOCKET_ERROR;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Initialize to invalid sockets.
 | |
|    */
 | |
|   
 | |
|   socks[0] = socks[1] = INVALID_SOCKET;
 | |
|   
 | |
|   if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
 | |
|   {
 | |
|     errno = getWSAErrno();
 | |
|     
 | |
|     return SOCKET_ERROR;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Zero out the structure and set params.
 | |
|    */
 | |
|   
 | |
|   memset(&addr, 0, sizeof(addr));
 | |
| 
 | |
|   addr.sin_family      = AF_INET;
 | |
|   addr.sin_addr.s_addr = htonl(0x7f000001);
 | |
|   addr.sin_port        = 0;
 | |
| 
 | |
|   /*
 | |
|    * Call base function.
 | |
|    */
 | |
| 
 | |
|   e = bind(listener, (const struct sockaddr*) &addr, sizeof(addr));
 | |
|   
 | |
|   if (e == SOCKET_ERROR)
 | |
|   {
 | |
|     e = WSAGetLastError();
 | |
|     
 | |
|     closesocket(listener);
 | |
|     
 | |
|     WSASetLastError(e);
 | |
|     
 | |
|     errno = getWSAErrno();
 | |
|     
 | |
|     return SOCKET_ERROR;
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Find out what ephermeral port got assigned.
 | |
|    */
 | |
|   
 | |
|   e = getsockname(listener, (struct sockaddr*) &addr, &addrlen);
 | |
|   
 | |
|   if (e == SOCKET_ERROR)
 | |
|   {
 | |
|     e = WSAGetLastError();
 | |
|     
 | |
|     closesocket(listener);
 | |
|    
 | |
|     WSASetLastError(e);
 | |
|     
 | |
|     errno = getWSAErrno();
 | |
|     
 | |
|     return SOCKET_ERROR;
 | |
|   }
 | |
| 
 | |
|   do
 | |
|   {
 | |
|     if (listen(listener, 1) == SOCKET_ERROR)
 | |
|     {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     if ((socks[0] = (int) WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, 0)) == (int) INVALID_SOCKET)
 | |
|     {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     if (connect(socks[0], (const struct sockaddr*) &addr, sizeof(addr)) == SOCKET_ERROR)
 | |
|     {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     if ((socks[1] = (int) accept(listener, NULL, NULL)) == (int) INVALID_SOCKET)
 | |
|     {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * Don't need to listen anymore.
 | |
|      */
 | |
|     
 | |
|     closesocket(listener);
 | |
| 
 | |
|     /*
 | |
|      * Maps the sockets.
 | |
|      */
 | |
|     
 | |
|     socks[0] = allocate_sfd((int)socks[0]);
 | |
|     socks[1] = allocate_sfd((int)socks[1]);
 | |
| 
 | |
|     /*
 | |
|      * All set, return the socket pair.
 | |
|      */
 | |
|     
 | |
|     return 0;
 | |
|   } while (0);
 | |
| 
 | |
|   /*
 | |
|    * Cleanup and return if we bailed out of creation above.
 | |
|    */
 | |
|   
 | |
|   e = WSAGetLastError();
 | |
|   
 | |
|   closesocket(listener);
 | |
|   
 | |
|   closesocket(socks[0]);
 | |
|   
 | |
|   closesocket(socks[1]);
 | |
|   
 | |
|   WSASetLastError(e);
 | |
|   
 | |
|   errno = getWSAErrno();
 | |
| 
 | |
|   socks[0] = INVALID_SOCKET;
 | |
|   socks[1] = INVALID_SOCKET;
 | |
| 
 | |
|   return SOCKET_ERROR;
 | |
| }
 | |
| 
 | |
| int DataAvailable ( HANDLE h )
 | |
| {
 | |
|     INPUT_RECORD irec = {0};
 | |
| 
 | |
|     DWORD events_read = 0;
 | |
| 
 | |
|     int ret = PeekConsoleInput (h, &irec, 1, &events_read);
 | |
| 
 | |
|     if (!ret)
 | |
|     {
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     if (events_read) // && irec.EventType == KEY_EVENT)
 | |
|     {
 | |
|       return events_read ;
 | |
|     }
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| int peekConsoleRead(int sfd)
 | |
| {
 | |
|   DWORD sleep_time = 0;
 | |
| 
 | |
|   HANDLE h = sfd_to_handle(sfd);
 | |
| 
 | |
|   if (h == INVALID_HANDLE_VALUE)
 | |
|   {
 | |
|     error("can't get a handle for sfd [%d]", sfd);
 | |
| 
 | |
|     return 0;
 | |
|   }
 | |
|   
 | |
|   FlushConsoleInputBuffer(h);
 | |
|   
 | |
|   for (;;)
 | |
|   {
 | |
|     INPUT_RECORD irec = {0};
 | |
| 
 | |
|     DWORD events_read = 0;
 | |
| 
 | |
|     int ret = PeekConsoleInput (h, &irec, 1, &events_read);
 | |
| 
 | |
|     if (!ret)
 | |
|     {
 | |
|       debug("PeekConsoleInput on sfd [%d] failed with error code [%d]",
 | |
|                  sfd, GetLastError());
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     if (events_read && irec.EventType == KEY_EVENT)
 | |
|     {
 | |
|       break;
 | |
|     }
 | |
|     else if (events_read)
 | |
|     {
 | |
|       ReadConsoleInput (h, &irec, 1, &events_read);
 | |
|     }
 | |
| 
 | |
|     Sleep (sleep_time >> 3);
 | |
|     
 | |
|     if (sleep_time < 80)
 | |
|     {
 | |
|       sleep_time++;
 | |
|     }  
 | |
|   }
 | |
| 
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| int peekConsoleWrite(int sfd)
 | |
| {
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| int peekPipeRead(int sfd)
 | |
| {
 | |
|   HANDLE h;
 | |
| 
 | |
|   DWORD n = 0;
 | |
|   
 | |
|   DWORD pFlags = 0;
 | |
|   
 | |
|   DWORD sleep_time = 0;
 | |
|   
 | |
|   int ret = 0;
 | |
| 
 | |
|   h = sfd_to_handle(sfd);
 | |
| 
 | |
|   if (h == INVALID_HANDLE_VALUE)
 | |
|   {
 | |
|     error("can't get a handle for sfd [%d]", sfd);
 | |
|     
 | |
|     return 0;
 | |
|   } 
 | |
| 
 | |
|   ret = GetNamedPipeInfo(h, &pFlags, NULL, NULL, NULL);
 | |
| 
 | |
|   if (!ret)
 | |
|   {
 | |
|     error("GetNamedPipeInfo on sfd [%d] failed with error code [%d]",
 | |
|               sfd, GetLastError());
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   for (;;)
 | |
|   {
 | |
|     ret = PeekNamedPipe (h, NULL, 0, NULL, &n, NULL);
 | |
| 
 | |
|     if (!ret)
 | |
|     {
 | |
|       //error("PeekNamedPipe on sfd [%d] failed with error code [%d]",
 | |
|       //          sfd, GetLastError());
 | |
|       return 0;
 | |
|     }
 | |
| 
 | |
|     if (n > 0)
 | |
|     {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     Sleep (sleep_time >> 3);
 | |
|     
 | |
|     if (sleep_time < 80)
 | |
|     {
 | |
|       sleep_time++;
 | |
|     }  
 | |
|   }
 | |
| 
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| int peekPipeWrite(int sfd)
 | |
| {
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| int selectSocketRead(int sfd)
 | |
| {
 | |
|   DBG_MSG("-> selectSocketRead(sfd = %d)...\n", sfd);
 | |
|   
 | |
|   int ret = 0;
 | |
| 
 | |
|   fd_set readsocks;
 | |
|   
 | |
|   struct timeval timeout = {1, 0};
 | |
| 
 | |
|   FD_ZERO(&readsocks);
 | |
| 
 | |
|   FD_SET((SOCKET) sfd_to_handle(sfd), &readsocks);
 | |
| 
 | |
|   
 | |
|   DBG_MSG("selectSocketRead(sfd = %d) : readsocks.fd_count = %d\n", sfd, readsocks.fd_count);
 | |
|   
 | |
|   DBG_MSG("selectSocketRead(sfd = %d, socket = %d) : select...\n", 
 | |
|               (int) sfd, (int) sfd_to_handle(sfd));
 | |
|   
 | |
|   while(ret == 0)
 | |
|   {
 | |
|     FD_ZERO(&readsocks);
 | |
| 
 | |
|     FD_SET((SOCKET) sfd_to_handle(sfd), &readsocks);
 | |
| 
 | |
|     ret = select(0, &readsocks, NULL, NULL, &timeout);
 | |
|   }
 | |
|   
 | |
|   DBG_MSG("selectSocketRead(sfd = %d, socket = %d) : end select...\n", 
 | |
|               (int) sfd, (int) sfd_to_handle(sfd));
 | |
| 
 | |
|   /*
 | |
|    * Bail if select failed for some reason.
 | |
|    */
 | |
|   
 | |
|   if (ret == SOCKET_ERROR)
 | |
|   {
 | |
|     error("select on sfd [%d] failed with error code [%d]",
 | |
|               sfd, GetLastError());
 | |
| 
 | |
|     DBG_MSG("<- selectSocketRead(sfd = %d)...\n", sfd);
 | |
| 
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   DBG_MSG("<- selectSocketRead(sfd = %d)...\n", sfd);
 | |
|   
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| int selectSocketWrite(int sfd)
 | |
| {
 | |
|   DBG_MSG("-> selectSocketWrite(sfd = %d)...\n", sfd);
 | |
|   
 | |
|   int ret = 0;
 | |
| 
 | |
|   fd_set writesocks;
 | |
|   
 | |
|   struct timeval timeout = {1, 0};
 | |
| 
 | |
|   FD_ZERO(&writesocks);
 | |
| 
 | |
|   FD_SET((SOCKET) sfd_to_handle(sfd), &writesocks);
 | |
| 
 | |
|   DBG_MSG("selectSocketWrite(sfd = %d) : writesocks.fd_count = %d...\n", sfd, writesocks.fd_count);
 | |
| 
 | |
|   DBG_MSG("selectSocketWrite(sfd = %d, socket = %d) : select...\n", 
 | |
|               (int) sfd, (int) sfd_to_handle(sfd));
 | |
| 
 | |
|   while (ret == 0)
 | |
|   {
 | |
|     FD_ZERO(&writesocks);
 | |
| 
 | |
|     FD_SET((SOCKET) sfd_to_handle(sfd), &writesocks);
 | |
| 
 | |
|     ret = select(0, NULL, &writesocks, NULL, &timeout);
 | |
|   }
 | |
|   
 | |
|   DBG_MSG("selectSocketWrite(sfd = %d, socket = %d) : end select...\n", 
 | |
|               (int) sfd, (int) sfd_to_handle(sfd));
 | |
| 
 | |
|   /*
 | |
|    * Fail if select failed for some reason.
 | |
|    */
 | |
| 
 | |
|   if (ret == SOCKET_ERROR)
 | |
|   {
 | |
|     error("select on sfd [%d] failed with error code [%d]",
 | |
|               sfd, GetLastError());
 | |
|           
 | |
|     DBG_MSG("<- selectSocketWrite(sfd = %d)...\n", sfd);
 | |
|           
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   DBG_MSG("<- selectSocketWrite(sfd = %d)...\n", sfd);
 | |
|  
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| DWORD WINAPI selectThread( LPVOID lpParam )
 | |
| {
 | |
|   DBG_MSG("-> selectThread()...\n");
 | |
|   
 | |
|   DWORD dwWaitResult;
 | |
| 
 | |
|   thread_data_p thread_data;
 | |
| 
 | |
|   thread_data = (thread_data_p)lpParam;
 | |
| 
 | |
|   int sfd = thread_data -> sfd;
 | |
|   int thread_no = thread_data -> thread_no;
 | |
|   int test_type = thread_data -> test_type;
 | |
| 
 | |
|   debug2("starting thread [%i] for sfd [%i] with test type[%i]",
 | |
|                   thread_no, sfd, test_type);
 | |
| 
 | |
|   while(1)
 | |
|   {
 | |
| 
 | |
|     dwWaitResult = WaitForSingleObject(thread_data -> semaphore1, INFINITE);
 | |
| 
 | |
|     if (thread_data -> exit)
 | |
|     {
 | |
|       goto out;
 | |
|     }  
 | |
| 
 | |
|     switch (dwWaitResult)
 | |
|     {
 | |
|       case WAIT_OBJECT_0:
 | |
|       {
 | |
|         switch(get_sfd_type(sfd))
 | |
|         {
 | |
|           case SFD_TYPE_FD:
 | |
|           {
 | |
|             break;
 | |
|           }  
 | |
|         
 | |
|           case SFD_TYPE_SOCKET:
 | |
|           {
 | |
|             if (test_type == TEST_READ)
 | |
|             {
 | |
|               selectSocketRead(sfd);
 | |
|             }  
 | |
|             else
 | |
|             {
 | |
|               selectSocketWrite(sfd);
 | |
|             }  
 | |
|             
 | |
|             break;
 | |
|           }  
 | |
|           
 | |
|           case SFD_TYPE_PIPE:
 | |
|           {  
 | |
|             if (test_type == TEST_READ)
 | |
|             {
 | |
|               peekPipeRead(sfd);
 | |
|             }  
 | |
|             else
 | |
|             {
 | |
|               peekPipeWrite(sfd);
 | |
|             }
 | |
|             
 | |
|             break;
 | |
|           }  
 | |
|          
 | |
|           case SFD_TYPE_CONSOLE:
 | |
|           {
 | |
|             if (test_type == TEST_READ)
 | |
|             {
 | |
|               peekConsoleRead(sfd);
 | |
|             }  
 | |
|             else
 | |
|             {
 | |
|               peekConsoleWrite(sfd);
 | |
|             }  
 | |
|             
 | |
|             break;
 | |
|           }  
 | |
|         }
 | |
|       
 | |
|         if (thread_data -> exit)
 | |
|         {
 | |
|           goto out;
 | |
|         }  
 | |
| 
 | |
|         if (!ReleaseSemaphore(thread_data -> semaphore2, 1, NULL))
 | |
|         {
 | |
|           error("WaitForSingleObject in thread [%d] failed with error code [%d]",
 | |
|                     thread_no, GetLastError());
 | |
| 
 | |
|           return 0;
 | |
|         } 
 | |
|           
 | |
|         break;
 | |
|       }  
 | |
| 
 | |
|       default:
 | |
|       {
 | |
|         error("ReleaseSemaphore in thread [%d] failed with error code [%d]",
 | |
|                    thread_no, GetLastError());
 | |
| 
 | |
|         return 0;
 | |
|       }
 | |
|     }  
 | |
|   }
 | |
| 
 | |
|   out:
 | |
| 
 | |
|   debug2("stopping thread [%i] for sfd [%i] with test type[%i]",
 | |
|                   thread_no, sfd, test_type);
 | |
| 
 | |
|   thread_data -> exited = 1;
 | |
| 
 | |
|   DBG_MSG("<- selectThread()...\n");
 | |
|   
 | |
|   ExitThread(1);
 | |
| 
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| 
 | |
| int startSelectThread(int sfd, int test_type)
 | |
| {
 | |
|   DBG_MSG("-> startSelectThread(sfd = %d, test_type = %d)...\n", sfd, test_type);
 | |
|   
 | |
|   int thread_no = 0;
 | |
|   
 | |
|   int i;
 | |
|   
 | |
|   DWORD ID;
 | |
| 
 | |
|   for (i = 0; i < MAX_THREADS; i++)
 | |
|   {
 | |
|     if (thread_data_set[i] == NULL)
 | |
|     {
 | |
|       thread_no = i;
 | |
|       
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (thread_data_set[thread_no] != NULL)
 | |
|   {
 | |
|       fatal("MAX_THREADS exceed");
 | |
|   }
 | |
| 
 | |
|   thread_data_set[thread_no] = (thread_data_p) HeapAlloc(GetProcessHeap(), 
 | |
|                                                              HEAP_ZERO_MEMORY, 
 | |
|                                                                  sizeof(thread_data_t));
 | |
| 
 | |
|   if (thread_data_set[thread_no] == NULL)
 | |
|   {
 | |
|     fatal("heap allocation failed with error code [%d]", GetLastError());
 | |
|   }
 | |
| 
 | |
|   thread_data_set[thread_no] -> sfd       = sfd;
 | |
|   thread_data_set[thread_no] -> thread_no = thread_no;
 | |
|   thread_data_set[thread_no] -> test_type = test_type;
 | |
|   thread_data_set[thread_no] -> signaled  = 0;
 | |
|   thread_data_set[thread_no] -> exit      = 0;
 | |
|   thread_data_set[thread_no] -> exited    = 0;
 | |
| 
 | |
|   thread_data_set[thread_no] -> semaphore1 = CreateSemaphore(NULL, 1, 1, NULL);
 | |
| 
 | |
|   if (thread_data_set[thread_no] -> semaphore1 == NULL)
 | |
|   {
 | |
|     fatal("CreateSemaphore failed with error code [%d]",
 | |
|               GetLastError());
 | |
|   }
 | |
| 
 | |
|   thread_data_set[thread_no] -> semaphore2 = CreateSemaphore(NULL, 0, 1, NULL);
 | |
| 
 | |
|   if (thread_data_set[thread_no] -> semaphore2 == NULL)
 | |
|   {
 | |
|     fatal("CreateSemaphore failed with error code [%d]", GetLastError());
 | |
|   }
 | |
| 
 | |
|   thread_data_set[thread_no] -> thread = CreateThread(NULL, 0, selectThread, 
 | |
|                                                         thread_data_set[thread_no],
 | |
|                                                             0, &ID);
 | |
| 
 | |
|   thread_data_set[thread_no] -> thread_id = ID;
 | |
| 
 | |
| 
 | |
|   if (thread_data_set[thread_no] -> thread == NULL)
 | |
|   {
 | |
|       fatal("CreateThread failed with error code [%d]", GetLastError());
 | |
|   }
 | |
| 
 | |
|   DBG_MSG("<- startSelectThread(thread_no = %d)...\n", thread_no);
 | |
| 
 | |
|   return thread_no;
 | |
| }
 | |
| 
 | |
| 
 | |
| int cleanSelectThread(int thread_no)
 | |
| {
 | |
|   DBG_MSG("-> cleanSelectThread(thread_no = %d)...\n", thread_no);
 | |
|   
 | |
|   CloseHandle(thread_data_set[thread_no] -> semaphore1);
 | |
|   CloseHandle(thread_data_set[thread_no] -> semaphore2);
 | |
|   CloseHandle(thread_data_set[thread_no] -> thread);
 | |
| 
 | |
|   if(thread_data_set[thread_no] != NULL)
 | |
|   {
 | |
| 	thread_data_p ap = thread_data_set[thread_no];
 | |
| 	thread_data_set[thread_no] = NULL;
 | |
|     HeapFree(GetProcessHeap(), 0, ap);
 | |
|        
 | |
|   }
 | |
|   
 | |
|   DBG_MSG("<- cleanSelectThread()...\n");
 | |
|           
 | |
|   return 1;
 | |
| }
 | |
| 
 | |
| // Add a Child process to be added to select mux so thyat we know when it has exited
 | |
| HANDLE ChildToWatch = NULL;
 | |
| int WSHELPAddChildToWatch ( HANDLE processtowatch)
 | |
| {
 | |
| 	ChildToWatch = processtowatch;
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int WSHELPDelChildToWatch ( HANDLE processtowatch)
 | |
| {
 | |
| 	if ( ChildToWatch == processtowatch )
 | |
| 		ChildToWatch = NULL ;
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| int WSHELPselect(int fds, fd_set* readsfds, fd_set* writesfds,
 | |
|                      fd_set* exceptsfds, const struct timeval* timeout)
 | |
| {
 | |
|   DBG_MSG("-> WSHELPselect(fds = %d)...\n", fds);
 | |
|   
 | |
|   DWORD dwWaitResult;
 | |
| 
 | |
|   DWORD ms;
 | |
| 
 | |
|   unsigned int i;
 | |
|   
 | |
|   int count = 0;
 | |
| 
 | |
|   static int sfd_read_to_thread_map[MAX_THREADS] = {0};
 | |
| 
 | |
|   static int sfd_write_to_thread_map[MAX_THREADS] = {0};
 | |
| 
 | |
|   HANDLE semaphores[MAX_THREADS] = {NULL};
 | |
| 
 | |
|   int i_sem = 0;
 | |
|   
 | |
|   int semaphores_to_thread_map[MAX_THREADS] = {0};
 | |
| 
 | |
|   static unsigned int threads_count = 0;
 | |
| 
 | |
|   /*
 | |
|    * 'except' should be implemented.
 | |
|    */
 | |
|    
 | |
|   if (exceptsfds)
 | |
|   {
 | |
|     fatal("exceptsfds not implemented");
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * convert timeout to ms or to INFINITE if null.
 | |
|    */
 | |
| 
 | |
|   ms = timeout ? (DWORD) (timeout -> tv_sec * 1000) + (timeout -> tv_usec / 1000) : INFINITE;
 | |
| 
 | |
|   if (ms == 0 && timeout -> tv_usec)
 | |
|   {
 | |
|     ms = 1;
 | |
|   }  
 | |
| 
 | |
|   /*
 | |
|    * just wait if all set's are empty.
 | |
|    */
 | |
|    
 | |
|   if (!readsfds && !writesfds && !exceptsfds)
 | |
|   {
 | |
|     HANDLE empty = NULL;
 | |
| 
 | |
|     dwWaitResult = WaitForSingleObject(empty, ms);
 | |
| 
 | |
|     switch (dwWaitResult)
 | |
|     {
 | |
|       case WAIT_OBJECT_0:
 | |
|       { 
 | |
|         errno = EINTR;
 | |
| 
 | |
|         DBG_MSG("<- WSHELPselect(fds = %d, ret = -1)...\n", fds);
 | |
|             
 | |
|         return -1;
 | |
|       }  
 | |
|             
 | |
|       case WAIT_FAILED:
 | |
|       {
 | |
|         fatal("WaitForSingleObject failed with error code [%d]", GetLastError());
 | |
|       }
 | |
|       
 | |
|       case WAIT_TIMEOUT:
 | |
|       {      
 | |
|         DBG_MSG("<- WSHELPselect(fds = %d, ret = 0)...\n", fds);
 | |
|             
 | |
|         return 0;
 | |
|       }  
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * threads for read fds removed from set should be stopped.
 | |
|    */
 | |
|   
 | |
|   DBG_MSG("WSHELPselect(fds = %d) : stopping threads for read fds "
 | |
|             "removed from set...\n", fds);
 | |
|   
 | |
|   if (read_sfd_set.fd_count != 0)
 | |
|   {
 | |
|     for (i = 0; i < read_sfd_set.fd_count; ++i)
 | |
|     {
 | |
|       int sfd = (int) read_sfd_set.fd_array[i];
 | |
|       
 | |
|       if (!FD_ISSET(sfd, readsfds))
 | |
|       {
 | |
|         //int thread_no = thread_data_set[sfd_read_to_thread_map[sfd]] -> thread_no;
 | |
| 
 | |
|         //debug("WSHELPselect(fds = %d) :   stoping thread_no = %d for sfd = %d...\n", fds, thread_no, sfd);
 | |
| 
 | |
|         thread_data_set[sfd_read_to_thread_map[sfd]] -> exit = 1;
 | |
| 
 | |
|         FD_CLR((SOCKET) sfd, &read_sfd_set);
 | |
| 
 | |
|         sfd_read_to_thread_map[sfd] = -1;
 | |
|       }
 | |
|       //else
 | |
|       //{
 | |
|       //  debug("WSHELPselect(fds = %d) : i = %d : sfd = %d, FD_ISSET != 0...\n", fds, sfd);
 | |
|       //}
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * threads for write fds removed from set should be stopped.
 | |
|    */
 | |
| 
 | |
|   DBG_MSG("WSHELPselect(fds = %d) : stopping threads for write fds removed from set...\n", fds);
 | |
|         
 | |
|   if (write_sfd_set.fd_count != 0)
 | |
|   {
 | |
|     for (i = 0; i < write_sfd_set.fd_count; ++i)
 | |
|     {
 | |
|       int sfd = (int) write_sfd_set.fd_array[i];
 | |
|       
 | |
|       if (!FD_ISSET(sfd, writesfds))
 | |
|       {
 | |
|         //int thread_no = thread_data_set[sfd_read_to_thread_map[sfd]] -> thread_no;
 | |
|         
 | |
|         //debug("WSHELPselect(fds = %d) :   stopping thread_no = %d for sfd = %d...\n", fds, thread_no, sfd);
 | |
| 
 | |
|         thread_data_set[sfd_write_to_thread_map[sfd]] -> exit = 1;
 | |
|         
 | |
|         FD_CLR((SOCKET) sfd, &write_sfd_set);
 | |
|         
 | |
|         sfd_write_to_thread_map[sfd] = -1;
 | |
|       }
 | |
|       //else
 | |
|       //{
 | |
|       //  debug("WSHELPselect(fds = %d) : i = %d : sfd = %d, FD_ISSET != 0...\n", fds, sfd);
 | |
|       //}
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   DBG_MSG("WSHELPselect(fds = %d) : Weaking up threads signaled in previous run...\n", fds);
 | |
| 
 | |
|   for (i = 0; i < MAX_THREADS; i++)
 | |
|   {
 | |
|     /*
 | |
|      * threads signaled in previous run should be waken up.
 | |
|      */
 | |
|   
 | |
|     if (thread_data_set[i] != NULL && thread_data_set[i] -> signaled == 1)
 | |
|     {
 | |
|       if (!ReleaseSemaphore(thread_data_set[i] -> semaphore1, 1, NULL))
 | |
|       {
 | |
|         fatal("ReleaseSemaphore failed with error code [%d]", GetLastError());
 | |
|       }
 | |
|     
 | |
|       thread_data_set[i] -> signaled = 0;
 | |
|     }
 | |
|      
 | |
|     /*
 | |
|      * Cleaning after exited threads.
 | |
|      */
 | |
|     
 | |
|     if (thread_data_set[i] != NULL && thread_data_set[i] -> exited == 1)
 | |
|     {
 | |
|       cleanSelectThread(i);
 | |
| 
 | |
|       threads_count--;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * new thread should be started for each new read fd.
 | |
|    */
 | |
| 
 | |
|   DBG_MSG("WSHELPselect(fds = %d) : Starting new thread for each new read fd...\n", fds);
 | |
|   
 | |
|   if (readsfds != NULL && readsfds -> fd_count != 0)
 | |
|   {
 | |
|     for (i = 0; i < readsfds -> fd_count; ++i)
 | |
|     {
 | |
|       int sfd = (int) readsfds -> fd_array[i];
 | |
|       
 | |
|       if (!FD_ISSET(sfd, &read_sfd_set))
 | |
|       {
 | |
|         int thread_no = startSelectThread(sfd, TEST_READ);
 | |
|         
 | |
|         //debug("WSHELPselect(fds = %d) :   Starting read thread (thread_no = %d) for sfd = %d...\n",
 | |
|         //          fds, thread_no, sfd);
 | |
|         
 | |
|         read_sfd_set_add(sfd);
 | |
|         
 | |
|         sfd_read_to_thread_map[sfd] = thread_no;
 | |
|         
 | |
|         threads_count++;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * New thread should be started for each new write fd.
 | |
|    */
 | |
| 
 | |
|   DBG_MSG("WSHELPselect(fds = %d) : Starting new thread for each new write fd...\n", fds);
 | |
|   
 | |
|   if (writesfds != NULL && writesfds -> fd_count != 0)
 | |
|   {
 | |
|     for (i = 0; i < writesfds -> fd_count; ++i)
 | |
|     {
 | |
|       int sfd = (int) writesfds -> fd_array[i];
 | |
|    
 | |
|       if (!FD_ISSET(sfd, &write_sfd_set))
 | |
|       {
 | |
|         int thread_no = startSelectThread(sfd, TEST_WRITE);
 | |
|         
 | |
|         //debug("WSHELPselect(fds = %d) :   Starting write thread (thread_no = %d) for sfd = %d...\n",
 | |
|         //          fds, thread_no, sfd);
 | |
| 
 | |
|         
 | |
|         write_sfd_set_add(sfd);
 | |
|         
 | |
|         sfd_write_to_thread_map[sfd] = thread_no;
 | |
|         
 | |
|         threads_count++;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * constructing array of semaphores for working threads
 | |
|    * new array is needed because in threads map we can have
 | |
|    * threads which should exit right now.
 | |
|    */
 | |
| 
 | |
|   DBG_MSG("WSHELPselect(fds = %d) : constructing array of semaphores for working threads...\n", fds);
 | |
| 
 | |
|   for (i = 0; i < MAX_THREADS; i++)
 | |
|   {
 | |
|     if (thread_data_set[i] != NULL && !thread_data_set[i] -> exit )
 | |
|     {
 | |
|       semaphores[i_sem] = thread_data_set[i] -> semaphore2;
 | |
| 
 | |
|       semaphores_to_thread_map[i_sem] = i;
 | |
|       
 | |
|       i_sem++;
 | |
|     }
 | |
| 
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * wait for signal from threads.
 | |
|    */
 | |
|    
 | |
|   #ifdef DEBUG
 | |
|   
 | |
|   {
 | |
|     char str[256] = "{";
 | |
|     char tmp[32]  = "";
 | |
|     
 | |
|     for (i = 0; i < read_sfd_set.fd_count; ++i)
 | |
|     {
 | |
|       int sfd = (int) read_sfd_set.fd_array[i];
 | |
|       
 | |
|       sprintf(tmp, " %d", sfd);
 | |
|       
 | |
|       strcat(str, tmp);
 | |
|     }
 | |
|     
 | |
|     strcat(str, " }");
 | |
|     
 | |
|     debug("read_sfd_set = %s", str);
 | |
|   
 | |
|     /*
 | |
|      *
 | |
|      */
 | |
|   
 | |
|     str[0] = '{';
 | |
|     str[1] = '\0';
 | |
|     
 | |
|     for (i = 0; i < write_sfd_set.fd_count; ++i)
 | |
|     {
 | |
|       int sfd = (int) write_sfd_set.fd_array[i];
 | |
|       
 | |
|       sprintf(tmp, " %d", sfd);
 | |
|       
 | |
|       strcat(str, tmp);
 | |
|     }
 | |
|     
 | |
|     strcat(str, " }");
 | |
|     
 | |
|     debug("write_sfd_set = %s", str);
 | |
|   }
 | |
|   
 | |
|   #endif
 | |
|   
 | |
|   
 | |
|   DBG_MSG("WSHELPselect(fds = %d) : Waiting for signal from threads...\n", fds);
 | |
| 
 | |
|   DBG_MSG("i_sem = %d\n", i_sem);
 | |
|  
 | |
|   // add a child process handle to the mux if it was registered
 | |
|   if ( ChildToWatch ) {
 | |
| 	semaphores[i_sem] = ChildToWatch ;
 | |
| 	i_sem++;
 | |
|   }
 | |
|   
 | |
|   dwWaitResult = WaitForMultipleObjects(i_sem, semaphores, FALSE, ms);
 | |
| 
 | |
|   //debug("WSHELPselect(fds = %d) :   FD_ZERO(readsfds)...\n", fds);
 | |
|   
 | |
|   if (readsfds) FD_ZERO(readsfds);
 | |
|   
 | |
|   //debug("WSHELPselect(fds = %d) :   FD_ZERO(writesfds)...\n", fds);
 | |
|   
 | |
|   if (writesfds) FD_ZERO(writesfds);
 | |
|   
 | |
|   //debug("WSHELPselect(fds = %d) :   FD_ZERO(exceptsfds)...\n", fds);
 | |
|   
 | |
|   if (exceptsfds) FD_ZERO(exceptsfds);
 | |
| 
 | |
|   switch (dwWaitResult)
 | |
|   {
 | |
|     case WAIT_FAILED:
 | |
|     {
 | |
|       fatal("WaitForMultipleObjects failed with error code [%d]", GetLastError());
 | |
|     }
 | |
|       
 | |
|     case WAIT_TIMEOUT:
 | |
|     {
 | |
|       DBG_MSG("<- WSHELPselect(fds = %d, ret = 0)...\n", fds);
 | |
|      
 | |
|       return 0;
 | |
|     }   
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * Prepare return fd sets with signaled fd's.
 | |
|    */
 | |
| 
 | |
|   //debug("WSHELPselect(fds = %d) : preparing return fd sets with signaled fd's...\n", fds);
 | |
|   
 | |
|   for (i = 0; i<MAX_THREADS; i++)
 | |
|   {
 | |
|     if (dwWaitResult == WAIT_OBJECT_0 + i)
 | |
|     {
 | |
|       int thread_no = semaphores_to_thread_map[i];
 | |
|       
 | |
|       if (thread_data_set[thread_no] -> test_type == TEST_READ)
 | |
|       {
 | |
|         FD_SET((SOCKET) thread_data_set[thread_no] -> sfd, readsfds);
 | |
|         
 | |
|         DBG_MSG("WSHELPselect(fds = %d) :   "
 | |
|                        "thread_no = %d, sfd = %d, readsfds = %d...\n", 
 | |
|                            fds, thread_no,
 | |
|                                thread_data_set[thread_no] -> sfd, (int) readsfds);
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         FD_SET((SOCKET) thread_data_set[thread_no] -> sfd, writesfds);
 | |
|         
 | |
|         DBG_MSG("WSHELPselect(fds = %d) :   "
 | |
|                        "thread_no = %d, sfd = %d, readsfds = %d...\n", 
 | |
|                            fds, thread_no, 
 | |
|                                thread_data_set[thread_no] -> sfd, (int) writesfds);
 | |
|       }  
 | |
| 
 | |
|       count ++;
 | |
| 
 | |
|       thread_data_set[thread_no] -> signaled = 1;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   DBG_MSG("<- WSHELPselect(fds = %d, ret = %d)...\n", fds, count);
 | |
|   
 | |
|   return count;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * IO functions.
 | |
|  */
 | |
| 
 | |
| int WSHELPread(int sfd, char *dst, unsigned int max)
 | |
| {
 | |
|   DBG_MSG("-> WSHELPread(sfd = %d)...\n", sfd);
 | |
| 
 | |
|  
 | |
|   SOCKET sock;
 | |
| 
 | |
|   int ret = -1;
 | |
|   int sfd_type = get_sfd_type(sfd);
 | |
| 
 | |
|   switch (sfd_type)
 | |
|   {
 | |
|     case SFD_TYPE_SOCKET:
 | |
|     {
 | |
|       /*
 | |
|        * Clear errno.
 | |
|        */
 | |
|       
 | |
|       errno = 0;
 | |
| 
 | |
|       /*
 | |
|        * Get the SOCKET.
 | |
|        */
 | |
|       
 | |
|       sock = (SOCKET) sfd_to_handle(sfd);
 | |
| 
 | |
|       /*
 | |
|        * Call the underlying function.
 | |
|        */
 | |
|       
 | |
|       ret = recv(sock, dst, max, 0);
 | |
| 
 | |
|       if (FD_ISSET(sfd, &debug_sfds))
 | |
|       {
 | |
|         if (ret > 0)
 | |
|         {
 | |
|           dst[ret] = '\0';
 | |
| 
 | |
|           debug("read[%d]: %s", sfd, dst);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (ret < 0)
 | |
|       {
 | |
|         debug("read from socket sfd [%d] failed with error code [%d]",
 | |
|                   sfd, GetLastError());
 | |
|       }
 | |
| 
 | |
|       /*
 | |
|        * Check for errors.
 | |
|        */
 | |
|       
 | |
|       if (ret == SOCKET_ERROR)
 | |
|       {
 | |
|         errno = getWSAErrno();
 | |
|         
 | |
|         DBG_MSG("WSHELPread(sfd = %d) : SOCKET_ERROR...\n", sfd);
 | |
| 
 | |
|         DBG_MSG("<- WSHELPread(sfd = %d, ret = -1)...\n", sfd);
 | |
|         
 | |
|         return -1;
 | |
|       }
 | |
| 
 | |
|       break;
 | |
|     }
 | |
|     
 | |
|     case SFD_TYPE_FD:
 | |
|     case SFD_TYPE_PIPE:
 | |
|     //case SFD_TYPE_CONSOLE:
 | |
|     {
 | |
| 
 | |
|       ret = _read(sfd_to_fd(sfd), dst, max);
 | |
| 
 | |
|       if (FD_ISSET(sfd_to_fd(sfd), &debug_sfds))
 | |
|       {
 | |
|         if (ret > 0)
 | |
|         {
 | |
|           dst[ret] = '\0';
 | |
| 
 | |
|           debug("read[%d] len %d: %s", sfd_to_fd(sfd), ret, dst);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (ret < 0)
 | |
|       {
 | |
|         error("read from pipe/console sfd [%d] failed with error code [%d]",
 | |
|                   sfd, GetLastError());
 | |
| 
 | |
|       }
 | |
| 
 | |
|       break;
 | |
|     }
 | |
| 	case SFD_TYPE_CONSOLE:
 | |
|     {
 | |
| 		//if (sfd_type == SFD_TYPE_CONSOLE) {
 | |
| 			// we could be send here due to ctrl-c input, so no data to read
 | |
| 			//if ( DataAvailable (sfd_to_handle(sfd)) <=0  )
 | |
| 				//return 1; // no data to read
 | |
| 		//}
 | |
|       ret = ReadConsoleForTermEmul( sfd_to_handle(sfd), dst, max);
 | |
| 
 | |
|       if (ret < 0)
 | |
|       {
 | |
|         error("read from pipe/console sfd [%d] failed with error code [%d]",
 | |
|                   sfd, GetLastError());
 | |
|       }
 | |
|       if (ret == 0)
 | |
|     	  return 0; //1;
 | |
| 
 | |
|       break;
 | |
|     }
 | |
|     case 99:
 | |
|     {
 | |
|       ret = _getch();
 | |
|       if ( ( ret == 0) || (ret == 0xE0) ) {
 | |
|     	  dst[0] = ret ;
 | |
|     	  ret = _getch(); // function key or arrow key needs 2 calls, the first returning a 0 or 0xE0
 | |
|           dst[1] = ret;
 | |
|           ret = 2;
 | |
|       }
 | |
|       else {
 | |
|     	  dst[0] = ret;
 | |
|     	  ret = 1;
 | |
|       }
 | |
|       
 | |
|       if (FD_ISSET(sfd_to_fd(sfd), &debug_sfds))
 | |
|       {
 | |
|         if (ret > 0)
 | |
|         {
 | |
|           dst[ret] = '\0';
 | |
| 
 | |
|           debug("read[%d] len %d: %s", sfd_to_fd(sfd), ret, dst);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (ret < 0)
 | |
|       {
 | |
|         error("read from pipe/console sfd [%d] failed with error code [%d]",
 | |
|                   sfd, GetLastError());
 | |
|       }
 | |
| 
 | |
|       break;
 | |
|     }  
 | |
|   }
 | |
| 
 | |
|   DBG_MSG("<- WSHELPread(sfd = %d, ret = %d)...\n", sfd, ret);
 | |
|   
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int WSHELPwrite(int sfd, const char *buf, unsigned int max)
 | |
| {
 | |
|   DBG_MSG("-> WSHELPwrite(sfd = %d)...\n", sfd);
 | |
|   
 | |
|   SOCKET sock;
 | |
|   
 | |
|   int ret = -1;
 | |
| 
 | |
|   int sfd_type = get_sfd_type(sfd);
 | |
|   if ( (glob_itissshclient) && ( sfd_type == SFD_TYPE_CONSOLE ) )
 | |
| 	  sfd_type = SFD_TYPE_PIPE ; // client write type uses _write() in place ofn console insertion
 | |
| 
 | |
|   switch(sfd_type)
 | |
|   {
 | |
|     case SFD_TYPE_SOCKET:
 | |
|     {
 | |
|       /*
 | |
|        * Clear errno.
 | |
|        */
 | |
|       
 | |
|       errno = 0;
 | |
| 
 | |
|       /*
 | |
|        * Get the SOCKET.
 | |
|        */
 | |
|       
 | |
|       sock = (SOCKET) sfd_to_handle(sfd);
 | |
| 
 | |
|       if (FD_ISSET(sfd, &crlf_sfds) && max == 1 && buf[0] == 13)
 | |
|       {
 | |
|         /*
 | |
|          * FIXME: We're getting CR's (13) instead of CR + LF or just LF, 
 | |
|          * either of which would work.
 | |
|          */
 | |
|         
 | |
|         char locbuf[1] = {10};
 | |
| 
 | |
|         ret = send(sock, locbuf, 1, 0);
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         /*
 | |
|          * Call the underlying function.
 | |
|          */
 | |
|         
 | |
|         ret = send(sock, buf, max, 0);
 | |
|       }
 | |
| 
 | |
|       if (FD_ISSET(sfd, &debug_sfds))
 | |
|       {
 | |
|         if (ret > 0)
 | |
|         {
 | |
|           static int writecount = 0;
 | |
|           
 | |
|           char *locbuf = malloc(max + 1);
 | |
|           
 | |
|           memcpy(locbuf, buf, max);
 | |
| 
 | |
|           locbuf[max] = '\0';
 | |
| 
 | |
|           writecount += max;
 | |
| 
 | |
|           debug("write[%d] len %d: %s", sfd, max, locbuf);
 | |
|           
 | |
|           if (max == 1)
 | |
|           {
 | |
|             debug("write[%d] one char: %08x", sfd, locbuf[0]);
 | |
|           }
 | |
|           
 | |
|           free(locbuf);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (ret < 0)
 | |
|       {
 | |
|         /*
 | |
|          * write error only if failed sfd is not a stderr (2).
 | |
|          */
 | |
| 
 | |
|         if (sfd != 2)
 | |
|         {
 | |
|           //error("write to socket sfd [%d] failed with error code [%d]",
 | |
|           //          sfd, GetLastError());
 | |
| 
 | |
|           DBG_MSG("<- WSHELPwrite(sfd = %d, ret = -1)...\n", sfd);
 | |
|         }
 | |
| 
 | |
|         exit(-1);
 | |
|       }
 | |
| 
 | |
|       /*
 | |
|        * Check for errors.
 | |
|        */
 | |
|       
 | |
|       if (ret == SOCKET_ERROR)
 | |
|       {
 | |
|         errno = getWSAErrno();
 | |
| 
 | |
|         DBG_MSG("WSHELPwrite(sfd = %d) : SOCKET_ERROR...\n", sfd);
 | |
| 
 | |
|         DBG_MSG("<- WSHELPwrite(sfd = %d, ret = -1)...\n", sfd);
 | |
| 
 | |
|         return -1;
 | |
|       }
 | |
|       break;
 | |
|     }  
 | |
| 
 | |
|     case SFD_TYPE_FD:
 | |
|     case SFD_TYPE_PIPE:
 | |
|     //case SFD_TYPE_CONSOLE:
 | |
|     {
 | |
|       ret = _write(sfd_to_fd(sfd), buf, max);
 | |
|       
 | |
|       if (FD_ISSET(sfd_to_fd(sfd), &debug_sfds))
 | |
|       {
 | |
|         if (ret > 0)
 | |
|         {
 | |
|           char *locbuf = malloc(max + 1);
 | |
|          
 | |
|           memcpy(locbuf, buf, max);
 | |
| 
 | |
|           locbuf[max] = '\0';
 | |
|           
 | |
|           debug("write[%d]: %s", sfd_to_fd(sfd), locbuf);
 | |
|           
 | |
|           free(locbuf);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (ret < 0)
 | |
|       {
 | |
|         /*
 | |
|          * write error only if failed sfd is not a stderr (2).
 | |
|          */
 | |
|   
 | |
|         if (sfd != 2)
 | |
|         {
 | |
|           error("write to pipe/console sfd [%d] failed with error code [%d]",
 | |
|                     sfd, GetLastError());
 | |
|         }
 | |
|       }
 | |
|       
 | |
|       break;
 | |
|     }
 | |
|     case SFD_TYPE_CONSOLE:
 | |
|     {
 | |
|       //ret = _write(sfd_to_fd(sfd), buf, max);
 | |
| 	  size_t dwWritten = 0 ;
 | |
| 	  ret = WriteToConsole(sfd_to_handle(sfd), buf, max, &dwWritten, 0) ;
 | |
| 	  ret = max ;
 | |
|           
 | |
|       break;
 | |
|     }  	
 | |
|   }
 | |
| 
 | |
|   DBG_MSG("<- WSHELPwrite(sfd = %d, ret = %d)...\n", sfd, ret);
 | |
|   
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| int WSHELPclose(int sfd)
 | |
| {
 | |
|   DBG_MSG("-> WSHELPclose(sfd = %d)...\n", sfd);
 | |
|   
 | |
|   int i;
 | |
|   
 | |
|   int socketInUse = 0;
 | |
|   
 | |
|   SOCKET sock;
 | |
|   
 | |
|   int ret = -1;
 | |
| 
 | |
|   switch(get_sfd_type(sfd))
 | |
|   {
 | |
|     case SFD_TYPE_SOCKET:
 | |
|     {
 | |
|       /*
 | |
|        * Clear errno.
 | |
|        */
 | |
|       
 | |
|       errno = 0;
 | |
| 
 | |
|       /*
 | |
|        * Get the SOCKET.
 | |
|        */
 | |
|       
 | |
|       sock = (SOCKET) sfd_to_handle(sfd);
 | |
|      
 | |
|       if (sock == INVALID_SOCKET)
 | |
|       {
 | |
|         errno = EBADF;
 | |
|                
 | |
|         DBG_MSG("WSHELPclose(sfd = %d) : INVALID_SOCKET...\n", sfd);
 | |
| 
 | |
|         DBG_MSG("<- WSHELPclose(sfd = %d, ret = -1)...\n", sfd);
 | |
|                
 | |
|         return -1;
 | |
|       }
 | |
| 
 | |
|       /*
 | |
|        * Remove cookie in SocketCookieMap var (for AF_UNIX only).
 | |
|        */
 | |
|       
 | |
|       for (i = 0; i < SFD_MAP_SIZE; i++)
 | |
|       {
 | |
|         /*
 | |
|          * Find socket in table.
 | |
|          */
 | |
|         
 | |
|         if (SocketCookieMap[i].socket == sock)
 | |
|         {
 | |
|           /*
 | |
|            * Remove cookie.
 | |
|            */
 | |
|           
 | |
|           SocketCookieMap[i].socket = 0;
 | |
| 
 | |
|           if (SocketCookieMap[i].cookie)
 | |
|           {
 | |
|             free(SocketCookieMap[i].cookie);
 | |
|           }
 | |
|           
 | |
|           if (SocketCookieMap[i].f)
 | |
|           {
 | |
|             fclose(SocketCookieMap[i].f);
 | |
|           }
 | |
|           
 | |
|           break;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       /*
 | |
|        * Test is socket in use by another sfd?
 | |
|        */
 | |
| 
 | |
|       socketInUse = 0;
 | |
| 
 | |
|       i = 0;
 | |
|       
 | |
|       while(!socketInUse && i < SFD_MAP_SIZE)
 | |
|       {
 | |
|         //DBG_MSG("%d |-> %d ? %d\n", i, sfd_to_handle(i), sock);
 | |
|         
 | |
|         if (((int) sfd_to_handle(i) == (int) sock) && (i != (int) sfd))
 | |
|         {
 | |
|           socketInUse = 1;
 | |
|         }
 | |
| 
 | |
|         i++;
 | |
|       }
 | |
|       
 | |
|       /*
 | |
|        * Call the underlying function.
 | |
|        */
 | |
| 
 | |
|       if (!socketInUse)
 | |
|       {
 | |
|         DBG_MSG("Closing socket %d\n", sock);
 | |
|       
 | |
|         ret = closesocket(sock);
 | |
|       }
 | |
|       else
 | |
|       {
 | |
|         DBG_MSG("Socket %d in use.\n", sock);
 | |
|         
 | |
|         ret = 0;
 | |
|       }
 | |
| 
 | |
|       /*
 | |
|        * Remove mapping table entry.
 | |
|        */
 | |
|       
 | |
|       free_sfd(sfd);
 | |
| 
 | |
|       /*
 | |
|        * Check for errors.
 | |
|        */
 | |
|       
 | |
|       if (ret == SOCKET_ERROR)
 | |
|       {
 | |
|         errno = getWSAErrno();
 | |
|               
 | |
|         DBG_MSG("WSHELPclose(sfd = %d) : SOCKET_ERROR...\n", sfd);
 | |
| 
 | |
|         DBG_MSG("<- WSHELPclose(sfd = %d, ret = -1)...\n", sfd);
 | |
|               
 | |
|         return -1;
 | |
|       }
 | |
|       
 | |
|       break;
 | |
|     }  
 | |
|     
 | |
|     case SFD_TYPE_FD:
 | |
|     case SFD_TYPE_PIPE:
 | |
|     case SFD_TYPE_CONSOLE:
 | |
|     {
 | |
|       ret = _close(sfd_to_fd(sfd));
 | |
| 
 | |
|       free_sfd(sfd);
 | |
| 
 | |
|       break;
 | |
|     }  
 | |
|   }
 | |
| 
 | |
|   DBG_MSG("<- WSHELPclose(sfd = %d, ret = %d)...\n", sfd, ret);
 | |
|   
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Internal functions.
 | |
|  */
 | |
| 
 | |
| void WSHELPinitialize()
 | |
| {
 | |
|   DBG_MSG("-> WSHELPinitialize()...\n");
 | |
|   
 | |
|   WORD wVersionRequested;
 | |
|   
 | |
|   WSADATA wsaData;
 | |
|   
 | |
|   int err;
 | |
| 
 | |
|   wVersionRequested = MAKEWORD(2, 2);
 | |
| 
 | |
|   if (WSAStartup(wVersionRequested, &wsaData))
 | |
|   {  
 | |
|     fatal("ERROR: Cannot initialize WinSock DLL.");
 | |
|   }  
 | |
| 
 | |
|   /*
 | |
|    * Confirm that the WinSock DLL supports 2.2. 
 | |
|    * Note that if the DLL supports versions greater   
 | |
|    * than 2.2 in addition to 2.2, it will still return
 | |
|    * 2.2 in wVersion since that is the version we     
 | |
|    * requested.
 | |
|    */
 | |
|   
 | |
|   if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
 | |
|   {
 | |
|     fatal("ERROR: WinSock 2.2 needed.");
 | |
|   }
 | |
| 
 | |
|   /*
 | |
|    * The WinSock DLL is acceptable. Proceed.
 | |
|    */
 | |
|   
 | |
|   winsock_initialized = 1;
 | |
| 
 | |
| #ifndef __MINGW32__
 | |
|  // _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
 | |
|  // _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
 | |
|  // _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
 | |
|  // _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
 | |
|  // _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
 | |
|  // _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
|   DBG_MSG("<- WSHELPinitialize()...\n");
 | |
| }
 | |
| 
 | |
| 
 | |
| void allocate_standard_descriptor(int fd)
 | |
| {
 | |
|   DBG_MSG("-> allocate_standard_descriptor(fd = %d)...\n", fd);
 | |
|   
 | |
|   int asfd = allocate_sfd(fd);
 | |
| 
 | |
|   void sfd_set_to_console(int sfd);
 | |
|   if (asfd >= 0)
 | |
| 	  sfd_set_to_console(asfd);
 | |
|   
 | |
|   DBG_MSG("<- allocate_standard_descriptor()...");
 | |
| }
 |