(w32_getpw, w32_socket, w32_connect, w32_recv, w32_send,
w32_writev_socket, w32_close_socket, getpass, w32_openfd, w32_openhandle, w32_readv_handle, w32_close_handle, sysdep_init, sysdep_stdin_init, w32_select, w32_signal_handler, sigaction, stdin_read_thread, w32_ring_from_file_to_bounce_buf) [_WIN32]: New w32 equivalent functions for POSIX functions. (recvline, sendcmd, tcp_connect, hostconnect, getpass, main, intr, play, ring_to_file, ring_from_file, doexecute, doredir) [_WIN32]: Use new WIN32 equivalent functions. (main) [_WIN32]: Add sysdep_init() to support system dependent initialization for equivalence functions. (play) [_WIN32]: Add sysdef_stdin_init() to support system dependent initialization for reading stdin. (recv_input, play) [_WIN32]: Replace the calls to ring_to_file() and select() with WIN32 specific enhanced versions. Makefile.in: update dependencies with new files. Make.mk: Add using of getopt.c and getopt.h from src/lib/w32 directory. Add getopt.c and getopt.h to tar for client.
This commit is contained in:
parent
006c4bcce4
commit
f082ef9fa6
12 changed files with 750 additions and 110 deletions
|
@ -29,6 +29,7 @@
|
|||
*
|
||||
* Known contributors to this file:
|
||||
* Markus Armbruster, 2007
|
||||
* Ron Koenderink, 2007
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
@ -38,15 +39,254 @@
|
|||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef _WIN32
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <io.h>
|
||||
#endif
|
||||
#include "linebuf.h"
|
||||
#include "misc.h"
|
||||
#include "proto.h"
|
||||
#include "ringbuf.h"
|
||||
#include "secure.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
static CRITICAL_SECTION signal_critical_section;
|
||||
static LPCRITICAL_SECTION signal_critical_section_ptr = NULL;
|
||||
|
||||
static unsigned char bounce_buf[RING_SIZE];
|
||||
/*
|
||||
* Set bounce_empty to indicate bounce_buf is available for the stdin thread
|
||||
* to use.
|
||||
*/
|
||||
static HANDLE bounce_empty;
|
||||
/*
|
||||
* Set bounce_full to indicate bounce_buf is contains data from the
|
||||
* stdin thread and is available for recv_input
|
||||
*/
|
||||
static HANDLE bounce_full;
|
||||
/* Ctrl-C (SIGINT) was detected, generate EINTR for the w32_select() */
|
||||
static HANDLE ctrl_c_event;
|
||||
static int bounce_status, bounce_error;
|
||||
|
||||
#define SIGPIPE -1
|
||||
static void (*ctrl_handler)(int sig) = { SIG_DFL };
|
||||
|
||||
/*
|
||||
* Ctrl-C handler for emulating the SIGINT in WIN32
|
||||
*/
|
||||
static BOOL WINAPI
|
||||
w32_signal_handler(DWORD ctrl_type)
|
||||
{
|
||||
if (ctrl_type == CTRL_C_EVENT) {
|
||||
EnterCriticalSection(signal_critical_section_ptr);
|
||||
if (ctrl_handler != SIG_DFL) {
|
||||
ctrl_handler(SIGINT);
|
||||
LeaveCriticalSection(signal_critical_section_ptr);
|
||||
SetEvent(ctrl_c_event);
|
||||
return TRUE;
|
||||
} else
|
||||
LeaveCriticalSection(signal_critical_section_ptr);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* WIN32 equivalent for sigaction supports the following:
|
||||
* set handler for SIGINT using WIN32 Ctrl-C handler
|
||||
* reset handler SIGINT to SIG_DFL
|
||||
* ignore SIGPIPE
|
||||
*/
|
||||
static int
|
||||
sigaction(int signal, struct sigaction *action, struct sigaction *oaction)
|
||||
{
|
||||
assert(!oaction);
|
||||
assert(action);
|
||||
|
||||
if (signal == SIGPIPE)
|
||||
assert(action->sa_handler == SIG_IGN);
|
||||
else {
|
||||
assert(signal == SIGINT && action->sa_handler != SIG_IGN);
|
||||
if (ctrl_handler == action->sa_handler)
|
||||
return 0;
|
||||
if (signal_critical_section_ptr == NULL) {
|
||||
signal_critical_section_ptr = &signal_critical_section;
|
||||
InitializeCriticalSection(signal_critical_section_ptr);
|
||||
}
|
||||
EnterCriticalSection(signal_critical_section_ptr);
|
||||
if (!SetConsoleCtrlHandler(w32_signal_handler,
|
||||
action->sa_handler != SIG_DFL)) {
|
||||
errno = GetLastError();
|
||||
LeaveCriticalSection(signal_critical_section_ptr);
|
||||
return -1;
|
||||
}
|
||||
ctrl_handler = action->sa_handler;
|
||||
LeaveCriticalSection(signal_critical_section_ptr);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the stdin in WIN32 environment
|
||||
* WIN32 does not support select type function on console input
|
||||
* so the client uses a separate thread to read input
|
||||
*/
|
||||
static DWORD WINAPI
|
||||
stdin_read_thread(LPVOID lpParam)
|
||||
{
|
||||
for (;;) {
|
||||
if (WaitForSingleObject(bounce_empty, INFINITE) != WAIT_OBJECT_0)
|
||||
break;
|
||||
bounce_status = _read(0, bounce_buf, sizeof(bounce_buf));
|
||||
bounce_error = errno;
|
||||
if (bounce_status == 0) {
|
||||
if (_isatty(0)) {
|
||||
SetEvent(bounce_empty);
|
||||
continue;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
SetEvent(bounce_full);
|
||||
}
|
||||
SetEvent(bounce_full);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize and start the stdin reading thread for WIN32
|
||||
*/
|
||||
static void
|
||||
sysdep_stdin_init()
|
||||
{
|
||||
bounce_empty = CreateEvent(NULL, FALSE, TRUE, "bounce_empty");
|
||||
bounce_full = CreateEvent(NULL, TRUE, FALSE, "bounce_full");
|
||||
ctrl_c_event = CreateEvent(NULL, FALSE, FALSE, "Ctrl_C");
|
||||
CreateThread(NULL, 0, stdin_read_thread, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function uses to WaitForMultipleObjects to wait for both
|
||||
* stdin and socket reading or writing.
|
||||
* Stdin is treated special in WIN32. Waiting for stdin is done
|
||||
* via a bounce_full event which is set in the stdin thread.
|
||||
* Execute command file reading is done via handle. Execute
|
||||
* command is read via CreateFile/ReadFile instead open/read
|
||||
* because a file descriptor is not waitable.
|
||||
* WaitForMultipleObjects will only respond with one object
|
||||
* so an additonal select is also done to determine
|
||||
* which individual events are active for the sock.
|
||||
*/
|
||||
static int
|
||||
w32_select(int nfds, fd_set *rdfd, fd_set *wrfd, fd_set *errfd, struct timeval* time)
|
||||
{
|
||||
HANDLE handles[3];
|
||||
SOCKET sock;
|
||||
int result, s_result, num_handles = 0;
|
||||
struct timeval tv_time = {0, 0};
|
||||
fd_set rdfd2;
|
||||
|
||||
if (rdfd->fd_count > 1) {
|
||||
sock = rdfd->fd_array[1];
|
||||
if (rdfd->fd_array[0])
|
||||
handles[num_handles++] = (HANDLE)rdfd->fd_array[0];
|
||||
else {
|
||||
handles[num_handles++] = ctrl_c_event;
|
||||
handles[num_handles++] = bounce_full;
|
||||
}
|
||||
} else {
|
||||
assert(rdfd->fd_count == 1);
|
||||
sock = rdfd->fd_array[0];
|
||||
}
|
||||
assert(wrfd->fd_count == 0 ||
|
||||
(wrfd->fd_count == 1 && wrfd->fd_array[0] == sock));
|
||||
/* always wait on the socket */
|
||||
handles[num_handles++] = WSACreateEvent();
|
||||
|
||||
if (wrfd->fd_count > 0)
|
||||
WSAEventSelect(sock, handles[num_handles - 1],
|
||||
FD_READ | FD_WRITE | FD_CLOSE);
|
||||
else
|
||||
WSAEventSelect(sock, handles[num_handles - 1],
|
||||
FD_READ | FD_CLOSE);
|
||||
|
||||
result = WaitForMultipleObjects(num_handles, handles, 0, INFINITE);
|
||||
if (result < 0) {
|
||||
errno = GetLastError();
|
||||
WSACloseEvent(handles[num_handles - 1]);
|
||||
return -1;
|
||||
}
|
||||
WSACloseEvent(handles[num_handles - 1]);
|
||||
|
||||
if (num_handles == 3 && result == WAIT_OBJECT_0) {
|
||||
errno = EINTR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
FD_ZERO(&rdfd2);
|
||||
FD_SET(sock, &rdfd2);
|
||||
s_result = select(sock + 1, &rdfd2, wrfd, NULL, &tv_time);
|
||||
|
||||
if (s_result < 0) {
|
||||
errno = WSAGetLastError();
|
||||
return s_result;
|
||||
}
|
||||
|
||||
*rdfd = rdfd2;
|
||||
if (num_handles == 3 && result == WAIT_OBJECT_0 + 1) {
|
||||
FD_SET((SOCKET)0, rdfd);
|
||||
s_result++;
|
||||
}
|
||||
if (num_handles == 2 && result == WAIT_OBJECT_0) {
|
||||
FD_SET((SOCKET)handles[0], rdfd);
|
||||
s_result++;
|
||||
}
|
||||
return s_result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read input from the user either stdin or from file.
|
||||
* For stdin, read from bounce_buf which filled by the stdin thread
|
||||
* otherwise use the regular ring_from_file.
|
||||
*/
|
||||
static int
|
||||
w32_ring_from_file_or_bounce_buf(struct ring *r, int fd)
|
||||
{
|
||||
int i, res;
|
||||
|
||||
if (fd)
|
||||
return ring_from_file(r, fd);
|
||||
|
||||
if (bounce_status < 0) {
|
||||
errno = bounce_error;
|
||||
res = bounce_status;
|
||||
} else {
|
||||
for (i = 0; i < bounce_status; i++) {
|
||||
if (ring_putc(r, bounce_buf[i]) == EOF) {
|
||||
/* more work to do, hold on to bounce_buf */
|
||||
memmove(bounce_buf, bounce_buf + i, bounce_status - i);
|
||||
bounce_status -= i;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
res = i;
|
||||
}
|
||||
|
||||
ResetEvent(bounce_full);
|
||||
SetEvent(bounce_empty);
|
||||
return res;
|
||||
}
|
||||
#define ring_from_file w32_ring_from_file_or_bounce_buf
|
||||
#define close(fd) w32_close_handle((fd))
|
||||
#define read(sock, buffer, buf_size) \
|
||||
w32_recv((sock), (buffer), (buf_size), 0)
|
||||
#define select(nfds, rd, wr, error, time) \
|
||||
w32_select((nfds), (rd), (wr), (error), (time))
|
||||
#else
|
||||
#define sysdep_stdin_init() ((void)0)
|
||||
#endif
|
||||
|
||||
#define EOF_COOKIE "ctld\n"
|
||||
#define INTR_COOKIE "\naborted\n"
|
||||
|
||||
|
@ -197,9 +437,6 @@ static void
|
|||
intr(int sig)
|
||||
{
|
||||
send_intr = 1;
|
||||
#ifdef _WIN32
|
||||
signal(SIGINT, intr);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -231,6 +468,7 @@ play(int sock)
|
|||
ring_init(&inbuf);
|
||||
eof_fd0 = send_eof = send_intr = 0;
|
||||
input_fd = 0;
|
||||
sysdep_stdin_init(&eof_fd0, &inbuf);
|
||||
|
||||
for (;;) {
|
||||
FD_ZERO(&rdfd);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue