server: Enhanced the console input object so that it doesn't require a wineconsole to be running.
diff --git a/server/console.c b/server/console.c
index d44ad41..9d84491 100644
--- a/server/console.c
+++ b/server/console.c
@@ -28,6 +28,9 @@
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
@@ -62,10 +65,13 @@
int output_cp; /* console output codepage */
user_handle_t win; /* window handle if backend supports it */
struct event *event; /* event to wait on for input queue */
+ struct fd *fd; /* for bare console, attached input fd */
+ struct termios termios; /* for bare console, saved termio info */
};
static void console_input_dump( struct object *obj, int verbose );
static void console_input_destroy( struct object *obj );
+static struct fd *console_input_get_fd( struct object *obj );
static const struct object_ops console_input_ops =
{
@@ -77,7 +83,7 @@
NULL, /* signaled */
no_satisfied, /* satisfied */
no_signal, /* signal */
- no_get_fd, /* get_fd */
+ console_input_get_fd, /* get_fd */
default_fd_map_access, /* map_access */
default_get_sd, /* get_sd */
default_set_sd, /* set_sd */
@@ -162,10 +168,36 @@
screen_buffer_destroy /* destroy */
};
+static enum server_fd_type console_get_fd_type( struct fd *fd );
+
+static const struct fd_ops console_fd_ops =
+{
+ default_fd_get_poll_events, /* get_poll_events */
+ default_poll_event, /* poll_event */
+ no_flush, /* flush */
+ console_get_fd_type, /* get_fd_type */
+ default_fd_ioctl, /* ioctl */
+ default_fd_queue_async, /* queue_async */
+ default_fd_reselect_async, /* reselect_async */
+ default_fd_cancel_async /* cancel_async */
+};
+
static struct list screen_buffer_list = LIST_INIT(screen_buffer_list);
static const char_info_t empty_char_info = { ' ', 0x000f }; /* white on black space */
+static struct fd *console_input_get_fd( struct object* obj )
+{
+ struct console_input *console_input = (struct console_input*)obj;
+ assert( obj->ops == &console_input_ops );
+ return console_input->fd ? (struct fd*)grab_object( console_input->fd ) : NULL;
+}
+
+static enum server_fd_type console_get_fd_type( struct fd *fd )
+{
+ return FD_TYPE_CHAR;
+}
+
/* dumps the renderer events of a console */
static void console_input_events_dump( struct object *obj, int verbose )
{
@@ -197,7 +229,8 @@
{
int collapsed = FALSE;
- /* to be done even when evt has been generated by the rendere ? */
+ if (!evts) return;
+ /* to be done even when evt has been generated by the renderer ? */
/* try to collapse evt into current queue's events */
if (evts->num_used)
@@ -255,7 +288,7 @@
return evt;
}
-static struct object *create_console_input( struct thread* renderer )
+static struct object *create_console_input( struct thread* renderer, int fd )
{
struct console_input *console_input;
@@ -267,7 +300,7 @@
console_input->active = NULL;
console_input->recnum = 0;
console_input->records = NULL;
- console_input->evt = create_console_input_events();
+ console_input->evt = renderer ? create_console_input_events() : NULL;
console_input->title = NULL;
console_input->history_size = 50;
console_input->history = calloc( console_input->history_size, sizeof(WCHAR*) );
@@ -278,12 +311,50 @@
console_input->output_cp = 0;
console_input->win = 0;
console_input->event = create_event( NULL, NULL, 0, 1, 0, NULL );
+ console_input->fd = NULL;
- if (!console_input->history || !console_input->evt || !console_input->event)
+ if (!console_input->history || (renderer && !console_input->evt) || !console_input->event)
{
release_object( console_input );
return NULL;
}
+ if (fd != -1) /* bare console */
+ {
+ struct termios term;
+
+ if (!(console_input->fd = create_anonymous_fd( &console_fd_ops, fd, &console_input->obj,
+ FILE_SYNCHRONOUS_IO_NONALERT )))
+ {
+ release_object( console_input );
+ return NULL;
+ }
+ if (tcgetattr(fd, &term) < 0)
+ {
+ release_object( console_input );
+ set_error( STATUS_INVALID_HANDLE );
+ return NULL;
+ }
+ console_input->termios = term;
+ term.c_lflag &= ~(ECHO | ECHONL | ICANON | IEXTEN);
+ term.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
+ term.c_cflag &= ~(CSIZE | PARENB);
+ term.c_cflag |= CS8;
+ /* FIXME: we should actually disable output processing here
+ * and let kernel32/console.c do the job (with support of enable/disable of
+ * processed output)
+ */
+ /* term.c_oflag &= ~(OPOST); */
+ term.c_cc[VMIN] = 1;
+ term.c_cc[VTIME] = 0;
+ if (tcsetattr(fd, TCSANOW, &term) < 0)
+ {
+ release_object( console_input );
+ set_error( STATUS_INVALID_HANDLE );
+ return NULL;
+ }
+ allow_fd_caching( console_input->fd );
+ }
+
return &console_input->obj;
}
@@ -374,10 +445,10 @@
{
struct console_input* console = process->console;
- if (!console || !console->renderer) return 0;
+ if (!console) return 0;
process->console = NULL;
- if (--console->num_proc == 0)
+ if (--console->num_proc == 0 && console->renderer)
{
/* all processes have terminated... tell the renderer to terminate too */
struct console_renderer_event evt;
@@ -424,7 +495,6 @@
/* otherwise, if parent has a console, attach child to this console */
if (!done && parent->console)
{
- assert(parent->console->renderer);
process->console = (struct console_input*)grab_object( parent->console );
process->console->num_proc++;
}
@@ -444,7 +514,6 @@
access, &console_input_ops );
else if (current->process->console)
{
- assert( current->process->console->renderer );
console = (struct console_input *)grab_object( current->process->console );
}
@@ -1020,9 +1089,17 @@
if (curr->input == console_in) curr->input = NULL;
}
- release_object( console_in->evt );
- console_in->evt = NULL;
+ if (console_in->evt)
+ {
+ release_object( console_in->evt );
+ console_in->evt = NULL;
+ }
release_object( console_in->event );
+ if (console_in->fd)
+ {
+ tcsetattr(get_unix_fd(console_in->fd), TCSANOW, &console_in->termios);
+ release_object( console_in->fd );
+ }
for (i = 0; i < console_in->history_size; i++)
free( console_in->history[i] );
@@ -1295,35 +1372,58 @@
obj_handle_t in = 0;
obj_handle_t evt = 0;
struct process *process;
+ struct thread *renderer;
struct console_input *console;
+ int fd;
- if (req->pid)
+ switch (req->pid)
{
- if (!(process = get_process_from_id( req->pid ))) return;
- }
- else
- {
+ case 0:
+ /* renderer is current, console to be attached to parent process */
+ renderer = current;
if (!(process = current->process->parent))
{
set_error( STATUS_ACCESS_DENIED );
return;
}
grab_object( process );
+ break;
+ case 0xffffffff:
+ /* no renderer, console to be attached to current process */
+ renderer = NULL;
+ process = current->process;
+ grab_object( process );
+ break;
+ default:
+ /* renderer is current, console to be attached to req->pid */
+ renderer = current;
+ if (!(process = get_process_from_id( req->pid ))) return;
}
if (process != current->process && process->console)
+ {
set_error( STATUS_ACCESS_DENIED );
- else if ((console = (struct console_input*)create_console_input( current )))
+ goto the_end;
+ }
+ if (req->input_fd != -1)
+ {
+ if ((fd = thread_get_inflight_fd( current, req->input_fd )) == -1)
+ {
+ set_error( STATUS_INVALID_PARAMETER );
+ goto the_end;
+ }
+ }
+ else fd = -1;
+
+ if ((console = (struct console_input*)create_console_input( renderer, fd )))
{
if ((in = alloc_handle( current->process, console, req->access, req->attributes )))
{
- if ((evt = alloc_handle( current->process, console->evt, SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE, 0 )))
+ if (!console->evt ||
+ (evt = alloc_handle( current->process, console->evt, SYNCHRONIZE|GENERIC_READ|GENERIC_WRITE, 0 )))
{
- if (process != current->process)
- {
- process->console = (struct console_input*)grab_object( console );
- console->num_proc++;
- }
+ process->console = (struct console_input*)grab_object( console );
+ console->num_proc++;
reply->handle_in = in;
reply->event = evt;
release_object( console );
@@ -1363,13 +1463,12 @@
reply->handle = 0;
if (!req->from)
{
- if (current->process->console && current->process->console->renderer)
+ if (current->process->console)
obj = grab_object( (struct object*)current->process->console );
}
else if (req->from == (obj_handle_t)1)
{
- if (current->process->console && current->process->console->renderer &&
- current->process->console->active)
+ if (current->process->console && current->process->console->active)
obj = grab_object( (struct object*)current->process->console->active );
}
else if ((obj = get_handle_obj( current->process, req->from,
@@ -1608,7 +1707,7 @@
{
struct console_input* console = NULL;
- if (current->process->console && current->process->console->renderer)
+ if (current->process->console)
console = (struct console_input*)grab_object( (struct object*)current->process->console );
else enum_processes(cgwe_enum, &console);