diff options
Diffstat (limited to 'debian')
-rw-r--r-- | debian/changelog | 18 | ||||
-rw-r--r-- | debian/control | 2 | ||||
-rw-r--r-- | debian/hurd.install | 2 | ||||
-rw-r--r-- | debian/hurd.postinst | 14 | ||||
-rw-r--r-- | debian/local/rc | 137 | ||||
-rw-r--r-- | debian/patches/console_repeater.patch | 2557 | ||||
-rw-r--r-- | debian/patches/console_switch3.patch | 839 | ||||
-rw-r--r-- | debian/patches/libcons_repeater.patch | 525 | ||||
-rw-r--r-- | debian/patches/netfs_io_select.patch | 58 | ||||
-rw-r--r-- | debian/patches/netfs_nonblock.patch | 21 | ||||
-rw-r--r-- | debian/patches/rc.patch | 54 |
11 files changed, 3242 insertions, 985 deletions
diff --git a/debian/changelog b/debian/changelog index cd2fd4de..503d3bb6 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,21 @@ +hurd (20040508-3) unstable; urgency=low + + * debian/local/rc: Removed. + * debian/patches/rc.patch: New file. (Closes: #254147) + * debian/hurd.install: Install tmp/libexec/rc. + * debian/patches/console_switch3.patch: Removed. + * debian/patches/console_repeater.patch: New patch by Marco Gerards. + * debian/patches/libcons_repeater.patch: New patch by Marco Gerards. + * debian/patches/netfs_io_select.patch: New patch by Marco Gerards. + * debian/patches/netfs_nonblock.patch: New patch by Marco Gerards. + * Rebuilt against glibc_2.3.2.ds1-16. + * debian/hurd.postinst: Make sure /bin/login is suid. (Closes: #251863) + * debian/control (Uploaders): Added myself. + * debian/hurd.postinst: Only create the tty devices if they do not + exist already. (Closes: #268347) + + -- Michael Banck <mbanck@debian.org> Thu, 9 Sep 2004 22:32:07 +0200 + hurd (20040508-2) unstable; urgency=low * Fix typo in postinst. (Closes: #253662) diff --git a/debian/control b/debian/control index 98460285..43570128 100644 --- a/debian/control +++ b/debian/control @@ -4,7 +4,7 @@ Priority: required Maintainer: GNU Hurd Maintainers <bug-hurd@gnu.org> Standards-Version: 3.6.1.0 Build-Depends: mig (>= 1.3-2), texinfo, libncursesw5-dev, cdbs, debhelper -Uploaders: Jeff Bailey <jbailey@raspberryginger.com>, Marcus Brinkmann <brinkmd@debian.org>, Neal H. Walfield <neal@debian.org> +Uploaders: Jeff Bailey <jbailey@raspberryginger.com>, Marcus Brinkmann <brinkmd@debian.org>, Neal H. Walfield <neal@debian.org>, Michael Banck <mbanck@debian.org> Package: hurd Priority: required diff --git a/debian/hurd.install b/debian/hurd.install index a087fc81..f7b91cbe 100644 --- a/debian/hurd.install +++ b/debian/hurd.install @@ -1,7 +1,7 @@ debian/tmp/lib/*.so.* debian/tmp/lib/hurd/console/*.so.* debian/tmp/hurd/* -debian/local/rc libexec +debian/tmp/libexec/rc debian/tmp/libexec/getty debian/tmp/libexec/console-run debian/tmp/libexec/runttys diff --git a/debian/hurd.postinst b/debian/hurd.postinst index 8ec6895b..7daf7b2d 100644 --- a/debian/hurd.postinst +++ b/debian/hurd.postinst @@ -12,11 +12,11 @@ fi #DEBHELPER# -(cd /dev && /sbin/MAKEDEV vcs) || true -(cd /dev && /sbin/MAKEDEV tty1) || true -(cd /dev && /sbin/MAKEDEV tty2) || true -(cd /dev && /sbin/MAKEDEV tty3) || true -(cd /dev && /sbin/MAKEDEV tty4) || true -(cd /dev && /sbin/MAKEDEV tty5) || true -(cd /dev && /sbin/MAKEDEV tty6) || true +for i in vcs tty1 tty2 tty3 tty4 tty5 tty6; do + if ! [ -e /dev/$i ]; then + cd /dev + /sbin/MAKEDEV $i || true + fi +done +chmod u+s /bin/login diff --git a/debian/local/rc b/debian/local/rc deleted file mode 100644 index 42609d01..00000000 --- a/debian/local/rc +++ /dev/null @@ -1,137 +0,0 @@ -#!/bin/bash -PATH=/bin:/sbin:/usr/bin:/usr/sbin - -# Start the default pager. It will bail if there is already one running. -/hurd/mach-defpager - -# Set up swap space. This will complain if no default pager is functioning. -swapon -a - -# Check filesystems. -if [ -r /fastboot ] -then - # ... or don't. - rm -f /fastboot - echo Fast boot ... skipping disk checks -elif [ $1x = autobootx ] -then - echo Automatic boot in progress... - date - - /sbin/fsck --preen --writable - - case $? in - # Successful completion - 0) - ;; - # Filesystem modified (but ok now) - 1 | 2) - ;; - # Fsck couldn't fix it. - 4 | 8) - echo "Automatic boot failed... help!" - exit 1 - ;; - # Signal that really interrupted something - 20 | 130 | 131) - echo "Boot interrupted" - exit 1 - ;; - # Special `let fsck finish' interruption (SIGQUIT) - 12) - echo "Boot interrupted (filesystem checks complete)" - exit 1 - ;; - # Oh dear. - *) - echo "Unknown error during fsck (exit status $?)" - exit 1 - ;; - esac -fi - -echo -n cleaning up left over files... -rm -f /etc/nologin -rm -f /var/lock/LCK.* -if test -d /tmp; then - - # Forcibly remove all translators in the directory. - # It is then safe to attempt to remove files and descend directories. - # All parameters must begin with "./". - function remove_translators() { - local f - for f; do - settrans -pagfS "$f" - if [ -L "$f" ] || [ ! -d "$f" ]; then - rm "$f" - else - remove_translators "$f"/* "$f"/.[!.] "$f"/.??* - rmdir "$f" - fi - done - } - - (cd /tmp - shopt -s nullglob - for f in * .[!.] .??*; do - case "$f" in - 'lost+found'|'quotas') ;; - *) remove_translators "./$f" - esac - done) - - unset -f remove_translators # because it relies on nullglob - -fi - -if test -d /var/run; then - (cd /var/run && { - find . ! -type d ! -name utmp ! -name innd.pid \ - -exec rm -f -- {} \; - cp /dev/null utmp - if grep -q ^utmp: /etc/group - then - chmod 664 utmp - chgrp utmp utmp - fi; }) -fi - -echo done - -# This file must exist for e2fsck to work. XXX -touch /var/run/mtab - -#echo -n restoring pty permissions... -#chmod 666 /dev/tty[pqrs]* -#echo done - -#echo -n updating /etc/motd... -#echo GNU\'s Not Unix Version `uname --release` > /tmp/newmotd -#egrep -v 'GNU|Version' /etc/motd >> /tmp/newmotd -#mv /tmp/newmotd /etc/motd -#echo done - -chmod 664 /etc/motd - -( - trap ":" INT QUIT TSTP - - if [ -d /etc/rc.boot ] - then - for i in /etc/rc.boot/S* - do - [ ! -f $i ] && continue - $i start - done - fi - if [ -d /etc/rc2.d ] - then - for i in /etc/rc2.d/S* - do - [ ! -f $i ] && continue - $i start - done - fi -) - -date diff --git a/debian/patches/console_repeater.patch b/debian/patches/console_repeater.patch new file mode 100644 index 00000000..fff33c4e --- /dev/null +++ b/debian/patches/console_repeater.patch @@ -0,0 +1,2557 @@ +diff -upN --exclude=CVS ../console-client.cvs/Makefile ./Makefile +--- console-client.cvs/Makefile 2002-09-17 12:26:10.000000000 +0000 ++++ console-client/Makefile 2004-07-27 07:19:22.000000000 +0000 +@@ -19,13 +19,13 @@ dir := console-client + makemode := utility + + target = console +-SRCS = console.c timer.c driver.c ++SRCS = console.c timer.c driver.c trans.c + LCLHDRS = timer.h driver.h display.h input.h bell.h \ +- unicode.h bdf.h \ ++ unicode.h bdf.h inputdev.h \ + vga-dynafont.h vga-dynacolor.h vga-hw.h vga.h + + OBJS = $(filter-out %.sh,$(SRCS:.c=.o)) +-HURDLIBS = cons threads ports ++HURDLIBS = cons threads ports netfs fshelp iohelp + LDLIBS = -ldl + module-dir = $(libdir)/hurd/console + console-LDFLAGS = -Wl,-E +@@ -41,11 +41,13 @@ driver-CPPFLAGS = -D'CONSOLE_DEFPATH="$( + console: ../libcons/libcons.a ../libports/libports.a \ + ../libthreads/libthreads.a ../libshouldbeinlibc/libshouldbeinlibc.a + +-modules = vga pc_kbd generic_speaker ++modules = vga pc_kbd generic_speaker pc_mouse + + vga.so.$(hurd-version): $(patsubst %.c,%_pic.o,bdf.c vga-dynafont.c \ + vga-dynacolor.c vga-support.c vga.c) +-pc_kbd.so.$(hurd-version): $(patsubst %.c,%_pic.o,pc-kbd.c) ++pc_kbd.so.$(hurd-version): $(patsubst %.c,%_pic.o,pc-kbd.c kdioctlServer.o kbd-repeat.c) ++pc_mouse.so.$(hurd-version): $(patsubst %.c,%_pic.o,pc-mouse.c) ++ + generic_speaker.so.$(hurd-version): $(patsubst %.c,%_pic.o,generic-speaker.c) + + ifneq ($(LIBNCURSESW),) +diff -upN --exclude=CVS ../console-client.cvs/console.c ./console.c +--- console-client.cvs/console.c 2004-07-27 07:14:05.000000000 +0000 ++++ console-client/console.c 2004-07-27 06:52:59.000000000 +0000 +@@ -47,6 +47,15 @@ static struct mutex global_lock; + displayed. */ + static vcons_t active_vcons = NULL; + ++/* Contains the VT id when switched away. */ ++static int saved_id = 0; ++ ++/* The console, used to switch back. */ ++static cons_t saved_cons; ++ ++/* The pathname of the node on which the translator is set. */ ++static char *consnode_path; ++ + + /* Callbacks for input source drivers. */ + +@@ -121,6 +130,36 @@ console_input (char *buf, size_t size) + } + + ++error_t ++console_move_mouse (mouse_event_t ev) ++{ ++ error_t err; ++ vcons_t vcons; ++ ++ mutex_lock (&global_lock); ++ vcons = active_vcons; ++ ++ vcons = active_vcons; ++ if (!vcons) ++ { ++ mutex_unlock (&global_lock); ++ return EINVAL; ++ } ++ ports_port_ref (vcons); ++ mutex_unlock (&global_lock); ++ ++ if (vcons) ++ { ++ err = cons_vcons_move_mouse (vcons, ev); ++ ports_port_deref (vcons); ++ } ++ ++ mutex_unlock (&global_lock); ++ ++ return 0; ++} ++ ++ + /* Scroll the active console by TYPE and VALUE as specified by + cons_vcons_scrollback. */ + int +@@ -148,6 +187,52 @@ console_scrollback (cons_scroll_t type, + } + + ++/* Switch away from the console an external use of the console like ++ XFree. */ ++void ++console_switch_away (void) ++{ ++ mutex_lock (&global_lock); ++ saved_id = active_vcons->id; ++ saved_cons = active_vcons->cons; ++ cons_vcons_close (active_vcons); ++ active_vcons = NULL; ++ mutex_unlock (&global_lock); ++} ++ ++/* Switch back to the console client from an external user of the ++ console like XFree. */ ++void ++console_switch_back (void) ++{ ++ vcons_list_t conslist; ++ mutex_lock (&global_lock); ++ if (saved_cons) ++ { ++ error_t err; ++ ++ err = cons_lookup (saved_cons, saved_id, 1, &conslist); ++ if (err) ++ { ++ mutex_unlock (&global_lock); ++ return; ++ } ++ ++ err = cons_vcons_open (saved_cons, conslist, &active_vcons); ++ if (err) ++ { ++ mutex_unlock (&global_lock); ++ return; ++ } ++ ++ conslist->vcons = active_vcons; ++ saved_cons = NULL; ++ mutex_unlock (&active_vcons->lock); ++ } ++ mutex_unlock (&global_lock); ++} ++ ++ + /* Exit the console client. Does not return. */ + void + console_exit (void) +@@ -371,6 +456,33 @@ cons_vcons_set_dimension (vcons_t vcons, + return 0; + } + ++ ++error_t ++cons_vcons_set_mousecursor_pos (vcons_t vcons, float x, float y) ++{ ++ mutex_lock (&global_lock); ++ if (vcons == active_vcons) ++ display_iterate ++ if (display->ops->set_mousecursor_pos) ++ display->ops->set_mousecursor_pos (display->handle, x, y); ++ mutex_unlock (&global_lock); ++ return 0; ++} ++ ++ ++error_t ++cons_vcons_set_mousecursor_status (vcons_t vcons, int status) ++{ ++ mutex_lock (&global_lock); ++ if (vcons == active_vcons) ++ display_iterate ++ if (display->ops->set_mousecursor_status) ++ display->ops->set_mousecursor_status (display->handle, status); ++ mutex_unlock (&global_lock); ++ return 0; ++ ++} ++ + + /* Console-specific options. */ + static const struct argp_option +@@ -378,6 +490,7 @@ options[] = + { + {"driver-path", 'D', "PATH", 0, "Specify search path for driver modules" }, + {"driver", 'd', "NAME", 0, "Add driver NAME to the console" }, ++ {"consnode", 'c', "PATH", 0, "Set a translator on the node PATH" }, + {0} + }; + +@@ -426,6 +539,12 @@ parse_opt (int key, char *arg, struct ar + devcount++; + break; + ++ case 'c': ++ consnode_path = strdup (arg); ++ if (!consnode_path) ++ return ENOMEM; ++ break; ++ + case ARGP_KEY_SUCCESS: + if (!devcount) + { +@@ -446,6 +565,33 @@ static const struct argp_child startup_c + static struct argp startup_argp = {options, parse_opt, 0, + 0, startup_children}; + ++static int exit_signal = 0; ++ ++static void ++sighandler (int sig) ++{ ++ exit_signal = 1; ++} ++ ++static any_t ++wait_for_exit (any_t unused) ++{ ++ while (!exit_signal) ++ sleep (1); ++ console_exit (); ++ return 0; ++} ++ ++#define HANDLE_SIGNAL(SIG) \ ++ if (signal (SIG, sighandler)) \ ++ { \ ++ driver_fini (); \ ++ error (1, errno, "Couldn't set signal handler"); \ ++ } ++ ++error_t test_read (loff_t offset, size_t *len, void *data); ++error_t test_read2 (loff_t offset, size_t *len, void *data); ++ + int + main (int argc, char *argv[]) + { +@@ -456,7 +602,13 @@ main (int argc, char *argv[]) + + /* Parse our command line. This shouldn't ever return an error. */ + argp_parse (&startup_argp, argc, argv, ARGP_IN_ORDER, 0, 0); +- ++ ++ HANDLE_SIGNAL (SIGTERM); ++ HANDLE_SIGNAL (SIGINT); ++ HANDLE_SIGNAL (SIGQUIT); ++ HANDLE_SIGNAL (SIGILL); ++ HANDLE_SIGNAL (SIGSEGV); ++ + err = driver_start (&errname); + if (err) + error (1, err, "Starting driver %s failed", errname); +@@ -469,14 +621,19 @@ main (int argc, char *argv[]) + driver_fini (); + error (1, err, "Console library initialization failed"); + } +- ++ + err = timer_init (); + if (err) + { + driver_fini (); + error (1, err, "Timer thread initialization failed"); + } +- ++ ++ cthread_detach (cthread_fork (wait_for_exit, NULL)); ++ ++ if (consnode_path) ++ console_setup_node (consnode_path); ++ + cons_server_loop (); + + /* Never reached. */ +diff -upN --exclude=CVS ../console-client.cvs/display.h ./display.h +--- console-client.cvs/display.h 2004-03-07 00:27:08.000000000 +0000 ++++ console-client/display.h 2004-04-02 07:29:55.000000000 +0000 +@@ -1,5 +1,5 @@ + /* display.h - The interface to and for a display driver. +- Copyright (C) 2002, 2003 Free Software Foundation, Inc. ++ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. +@@ -141,6 +141,15 @@ struct display_ops + write that covers the whole new screen. */ + error_t (*set_dimension) (void *handle, unsigned int width, + unsigned int height); ++ ++ /* Move the mouse cursor to the position X, Y. If the mouse cursor ++ is visible, update its position. */ ++ error_t (*set_mousecursor_pos) (void *handle, float x, float y); ++ ++ /* If STATUS is set to 0, hide the mouse cursor, otherwise show ++ it. */ ++ error_t (*set_mousecursor_status) (void *handle, int status); ++ + }; + + #endif /* _DISPLAY_H_ */ +diff -upN --exclude=CVS ../console-client.cvs/driver.c ./driver.c +--- console-client.cvs/driver.c 2004-03-21 19:57:00.000000000 +0000 ++++ console-client/driver.c 2004-04-02 07:29:40.000000000 +0000 +@@ -248,8 +248,8 @@ error_t + driver_start (char **name) + { + error_t err = 0; +- unsigned int i; +- ++ int i; ++ + mutex_lock (&driver_list_lock); + for (i = 0; i < driver_list_len; i++) + { +diff -upN --exclude=CVS ../console-client.cvs/input.h ./input.h +--- console-client.cvs/input.h 2002-09-17 12:26:10.000000000 +0000 ++++ console-client/input.h 2004-07-27 06:47:14.000000000 +0000 +@@ -1,5 +1,5 @@ + /* input.h - The interface to and for an input driver. +- Copyright (C) 2002 Free Software Foundation, Inc. ++ Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. +@@ -65,6 +65,17 @@ void console_error (const wchar_t *const + /* Exit the console client. Does not return. */ + void console_exit (void); + ++/* Switch away from the console an external use of the console like ++ XFree. */ ++void console_switch_away (void); ++ ++/* Switch back to the console client from an external user of the ++ console like XFree. */ ++void console_switch_back (void); ++ ++error_t console_move_mouse (mouse_event_t ev); ++ ++ + #if QUAERENDO_INVENIETIS + /* Do not use, do not remove. */ + void console_deprecated (int key); +diff -upN --exclude=CVS ../console-client.cvs/inputdev.h ./inputdev.h +--- console-client.cvs/inputdev.h 1970-01-01 00:00:00.000000000 +0000 ++++ console-client/inputdev.h 2004-07-25 01:55:17.000000000 +0000 +@@ -0,0 +1,138 @@ ++/* inputdev.h - Interfaces for the PC pc-kbd and mouse input drivers. ++ Copyright (C) 2002, 2004 Free Software Foundation, Inc. ++ Written by Marco Gerards. ++ ++ 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. */ ++ ++/* This gross stuff is cut & pasted from Mach sources, as Mach doesn't ++ export the interface we are using here. */ ++ ++/* ++ * Mach Operating System ++ * Copyright (c) 1991,1990,1989 Carnegie Mellon University ++ * All Rights Reserved. ++ * ++ * Permission to use, copy, modify and distribute this software and its ++ * documentation is hereby granted, provided that both the copyright ++ * notice and this permission notice appear in all copies of the ++ * software, derivative works or modified versions, and any portions ++ * thereof, and that both notices appear in supporting documentation. ++ * ++ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ++ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ++ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ++ * ++ * Carnegie Mellon requests users of this software to return to ++ * ++ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU ++ * School of Computer Science ++ * Carnegie Mellon University ++ * Pittsburgh PA 15213-3890 ++ * ++ * any improvements or extensions that they make and grant Carnegie Mellon ++ * the rights to redistribute these changes. ++ */ ++ ++#ifndef _INPUTDEV_H_ ++#define _INPUTDEV_H_ 1 ++ ++#include <trans.h> ++ ++typedef u_short kev_type; /* kd event type */ ++ ++/* (used for event records) */ ++struct mouse_motion { ++ short mm_deltaX; /* units? */ ++ short mm_deltaY; ++}; ++typedef u_char Scancode; ++ ++typedef struct { ++ kev_type type; /* see below */ ++ struct timeval time; /* timestamp */ ++ union { /* value associated with event */ ++ boolean_t up; /* MOUSE_LEFT .. MOUSE_RIGHT */ ++ Scancode sc; /* KEYBD_EVENT */ ++ struct mouse_motion mmotion; /* MOUSE_MOTION */ ++ } value; ++} kd_event; ++#define m_deltaX mmotion.mm_deltaX ++#define m_deltaY mmotion.mm_deltaY ++ ++/* ++ * kd_event ID's. ++ */ ++#define MOUSE_LEFT 1 /* mouse left button up/down */ ++#define MOUSE_MIDDLE 2 ++#define MOUSE_RIGHT 3 ++#define MOUSE_MOTION 4 /* mouse motion */ ++#define KEYBD_EVENT 5 /* key up/down */ ++ ++ ++#define IOCPARM_MASK 0x1fff /* parameter length, at most 13 bits */ ++#define IOC_OUT 0x40000000 /* copy out parameters */ ++#define IOC_IN 0x80000000U /* copy in parameters */ ++ ++#ifndef _IOC ++#define _IOC(inout,group,num,len) \ ++ (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num)) ++#endif ++#ifndef _IOR ++#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t)) ++#endif ++#ifndef _IOW ++#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t)) ++#endif ++ ++#define KDSKBDMODE _IOW('K', 1, int) /* set keyboard mode */ ++#define KB_EVENT 1 ++#define KB_ASCII 2 ++ ++#define KDGKBDTYPE _IOR('K', 2, int) /* get keyboard type */ ++#define KB_VANILLAKB 0 ++ ++#define KDSETLEDS _IOW('K', 5, int) /* set keyboard leds */ ++ ++/* ++ * Low 3 bits of minor are the com port #. ++ * The high 5 bits of minor are the mouse type ++ */ ++#define MOUSE_SYSTEM_MOUSE 0 ++#define MICROSOFT_MOUSE 1 ++#define IBM_MOUSE 2 ++#define NO_MOUSE 3 ++#define LOGITECH_TRACKMAN 4 ++#define MICROSOFT_MOUSE7 5 ++ ++#define DEV_COM0 "com0" ++#define DEV_COM1 "com1" ++ ++/* End of Mach code. */ ++ ++ ++/* Amount of times the device was opened. Normally this translator ++ should be only opened once. */ ++extern int kbd_repeater_opened; ++ ++/* Place the keyboard event KEY in the keyboard buffer. */ ++void kbd_repeat_key (kd_event *key); ++ ++/* Set the repeater translator. The node will be named NODENAME and ++ NODE will be filled with information about this node. */ ++error_t kbd_setrepeater (const char *nodename, consnode_t *node); ++ ++#endif /* _INPUTDEV_H_ */ +diff -upN --exclude=CVS ../console-client.cvs/kbd-repeat.c ./kbd-repeat.c +--- console-client.cvs/kbd-repeat.c 1970-01-01 00:00:00.000000000 +0000 ++++ console-client/kbd-repeat.c 2004-07-27 06:51:47.000000000 +0000 +@@ -0,0 +1,258 @@ ++/* kbd-repeat.c - Keyboard repeater. ++ Copyright (C) 2004 Free Software Foundation, Inc. ++ Written by Marco Gerards. ++ ++ 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 <hurd/netfs.h> ++#include <stdlib.h> ++#include <error.h> ++#include <string.h> ++#include <fcntl.h> ++#include <sys/mman.h> ++ ++#include "kdioctl_S.h" ++#include "inputdev.h" ++#include "input.h" ++ ++/* The amount of keyboard events that can be stored in the keyboard buffer. */ ++#define KBDEVTBUFSZ 20 ++ ++/* The size of the keyboard buffer in bytes. */ ++#define KBDBUFSZ (KBDEVTBUFSZ * sizeof (kd_event)) ++ ++/* Return the position of X in the buffer. */ ++#define KBDBUF_POS(x) ((x) % KBDBUFSZ) ++ ++/* The keyboard buffer. */ ++static struct kbdbuf ++{ ++ char keybuffer[KBDBUFSZ]; ++ int pos; ++ size_t size; ++ struct condition readcond; ++ struct condition writecond; ++} kbdbuf; ++ ++/* Wakeup for select */ ++static struct condition select_alert; ++ ++/* The global lock */ ++static struct mutex global_lock; ++ ++/* Amount of times the device was opened. Normally this translator ++ should be only opened once. */ ++int kbd_repeater_opened; ++ ++ ++/* Place the keyboard event KEY in the keyboard buffer. */ ++void ++kbd_repeat_key (kd_event *key) ++{ ++ kd_event *ev; ++ ++ mutex_lock (&global_lock); ++ while (kbdbuf.size + sizeof (kd_event) > KBDBUFSZ) ++ { ++ /* The input buffer is full, wait until there is some space. */ ++ if (hurd_condition_wait (&kbdbuf.writecond, &global_lock)) ++ { ++ mutex_unlock (&global_lock); ++ /* Interrupt, silently continue. */ ++ } ++ } ++ ev = (kd_event *) &kbdbuf.keybuffer[KBDBUF_POS (kbdbuf.pos ++ + kbdbuf.size)]; ++ kbdbuf.size += sizeof (kd_event); ++ memcpy (ev, key, sizeof (kd_event)); ++ ++ condition_broadcast (&kbdbuf.readcond); ++ mutex_unlock (&global_lock); ++} ++ ++ ++static error_t ++repeater_select (struct protid *cred, mach_port_t reply, ++ mach_msg_type_name_t replytype, int *type) ++{ ++ if (!cred) ++ return EOPNOTSUPP; ++ ++ if (*type & ~SELECT_READ) ++ return EINVAL; ++ ++ if (*type == 0) ++ return 0; ++ ++ mutex_lock (&global_lock); ++ while (1) ++ { ++ if (kbdbuf.size > 0) ++ { ++ *type = SELECT_READ; ++ mutex_unlock (&global_lock); ++ ++ return 0; ++ } ++ ++ ports_interrupt_self_on_port_death (cred, reply); ++ if (hurd_condition_wait (&select_alert, &global_lock)) ++ { ++ *type = 0; ++ mutex_unlock (&global_lock); ++ ++ return EINTR; ++ } ++ } ++} ++ ++ ++static error_t ++repeater_read (struct protid *cred, char **data, ++ mach_msg_type_number_t *datalen, off_t offset, ++ mach_msg_type_number_t amount) ++{ ++ /* Deny access if they have bad credentials. */ ++ if (! cred) ++ return EOPNOTSUPP; ++ else if (! (cred->po->openstat & O_READ)) ++ return EBADF; ++ ++ mutex_lock (&global_lock); ++ while (amount > kbdbuf.size) ++ { ++ if (cred->po->openstat & O_NONBLOCK && amount > kbdbuf.size) ++ { ++ mutex_unlock (&global_lock); ++ return EWOULDBLOCK; ++ } ++ ++ if (hurd_condition_wait (&kbdbuf.readcond, &global_lock)) ++ { ++ mutex_unlock (&global_lock); ++ return EINTR; ++ } ++ } ++ ++ if (amount > 0) ++ { ++ char *keydata; ++ unsigned int i = 0; ++ ++ /* Allocate a buffer when this is required. */ ++ if (*datalen < amount) ++ { ++ *data = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); ++ if (*data == MAP_FAILED) ++ { ++ mutex_unlock (&global_lock); ++ return ENOMEM; ++ } ++ } ++ ++ /* Copy the bytes to the user's buffer and remove them from the ++ keyboard buffer. */ ++ keydata = *data; ++ while (i != amount) ++ { ++ keydata[i++] = kbdbuf.keybuffer[kbdbuf.pos++]; ++ kbdbuf.pos = KBDBUF_POS (kbdbuf.pos); ++ } ++ kbdbuf.size -= amount; ++ condition_broadcast (&kbdbuf.writecond); ++ } ++ ++ *datalen = amount; ++ mutex_unlock (&global_lock); ++ ++ return 0; ++} ++ ++ ++static void ++repeater_open (void) ++{ ++ /* Make sure the console does not access the hardware anymore. */ ++ if (! kbd_repeater_opened) ++ console_switch_away (); ++ kbd_repeater_opened++; ++} ++ ++ ++static void ++repeater_close (void) ++{ ++ kbd_repeater_opened--; ++ ++ /* Allow the console to access the hardware again. */ ++ if (! kbd_repeater_opened) ++ { ++ console_switch_back (); ++ kbdbuf.pos = 0; ++ kbdbuf.size = 0; ++ } ++} ++ ++ ++/* Set the repeater translator. The node will be named NODENAME and ++ NODE will be filled with information about this node. */ ++error_t ++kbd_setrepeater (const char *nodename, consnode_t *cn) ++{ ++ extern int kdioctl_server (mach_msg_header_t *inp, mach_msg_header_t *outp); ++ error_t err; ++ ++ err = console_create_consnode (nodename, cn); ++ if (err) ++ return err; ++ ++ (*cn)->read = repeater_read; ++ (*cn)->write = 0; ++ (*cn)->select = repeater_select; ++ (*cn)->open = repeater_open; ++ (*cn)->close = repeater_close; ++ (*cn)->demuxer = kdioctl_server; ++ ++ mutex_init (&global_lock); ++ ++ condition_init (&kbdbuf.readcond); ++ condition_init (&kbdbuf.writecond); ++ ++ condition_init (&select_alert); ++ condition_implies (&kbdbuf.readcond, &select_alert); ++ ++ console_register_consnode (*cn); ++ ++ return 0; ++} ++ ++ ++/* Some RPC calls for controlling the keyboard. These calls are just ++ ignored and just exist to make XFree happy. */ ++ ++kern_return_t ++S_kdioctl_kdskbdmode (io_t port, int mode) ++{ ++ return 0; ++} ++ ++ ++kern_return_t ++S_kdioctl_kdgkbdmode (io_t port, int *mode) ++{ ++ return 0; ++} +diff -upN --exclude=CVS ../console-client.cvs/pc-kbd.c ./pc-kbd.c +--- console-client.cvs/pc-kbd.c 2004-02-02 22:08:14.000000000 +0000 ++++ console-client/pc-kbd.c 2004-07-27 06:59:25.000000000 +0000 +@@ -23,6 +23,7 @@ + #include <string.h> + #include <iconv.h> + #include <sys/mman.h> ++#include <argp.h> + + #include <device/device.h> + #include <cthreads.h> +@@ -31,6 +32,7 @@ + #include <hurd/cons.h> + + #include "driver.h" ++#include "inputdev.h" + + + /* The keyboard device in the kernel. */ +@@ -52,6 +54,11 @@ int gnumach_v1_compat; + /* Forward declaration. */ + static struct input_ops pc_kbd_ops; + ++/* The name of the repeater node. */ ++static char *repeater_node; ++ ++/* The repeater node. */ ++static consnode_t cnode; + + /* A list of scan codes generated by the keyboard, in the set 2 encoding. */ + enum scancode +@@ -558,87 +565,6 @@ enum scancode sc_set1_to_set2_x1[] = + SC_X1_DEL + }; + +- +-/* This gross stuff is cut & pasted from Mach sources, as Mach doesn't +- export the interface we are using here. */ +- +-/* +- * Mach Operating System +- * Copyright (c) 1991,1990,1989 Carnegie Mellon University +- * All Rights Reserved. +- * +- * Permission to use, copy, modify and distribute this software and its +- * documentation is hereby granted, provided that both the copyright +- * notice and this permission notice appear in all copies of the +- * software, derivative works or modified versions, and any portions +- * thereof, and that both notices appear in supporting documentation. +- * +- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" +- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR +- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. +- * +- * Carnegie Mellon requests users of this software to return to +- * +- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU +- * School of Computer Science +- * Carnegie Mellon University +- * Pittsburgh PA 15213-3890 +- * +- * any improvements or extensions that they make and grant Carnegie Mellon +- * the rights to redistribute these changes. +- */ +- +-typedef u_short kev_type; /* kd event type */ +- +-/* (used for event records) */ +-struct mouse_motion { +- short mm_deltaX; /* units? */ +- short mm_deltaY; +-}; +-typedef u_char Scancode; +- +-typedef struct { +- kev_type type; /* see below */ +- struct timeval time; /* timestamp */ +- union { /* value associated with event */ +- boolean_t up; /* MOUSE_LEFT .. MOUSE_RIGHT */ +- Scancode sc; /* KEYBD_EVENT */ +- struct mouse_motion mmotion; /* MOUSE_MOTION */ +- } value; +-} kd_event; +-#define m_deltaX mmotion.mm_deltaX +-#define m_deltaY mmotion.mm_deltaY +- +-/* +- * kd_event ID's. +- */ +-#define MOUSE_LEFT 1 /* mouse left button up/down */ +-#define MOUSE_MIDDLE 2 +-#define MOUSE_RIGHT 3 +-#define MOUSE_MOTION 4 /* mouse motion */ +-#define KEYBD_EVENT 5 /* key up/down */ +- +- +-#define IOCPARM_MASK 0x1fff /* parameter length, at most 13 bits */ +-#define IOC_OUT 0x40000000 /* copy out parameters */ +-#define IOC_IN 0x80000000U /* copy in parameters */ +-#define _IOC(inout,group,num,len) \ +- (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num)) +-#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t)) +-#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t)) +- +-#define KDSKBDMODE _IOW('K', 1, int) /* set keyboard mode */ +-#define KB_EVENT 1 +-#define KB_ASCII 2 +- +-#define KDGKBDTYPE _IOR('K', 2, int) /* get keyboard type */ +-#define KB_VANILLAKB 0 +- +-#define KDSETLEDS _IOW('K', 5, int) /* set keyboard leds */ +- +- +-/* End of Mach code. */ +- + static enum scancode + gnumach_v1_input_next () + { +@@ -658,6 +584,13 @@ gnumach_v1_input_next () + terminate. */ + if (err) + return 0; ++ ++ if (kbd_repeater_opened && data_buf.type == KEYBD_EVENT) ++ { ++ kbd_repeat_key (&data_buf); ++ data_buf.type = 0; ++ continue; ++ } + } + while (data_buf.type != KEYBD_EVENT); + +@@ -1088,10 +1021,56 @@ input_loop (any_t unused) + + + ++ ++ ++static const char doc[] = "PC Keyboard Driver"; ++ ++static const struct argp_option options[] = ++ { ++ {"repeat", 'r', "NODE", 0, "Set a repeater translator on NODE"}, ++ { 0 } ++ }; ++ ++static error_t ++parse_opt (int key, char *arg, struct argp_state *state) ++{ ++ int *pos = (int *) state->input; ++ ++ switch (key) ++ { ++ case 'r': ++ repeater_node = arg; ++ break; ++ ++ case ARGP_KEY_END: ++ break; ++ ++ default: ++ return ARGP_ERR_UNKNOWN; ++ } ++ ++ *pos = state->next; ++ return 0; ++} ++ ++static struct argp argp = {options, parse_opt, 0, doc}; ++ + /* Initialize the PC keyboard driver. */ + static error_t + pc_kbd_init (void **handle, int no_exit, int argc, char *argv[], int *next) + { ++ error_t err; ++ int pos = 1; ++ ++ /* Parse the arguments. */ ++ err = argp_parse (&argp, argc, argv, ARGP_IN_ORDER | ARGP_NO_EXIT ++ | ARGP_SILENT, 0 , &pos); ++ *next += pos - 1; ++ ++ if (err && err != EINVAL) ++ return err; ++ ++ + return 0; + } + +@@ -1156,6 +1135,10 @@ pc_kbd_start (void *handle) + iconv_close (cd); + return err; + } ++ ++ if (repeater_node) ++ kbd_setrepeater (repeater_node, &cnode); ++ + cthread_detach (cthread_fork (input_loop, NULL)); + + return 0; +@@ -1175,6 +1158,9 @@ pc_kbd_fini (void *handle, int force) + mach_port_deallocate (mach_task_self (), kbd_dev); + iconv_close (cd); + ++ console_unregister_consnode (cnode); ++ console_destroy_consnode (cnode); ++ + return 0; + } + +diff -upN --exclude=CVS ../console-client.cvs/pc-mouse.c ./pc-mouse.c +--- console-client.cvs/pc-mouse.c 1970-01-01 00:00:00.000000000 +0000 ++++ console-client/pc-mouse.c 2004-07-27 06:57:04.000000000 +0000 +@@ -0,0 +1,475 @@ ++/* pc-mouse.c - Mouse driver. ++ Copyright (C) 2004 Free Software Foundation, Inc. ++ Written by Marco Gerards. ++ ++ 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 <argp.h> ++#include <hurd.h> ++#include <hurd/ports.h> ++#include <device/device.h> ++#include <fcntl.h> ++#include <sys/mman.h> ++#include "driver.h" ++#include "inputdev.h" ++ ++static struct input_ops pc_mouse_ops; ++ ++/* Default to the protocol I use :). */ ++static int majordev = IBM_MOUSE; ++static int minordev = 0; ++ ++static device_t mousedev; ++ ++ ++/* The amount of mouse events that can be stored in the event buffer. */ ++#define MOUSEDEVTBUFSZ 256 ++ ++/* The size of the event buffer in bytes. */ ++#define MOUSEBUFSZ (MOUSEDEVTBUFSZ * sizeof (kd_event)) ++ ++/* Return the position of X in the buffer. */ ++#define MOUSEBUF_POS(x) ((x) % MOUSEBUFSZ) ++ ++/* The mouse event buffer. */ ++static struct mousebuf ++{ ++ char evtbuffer[MOUSEBUFSZ]; ++ int pos; ++ size_t size; ++ struct condition readcond; ++ struct condition writecond; ++} mousebuf; ++ ++/* Wakeup for select */ ++static struct condition select_alert; ++ ++/* The global lock */ ++static struct mutex global_lock; ++ ++/* Amount of times the device was opened. Normally this translator ++ should be only opened once. */ ++static int mouse_repeater_opened; ++ ++/* The name of the repeater node. */ ++static char *repeater_node; ++ ++/* The repeater node. */ ++static consnode_t cnode; ++ ++ ++/* Place the mouse event EVNT in the mouse event buffer. */ ++static void ++repeat_event (kd_event *evt) ++{ ++ kd_event *ev; ++ ++ mutex_lock (&global_lock); ++ while (mousebuf.size + sizeof (kd_event) > MOUSEBUFSZ) ++ { ++ /* The input buffer is full, wait until there is some space. */ ++ if (hurd_condition_wait (&mousebuf.writecond, &global_lock)) ++ { ++ mutex_unlock (&global_lock); ++ /* Interrupt, silently continue. */ ++ } ++ } ++ ev = (kd_event *) &mousebuf.evtbuffer[MOUSEBUF_POS (mousebuf.pos ++ + mousebuf.size)]; ++ mousebuf.size += sizeof (kd_event); ++ memcpy (ev, evt, sizeof (kd_event)); ++ ++ condition_broadcast (&mousebuf.readcond); ++ mutex_unlock (&global_lock); ++} ++ ++ ++static error_t ++repeater_select (struct protid *cred, mach_port_t reply, ++ mach_msg_type_name_t replytype, int *type) ++{ ++ if (!cred) ++ return EOPNOTSUPP; ++ ++ if (*type & ~SELECT_READ) ++ return EINVAL; ++ ++ if (*type == 0) ++ return 0; ++ ++ mutex_lock (&global_lock); ++ while (1) ++ { ++ if (mousebuf.size > 0) ++ { ++ *type = SELECT_READ; ++ mutex_unlock (&global_lock); ++ ++ return 0; ++ } ++ ++ ports_interrupt_self_on_port_death (cred, reply); ++ if (hurd_condition_wait (&select_alert, &global_lock)) ++ { ++ *type = 0; ++ mutex_unlock (&global_lock); ++ ++ return EINTR; ++ } ++ } ++} ++ ++ ++static void ++repeater_open (void) ++{ ++ mouse_repeater_opened++; ++} ++ ++ ++static void ++repeater_close (void) ++{ ++ mouse_repeater_opened--; ++ if (!mouse_repeater_opened) ++ { ++ mousebuf.pos = 0; ++ mousebuf.size = 0; ++ } ++} ++ ++ ++static error_t ++repeater_read (struct protid *cred, char **data, ++ mach_msg_type_number_t *datalen, off_t offset, ++ mach_msg_type_number_t amount) ++{ ++ /* Deny access if they have bad credentials. */ ++ if (! cred) ++ return EOPNOTSUPP; ++ else if (! (cred->po->openstat & O_READ)) ++ return EBADF; ++ ++ mutex_lock (&global_lock); ++ while (!mousebuf.size) ++ { ++ if (cred->po->openstat & O_NONBLOCK && mousebuf.size == 0) ++ { ++ mutex_unlock (&global_lock); ++ return EWOULDBLOCK; ++ } ++ ++ if (hurd_condition_wait (&mousebuf.readcond, &global_lock)) ++ { ++ mutex_unlock (&global_lock); ++ return EINTR; ++ } ++ } ++ ++ amount = (amount / sizeof (kd_event) - 1) * sizeof (kd_event); ++ if (amount > mousebuf.size) ++ amount = mousebuf.size; ++ ++ if (amount > 0) ++ { ++ char *mousedata; ++ unsigned int i = 0; ++ ++ /* Allocate a buffer when this is required. */ ++ if (*datalen < amount) ++ { ++ *data = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); ++ if (*data == MAP_FAILED) ++ { ++ mutex_unlock (&global_lock); ++ return ENOMEM; ++ } ++ } ++ ++ /* Copy the bytes to the user's buffer and remove them from the ++ mouse events buffer. */ ++ mousedata = *data; ++ while (i != amount) ++ { ++ mousedata[i++] = mousebuf.evtbuffer[mousebuf.pos++]; ++ mousebuf.pos = MOUSEBUF_POS (mousebuf.pos); ++ } ++ mousebuf.size -= amount; ++ condition_broadcast (&mousebuf.writecond); ++ } ++ ++ *datalen = amount; ++ mutex_unlock (&global_lock); ++ ++ return 0; ++} ++ ++ ++ ++static any_t ++input_loop (any_t unused) ++{ ++ kd_event *ev; ++ vm_offset_t buf; ++ mach_msg_type_number_t buf_size; ++ ++ while (1) ++ { ++ struct mouse_event evt = { 0 }; ++ device_read (mousedev, 0, 0, sizeof (kd_event), (char **)&buf, &buf_size); ++ ev = (kd_event *) buf; ++ ++ /* The repeater is set, send the event to the repeater. */ ++ if (mouse_repeater_opened) ++ { ++ repeat_event (ev); ++ continue; ++ } ++ ++ evt.mouse_movement = MOUSE_MOVE_REL; ++ ++ switch (ev->type) ++ { ++ case MOUSE_LEFT: ++ evt.button = CONS_MOUSE_BUTTON1; ++ break; ++ case MOUSE_MIDDLE: ++ evt.button = CONS_MOUSE_BUTTON2; ++ break; ++ case MOUSE_RIGHT: ++ evt.button = CONS_MOUSE_BUTTON3; ++ break; ++ ++ case MOUSE_MOTION: ++ evt.x = ev->value.mmotion.mm_deltaX; ++ evt.y = -ev->value.mmotion.mm_deltaY; ++ break; ++ } ++ ++ if (ev->type > 0 && ev->type <= 3) ++ { ++ if (ev->value.up) ++ evt.mouse_button = MOUSE_BUTTON_RELEASED; ++ else ++ evt.mouse_button = MOUSE_BUTTON_PRESSED; ++ } ++ ++ /* Generate a mouse movement event. */ ++ console_move_mouse (&evt); ++ } ++} ++ ++ ++#define PROTO_MOUSESYSTEM "mousesystem" ++#define PROTO_MICROSOFT "microsoft" ++#define PROTO_PS2 "ps/2" ++#define PROTO_NOMOUSE "nomouse" ++#define PROTO_LOGITECH "logitech" ++#define PROTO_MOUSE7 "mouse7" ++ ++/* The supported mouse protocols. Be careful with adding more, the ++ protocols are carefully ordered so the index is the major device ++ number. */ ++static char *mouse_protocols[] = ++ { ++ PROTO_MOUSESYSTEM, ++ PROTO_MICROSOFT, ++ PROTO_PS2, ++ PROTO_NOMOUSE, ++ PROTO_LOGITECH, ++ PROTO_MOUSE7 ++ }; ++ ++static const char doc[] = "Mouse Driver"; ++ ++static const struct argp_option options[] = ++ { ++ { "protocol", 'p', "PROTOCOL", 0, "One of the protocols: " ++ PROTO_MOUSESYSTEM ", " PROTO_MICROSOFT ", " PROTO_PS2 ", " ++ PROTO_NOMOUSE ", " PROTO_LOGITECH ", " PROTO_MOUSE7 }, ++ { "device", 'e', "DEVICE" , 0, "One of the devices: " DEV_COM0 ", " DEV_COM1 }, ++ { "repeat", 'r', "NODE", 0, "Set a repeater translator on NODE"}, ++ { 0 } ++ }; ++ ++static error_t setrepeater (const char *nodename); ++ ++static error_t ++parse_opt (int key, char *arg, struct argp_state *state) ++{ ++ int *pos = (int *) state->input; ++ ++ switch (key) ++ { ++ case 'p': ++ { ++ unsigned int i; ++ ++ for (i = 0; i < (sizeof (mouse_protocols) / sizeof (char *)); i++) ++ { ++ if (!strcasecmp (arg, mouse_protocols[i])) ++ { ++ majordev = i; ++ *pos = state->next; ++ return 0; ++ } ++ } ++ fprintf (stderr, "Unknown protocol `%s'\n", arg); ++ argp_usage (state); ++ return ARGP_ERR_UNKNOWN; ++ } ++ ++ case 'e': ++ { ++ if (!strcasecmp (DEV_COM0, arg)) ++ minordev = 0; ++ else if (!strcasecmp (DEV_COM1, arg)) ++ minordev = 1; ++ else ++ { ++ fprintf (stderr, "Unknown device `%s'\n", arg); ++ argp_usage (state); ++ return ARGP_ERR_UNKNOWN; ++ } ++ break; ++ } ++ ++ case 'r': ++ repeater_node = arg; ++ break; ++ ++ case ARGP_KEY_END: ++ break; ++ ++ default: ++ return ARGP_ERR_UNKNOWN; ++ } ++ ++ *pos = state->next; ++ return 0; ++} ++ ++ ++static struct argp argp = {options, parse_opt, 0, doc}; ++ ++static error_t ++pc_mouse_init (void **handle, int no_exit, int argc, char *argv[], int *next) ++{ ++ error_t err; ++ int pos = 1; ++ ++ /* Parse the arguments. */ ++ err = argp_parse (&argp, argc, argv, ARGP_IN_ORDER | ARGP_NO_EXIT ++ | ARGP_SILENT, 0, &pos); ++ *next += pos - 1; ++ if (err && err != EINVAL) ++ return err; ++ ++ return 0; ++} ++ ++ ++static error_t ++pc_mouse_start (void *handle) ++{ ++ error_t err; ++ char device_name[9]; ++ int devnum = majordev << 3 | minordev; ++ device_t device_master; ++ ++ sprintf (device_name, "mouse%d", devnum); ++ err = get_privileged_ports (0, &device_master); ++ ++ err = device_open (device_master, D_READ, device_name, &mousedev); ++ mach_port_deallocate (mach_task_self (), device_master); ++ if (err) ++ return ENODEV; ++ ++ err = driver_add_input (&pc_mouse_ops, NULL); ++ if (err) ++ { ++ device_close (mousedev); ++ mach_port_deallocate (mach_task_self (), mousedev); ++ ++ return err; ++ } ++ ++ cthread_detach (cthread_fork (input_loop, NULL)); ++ ++ if (repeater_node) ++ setrepeater (repeater_node); ++ ++ return 0; ++} ++ ++ ++static error_t ++pc_mouse_fini (void *handle, int force) ++{ ++ device_close (mousedev); ++ mach_port_deallocate (mach_task_self (), mousedev); ++ console_unregister_consnode (cnode); ++ console_destroy_consnode (cnode); ++ ++ return 0; ++} ++ ++ ++ ++struct driver_ops driver_pc_mouse_ops = ++ { ++ pc_mouse_init, ++ pc_mouse_start, ++ pc_mouse_fini ++ }; ++ ++static struct input_ops pc_mouse_ops = ++ { ++ NULL, ++ NULL ++ }; ++ ++ ++/* Set make repeater translator node named NODENAME. */ ++static error_t ++setrepeater (const char *nodename) ++{ ++ error_t err; ++ ++ err = console_create_consnode (nodename, &cnode); ++ if (err) ++ return err; ++ ++ cnode->read = repeater_read; ++ cnode->write = 0; ++ cnode->select = repeater_select; ++ cnode->open = repeater_open; ++ cnode->close = repeater_close; ++ cnode->demuxer = 0; ++ ++ mutex_init (&global_lock); ++ ++ condition_init (&mousebuf.readcond); ++ condition_init (&mousebuf.writecond); ++ ++ condition_init (&select_alert); ++ condition_implies (&mousebuf.readcond, &select_alert); ++ ++ console_register_consnode (cnode); ++ ++ return 0; ++} +diff -upN --exclude=CVS ../console-client.cvs/trans.c ./trans.c +--- console-client.cvs/trans.c 1970-01-01 00:00:00.000000000 +0000 ++++ console-client/trans.c 2004-07-27 05:42:40.000000000 +0000 +@@ -0,0 +1,872 @@ ++/* trans.c -- Control a translator node for the repeaters. ++ Copyright (C) 2004 Free Software Foundation, Inc. ++ Written by Marco Gerards. ++ ++ This program 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. ++ ++ This program 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-1307 USA */ ++ ++#include <fcntl.h> ++#include <maptime.h> ++#include <stddef.h> ++#include <dirent.h> ++#include <sys/mman.h> ++#include <unistd.h> ++#include <hurd/hurd_types.h> ++#include <error.h> ++#include <version.h> ++ ++#include "trans.h" ++ ++ ++/* The user must define this variable. Set this to the name of the ++ filesystem server. */ ++char *netfs_server_name = "console"; ++ ++/* The user must define this variables. Set this to be the server ++ version number. */ ++char *netfs_server_version = HURD_VERSION; ++ ++int netfs_maxsymlinks = 0; ++ ++/* Handy source of time. */ ++static volatile struct mapped_time_value *console_maptime; ++ ++static consnode_t node_list = 0; ++ ++struct netnode ++{ ++ consnode_t node; ++}; ++ ++typedef mach_msg_header_t request_t; ++ ++ ++ ++int ++console_demuxer (mach_msg_header_t *inp, ++ mach_msg_header_t *outp) ++{ ++ int ret; ++ struct protid *user = (struct protid *) inp; ++ request_t *inop = (request_t *) inp; ++ ++ ret = netfs_demuxer (inp, outp); ++ if (ret) ++ return ret; ++ ++ user = ports_lookup_port (netfs_port_bucket, inop->msgh_local_port, netfs_protid_class); ++ if (!user) ++ return ret; ++ ++ /* Don't do anything for the root node. */ ++ if (user->po->np == netfs_root_node) ++ { ++ ports_port_deref (user); ++ return 0; ++ } ++ ++ if (!ret && user->po->np->nn->node->demuxer) ++ ret = user->po->np->nn->node->demuxer (inp, outp); ++ ++ ports_port_deref (user); ++ return ret; ++} ++ ++ ++ ++/* The user must define this function. Make sure that NP->nn_stat is ++ filled with the most current information. CRED identifies the user ++ responsible for the operation. NP is locked. */ ++error_t ++netfs_validate_stat (struct node *np, struct iouser *cred) ++{ ++ return 0; ++} ++ ++ ++/* The user must define this function. This should attempt a chmod ++ call for the user specified by CRED on locked node NP, to change ++ the owner to UID and the group to GID. */ ++error_t ++netfs_attempt_chown (struct iouser *cred, struct node *np, ++ uid_t uid, uid_t gid) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. This should attempt a chauthor ++ call for the user specified by CRED on locked node NP, thereby ++ changing the author to AUTHOR. */ ++error_t ++netfs_attempt_chauthor (struct iouser *cred, struct node *np, ++ uid_t author) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. This should attempt a chmod ++ call for the user specified by CRED on locked node NODE, to change ++ the mode to MODE. Unlike the normal Unix and Hurd meaning of ++ chmod, this function is also used to attempt to change files into ++ other types. If such a transition is attempted which is ++ impossible, then return EOPNOTSUPP. */ ++error_t ++netfs_attempt_chmod (struct iouser *cred, struct node *np, ++ mode_t mode) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. Attempt to turn locked node NP ++ (user CRED) into a symlink with target NAME. */ ++error_t ++netfs_attempt_mksymlink (struct iouser *cred, struct node *np, ++ char *name) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. Attempt to turn NODE (user ++ CRED) into a device. TYPE is either S_IFBLK or S_IFCHR. NP is ++ locked. */ ++error_t ++netfs_attempt_mkdev (struct iouser *cred, struct node *np, ++ mode_t type, dev_t indexes) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user may define this function. Attempt to set the passive ++ translator record for FILE to ARGZ (of length ARGZLEN) for user ++ CRED. NP is locked. */ ++error_t ++netfs_set_translator (struct iouser *cred, struct node *np, ++ char *argz, size_t argzlen) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user may define this function (but should define it together ++ with netfs_set_translator). For locked node NODE with S_IPTRANS ++ set in its mode, look up the name of its translator. Store the ++ name into newly malloced storage, and return it in *ARGZ; set ++ *ARGZ_LEN to the total length. */ ++error_t ++netfs_get_translator (struct node *node, char **argz, ++ size_t *argz_len) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. This should attempt a chflags ++ call for the user specified by CRED on locked node NP, to change ++ the flags to FLAGS. */ ++error_t ++netfs_attempt_chflags (struct iouser *cred, struct node *np, ++ int flags) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. This should attempt a utimes ++ call for the user specified by CRED on locked node NP, to change ++ the atime to ATIME and the mtime to MTIME. If ATIME or MTIME is ++ null, then set to the current time. */ ++error_t ++netfs_attempt_utimes (struct iouser *cred, struct node *np, ++ struct timespec *atime, struct timespec *mtime) ++{ ++ error_t err = fshelp_isowner (&np->nn_stat, cred); ++ int flags = TOUCH_CTIME; ++ ++ if (! err) ++ { ++ if (mtime) ++ { ++ np->nn_stat.st_mtime = mtime->tv_sec; ++ np->nn_stat.st_mtime_usec = mtime->tv_nsec / 1000; ++ } ++ else ++ flags |= TOUCH_MTIME; ++ ++ if (atime) ++ { ++ np->nn_stat.st_atime = atime->tv_sec; ++ np->nn_stat.st_atime_usec = atime->tv_nsec / 1000; ++ } ++ else ++ flags |= TOUCH_ATIME; ++ ++ fshelp_touch (&np->nn_stat, flags, console_maptime); ++ } ++ return err; ++ ++} ++ ++ ++/* The user must define this function. This should attempt to set the ++ size of the locked file NP (for user CRED) to SIZE bytes long. */ ++error_t ++netfs_attempt_set_size (struct iouser *cred, struct node *np, ++ loff_t size) ++{ ++ return EOPNOTSUPP; ++} ++ ++/* The user must define this function. This should attempt to fetch ++ filesystem status information for the remote filesystem, for the ++ user CRED. NP is locked. */ ++error_t ++netfs_attempt_statfs (struct iouser *cred, struct node *np, ++ fsys_statfsbuf_t *st) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. This should sync the locked ++ file NP completely to disk, for the user CRED. If WAIT is set, ++ return only after the sync is completely finished. */ ++error_t ++netfs_attempt_sync (struct iouser *cred, struct node *np, ++ int wait) ++{ ++ return 0; ++} ++ ++ ++/* The user must define this function. This should sync the entire ++ remote filesystem. If WAIT is set, return only after the sync is ++ completely finished. */ ++error_t ++netfs_attempt_syncfs (struct iouser *cred, int wait) ++{ ++ return 0; ++} ++ ++ ++/* The user must define this function. Lookup NAME in DIR (which is ++ locked) for USER; set *NP to the found name upon return. If the ++ name was not found, then return ENOENT. On any error, clear *NP. ++ (*NP, if found, should be locked and a reference to it generated. ++ This call should unlock DIR no matter what.) */ ++error_t ++netfs_attempt_lookup (struct iouser *user, struct node *dir, ++ char *name, struct node **node) ++{ ++ error_t err; ++ consnode_t cn; ++ ++ *node = 0; ++ err = fshelp_access (&dir->nn_stat, S_IEXEC, user); ++ if (err) ++ goto out; ++ ++ if (strcmp (name, ".") == 0) ++ { ++ /* Current directory -- just add an additional reference to DIR ++ and return it. */ ++ netfs_nref (dir); ++ *node = dir; ++ goto out; ++ } ++ ++ if (strcmp (name, "..") == 0) ++ { ++ err = EAGAIN; ++ goto out; ++ } ++ ++ for (cn = node_list; cn; cn = cn->next) ++ if (!strcmp (name, cn->name)) ++ { ++ if (cn->node == NULL) ++ { ++ struct netnode *nn = calloc (1, sizeof *nn); ++ if (nn == NULL) ++ { ++ err = ENOMEM; ++ goto out; ++ } ++ ++ *node = netfs_make_node (nn); ++ ++ nn->node = cn; ++ (*node)->nn_stat = netfs_root_node->nn_stat; ++ (*node)->nn_stat.st_mode = S_IFCHR | (netfs_root_node->nn_stat.st_mode & ~S_IFMT & ~S_ITRANS); ++ (*node)->nn_stat.st_size = 0; ++ cn->node = *node; ++ goto out; ++ } ++ else ++ { ++ *node = cn->node; ++ ++ netfs_nref (*node); ++ goto out; ++ } ++ } ++ ++ err = ENOENT; ++ ++ out: ++ mutex_unlock (&dir->lock); ++ if (err) ++ *node = 0; ++ else ++ mutex_lock (&(*node)->lock); ++ ++ if (!err && (*node)->nn->node->open) ++ (*node)->nn->node->open (); ++ ++ return err; ++} ++ ++ ++error_t ++netfs_S_io_seek (struct protid *user, off_t offset, ++ int whence, off_t *newoffset) ++{ ++ /* XXX: Will all nodes be device nodes? */ ++ if (!user) ++ return EOPNOTSUPP; ++ else ++ return ESPIPE; ++} ++ ++ ++error_t ++netfs_S_io_select (struct protid *user, mach_port_t reply, ++ mach_msg_type_name_t replytype, int *type) ++{ ++ struct node *np; ++ ++ if (!user) ++ return EOPNOTSUPP; ++ ++ np = user->po->np; ++ ++ if (np->nn->node->select) ++ return np->nn->node->select (user, reply, replytype, type); ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. Delete NAME in DIR (which is ++ locked) for USER. */ ++error_t ++netfs_attempt_unlink (struct iouser *user, struct node *dir, ++ char *name) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. Attempt to rename the ++ directory FROMDIR to TODIR. Note that neither of the specific nodes ++ are locked. */ ++error_t ++netfs_attempt_rename (struct iouser *user, struct node *fromdir, ++ char *fromname, struct node *todir, ++ char *toname, int excl) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. Attempt to create a new ++ directory named NAME in DIR (which is locked) for USER with mode ++ MODE. */ ++error_t ++netfs_attempt_mkdir (struct iouser *user, struct node *dir, ++ char *name, mode_t mode) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. Attempt to remove directory ++ named NAME in DIR (which is locked) for USER. */ ++error_t ++netfs_attempt_rmdir (struct iouser *user, ++ struct node *dir, char *name) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. Create a link in DIR with name ++ NAME to FILE for USER. Note that neither DIR nor FILE are ++ locked. If EXCL is set, do not delete the target. Return EEXIST if ++ NAME is already found in DIR. */ ++error_t ++netfs_attempt_link (struct iouser *user, struct node *dir, ++ struct node *file, char *name, int excl) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. Attempt to create an anonymous ++ file related to DIR (which is locked) for USER with MODE. Set *NP ++ to the returned file upon success. No matter what, unlock DIR. */ ++error_t ++netfs_attempt_mkfile (struct iouser *user, struct node *dir, ++ mode_t mode, struct node **np) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. Attempt to create a file named ++ NAME in DIR (which is locked) for USER with MODE. Set *NP to the ++ new node upon return. On any error, clear *NP. *NP should be ++ locked on success; no matter what, unlock DIR before returning. */ ++error_t ++netfs_attempt_create_file (struct iouser *user, struct node *dir, ++ char *name, mode_t mode, struct node **np) ++{ ++ *np = 0; ++ mutex_unlock (&dir->lock); ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. Read the contents of locked ++ node NP (a symlink), for USER, into BUF. */ ++error_t ++netfs_attempt_readlink (struct iouser *user, struct node *np, ++ char *buf) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. Locked node NP is being opened ++ by USER, with FLAGS. NEWNODE is nonzero if we just created this ++ node. Return an error if we should not permit the open to complete ++ because of a permission restriction. */ ++error_t ++netfs_check_open_permissions (struct iouser *user, struct node *np, ++ int flags, int newnode) ++{ ++ error_t err = 0; ++ ++ if (flags & O_READ) ++ err = fshelp_access (&np->nn_stat, S_IREAD, user); ++ if (!err && (flags & O_WRITE)) ++ err = fshelp_access (&np->nn_stat, S_IWRITE, user); ++ if (!err && (flags & O_EXEC)) ++ err = fshelp_access (&np->nn_stat, S_IEXEC, user); ++ return err; ++ ++} ++ ++ ++/* This function will never be called. It is only used when a node is ++ a symlink or by io_read, which is overridden. */ ++error_t ++netfs_attempt_read (struct iouser *cred, struct node *np, ++ loff_t offset, size_t *len, void *data) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++/* This function will never be called. It is only called from ++ io_write, which is overridden. */ ++error_t ++netfs_attempt_write (struct iouser *cred, struct node *np, ++ loff_t offset, size_t *len, void *data) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++error_t ++netfs_S_io_read (struct protid *user, ++ char **data, ++ mach_msg_type_number_t *datalen, ++ off_t offset, ++ mach_msg_type_number_t amount) ++{ ++ struct node *np; ++ ++ if (!user) ++ return EOPNOTSUPP; ++ np = user->po->np; ++ ++ if (np->nn->node->read) ++ return np->nn->node->read (user, data, datalen, offset, amount); ++ return EOPNOTSUPP; ++} ++ ++ ++error_t ++netfs_S_io_write (struct protid *user, ++ char *data, ++ mach_msg_type_number_t datalen, ++ off_t offset, ++ mach_msg_type_number_t *amount) ++{ ++ struct node *np; ++ ++ if (!user) ++ return EOPNOTSUPP; ++ ++ np = user->po->np; ++ if (np->nn->node->read) ++ return np->nn->node->write (user, data, datalen, offset, amount); ++ return EOPNOTSUPP; ++} ++ ++ ++/* The user must define this function. Return the valid access ++ types (bitwise OR of O_READ, O_WRITE, and O_EXEC) in *TYPES for ++ locked file NP and user CRED. */ ++error_t ++netfs_report_access (struct iouser *cred, struct node *np, ++ int *types) ++{ ++ *types = 0; ++ if (fshelp_access (&np->nn_stat, S_IREAD, cred) == 0) ++ *types |= O_READ; ++ if (fshelp_access (&np->nn_stat, S_IWRITE, cred) == 0) ++ *types |= O_WRITE; ++ if (fshelp_access (&np->nn_stat, S_IEXEC, cred) == 0) ++ *types |= O_EXEC; ++ return 0; ++ ++} ++ ++/* The user must define this function. Node NP has no more references; ++ free all its associated storage. */ ++void netfs_node_norefs (struct node *np) ++ ++{ ++ if (np->nn->node->close) ++ np->nn->node->close (); ++ np->nn->node->node = 0; ++ ++ spin_unlock (&netfs_node_refcnt_lock); ++ free (np->nn); ++ free (np); ++} ++ ++ ++/* Returned directory entries are aligned to blocks this many bytes long. ++ Must be a power of two. */ ++#define DIRENT_ALIGN 4 ++#define DIRENT_NAME_OFFS offsetof (struct dirent, d_name) ++/* Length is structure before the name + the name + '\0', all ++ padded to a four-byte alignment. */ ++#define DIRENT_LEN(name_len) \ ++ ((DIRENT_NAME_OFFS + (name_len) + 1 + (DIRENT_ALIGN - 1)) \ ++ & ~(DIRENT_ALIGN - 1)) ++ ++/* The user must define this function. Fill the array *DATA of size ++ BUFSIZE with up to NENTRIES dirents from DIR (which is locked) ++ starting with entry ENTRY for user CRED. The number of entries in ++ the array is stored in *AMT and the number of bytes in *DATACNT. ++ If the supplied buffer is not large enough to hold the data, it ++ should be grown. */ ++error_t ++netfs_get_dirents (struct iouser *cred, struct node *dir, ++ int first_entry, int num_entries, char **data, ++ mach_msg_type_number_t *data_len, ++ vm_size_t max_data_len, int *data_entries) ++{ ++ error_t err; ++ int count = 0; ++ size_t size = 0; /* Total size of our return block. */ ++ consnode_t cn = node_list; ++ consnode_t first_node; ++ ++ ++ /* Add the length of a directory entry for NAME to SIZE and return true, ++ unless it would overflow MAX_DATA_LEN or NUM_ENTRIES, in which case ++ return false. */ ++ int bump_size (const char *name) ++ { ++ if (num_entries == -1 || count < num_entries) ++ { ++ size_t new_size = size + DIRENT_LEN (strlen (name)); ++ if (max_data_len > 0 && new_size > max_data_len) ++ return 0; ++ size = new_size; ++ count++; ++ return 1; ++ } ++ else ++ return 0; ++ } ++ ++ if (dir != netfs_root_node) ++ return ENOTDIR; ++ ++ for (first_node = node_list, count = 2; ++ first_node && first_entry > count; ++ first_node = first_node->next); ++ count++; ++ ++ count = 0; ++ ++ /* Make space for the `.' and `..' entries. */ ++ if (first_entry == 0) ++ bump_size ("."); ++ if (first_entry <= 1) ++ bump_size (".."); ++ ++ for (cn = first_node; cn; cn = cn->next) ++ bump_size (cn->name); ++ ++ ++ /* Allocate it. */ ++ *data = mmap (0, size, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); ++ err = ((void *) *data == (void *) -1) ? errno : 0; ++ ++ if (! err) ++ /* Copy out the result. */ ++ { ++ char *p = *data; ++ ++ int add_dir_entry (const char *name, ino_t fileno, int type) ++ { ++ if (num_entries == -1 || count < num_entries) ++ { ++ struct dirent hdr; ++ size_t name_len = strlen (name); ++ size_t sz = DIRENT_LEN (name_len); ++ ++ if (sz > size) ++ return 0; ++ else ++ size -= sz; ++ ++ hdr.d_fileno = fileno; ++ hdr.d_reclen = sz; ++ hdr.d_type = type; ++ hdr.d_namlen = name_len; ++ ++ memcpy (p, &hdr, DIRENT_NAME_OFFS); ++ strcpy (p + DIRENT_NAME_OFFS, name); ++ p += sz; ++ ++ count++; ++ ++ return 1; ++ } ++ else ++ return 0; ++ } ++ ++ *data_len = size; ++ *data_entries = count; ++ ++ count = 0; ++ ++ /* Add `.' and `..' entries. */ ++ if (first_entry == 0) ++ add_dir_entry (".", 2, DT_DIR); ++ if (first_entry <= 1) ++ add_dir_entry ("..", 2, DT_DIR); ++ ++ /* Fill in the real directory entries. */ ++ for (cn = first_node; cn; cn = cn->next) ++ if (!add_dir_entry (cn->name, cn->id, DT_CHR)) ++ break; ++ } ++ ++ fshelp_touch (&dir->nn_stat, TOUCH_ATIME, console_maptime); ++ return err; ++} ++ ++ ++/* The user may define this function. For a full description, ++ see hurd/hurd_types.h. The default response indicates a network ++ store. If the supplied buffers are not large enough, they should ++ be grown as necessary. NP is locked. */ ++error_t ++netfs_file_get_storage_info (struct iouser *cred, ++ struct node *np, ++ mach_port_t **ports, ++ mach_msg_type_name_t *ports_type, ++ mach_msg_type_number_t *num_ports, ++ int **ints, ++ mach_msg_type_number_t *num_ints, ++ loff_t **offsets, ++ mach_msg_type_number_t *num_offsets, ++ char **data, ++ mach_msg_type_number_t *data_len) ++{ ++ return EOPNOTSUPP; ++} ++ ++ ++ ++static any_t ++console_client_translator (any_t unused) ++{ ++ error_t err; ++ ++ do ++ { ++ ports_manage_port_operations_multithread (netfs_port_bucket, ++ console_demuxer, ++ 1000 * 60 * 2, ++ 1000 * 60 * 10, ++ 0); ++ err = netfs_shutdown (0); ++ } ++ while (err); ++ return 0; ++} ++ ++error_t ++console_create_consnode (const char *name, consnode_t *cn) ++{ ++ *cn = malloc (sizeof (struct consnode)); ++ if (!*cn) ++ return ENOMEM; ++ ++ (*cn)->name = strdup (name); ++ if (!(*cn)->name) ++ { ++ free (cn); ++ return ENOMEM; ++ } ++ ++ return 0; ++} ++ ++ ++void ++console_destroy_consnode (consnode_t cn) ++{ ++ if (!cn) ++ return; ++ free (cn->name); ++ free (cn); ++} ++ ++ ++void ++console_register_consnode (consnode_t cn) ++{ ++ cn->node = 0; ++ cn->next = node_list; ++ node_list = cn; ++} ++ ++ ++void ++console_unregister_consnode (consnode_t cn) ++{ ++ if (!cn) ++ return; ++ ++ if (node_list == cn) ++ node_list = cn->next; ++ else ++ { ++ consnode_t prev = node_list; ++ ++ for (prev = node_list; prev->next != cn; prev = prev->next) ++ ; ++ ++ prev->next = cn->next; ++ } ++ ++ return 0; ++} ++ ++ ++error_t ++console_setup_node (char *path) ++{ ++ mach_port_t underlying; ++ mach_port_t bootstrap; ++ error_t err; ++ struct stat ul_stat; ++ file_t node; ++ struct port_info *newpi; ++ mach_port_t right; ++ ++ node = file_name_lookup (path, O_CREAT|O_NOTRANS, 0664); ++ if (node == MACH_PORT_NULL) ++ return errno; ++ ++ task_get_bootstrap_port (mach_task_self (), &bootstrap); ++ netfs_init (); ++ ++ /* Create the root node (some attributes initialized below). */ ++ netfs_root_node = netfs_make_node (0); ++ if (! netfs_root_node) ++ error (1, ENOMEM, "Cannot create root node"); ++ ++ err = maptime_map (0, 0, &console_maptime); ++ if (err) ++ error (1, err, "Cannot map time"); ++ ++ err = ports_create_port (netfs_control_class, netfs_port_bucket, sizeof (struct port_info), &newpi); ++ right = ports_get_send_right (newpi); ++ err = file_set_translator (node, 0, FS_TRANS_EXCL | FS_TRANS_SET, 0, 0, 0, ++ right, MACH_MSG_TYPE_COPY_SEND); ++ mach_port_deallocate (mach_task_self (), right); ++ underlying = node; ++ ++ err = io_stat (node, &ul_stat); ++ if (err) ++ error (1, err, "Cannot stat underlying node"); ++ ++ netfs_root_node->nn_stat.st_ino = 2; ++ netfs_root_node->nn_stat.st_mode |= S_IFDIR; ++ netfs_root_node->nn_stat.st_uid = ul_stat.st_uid; ++ netfs_root_node->nn_stat.st_gid = ul_stat.st_gid; ++ netfs_root_node->nn_stat.st_author = ul_stat.st_author; ++ netfs_root_node->nn_stat.st_mode = S_IFDIR | (ul_stat.st_mode & ~S_IFMT & ~S_ITRANS); ++ netfs_root_node->nn_stat.st_fsid = getpid (); ++ netfs_root_node->nn_stat.st_nlink = 1; ++ netfs_root_node->nn_stat.st_size = 0; ++ netfs_root_node->nn_stat.st_fstype = FSTYPE_MISC; ++ ++ netfs_root_node->nn_translated = 0; ++ ++ /* If the underlying node isn't a directory, propagate read permission to ++ execute permission since we need that for lookups. */ ++ if (! S_ISDIR (ul_stat.st_mode)) ++ { ++ if (ul_stat.st_mode & S_IRUSR) ++ netfs_root_node->nn_stat.st_mode |= S_IXUSR; ++ if (ul_stat.st_mode & S_IRGRP) ++ netfs_root_node->nn_stat.st_mode |= S_IXGRP; ++ if (ul_stat.st_mode & S_IROTH) ++ netfs_root_node->nn_stat.st_mode |= S_IXOTH; ++ } ++ ++ fshelp_touch (&netfs_root_node->nn_stat, TOUCH_ATIME|TOUCH_MTIME|TOUCH_CTIME, ++ console_maptime); ++ ++ cthread_detach (cthread_fork (console_client_translator, NULL)); ++ ++ return 0; ++} +diff -upN --exclude=CVS ../console-client.cvs/trans.h ./trans.h +--- console-client.cvs/trans.h 1970-01-01 00:00:00.000000000 +0000 ++++ console-client/trans.h 2004-07-27 05:40:11.000000000 +0000 +@@ -0,0 +1,68 @@ ++/* trans.h -- Control a translator node for the repeaters. ++ Copyright (C) 2004 Free Software Foundation, Inc. ++ Written by Marco Gerards. ++ ++ This program 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. ++ ++ This program 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-1307 USA */ ++ ++#include <hurd/netfs.h> ++ ++struct consnode ++{ ++ /* The filename of the node. */ ++ char *name; ++ ++ /* The id of the node. */ ++ int id; ++ ++ /* Cached if the node is already opened. */ ++ struct node *node; ++ ++ /* Read data from a node. This is exactly the same as io_read ++ does. */ ++ error_t (*read) (struct protid *user, char **data, ++ mach_msg_type_number_t *datalen, off_t offset, ++ mach_msg_type_number_t amount); ++ ++ /* Read data to a node. This is exactly the same as io_write ++ does. */ ++ error_t (*write) (struct protid *user, char *data, ++ mach_msg_type_number_t datalen, off_t offset, ++ mach_msg_type_number_t *amount); ++ ++ /* This is exactly the same as io_select does. */ ++ error_t (*select) (struct protid *user, mach_port_t reply, ++ mach_msg_type_name_t replytype, int *type); ++ ++ /* Called when the node is opened. */ ++ void (*open) (void); ++ ++ /* Called when the node is closed. */ ++ void (*close) (void); ++ ++ /* The demuxer used for this node. */ ++ int (*demuxer) (mach_msg_header_t *inp, mach_msg_header_t *outp); ++ ++ struct consnode *next; ++}; ++ ++typedef struct consnode *consnode_t; ++ ++void console_register_consnode (consnode_t cn); ++ ++void console_unregister_consnode (consnode_t node); ++ ++error_t console_create_consnode (const char *name, consnode_t *cn); ++ ++void console_destroy_consnode (consnode_t cn); +diff -upN --exclude=CVS ../console-client.cvs/vga.c ./vga.c +--- console-client.cvs/vga.c 2004-03-21 19:57:00.000000000 +0000 ++++ console-client/vga.c 2004-04-02 07:16:38.000000000 +0000 +@@ -93,6 +93,15 @@ struct refchr + }; + + ++typedef struct vga_mousecursor ++{ ++ float posx; ++ float posy; ++ char oldcolor; ++ int visible; ++ int enabled; ++} vga_mousecursor_t; ++ + struct vga_display + { + /* The VGA font for this display. */ +@@ -110,6 +119,9 @@ struct vga_display + conchar_attr_t cur_conchar_attr; + char cur_attr; + ++ /* The state of the mouse cursor. */ ++ vga_mousecursor_t mousecursor; ++ + /* Remember for each cell on the display the glyph written to it and + the colors (in the upper byte) assigned. 0 means unassigned. */ + +@@ -151,6 +163,37 @@ vga_display_flash (void *handle) + return 0; + } + ++ ++static void ++hide_mousecursor (struct vga_display *disp) ++{ ++ char *oldpos = vga_videomem + 2 * ((int) disp->mousecursor.posy * disp->width ++ + (int) disp->mousecursor.posx) + 1; ++ ++ if (!disp->mousecursor.visible) ++ return; ++ ++ /* First remove the old cursor. */ ++ *oldpos = disp->mousecursor.oldcolor; ++ disp->mousecursor.visible = 0; ++} ++ ++ ++static void ++draw_mousecursor (struct vga_display *disp) ++{ ++ char *newpos = vga_videomem + 2 * ((int) disp->mousecursor.posy * disp->width ++ + (int) disp->mousecursor.posx) + 1; ++ ++ if (disp->mousecursor.visible) ++ return; ++ ++ /* Draw the new cursor. */ ++ disp->mousecursor.oldcolor = *newpos; ++ *newpos = (127) ^ *newpos; ++ ++ disp->mousecursor.visible = 1; ++} + + + static const char doc[] = "VGA Driver"; +@@ -408,6 +451,8 @@ vga_display_scroll (void *handle, int de + int count = abs(delta) * disp->width; + int i; + struct refchr *refpos; ++ ++ hide_mousecursor (disp); + + /* XXX: If the virtual console is bigger than the physical console it is + impossible to scroll because the data to scroll is not in memory. */ +@@ -595,6 +640,7 @@ vga_display_write (void *handle, conchar + struct vga_display *disp = handle; + char *pos; + struct refchr *refpos = &disp->refmatrix[row][col]; ++ char *mouse_cursor_pos; + + /* The starting column is outside the physical screen. */ + if (disp->width < current_width && col >= disp->width) +@@ -607,6 +653,9 @@ vga_display_write (void *handle, conchar + } + + pos = vga_videomem + 2 * (row * disp->width + col); ++ mouse_cursor_pos = vga_videomem + 2 ++ * ((int) disp->mousecursor.posy ++ * disp->width + (int) disp->mousecursor.posx) + 1; + + /* Although all references to the current fgcol or bgcol could have + been released here, for example due to a scroll operation, we +@@ -662,6 +711,10 @@ vga_display_write (void *handle, conchar + } + + *(pos++) = charval & 0xff; ++ ++ if (pos == mouse_cursor_pos) ++ disp->mousecursor.visible = 0; ++ + *(pos++) = disp->cur_attr + | (disp->df_size == 512 ? (charval >> 5) & 0x8 : 0); + +@@ -700,6 +753,57 @@ vga_set_dimension (void *handle, unsigne + return 0; + } + ++ ++static error_t ++vga_display_update (void *handle) ++{ ++ struct vga_display *disp = handle; ++ ++ if (disp->mousecursor.enabled) ++ draw_mousecursor (disp); ++ ++ return 0; ++} ++ ++ ++static error_t ++vga_set_mousecursor_pos (void *handle, float x, float y) ++{ ++ struct vga_display *disp = handle; ++ ++ /* If the mouse did not move from the character position, don't ++ bother about updating the cursor position. */ ++ if (disp->mousecursor.visible && x == (int) disp->mousecursor.posx ++ && y == (int) disp->mousecursor.posy) ++ return 0; ++ ++ hide_mousecursor (disp); ++ ++ disp->mousecursor.posx = x; ++ disp->mousecursor.posy = y; ++ ++ if (disp->mousecursor.enabled) ++ draw_mousecursor (disp); ++ ++ return 0; ++} ++ ++ ++static error_t ++vga_set_mousecursor_status (void *handle, int status) ++{ ++ struct vga_display *disp = handle; ++ ++ disp->mousecursor.enabled = status; ++ if (!status) ++ hide_mousecursor (disp); ++ else ++ draw_mousecursor (disp); ++ ++ return 0; ++} ++ ++ + + struct driver_ops driver_vga_ops = + { +@@ -715,8 +819,10 @@ static struct display_ops vga_display_op + vga_display_scroll, + vga_display_clear, + vga_display_write, +- NULL, ++ vga_display_update, + vga_display_flash, + NULL, +- vga_set_dimension ++ vga_set_dimension, ++ vga_set_mousecursor_pos, ++ vga_set_mousecursor_status + }; diff --git a/debian/patches/console_switch3.patch b/debian/patches/console_switch3.patch deleted file mode 100644 index 13c090d3..00000000 --- a/debian/patches/console_switch3.patch +++ /dev/null @@ -1,839 +0,0 @@ -2004-04-01 Marco Gerards <metgerards@student.han.nl> - - * Makefile (LCLHDRS): Add inputdev.h. - (pc_kbd.so.$(hurd-version)): Add kdioctlServer.o kbd-repeat.c. - (pc_kbd-LDLIBS): New variable. - * console.c (saved_id): New variable. - (saved_cons): Likewise. - (console_switch_away): New function. - (console_switch_back): Likewise. - * input.h (console_switch_away): New prototype. - (console_switch_back): Likewise. - * pc-kbd.c: Include "inputdev.h" and <argp.h>. - (repeater_node): New variable. - (doc): Likewise. - (options): Likewise. - (argp): Likewise. - (parse_opt): New function. - (pc_kbd_init): Parse the arguments. - (gnumach_v1_input_next): Pass the keyboard event to the repeater - if the repeater is active. - (pc_kbd_init): Parse the `--repeat' argument. - (pc_kbd_start): If a repeater node was specified, start it as a - translator on the given node. - (kev_type, mouse_motion, mouse_motion, Scancode, m_deltaX) - (m_deltaY, MOUSE_LEFT, MOUSE_MIDDLE, MOUSE_RIGHT, MOUSE_MOTION) - (MOUSE_EVENT, IOCPARM_MASK, IOC_OUT, IOC_IN, _IOC, _IOR, _IOW) - (KDSKBDMODE, KB_EVENT, KB_ASCII, KDFKBDTYPE, KB_VANILLAKB) - (KB_EVENT, KBSETLEDS): Move from here... - * inputdev.h: ... to here. New file. - * kbd-repeat.c: New file. - - - -diff -upN ../../console-client/Makefile ./Makefile ---- ../../console-client/Makefile 2002-09-17 14:26:10.000000000 +0200 -+++ console-client/Makefile 2004-03-28 10:53:06.000000000 +0200 -@@ -21,7 +21,7 @@ makemode := utility - target = console - SRCS = console.c timer.c driver.c - LCLHDRS = timer.h driver.h display.h input.h bell.h \ -- unicode.h bdf.h \ -+ unicode.h bdf.h inputdev.h \ - vga-dynafont.h vga-dynacolor.h vga-hw.h vga.h - - OBJS = $(filter-out %.sh,$(SRCS:.c=.o)) -@@ -45,7 +45,9 @@ modules = vga pc_kbd generic_speaker - - vga.so.$(hurd-version): $(patsubst %.c,%_pic.o,bdf.c vga-dynafont.c \ - vga-dynacolor.c vga-support.c vga.c) --pc_kbd.so.$(hurd-version): $(patsubst %.c,%_pic.o,pc-kbd.c) -+pc_kbd.so.$(hurd-version): $(patsubst %.c,%_pic.o,pc-kbd.c kdioctlServer.o kbd-repeat.c) -+pc_kbd-LDLIBS = -ltrivfs -+ - generic_speaker.so.$(hurd-version): $(patsubst %.c,%_pic.o,generic-speaker.c) - - ifneq ($(LIBNCURSESW),) -diff -upN ../../console-client/console.c ./console.c ---- ../../console-client/console.c 2004-03-24 23:53:17.000000000 +0100 -+++ console-client/console.c 2004-03-28 11:10:42.000000000 +0200 -@@ -47,6 +47,12 @@ static struct mutex global_lock; - displayed. */ - static vcons_t active_vcons = NULL; - -+/* Contains the VT id when switched away. */ -+static int saved_id = 0; -+ -+/* The console, used to switch back. */ -+static cons_t saved_cons; -+ - - /* Callbacks for input source drivers. */ - -@@ -94,6 +100,53 @@ console_switch (int id, int delta) - } - - -+/* Switch away from the console an external use of the console like -+ XFree. */ -+void -+console_switch_away (void) -+{ -+ mutex_lock (&global_lock); -+ saved_id = active_vcons->id; -+ saved_cons = active_vcons->cons; -+ cons_vcons_close (active_vcons); -+ active_vcons = NULL; -+ mutex_unlock (&global_lock); -+} -+ -+/* Switch back to the console client from an external user of the -+ console like XFree. */ -+void -+console_switch_back (void) -+{ -+ vcons_list_t conslist; -+ mutex_lock (&global_lock); -+ if (saved_cons) -+ { -+ error_t err; -+ -+ err = cons_lookup (saved_cons, saved_id, 1, &conslist); -+ if (err) -+ { -+ mutex_unlock (&global_lock); -+ return; -+ } -+ -+ err = cons_vcons_open (saved_cons, conslist, &active_vcons); -+ if (err) -+ { -+ mutex_unlock (&global_lock); -+ return; -+ } -+ -+ conslist->vcons = active_vcons; -+ saved_cons = NULL; -+ mutex_unlock (&active_vcons->lock); -+ } -+ mutex_unlock (&global_lock); -+} -+ -+ -+ - /* Enter SIZE bytes from the buffer BUF into the currently active - console. This can be called by the input driver at any time. */ - error_t -diff -upN ../../console-client/input.h ./input.h ---- ../../console-client/input.h 2002-09-17 14:26:10.000000000 +0200 -+++ console-client/input.h 2004-03-28 10:53:13.000000000 +0200 -@@ -1,5 +1,5 @@ - /* input.h - The interface to and for an input driver. -- Copyright (C) 2002 Free Software Foundation, Inc. -+ Copyright (C) 2002, 2004 Free Software Foundation, Inc. - Written by Marcus Brinkmann. - - This file is part of the GNU Hurd. -@@ -65,6 +65,15 @@ void console_error (const wchar_t *const - /* Exit the console client. Does not return. */ - void console_exit (void); - -+/* Switch away from the console an external use of the console like -+ XFree. */ -+void console_switch_away (void); -+ -+/* Switch back to the console client from an external user of the -+ console like XFree. */ -+void console_switch_back (void); -+ -+ - #if QUAERENDO_INVENIETIS - /* Do not use, do not remove. */ - void console_deprecated (int key); -diff -upN ../../console-client/inputdev.h ./inputdev.h ---- ../../console-client/inputdev.h 1970-01-01 01:00:00.000000000 +0100 -+++ console-client/inputdev.h 2004-03-28 10:53:13.000000000 +0200 -@@ -0,0 +1,122 @@ -+/* inputdev.h - Interfaces for the PC pc-kbd and mouse input drivers. -+ Copyright (C) 2002, 2004 Free Software Foundation, Inc. -+ Written by Marco Gerards. -+ -+ 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. */ -+ -+/* This gross stuff is cut & pasted from Mach sources, as Mach doesn't -+ export the interface we are using here. */ -+ -+/* -+ * Mach Operating System -+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University -+ * All Rights Reserved. -+ * -+ * Permission to use, copy, modify and distribute this software and its -+ * documentation is hereby granted, provided that both the copyright -+ * notice and this permission notice appear in all copies of the -+ * software, derivative works or modified versions, and any portions -+ * thereof, and that both notices appear in supporting documentation. -+ * -+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" -+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR -+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. -+ * -+ * Carnegie Mellon requests users of this software to return to -+ * -+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU -+ * School of Computer Science -+ * Carnegie Mellon University -+ * Pittsburgh PA 15213-3890 -+ * -+ * any improvements or extensions that they make and grant Carnegie Mellon -+ * the rights to redistribute these changes. -+ */ -+ -+#ifndef _INPUTDEV_H_ -+#define _INPUTDEV_H_ 1 -+ -+typedef u_short kev_type; /* kd event type */ -+ -+/* (used for event records) */ -+struct mouse_motion { -+ short mm_deltaX; /* units? */ -+ short mm_deltaY; -+}; -+typedef u_char Scancode; -+ -+typedef struct { -+ kev_type type; /* see below */ -+ struct timeval time; /* timestamp */ -+ union { /* value associated with event */ -+ boolean_t up; /* MOUSE_LEFT .. MOUSE_RIGHT */ -+ Scancode sc; /* KEYBD_EVENT */ -+ struct mouse_motion mmotion; /* MOUSE_MOTION */ -+ } value; -+} kd_event; -+#define m_deltaX mmotion.mm_deltaX -+#define m_deltaY mmotion.mm_deltaY -+ -+/* -+ * kd_event ID's. -+ */ -+#define MOUSE_LEFT 1 /* mouse left button up/down */ -+#define MOUSE_MIDDLE 2 -+#define MOUSE_RIGHT 3 -+#define MOUSE_MOTION 4 /* mouse motion */ -+#define KEYBD_EVENT 5 /* key up/down */ -+ -+ -+#define IOCPARM_MASK 0x1fff /* parameter length, at most 13 bits */ -+#define IOC_OUT 0x40000000 /* copy out parameters */ -+#define IOC_IN 0x80000000U /* copy in parameters */ -+ -+#ifndef _IOC -+#define _IOC(inout,group,num,len) \ -+ (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num)) -+#endif -+#ifndef _IOR -+#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t)) -+#endif -+#ifndef _IOW -+#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t)) -+#endif -+ -+#define KDSKBDMODE _IOW('K', 1, int) /* set keyboard mode */ -+#define KB_EVENT 1 -+#define KB_ASCII 2 -+ -+#define KDGKBDTYPE _IOR('K', 2, int) /* get keyboard type */ -+#define KB_VANILLAKB 0 -+ -+#define KDSETLEDS _IOW('K', 5, int) /* set keyboard leds */ -+ -+ -+/* End of Mach code. */ -+ -+ -+/* Amount of times the device was opened. Normally this translator -+ should be only opened once. */ -+extern int kbd_repeater_opened; -+ -+/* Place the keyboard event KEY in the keyboard buffer. */ -+void repeat_key (kd_event *key); -+ -+/* Set the repeater translator on the node PATH. */ -+error_t setrepeater (const char *path); -+ -+#endif /* _INPUTDEV_H_ */ -diff -upN ../../console-client/kbd-repeat.c ./kbd-repeat.c ---- ../../console-client/kbd-repeat.c 1970-01-01 01:00:00.000000000 +0100 -+++ console-client/kbd-repeat.c 2004-04-01 03:22:46.000000000 +0200 -@@ -0,0 +1,357 @@ -+/* kbd-repeat.c - Keyboard repeater. -+ Copyright (C) 2004 Free Software Foundation, Inc. -+ Written by Marco Gerards. -+ -+ 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 <hurd/trivfs.h> -+#include <stdlib.h> -+#include <error.h> -+#include <string.h> -+#include <fcntl.h> -+#include <sys/mman.h> -+ -+#include "kdioctl_S.h" -+#include "inputdev.h" -+#include "input.h" -+ -+/* The amount of keyboard events that can be stored in the keyboard buffer. */ -+#define KBDEVTBUFSZ 20 -+ -+/* The size of the keyboard buffer in bytes. */ -+#define KBDBUFSZ (KBDEVTBUFSZ * sizeof (kd_event)) -+ -+/* Return the position of X in the buffer. */ -+#define KBDBUF_POS(x) ((x) % KBDBUFSZ) -+ -+/* The keyboard buffer. */ -+struct kbdbuf -+{ -+ char keybuffer[KBDBUFSZ]; -+ int pos; -+ size_t size; -+ struct condition readcond; -+ struct condition writecond; -+} kbdbuf; -+ -+/* Wakeup for select */ -+static struct condition select_alert; -+ -+/* The global lock */ -+static struct mutex global_lock; -+ -+/* Bucket to handle the keyboard RPCs. */ -+static struct port_bucket *kbdbucket; -+ -+/* Amount of times the device was opened. Normally this translator -+ should be only opened once. */ -+int kbd_repeater_opened; -+ -+ -+static int -+kdioctl_demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) -+{ -+ extern int kdioctl_server (mach_msg_header_t *inp, mach_msg_header_t *outp); -+ return kdioctl_server (inp, outp) || trivfs_demuxer (inp, outp); -+} -+ -+ -+/* Place the keyboard event KEY in the keyboard buffer. */ -+void -+repeat_key (kd_event *key) -+{ -+ kd_event *ev; -+ -+ mutex_lock (&global_lock); -+ while (kbdbuf.size + sizeof (kd_event) > KBDBUFSZ) -+ { -+ /* The input buffer is full, wait until there is some space. */ -+ if (hurd_condition_wait (&kbdbuf.writecond, &global_lock)) -+ { -+ mutex_unlock (&global_lock); -+ /* Interrupt, silently continue. */ -+ } -+ } -+ ev = (kd_event *) &kbdbuf.keybuffer[KBDBUF_POS (kbdbuf.pos -+ + kbdbuf.size)]; -+ kbdbuf.size += sizeof (kd_event); -+ memcpy (ev, key, sizeof (kd_event)); -+ condition_broadcast (&kbdbuf.readcond); -+ mutex_unlock (&global_lock); -+} -+ -+ -+/* Thread to handle operations on the kbdbucket. */ -+static any_t -+repeater_translator_function (void *arg) -+{ -+ ports_manage_port_operations_one_thread (kbdbucket, kdioctl_demuxer, 0); -+ return 0; -+} -+ -+ -+/* Set the repeater translator on the node PATH. */ -+error_t -+setrepeater (const char *path) -+{ -+ error_t err; -+ struct trivfs_control *control; -+ file_t node; -+ -+ kbdbucket = ports_create_bucket (); -+ -+ node = file_name_lookup (path, O_CREAT|O_NOTRANS, 0664); -+ if (node == MACH_PORT_NULL) -+ return errno; -+ -+ err = trivfs_create_control (node, 0, kbdbucket, 0, kbdbucket, &control); -+ if (! err) -+ { -+ mach_port_t right = ports_get_send_right (control); -+ err = file_set_translator (node, 0, FS_TRANS_EXCL | FS_TRANS_SET, 0, 0, 0, -+ right, MACH_MSG_TYPE_COPY_SEND); -+ mach_port_deallocate (mach_task_self (), right); -+ } -+ else -+ return err; -+ -+ mutex_init (&global_lock); -+ -+ condition_init (&kbdbuf.readcond); -+ condition_init (&kbdbuf.writecond); -+ -+ condition_init (&select_alert); -+ condition_implies (&kbdbuf.readcond, &select_alert); -+ -+ cthread_detach (cthread_fork (repeater_translator_function, 0)); -+ -+ return 0; -+} -+ -+ -+/* Just act like the Mach kbd device. */ -+int trivfs_fstype = FSTYPE_DEV; -+int trivfs_fsid = 0; -+ -+int trivfs_allow_open = O_READ; -+ -+int trivfs_support_read = 1; -+int trivfs_support_write = 0; -+int trivfs_support_exec = 0; -+ -+error_t -+trivfs_S_io_select (struct trivfs_protid *cred, mach_port_t reply, -+ mach_msg_type_name_t reply_type, int *type) -+{ -+ int available = 0; -+ -+ if (!cred) -+ return EOPNOTSUPP; -+ -+ if (*type & ~SELECT_READ) -+ return EINVAL; -+ -+ if (*type == 0) -+ return 0; -+ -+ available = 0; -+ -+ mutex_lock (&global_lock); -+ while (1) -+ { -+ if (available && kbdbuf.size > 0) -+ { -+ *type = SELECT_READ; -+ mutex_unlock (&global_lock); -+ -+ return 0; -+ } -+ -+ if (cred->po->openmodes & O_NONBLOCK) -+ { -+ mutex_unlock (&global_lock); -+ -+ return EWOULDBLOCK; -+ } -+ -+ ports_interrupt_self_on_port_death (cred, reply); -+ if (hurd_condition_wait (&select_alert, &global_lock)) -+ { -+ *type = 0; -+ mutex_unlock (&global_lock); -+ -+ return EINTR; -+ } -+ } -+} -+ -+ -+void -+trivfs_modify_stat (struct trivfs_protid *cred, io_statbuf_t *st) -+{ -+ /* Mark the node as a read-only plain file. */ -+ st->st_mode &= ~(S_IFMT); -+ st->st_mode |= (S_IRUSR | S_IFCHR); -+ -+ st->st_size = 0; -+ st->st_blocks = 0; -+ -+} -+ -+ -+/* No one wants this. Use the console client to terminate the console -+ client or send a signal. */ -+error_t -+trivfs_goaway (struct trivfs_control *cntl, int flags) -+{ -+ return EOPNOTSUPP; -+} -+ -+ -+static error_t -+open_hook (struct trivfs_peropen *peropen) -+{ -+ /* Make sure the console does not access the hardware anymore. */ -+ if (! kbd_repeater_opened) -+ console_switch_away (); -+ kbd_repeater_opened++; -+ -+ return 0; -+} -+ -+ -+static void -+close_hook (struct trivfs_peropen *peropen) -+{ -+ kbd_repeater_opened--; -+ -+ /* Allow the console to access the hardware again. */ -+ if (! kbd_repeater_opened) -+ { -+ console_switch_back (); -+ kbdbuf.pos = 0; -+ kbdbuf.size = 0; -+ -+ } -+} -+ -+ -+/* Read data from an IO object. If offset is -1, read from the object -+ maintained file pointer. If the object is not seekable, offset is -+ ignored. The amount desired to be read is in AMOUNT. */ -+error_t -+trivfs_S_io_read (struct trivfs_protid *cred, -+ mach_port_t reply, mach_msg_type_name_t reply_type, -+ char **data, mach_msg_type_number_t *data_len, -+ loff_t offs, mach_msg_type_number_t amount) -+{ -+ /* Deny access if they have bad credentials. */ -+ if (! cred) -+ return EOPNOTSUPP; -+ else if (! (cred->po->openmodes & O_READ)) -+ return EBADF; -+ -+ -+ mutex_lock (&global_lock); -+ while (amount > kbdbuf.size) -+ { -+ if (cred->po->openmodes & O_NONBLOCK && amount > kbdbuf.size) -+ { -+ mutex_unlock (&global_lock); -+ return EWOULDBLOCK; -+ } -+ -+ if (hurd_condition_wait (&kbdbuf.readcond, &global_lock)) -+ { -+ mutex_unlock (&global_lock); -+ return EINTR; -+ } -+ } -+ -+ if (amount > 0) -+ { -+ char *keydata; -+ unsigned int i = 0; -+ -+ /* Allocate a buffer when this is required. */ -+ if (*data_len < amount) -+ { -+ *data = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0); -+ if (*data == MAP_FAILED) -+ { -+ mutex_unlock (&global_lock); -+ return ENOMEM; -+ } -+ } -+ -+ /* Copy the bytes to the user's buffer and remove them from the -+ keyboard buffer. */ -+ keydata = *data; -+ while (i != amount) -+ { -+ keydata[i++] = kbdbuf.keybuffer[kbdbuf.pos++]; -+ kbdbuf.pos = KBDBUF_POS (kbdbuf.pos); -+ } -+ kbdbuf.size -= amount; -+ condition_broadcast (&kbdbuf.writecond); -+ } -+ -+ *data_len = amount; -+ mutex_unlock (&global_lock); -+ -+ return 0; -+} -+ -+ -+/* Change current read/write offset */ -+error_t -+trivfs_S_io_seek (struct trivfs_protid *cred, -+ mach_port_t reply, mach_msg_type_name_t reply_type, -+ off_t offs, int whence, off_t *new_offs) -+{ -+ if (!cred) -+ return EOPNOTSUPP; -+ else -+ return ESPIPE; -+} -+ -+ -+/* If this variable is set, it is called every time a new peropen -+ structure is created and initialized. */ -+error_t (*trivfs_peropen_create_hook)(struct trivfs_peropen *) = open_hook; -+ -+/* If this variable is set, it is called every time a peropen structure -+ is about to be destroyed. */ -+void (*trivfs_peropen_destroy_hook) (struct trivfs_peropen *) = close_hook; -+ -+ -+/* Some RPC calls for controlling the keyboard. These calls are just -+ ignored and just exist to make XFree happy. */ -+ -+kern_return_t -+S_kdioctl_kdskbdmode (io_t port, int mode) -+{ -+ return 0; -+} -+ -+ -+kern_return_t -+S_kdioctl_kdgkbdmode (io_t port, int *mode) -+{ -+ return 0; -+} -diff -upN ../../console-client/pc-kbd.c ./pc-kbd.c ---- ../../console-client/pc-kbd.c 2004-02-02 22:25:10.000000000 +0100 -+++ console-client/pc-kbd.c 2004-03-28 11:35:46.000000000 +0200 -@@ -23,6 +23,7 @@ - #include <string.h> - #include <iconv.h> - #include <sys/mman.h> -+#include <argp.h> - - #include <device/device.h> - #include <cthreads.h> -@@ -31,6 +32,7 @@ - #include <hurd/cons.h> - - #include "driver.h" -+#include "inputdev.h" - - - /* The keyboard device in the kernel. */ -@@ -52,6 +54,10 @@ int gnumach_v1_compat; - /* Forward declaration. */ - static struct input_ops pc_kbd_ops; - -+ -+/* The node on which the repeater translator is set. */ -+static char *repeater_node; -+ - - /* A list of scan codes generated by the keyboard, in the set 2 encoding. */ - enum scancode -@@ -558,87 +564,6 @@ enum scancode sc_set1_to_set2_x1[] = - SC_X1_DEL - }; - -- --/* This gross stuff is cut & pasted from Mach sources, as Mach doesn't -- export the interface we are using here. */ -- --/* -- * Mach Operating System -- * Copyright (c) 1991,1990,1989 Carnegie Mellon University -- * All Rights Reserved. -- * -- * Permission to use, copy, modify and distribute this software and its -- * documentation is hereby granted, provided that both the copyright -- * notice and this permission notice appear in all copies of the -- * software, derivative works or modified versions, and any portions -- * thereof, and that both notices appear in supporting documentation. -- * -- * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" -- * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR -- * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. -- * -- * Carnegie Mellon requests users of this software to return to -- * -- * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU -- * School of Computer Science -- * Carnegie Mellon University -- * Pittsburgh PA 15213-3890 -- * -- * any improvements or extensions that they make and grant Carnegie Mellon -- * the rights to redistribute these changes. -- */ -- --typedef u_short kev_type; /* kd event type */ -- --/* (used for event records) */ --struct mouse_motion { -- short mm_deltaX; /* units? */ -- short mm_deltaY; --}; --typedef u_char Scancode; -- --typedef struct { -- kev_type type; /* see below */ -- struct timeval time; /* timestamp */ -- union { /* value associated with event */ -- boolean_t up; /* MOUSE_LEFT .. MOUSE_RIGHT */ -- Scancode sc; /* KEYBD_EVENT */ -- struct mouse_motion mmotion; /* MOUSE_MOTION */ -- } value; --} kd_event; --#define m_deltaX mmotion.mm_deltaX --#define m_deltaY mmotion.mm_deltaY -- --/* -- * kd_event ID's. -- */ --#define MOUSE_LEFT 1 /* mouse left button up/down */ --#define MOUSE_MIDDLE 2 --#define MOUSE_RIGHT 3 --#define MOUSE_MOTION 4 /* mouse motion */ --#define KEYBD_EVENT 5 /* key up/down */ -- -- --#define IOCPARM_MASK 0x1fff /* parameter length, at most 13 bits */ --#define IOC_OUT 0x40000000 /* copy out parameters */ --#define IOC_IN 0x80000000U /* copy in parameters */ --#define _IOC(inout,group,num,len) \ -- (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num)) --#define _IOR(g,n,t) _IOC(IOC_OUT, (g), (n), sizeof(t)) --#define _IOW(g,n,t) _IOC(IOC_IN, (g), (n), sizeof(t)) -- --#define KDSKBDMODE _IOW('K', 1, int) /* set keyboard mode */ --#define KB_EVENT 1 --#define KB_ASCII 2 -- --#define KDGKBDTYPE _IOR('K', 2, int) /* get keyboard type */ --#define KB_VANILLAKB 0 -- --#define KDSETLEDS _IOW('K', 5, int) /* set keyboard leds */ -- -- --/* End of Mach code. */ -- - static enum scancode - gnumach_v1_input_next () - { -@@ -658,6 +583,13 @@ gnumach_v1_input_next () - terminate. */ - if (err) - return 0; -+ -+ if (kbd_repeater_opened && data_buf.type == KEYBD_EVENT) -+ { -+ repeat_key (&data_buf); -+ data_buf.type = 0; -+ continue; -+ } - } - while (data_buf.type != KEYBD_EVENT); - -@@ -1088,10 +1020,56 @@ input_loop (any_t unused) - - - -+ -+ -+static const char doc[] = "PC Keyboard Driver"; -+ -+static const struct argp_option options[] = -+ { -+ {"repeat", 'r', "NODE", 0, "Set a repeater translator on NODE"}, -+ { 0 } -+ }; -+ -+static error_t -+parse_opt (int key, char *arg, struct argp_state *state) -+{ -+ int *pos = (int *) state->input; -+ -+ switch (key) -+ { -+ case 'r': -+ repeater_node = arg; -+ break; -+ -+ case ARGP_KEY_END: -+ break; -+ -+ default: -+ return ARGP_ERR_UNKNOWN; -+ } -+ -+ *pos = state->next; -+ return 0; -+} -+ -+static struct argp argp = {options, parse_opt, 0, doc}; -+ - /* Initialize the PC keyboard driver. */ - static error_t - pc_kbd_init (void **handle, int no_exit, int argc, char *argv[], int *next) - { -+ error_t err; -+ int pos = 1; -+ -+ /* Parse the arguments. */ -+ err = argp_parse (&argp, argc, argv, ARGP_IN_ORDER | ARGP_NO_EXIT -+ | ARGP_SILENT, 0 , &pos); -+ *next += pos - 1; -+ -+ if (err && err != EINVAL) -+ return err; -+ -+ - return 0; - } - -@@ -1156,6 +1134,10 @@ pc_kbd_start (void *handle) - iconv_close (cd); - return err; - } -+ -+ if (repeater_node) -+ setrepeater (repeater_node); -+ - cthread_detach (cthread_fork (input_loop, NULL)); - - return 0; diff --git a/debian/patches/libcons_repeater.patch b/debian/patches/libcons_repeater.patch new file mode 100644 index 00000000..21df71d9 --- /dev/null +++ b/debian/patches/libcons_repeater.patch @@ -0,0 +1,525 @@ +Common subdirectories: ../libcons.cvs/CVS and ./CVS +diff -upN ../libcons.cvs/Makefile ./Makefile +--- libcons.cvs/Makefile 2002-09-13 23:40:10.000000000 +0000 ++++ libcons/Makefile 2004-04-02 07:44:48.000000000 +0000 +@@ -23,7 +23,7 @@ SRCS= demuxer.c init-init.c init-loop.c + dir-changed.c file-changed.c opts-std-startup.c cons-lookup.c \ + cons-switch.c vcons-remove.c vcons-add.c vcons-open.c \ + vcons-close.c vcons-destroy.c vcons-refresh.c vcons-scrollback.c \ +- vcons-input.c ++ vcons-input.c vcons-move-mouse.c vcons-event.c + LCLHDRS = priv.h mutations.h + installhdrs = cons.h + +diff -upN ../libcons.cvs/cons.h ./cons.h +--- libcons.cvs/cons.h 2003-08-16 18:06:23.000000000 +0000 ++++ libcons/cons.h 2004-04-02 07:42:20.000000000 +0000 +@@ -123,6 +123,31 @@ struct cons + int slack; + }; + ++ ++enum mouse_movement ++ { ++ MOUSE_MOVE_REL, ++ MOUSE_MOVE_ABS, ++ MOUSE_MOVE_PROC ++ }; ++ ++enum mouse_button ++ { ++ MOUSE_BUTTON_NO_OP, ++ MOUSE_BUTTON_PRESSED, ++ MOUSE_BUTTON_RELEASED ++ }; ++ ++typedef struct mouse_event ++{ ++ enum mouse_movement mouse_movement; ++ float x; ++ float y; ++ ++ enum mouse_button mouse_button; ++ int button; ++} *mouse_event_t; ++ + + /* The user must define this variable. Set this to the name of the + console client. */ +@@ -256,6 +281,14 @@ typedef enum + down. */ + int cons_vcons_scrollback (vcons_t vcons, cons_scroll_t type, float value); + ++/* Set the mouse cursor position to X, Y. VCONS is locked. */ ++error_t cons_vcons_set_mousecursor_pos (vcons_t vcons, float x, float y); ++ ++/* If STATUS is set to 0, hide the mouse cursor, otherwise show ++ it. VCONS is locked. */ ++error_t cons_vcons_set_mousecursor_status (vcons_t vcons, int status); ++ ++ + + extern const struct argp cons_startup_argp; + +@@ -286,4 +319,6 @@ void cons_vcons_destroy (void *port); + /* Redraw the virtual console VCONS, which is locked. */ + void cons_vcons_refresh (vcons_t vcons); + ++error_t cons_vcons_move_mouse (vcons_t vcons, mouse_event_t ev); ++ + #endif /* hurd/cons.h */ +diff -upN ../libcons.cvs/file-changed.c ./file-changed.c +--- libcons.cvs/file-changed.c 2003-08-02 21:43:46.000000000 +0000 ++++ libcons/file-changed.c 2004-04-02 07:02:31.000000000 +0000 +@@ -1,5 +1,5 @@ + /* file-changed.c - Handling file changed notifications. +- Copyright (C) 2002, 2003 Free Software Foundation, Inc. ++ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. +@@ -93,6 +93,7 @@ cons_S_file_changed (cons_notify_t notif + /* The cursor was visible before. */ + cons_vcons_set_cursor_status (vcons, CONS_CURSOR_INVISIBLE); + ++ _cons_vcons_console_event (vcons, CONSEVT_OUTPUT); + cons_vcons_update (vcons); + } + if (change.what.cursor_status) +@@ -185,6 +186,7 @@ cons_S_file_changed (cons_notify_t notif + end - size + 1, + 0, (size - vis_start) + / vcons->state.screen.width); ++ _cons_vcons_console_event (vcons, CONSEVT_OUTPUT); + cons_vcons_update (vcons); + } + vcons->state.screen.cur_line = new_cur_line; +@@ -342,6 +344,7 @@ cons_S_file_changed (cons_notify_t notif + (size - rotate) + / vcons->state.screen.width); + } ++ _cons_vcons_console_event (vcons, CONSEVT_OUTPUT); + cons_vcons_update (vcons); + } + } +diff -upN ../libcons.cvs/opts-std-startup.c ./opts-std-startup.c +--- libcons.cvs/opts-std-startup.c 2003-08-02 21:43:46.000000000 +0000 ++++ libcons/opts-std-startup.c 2004-04-02 00:35:20.000000000 +0000 +@@ -1,5 +1,5 @@ + /* opts-std-startup.c - Standard startup-time command line parser. +- Copyright (C) 1995,96,97,98,99,2001,02,2003 Free Software Foundation, Inc. ++ Copyright (C) 1995,96,97,98,99,2001,02,2003,2004 Free Software Foundation, Inc. + Written by Miles Bader <miles@gnu.org> and Marcus Brinkmann. + + This file is part of the GNU Hurd. +@@ -25,7 +25,7 @@ + #include "priv.h" + + +-/* Option keys for long-only options in diskfs_common_options. */ ++/* Option keys for long-only options in argp_option. */ + #define OPT_SLACK 600 /* --slack */ + #define OPT_JUMP_DOWN_ON_INPUT 601 /* --jump-down-on-input */ + #define OPT_NO_JUMP_DOWN_ON_INPUT 602 /* --no-jump-down-on-input */ +@@ -33,13 +33,20 @@ + #define OPT_NO_JUMP_DOWN_ON_OUTPUT 604 /* --no-jump-down-on-output */ + #define OPT_VISUAL_BELL 605 /* --visual-bell */ + #define OPT_AUDIBLE_BELL 606 /* --audible-bell */ ++#define OPT_MOUSE_SHOW 607 /* --mouse-show */ ++#define OPT_MOUSE_HIDE 608 /* --mouse-hide */ ++#define OPT_MOUSE_SENS 609 /* --mouse-sensitivity */ + +-/* Common value for diskfs_common_options and diskfs_default_sync_interval. */ ++/* The number of records the client is allowed to lag behind the server. */ + #define DEFAULT_SLACK 100 + #define DEFAULT_SLACK_STRING STRINGIFY(DEFAULT_SLACK) + #define STRINGIFY(x) STRINGIFY_1(x) + #define STRINGIFY_1(x) #x + ++/* The mouse sensitivity. */ ++#define DEFAULT_MOUSE_SENS 3.0 ++#define DEFAULT_MOUSE_SENS_STRING STRINGIFY(DEFAULT_SLACK) ++ + /* Number of records the client is allowed to lag behind the + server. */ + int _cons_slack = DEFAULT_SLACK; +@@ -59,6 +66,15 @@ bell_type_t _cons_visual_bell = BELL_VIS + /* The type of bell used for the audible bell. */ + bell_type_t _cons_audible_bell = BELL_AUDIBLE; + ++/* The type of events that will make the mouse cursor visible. */ ++int _cons_show_mouse = CONSEVT_MOUSEMOVE; ++ ++/* The type of events that will hide the mouse cursor. */ ++int _cons_hide_mouse = CONSEVT_KEYPRESS; ++ ++/* The mouse sensitivity. */ ++float _cons_mouse_sens = DEFAULT_MOUSE_SENS; ++ + static const struct argp_option + startup_options[] = + { +@@ -76,6 +92,15 @@ startup_options[] = + "off, visual, audible" }, + { "audible-bell", OPT_AUDIBLE_BELL, "BELL", 0, "Audible bell: on (default), " + "off, visual, audible" }, ++ { "mouse-show", OPT_MOUSE_SHOW, "EVENTS", 0, "One or more of the events" ++ " MOUSEMOVE, MOUSEBUTTON, KEYPRESS, OUTPUT (default is MOUSEMOVE), if one" ++ " of these events occur the mouse cursor will be made visible" }, ++ { "mouse-hide", OPT_MOUSE_HIDE, "EVENTS", 0, "One or more of the events" ++ " MOUSEMOVE, MOUSEBUTTON, KEYPRESS, OUTPUT (default is KEYPRESS), if one" ++ " of these events occur the mouse cursor will be hidden " }, ++ { "mouse-sensitivity", OPT_MOUSE_SENS, "SENSITIVITY", 0, "The mouse" ++ " sensitivity (default " DEFAULT_MOUSE_SENS_STRING "). A lower value" ++ " means more sensitive" }, + { 0, 0 } + }; + +@@ -86,6 +111,30 @@ static const char doc[] = "A console cli + static error_t + parse_startup_opt (int opt, char *arg, struct argp_state *state) + { ++ int parse_events (char *events) ++ { ++ char *evtstr = strdupa (events); ++ char *tok = strtok (evtstr, ","); ++ int evmask = 0; ++ ++ while (tok) ++ { ++ if (!strcasecmp ("mousemove", tok)) ++ evmask |= CONSEVT_MOUSEMOVE; ++ else if (!strcasecmp ("mousebutton", tok)) ++ evmask |= CONSEVT_MOUSEBUTTON; ++ else if (!strcasecmp ("keypress", tok)) ++ evmask |= CONSEVT_KEYPRESS; ++ else if (!strcasecmp ("output", tok)) ++ evmask |= CONSEVT_OUTPUT; ++ else ++ argp_error (state, "The event can be one of: MOUSEMOVE," ++ " MOUSEBUTTON, KEYPRESS or OUTPUT"); ++ tok = strtok (NULL, ","); ++ } ++ return evmask; ++ } ++ + switch (opt) + { + case OPT_SLACK: +@@ -131,7 +180,28 @@ parse_startup_opt (int opt, char *arg, s + argp_error (state, "The visual bell can be one of: on, off, visual, " + "audible"); + break; +- ++ ++ case OPT_MOUSE_SHOW: ++ _cons_show_mouse = parse_events (arg); ++ break; ++ ++ case OPT_MOUSE_HIDE: ++ _cons_hide_mouse = parse_events (arg); ++ break; ++ ++ case OPT_MOUSE_SENS: ++ { ++ char *tail; ++ ++ errno = 0; ++ _cons_mouse_sens = strtod (arg, &tail); ++ if (tail == NULL || tail == arg || *tail != '\0') ++ argp_error (state, "SENSITIVITY is not a number: %s", arg); ++ if (errno) ++ argp_error (state, "Overflow in argument SENSITIVITY %s", arg); ++ break; ++ } ++ + case ARGP_KEY_ARG: + if (state->arg_num > 0) + /* Too many arguments. */ +diff -upN ../libcons.cvs/priv.h ./priv.h +--- libcons.cvs/priv.h 2003-08-02 21:43:46.000000000 +0000 ++++ libcons/priv.h 2004-04-02 00:52:07.000000000 +0000 +@@ -29,6 +29,11 @@ typedef enum + BELL_AUDIBLE + } bell_type_t; + ++#define CONSEVT_MOUSEMOVE (1 << 1) ++#define CONSEVT_MOUSEBUTTON (1 << 2) ++#define CONSEVT_KEYPRESS (1 << 4) ++#define CONSEVT_OUTPUT (1 << 8) ++ + + /* Number of records the client is allowed to lag behind the + server. */ +@@ -49,11 +54,26 @@ extern bell_type_t _cons_visual_bell; + /* The type of bell used for the audible bell. */ + extern bell_type_t _cons_audible_bell; + ++/* The type of events that will make the mouse cursor visible. */ ++extern int _cons_show_mouse; ++ ++/* The type of events that will hide the mouse cursor. */ ++extern int _cons_hide_mouse; ++ ++/* The mouse sensitivity. */ ++extern float _cons_mouse_sens; ++ + + /* Non-locking version of cons_vcons_scrollback. Does also not update + the display. */ + int _cons_vcons_scrollback (vcons_t vcons, cons_scroll_t type, float value); + ++/* Non-locking version of cons_vcons_input. */ ++error_t _cons_vcons_input (vcons_t vcons, char *buf, size_t size); ++ ++/* Generate the console event EVENT for console VCONS. */ ++void _cons_vcons_console_event (vcons_t vcons, int event); ++ + + /* Called by MiG to translate ports into cons_notify_t. mutations.h + arranges for this to happen for the fs_notify interfaces. */ +diff -upN ../libcons.cvs/vcons-event.c ./vcons-event.c +--- libcons.cvs/vcons-event.c 1970-01-01 00:00:00.000000000 +0000 ++++ libcons/vcons-event.c 2004-04-02 07:39:07.000000000 +0000 +@@ -0,0 +1,31 @@ ++/* vcons-event.c - Handle console events. ++ Copyright (C) 2004 Free Software Foundation, Inc. ++ Written by Marco Gerards. ++ ++ 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 "cons.h" ++#include "priv.h" ++ ++void ++_cons_vcons_console_event (vcons_t vcons, int event) ++{ ++ if (_cons_show_mouse & event) ++ cons_vcons_set_mousecursor_status (vcons, 1); ++ else if (_cons_hide_mouse & event) ++ cons_vcons_set_mousecursor_status (vcons, 0); ++} +diff -upN ../libcons.cvs/vcons-input.c ./vcons-input.c +--- libcons.cvs/vcons-input.c 2002-09-13 23:53:55.000000000 +0000 ++++ libcons/vcons-input.c 2004-04-02 07:02:54.000000000 +0000 +@@ -1,5 +1,5 @@ + /* vcons-input.c - Add input to a virtual console. +- Copyright (C) 2002 Free Software Foundation, Inc. ++ Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. +@@ -24,18 +24,12 @@ + #include "cons.h" + #include "priv.h" + +-/* Enter SIZE bytes from the buffer BUF into the virtual console +- VCONS. */ ++/* Non-locking version of cons_vcons_input. */ + error_t +-cons_vcons_input (vcons_t vcons, char *buf, size_t size) ++_cons_vcons_input (vcons_t vcons, char *buf, size_t size) + { + int ret; + +- mutex_lock (&vcons->lock); +- +- if (vcons->scrolling && _cons_jump_down_on_input) +- _cons_vcons_scrollback (vcons, CONS_SCROLL_ABSOLUTE_LINE, 0); +- + do + { + ret = write (vcons->input, buf, size); +@@ -47,8 +41,24 @@ cons_vcons_input (vcons_t vcons, char *b + } + while (size && (ret != -1 || errno == EINTR)); + +- mutex_unlock (&vcons->lock); + return 0; + } + + ++/* Enter SIZE bytes from the buffer BUF into the virtual console ++ VCONS. */ ++error_t ++cons_vcons_input (vcons_t vcons, char *buf, size_t size) ++{ ++ mutex_lock (&vcons->lock); ++ ++ _cons_vcons_console_event (vcons, CONSEVT_KEYPRESS); ++ ++ if (vcons->scrolling && _cons_jump_down_on_input) ++ _cons_vcons_scrollback (vcons, CONS_SCROLL_ABSOLUTE_LINE, 0); ++ ++ _cons_vcons_input (vcons, buf, size); ++ ++ mutex_unlock (&vcons->lock); ++ return 0; ++} +diff -upN ../libcons.cvs/vcons-move-mouse.c ./vcons-move-mouse.c +--- libcons.cvs/vcons-move-mouse.c 1970-01-01 00:00:00.000000000 +0000 ++++ libcons/vcons-move-mouse.c 2004-07-27 07:07:34.000000000 +0000 +@@ -0,0 +1,98 @@ ++/* vcons-move-mouse.c - Catch mouse events. ++ Copyright (C) 2004 Free Software Foundation, Inc. ++ Written by Marco Gerards. ++ ++ 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 <errno.h> ++#include <unistd.h> ++ ++#include "cons.h" ++#include "priv.h" ++ ++static float mousepos_x; ++static float mousepos_y; ++ ++error_t ++cons_vcons_move_mouse (vcons_t vcons, mouse_event_t ev) ++{ ++ int ret; ++ char event[CONS_MOUSE_EVENT_LENGTH]; ++ uint32_t report_events = vcons->display->flags & CONS_FLAGS_TRACK_MOUSE; ++ ++ mutex_lock (&vcons->lock); ++ ++ switch (ev->mouse_movement) ++ { ++ case MOUSE_MOVE_REL: ++ mousepos_x += ((float) ev->x / _cons_mouse_sens); ++ mousepos_y += ((float) ev->y / _cons_mouse_sens); ++ break; ++ ++ case MOUSE_MOVE_PROC: ++ case MOUSE_MOVE_ABS: ++ break; ++ } ++ ++ /* Keep the mouse cursor in range of the VC. */ ++ if (mousepos_x < 0) ++ mousepos_x = 0; ++ if (mousepos_y < 0) ++ mousepos_y = 0; ++ if (mousepos_x >= (float) vcons->state.screen.width) ++ mousepos_x = vcons->state.screen.width - 1; ++ if (mousepos_y >= (float) vcons->state.screen.height) ++ mousepos_y = vcons->state.screen.height - 1; ++ ++ cons_vcons_set_mousecursor_pos (vcons, (float) mousepos_x, (float) mousepos_y); ++ ++ /* Report a mouse movement event. */ ++ if (ev->x || ev->y) ++ _cons_vcons_console_event (vcons, CONSEVT_MOUSEMOVE); ++ ++ /* Report a mouse button event. */ ++ if (ev->mouse_button != MOUSE_BUTTON_NO_OP) ++ _cons_vcons_console_event (vcons, CONSEVT_MOUSEBUTTON); ++ ++ if (report_events) ++ { ++ switch (ev->mouse_button) ++ { ++ case MOUSE_BUTTON_NO_OP: ++ break; ++ ++ case MOUSE_BUTTON_PRESSED: ++ /* Make a xterm like event string. */ ++ CONS_MOUSE_EVENT (event, ev->button, (int) mousepos_x + 1, (int) mousepos_y + 1); ++ ++ _cons_vcons_input (vcons, event, CONS_MOUSE_EVENT_LENGTH); ++ /* And send it to the server. */ ++ break; ++ ++ case MOUSE_BUTTON_RELEASED: ++ /* Make a xterm like event string. */ ++ CONS_MOUSE_EVENT (event, CONS_MOUSE_RELEASE, (int) mousepos_x + 1, (int) mousepos_y + 1); ++ ++ /* And send it to the server. */ ++ _cons_vcons_input (vcons, event, CONS_MOUSE_EVENT_LENGTH); ++ break; ++ } ++ } ++ ++ mutex_unlock (&vcons->lock); ++ return 0; ++} +diff -upN ../libcons.cvs/vcons-refresh.c ./vcons-refresh.c +--- libcons.cvs/vcons-refresh.c 2003-08-15 21:04:10.000000000 +0000 ++++ libcons/vcons-refresh.c 2004-04-02 07:03:08.000000000 +0000 +@@ -1,5 +1,5 @@ + /* vcons-refresh.c - Redraw a virtual console. +- Copyright (C) 2002, 2003 Free Software Foundation, Inc. ++ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. +@@ -22,6 +22,7 @@ + #include <assert.h> + + #include "cons.h" ++#include "priv.h" + + /* Redraw the virtual console VCONS, which is locked. */ + void +@@ -70,5 +71,6 @@ cons_vcons_refresh (vcons_t vcons) + cons_vcons_set_cursor_status (vcons, vcons->state.cursor.status); + cons_vcons_set_scroll_lock (vcons, vcons->state.flags + & CONS_FLAGS_SCROLL_LOCK); ++ _cons_vcons_console_event (vcons, CONSEVT_OUTPUT); + cons_vcons_update (vcons); + } +diff -upN ../libcons.cvs/vcons-scrollback.c ./vcons-scrollback.c +--- libcons.cvs/vcons-scrollback.c 2002-09-17 11:47:15.000000000 +0000 ++++ libcons/vcons-scrollback.c 2004-04-02 07:03:15.000000000 +0000 +@@ -1,5 +1,5 @@ + /* vcons-scrollback.c - Move forward and backward in the scrollback buffer. +- Copyright (C) 2002 Free Software Foundation, Inc. ++ Copyright (C) 2002, 2004 Free Software Foundation, Inc. + Written by Marcus Brinkmann. + + This file is part of the GNU Hurd. +@@ -23,6 +23,7 @@ + #include <cthreads.h> + + #include "cons.h" ++#include "priv.h" + + /* Non-locking version of cons_vcons_scrollback. Does also not update + the display. */ +@@ -155,6 +156,7 @@ cons_vcons_scrollback (vcons_t vcons, co + + mutex_lock (&vcons->lock); + ret = _cons_vcons_scrollback (vcons, type, value); ++ _cons_vcons_console_event (vcons, CONSEVT_OUTPUT); + cons_vcons_update (vcons); + mutex_unlock (&vcons->lock); + return ret; diff --git a/debian/patches/netfs_io_select.patch b/debian/patches/netfs_io_select.patch new file mode 100644 index 00000000..e24fa1ee --- /dev/null +++ b/debian/patches/netfs_io_select.patch @@ -0,0 +1,58 @@ +2004-07-28 Marco Gerards <metgerards@student.han.nl> + + * io-select.c: Include <hurd/ports.h>. + (netfs_S_io_select): Add arguments `reply' and `replytype'. + * mutations.h (IO_SELECT_REPLY_PORT): New macro. + + +Index: io-select.c +=================================================================== +RCS file: /cvsroot/hurd/hurd/libnetfs/io-select.c,v +retrieving revision 1.2 +diff -u -p -r1.2 io-select.c +--- libnetfs/io-select.c 9 May 1996 22:15:46 -0000 1.2 ++++ libnetfs/io-select.c 28 Jul 2004 12:40:29 -0000 +@@ -1,5 +1,5 @@ + /* +- Copyright (C) 1995, 1996 Free Software Foundation, Inc. ++ Copyright (C) 1995, 1996, 2004 Free Software Foundation, Inc. + Written by Michael I. Bushnell, p/BSG. + + This file is part of the GNU Hurd. +@@ -20,9 +20,12 @@ + + #include "netfs.h" + #include "io_S.h" ++#include <hurd/ports.h> + + error_t + netfs_S_io_select (struct protid *user, ++ mach_port_t reply, ++ mach_msg_type_name_t replytype, + int *type) + { + if (!user) +Index: mutations.h +=================================================================== +RCS file: /cvsroot/hurd/hurd/libnetfs/mutations.h,v +retrieving revision 1.3 +diff -u -p -r1.3 mutations.h +--- libnetfs/mutations.h 14 Dec 1995 23:30:59 -0000 1.3 ++++ libnetfs/mutations.h 28 Jul 2004 12:40:29 -0000 +@@ -1,5 +1,5 @@ + /* +- Copyright (C) 1995 Free Software Foundation, Inc. ++ Copyright (C) 1995, 2004 Free Software Foundation, Inc. + Written by Michael I. Bushnell, p/BSG. + + This file is part of the GNU Hurd. +@@ -20,6 +20,8 @@ + + /* Only CPP macro definitions should go in this file. */ + ++#define IO_SELECT_REPLY_PORT ++ + #define FILE_INTRAN protid_t begin_using_protid_port (file_t) + #define FILE_DESTRUCTOR end_using_protid_port (protid_t) + + diff --git a/debian/patches/netfs_nonblock.patch b/debian/patches/netfs_nonblock.patch new file mode 100644 index 00000000..0378d3e3 --- /dev/null +++ b/debian/patches/netfs_nonblock.patch @@ -0,0 +1,21 @@ +2004-07-24 Marco Gerards <metgerards@student.han.nl> + + * misc.h (OPENONLY_STATE_MODES): Remove O_NONBLOCK. + + +Index: misc.h +=================================================================== +RCS file: /cvsroot/hurd/hurd/libnetfs/misc.h,v +retrieving revision 1.2 +diff -u -p -r1.2 misc.h +--- libnetfs/misc.h 18 Dec 1995 19:02:52 -0000 1.2 ++++ libnetfs/misc.h 24 Jul 2004 19:14:12 -0000 +@@ -21,4 +21,4 @@ + #include <fcntl.h> + + /* Bits that are turned off after open */ +-#define OPENONLY_STATE_MODES (O_CREAT|O_EXCL|O_NOLINK|O_NOTRANS|O_NONBLOCK) ++#define OPENONLY_STATE_MODES (O_CREAT|O_EXCL|O_NOLINK|O_NOTRANS) + + + diff --git a/debian/patches/rc.patch b/debian/patches/rc.patch new file mode 100644 index 00000000..ba1fd3b4 --- /dev/null +++ b/debian/patches/rc.patch @@ -0,0 +1,54 @@ +--- hurd/daemons/rc.sh.orig 2004-07-09 21:48:42.000000000 +0000 ++++ hurd/daemons/rc.sh 2004-07-09 21:48:25.000000000 +0000 +@@ -85,7 +85,15 @@ + + fi + if test -d /var/run; then +- (cd /var/run && { rm -rf -- *; cp /dev/null utmp; chmod 644 utmp; }) ++ (cd /var/run && { ++ find . ! -type d ! -name utmp ! -name innd.pid \ ++ -exec rm -f -- {} \; ++ cp /dev/null utmp ++ if grep -q ^utmp: /etc/group ++ then ++ chmod 664 utmp ++ chgrp utmp utmp ++ fi; }) + fi + echo done + +@@ -104,15 +112,25 @@ + + chmod 664 /etc/motd + +-echo -n starting daemons: ++( ++ trap ":" INT QUIT TSTP + +-/sbin/syslogd && echo -n ' syslogd' +-/sbin/inetd && echo -n ' inetd' +- +-if test -x /sbin/sendmail -a -r /etc/sendmail.cf; then +- /sbin/sendmail -bd -q30m && echo -n ' sendmail' +-fi +- +-echo . ++ if [ -d /etc/rc.boot ] ++ then ++ for i in /etc/rc.boot/S* ++ do ++ [ ! -f $i ] && continue ++ $i start ++ done ++ fi ++ if [ -d /etc/rc2.d ] ++ then ++ for i in /etc/rc2.d/S* ++ do ++ [ ! -f $i ] && continue ++ $i start ++ done ++ fi ++) + + date |