Added DebugBreak.
[wine] / server / console.c
1 /*
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>
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>
22
23 #include "winerror.h"
24 #include "winnt.h"
25 #include "wincon.h"
26
27 #include "handle.h"
28 #include "process.h"
29 #include "thread.h"
30
31 struct screen_buffer;
32
33 struct console_input
34 {
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 */
41 };
42
43 struct screen_buffer
44 {
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 */
53 };
54
55
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 );
62
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 );
69
70 /* common routine */
71 static int console_get_info( struct object *obj, struct get_file_info_reply *reply );
72
73 static 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,
79     no_satisfied,
80     console_input_get_read_fd,
81     no_write_fd,
82     no_flush,
83     console_get_info,
84     console_input_destroy
85 };
86
87 static 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
99 };
100
101
102 static int create_console( int fd, struct object *obj[2] )
103 {
104     struct console_input *console_input;
105     struct screen_buffer *screen_buffer;
106     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     }
113     if ((write_fd = (fd != -1) ? dup(fd) : dup(1)) == -1)
114     {
115         file_set_error();
116         close( read_fd );
117         return 0;
118     }
119     if (!(console_input = mem_alloc( sizeof(struct console_input) )))
120     {
121         close( read_fd );
122         close( write_fd );
123         return 0;
124     }
125     if (!(screen_buffer = mem_alloc( sizeof(struct screen_buffer) )))
126     {
127         close( read_fd );
128         close( write_fd );
129         free( console_input );
130         return 0;
131     }
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;
157 }
158
159 /* allocate a console for this process */
160 int 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 */
175 int 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
183 static int set_console_fd( int handle, int fd, int pid )
184 {
185     struct console_input *input;
186     struct screen_buffer *output;
187     struct object *obj;
188     int fd_in, fd_out;
189
190     if (!(obj = get_handle_obj( current->process, handle, 0, NULL )))
191         return 0;
192     if (obj->ops == &console_input_ops)
193     {
194         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 );
208         return 0;
209     }
210
211     /* can't change the fd if someone is waiting on it */
212     assert( !input->obj.head );
213     assert( !output->obj.head );
214
215     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     }
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;
242 }
243
244 static int get_console_mode( int handle, int *mode )
245 {
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
266 static int set_console_mode( int handle, int mode )
267 {
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) */
289 static int set_console_info( int handle, struct set_console_info_request *req, const char *title )
290 {
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     }
305     release_object( console );
306     return 1;
307 }
308
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 )
311 {
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;
322 }
323
324 /* add input events to a console input queue */
325 static int write_console_input( int handle, int count, INPUT_RECORD *records )
326 {
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 */
348 static int read_console_input( int handle, int count, int flush )
349 {
350     struct console_input *console;
351     struct read_console_input_reply reply;
352
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)
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
380 static void console_input_dump( struct object *obj, int verbose )
381 {
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 );
385 }
386
387 static 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 );
391     if (!obj->head)  /* first on the queue */
392         set_select_events( &console->select, READ_EVENT );
393     add_queue( obj, entry );
394     return 1;
395 }
396
397 static void console_input_remove_queue( struct object *obj, struct wait_queue_entry *entry )
398 {
399     struct console_input *console = (struct console_input *)grab_object(obj);
400     assert( obj->ops == &console_input_ops );
401
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 );
406 }
407
408 static int console_input_signaled( struct object *obj, struct thread *thread )
409 {
410     struct console_input *console = (struct console_input *)obj;
411     assert( obj->ops == &console_input_ops );
412
413     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     }
425 }
426
427 static int console_input_get_read_fd( struct object *obj )
428 {
429     struct console_input *console = (struct console_input *)obj;
430     assert( obj->ops == &console_input_ops );
431     return dup( console->select.fd );
432 }
433
434 static 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
441 static void console_input_destroy( struct object *obj )
442 {
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 );
449 }
450
451 static 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 );
455     fprintf( stderr, "Console screen buffer fd=%d\n", console->select.fd );
456 }
457
458 static 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 */
463         set_select_events( &console->select, WRITE_EVENT );
464     add_queue( obj, entry );
465     return 1;
466 }
467
468 static 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 */
475         set_select_events( &console->select, 0 );
476     release_object( obj );
477 }
478
479 static int screen_buffer_signaled( struct object *obj, struct thread *thread )
480 {
481     struct screen_buffer *console = (struct screen_buffer *)obj;
482     assert( obj->ops == &screen_buffer_ops );
483
484     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     }
496 }
497
498 static 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 );
502     return dup( console->select.fd );
503 }
504
505 static void screen_buffer_destroy( struct object *obj )
506 {
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 );
515 }
516
517 /* allocate a console for the current process */
518 DECL_HANDLER(alloc_console)
519 {
520     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) );
537 }
538
539 /* free the console of the current process */
540 DECL_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 */
547 DECL_HANDLER(open_console)
548 {
549     struct open_console_reply reply = { -1 };
550     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 );
553     send_reply( current, -1, 1, &reply, sizeof(reply) );
554 }
555
556 /* set info about a console (output only) */
557 DECL_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) */
567 DECL_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 */
577 DECL_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) */
584 DECL_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) */
592 DECL_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 */
599 DECL_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 */
612 DECL_HANDLER(read_console_input)
613 {
614     read_console_input( req->handle, req->count, req->flush );
615 }