From 94d1c5884949b21303e66b80c00c1690ec0d9d60 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Wed, 5 Jun 2002 01:52:29 +0000 Subject: 2002-06-05 Marcus Brinkmann * main.c: Include "vcons.h" instead "console.h". * focus.c: Likewise. * Makefile (LCLHDRS): Rename console.h to vcons.h. (SRCS): Rename console.c to vcons.c. --- console/ChangeLog | 5 + console/Makefile | 4 +- console/console.c | 514 ------------------------------------------------------ console/console.h | 98 ----------- console/focus.c | 2 +- console/main.c | 2 +- console/vcons.c | 514 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ console/vcons.h | 98 +++++++++++ 8 files changed, 621 insertions(+), 616 deletions(-) delete mode 100644 console/console.c delete mode 100644 console/console.h create mode 100644 console/vcons.c create mode 100644 console/vcons.h diff --git a/console/ChangeLog b/console/ChangeLog index a51a927b..513802c6 100644 --- a/console/ChangeLog +++ b/console/ChangeLog @@ -6,6 +6,11 @@ * console.c: Likewise. * Makefile (LCLHDRS): Rename input.h to input-drv.h. + * main.c: Include "vcons.h" instead "console.h". + * focus.c: Likewise. + * Makefile (LCLHDRS): Rename console.h to vcons.h. + (SRCS): Rename console.c to vcons.c. + 2002-06-04 Marcus Brinkmann * display.h: New file. diff --git a/console/Makefile b/console/Makefile index 7174787f..a5de1e49 100644 --- a/console/Makefile +++ b/console/Makefile @@ -22,8 +22,8 @@ dir := console makemode := server target = console -SRCS = main.c console.c focus.c vga-display.c vga.c dynafont.c bdf.c -LCLHDRS = focus.h input-drv.h console.h display-drv.h vga.h vga-hw.h dynafont.h bdf.h \ +SRCS = main.c vcons.c focus.c vga-display.c vga.c dynafont.c bdf.c +LCLHDRS = focus.h input-drv.h vcons.h display-drv.h vga.h vga-hw.h dynafont.h bdf.h \ mutations.h priv.h HURDLIBS = trivfs fshelp iohelp threads ports ihash shouldbeinlibc diff --git a/console/console.c b/console/console.c deleted file mode 100644 index cecdb5b4..00000000 --- a/console/console.c +++ /dev/null @@ -1,514 +0,0 @@ -/* console.c - The device independant part of a console. - Copyright (C) 2002 Free Software Foundation, Inc. - Written by Marcus Brinkmann. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ - -#include -#include -#include -#include - -#include "console.h" -#include "display-drv.h" -#include "input-drv.h" - - -struct vcons -{ - /* Protected by cons_list_lock. */ - vcons_t next; - vcons_t prev; - int refcnt; - - /* The following members remain constant over the lifetime of the - object and don't need to be locked. */ - cons_t cons; - int id; - void *display_console; - - struct mutex lock; - /* Indicates if OWNER_ID is initialized. */ - int has_owner; - /* Specifies the ID of the process that should receive the WINCH - signal for this virtual console. */ - int owner_id; - - /* The output queue holds the characters that are to be outputted. - The display driver might refuse to handle some incomplete - multi-byte or composed character at the end of the buffer, so we - have to keep them around. */ - struct mutex output_lock; - int output_stopped; - struct condition output_resumed; - char *output; - size_t output_allocated; - size_t output_size; - - struct mutex input_lock; - /* XXX input queue. */ - char *input; - size_t input_allocated; - size_t input_size; -}; - - -struct cons -{ - /* Protected by cons_list_lock. */ - cons_t prev; - cons_t next; - int refcnt; - vcons_t vcons_list; - size_t vcons_length; - vcons_t vcons_active; - - /* The following members are static and don't need to be locked. */ - char *name; - display_ops_t display_ops; -}; - - -/* The lock protects the console list, all virtual console lists of - all consoles, and their reference counters. */ -struct mutex cons_list_lock; -cons_t cons_list; -size_t cons_length; - - -struct mutex config_lock; -/* The default encoding. */ -const char *config_encoding; -display_ops_t config_display; - - -/* Lookup the console with name NAME, acquire a reference for it, and - return it in R_CONS. If NAME doesn't exist, return ESRCH. */ -error_t -cons_lookup (const char *name, cons_t *r_cons) -{ - cons_t cons; - - mutex_lock (&cons_list_lock); - cons = cons_list; - while (cons) - { - if (!strcmp (name, cons->name)) - { - cons->refcnt++; - mutex_unlock (&cons_list_lock); - *r_cons = cons; - return 0; - } - cons = cons->next; - } - mutex_unlock (&cons_list_lock); - return ESRCH; -} - - -/* Release a reference to CONS. */ -void -cons_release (cons_t cons) -{ - mutex_lock (&cons_list_lock); - cons->refcnt--; - mutex_unlock (&cons_list_lock); -} - - -/* Lookup the virtual console with number ID in the console CONS, - acquire a reference for it, and return it in R_VCONS. If CREATE is - true, the virtual console will be created if it doesn't exist yet. - If CREATE is true, and ID 0, the first free virtual console id is - used. */ -error_t -vcons_lookup (cons_t cons, int id, int create, vcons_t *r_vcons) -{ - error_t err; - vcons_t previous_cons = 0; - vcons_t vcons; - - if (!id && !create) - return EINVAL; - - mutex_lock (&cons_list_lock); - if (id) - { - if (cons->vcons_list && cons->vcons_list->id <= id) - { - previous_cons = cons->vcons_list; - while (previous_cons->next && previous_cons->next->id <= id) - previous_cons = previous_cons->next; - if (previous_cons->id == id) - { - previous_cons->refcnt++; - mutex_unlock (&cons_list_lock); - *r_vcons = previous_cons; - return 0; - } - } - else if (!create) - { - mutex_unlock (&cons_list_lock); - return ESRCH; - } - } - else - { - id = 1; - if (cons->vcons_list && cons->vcons_list->id == 1) - { - previous_cons = cons->vcons_list; - while (previous_cons && previous_cons->id == id) - { - id++; - previous_cons = previous_cons->next; - } - } - } - - vcons = calloc (1, sizeof (struct vcons)); - if (!vcons) - { - mutex_unlock (&cons_list_lock); - return ENOMEM; - } - mutex_init (&vcons->lock); - mutex_init (&vcons->output_lock); - condition_init (&vcons->output_resumed); - vcons->refcnt = 1; - err = (*(cons->display_ops->create)) (&vcons->display_console, - config_encoding); - if (err) - { - mutex_unlock (&cons_list_lock); - free (vcons); - return err; - } - /* XXX Set up keyboard input etc. */ - vcons->cons = cons; - cons->refcnt++; - cons->vcons_length++; - /* Insert the virtual console into the doubly linked list. */ - if (previous_cons) - { - vcons->prev = previous_cons; - if (previous_cons->next) - { - previous_cons->next->prev = vcons; - vcons->next = previous_cons->next; - } - previous_cons->next = vcons; - } - else - { - if (cons->vcons_list) - { - cons->vcons_list->prev = vcons; - vcons->next = cons->vcons_list; - } - cons->vcons_list = vcons; - } - mutex_unlock (&cons_list_lock); - *r_vcons = vcons; - return 0; -} - - -/* Release a reference to the virtual console VCONS. If this was the - last reference the virtual console is destroyed. */ -void -vcons_release (vcons_t vcons) -{ - mutex_lock (&cons_list_lock); - if (!--vcons->refcnt) - { - /* As we keep a reference for all input focus groups pointing to - the virtual console, and a reference for the active console, - we know that without references, this virtual console is - neither active nor used by any input group. */ - - (*vcons->cons->display_ops->destroy) (vcons->display_console); - /* XXX Destroy the rest of the state. */ - - if (vcons->prev) - vcons->prev->next = vcons->next; - else - vcons->cons->vcons_list = vcons->next; - if (vcons->next) - vcons->next->prev = vcons->prev; - - vcons->cons->vcons_length--; - vcons->cons->refcnt--; - free (vcons); - } - mutex_unlock (&cons_list_lock); -} - - -/* Activate virtual console VCONS for WHO. WHO is a unique identifier - for the entity requesting the activation (which can be used by the - display driver to group several activation requests together). */ -void -vcons_activate (vcons_t vcons, int who) -{ - mutex_lock (&cons_list_lock); - if (vcons->cons->vcons_active != vcons) - { - (*vcons->cons->display_ops->activate) (vcons->display_console, who); - vcons->cons->vcons_active->refcnt--; - vcons->refcnt++; - vcons->cons->vcons_active = vcons; - } - mutex_unlock (&cons_list_lock); -} - - -/* Resume the output on the virtual console VCONS. */ -void -vcons_start_output (vcons_t vcons) -{ - mutex_lock (&vcons->output_lock); - if (vcons->output_stopped) - { - vcons->output_stopped = 0; - condition_broadcast (&vcons->output_resumed); - } - mutex_unlock (&vcons->output_lock); -} - - -/* Stop all output on the virtual console VCONS. */ -void -vcons_stop_output (vcons_t vcons) -{ - mutex_lock (&vcons->output_lock); - vcons->output_stopped = 1; - mutex_unlock (&vcons->output_lock); -} - - -/* Return the number of pending output bytes for VCONS. */ -size_t -vcons_pending_output (vcons_t vcons) -{ - int output_size; - mutex_lock (&vcons->output_lock); - output_size = vcons->output_size; - mutex_unlock (&vcons->output_lock); - return output_size; -} - - -/* Fush the input buffer, discarding all pending data. */ -void -vcons_flush_input (vcons_t vcons) -{ - mutex_lock (&vcons->input_lock); - vcons->input_size = 0; - mutex_unlock (&vcons->input_lock); -} - - -/* Flush the output buffer, discarding all pending data. */ -void -vcons_discard_output (vcons_t vcons) -{ - mutex_lock (&vcons->output_lock); - vcons->output_size = 0; - mutex_unlock (&vcons->output_lock); -} - - -/* Output DATALEN characters from the buffer DATA on the virtual - console VCONS. The DATA must be supplied in the system encoding - configured for VCONS. The function returns the amount of bytes - written (might be smaller than DATALEN) or -1 and the error number - in errno. If NONBLOCK is not zero, return with -1 and set errno - to EWOULDBLOCK if operation would block for a long time. */ -ssize_t -vcons_output (vcons_t vcons, int nonblock, char *data, size_t datalen) -{ - error_t err; - char *output; - size_t output_size; - ssize_t amount; - - error_t ensure_output_buffer_size (size_t new_size) - { - /* Must be a power of two. */ -#define OUTPUT_ALLOCSIZE 32 - - if (vcons->output_allocated < new_size) - { - char *new_output; - new_size = (new_size + OUTPUT_ALLOCSIZE - 1) & ~(OUTPUT_ALLOCSIZE - 1); - new_output = realloc (vcons->output, new_size); - if (!new_output) - return ENOMEM; - vcons->output = new_output; - vcons->output_allocated = new_size; - } - return 0; - } - - mutex_lock (&vcons->output_lock); - while (vcons->output_stopped) - { - if (nonblock) - { - mutex_unlock (&vcons->output_lock); - errno = EWOULDBLOCK; - return -1; - } - if (hurd_condition_wait (&vcons->output_resumed, &vcons->output_lock)) - { - mutex_unlock (&vcons->output_lock); - errno = EINTR; - return -1; - } - } - - if (vcons->output_size) - { - err = ensure_output_buffer_size (vcons->output_size + datalen); - if (err) - { - mutex_unlock (&vcons->output_lock); - errno = ENOMEM; - return -1; - } - output = vcons->output; - output_size = vcons->output_size; - memcpy (output + output_size, data, datalen); - output_size += datalen; - } - else - { - output = data; - output_size = datalen; - } - amount = output_size; - err = (*vcons->cons->display_ops->output) (vcons->display_console, - &output, &output_size); - amount -= output_size; - - if (err && !amount) - { - mutex_unlock (&vcons->output_lock); - errno = err; - return err; - } - - /* XXX What should be done with invalid characters etc? */ - if (output_size) - { - /* If we used the caller's buffer DATA, the remaining bytes - might not fit in our internal output buffer. In this case we - can reallocate the buffer in VCONS without needing to update - OUTPUT (as it points into DATA). */ - err = ensure_output_buffer_size (output_size); - if (err) - { - mutex_unlock (&vcons->output_lock); - return err; - } - memmove (vcons->output, output, output_size); - } - vcons->output_size = output_size; - amount += output_size; - - mutex_unlock (&vcons->output_lock); - return amount; -} - - -/* Add DATALEN bytes starting from DATA to the input queue in - VCONS. */ -error_t -vcons_input (vcons_t vcons, char *data, size_t datalen) -{ - error_t err = 0; - - error_t ensure_input_buffer_size (size_t new_size) - { - /* Must be a power of two. */ -#define INPUT_ALLOCSIZE 32 - - if (vcons->input_allocated < new_size) - { - char *new_input; - new_size = (new_size + INPUT_ALLOCSIZE - 1) & ~(INPUT_ALLOCSIZE - 1); - new_input = realloc (vcons->input, new_size); - if (!new_input) - return ENOMEM; - vcons->input = new_input; - vcons->input_allocated = new_size; - } - return 0; - } - - mutex_lock (&vcons->input_lock); - err = ensure_input_buffer_size (vcons->input_size + datalen); - if (err) - { - mutex_unlock (&vcons->input_lock); - return err; - } - memcpy (vcons->input + vcons->input_size, data, datalen); - vcons->input_size += datalen; - mutex_unlock (&vcons->input_lock); - return 0; -} - - -/* Return the dimension of the virtual console VCONS in WINSIZE. */ -void -vcons_getsize (vcons_t vcons, struct winsize *size) -{ - (*vcons->cons->display_ops->getsize) (vcons->display_console, size); -} - - -/* Set the owner of the virtual console VCONS to PID. The owner - receives the SIGWINCH signal when the terminal size changes. */ -error_t -vcons_set_owner (vcons_t vcons, pid_t pid) -{ - mutex_lock (&vcons->lock); - vcons->has_owner = 1; - vcons->owner_id = pid; - mutex_unlock (&vcons->lock); - return 0; -} - - -/* Return the owner of the virtual console VCONS in PID. If there is - no owner, return ENOTTY. */ -error_t -vcons_get_owner (vcons_t vcons, pid_t *pid) -{ - error_t err = 0; - mutex_lock (&vcons->lock); - if (!vcons->has_owner) - err = ENOTTY; - else - *pid = vcons->owner_id; - mutex_unlock (&vcons->lock); - return err; -} diff --git a/console/console.h b/console/console.h deleted file mode 100644 index b768afa4..00000000 --- a/console/console.h +++ /dev/null @@ -1,98 +0,0 @@ -/* console.h - Interface for the device independant part of a virtual console. - Copyright (C) 2002 Free Software Foundation, Inc. - Written by Marcus Brinkmann. - - This file is part of the GNU Hurd. - - The GNU Hurd is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2, or (at - your option) any later version. - - The GNU Hurd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ - -#include -#include -#include -#include - - -/* A handle for a console device. */ -typedef struct cons *cons_t; - -/* A handle for a virtual console device. */ -typedef struct vcons *vcons_t; - - -/* Lookup the console with name NAME, acquire a reference for it, and - return it in R_CONS. If NAME doesn't exist, return ESRCH. */ -error_t cons_lookup (const char *name, cons_t *r_cons); - -/* Release a reference to CONS. */ -void cons_release (cons_t cons); - -/* Lookup the virtual console with number ID in the console CONS, - acquire a reference for it, and return it in R_VCONS. If CREATE is - true, the virtual console will be created if it doesn't exist yet. - If CREATE is true, and ID 0, the first free virtual console id is - used. */ -error_t vcons_lookup (cons_t cons, int id, int create, vcons_t *r_vcons); - -/* Release a reference to the virtual console VCONS. If this was the - last reference the virtual console is destroyed. */ -void vcons_release (vcons_t vcons); - - -/* Activate virtual console VCONS for WHO. WHO is a unique identifier - for the entity requesting the activation (which can be used by the - display driver to group several activation requests together). */ -void vcons_activate (vcons_t vcons, int who); - -/* Resume the output on the virtual console VCONS. */ -void vcons_start_output (vcons_t vcons); - -/* Stop all output on the virtual console VCONS. */ -void vcons_stop_output (vcons_t vcons); - -/* Return the number of pending output bytes for VCONS. */ -size_t vcons_pending_output (vcons_t vcons); - -/* Fush the input buffer, discarding all pending data. */ -void vcons_flush_input (vcons_t vcons); - -/* Fush the output buffer, discarding all pending data. */ -void vcons_discard_output (vcons_t vcons); - -/* Add DATALEN bytes starting from DATA to the input queue in - VCONS. */ -error_t vcons_input (vcons_t vcons, char *data, size_t datalen); - -/* Output DATALEN characters from the buffer DATA on the virtual - console VCONS. The DATA must be supplied in the system encoding - configured for VCONS. The function returns the amount of bytes - written (might be smaller than DATALEN) or -1 and the error number - in errno. If NONBLOCK is not zero, return with -1 and set errno - to EWOULDBLOCK if operation would block for a long time. */ -ssize_t vcons_output (vcons_t vcons, int nonblock, char *data, size_t datalen); - -/* Hang interruptible until one of the conditions in TYPE is - fulfilled. Return the conditions fulfilled in TYPE. */ -error_t vcons_select (vcons_t vcons, int *type); - -/* Return the dimension of the virtual console VCONS in WINSIZE. */ -void vcons_getsize (vcons_t vcons, struct winsize *winsize); - -/* Set the owner of the virtual console VCONS to PID. The owner - receives the SIGWINCH signal when the terminal size changes. */ -error_t vcons_set_owner (vcons_t vcons, pid_t pid); - -/* Return the owner of the virtual console VCONS in PID. If there is - no owner, return ENOTTY. */ -error_t vcons_get_owner (vcons_t vcons, pid_t *pid); diff --git a/console/focus.c b/console/focus.c index c9779af1..0e2fc1f4 100644 --- a/console/focus.c +++ b/console/focus.c @@ -2,7 +2,7 @@ #include #include -#include "console.h" +#include "vcons.h" #include "input-drv.h" #include "focus.h" diff --git a/console/main.c b/console/main.c index cd28bc96..9ea5ec11 100644 --- a/console/main.c +++ b/console/main.c @@ -31,7 +31,7 @@ #include "priv.h" #include "tioctl_S.h" -#include "console.h" +#include "vcons.h" #include "focus.h" diff --git a/console/vcons.c b/console/vcons.c new file mode 100644 index 00000000..2e755b2c --- /dev/null +++ b/console/vcons.c @@ -0,0 +1,514 @@ +/* vcons.c - The device independant part of a console. + Copyright (C) 2002 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include +#include +#include +#include + +#include "vcons.h" +#include "display-drv.h" +#include "input-drv.h" + + +struct vcons +{ + /* Protected by cons_list_lock. */ + vcons_t next; + vcons_t prev; + int refcnt; + + /* The following members remain constant over the lifetime of the + object and don't need to be locked. */ + cons_t cons; + int id; + void *display_console; + + struct mutex lock; + /* Indicates if OWNER_ID is initialized. */ + int has_owner; + /* Specifies the ID of the process that should receive the WINCH + signal for this virtual console. */ + int owner_id; + + /* The output queue holds the characters that are to be outputted. + The display driver might refuse to handle some incomplete + multi-byte or composed character at the end of the buffer, so we + have to keep them around. */ + struct mutex output_lock; + int output_stopped; + struct condition output_resumed; + char *output; + size_t output_allocated; + size_t output_size; + + struct mutex input_lock; + /* XXX input queue. */ + char *input; + size_t input_allocated; + size_t input_size; +}; + + +struct cons +{ + /* Protected by cons_list_lock. */ + cons_t prev; + cons_t next; + int refcnt; + vcons_t vcons_list; + size_t vcons_length; + vcons_t vcons_active; + + /* The following members are static and don't need to be locked. */ + char *name; + display_ops_t display_ops; +}; + + +/* The lock protects the console list, all virtual console lists of + all consoles, and their reference counters. */ +struct mutex cons_list_lock; +cons_t cons_list; +size_t cons_length; + + +struct mutex config_lock; +/* The default encoding. */ +const char *config_encoding; +display_ops_t config_display; + + +/* Lookup the console with name NAME, acquire a reference for it, and + return it in R_CONS. If NAME doesn't exist, return ESRCH. */ +error_t +cons_lookup (const char *name, cons_t *r_cons) +{ + cons_t cons; + + mutex_lock (&cons_list_lock); + cons = cons_list; + while (cons) + { + if (!strcmp (name, cons->name)) + { + cons->refcnt++; + mutex_unlock (&cons_list_lock); + *r_cons = cons; + return 0; + } + cons = cons->next; + } + mutex_unlock (&cons_list_lock); + return ESRCH; +} + + +/* Release a reference to CONS. */ +void +cons_release (cons_t cons) +{ + mutex_lock (&cons_list_lock); + cons->refcnt--; + mutex_unlock (&cons_list_lock); +} + + +/* Lookup the virtual console with number ID in the console CONS, + acquire a reference for it, and return it in R_VCONS. If CREATE is + true, the virtual console will be created if it doesn't exist yet. + If CREATE is true, and ID 0, the first free virtual console id is + used. */ +error_t +vcons_lookup (cons_t cons, int id, int create, vcons_t *r_vcons) +{ + error_t err; + vcons_t previous_cons = 0; + vcons_t vcons; + + if (!id && !create) + return EINVAL; + + mutex_lock (&cons_list_lock); + if (id) + { + if (cons->vcons_list && cons->vcons_list->id <= id) + { + previous_cons = cons->vcons_list; + while (previous_cons->next && previous_cons->next->id <= id) + previous_cons = previous_cons->next; + if (previous_cons->id == id) + { + previous_cons->refcnt++; + mutex_unlock (&cons_list_lock); + *r_vcons = previous_cons; + return 0; + } + } + else if (!create) + { + mutex_unlock (&cons_list_lock); + return ESRCH; + } + } + else + { + id = 1; + if (cons->vcons_list && cons->vcons_list->id == 1) + { + previous_cons = cons->vcons_list; + while (previous_cons && previous_cons->id == id) + { + id++; + previous_cons = previous_cons->next; + } + } + } + + vcons = calloc (1, sizeof (struct vcons)); + if (!vcons) + { + mutex_unlock (&cons_list_lock); + return ENOMEM; + } + mutex_init (&vcons->lock); + mutex_init (&vcons->output_lock); + condition_init (&vcons->output_resumed); + vcons->refcnt = 1; + err = (*(cons->display_ops->create)) (&vcons->display_console, + config_encoding); + if (err) + { + mutex_unlock (&cons_list_lock); + free (vcons); + return err; + } + /* XXX Set up keyboard input etc. */ + vcons->cons = cons; + cons->refcnt++; + cons->vcons_length++; + /* Insert the virtual console into the doubly linked list. */ + if (previous_cons) + { + vcons->prev = previous_cons; + if (previous_cons->next) + { + previous_cons->next->prev = vcons; + vcons->next = previous_cons->next; + } + previous_cons->next = vcons; + } + else + { + if (cons->vcons_list) + { + cons->vcons_list->prev = vcons; + vcons->next = cons->vcons_list; + } + cons->vcons_list = vcons; + } + mutex_unlock (&cons_list_lock); + *r_vcons = vcons; + return 0; +} + + +/* Release a reference to the virtual console VCONS. If this was the + last reference the virtual console is destroyed. */ +void +vcons_release (vcons_t vcons) +{ + mutex_lock (&cons_list_lock); + if (!--vcons->refcnt) + { + /* As we keep a reference for all input focus groups pointing to + the virtual console, and a reference for the active console, + we know that without references, this virtual console is + neither active nor used by any input group. */ + + (*vcons->cons->display_ops->destroy) (vcons->display_console); + /* XXX Destroy the rest of the state. */ + + if (vcons->prev) + vcons->prev->next = vcons->next; + else + vcons->cons->vcons_list = vcons->next; + if (vcons->next) + vcons->next->prev = vcons->prev; + + vcons->cons->vcons_length--; + vcons->cons->refcnt--; + free (vcons); + } + mutex_unlock (&cons_list_lock); +} + + +/* Activate virtual console VCONS for WHO. WHO is a unique identifier + for the entity requesting the activation (which can be used by the + display driver to group several activation requests together). */ +void +vcons_activate (vcons_t vcons, int who) +{ + mutex_lock (&cons_list_lock); + if (vcons->cons->vcons_active != vcons) + { + (*vcons->cons->display_ops->activate) (vcons->display_console, who); + vcons->cons->vcons_active->refcnt--; + vcons->refcnt++; + vcons->cons->vcons_active = vcons; + } + mutex_unlock (&cons_list_lock); +} + + +/* Resume the output on the virtual console VCONS. */ +void +vcons_start_output (vcons_t vcons) +{ + mutex_lock (&vcons->output_lock); + if (vcons->output_stopped) + { + vcons->output_stopped = 0; + condition_broadcast (&vcons->output_resumed); + } + mutex_unlock (&vcons->output_lock); +} + + +/* Stop all output on the virtual console VCONS. */ +void +vcons_stop_output (vcons_t vcons) +{ + mutex_lock (&vcons->output_lock); + vcons->output_stopped = 1; + mutex_unlock (&vcons->output_lock); +} + + +/* Return the number of pending output bytes for VCONS. */ +size_t +vcons_pending_output (vcons_t vcons) +{ + int output_size; + mutex_lock (&vcons->output_lock); + output_size = vcons->output_size; + mutex_unlock (&vcons->output_lock); + return output_size; +} + + +/* Fush the input buffer, discarding all pending data. */ +void +vcons_flush_input (vcons_t vcons) +{ + mutex_lock (&vcons->input_lock); + vcons->input_size = 0; + mutex_unlock (&vcons->input_lock); +} + + +/* Flush the output buffer, discarding all pending data. */ +void +vcons_discard_output (vcons_t vcons) +{ + mutex_lock (&vcons->output_lock); + vcons->output_size = 0; + mutex_unlock (&vcons->output_lock); +} + + +/* Output DATALEN characters from the buffer DATA on the virtual + console VCONS. The DATA must be supplied in the system encoding + configured for VCONS. The function returns the amount of bytes + written (might be smaller than DATALEN) or -1 and the error number + in errno. If NONBLOCK is not zero, return with -1 and set errno + to EWOULDBLOCK if operation would block for a long time. */ +ssize_t +vcons_output (vcons_t vcons, int nonblock, char *data, size_t datalen) +{ + error_t err; + char *output; + size_t output_size; + ssize_t amount; + + error_t ensure_output_buffer_size (size_t new_size) + { + /* Must be a power of two. */ +#define OUTPUT_ALLOCSIZE 32 + + if (vcons->output_allocated < new_size) + { + char *new_output; + new_size = (new_size + OUTPUT_ALLOCSIZE - 1) & ~(OUTPUT_ALLOCSIZE - 1); + new_output = realloc (vcons->output, new_size); + if (!new_output) + return ENOMEM; + vcons->output = new_output; + vcons->output_allocated = new_size; + } + return 0; + } + + mutex_lock (&vcons->output_lock); + while (vcons->output_stopped) + { + if (nonblock) + { + mutex_unlock (&vcons->output_lock); + errno = EWOULDBLOCK; + return -1; + } + if (hurd_condition_wait (&vcons->output_resumed, &vcons->output_lock)) + { + mutex_unlock (&vcons->output_lock); + errno = EINTR; + return -1; + } + } + + if (vcons->output_size) + { + err = ensure_output_buffer_size (vcons->output_size + datalen); + if (err) + { + mutex_unlock (&vcons->output_lock); + errno = ENOMEM; + return -1; + } + output = vcons->output; + output_size = vcons->output_size; + memcpy (output + output_size, data, datalen); + output_size += datalen; + } + else + { + output = data; + output_size = datalen; + } + amount = output_size; + err = (*vcons->cons->display_ops->output) (vcons->display_console, + &output, &output_size); + amount -= output_size; + + if (err && !amount) + { + mutex_unlock (&vcons->output_lock); + errno = err; + return err; + } + + /* XXX What should be done with invalid characters etc? */ + if (output_size) + { + /* If we used the caller's buffer DATA, the remaining bytes + might not fit in our internal output buffer. In this case we + can reallocate the buffer in VCONS without needing to update + OUTPUT (as it points into DATA). */ + err = ensure_output_buffer_size (output_size); + if (err) + { + mutex_unlock (&vcons->output_lock); + return err; + } + memmove (vcons->output, output, output_size); + } + vcons->output_size = output_size; + amount += output_size; + + mutex_unlock (&vcons->output_lock); + return amount; +} + + +/* Add DATALEN bytes starting from DATA to the input queue in + VCONS. */ +error_t +vcons_input (vcons_t vcons, char *data, size_t datalen) +{ + error_t err = 0; + + error_t ensure_input_buffer_size (size_t new_size) + { + /* Must be a power of two. */ +#define INPUT_ALLOCSIZE 32 + + if (vcons->input_allocated < new_size) + { + char *new_input; + new_size = (new_size + INPUT_ALLOCSIZE - 1) & ~(INPUT_ALLOCSIZE - 1); + new_input = realloc (vcons->input, new_size); + if (!new_input) + return ENOMEM; + vcons->input = new_input; + vcons->input_allocated = new_size; + } + return 0; + } + + mutex_lock (&vcons->input_lock); + err = ensure_input_buffer_size (vcons->input_size + datalen); + if (err) + { + mutex_unlock (&vcons->input_lock); + return err; + } + memcpy (vcons->input + vcons->input_size, data, datalen); + vcons->input_size += datalen; + mutex_unlock (&vcons->input_lock); + return 0; +} + + +/* Return the dimension of the virtual console VCONS in WINSIZE. */ +void +vcons_getsize (vcons_t vcons, struct winsize *size) +{ + (*vcons->cons->display_ops->getsize) (vcons->display_console, size); +} + + +/* Set the owner of the virtual console VCONS to PID. The owner + receives the SIGWINCH signal when the terminal size changes. */ +error_t +vcons_set_owner (vcons_t vcons, pid_t pid) +{ + mutex_lock (&vcons->lock); + vcons->has_owner = 1; + vcons->owner_id = pid; + mutex_unlock (&vcons->lock); + return 0; +} + + +/* Return the owner of the virtual console VCONS in PID. If there is + no owner, return ENOTTY. */ +error_t +vcons_get_owner (vcons_t vcons, pid_t *pid) +{ + error_t err = 0; + mutex_lock (&vcons->lock); + if (!vcons->has_owner) + err = ENOTTY; + else + *pid = vcons->owner_id; + mutex_unlock (&vcons->lock); + return err; +} diff --git a/console/vcons.h b/console/vcons.h new file mode 100644 index 00000000..06c611da --- /dev/null +++ b/console/vcons.h @@ -0,0 +1,98 @@ +/* vcons.h - Interface for the device independant part of a virtual console. + Copyright (C) 2002 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ + +#include +#include +#include +#include + + +/* A handle for a console device. */ +typedef struct cons *cons_t; + +/* A handle for a virtual console device. */ +typedef struct vcons *vcons_t; + + +/* Lookup the console with name NAME, acquire a reference for it, and + return it in R_CONS. If NAME doesn't exist, return ESRCH. */ +error_t cons_lookup (const char *name, cons_t *r_cons); + +/* Release a reference to CONS. */ +void cons_release (cons_t cons); + +/* Lookup the virtual console with number ID in the console CONS, + acquire a reference for it, and return it in R_VCONS. If CREATE is + true, the virtual console will be created if it doesn't exist yet. + If CREATE is true, and ID 0, the first free virtual console id is + used. */ +error_t vcons_lookup (cons_t cons, int id, int create, vcons_t *r_vcons); + +/* Release a reference to the virtual console VCONS. If this was the + last reference the virtual console is destroyed. */ +void vcons_release (vcons_t vcons); + + +/* Activate virtual console VCONS for WHO. WHO is a unique identifier + for the entity requesting the activation (which can be used by the + display driver to group several activation requests together). */ +void vcons_activate (vcons_t vcons, int who); + +/* Resume the output on the virtual console VCONS. */ +void vcons_start_output (vcons_t vcons); + +/* Stop all output on the virtual console VCONS. */ +void vcons_stop_output (vcons_t vcons); + +/* Return the number of pending output bytes for VCONS. */ +size_t vcons_pending_output (vcons_t vcons); + +/* Fush the input buffer, discarding all pending data. */ +void vcons_flush_input (vcons_t vcons); + +/* Fush the output buffer, discarding all pending data. */ +void vcons_discard_output (vcons_t vcons); + +/* Add DATALEN bytes starting from DATA to the input queue in + VCONS. */ +error_t vcons_input (vcons_t vcons, char *data, size_t datalen); + +/* Output DATALEN characters from the buffer DATA on the virtual + console VCONS. The DATA must be supplied in the system encoding + configured for VCONS. The function returns the amount of bytes + written (might be smaller than DATALEN) or -1 and the error number + in errno. If NONBLOCK is not zero, return with -1 and set errno + to EWOULDBLOCK if operation would block for a long time. */ +ssize_t vcons_output (vcons_t vcons, int nonblock, char *data, size_t datalen); + +/* Hang interruptible until one of the conditions in TYPE is + fulfilled. Return the conditions fulfilled in TYPE. */ +error_t vcons_select (vcons_t vcons, int *type); + +/* Return the dimension of the virtual console VCONS in WINSIZE. */ +void vcons_getsize (vcons_t vcons, struct winsize *winsize); + +/* Set the owner of the virtual console VCONS to PID. The owner + receives the SIGWINCH signal when the terminal size changes. */ +error_t vcons_set_owner (vcons_t vcons, pid_t pid); + +/* Return the owner of the virtual console VCONS in PID. If there is + no owner, return ENOTTY. */ +error_t vcons_get_owner (vcons_t vcons, pid_t *pid); -- cgit v1.2.3