From 693eb63d90f9036680e538bc84275a32f707f926 Mon Sep 17 00:00:00 2001 From: Marcus Brinkmann Date: Wed, 12 Jun 2002 14:38:39 +0000 Subject: 2002-06-12 Marcus Brinkmann * console.c: Include . 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 , , , 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. --- console/console.c | 213 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 179 insertions(+), 34 deletions(-) (limited to 'console/console.c') 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 #include #include #include #include #include +#include #include #include #include #include #include #include +#include +#include #include -#include #include -#include "console.h" +#include + #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 @@ -1093,6 +1107,130 @@ netfs_attempt_write (struct iouser *cred, struct node *np, return err; } + +/* Implement io_map as described in . */ +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) @@ -1100,38 +1238,45 @@ 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; } -- cgit v1.2.3