diff options
author | Marcus Brinkmann <marcus@gnu.org> | 2002-06-12 14:38:39 +0000 |
---|---|---|
committer | Marcus Brinkmann <marcus@gnu.org> | 2002-06-12 14:38:39 +0000 |
commit | 693eb63d90f9036680e538bc84275a32f707f926 (patch) | |
tree | e4f6e1890526dee1e6a40c824dc1725480979479 /console/console.c | |
parent | 609a7d4a162f97ff3ea6d59cb7326fbaaa960fd4 (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/console.c')
-rw-r--r-- | console/console.c | 213 |
1 files changed, 179 insertions, 34 deletions
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; } |