Fix compiler warning.
[wine.git] / server / console.c
blob8ed9ec1c5140998fd967376aed61f2a12ef196f9
1 /*
2 * Server-side console management
4 * Copyright (C) 1998 Alexandre Julliard
6 * FIXME: all this stuff is a hack to avoid breaking
7 * the client-side console support.
8 */
10 #include <assert.h>
11 #include <fcntl.h>
12 #include <signal.h>
13 #include <string.h>
14 #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>
23 #include "winerror.h"
24 #include "winnt.h"
25 #include "wincon.h"
27 #include "handle.h"
28 #include "process.h"
29 #include "thread.h"
31 struct screen_buffer;
33 struct console_input
35 struct object obj; /* object header */
36 struct select_user select; /* select user */
37 int mode; /* input mode */
38 struct screen_buffer *output; /* associated screen buffer */
39 int recnum; /* number of input records */
40 INPUT_RECORD *records; /* input records */
43 struct screen_buffer
45 struct object obj; /* object header */
46 struct select_user select; /* select user */
47 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 */
56 static void console_input_dump( struct object *obj, int verbose );
57 static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry );
58 static void console_input_remove_queue( struct object *obj, struct wait_queue_entry *entry );
59 static int console_input_signaled( struct object *obj, struct thread *thread );
60 static int console_input_get_read_fd( struct object *obj );
61 static void console_input_destroy( struct object *obj );
63 static void screen_buffer_dump( struct object *obj, int verbose );
64 static int screen_buffer_add_queue( struct object *obj, struct wait_queue_entry *entry );
65 static void screen_buffer_remove_queue( struct object *obj, struct wait_queue_entry *entry );
66 static int screen_buffer_signaled( struct object *obj, struct thread *thread );
67 static int screen_buffer_get_write_fd( struct object *obj );
68 static void screen_buffer_destroy( struct object *obj );
70 /* common routine */
71 static int console_get_info( struct object *obj, struct get_file_info_reply *reply );
73 static const struct object_ops console_input_ops =
75 console_input_dump,
76 console_input_add_queue,
77 console_input_remove_queue,
78 console_input_signaled,
79 no_satisfied,
80 console_input_get_read_fd,
81 no_write_fd,
82 no_flush,
83 console_get_info,
84 console_input_destroy
87 static const struct object_ops screen_buffer_ops =
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
102 static int create_console( int fd, struct object *obj[2] )
104 struct console_input *console_input;
105 struct screen_buffer *screen_buffer;
106 int read_fd, write_fd;
108 if ((read_fd = (fd != -1) ? dup(fd) : dup(0)) == -1)
110 file_set_error();
111 return 0;
113 if ((write_fd = (fd != -1) ? dup(fd) : dup(1)) == -1)
115 file_set_error();
116 close( read_fd );
117 return 0;
119 if (!(console_input = mem_alloc( sizeof(struct console_input) )))
121 close( read_fd );
122 close( write_fd );
123 return 0;
125 if (!(screen_buffer = mem_alloc( sizeof(struct screen_buffer) )))
127 close( read_fd );
128 close( write_fd );
129 free( console_input );
130 return 0;
132 init_object( &console_input->obj, &console_input_ops, NULL );
133 init_object( &screen_buffer->obj, &screen_buffer_ops, NULL );
134 console_input->select.fd = read_fd;
135 console_input->select.func = default_select_event;
136 console_input->select.private = console_input;
137 console_input->mode = ENABLE_PROCESSED_INPUT | ENABLE_LINE_INPUT |
138 ENABLE_ECHO_INPUT | ENABLE_MOUSE_INPUT;
139 console_input->output = screen_buffer;
140 console_input->recnum = 0;
141 console_input->records = NULL;
142 screen_buffer->select.fd = write_fd;
143 screen_buffer->select.func = default_select_event;
144 screen_buffer->select.private = screen_buffer;
145 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" );
151 register_select_user( &console_input->select );
152 register_select_user( &screen_buffer->select );
153 CLEAR_ERROR();
154 obj[0] = &console_input->obj;
155 obj[1] = &screen_buffer->obj;
156 return 1;
159 /* allocate a console for this process */
160 int alloc_console( struct process *process )
162 struct object *obj[2];
163 if (process->console_in || process->console_out)
165 SET_ERROR( ERROR_ACCESS_DENIED );
166 return 0;
168 if (!create_console( -1, obj )) return 0;
169 process->console_in = obj[0];
170 process->console_out = obj[1];
171 return 1;
174 /* free the console for this process */
175 int free_console( struct process *process )
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;
183 static int set_console_fd( int handle, int fd, int pid )
185 struct console_input *input;
186 struct screen_buffer *output;
187 struct object *obj;
188 int fd_in, fd_out;
190 if (!(obj = get_handle_obj( current->process, handle, 0, NULL )))
191 return 0;
192 if (obj->ops == &console_input_ops)
194 input = (struct console_input *)obj;
195 output = input->output;
196 grab_object( output );
198 else if (obj->ops == &screen_buffer_ops)
200 output = (struct screen_buffer *)obj;
201 input = output->input;
202 grab_object( input );
204 else
206 SET_ERROR( ERROR_INVALID_HANDLE );
207 release_object( obj );
208 return 0;
211 /* can't change the fd if someone is waiting on it */
212 assert( !input->obj.head );
213 assert( !output->obj.head );
215 if ((fd_in = dup(fd)) == -1)
217 file_set_error();
218 release_object( input );
219 release_object( output );
220 return 0;
222 if ((fd_out = dup(fd)) == -1)
224 file_set_error();
225 close( fd_in );
226 release_object( input );
227 release_object( output );
228 return 0;
230 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 );
239 release_object( input );
240 release_object( output );
241 return 1;
244 static int get_console_mode( int handle, int *mode )
246 struct object *obj;
247 int ret = 0;
249 if (!(obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL )))
250 return 0;
251 if (obj->ops == &console_input_ops)
253 *mode = ((struct console_input *)obj)->mode;
254 ret = 1;
256 else if (obj->ops == &screen_buffer_ops)
258 *mode = ((struct screen_buffer *)obj)->mode;
259 ret = 1;
261 else SET_ERROR( ERROR_INVALID_HANDLE );
262 release_object( obj );
263 return ret;
266 static int set_console_mode( int handle, int mode )
268 struct object *obj;
269 int ret = 0;
271 if (!(obj = get_handle_obj( current->process, handle, GENERIC_READ, NULL )))
272 return 0;
273 if (obj->ops == &console_input_ops)
275 ((struct console_input *)obj)->mode = mode;
276 ret = 1;
278 else if (obj->ops == &screen_buffer_ops)
280 ((struct screen_buffer *)obj)->mode = mode;
281 ret = 1;
283 else SET_ERROR( ERROR_INVALID_HANDLE );
284 release_object( obj );
285 return ret;
288 /* set misc console information (output handle only) */
289 static int set_console_info( int handle, struct set_console_info_request *req, const char *title )
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)
297 console->cursor_size = req->cursor_size;
298 console->cursor_visible = req->cursor_visible;
300 if (req->mask & SET_CONSOLE_INFO_TITLE)
302 if (console->title) free( console->title );
303 console->title = strdup( title );
305 release_object( console );
306 return 1;
309 /* get misc console information (output handle only) */
310 static int get_console_info( int handle, struct get_console_info_reply *reply, const char **title )
312 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;
324 /* add input events to a console input queue */
325 static int write_console_input( int handle, int count, INPUT_RECORD *records )
327 INPUT_RECORD *new_rec;
328 struct console_input *console;
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) )))
336 SET_ERROR( ERROR_NOT_ENOUGH_MEMORY );
337 release_object( console );
338 return -1;
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;
347 /* retrieve a pointer to the console input records */
348 static int read_console_input( int handle, int count, int flush )
350 struct console_input *console;
351 struct read_console_input_reply reply;
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;
357 send_reply( current, -1, 2, &reply, sizeof(reply),
358 console->records, count * sizeof(INPUT_RECORD) );
359 if (flush)
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)
366 INPUT_RECORD *new_rec = realloc( console->records,
367 console->recnum * sizeof(INPUT_RECORD) );
368 if (new_rec) console->records = new_rec;
370 else
372 free( console->records );
373 console->records = NULL;
376 release_object( console );
377 return count;
380 static void console_input_dump( struct object *obj, int verbose )
382 struct console_input *console = (struct console_input *)obj;
383 assert( obj->ops == &console_input_ops );
384 fprintf( stderr, "Console input fd=%d\n", console->select.fd );
387 static int console_input_add_queue( struct object *obj, struct wait_queue_entry *entry )
389 struct console_input *console = (struct console_input *)obj;
390 assert( obj->ops == &console_input_ops );
391 if (!obj->head) /* first on the queue */
392 set_select_events( &console->select, READ_EVENT );
393 add_queue( obj, entry );
394 return 1;
397 static void console_input_remove_queue( struct object *obj, struct wait_queue_entry *entry )
399 struct console_input *console = (struct console_input *)grab_object(obj);
400 assert( obj->ops == &console_input_ops );
402 remove_queue( obj, entry );
403 if (!obj->head) /* last on the queue is gone */
404 set_select_events( &console->select, 0 );
405 release_object( obj );
408 static int console_input_signaled( struct object *obj, struct thread *thread )
410 struct console_input *console = (struct console_input *)obj;
411 assert( obj->ops == &console_input_ops );
413 if (check_select_events( &console->select, READ_EVENT ))
415 /* stop waiting on select() if we are signaled */
416 set_select_events( &console->select, 0 );
417 return 1;
419 else
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;
427 static int console_input_get_read_fd( struct object *obj )
429 struct console_input *console = (struct console_input *)obj;
430 assert( obj->ops == &console_input_ops );
431 return dup( console->select.fd );
434 static int console_get_info( struct object *obj, struct get_file_info_reply *reply )
436 memset( reply, 0, sizeof(*reply) );
437 reply->type = FILE_TYPE_CHAR;
438 return 1;
441 static void console_input_destroy( struct object *obj )
443 struct console_input *console = (struct console_input *)obj;
444 assert( obj->ops == &console_input_ops );
445 unregister_select_user( &console->select );
446 close( console->select.fd );
447 if (console->output) console->output->input = NULL;
448 free( console );
451 static void screen_buffer_dump( struct object *obj, int verbose )
453 struct screen_buffer *console = (struct screen_buffer *)obj;
454 assert( obj->ops == &screen_buffer_ops );
455 fprintf( stderr, "Console screen buffer fd=%d\n", console->select.fd );
458 static int screen_buffer_add_queue( struct object *obj, struct wait_queue_entry *entry )
460 struct screen_buffer *console = (struct screen_buffer *)obj;
461 assert( obj->ops == &screen_buffer_ops );
462 if (!obj->head) /* first on the queue */
463 set_select_events( &console->select, WRITE_EVENT );
464 add_queue( obj, entry );
465 return 1;
468 static void screen_buffer_remove_queue( struct object *obj, struct wait_queue_entry *entry )
470 struct screen_buffer *console = (struct screen_buffer *)grab_object(obj);
471 assert( obj->ops == &screen_buffer_ops );
473 remove_queue( obj, entry );
474 if (!obj->head) /* last on the queue is gone */
475 set_select_events( &console->select, 0 );
476 release_object( obj );
479 static int screen_buffer_signaled( struct object *obj, struct thread *thread )
481 struct screen_buffer *console = (struct screen_buffer *)obj;
482 assert( obj->ops == &screen_buffer_ops );
484 if (check_select_events( &console->select, WRITE_EVENT ))
486 /* stop waiting on select() if we are signaled */
487 set_select_events( &console->select, 0 );
488 return 1;
490 else
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;
498 static int screen_buffer_get_write_fd( struct object *obj )
500 struct screen_buffer *console = (struct screen_buffer *)obj;
501 assert( obj->ops == &screen_buffer_ops );
502 return dup( console->select.fd );
505 static void screen_buffer_destroy( struct object *obj )
507 struct screen_buffer *console = (struct screen_buffer *)obj;
508 assert( obj->ops == &screen_buffer_ops );
509 unregister_select_user( &console->select );
510 close( console->select.fd );
511 if (console->input) console->input->output = NULL;
512 if (console->pid) kill( console->pid, SIGTERM );
513 if (console->title) free( console->title );
514 free( console );
517 /* allocate a console for the current process */
518 DECL_HANDLER(alloc_console)
520 struct alloc_console_reply reply = { -1, -1 };
522 if (!alloc_console( current->process )) goto done;
524 if ((reply.handle_in = alloc_handle( current->process, current->process->console_in,
525 req->access, req->inherit )) != -1)
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;
533 free_console( current->process );
535 done:
536 send_reply( current, -1, 1, &reply, sizeof(reply) );
539 /* free the console of the current process */
540 DECL_HANDLER(free_console)
542 free_console( current->process );
543 send_reply( current, -1, 0 );
546 /* open a handle to the process console */
547 DECL_HANDLER(open_console)
549 struct open_console_reply reply = { -1 };
550 struct object *obj= req->output ? current->process->console_out : current->process->console_in;
552 if (obj) reply.handle = alloc_handle( current->process, obj, req->access, req->inherit );
553 send_reply( current, -1, 1, &reply, sizeof(reply) );
556 /* set info about a console (output only) */
557 DECL_HANDLER(set_console_info)
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 );
566 /* get info about a console (output only) */
567 DECL_HANDLER(get_console_info)
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 );
576 /* set a console fd */
577 DECL_HANDLER(set_console_fd)
579 set_console_fd( req->handle, fd, req->pid );
580 send_reply( current, -1, 0 );
583 /* get a console mode (input or output) */
584 DECL_HANDLER(get_console_mode)
586 struct get_console_mode_reply reply;
587 get_console_mode( req->handle, &reply.mode );
588 send_reply( current, -1, 1, &reply, sizeof(reply) );
591 /* set a console mode (input or output) */
592 DECL_HANDLER(set_console_mode)
594 set_console_mode( req->handle, req->mode );
595 send_reply( current, -1, 0 );
598 /* add input records to a console input queue */
599 DECL_HANDLER(write_console_input)
601 struct write_console_input_reply reply;
602 INPUT_RECORD *records = (INPUT_RECORD *)data;
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) );
611 /* fetch input records from a console input queue */
612 DECL_HANDLER(read_console_input)
614 read_console_input( req->handle, req->count, req->flush );