summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcus Brinkmann <marcus@gnu.org>2005-07-11 13:59:24 +0000
committerMarcus Brinkmann <marcus@gnu.org>2005-07-11 13:59:24 +0000
commit94414efd38f6a555ac97d013bd0aced76803142d (patch)
tree39a3a126bf24edc3a0e1658fc0863f0da9453909
parent2f745c154065dfeae33c864b4e61cfca7a3d4974 (diff)
2005-07-11 Samuel Thibault <samuel.thibault@ens-lyon.org>
* Makefile (modules): Add `current-vcs' and its rules. * console.c (console_current_id): New function. * input.h (console_current_id): New prototype. * trans.c (struct netnode): New member `symlink_path'. (console_demuxer): Handle case when node it anonymous. (netfs_S_io_select): Likewise. (netfs_S_io_read): Likewise. (netfs_S_io_write): Likewise. (netfs_report_access): Likewise. (netfs_attempt_mksymlink): Implement symlinks. (netfs_attempt_lookup): Likewise. (netfs_attempt_unlink): Likewise. (netfs_attempt_link): Likewise. (netfs_attempt_mkfile): Likewise. (netfs_attempt_readlink): Likewise. (netfs_get_dirents): Likewise. (netfs_create_consnode): Likewise. * trans.h (struct consnode): New members `readlink' and `mksymlink'. * current-vcs.c: New file.
-rw-r--r--console-client/ChangeLog22
-rw-r--r--console-client/Makefile3
-rw-r--r--console-client/console.c18
-rw-r--r--console-client/current-vcs.c223
-rw-r--r--console-client/input.h3
-rw-r--r--console-client/trans.c110
-rw-r--r--console-client/trans.h6
7 files changed, 374 insertions, 11 deletions
diff --git a/console-client/ChangeLog b/console-client/ChangeLog
index 55968d42..b1d0c2dc 100644
--- a/console-client/ChangeLog
+++ b/console-client/ChangeLog
@@ -1,3 +1,25 @@
+2005-07-11 Samuel Thibault <samuel.thibault@ens-lyon.org>
+
+ * Makefile (modules): Add `current-vcs' and its rules.
+ * console.c (console_current_id): New function.
+ * input.h (console_current_id): New prototype.
+ * trans.c (struct netnode): New member `symlink_path'.
+ (console_demuxer): Handle case when node it anonymous.
+ (netfs_S_io_select): Likewise.
+ (netfs_S_io_read): Likewise.
+ (netfs_S_io_write): Likewise.
+ (netfs_report_access): Likewise.
+ (netfs_attempt_mksymlink): Implement symlinks.
+ (netfs_attempt_lookup): Likewise.
+ (netfs_attempt_unlink): Likewise.
+ (netfs_attempt_link): Likewise.
+ (netfs_attempt_mkfile): Likewise.
+ (netfs_attempt_readlink): Likewise.
+ (netfs_get_dirents): Likewise.
+ (netfs_create_consnode): Likewise.
+ * trans.h (struct consnode): New members `readlink' and `mksymlink'.
+ * current-vcs.c: New file.
+
2005-01-10 Alfred M. Szmidt <ams@gnu.org>
* console.c (consnode_path): Renamed to ...
diff --git a/console-client/Makefile b/console-client/Makefile
index 1a8bbe28..ff1a8f29 100644
--- a/console-client/Makefile
+++ b/console-client/Makefile
@@ -41,7 +41,7 @@ driver-CPPFLAGS = -D'CONSOLE_DEFPATH="$(module-dir)\0"' \
console: ../libcons/libcons.a ../libports/libports.a \
../libthreads/libthreads.a ../libshouldbeinlibc/libshouldbeinlibc.a
-modules = vga pc_kbd generic_speaker pc_mouse
+modules = vga pc_kbd generic_speaker pc_mouse current_vcs
vga-CPPFLAGS = -DDEFAULT_VGA_FONT_DIR=\"${datadir}/hurd/\"
vga.so.$(hurd-version): $(patsubst %.c,%_pic.o,bdf.c vga-dynafont.c \
@@ -49,6 +49,7 @@ vga.so.$(hurd-version): $(patsubst %.c,%_pic.o,bdf.c vga-dynafont.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)
+current_vcs.so.$(hurd-version): $(patsubst %.c,%_pic.o,current-vcs.c)
ifneq ($(LIBNCURSESW),)
modules += ncursesw
diff --git a/console-client/console.c b/console-client/console.c
index 019ea3f1..06a8c1ac 100644
--- a/console-client/console.c
+++ b/console-client/console.c
@@ -64,6 +64,24 @@ static char *console_node;
/* Callbacks for input source drivers. */
+/* Returns current console ID. */
+error_t
+console_current_id (int *cur)
+{
+ vcons_t vcons;
+
+ mutex_lock (&global_lock);
+ vcons = active_vcons;
+ if (!vcons)
+ {
+ mutex_unlock (&global_lock);
+ return ENODEV;
+ }
+ *cur = vcons->id;
+ mutex_unlock (&global_lock);
+ return 0;
+}
+
/* Switch the active console to console ID or DELTA (relative to the
active console). */
error_t
diff --git a/console-client/current-vcs.c b/console-client/current-vcs.c
new file mode 100644
index 00000000..3bfc1a75
--- /dev/null
+++ b/console-client/current-vcs.c
@@ -0,0 +1,223 @@
+/* current-vcs.c -- Add a "current vcs" symlink to the cons node.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+ Written by Samuel Thibault.
+
+ 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 <argp.h>
+#include <driver.h>
+#include <input.h>
+#include <stdio.h>
+#include <error.h>
+#include <sys/mman.h>
+
+#include "trans.h"
+
+
+/* We use the same infrastructure as the kbd and mouse repeaters. */
+
+/* The default name of the node of the repeater. */
+#define DEFAULT_REPEATER_NODE "vcs"
+
+/* The name of the repeater node. */
+static char *repeater_node;
+
+/* The repeater node. */
+static consnode_t vcs_node;
+
+
+/* Callbacks for vcs console node. */
+
+/* Reading the link to get current vcs, returns length of path (trailing \0
+ excluded). */
+static error_t
+vcs_readlink (struct iouser *user, struct node *np, char *buf)
+{
+ int cur;
+ error_t ret = 0;
+
+ ret = console_current_id (&cur);
+ if (!ret)
+ {
+ if (!buf)
+ ret = snprintf (NULL, 0, "%s/%d", cons_file, cur);
+ else
+ ret = sprintf (buf, "%s/%d", cons_file, cur);
+
+ if (ret < 0)
+ ret = errno;
+ }
+ return ret;
+}
+
+static error_t
+vcs_read (struct protid *user, char **data,
+ mach_msg_type_number_t * datalen, off_t offset,
+ mach_msg_type_number_t amount)
+{
+ int err;
+ int size;
+ char *buf;
+
+ if (amount > 0)
+ {
+ size = vcs_readlink (user->user, NULL, NULL);
+ if (size < 0)
+ return size;
+
+ buf = alloca (size);
+
+ err = vcs_readlink (user->user, NULL, buf);
+
+ if (err < 0)
+ return err;
+
+ if (offset + amount > size)
+ amount = size - offset;
+ if (amount < 0)
+ amount = 0;
+
+ if (*datalen < amount)
+ {
+ *data = mmap (0, amount, PROT_READ | PROT_WRITE, MAP_ANON, 0, 0);
+ if (*data == MAP_FAILED)
+ return ENOMEM;
+ }
+
+ memcpy (*data, buf + offset, amount);
+ *datalen = amount;
+ }
+ return 0;
+}
+
+/* Making a link to set current vcs.
+ Relative values perform relative switches. */
+static error_t
+vcs_mksymlink (struct iouser *user, struct node *np, char *name)
+{
+ char *c, *d;
+ int vt, delta = 0;
+
+ c = strrchr (name, '/');
+ if (!c)
+ c = name;
+ else
+ c++;
+ if (!*c)
+ return EINVAL;
+
+ if (*c == '-' || *c == '+')
+ delta = 1;
+
+ vt = strtol (c, &d, 10);
+ if (*d)
+ /* Bad number. */
+ return EINVAL;
+
+ if (!vt)
+ return 0;
+ return console_switch (delta ? 0 : vt, delta ? vt : 0);
+}
+
+
+static const char doc[] = "Current VCS Driver";
+
+static const struct argp_option options[] =
+ {
+ { "repeater", 'r', "NODE", OPTION_ARG_OPTIONAL,
+ "Set a current vcs translator on NODE (default: " DEFAULT_REPEATER_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 ? arg: DEFAULT_REPEATER_NODE;
+ 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 current VCS driver. */
+static error_t
+vcs_repeat_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
+vcs_repeat_start (void *handle)
+{
+ error_t err;
+
+ err = console_create_consnode (repeater_node, &vcs_node);
+ if (err)
+ return err;
+
+ vcs_node->read = vcs_read;
+ vcs_node->write = NULL;
+ vcs_node->select = NULL;
+ vcs_node->open = NULL;
+ vcs_node->close = NULL;
+ vcs_node->demuxer = NULL;
+ vcs_node->readlink = vcs_readlink;
+ vcs_node->mksymlink = vcs_mksymlink;
+ console_register_consnode (vcs_node);
+
+ return 0;
+}
+
+static error_t
+vcs_repeat_fini (void *handle, int force)
+{
+ console_unregister_consnode (vcs_node);
+ console_destroy_consnode (vcs_node);
+ return 0;
+}
+
+
+struct driver_ops driver_vcs_repeat_ops =
+ {
+ vcs_repeat_init,
+ vcs_repeat_start,
+ vcs_repeat_fini
+ };
+
diff --git a/console-client/input.h b/console-client/input.h
index e5683a8e..351fa34a 100644
--- a/console-client/input.h
+++ b/console-client/input.h
@@ -55,6 +55,9 @@ error_t console_input (char *buf, size_t size);
cons_vcons_scrollback. */
int console_scrollback (cons_scroll_t type, float value);
+/* Returns current console ID. */
+error_t console_current_id (int *cur);
+
/* Switch the active console to console ID or DELTA (relative to the
active console). */
error_t console_switch (int id, int delta);
diff --git a/console-client/trans.c b/console-client/trans.c
index 83342bcc..ee7581b4 100644
--- a/console-client/trans.c
+++ b/console-client/trans.c
@@ -41,6 +41,7 @@ static consnode_t node_list = 0;
struct netnode
{
consnode_t node;
+ char *symlink_path;
};
typedef mach_msg_header_t request_t;
@@ -69,7 +70,7 @@ console_demuxer (mach_msg_header_t *inp,
return 0;
}
- if (!ret && user->po->np->nn->node->demuxer)
+ if (!ret && user->po->np->nn->node && user->po->np->nn->node->demuxer)
ret = user->po->np->nn->node->demuxer (inp, outp);
ports_port_deref (user);
@@ -125,6 +126,15 @@ error_t
netfs_attempt_mksymlink (struct iouser *cred, struct node *np,
char *name)
{
+ if (!np->nn->node)
+ {
+ if (np->nn->symlink_path)
+ free (np->nn->symlink_path);
+ np->nn->symlink_path = strdup (name);
+ return 0;
+ }
+ else if (np->nn->node->mksymlink)
+ return np->nn->node->mksymlink (cred, np, name);
return EOPNOTSUPP;
}
@@ -272,8 +282,18 @@ netfs_attempt_lookup (struct iouser *user, struct node *dir,
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_mode = (netfs_root_node->nn_stat.st_mode & ~S_IFMT & ~S_ITRANS);
(*node)->nn_stat.st_ino = 5;
+ if (cn->readlink)
+ {
+ (*node)->nn_stat.st_mode |= S_IFLNK;
+ (*node)->nn_stat.st_size = cn->readlink (user, NULL, NULL);
+ }
+ else
+ {
+ (*node)->nn_stat.st_mode |= S_IFCHR;
+ (*node)->nn_stat.st_size = 0;
+ }
cn->node = *node;
goto out;
}
@@ -325,7 +345,7 @@ netfs_S_io_select (struct protid *user, mach_port_t reply,
np = user->po->np;
- if (np->nn->node->select)
+ if (np->nn->node && np->nn->node->select)
return np->nn->node->select (user, reply, replytype, type);
return EOPNOTSUPP;
}
@@ -336,6 +356,21 @@ error_t
netfs_attempt_unlink (struct iouser *user, struct node *dir,
char *name)
{
+ error_t err;
+ consnode_t cn;
+
+ err = fshelp_access (&dir->nn_stat, S_IWRITE, user);
+ if (err)
+ return err;
+
+ for (cn = node_list; cn; cn = cn->next)
+ if (!strcmp (name, cn->name))
+ {
+ if (cn->mksymlink)
+ return 0;
+ else
+ break;
+ }
return EOPNOTSUPP;
}
@@ -378,6 +413,30 @@ error_t
netfs_attempt_link (struct iouser *user, struct node *dir,
struct node *file, char *name, int excl)
{
+ error_t err;
+ consnode_t cn;
+
+ err = fshelp_access (&dir->nn_stat, S_IWRITE, user);
+ if (err)
+ return err;
+
+ if (!file->nn->node && file->nn->symlink_path)
+ {
+ for (cn = node_list; cn; cn = cn->next)
+ if (!strcmp (name, cn->name))
+ {
+ if (cn->mksymlink)
+ {
+ file->nn->node = cn;
+ cn->mksymlink (user, file, file->nn->symlink_path);
+ free (file->nn->symlink_path);
+ file->nn->symlink_path = NULL;
+ return 0;
+ }
+ else
+ break;
+ }
+ }
return EOPNOTSUPP;
}
@@ -389,7 +448,27 @@ error_t
netfs_attempt_mkfile (struct iouser *user, struct node *dir,
mode_t mode, struct node **np)
{
- return EOPNOTSUPP;
+ error_t err;
+ struct netnode *nn;
+
+ err = fshelp_access (&dir->nn_stat, S_IWRITE, user);
+ if (err)
+ {
+ *np = 0;
+ return err;
+ }
+
+ mutex_unlock (&dir->lock);
+
+ nn = calloc (1, sizeof (*nn));
+ if (!nn)
+ return ENOMEM;
+
+ *np = netfs_make_node (nn);
+ mutex_lock (&(*np)->lock);
+ spin_unlock (&netfs_node_refcnt_lock);
+
+ return 0;
}
@@ -413,6 +492,8 @@ error_t
netfs_attempt_readlink (struct iouser *user, struct node *np,
char *buf)
{
+ if (np->nn->node && np->nn->node->readlink)
+ return np->nn->node->readlink (user, np, buf);
return EOPNOTSUPP;
}
@@ -471,7 +552,7 @@ netfs_S_io_read (struct protid *user,
return EOPNOTSUPP;
np = user->po->np;
- if (np->nn->node->read)
+ if (np->nn->node && np->nn->node->read)
return np->nn->node->read (user, data, datalen, offset, amount);
return EOPNOTSUPP;
}
@@ -490,7 +571,7 @@ netfs_S_io_write (struct protid *user,
return EOPNOTSUPP;
np = user->po->np;
- if (np->nn->node->read)
+ if (np->nn->node && np->nn->node->write)
return np->nn->node->write (user, data, datalen, offset, amount);
return EOPNOTSUPP;
}
@@ -517,9 +598,15 @@ netfs_report_access (struct iouser *cred, struct node *np,
void netfs_node_norefs (struct node *np)
{
- if (np->nn->node->close)
- np->nn->node->close ();
- np->nn->node->node = 0;
+ if (np->nn->node)
+ {
+ if (np->nn->node->close)
+ np->nn->node->close ();
+ np->nn->node->node = 0;
+ }
+
+ if (np->nn->symlink_path)
+ free (np->nn->symlink_path);
spin_unlock (&netfs_node_refcnt_lock);
free (np->nn);
@@ -645,7 +732,7 @@ netfs_get_dirents (struct iouser *cred, struct node *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))
+ if (!add_dir_entry (cn->name, cn->id, cn->readlink ? DT_LNK : DT_CHR))
break;
}
@@ -689,6 +776,9 @@ console_create_consnode (const char *name, consnode_t *cn)
return ENOMEM;
}
+ (*cn)->readlink = NULL;
+ (*cn)->mksymlink = NULL;
+
return 0;
}
diff --git a/console-client/trans.h b/console-client/trans.h
index 1b5156ae..f781e31f 100644
--- a/console-client/trans.h
+++ b/console-client/trans.h
@@ -54,6 +54,12 @@ struct consnode
/* The demuxer used for this node. */
int (*demuxer) (mach_msg_header_t *inp, mach_msg_header_t *outp);
+ /* Called when the symlink is read */
+ error_t (*readlink) (struct iouser *user, struct node *np, char *buf);
+
+ /* Called when the symlink is written */
+ error_t (*mksymlink) (struct iouser *cred, struct node *np, char *name);
+
struct consnode *next;
};