summaryrefslogtreecommitdiff
path: root/console
diff options
context:
space:
mode:
authorMarcus Brinkmann <marcus@gnu.org>2002-06-12 14:38:39 +0000
committerMarcus Brinkmann <marcus@gnu.org>2002-06-12 14:38:39 +0000
commit693eb63d90f9036680e538bc84275a32f707f926 (patch)
treee4f6e1890526dee1e6a40c824dc1725480979479 /console
parent609a7d4a162f97ff3ea6d59cb7326fbaaa960fd4 (diff)
2002-06-12 Marcus Brinkmann <marcus@gnu.org>
* console.c: Include <argz.h>. Do not include "console.h", but inline it. New macro DEFAULT_ENCODING. (struct cons): De-const-ify member ENCODING. (mycons, cons): Remove global variables. (vcons_lookup): Use default encoding if CONS->encoding is not set. (new_node): Access CONS through VCONS. Adjust size of display node. (netfs_attempt_read): Truncate length to read before reading. (netfs_S_io_map): New function. (options): New global variable. (parse_opt): New function. (netfs_append_args): New function. (main): New variable CONS to hold console structure. Rediddle initialization to allocate memory for it, parse arguments, and create the root node in correct order. Also call display_init. * console.h: Rewritten with new meaning. It now describes the public interface of the console. * display.c: Include <assert.h>, <error.h>, <hurd.h>, <hurd/pager.h> and "console.h". (struct screen): Removed. (struct cursor): Remove members X, Y and status. (struct user_pager_info): New struct. (struct display): Remove member SCREEN, add new members USER, UPI, MEMOBJ and MEMOBJ_SIZE. (pager_bucket): New global variable. (display_get_filemap): New function. (pager_clear_user_data): Likewise. (pager_read_page): Likewise. (pager_write_page): Likewise. (pager_unlock_page): Likewise. (pager_report_extent): Likewise. (pager_dropweak): Likewise. (service_paging_requests): Likewise. (screen_init): Renamed to ... (user_create): ... this new function and changed to allocate memory object and map it for USER data in display structure. (screen_deinit): Renamed to ... (user_destroy): ... this new function and rewrote it. (MATRIX_POS): New macro. (screen_fill): Take DISPLAY argument instead SCREEN. Use MATRIX_POS. (screen_scroll_up): Likewise. (screen_scroll_down): Likewise. (screen_scroll_left): Likewise. (screen_scroll_right): Likewise. (handle_esc_bracket_hl): Take DISPLAY argument instead CURSOR. (handle_esc_bracket): Access screen and cursor fields correctly. (display_output_one): Likewise. (display_getsize): Likewise. (display_init): New function. (display_create): New variables width, height, lines. Call user_create, not screen_init. Call user_destroy, not screen_deinit. (display_destroy): Call user_destroy, not screen_deinit. (display_read): Reimplement using memory mapping. * display.h: New prototypes for display_init and display_get_filemap.
Diffstat (limited to 'console')
-rw-r--r--console/ChangeLog60
-rw-r--r--console/console.c213
-rw-r--r--console/console.h57
-rw-r--r--console/display.c515
-rw-r--r--console/display.h4
5 files changed, 601 insertions, 248 deletions
diff --git a/console/ChangeLog b/console/ChangeLog
index 332a70ba..53fa34a8 100644
--- a/console/ChangeLog
+++ b/console/ChangeLog
@@ -1,3 +1,63 @@
+2002-06-12 Marcus Brinkmann <marcus@gnu.org>
+
+ * console.c: Include <argz.h>. Do not include "console.h", but
+ inline it. New macro DEFAULT_ENCODING.
+ (struct cons): De-const-ify member ENCODING.
+ (mycons, cons): Remove global variables.
+ (vcons_lookup): Use default encoding if CONS->encoding is not set.
+ (new_node): Access CONS through VCONS. Adjust size of display
+ node.
+ (netfs_attempt_read): Truncate length to read before reading.
+ (netfs_S_io_map): New function.
+ (options): New global variable.
+ (parse_opt): New function.
+ (netfs_append_args): New function.
+ (main): New variable CONS to hold console structure. Rediddle
+ initialization to allocate memory for it, parse arguments, and
+ create the root node in correct order. Also call display_init.
+ * console.h: Rewritten with new meaning. It now describes the
+ public interface of the console.
+ * display.c: Include <assert.h>, <error.h>, <hurd.h>,
+ <hurd/pager.h> and "console.h".
+ (struct screen): Removed.
+ (struct cursor): Remove members X, Y and status.
+ (struct user_pager_info): New struct.
+ (struct display): Remove member SCREEN, add new members USER, UPI,
+ MEMOBJ and MEMOBJ_SIZE.
+ (pager_bucket): New global variable.
+ (display_get_filemap): New function.
+ (pager_clear_user_data): Likewise.
+ (pager_read_page): Likewise.
+ (pager_write_page): Likewise.
+ (pager_unlock_page): Likewise.
+ (pager_report_extent): Likewise.
+ (pager_dropweak): Likewise.
+ (service_paging_requests): Likewise.
+ (screen_init): Renamed to ...
+ (user_create): ... this new function and changed to allocate
+ memory object and map it for USER data in display structure.
+ (screen_deinit): Renamed to ...
+ (user_destroy): ... this new function and rewrote it.
+ (MATRIX_POS): New macro.
+ (screen_fill): Take DISPLAY argument instead SCREEN. Use
+ MATRIX_POS.
+ (screen_scroll_up): Likewise.
+ (screen_scroll_down): Likewise.
+ (screen_scroll_left): Likewise.
+ (screen_scroll_right): Likewise.
+ (handle_esc_bracket_hl): Take DISPLAY argument instead CURSOR.
+ (handle_esc_bracket): Access screen and cursor fields correctly.
+ (display_output_one): Likewise.
+ (display_getsize): Likewise.
+ (display_init): New function.
+ (display_create): New variables width, height, lines. Call
+ user_create, not screen_init. Call user_destroy, not
+ screen_deinit.
+ (display_destroy): Call user_destroy, not
+ screen_deinit.
+ (display_read): Reimplement using memory mapping.
+ * display.h: New prototypes for display_init and display_get_filemap.
+
2002-06-09 Marcus Brinkmann <marcus@gnu.org>
* display.c (struct cursor): Change type of all members from int
diff --git a/console/console.c b/console/console.c
index c0dbf4f5..3c1c5ce2 100644
--- a/console/console.c
+++ b/console/console.c
@@ -16,25 +16,27 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include <hurd/netfs.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <unistd.h>
#include <argp.h>
+#include <argz.h>
#include <error.h>
#include <string.h>
#include <fcntl.h>
#include <dirent.h>
#include <sys/mman.h>
#include <sys/stat.h>
+#include <rwlock.h>
+#include <maptime.h>
#include <cthreads.h>
-#include <mcheck.h>
#include <version.h>
-#include "console.h"
+#include <hurd/netfs.h>
+
#include "display.h"
#include "input.h"
@@ -44,6 +46,11 @@ char *netfs_server_name = "console";
char *netfs_server_version = HURD_VERSION;
int netfs_maxsymlinks = 16; /* Arbitrary. */
+/* Handy source of time. */
+volatile struct mapped_time_value *console_maptime;
+
+#define DEFAULT_ENCODING "ISO-8859-1"
+
struct vcons
{
@@ -68,24 +75,28 @@ struct vcons
struct node *disp_node;
struct node *inpt_node;
};
+/* A handle for a virtual console device. */
+typedef struct vcons *vcons_t;
struct cons
{
/* The lock protects the console, all virtual consoles contained in
- it and the reference counters. It also locks the
- configuration. */
+ it and the reference counters. It also locks the configuration
+ parameters. */
struct mutex lock;
vcons_t vcons_list;
/* The encoding. */
- const char *encoding;
+ char *encoding;
struct node *node;
mach_port_t underlying;
/* A template for the stat information of all nodes. */
struct stat stat_template;
-} mycons;
-cons_t cons = &mycons;
+};
+/* A handle for a console device. */
+typedef struct cons *cons_t;
+
/* 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.
@@ -150,7 +161,7 @@ vcons_lookup (cons_t cons, int id, int create, vcons_t *r_vcons)
/* XXX Error checking. */
mutex_init (&vcons->lock);
- err = display_create (&vcons->display, cons->encoding);
+ err = display_create (&vcons->display, cons->encoding ?: DEFAULT_ENCODING);
if (err)
{
free (vcons->name);
@@ -159,7 +170,7 @@ vcons_lookup (cons_t cons, int id, int create, vcons_t *r_vcons)
return err;
}
- err = input_create (&vcons->input, cons->encoding);
+ err = input_create (&vcons->input, cons->encoding ?: DEFAULT_ENCODING);
if (err)
{
display_destroy (vcons->display);
@@ -268,7 +279,7 @@ new_node (struct node **np, vcons_t vcons, vcons_node_type type)
free (nn);
return ENOMEM;
}
- (*np)->nn_stat = cons->stat_template;
+ (*np)->nn_stat = vcons->cons->stat_template;
(*np)->nn_translated = 0;
switch (type)
@@ -288,7 +299,7 @@ new_node (struct node **np, vcons_t vcons, vcons_node_type type)
(*np)->nn_stat.st_ino = (vcons->id << 2) + 2;
(*np)->nn_stat.st_mode |= S_IFREG;
(*np)->nn_stat.st_mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH);
- (*np)->nn_stat.st_size = 2008 * sizeof (wchar_t); /* XXX */
+ (*np)->nn_stat.st_size = 2011 * sizeof (wchar_t); /* XXX */
break;
case VCONS_NODE_INPUT:
(*np)->nn_stat.st_ino = (vcons->id << 2) + 3;
@@ -300,14 +311,14 @@ new_node (struct node **np, vcons_t vcons, vcons_node_type type)
/* If the underlying node isn't a directory, propagate read permission to
execute permission since we need that for lookups. */
- if (! S_ISDIR (cons->stat_template.st_mode)
+ if (! S_ISDIR (vcons->cons->stat_template.st_mode)
&& S_ISDIR ((*np)->nn_stat.st_mode))
{
- if (cons->stat_template.st_mode & S_IRUSR)
+ if (vcons->cons->stat_template.st_mode & S_IRUSR)
(*np)->nn_stat.st_mode |= S_IXUSR;
- if (cons->stat_template.st_mode & S_IRGRP)
+ if (vcons->cons->stat_template.st_mode & S_IRGRP)
(*np)->nn_stat.st_mode |= S_IXGRP;
- if (cons->stat_template.st_mode & S_IROTH)
+ if (vcons->cons->stat_template.st_mode & S_IROTH)
(*np)->nn_stat.st_mode |= S_IXOTH;
}
@@ -1037,11 +1048,14 @@ netfs_attempt_read (struct iouser *cred, struct node *np,
else
{
/* Pass display content to caller. */
- ssize_t amt;
+ ssize_t amt = *len;
assert (np == vcons->disp_node);
- amt = display_read (vcons->display,
- /* cred->po->openstat & O_NONBLOCK */ 0,
- offset, data, *len);
+
+ if (amt > np->nn_stat.st_size)
+ amt = np->nn_stat.st_size;
+ amt = display_read (vcons->display,
+ /* cred->po->openstat & O_NONBLOCK */ 0,
+ offset, data, amt);
if (amt == -1)
err = errno;
else
@@ -1094,44 +1108,175 @@ netfs_attempt_write (struct iouser *cred, struct node *np,
}
+/* Implement io_map as described in <hurd/io.defs>. */
+kern_return_t
+netfs_S_io_map (struct protid *cred,
+ memory_object_t *rdobj,
+ mach_msg_type_name_t *rdtype,
+ memory_object_t *wrobj,
+ mach_msg_type_name_t *wrtype)
+{
+ int flags;
+ struct node *np;
+ vcons_t vcons;
+
+ if (!cred)
+ return EOPNOTSUPP;
+
+ np = cred->po->np;
+ vcons = np->nn->vcons;
+ if (!vcons || np != vcons->disp_node)
+ return EOPNOTSUPP;
+
+ *wrobj = *rdobj = MACH_PORT_NULL;
+
+ flags = cred->po->openstat & (O_READ | O_WRITE);
+
+ mutex_lock (&np->lock);
+ switch (flags)
+ {
+ case O_READ | O_WRITE:
+ *wrobj = *rdobj = display_get_filemap (vcons->display,
+ VM_PROT_READ | VM_PROT_WRITE);
+ if (*wrobj == MACH_PORT_NULL)
+ goto error;
+ mach_port_mod_refs (mach_task_self (), *rdobj, MACH_PORT_RIGHT_SEND, 1);
+ break;
+ case O_READ:
+ *rdobj = display_get_filemap (vcons->display, VM_PROT_READ);
+ if (*rdobj == MACH_PORT_NULL)
+ goto error;
+ break;
+ case O_WRITE:
+ *wrobj = display_get_filemap (vcons->display, VM_PROT_WRITE);
+ if (*wrobj == MACH_PORT_NULL)
+ goto error;
+ break;
+ }
+ mutex_unlock (&np->lock);
+
+ *rdtype = MACH_MSG_TYPE_MOVE_SEND;
+ *wrtype = MACH_MSG_TYPE_MOVE_SEND;
+
+ return 0;
+
+ error:
+ mutex_unlock (&np->lock);
+ return errno;
+}
+
+
+static const struct argp_option options[] =
+{
+ {"encoding", 'e', "NAME", 0, "Set encoding of virtual consoles to"
+ " NAME (default `" DEFAULT_ENCODING "')" },
+ {0}
+};
+
+static error_t
+parse_opt (int opt, char *arg, struct argp_state *state)
+{
+ cons_t cons = state->input;
+
+ switch (opt)
+ {
+ default:
+ return ARGP_ERR_UNKNOWN;
+ case ARGP_KEY_SUCCESS:
+ case ARGP_KEY_ERROR:
+ break;
+
+ case ARGP_KEY_INIT:
+ mutex_lock (&cons->lock);
+ break;
+
+ case ARGP_KEY_FINI:
+ mutex_unlock (&cons->lock);
+ break;
+
+ case 'e':
+ /* XXX Check validity of encoding. Can we perform all necessary
+ conversions? */
+ {
+ char *new = strdup (arg);
+ if (!new)
+ return ENOMEM;
+ if (cons->encoding)
+ free (cons->encoding);
+ cons->encoding = new;
+ }
+ break;
+ }
+ return 0;
+}
+
+/* Return an argz string describing the current options. Fill *ARGZ
+ with a pointer to newly malloced storage holding the list and *LEN
+ to the length of that storage. */
+error_t
+netfs_append_args (char **argz, size_t *argz_len)
+{
+ error_t err = 0;
+ cons_t cons = netfs_root_node->nn->cons;
+
+ if (cons->encoding && strcmp (cons->encoding, DEFAULT_ENCODING))
+ {
+ char *buf;
+ asprintf (&buf, "--encoding=%s", cons->encoding);
+ if (buf)
+ err = argz_add (argz, argz_len, buf);
+ else
+ err = errno;
+ }
+ return err;
+}
+
+
int
main (int argc, char **argv)
{
error_t err;
mach_port_t bootstrap;
struct stat ul_stat;
- struct netnode root_nn = { cons: cons, vcons: 0 };
+ cons_t cons;
+ struct netnode root_nn = { vcons: 0 };
+ struct argp argp = { options, parse_opt, NULL,
+ "A translator that provides virtual consoles." };
- mtrace();
- struct argp argp
- = { NULL, NULL, NULL,
- "A translator that provides virtual console displays." };
+ cons = malloc (sizeof (struct cons));
+ if (!malloc)
+ error (1, ENOMEM, "Cannot create console structure");
+ mutex_init (&cons->lock);
+ cons->encoding = NULL;
+ cons->vcons_list = NULL;
+ root_nn.cons = cons;
/* Parse our command line arguments (all none of them). */
- argp_parse (&argp, argc, argv, 0, 0, 0);
+ argp_parse (&argp, argc, argv, 0, 0, cons);
task_get_bootstrap_port (mach_task_self (), &bootstrap);
+
netfs_init ();
+ display_init ();
+
/* Create the root node (some attributes initialized below). */
netfs_root_node = netfs_make_node (&root_nn);
if (! netfs_root_node)
- error (5, ENOMEM, "Cannot create root node");
+ error (2, ENOMEM, "Cannot create root node");
err = maptime_map (0, 0, &console_maptime);
if (err)
- error (6, err, "Cannot map time");
+ error (3, err, "Cannot map time");
- mutex_init (&cons->lock);
- cons->encoding = "ISO-8859-1";
cons->node = netfs_root_node;
cons->underlying = netfs_startup (bootstrap, O_READ);
if (cons->underlying == MACH_PORT_NULL)
- error (5, err, "Cannot get underlying node");
+ error (4, err, "Cannot get underlying node");
err = io_stat (cons->underlying, &ul_stat);
if (err)
- error (6, err, "Cannot stat underlying node");
+ error (5, err, "Cannot stat underlying node");
/* CONS.stat_template contains some fields that are inherited by all
nodes we create. */
@@ -1164,8 +1309,8 @@ main (int argc, char **argv)
fshelp_touch (&netfs_root_node->nn_stat, TOUCH_ATIME|TOUCH_MTIME|TOUCH_CTIME,
console_maptime);
- netfs_server_loop (); /* Never returns. */
-
+ netfs_server_loop ();
+
/*NOTREACHED*/
return 0;
}
diff --git a/console/console.h b/console/console.h
index 3642bfe4..27996955 100644
--- a/console/console.h
+++ b/console/console.h
@@ -1,4 +1,4 @@
-/* console.h -- Interfaces for the console server.
+/* console.h -- Public interface to the console server.
Copyright (C) 2002 Free Software Foundation, Inc.
Written by Marcus Brinkmann.
@@ -16,20 +16,51 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#ifndef CONSOLE_H
-#define CONSOLE_H
+#ifndef _HURD_CONSOLE_H
+#define _HURD_CONSOLE_H
-#include <hurd/netfs.h>
-#include <rwlock.h>
-#include <maptime.h>
+#include <sys/types.h>
-/* Handy source of time. */
-volatile struct mapped_time_value *console_maptime;
+struct cons_display
+{
+#define CONS_MAGIC 0x48555244 /* Hex for "HURD". */
+ u_int32_t magic; /* CONS_MAGIC, use to detect
+ endianess. */
+#define CONS_VERSION_MAJ 0x0
+#define CONS_VERSION_MAJ_SHIFT 16
+#define CONS_VERSION_AGE 0x0
+ u_int32_t version; /* Version of interface. Lower 16
+ bits define the age, upper 16 bits
+ the major version. */
+ struct
+ {
+ u_int32_t width; /* Width of screen matrix. */
+ u_int32_t lines; /* Length of whole matrix. */
+ u_int32_t cur_line; /* Beginning of visible area. */
+ u_int32_t scr_lines;/* Number of lines in scrollback buffer
+ preceeding CUR_LINE. */
+ u_int32_t height; /* Number of lines in visible area following
+ (and including) CUR_LINE. */
+ u_int32_t matrix; /* Index (in wchar_t) of the beginning of
+ screen matrix in this structure. */
+ } screen;
-/* A handle for a console device. */
-typedef struct cons *cons_t;
+ struct
+ {
+ u_int32_t col; /* Current column (x-position) of cursor. */
+ u_int32_t row; /* Current row (y-position) of cursor. */
-/* A handle for a virtual console device. */
-typedef struct vcons *vcons_t;
+#define CONS_CURSOR_INVISIBLE 0
+#define CONS_CURSOR_NORMAL 1
+#define CONS_CURSOR_VERY_VISIBLE 2
+ u_int32_t status; /* Visibility status of cursor. */
+ } cursor;
-#endif /* CONSOLE_H */
+ /* Don't use this, use ((wchar_t *) cons_display +
+ cons_display.screen.matrix) instead. This will make your client
+ upward compatible with future versions of this interface. */
+ wchar_t _matrix[0];
+};
+
+
+#endif /* _HURD_CONSOLE_H */
diff --git a/console/display.c b/console/display.c
index 0fffba24..9c33b933 100644
--- a/console/display.c
+++ b/console/display.c
@@ -25,47 +25,27 @@
#include <iconv.h>
#include <argp.h>
#include <string.h>
+#include <assert.h>
+#include <error.h>
#include <sys/io.h>
-#include <sys/mman.h>
#include <sys/fcntl.h>
+#include <sys/mman.h>
#include <cthreads.h>
+#include <hurd.h>
+#include <hurd/pager.h>
+
#ifndef __STDC_ISO_10646__
#error It is required that wchar_t is UCS-4.
#endif
+#include "console.h"
#include "display.h"
-struct screen
-{
- /* A screen matrix, including the scroll back buffer. */
- wchar_t *matrix;
-
- /* The size of the screen, in lines. */
- int lines;
-
- /* The top most line of the screen in the video buffer. */
- int current_line;
-
- /* Maximum number of lines scrolled back. */
- int scrolling_max;
-
- int width;
- int height;
-};
-typedef struct screen *screen_t;
-
struct cursor
{
- /* The visibility of the cursor. */
- u_int32_t status;
-#define CURSOR_INVISIBLE 1
-#define CURSOR_STANDOUT 2
-
- u_int32_t x;
- u_int32_t y;
u_int32_t saved_x;
u_int32_t saved_y;
};
@@ -128,107 +108,251 @@ struct attr
};
typedef struct attr *attr_t;
+struct user_pager_info
+{
+ display_t display;
+ struct pager *p;
+};
+
struct display
{
/* The lock for the virtual console display structure. */
struct mutex lock;
- struct screen screen;
- struct cursor cursor;
- struct output output;
- struct attr attr;
-
/* 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;
+
+ struct cursor cursor;
+ struct output output;
+ struct attr attr;
+ struct cons_display *user;
+
+ struct user_pager_info *upi;
+ memory_object_t memobj;
+ size_t memobj_size;
};
+
+/* We need a separate bucket for the pager ports. */
+struct port_bucket *pager_bucket;
+
+mach_port_t
+display_get_filemap (display_t display, vm_prot_t prot)
+{
+ error_t err;
+
+ /* Add a reference for each call, the caller will deallocate it. */
+ err = mach_port_mod_refs (mach_task_self (), display->memobj,
+ MACH_PORT_RIGHT_SEND, +1);
+ assert_perror (err);
+
+ return display->memobj;
+}
+
+/* Implement the pager_clear_user_data callback from the pager library. */
+void
+pager_clear_user_data (struct user_pager_info *upi)
+{
+ free (upi);
+}
+
+/* XXX This is not good enough. We actually need to provide a backing
+ store. */
+error_t
+pager_read_page (struct user_pager_info *pager, vm_offset_t page,
+ vm_address_t *buf, int *writelock)
+{
+ /* This is a read-only medium */
+ *writelock = 1;
+
+ *buf = (vm_address_t) mmap (0, vm_page_size, PROT_READ|PROT_WRITE,
+ MAP_ANON, 0, 0);
+ return 0;
+}
+error_t
+pager_write_page (struct user_pager_info *pager,
+ vm_offset_t page,
+ vm_address_t buf)
+{
+ /* XXX Implement me. */
+ assert (0);
+}
+
+error_t
+pager_unlock_page (struct user_pager_info *pager,
+ vm_offset_t address)
+{
+ return 0;
+}
+
+/* Tell how big the file is. */
+error_t
+pager_report_extent (struct user_pager_info *upi,
+ vm_address_t *offset,
+ vm_size_t *size)
+{
+ display_t display = upi->display;
+ *offset = 0;
+ *size = display->memobj_size;
+ return 0;
+}
+
+void
+pager_dropweak (struct user_pager_info *upi)
+{
+}
+
+/* A top-level function for the paging thread that just services paging
+ requests. */
+static void
+service_paging_requests (any_t arg)
+{
+ struct port_bucket *pager_bucket = arg;
+ for (;;)
+ ports_manage_port_operations_multithread (pager_bucket,
+ pager_demuxer,
+ 1000 * 60 * 2,
+ 1000 * 60 * 10, 0);
+}
+
+
static error_t
-screen_init (screen_t screen)
+user_create (display_t display, u_int32_t width, u_int32_t height,
+ u_int32_t lines)
{
- screen->width = 80;
- screen->height = 25;
- screen->lines = 25; /* XXX For now. */
- screen->current_line = 0;
- screen->matrix = calloc (screen->lines * screen->width, sizeof (wchar_t));
- if (!screen->matrix)
- return ENOMEM;
+ error_t err;
+ struct cons_display *user;
+ display->memobj_size = round_page (sizeof (struct cons_display) +
+ sizeof (u_int32_t) * width * lines);
+
+ display->upi = malloc (sizeof (struct user_pager_info));
+ if (!display->upi)
+ return MACH_PORT_NULL;
+ display->upi->display = display;
+ /* 1 & MOCD correct? */
+ display->upi->p = pager_create (display->upi, pager_bucket,
+ 1, MEMORY_OBJECT_COPY_DELAY);
+ if (display->upi->p == 0)
+ {
+ free (display->upi);
+ return errno;
+ }
+ display->memobj = pager_get_port (display->upi->p);
+ ports_port_deref (display->upi->p);
+
+ mach_port_insert_right (mach_task_self (), display->memobj, display->memobj,
+ MACH_MSG_TYPE_MAKE_SEND);
+
+ err = vm_map (mach_task_self (),
+ (vm_address_t *) &user, (vm_size_t) display->memobj_size,
+ (vm_address_t) 0,
+ 1 /* ! (flags & MAP_FIXED) */,
+ display->memobj, 0 /* (vm_offset_t) offset */,
+ 0 /* ! (flags & MAP_SHARED) */,
+ VM_PROT_READ | VM_PROT_WRITE,
+ VM_PROT_READ | VM_PROT_WRITE,
+ VM_INHERIT_NONE);
+ if (err)
+ {
+ /* UPI will be cleaned up by libpager. */
+ mach_port_deallocate (mach_task_self (), display->memobj);
+ return err;
+ }
+
+ user->magic = CONS_MAGIC;
+ user->version = CONS_VERSION_MAJ << 16 | CONS_VERSION_AGE;
+ user->screen.width = width;
+ user->screen.height = height;
+ user->screen.lines = lines;
+ user->screen.cur_line = 0;
+ user->screen.scr_lines = 0;
+ user->screen.matrix = sizeof (struct cons_display) / sizeof (u_int32_t);
+ user->cursor.col = 0;
+ user->cursor.row = 0;
+ user->cursor.status = CONS_CURSOR_NORMAL;
+ wmemset (user->_matrix, L' ', user->screen.width * user->screen.lines);
- wmemset (screen->matrix, L' ', screen->height * screen->width);
/* XXX Set attribute flags. */
+ display->user = user;
return 0;
}
static void
-screen_deinit (screen_t screen)
+user_destroy (display_t display)
{
- free (screen->matrix);
+ /* The pager will be deallocated by libpager. */
+ mach_port_deallocate (mach_task_self (), display->memobj);
}
+
+#define MATRIX_POS(user,x,y) ((user)->_matrix \
+ + (((user)->screen.cur_line + (y)) % (user)->screen.height) \
+ * (user)->screen.width + (x))
+
static void
-screen_fill (screen_t screen, size_t x, size_t y, size_t w, size_t h,
+screen_fill (display_t display, size_t x, size_t y, size_t w, size_t h,
wchar_t chr, char attr)
{
- wchar_t *matrixp = screen->matrix
- + ((screen->current_line + y) % screen->height) * screen->width + x;
+ struct cons_display *user = display->user;
+ wchar_t *matrixp = MATRIX_POS (user, x, y);
while (h--)
{
/* XXX Set attribute flags. */
wmemset (matrixp, L' ', w);
- matrixp += screen->width;
+ matrixp += user->screen.width;
}
- /* XXX Flag screen change, but here? */
+ /* XXX Flag screen change, but here or where else? */
}
static void
-screen_scroll_up (screen_t screen, size_t x, size_t y, size_t w, size_t h,
+screen_scroll_up (display_t display, size_t x, size_t y, size_t w, size_t h,
int amt, wchar_t chr, char attr)
{
- wchar_t *matrixp = screen->matrix
- + ((screen->current_line + y) % screen->height) * screen->width + x;
+ struct cons_display *user = display->user;
+ wchar_t *matrixp = MATRIX_POS (user, x, y);
if (amt < 0)
return;
while (h-- > amt)
{
- wmemcpy (matrixp, matrixp + amt * screen->width, w);
- matrixp += screen->width;
+ wmemcpy (matrixp, matrixp + amt * user->screen.width, w);
+ matrixp += user->screen.width;
}
- screen_fill (screen, x, y, w, h, chr, attr);
+ screen_fill (display, x, y, w, h, chr, attr);
}
static void
-screen_scroll_down (screen_t screen, size_t x, size_t y, size_t w, size_t h,
+screen_scroll_down (display_t display, size_t x, size_t y, size_t w, size_t h,
int amt, wchar_t chr, char attr)
{
- wchar_t *matrixp = screen->matrix
- + ((screen->current_line + y + h - 1) % screen->height)
- * screen->width + x;
+ struct cons_display *user = display->user;
+ wchar_t *matrixp = MATRIX_POS (user, x, y + h - 1);
if (amt < 0)
return;
while (h-- > amt)
{
- wmemcpy (matrixp, matrixp - amt * screen->width, w);
- matrixp -= screen->width;
+ wmemcpy (matrixp, matrixp - amt * user->screen.width, w);
+ matrixp -= user->screen.width;
}
- screen_fill (screen, x, y, w, h, chr, attr);
+ screen_fill (display, x, y, w, h, chr, attr);
}
static void
-screen_scroll_left (screen_t screen, size_t x, size_t y, size_t w, size_t h,
+screen_scroll_left (display_t display, size_t x, size_t y, size_t w, size_t h,
int amt, wchar_t chr, char attr)
{
+ struct cons_display *user = display->user;
+ wchar_t *matrixp = MATRIX_POS (user, x, y);
int i;
- wchar_t *matrixp = screen->matrix
- + ((screen->current_line + y) % screen->height) * screen->width + x;
if (amt < 0)
return;
@@ -238,18 +362,18 @@ screen_scroll_left (screen_t screen, size_t x, size_t y, size_t w, size_t h,
for (i = 0; i < y + h; i++)
{
wmemmove (matrixp, matrixp + amt, w - amt);
- matrixp += screen->width;
+ matrixp += user->screen.width;
}
- screen_fill (screen, x + w - amt, y, amt, h, chr, attr);
+ screen_fill (display, x + w - amt, y, amt, h, chr, attr);
}
static void
-screen_scroll_right (screen_t screen, size_t x, size_t y, size_t w, size_t h,
+screen_scroll_right (display_t display, size_t x, size_t y, size_t w, size_t h,
int amt, wchar_t chr, char attr)
{
+ struct cons_display *user = display->user;
+ wchar_t *matrixp = MATRIX_POS (user, x, y);
int i;
- wchar_t *matrixp = screen->matrix
- + ((screen->current_line + y) % screen->height) * screen->width + x;
if (amt < 0)
return;
@@ -259,9 +383,9 @@ screen_scroll_right (screen_t screen, size_t x, size_t y, size_t w, size_t h,
for (i = 0; i < y + h; i++)
{
wmemmove (matrixp + amt, matrixp, w - amt);
- matrixp += screen->width;
+ matrixp += user->screen.width;
}
- screen_fill (screen, x, y, amt, h, chr, attr);
+ screen_fill (display, x, y, amt, h, chr, attr);
}
@@ -289,16 +413,16 @@ output_deinit (output_t output)
static void
-handle_esc_bracket_hl (cursor_t cursor, int code, int flag)
+handle_esc_bracket_hl (display_t display, int code, int flag)
{
switch (code)
{
case 34:
/* Cursor standout: <cnorm>, <cvvis>. */
if (flag)
- cursor->status |= CURSOR_STANDOUT;
+ display->user->cursor.status = CONS_CURSOR_VERY_VISIBLE;
else
- cursor->status &= ~CURSOR_STANDOUT;
+ display->user->cursor.status = CONS_CURSOR_NORMAL;
/* XXX Flag cursor status change. */
break;
}
@@ -390,20 +514,21 @@ handle_esc_bracket_m (attr_t attr, int code)
static void
handle_esc_bracket (display_t display, char op)
{
+ struct cons_display *user = display->user;
parse_t parse = &display->output.parse;
int i;
static void limit_cursor (void)
{
- if (display->cursor.x >= display->screen.width)
- display->cursor.x = display->screen.width - 1;
- else if (display->cursor.x < 0)
- display->cursor.x = 0;
+ if (user->cursor.col >= user->screen.width)
+ user->cursor.col = user->screen.width - 1;
+ else if (user->cursor.col < 0)
+ user->cursor.col = 0;
- if (display->cursor.y >= display->screen.height)
- display->cursor.y = display->screen.height - 1;
- else if (display->cursor.y < 0)
- display->cursor.y = 0;
+ if (user->cursor.row >= user->screen.height)
+ user->cursor.row = user->screen.height - 1;
+ else if (user->cursor.row < 0)
+ user->cursor.row = 0;
/* XXX Flag cursor change. */
}
@@ -413,64 +538,64 @@ handle_esc_bracket (display_t display, char op)
case 'H':
case 'f':
/* Cursor position: <cup>. */
- display->cursor.x = parse->params[1] - 1;
- display->cursor.y = parse->params[0] - 1;
+ user->cursor.col = parse->params[1] - 1;
+ user->cursor.row = parse->params[0] - 1;
limit_cursor ();
break;
case 'G':
/* Horizontal position: <hpa>. */
- display->cursor.x = parse->params[0] - 1;
+ user->cursor.col = parse->params[0] - 1;
limit_cursor ();
break;
case 'F':
/* Beginning of previous line. */
- display->cursor.x = 0;
+ user->cursor.col = 0;
/* fall through */
case 'A':
/* Cursor up: <cuu>, <cuu1>. */
- display->cursor.y -= (parse->params[0] ?: 1);
+ user->cursor.row -= (parse->params[0] ?: 1);
limit_cursor ();
break;
case 'E':
/* Beginning of next line. */
- display->cursor.x = 0;
+ user->cursor.col = 0;
/* Fall through. */
case 'B':
/* Cursor down: <cud1>, <cud>. */
- display->cursor.y += (parse->params[0] ?: 1);
+ user->cursor.row += (parse->params[0] ?: 1);
limit_cursor ();
break;
case 'C':
/* Cursor right: <cuf1>, <cuf>. */
- display->cursor.x += (parse->params[0] ?: 1);
+ user->cursor.col += (parse->params[0] ?: 1);
limit_cursor ();
break;
case 'D':
/* Cursor left: <cub>, <cub1>. */
- display->cursor.x -= (parse->params[0] ?: 1);
+ user->cursor.col -= (parse->params[0] ?: 1);
limit_cursor ();
break;
case 's':
/* Save cursor position: <sc>. */
- display->cursor.saved_x = display->cursor.x;
- display->cursor.saved_y = display->cursor.y;
+ display->cursor.saved_x = user->cursor.col;
+ display->cursor.saved_y = user->cursor.row;
break;
case 'u':
/* Restore cursor position: <rc>. */
- display->cursor.x = display->cursor.saved_x;
- display->cursor.y = display->cursor.saved_y;
+ user->cursor.col = display->cursor.saved_x;
+ user->cursor.row = display->cursor.saved_y;
/* In case the screen was larger before: */
limit_cursor ();
break;
case 'h':
/* Reset mode. */
for (i = 0; i < parse->nparams; i++)
- handle_esc_bracket_hl (&display->cursor, parse->params[i], 0);
+ handle_esc_bracket_hl (display, parse->params[i], 0);
break;
case 'l':
/* Set mode. */
for (i = 0; i < parse->nparams; i++)
- handle_esc_bracket_hl (&display->cursor, parse->params[i], 1);
+ handle_esc_bracket_hl (display, parse->params[i], 1);
break;
case 'm':
for (i = 0; i < parse->nparams; i++)
@@ -481,27 +606,27 @@ handle_esc_bracket (display_t display, char op)
{
case 0:
/* Clear to end of screen: <ed>. */
- screen_fill (&display->screen, display->cursor.x, display->cursor.y,
- display->screen.width - display->cursor.x, 1, L' ',
+ screen_fill (display, user->cursor.col, user->cursor.row,
+ user->screen.width - user->cursor.col, 1, L' ',
display->attr.current);
- screen_fill (&display->screen, 0, display->cursor.y + 1,
- display->screen.width,
- display->screen.height - display->cursor.y,
+ screen_fill (display, 0, user->cursor.row + 1,
+ user->screen.width,
+ user->screen.height - user->cursor.row,
L' ', display->attr.current);
break;
case 1:
/* Clear to beginning of screen. */
- screen_fill (&display->screen, 0, 0,
- display->screen.width, display->cursor.y,
+ screen_fill (display, 0, 0,
+ user->screen.width, user->cursor.row,
L' ', display->attr.current);
- screen_fill (&display->screen, 0, display->cursor.y,
- display->cursor.x + 1, 1,
+ screen_fill (display, 0, user->cursor.row,
+ user->cursor.col + 1, 1,
L' ', display->attr.current);
break;
case 2:
/* Clear entire screen. */
- screen_fill (&display->screen, 0, 0,
- display->screen.width, display->screen.height,
+ screen_fill (display, 0, 0,
+ user->screen.width, user->screen.height,
L' ', display->attr.current);
break;
}
@@ -511,73 +636,73 @@ handle_esc_bracket (display_t display, char op)
{
case 0:
/* Clear to end of line: <el>. */
- screen_fill (&display->screen, display->cursor.x, display->cursor.y,
- display->screen.width - display->cursor.x, 1,
+ screen_fill (display, user->cursor.col, user->cursor.row,
+ user->screen.width - user->cursor.col, 1,
L' ', display->attr.current);
break;
case 1:
/* Clear to beginning of line: <el1>. */
- screen_fill (&display->screen, 0, display->cursor.y,
- display->cursor.x + 1, 1,
+ screen_fill (display, 0, user->cursor.row,
+ user->cursor.col + 1, 1,
L' ', display->attr.current);
break;
case 2:
/* Clear entire line. */
- screen_fill (&display->screen, 0, display->cursor.y,
- display->screen.width, 1,
+ screen_fill (display, 0, user->cursor.row,
+ user->screen.width, 1,
L' ', display->attr.current);
break;
}
break;
case 'L':
/* Insert line(s): <il1>, <il>. */
- screen_scroll_down (&display->screen, 0, display->cursor.y,
- display->screen.width,
- display->screen.height - display->cursor.y,
+ screen_scroll_down (display, 0, user->cursor.row,
+ user->screen.width,
+ user->screen.height - user->cursor.row,
parse->params[0] ?: 1,
L' ', display->attr.current);
break;
case 'M':
/* Delete line(s): <dl1>, <dl>. */
- screen_scroll_up (&display->screen, 0, display->cursor.y,
- display->screen.width,
- display->screen.height - display->cursor.y,
+ screen_scroll_up (display, 0, user->cursor.row,
+ user->screen.width,
+ user->screen.height - user->cursor.row,
parse->params[0] ?: 1,
L' ', display->attr.current);
break;
case '@':
/* Insert character(s): <ich1>, <ich>. */
- screen_scroll_right (&display->screen, display->cursor.x,
- display->cursor.y,
- display->screen.width - display->cursor.x, 1,
+ screen_scroll_right (display, user->cursor.col,
+ user->cursor.row,
+ user->screen.width - user->cursor.col, 1,
parse->params[0] ?: 1,
L' ', display->attr.current);
break;
case 'P':
/* Delete character(s): <dch1>, <dch>. */
- screen_scroll_left (&display->screen, display->cursor.x,
- display->cursor.y,
- display->screen.width - display->cursor.x, 1,
+ screen_scroll_left (display, user->cursor.col,
+ user->cursor.row,
+ user->screen.width - user->cursor.col, 1,
parse->params[0] ?: 1,
L' ', display->attr.current);
break;
case 'S':
/* Scroll up: <ind>, <indn>. */
- screen_scroll_up (&display->screen, 0, 0,
- display->screen.width, display->screen.height,
+ screen_scroll_up (display, 0, 0,
+ user->screen.width, user->screen.height,
parse->params[0] ?: 1,
L' ', display->attr.current);
break;
case 'T':
/* Scroll down: <ri>, <rin>. */
- screen_scroll_down (&display->screen, 0, 0,
- display->screen.width, display->screen.height,
+ screen_scroll_down (display, 0, 0,
+ user->screen.width, user->screen.height,
parse->params[0] ?: 1,
L' ', display->attr.current);
break;
case 'X':
/* Erase character(s): <ech>. */
- screen_fill (&display->screen, display->cursor.x, display->cursor.y,
+ screen_fill (display, user->cursor.col, user->cursor.row,
parse->params[0] ?: 1, 1,
L' ', display->attr.current);
break;
@@ -592,9 +717,9 @@ handle_esc_bracket_question_hl (display_t display, int code, int flag)
case 25:
/* Cursor invisibility: <civis>, <cnorm>. */
if (flag)
- display->cursor.status |= CURSOR_INVISIBLE;
+ display->user->cursor.status = CONS_CURSOR_INVISIBLE;
else
- display->cursor.status &= ~CURSOR_INVISIBLE;
+ display->user->cursor.status = CONS_CURSOR_NORMAL;
/* XXX Flag cursor status change. */
break;
}
@@ -626,26 +751,27 @@ handle_esc_bracket_question (display_t display, char op)
static void
display_output_one (display_t display, wchar_t chr)
{
+ struct cons_display *user = display->user;
parse_t parse = &display->output.parse;
void newline (void)
{
- if (display->cursor.y < display->screen.height - 1)
+ if (user->cursor.row < user->screen.height - 1)
{
- display->cursor.y++;
+ user->cursor.row++;
/* XXX Flag cursor update. */
}
else
{
- display->screen.current_line++;
- display->screen.current_line %= display->screen.lines;
+ user->screen.cur_line++;
+ user->screen.cur_line %= user->screen.lines;
/* XXX Set attribute flags. */
- screen_fill (&display->screen, 0, display->screen.height - 1,
- display->screen.width, 1, L' ', display->screen.width);
- if (display->screen.scrolling_max <
- display->screen.lines - display->screen.height)
- display->screen.scrolling_max++;
+ screen_fill (display, 0, user->screen.height - 1,
+ user->screen.width, 1, L' ', user->screen.width);
+ if (user->screen.scr_lines <
+ user->screen.lines - user->screen.height)
+ user->screen.scr_lines++;
/* XXX Flag current line change. */
/* XXX Flag change of last line. */
/* XXX Possibly flag change of length of scroll back buffer. */
@@ -659,9 +785,9 @@ display_output_one (display_t display, wchar_t chr)
{
case L'\r':
/* Carriage return: <cr>. */
- if (display->cursor.x)
+ if (user->cursor.col)
{
- display->cursor.x = 0;
+ user->cursor.col = 0;
/* XXX Flag cursor update. */
}
break;
@@ -671,26 +797,26 @@ display_output_one (display_t display, wchar_t chr)
break;
case L'\b':
/* Cursor backward: <cub1>. */
- if (display->cursor.x > 0 || display->cursor.y > 0)
+ if (user->cursor.col > 0 || user->cursor.row > 0)
{
- if (display->cursor.x > 0)
- display->cursor.x--;
+ if (user->cursor.col > 0)
+ user->cursor.col--;
else
{
/* XXX This implements the <bw> functionality.
The alternative is to cut off and set x to 0. */
- display->cursor.x = display->screen.width - 1;
- display->cursor.y--;
+ user->cursor.col = user->screen.width - 1;
+ user->cursor.row--;
}
/* XXX Flag cursor update. */
}
break;
case L'\t':
/* Horizontal tab: <ht> */
- display->cursor.x = (display->cursor.x | 7) + 1;
- if (display->cursor.x >= display->screen.width)
+ user->cursor.col = (user->cursor.col | 7) + 1;
+ if (user->cursor.col >= user->screen.width)
{
- display->cursor.x = 0;
+ user->cursor.col = 0;
newline ();
}
/* XXX Flag cursor update. */
@@ -703,17 +829,17 @@ display_output_one (display_t display, wchar_t chr)
break;
default:
{
- int line = (display->screen.current_line + display->cursor.y)
- % display->screen.lines;
+ int line = (user->screen.cur_line + user->cursor.row)
+ % user->screen.lines;
/* XXX Set attribute flags. */
- display->screen.matrix[line * display->screen.width
- + display->cursor.x] = chr;
+ user->_matrix[line * user->screen.width
+ + user->cursor.col] = chr;
- display->cursor.x++;
- if (display->cursor.x == display->screen.width)
+ user->cursor.col++;
+ if (user->cursor.col == user->screen.width)
{
- display->cursor.x = 0;
+ user->cursor.col = 0;
newline ();
}
}
@@ -729,10 +855,10 @@ display_output_one (display_t display, wchar_t chr)
break;
case L'c':
/* Clear screen and home cursor: <clear>. */
- screen_fill (&display->screen, 0, 0,
- display->screen.width, display->screen.height,
+ screen_fill (display, 0, 0,
+ user->screen.width, user->screen.height,
L' ', display->attr.current);
- display->cursor.x = display->cursor.y = 0;
+ user->cursor.col = user->cursor.row = 0;
/* XXX Flag cursor change. */
parse->state = STATE_NORMAL;
break;
@@ -818,6 +944,19 @@ display_output_some (display_t display, char **buffer, size_t *length)
return err;
}
+void
+display_init (void)
+{
+ /* Create the pager bucket, and start to serve paging requests. */
+ pager_bucket = ports_create_bucket ();
+ if (! pager_bucket)
+ error (5, errno, "Cannot create pager bucket");
+
+ /* Make a thread to service paging requests. */
+ cthread_detach (cthread_fork ((cthread_fn_t) service_paging_requests,
+ (any_t)pager_bucket));
+}
+
/* Create a new virtual console display, with the system encoding
being ENCODING. */
error_t
@@ -825,6 +964,9 @@ display_create (display_t *r_display, const char *encoding)
{
error_t err = 0;
display_t display;
+ int width = 80;
+ int height = 25;
+ int lines = 25; /* XXX For now. */
*r_display = NULL;
display = calloc (1, sizeof *display);
@@ -832,7 +974,7 @@ display_create (display_t *r_display, const char *encoding)
return ENOMEM;
mutex_init (&display->lock);
- err = screen_init (&display->screen);
+ err = user_create (display, width, height, lines);
if (err)
{
free (display);
@@ -842,7 +984,7 @@ display_create (display_t *r_display, const char *encoding)
err = output_init (&display->output, encoding);
if (err)
{
- screen_deinit (&display->screen);
+ user_destroy (display);
free (display);
}
*r_display = display;
@@ -855,7 +997,7 @@ void
display_destroy (display_t display)
{
output_deinit (&display->output);
- screen_deinit (&display->screen);
+ user_destroy (display);
free (display);
}
@@ -865,8 +1007,8 @@ void
display_getsize (display_t display, struct winsize *winsize)
{
mutex_lock (&display->lock);
- winsize->ws_row = display->screen.height;
- winsize->ws_col = display->screen.width;
+ winsize->ws_row = display->user->screen.height;
+ winsize->ws_col = display->user->screen.width;
winsize->ws_xpixel = 0;
winsize->ws_ypixel = 0;
mutex_unlock (&display->lock);
@@ -1003,43 +1145,14 @@ display_output (display_t display, int nonblock, char *data, size_t datalen)
return amount;
}
-ssize_t display_read (display_t display, int nonblock, off_t off,
- char *data, size_t len)
+ssize_t
+display_read (display_t display, int nonblock, off_t off,
+ char *data, size_t len)
{
- u_int32_t metadata[8];
- size_t metadatalen = sizeof (metadata);
- ssize_t written = 0;
-
mutex_lock (&display->lock);
- metadata[0] = display->screen.width;
- metadata[1] = display->screen.height;
- metadata[2] = display->screen.lines;
- metadata[3] = display->screen.current_line;
- metadata[4] = display->screen.scrolling_max;
- metadata[5] = display->cursor.x;
- metadata[6] = display->cursor.y;
- metadata[7] = display->cursor.status;
-
- if (off >= 0 && off < metadatalen)
- {
- int part_len = len;
-
- if (part_len > metadatalen)
- part_len = metadatalen;
- memcpy (data, (char *) metadata + off, part_len);
- data += part_len;
- len -= part_len;
- written += part_len;
- }
- off -= metadatalen;
- if (off < 0)
- off = 0;
-
- if (off + len > 2000 * sizeof(wchar_t))
- len = 2000 * sizeof(wchar_t) - off;
- memcpy (data, (char *) display->screen.matrix + off, len);
+ memcpy (data, ((char *) display->user) + off, len);
mutex_unlock (&display->lock);
- return written + len;
+ return len;
}
/* Resume the output on the display DISPLAY. */
diff --git a/console/display.h b/console/display.h
index 6762e1b7..c48aec99 100644
--- a/console/display.h
+++ b/console/display.h
@@ -26,6 +26,8 @@
struct display;
typedef struct display *display_t;
+void display_init (void);
+
/* Create a new virtual console display, with the system encoding
being ENCODING. */
error_t display_create (display_t *r_display, const char *encoding);
@@ -53,6 +55,8 @@ error_t display_get_owner (display_t display, pid_t *pid);
ssize_t display_output (display_t display, int nonblock, char *data,
size_t datalen);
+mach_port_t display_get_filemap (display_t display, vm_prot_t prot);
+
ssize_t display_read (display_t display, int nonblock, off_t off,
char *data, size_t len);