blob: 8ed9ec1c5140998fd967376aed61f2a12ef196f9 [file] [log] [blame]
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +00001/*
2 * Server-side console management
3 *
4 * Copyright (C) 1998 Alexandre Julliard
5 *
6 * FIXME: all this stuff is a hack to avoid breaking
7 * the client-side console support.
8 */
9
10#include <assert.h>
11#include <fcntl.h>
Alexandre Julliard62a8b431999-01-19 17:48:23 +000012#include <signal.h>
Alexandre Julliard05625391999-01-03 11:55:56 +000013#include <string.h>
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000014#include <stdio.h>
15#include <stdlib.h>
16#include <sys/errno.h>
17#include <sys/stat.h>
18#include <sys/time.h>
19#include <sys/types.h>
20#include <time.h>
21#include <unistd.h>
22
23#include "winerror.h"
24#include "winnt.h"
Alexandre Julliard62a8b431999-01-19 17:48:23 +000025#include "wincon.h"
Alexandre Julliard43c190e1999-05-15 10:48:19 +000026
27#include "handle.h"
28#include "process.h"
29#include "thread.h"
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000030
Alexandre Julliard62a8b431999-01-19 17:48:23 +000031struct screen_buffer;
32
33struct console_input
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000034{
Alexandre Julliard62a8b431999-01-19 17:48:23 +000035 struct object obj; /* object header */
Alexandre Julliard57e11311999-05-16 16:59:38 +000036 struct select_user select; /* select user */
Alexandre Julliard62a8b431999-01-19 17:48:23 +000037 int mode; /* input mode */
38 struct screen_buffer *output; /* associated screen buffer */
Alexandre Julliard4b461121999-01-31 19:04:30 +000039 int recnum; /* number of input records */
40 INPUT_RECORD *records; /* input records */
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000041};
42
Alexandre Julliard62a8b431999-01-19 17:48:23 +000043struct screen_buffer
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000044{
Alexandre Julliard62a8b431999-01-19 17:48:23 +000045 struct object obj; /* object header */
Alexandre Julliard57e11311999-05-16 16:59:38 +000046 struct select_user select; /* select user */
Alexandre Julliard62a8b431999-01-19 17:48:23 +000047 int mode; /* output mode */
48 struct console_input *input; /* associated console input */
49 int cursor_size; /* size of cursor (percentage filled) */
50 int cursor_visible;/* cursor visibility flag */
51 int pid; /* xterm pid (hack) */
52 char *title; /* console title */
53};
54
55
56static void console_input_dump( struct object *obj, int verbose );
57static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry );
58static void console_input_remove_queue( struct object *obj, struct wait_queue_entry *entry );
59static int console_input_signaled( struct object *obj, struct thread *thread );
60static int console_input_get_read_fd( struct object *obj );
61static void console_input_destroy( struct object *obj );
62
63static void screen_buffer_dump( struct object *obj, int verbose );
64static int screen_buffer_add_queue( struct object *obj, struct wait_queue_entry *entry );
65static void screen_buffer_remove_queue( struct object *obj, struct wait_queue_entry *entry );
66static int screen_buffer_signaled( struct object *obj, struct thread *thread );
67static int screen_buffer_get_write_fd( struct object *obj );
68static void screen_buffer_destroy( struct object *obj );
69
70/* common routine */
71static int console_get_info( struct object *obj, struct get_file_info_reply *reply );
72
73static const struct object_ops console_input_ops =
74{
75 console_input_dump,
76 console_input_add_queue,
77 console_input_remove_queue,
78 console_input_signaled,
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000079 no_satisfied,
Alexandre Julliard62a8b431999-01-19 17:48:23 +000080 console_input_get_read_fd,
81 no_write_fd,
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000082 no_flush,
Alexandre Julliard05625391999-01-03 11:55:56 +000083 console_get_info,
Alexandre Julliard62a8b431999-01-19 17:48:23 +000084 console_input_destroy
85};
86
87static const struct object_ops screen_buffer_ops =
88{
89 screen_buffer_dump,
90 screen_buffer_add_queue,
91 screen_buffer_remove_queue,
92 screen_buffer_signaled,
93 no_satisfied,
94 no_read_fd,
95 screen_buffer_get_write_fd,
96 no_flush,
97 console_get_info,
98 screen_buffer_destroy
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +000099};
100
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000101
Alexandre Julliard039aa421999-06-11 18:31:22 +0000102static int create_console( int fd, struct object *obj[2] )
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000103{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000104 struct console_input *console_input;
105 struct screen_buffer *screen_buffer;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000106 int read_fd, write_fd;
107
108 if ((read_fd = (fd != -1) ? dup(fd) : dup(0)) == -1)
109 {
110 file_set_error();
111 return 0;
112 }
Alexandre Julliard638f1691999-01-17 16:32:32 +0000113 if ((write_fd = (fd != -1) ? dup(fd) : dup(1)) == -1)
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000114 {
115 file_set_error();
116 close( read_fd );
117 return 0;
118 }
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000119 if (!(console_input = mem_alloc( sizeof(struct console_input) )))
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000120 {
121 close( read_fd );
122 close( write_fd );
123 return 0;
124 }
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000125 if (!(screen_buffer = mem_alloc( sizeof(struct screen_buffer) )))
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000126 {
127 close( read_fd );
128 close( write_fd );
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000129 free( console_input );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000130 return 0;
131 }
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000132 init_object( &console_input->obj, &console_input_ops, NULL );
133 init_object( &screen_buffer->obj, &screen_buffer_ops, NULL );
Alexandre Julliard57e11311999-05-16 16:59:38 +0000134 console_input->select.fd = read_fd;
135 console_input->select.func = default_select_event;
136 console_input->select.private = console_input;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000137 console_input->mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT |
138 ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT;
139 console_input->output = screen_buffer;
Alexandre Julliard4b461121999-01-31 19:04:30 +0000140 console_input->recnum = 0;
141 console_input->records = NULL;
Alexandre Julliard57e11311999-05-16 16:59:38 +0000142 screen_buffer->select.fd = write_fd;
143 screen_buffer->select.func = default_select_event;
144 screen_buffer->select.private = screen_buffer;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000145 screen_buffer->mode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT;
146 screen_buffer->input = console_input;
147 screen_buffer->cursor_size = 100;
148 screen_buffer->cursor_visible = 1;
149 screen_buffer->pid = 0;
150 screen_buffer->title = strdup( "Wine console" );
Alexandre Julliard57e11311999-05-16 16:59:38 +0000151 register_select_user( &console_input->select );
152 register_select_user( &screen_buffer->select );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000153 CLEAR_ERROR();
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000154 obj[0] = &console_input->obj;
155 obj[1] = &screen_buffer->obj;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000156 return 1;
157}
158
Alexandre Julliard039aa421999-06-11 18:31:22 +0000159/* allocate a console for this process */
160int alloc_console( struct process *process )
161{
162 struct object *obj[2];
163 if (process->console_in || process->console_out)
164 {
165 SET_ERROR( ERROR_ACCESS_DENIED );
166 return 0;
167 }
168 if (!create_console( -1, obj )) return 0;
169 process->console_in = obj[0];
170 process->console_out = obj[1];
171 return 1;
172}
173
174/* free the console for this process */
175int free_console( struct process *process )
176{
177 if (process->console_in) release_object( process->console_in );
178 if (process->console_out) release_object( process->console_out );
179 process->console_in = process->console_out = NULL;
180 return 1;
181}
182
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000183static int set_console_fd( int handle, int fd, int pid )
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000184{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000185 struct console_input *input;
186 struct screen_buffer *output;
187 struct object *obj;
188 int fd_in, fd_out;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000189
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000190 if (!(obj = get_handle_obj( current->process, handle, 0, NULL )))
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000191 return 0;
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000192 if (obj->ops == &console_input_ops)
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000193 {
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000194 input = (struct console_input *)obj;
195 output = input->output;
196 grab_object( output );
197 }
198 else if (obj->ops == &screen_buffer_ops)
199 {
200 output = (struct screen_buffer *)obj;
201 input = output->input;
202 grab_object( input );
203 }
204 else
205 {
206 SET_ERROR( ERROR_INVALID_HANDLE );
207 release_object( obj );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000208 return 0;
209 }
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000210
Alexandre Julliard57e11311999-05-16 16:59:38 +0000211 /* can't change the fd if someone is waiting on it */
212 assert( !input->obj.head );
213 assert( !output->obj.head );
214
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000215 if ((fd_in = dup(fd)) == -1)
216 {
217 file_set_error();
218 release_object( input );
219 release_object( output );
220 return 0;
221 }
222 if ((fd_out = dup(fd)) == -1)
223 {
224 file_set_error();
225 close( fd_in );
226 release_object( input );
227 release_object( output );
228 return 0;
229 }
Alexandre Julliard57e11311999-05-16 16:59:38 +0000230 unregister_select_user( &input->select );
231 unregister_select_user( &output->select );
232 close( input->select.fd );
233 close( output->select.fd );
234 input->select.fd = fd_in;
235 output->select.fd = fd_out;
236 output->pid = pid;
237 register_select_user( &input->select );
238 register_select_user( &output->select );
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000239 release_object( input );
240 release_object( output );
241 return 1;
242}
243
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000244static int get_console_mode( int handle, int *mode )
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000245{
246 struct object *obj;
247 int ret = 0;
248
249 if (!(obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL )))
250 return 0;
251 if (obj->ops == &console_input_ops)
252 {
253 *mode = ((struct console_input *)obj)->mode;
254 ret = 1;
255 }
256 else if (obj->ops == &screen_buffer_ops)
257 {
258 *mode = ((struct screen_buffer *)obj)->mode;
259 ret = 1;
260 }
261 else SET_ERROR( ERROR_INVALID_HANDLE );
262 release_object( obj );
263 return ret;
264}
265
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000266static int set_console_mode( int handle, int mode )
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000267{
268 struct object *obj;
269 int ret = 0;
270
271 if (!(obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL )))
272 return 0;
273 if (obj->ops == &console_input_ops)
274 {
275 ((struct console_input *)obj)->mode = mode;
276 ret = 1;
277 }
278 else if (obj->ops == &screen_buffer_ops)
279 {
280 ((struct screen_buffer *)obj)->mode = mode;
281 ret = 1;
282 }
283 else SET_ERROR( ERROR_INVALID_HANDLE );
284 release_object( obj );
285 return ret;
286}
287
288/* set misc console information (output handle only) */
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000289static int set_console_info( int handle, struct set_console_info_request *req, const char *title )
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000290{
291 struct screen_buffer *console;
292 if (!(console = (struct screen_buffer *)get_handle_obj( current->process, handle,
293 GENERIC_WRITE, &screen_buffer_ops )))
294 return 0;
295 if (req->mask & SET_CONSOLE_INFO_CURSOR)
296 {
297 console->cursor_size = req->cursor_size;
298 console->cursor_visible = req->cursor_visible;
299 }
300 if (req->mask & SET_CONSOLE_INFO_TITLE)
301 {
302 if (console->title) free( console->title );
303 console->title = strdup( title );
304 }
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000305 release_object( console );
306 return 1;
307}
308
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000309/* get misc console information (output handle only) */
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000310static int get_console_info( int handle, struct get_console_info_reply *reply, const char **title )
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000311{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000312 struct screen_buffer *console;
313 if (!(console = (struct screen_buffer *)get_handle_obj( current->process, handle,
314 GENERIC_READ, &screen_buffer_ops )))
315 return 0;
316 reply->cursor_size = console->cursor_size;
317 reply->cursor_visible = console->cursor_visible;
318 reply->pid = console->pid;
319 *title = console->title;
320 release_object( console );
321 return 1;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000322}
323
Alexandre Julliard4b461121999-01-31 19:04:30 +0000324/* add input events to a console input queue */
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000325static int write_console_input( int handle, int count, INPUT_RECORD *records )
Alexandre Julliard4b461121999-01-31 19:04:30 +0000326{
327 INPUT_RECORD *new_rec;
328 struct console_input *console;
329
330 if (!(console = (struct console_input *)get_handle_obj( current->process, handle,
331 GENERIC_WRITE, &console_input_ops )))
332 return -1;
333 if (!(new_rec = realloc( console->records,
334 (console->recnum + count) * sizeof(INPUT_RECORD) )))
335 {
336 SET_ERROR( ERROR_NOT_ENOUGH_MEMORY );
337 release_object( console );
338 return -1;
339 }
340 console->records = new_rec;
341 memcpy( new_rec + console->recnum, records, count * sizeof(INPUT_RECORD) );
342 console->recnum += count;
343 release_object( console );
344 return count;
345}
346
347/* retrieve a pointer to the console input records */
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000348static int read_console_input( int handle, int count, int flush )
Alexandre Julliard4b461121999-01-31 19:04:30 +0000349{
350 struct console_input *console;
Alexandre Julliard039aa421999-06-11 18:31:22 +0000351 struct read_console_input_reply reply;
Alexandre Julliard4b461121999-01-31 19:04:30 +0000352
353 if (!(console = (struct console_input *)get_handle_obj( current->process, handle,
354 GENERIC_READ, &console_input_ops )))
355 return -1;
356 if ((count < 0) || (count > console->recnum)) count = console->recnum;
Alexandre Julliard039aa421999-06-11 18:31:22 +0000357 send_reply( current, -1, 2, &reply, sizeof(reply),
358 console->records, count * sizeof(INPUT_RECORD) );
Alexandre Julliard4b461121999-01-31 19:04:30 +0000359 if (flush)
360 {
361 int i;
362 for (i = count; i < console->recnum; i++)
363 console->records[i-count] = console->records[i];
364 if ((console->recnum -= count) > 0)
365 {
366 INPUT_RECORD *new_rec = realloc( console->records,
367 console->recnum * sizeof(INPUT_RECORD) );
368 if (new_rec) console->records = new_rec;
369 }
370 else
371 {
372 free( console->records );
373 console->records = NULL;
374 }
375 }
376 release_object( console );
377 return count;
378}
379
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000380static void console_input_dump( struct object *obj, int verbose )
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000381{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000382 struct console_input *console = (struct console_input *)obj;
383 assert( obj->ops == &console_input_ops );
Alexandre Julliard57e11311999-05-16 16:59:38 +0000384 fprintf( stderr, "Console input fd=%d\n", console->select.fd );
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000385}
386
387static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry )
388{
389 struct console_input *console = (struct console_input *)obj;
390 assert( obj->ops == &console_input_ops );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000391 if (!obj->head) /* first on the queue */
Alexandre Julliard57e11311999-05-16 16:59:38 +0000392 set_select_events( &console->select, READ_EVENT );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000393 add_queue( obj, entry );
Alexandre Julliarda8b8d9c1999-01-01 16:59:27 +0000394 return 1;
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000395}
396
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000397static void console_input_remove_queue( struct object *obj, struct wait_queue_entry *entry )
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000398{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000399 struct console_input *console = (struct console_input *)grab_object(obj);
400 assert( obj->ops == &console_input_ops );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000401
402 remove_queue( obj, entry );
403 if (!obj->head) /* last on the queue is gone */
Alexandre Julliard57e11311999-05-16 16:59:38 +0000404 set_select_events( &console->select, 0 );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000405 release_object( obj );
406}
407
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000408static int console_input_signaled( struct object *obj, struct thread *thread )
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000409{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000410 struct console_input *console = (struct console_input *)obj;
411 assert( obj->ops == &console_input_ops );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000412
Alexandre Julliard57e11311999-05-16 16:59:38 +0000413 if (check_select_events( &console->select, READ_EVENT ))
414 {
415 /* stop waiting on select() if we are signaled */
416 set_select_events( &console->select, 0 );
417 return 1;
418 }
419 else
420 {
421 /* restart waiting on select() if we are no longer signaled */
422 if (obj->head) set_select_events( &console->select, READ_EVENT );
423 return 0;
424 }
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000425}
426
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000427static int console_input_get_read_fd( struct object *obj )
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000428{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000429 struct console_input *console = (struct console_input *)obj;
430 assert( obj->ops == &console_input_ops );
Alexandre Julliard57e11311999-05-16 16:59:38 +0000431 return dup( console->select.fd );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000432}
433
Alexandre Julliard05625391999-01-03 11:55:56 +0000434static int console_get_info( struct object *obj, struct get_file_info_reply *reply )
435{
436 memset( reply, 0, sizeof(*reply) );
437 reply->type = FILE_TYPE_CHAR;
438 return 1;
439}
440
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000441static void console_input_destroy( struct object *obj )
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000442{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000443 struct console_input *console = (struct console_input *)obj;
444 assert( obj->ops == &console_input_ops );
Alexandre Julliard57e11311999-05-16 16:59:38 +0000445 unregister_select_user( &console->select );
446 close( console->select.fd );
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000447 if (console->output) console->output->input = NULL;
448 free( console );
449}
450
451static void screen_buffer_dump( struct object *obj, int verbose )
452{
453 struct screen_buffer *console = (struct screen_buffer *)obj;
454 assert( obj->ops == &screen_buffer_ops );
Alexandre Julliard57e11311999-05-16 16:59:38 +0000455 fprintf( stderr, "Console screen buffer fd=%d\n", console->select.fd );
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000456}
457
458static int screen_buffer_add_queue( struct object *obj, struct wait_queue_entry *entry )
459{
460 struct screen_buffer *console = (struct screen_buffer *)obj;
461 assert( obj->ops == &screen_buffer_ops );
462 if (!obj->head) /* first on the queue */
Alexandre Julliard57e11311999-05-16 16:59:38 +0000463 set_select_events( &console->select, WRITE_EVENT );
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000464 add_queue( obj, entry );
465 return 1;
466}
467
468static void screen_buffer_remove_queue( struct object *obj, struct wait_queue_entry *entry )
469{
470 struct screen_buffer *console = (struct screen_buffer *)grab_object(obj);
471 assert( obj->ops == &screen_buffer_ops );
472
473 remove_queue( obj, entry );
474 if (!obj->head) /* last on the queue is gone */
Alexandre Julliard57e11311999-05-16 16:59:38 +0000475 set_select_events( &console->select, 0 );
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000476 release_object( obj );
477}
478
479static int screen_buffer_signaled( struct object *obj, struct thread *thread )
480{
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000481 struct screen_buffer *console = (struct screen_buffer *)obj;
482 assert( obj->ops == &screen_buffer_ops );
483
Alexandre Julliard57e11311999-05-16 16:59:38 +0000484 if (check_select_events( &console->select, WRITE_EVENT ))
485 {
486 /* stop waiting on select() if we are signaled */
487 set_select_events( &console->select, 0 );
488 return 1;
489 }
490 else
491 {
492 /* restart waiting on select() if we are no longer signaled */
493 if (obj->head) set_select_events( &console->select, WRITE_EVENT );
494 return 0;
495 }
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000496}
497
498static int screen_buffer_get_write_fd( struct object *obj )
499{
500 struct screen_buffer *console = (struct screen_buffer *)obj;
501 assert( obj->ops == &screen_buffer_ops );
Alexandre Julliard57e11311999-05-16 16:59:38 +0000502 return dup( console->select.fd );
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000503}
504
505static void screen_buffer_destroy( struct object *obj )
506{
507 struct screen_buffer *console = (struct screen_buffer *)obj;
508 assert( obj->ops == &screen_buffer_ops );
Alexandre Julliard57e11311999-05-16 16:59:38 +0000509 unregister_select_user( &console->select );
510 close( console->select.fd );
Alexandre Julliard62a8b431999-01-19 17:48:23 +0000511 if (console->input) console->input->output = NULL;
512 if (console->pid) kill( console->pid, SIGTERM );
513 if (console->title) free( console->title );
Alexandre Julliardaa0ebd01998-12-30 12:06:45 +0000514 free( console );
515}
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000516
517/* allocate a console for the current process */
518DECL_HANDLER(alloc_console)
519{
Alexandre Julliard039aa421999-06-11 18:31:22 +0000520 struct alloc_console_reply reply = { -1, -1 };
521
522 if (!alloc_console( current->process )) goto done;
523
524 if ((reply.handle_in = alloc_handle( current->process, current->process->console_in,
525 req->access, req->inherit )) != -1)
526 {
527 if ((reply.handle_out = alloc_handle( current->process, current->process->console_out,
528 req->access, req->inherit )) != -1)
529 goto done; /* everything is fine */
530 close_handle( current->process, reply.handle_in );
531 reply.handle_in = -1;
532 }
533 free_console( current->process );
534
535 done:
536 send_reply( current, -1, 1, &reply, sizeof(reply) );
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000537}
538
539/* free the console of the current process */
540DECL_HANDLER(free_console)
541{
542 free_console( current->process );
543 send_reply( current, -1, 0 );
544}
545
546/* open a handle to the process console */
547DECL_HANDLER(open_console)
548{
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000549 struct open_console_reply reply = { -1 };
Alexandre Julliard039aa421999-06-11 18:31:22 +0000550 struct object *obj= req->output ? current->process->console_out : current->process->console_in;
551
552 if (obj) reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
Alexandre Julliard43c190e1999-05-15 10:48:19 +0000553 send_reply( current, -1, 1, &reply, sizeof(reply) );
554}
555
556/* set info about a console (output only) */
557DECL_HANDLER(set_console_info)
558{
559 char *name = (char *)data;
560 if (!len) name = NULL;
561 else CHECK_STRING( "set_console_info", name, len );
562 set_console_info( req->handle, req, name );
563 send_reply( current, -1, 0 );
564}
565
566/* get info about a console (output only) */
567DECL_HANDLER(get_console_info)
568{
569 struct get_console_info_reply reply;
570 const char *title;
571 get_console_info( req->handle, &reply, &title );
572 send_reply( current, -1, 2, &reply, sizeof(reply),
573 title, title ? strlen(title)+1 : 0 );
574}
575
576/* set a console fd */
577DECL_HANDLER(set_console_fd)
578{
579 set_console_fd( req->handle, fd, req->pid );
580 send_reply( current, -1, 0 );
581}
582
583/* get a console mode (input or output) */
584DECL_HANDLER(get_console_mode)
585{
586 struct get_console_mode_reply reply;
587 get_console_mode( req->handle, &reply.mode );
588 send_reply( current, -1, 1, &reply, sizeof(reply) );
589}
590
591/* set a console mode (input or output) */
592DECL_HANDLER(set_console_mode)
593{
594 set_console_mode( req->handle, req->mode );
595 send_reply( current, -1, 0 );
596}
597
598/* add input records to a console input queue */
599DECL_HANDLER(write_console_input)
600{
601 struct write_console_input_reply reply;
602 INPUT_RECORD *records = (INPUT_RECORD *)data;
603
604 if (len != req->count * sizeof(INPUT_RECORD))
605 fatal_protocol_error( "write_console_input: bad length %d for %d records\n",
606 len, req->count );
607 reply.written = write_console_input( req->handle, req->count, records );
608 send_reply( current, -1, 1, &reply, sizeof(reply) );
609}
610
611/* fetch input records from a console input queue */
612DECL_HANDLER(read_console_input)
613{
614 read_console_input( req->handle, req->count, req->flush );
615}