diff options
author | Roland McGrath <roland@gnu.org> | 1999-11-08 20:50:24 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1999-11-08 20:50:24 +0000 |
commit | bacd54d884a2e5f5675c83865ea33a899688582d (patch) | |
tree | 455d8aeda109269987b0a7873564bef047d47d7c | |
parent | 1d852b4d44ac8eeb55568ed17032d1991c993757 (diff) |
1999-11-08 Roland McGrath <roland@baalperazim.frob.com>
* hello.c: New file. From Gord with some cleanups and hacks from me.
* Makefile (targets, SRCS): Add hello, hello.c.
(hello): Add appropriate deps.
-rw-r--r-- | trans/Makefile | 11 | ||||
-rw-r--r-- | trans/hello.c | 284 |
2 files changed, 290 insertions, 5 deletions
diff --git a/trans/Makefile b/trans/Makefile index 5d5900fa..14091d72 100644 --- a/trans/Makefile +++ b/trans/Makefile @@ -1,5 +1,5 @@ # -# Copyright (C) 1994, 1995, 1996, 1997 Free Software Foundation +# Copyright (C) 1994,95,96,97,99 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -18,9 +18,10 @@ dir := trans makemode := servers -targets = symlink firmlink ifsock magic null fifo new-fifo fwd crash password +targets = symlink firmlink ifsock magic null fifo new-fifo fwd crash \ + password hello SRCS = ifsock.c symlink.c magic.c null.c fifo.c new-fifo.c fwd.c \ - crash.c firmlink.c password.c + crash.c firmlink.c password.c hello.c OBJS = $(SRCS:.c=.o) fsysServer.o ifsockServer.o passwordServer.o HURDLIBS=ports trivfs threads fshelp pipe ihash shouldbeinlibc password-LDLIBS = $(LIBCRYPT) @@ -35,8 +36,8 @@ password: passwordServer.o crash password: ../libports/libports.a ../libtrivfs/libtrivfs.a ../libthreads/libthreads.a ../libfshelp/libfshelp.a fifo new-fifo: ../libpipe/libpipe.a fwd new-fifo: ../libfshelp/libfshelp.a ../libports/libports.a -magic null ifsock fifo new-fifo firmlink: ../libtrivfs/libtrivfs.a ../libfshelp/libfshelp.a ../libports/libports.a ../libihash/libihash.a +hello magic null ifsock fifo new-fifo firmlink: ../libtrivfs/libtrivfs.a ../libfshelp/libfshelp.a ../libports/libports.a ../libihash/libihash.a $(targets): ../libshouldbeinlibc/libshouldbeinlibc.a -magic fwd null ifsock fifo new-fifo firmlink: ../libthreads/libthreads.a +hello magic fwd null ifsock fifo new-fifo firmlink: ../libthreads/libthreads.a $(targets): %: %.o diff --git a/trans/hello.c b/trans/hello.c new file mode 100644 index 00000000..f4f0e5e6 --- /dev/null +++ b/trans/hello.c @@ -0,0 +1,284 @@ +/* hello.c - A trivial single-file translator + Copyright (C) 1998, 1999 Free Software Foundation, Inc. + Gordon Matzigkeit <gord@fig.org>, 1999 + 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 */ + +#define _GNU_SOURCE 1 + +#include <hurd/trivfs.h> +#include <stdio.h> +#include <argp.h> +#include <argz.h> +#include <error.h> +#include <string.h> +#include <fcntl.h> +#include <sys/mman.h> + +/* The message we return when we are read. */ +static const char hello[] = "Hello, world!\n"; +static char *contents = (char *) hello; +static size_t contents_len = sizeof hello - 1; + +/* Trivfs hooks. */ +int trivfs_fstype = FSTYPE_MISC; +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; + +/* NOTE: This example is not robust: it is possible to trigger some + assertion failures because we don't implement the following: + + $ cd /src/hurd/libtrivfs + $ grep -l 'assert.*!trivfs_support_read' *.c | + xargs grep '^trivfs_S_' | sed 's/^[^:]*:\([^ ]*\).*$/\1/' + trivfs_S_io_get_icky_async_id + trivfs_S_io_async + trivfs_S_io_map + trivfs_S_io_get_openmodes + trivfs_S_io_clear_some_openmodes + trivfs_S_io_set_some_openmodes + trivfs_S_io_set_all_openmodes + trivfs_S_io_get_owner + trivfs_S_io_mod_owner + trivfs_S_io_readable + trivfs_S_io_select + $ + + For that reason, you should run this as an active translator + `settrans -ac testnode /path/to/thello' so that you can see the + error messages when they appear. */ + +/* A hook for us to keep track of the file descriptor state. */ +struct open +{ + off_t offs; +}; + +void +trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st) +{ + /* Mark the node as a read-only plain file. */ + st->st_mode &= ~(S_IFMT | ALLPERMS); + st->st_mode |= (S_IFREG | S_IRUSR | S_IRGRP | S_IROTH); + st->st_size = sizeof (hello) - 1; +} + +error_t +trivfs_goaway (struct trivfs_control *cntl, int flags) +{ + exit (0); +} + + +static error_t +open_hook (struct trivfs_peropen *peropen) +{ + struct open *op = malloc (sizeof (struct open)); + if (op == NULL) + return ENOMEM; + + /* Initialize the offset. */ + op->offs = 0; + peropen->hook = op; + return 0; +} + + +static void +close_hook (struct trivfs_peropen *peropen) +{ + free (peropen->hook); +} + + +/* 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, + vm_address_t *data, mach_msg_type_number_t *data_len, + off_t offs, mach_msg_type_number_t amount) +{ + struct open *op; + + /* Deny access if they have bad credentials. */ + if (! cred) + return EOPNOTSUPP; + else if (! (cred->po->openmodes & O_READ)) + return EBADF; + + /* Get the offset. */ + op = cred->po->hook; + if (offs == -1) + offs = op->offs; + + /* Prune the amount they want to read. */ + if (offs > contents_len) + offs = contents_len; + if (offs + amount > contents_len) + amount = contents_len - offs; + + if (amount > 0) + { + /* Possibly allocate a new buffer. */ + if (*data_len < amount) + *data = (vm_address_t) mmap (0, amount, PROT_READ|PROT_WRITE, + MAP_ANON, 0, 0); + + /* Copy the constant data into the buffer. */ + memcpy ((char *) *data, contents + offs, amount); + + /* Update the saved offset. */ + op->offs += amount; + } + + *data_len = amount; + 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) +{ + struct open *op; + error_t err = 0; + if (! cred) + return EOPNOTSUPP; + + op = cred->po->hook; + switch (whence) + { + case SEEK_SET: + op->offs = offs; break; + case SEEK_CUR: + op->offs += offs; break; + case SEEK_END: + op->offs = contents_len - offs; break; + default: + err = EINVAL; + } + + if (! err) + *new_offs = op->offs; + + return err; +} + + +/* 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; + + +/* Options processing. We accept the same options on the command line + and from fsys_set_options. */ + +static const struct argp_option options[] = +{ + {"contents", 'c', "STRING", 0, "Specify the contents of the virtual file"}, + {0} +}; + +static error_t +parse_opt (int opt, char *arg, struct argp_state *state) +{ + switch (opt) + { + default: + return ARGP_ERR_UNKNOWN; + case ARGP_KEY_INIT: + case ARGP_KEY_SUCCESS: + case ARGP_KEY_ERROR: + break; + + case 'c': + { + char *new = strdup (arg); + if (new == NULL) + return ENOMEM; + if (contents != hello) + free (contents); + contents = new; + contents_len = strlen (new); + break; + } + } + return 0; +} + +/* This will be called from libtrivfs to help construct the answer + to an fsys_get_options RPC. */ +error_t +trivfs_append_args (struct trivfs_control *fsys, + char **argz, size_t *argz_len) +{ + error_t err; + char *opt; + + if (asprintf (&opt, "--contents=%s", contents) < 0) + return ENOMEM; + + err = argz_add (argz, argz_len, opt); + + free (opt); + + return err; +} + +static struct argp hello_argp = { options, parse_opt, 0, 0 }; + +/* Setting this variable makes libtrivfs use our argp to + parse options passed in an fsys_set_options RPC. */ +struct argp *trivfs_runtime_argp = &hello_argp; + + +int +main (int argc, char **argv) +{ + error_t err; + mach_port_t bootstrap; + struct trivfs_control *fsys; + + /* We use the same argp for options available at startup + as for options we'll accept in an fsys_set_options RPC. */ + argp_parse (&hello_argp, argc, argv, 0, 0, 0); + + task_get_bootstrap_port (mach_task_self (), &bootstrap); + if (bootstrap == MACH_PORT_NULL) + error (1, 0, "Must be started as a translator"); + + /* Reply to our parent */ + err = trivfs_startup (bootstrap, 0, 0, 0, 0, 0, &fsys); + mach_port_deallocate (mach_task_self (), bootstrap); + if (err) + error (3, err, "trivfs_startup"); + + /* Launch. */ + ports_manage_port_operations_one_thread (fsys->pi.bucket, trivfs_demuxer, 0); + + return 0; +} |