[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] libhurdutil: New library containing utils to be used by Guix.
From: |
manolis837 |
Subject: |
[PATCH] libhurdutil: New library containing utils to be used by Guix. |
Date: |
Wed, 25 May 2016 18:05:57 +0300 |
From: Manolis Ragkousis <manolis837@gmail.com>
* libhurdutil/hurdutil.h: New file.
* libhurdutil/settrans.c: New file.
* libhurdutil/Makefile: New file.
* utils/Makefile (HURDLIBS, settrans): Use the new library.
* utils/settrans.c: Update to use the new library.
* Makefile: (lib-subdirs): Add library.
---
Makefile | 2 +-
libhurdutil/Makefile | 28 +++
libhurdutil/hurdutil.h | 78 ++++++++
libhurdutil/settrans.c | 377 +++++++++++++++++++++++++++++++++++++++
utils/Makefile | 4 +-
utils/settrans.c | 475 +++++++++++--------------------------------------
6 files changed, 594 insertions(+), 370 deletions(-)
create mode 100644 libhurdutil/Makefile
create mode 100644 libhurdutil/hurdutil.h
create mode 100644 libhurdutil/settrans.c
diff --git a/Makefile b/Makefile
index d48baaa..e712767 100644
--- a/Makefile
+++ b/Makefile
@@ -29,7 +29,7 @@ include ./Makeconf
lib-subdirs = libshouldbeinlibc libihash libiohelp libports libthreads \
libpager libfshelp libdiskfs libtrivfs libps \
libnetfs libpipe libstore libhurdbugaddr libftpconn libcons \
- libhurd-slab
+ libhurd-slab libhurdutil
# Hurd programs
prog-subdirs = auth proc exec term \
diff --git a/libhurdutil/Makefile b/libhurdutil/Makefile
new file mode 100644
index 0000000..2e0e642
--- /dev/null
+++ b/libhurdutil/Makefile
@@ -0,0 +1,28 @@
+# Copyright (C) 2016 Free Software Foundation, Inc.
+#
+# 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+dir := libhurdutil
+makemode := library
+
+libname := libhurdutil
+SRCS = settrans.c
+installhdrs = hurdutil.h
+
+OBJS = $(SRCS:.c=.o)
+
+include ../Makeconf
diff --git a/libhurdutil/hurdutil.h b/libhurdutil/hurdutil.h
new file mode 100644
index 0000000..5786cff
--- /dev/null
+++ b/libhurdutil/hurdutil.h
@@ -0,0 +1,78 @@
+/* hurdutil.h - Hurd utils interface.
+ Copyright (C) 2016 Free Software Foundation, Inc.
+ Written by Manolis Fragkiskos Ragkousis <manolis837@gmail.com>.
+
+ 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 the GNU Hurd; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _HURD_UTIL_H
+#define _HURD_UTIL_H
+
+#include <errno.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#include <hurd/fsys.h>
+
+struct settrans_flags
+{
+ /* The name of the node we're putting the translator on. */
+ char *node_name;
+
+ /* Flags to pass to file_set_translator. */
+ int lookup_flags;
+ int goaway_flags;
+
+ /* Various option flags. */
+ int passive;
+ int active;
+ int keep_active;
+ int pause;
+ int kill_active;
+ int orphan;
+ int start;
+ int stack;
+ int excl;
+ int timeout;
+ char *pid_file;
+ char *underlying_node_name;
+ int underlying_lookup_flags;
+ char **chroot_command;
+ char *chroot_chdir;
+
+ /* The translator's arg vector, in '\0' separated format. */
+ char *argz;
+ size_t argz_len;
+};
+typedef struct settrans_flags *settrans_flags_t;
+
+/* Initialize the flags to be used. */
+void settrans_flags_init (settrans_flags_t flags);
+
+/* Release the memory allocated. */
+void settrans_flags_cleanup (settrans_flags_t flags);
+
+/* Create the struct containing the flags and initialize them.
+ If a memory allocation error occurs, ENOMEM is returned,
+ otherwise 0.*/
+error_t settrans_flags_create (settrans_flags_t *flags);
+
+/* Set a translator according to the flags passed. On success return 0. */
+error_t settrans(settrans_flags_t flags);
+
+#endif /* _HURD_UTIL_H */
diff --git a/libhurdutil/settrans.c b/libhurdutil/settrans.c
new file mode 100644
index 0000000..eeaa964
--- /dev/null
+++ b/libhurdutil/settrans.c
@@ -0,0 +1,377 @@
+/* settrans.c - Set a file's translator.
+
+ Copyright (C) 1995,96,97,98,2001,02,13,14,16
+ Free Software Foundation, Inc.
+ Written by Miles Bader <miles@gnu.org>
+ Written by Manolis Fragkiskos Ragkousis <manolis837@gmail.com>.
+
+ 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 the GNU Hurd; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <argp.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include <hurd.h>
+#include <error.h>
+#include <argz.h>
+#include <hurd/fshelp.h>
+#include <hurd/lookup.h>
+
+
+#include "hurdutil.h"
+
+#define DEFAULT_TIMEOUT 60
+
+/* Authentication of the current process. */
+uid_t *uids;
+gid_t *gids;
+size_t uids_len, gids_len;
+
+/* Initialize and populate the uids and gids vectors. */
+error_t
+get_credentials (void)
+{
+ /* Fetch uids... */
+ uids_len = geteuids (0, 0);
+ if (uids_len < 0)
+ return errno;
+
+ uids = malloc (uids_len * sizeof (uid_t));
+ if (! uids)
+ return ENOMEM;
+
+ uids_len = geteuids (uids_len, uids);
+ if (uids_len < 0)
+ return errno;
+
+ /* ... and gids. */
+ gids_len = getgroups (0, 0);
+ if (gids_len < 0)
+ return errno;
+
+ gids = malloc (gids_len * sizeof (gid_t));
+ if (! uids)
+ return ENOMEM;
+
+ gids_len = getgroups (gids_len, gids);
+ if (gids_len < 0)
+ return errno;
+
+ return 0;
+}
+
+/* ---------------------------------------------------------------- */
+
+void
+settrans_flags_init (settrans_flags_t flags)
+{
+ flags->node_name = 0;
+
+ flags->lookup_flags = O_NOTRANS;
+ flags->goaway_flags = 0;
+
+ flags->passive = 0;
+ flags->active = 0;
+ flags->keep_active = 0;
+ flags->pause = 0;
+ flags->kill_active = 0;
+ flags->orphan = 0;
+ flags->start = 0;
+ flags->stack = 0;
+ flags->excl = 0;
+ flags->timeout = DEFAULT_TIMEOUT * 1000; /* ms */
+ flags->pid_file = 0;
+ flags->underlying_node_name = NULL;
+ flags->chroot_command = 0;
+ flags->chroot_chdir = "/";
+
+ flags->argz;
+ flags->argz_len;
+}
+
+void
+settrans_flags_cleanup (settrans_flags_t flags)
+{
+ free(flags);
+}
+
+error_t
+settrans_flags_create (settrans_flags_t *flags)
+{
+ *flags = malloc (sizeof (struct settrans_flags));
+ if (*flags == NULL)
+ return ENOMEM;
+
+ settrans_flags_init(*flags);
+
+ return 0;
+}
+
+error_t settrans(settrans_flags_t flags)
+{
+ error_t err;
+
+ /* The filesystem node we're putting a translator on. */
+ char *node_name = flags->node_name;
+ file_t node;
+
+ /* The translator's arg vector, in '\0' separated format. */
+ char *argz = flags->argz;
+ size_t argz_len = flags->argz_len;
+
+ /* The control port for any active translator we start up. */
+ fsys_t active_control = MACH_PORT_NULL;
+
+ /* Flags to pass to file_set_translator. */
+ int active_flags = 0;
+ int passive_flags = 0;
+ int lookup_flags = flags->lookup_flags;
+ int goaway_flags = flags->goaway_flags;
+
+ /* Various option flags. */
+ int passive = flags->passive;
+ int active = flags->active;
+ int keep_active = flags->keep_active;
+ int pause = flags->pause;
+ int kill_active = flags->kill_active;
+ int orphan = flags->orphan;
+ int start = flags->start;
+ int stack = flags->stack;
+ char *pid_file = flags->pid_file;
+ int excl = flags->excl;
+ int timeout = flags->timeout; /* ms */
+ char *underlying_node_name = flags->underlying_node_name;
+ int underlying_lookup_flags = flags->underlying_lookup_flags;
+ char **chroot_command = flags->chroot_command;
+ char *chroot_chdir = flags->chroot_chdir;
+
+ if (stack)
+ {
+ underlying_node_name = node_name;
+ underlying_lookup_flags = lookup_flags && ~O_NOTRANS;
+ }
+ else
+ underlying_lookup_flags = lookup_flags;
+
+
+ if (!active && !passive && !chroot_command)
+ passive = 1; /* By default, set the passive translator. */
+
+ if (passive)
+ passive_flags = FS_TRANS_SET | (excl ? FS_TRANS_EXCL : 0);
+ if (active)
+ active_flags = FS_TRANS_SET | (excl ? FS_TRANS_EXCL : 0)
+ | (orphan ? FS_TRANS_ORPHAN : 0);
+
+ if (passive && !active)
+ {
+ /* When setting just the passive, decide what to do with any active. */
+ if (kill_active)
+ /* Make it go away. */
+ active_flags = FS_TRANS_SET;
+ else if (! keep_active)
+ /* Ensure that there isn't one. */
+ active_flags = FS_TRANS_SET | FS_TRANS_EXCL;
+ }
+
+ if (start)
+ {
+ /* Retrieve the passive translator record in argz. */
+ mach_port_t node = file_name_lookup (node_name, lookup_flags, 0);
+ if (node == MACH_PORT_NULL)
+ error (4, errno, "%s", node_name);
+
+ char buf[1024];
+ argz = buf;
+ argz_len = sizeof (buf);
+
+ err = file_get_translator (node, &argz, &argz_len);
+ if (err == EINVAL)
+ error (4, 0, "%s: no passive translator record found", node_name);
+ if (err)
+ error (4, err, "%s", node_name);
+
+ mach_port_deallocate (mach_task_self (), node);
+ }
+
+ if ((active || chroot_command) && argz_len > 0)
+ {
+ /* Error during file lookup; we use this to avoid duplicating error
+ messages. */
+ error_t open_err = 0;
+
+ /* The callback to start_translator opens NODE as a side effect. */
+ error_t open_node (int flags,
+ mach_port_t *underlying,
+ mach_msg_type_name_t *underlying_type,
+ task_t task, void *cookie)
+ {
+ if (pause)
+ {
+ fprintf (stderr, "Translator pid: %d\nPausing...",
+ task2pid (task));
+ getchar ();
+ }
+
+ if (pid_file != NULL)
+ {
+ FILE *h;
+ h = fopen (pid_file, "w");
+ if (h == NULL)
+ error (4, errno, "Failed to open pid file");
+
+ fprintf (h, "%i\n", task2pid (task));
+ fclose (h);
+ }
+
+ node = file_name_lookup (node_name, flags | lookup_flags, 0666);
+ if (node == MACH_PORT_NULL)
+ {
+ open_err = errno;
+ return open_err;
+ }
+
+ if (underlying_node_name)
+ {
+ *underlying = file_name_lookup (underlying_node_name,
+ flags | underlying_lookup_flags,
+ 0666);
+ if (! MACH_PORT_VALID (*underlying))
+ {
+ /* For the error message. */
+ node_name = underlying_node_name;
+ open_err = errno;
+ return open_err;
+ }
+ }
+ else
+ *underlying = node;
+ *underlying_type = MACH_MSG_TYPE_COPY_SEND;
+
+ return 0;
+ }
+ err = fshelp_start_translator (open_node, NULL, argz, argz, argz_len,
+ timeout, &active_control);
+ if (err)
+ /* If ERR is due to a problem opening the translated node, we print
+ that name, otherwise, the name of the translator. */
+ error(4, err, "%s", (err == open_err) ? node_name : argz);
+ }
+ else
+ {
+ node = file_name_lookup(node_name, lookup_flags, 0666);
+ if (node == MACH_PORT_NULL)
+ error(1, errno, "%s", node_name);
+ }
+
+ if (active || passive)
+ {
+ err = file_set_translator (node,
+ passive_flags, active_flags, goaway_flags,
+ argz, argz_len,
+ active_control, MACH_MSG_TYPE_COPY_SEND);
+ if (err)
+ {
+ error (5, err, "%s", node_name);
+ }
+
+ }
+
+ if (chroot_command)
+ {
+ pid_t child;
+ int status;
+ switch ((child = fork ()))
+ {
+ case -1:
+ error (6, errno, "fork");
+
+ case 0:; /* Child. */
+ /* We will act as the parent filesystem would for a lookup
+ of the active translator's root node, then use this port
+ as our root directory while we exec the command. */
+
+ char retry_name[1024]; /* XXX */
+ retry_type do_retry;
+ mach_port_t root;
+ file_t executable;
+ char *prefixed_name;
+
+ err = get_credentials ();
+ if (err)
+ error (6, err, "getting credentials");
+
+ err = fsys_getroot (active_control,
+ MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND,
+ uids, uids_len, gids, gids_len, 0,
+ &do_retry, retry_name, &root);
+ mach_port_deallocate (mach_task_self (), active_control);
+ if (err)
+ error (6, err, "fsys_getroot");
+ err = hurd_file_name_lookup_retry (&_hurd_ports_use, &getdport, 0,
+ do_retry, retry_name, 0, 0,
+ &root);
+ if (err)
+ error (6, err, "cannot resolve root port");
+
+ if (setcrdir (root))
+ error (7, errno, "cannot install root port");
+ mach_port_deallocate (mach_task_self (), root);
+ if (chdir (chroot_chdir))
+ error (8, errno, "%s", chroot_chdir);
+
+ /* Lookup executable in PATH. */
+ executable = file_name_path_lookup (chroot_command[0],
+ getenv ("PATH"),
+ O_EXEC, 0,
+ &prefixed_name);
+ if (MACH_PORT_VALID (executable))
+ {
+ err = mach_port_deallocate (mach_task_self (), executable);
+ assert_perror (err);
+ if (prefixed_name)
+ chroot_command[0] = prefixed_name;
+ }
+
+ execvp (chroot_command[0], chroot_command);
+ error (8, errno, "cannot execute %s", chroot_command[0]);
+ break;
+
+ default: /* Parent. */
+ if (waitpid (child, &status, 0) != child)
+ error (8, errno, "waitpid on %d", child);
+
+ err = fsys_goaway (active_control, goaway_flags);
+ if (err && err != EBUSY)
+ error (9, err, "fsys_goaway");
+
+ if (WIFSIGNALED (status))
+ error (WTERMSIG (status) + 128, 0,
+ "%s for child %d", strsignal (WTERMSIG (status)), child);
+ if (WEXITSTATUS (status) != 0)
+ error (WEXITSTATUS (status), 0,
+ "Error %d for child %d", WEXITSTATUS (status), child);
+ }
+ }
+ return 0;
+}
diff --git a/utils/Makefile b/utils/Makefile
index d2ef9e8..be10cf6 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -34,7 +34,7 @@ SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c
rmauth.c \
nullauth.c match-options.c msgids.c rpcscan.c
OBJS = $(filter-out %.sh,$(SRCS:.c=.o))
-HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc
+HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc hurdutil
LDLIBS += -lpthread
login-LDLIBS = -lutil -lcrypt
addauth-LDLIBS = -lcrypt
@@ -60,7 +60,7 @@ storeinfo storecat storeread: ../libstore/libstore.a
ftpcp ftpdir: ../libftpconn/libftpconn.a
mount umount: ../libihash/libihash.a
settrans: ../libfshelp/libfshelp.a ../libihash/libihash.a \
- ../libports/libports.a
+ ../libports/libports.a ../libhurdutil/libhurdutil.a
ps w ids settrans syncfs showtrans fsysopts storeinfo login vmstat portinfo \
devprobe vminfo addauth rmauth setauth unsu ftpcp ftpdir storeread \
storecat msgport mount umount nullauth rpctrace: \
diff --git a/utils/settrans.c b/utils/settrans.c
index ee7cba5..14dd520 100644
--- a/utils/settrans.c
+++ b/utils/settrans.c
@@ -3,6 +3,7 @@
Copyright (C) 1995,96,97,98,2001,02,13,14
Free Software Foundation, Inc.
Written by Miles Bader <miles@gnu.org>
+ Revised by Manolis Fragkiskos Ragkousis <manolis837@gmail.com>.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -38,11 +39,10 @@
#include <hurd/lookup.h>
#include <hurd/fsys.h>
+#include <hurd/hurdutil.h>
const char *argp_program_version = STANDARD_HURD_VERSION (settrans);
-#define DEFAULT_TIMEOUT 60
-
#define _STRINGIFY(arg) #arg
#define STRINGIFY(arg) _STRINGIFY (arg)
@@ -93,44 +93,6 @@ static char *args_doc = "NODE [TRANSLATOR ARG...]";
static char *doc = "Set the passive/active translator on NODE."
"\vBy default the passive translator is set.";
-/* Authentication of the current process. */
-uid_t *uids;
-gid_t *gids;
-size_t uids_len, gids_len;
-
-/* Initialize and populate the uids and gids vectors. */
-error_t
-get_credentials (void)
-{
- /* Fetch uids... */
- uids_len = geteuids (0, 0);
- if (uids_len < 0)
- return errno;
-
- uids = malloc (uids_len * sizeof (uid_t));
- if (! uids)
- return ENOMEM;
-
- uids_len = geteuids (uids_len, uids);
- if (uids_len < 0)
- return errno;
-
- /* ... and gids. */
- gids_len = getgroups (0, 0);
- if (gids_len < 0)
- return errno;
-
- gids = malloc (gids_len * sizeof (gid_t));
- if (! uids)
- return ENOMEM;
-
- gids_len = getgroups (gids_len, gids);
- if (gids_len < 0)
- return errno;
-
- return 0;
-}
-
/* ---------------------------------------------------------------- */
int
@@ -138,343 +100,122 @@ main(int argc, char *argv[])
{
error_t err;
- /* The filesystem node we're putting a translator on. */
- char *node_name = 0;
- file_t node;
-
- /* The translator's arg vector, in '\0' separated format. */
- char *argz = 0;
- size_t argz_len = 0;
-
- /* The control port for any active translator we start up. */
- fsys_t active_control = MACH_PORT_NULL;
-
- /* Flags to pass to file_set_translator. */
- int active_flags = 0;
- int passive_flags = 0;
- int lookup_flags = O_NOTRANS;
- int goaway_flags = 0;
-
- /* Various option flags. */
- int passive = 0, active = 0, keep_active = 0, pause = 0, kill_active = 0,
- orphan = 0;
- int start = 0;
- int stack = 0;
- char *pid_file = NULL;
- int excl = 0;
- int timeout = DEFAULT_TIMEOUT * 1000; /* ms */
- char *underlying_node_name = NULL;
- int underlying_lookup_flags;
- char **chroot_command = 0;
- char *chroot_chdir = "/";
+ /* The flags to be used to create the translator. */
+ settrans_flags_t flags;
+
+ settrans_flags_create(&flags);
/* Parse our options... */
error_t parse_opt (int key, char *arg, struct argp_state *state)
- {
- switch (key)
- {
- case ARGP_KEY_ARG:
- if (state->arg_num == 0)
- node_name = arg;
- else /* command */
- {
- if (start)
- argp_error (state, "both --start and TRANSLATOR given");
-
- error_t err =
- argz_create (state->argv + state->next - 1, &argz, &argz_len);
- if (err)
- error(3, err, "Can't create options vector");
- state->next = state->argc; /* stop parsing */
- }
- break;
-
- case ARGP_KEY_NO_ARGS:
- argp_usage (state);
- return EINVAL;
-
- case 'a': active = 1; break;
- case 's':
- start = 1;
- active = 1; /* start implies active */
- break;
- case OPT_STACK:
- stack = 1;
- active = 1; /* stack implies active */
- orphan = 1; /* stack implies orphan */
- break;
- case 'p': passive = 1; break;
- case 'k': keep_active = 1; break;
- case 'g': kill_active = 1; break;
- case 'x': excl = 1; break;
- case 'P': pause = 1; break;
- case 'F':
- pid_file = strdup (arg);
- if (pid_file == NULL)
- error(3, ENOMEM, "Failed to duplicate argument");
- break;
-
- case 'o': orphan = 1; break;
- case 'U':
- underlying_node_name = strdup (arg);
- if (underlying_node_name == NULL)
- error(3, ENOMEM, "Failed to duplicate argument");
- break;
-
- case 'C':
- if (chroot_command)
- {
- argp_error (state, "--chroot given twice");
- return EINVAL;
- }
- chroot_command = &state->argv[state->next];
- while (state->next < state->argc)
- {
- if (!strcmp (state->argv[state->next], "--"))
- {
- state->argv[state->next++] = 0;
- if (chroot_command[0] == 0)
- {
- argp_error (state,
- "--chroot must be followed by a command");
- return EINVAL;
- }
- return 0;
- }
- ++state->next;
- }
- argp_error (state, "--chroot command must be terminated with `--'");
- return EINVAL;
-
- case OPT_CHROOT_CHDIR:
- if (arg[0] != '/')
- argp_error (state, "--chroot-chdir must be absolute");
- chroot_chdir = arg;
- break;
-
- case 'c': lookup_flags |= O_CREAT; break;
- case 'L': lookup_flags &= ~O_NOTRANS; break;
-
- case 'R': goaway_flags |= FSYS_GOAWAY_RECURSE; break;
- case 'S': goaway_flags |= FSYS_GOAWAY_NOSYNC; break;
- case 'f': goaway_flags |= FSYS_GOAWAY_FORCE; break;
-
- /* Use atof so the user can specifiy fractional timeouts. */
- case 't': timeout = atof (arg) * 1000.0; break;
-
- default:
- return ARGP_ERR_UNKNOWN;
- }
- return 0;
- }
+ {
+ switch (key)
+ {
+ case ARGP_KEY_ARG:
+ if (state->arg_num == 0)
+ flags->node_name = arg;
+ else /* command */
+ {
+ if (flags->start)
+ argp_error (state, "both --start and TRANSLATOR given");
+
+ error_t err =
+ argz_create (state->argv + state->next - 1, &flags->argz,
&flags->argz_len);
+ if (err)
+ error(3, err, "Can't create options vector");
+ state->next = state->argc; /* stop parsing */
+ }
+ break;
+
+ case ARGP_KEY_NO_ARGS:
+ argp_usage (state);
+ return EINVAL;
+
+ case 'a': flags->active = 1; break;
+ case 's':
+ flags->start = 1;
+ flags->active = 1; /* start implies active */
+ break;
+ case OPT_STACK:
+ flags->stack = 1;
+ flags->active = 1; /* stack implies active */
+ flags->orphan = 1; /* stack implies orphan */
+ break;
+ case 'p': flags->passive = 1; break;
+ case 'k': flags->keep_active = 1; break;
+ case 'g': flags->kill_active = 1; break;
+ case 'x': flags->excl = 1; break;
+ case 'P': flags->pause = 1; break;
+ case 'F':
+ flags->pid_file = strdup (arg);
+ if (flags->pid_file == NULL)
+ error(3, ENOMEM, "Failed to duplicate argument");
+ break;
+
+ case 'o': flags->orphan = 1; break;
+ case 'U':
+ flags->underlying_node_name = strdup (arg);
+ if (flags->underlying_node_name == NULL)
+ error(3, ENOMEM, "Failed to duplicate argument");
+ break;
+
+ case 'C':
+ if (flags->chroot_command)
+ {
+ argp_error (state, "--chroot given twice");
+ return EINVAL;
+ }
+ flags->chroot_command = &state->argv[state->next];
+ while (state->next < state->argc)
+ {
+ if (!strcmp (state->argv[state->next], "--"))
+ {
+ state->argv[state->next++] = 0;
+ if (flags->chroot_command[0] == 0)
+ {
+ argp_error (state,
+ "--chroot must be followed by a command");
+ return EINVAL;
+ }
+ return 0;
+ }
+ ++state->next;
+ }
+ argp_error (state, "--chroot command must be terminated with `--'");
+ return EINVAL;
+
+ case OPT_CHROOT_CHDIR:
+ if (arg[0] != '/')
+ argp_error (state, "--chroot-chdir must be absolute");
+ flags->chroot_chdir = arg;
+ break;
+
+ case 'c': flags->lookup_flags |= O_CREAT; break;
+ case 'L': flags->lookup_flags &= ~O_NOTRANS; break;
+
+ case 'R': flags->goaway_flags |= FSYS_GOAWAY_RECURSE; break;
+ case 'S': flags->goaway_flags |= FSYS_GOAWAY_NOSYNC; break;
+ case 'f': flags->goaway_flags |= FSYS_GOAWAY_FORCE; break;
+
+ /* Use atof so the user can specifiy fractional timeouts. */
+ case 't': flags->timeout = atof (arg) * 1000.0; break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+ }
struct argp argp = {options, parse_opt, args_doc, doc};
argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0);
- if (stack)
- {
- underlying_node_name = node_name;
- underlying_lookup_flags = lookup_flags && ~O_NOTRANS;
- }
- else
- underlying_lookup_flags = lookup_flags;
-
- if (!active && !passive && !chroot_command)
- passive = 1; /* By default, set the passive translator. */
-
- if (passive)
- passive_flags = FS_TRANS_SET | (excl ? FS_TRANS_EXCL : 0);
- if (active)
- active_flags = FS_TRANS_SET | (excl ? FS_TRANS_EXCL : 0)
- | (orphan ? FS_TRANS_ORPHAN : 0);
-
- if (passive && !active)
- {
- /* When setting just the passive, decide what to do with any active. */
- if (kill_active)
- /* Make it go away. */
- active_flags = FS_TRANS_SET;
- else if (! keep_active)
- /* Ensure that there isn't one. */
- active_flags = FS_TRANS_SET | FS_TRANS_EXCL;
- }
-
- if (start)
- {
- /* Retrieve the passive translator record in argz. */
- mach_port_t node = file_name_lookup (node_name, lookup_flags, 0);
- if (node == MACH_PORT_NULL)
- error (4, errno, "%s", node_name);
-
- char buf[1024];
- argz = buf;
- argz_len = sizeof (buf);
-
- err = file_get_translator (node, &argz, &argz_len);
- if (err == EINVAL)
- error (4, 0, "%s: no passive translator record found", node_name);
- if (err)
- error (4, err, "%s", node_name);
-
- mach_port_deallocate (mach_task_self (), node);
- }
-
- if ((active || chroot_command) && argz_len > 0)
- {
- /* Error during file lookup; we use this to avoid duplicating error
- messages. */
- error_t open_err = 0;
-
- /* The callback to start_translator opens NODE as a side effect. */
- error_t open_node (int flags,
- mach_port_t *underlying,
- mach_msg_type_name_t *underlying_type,
- task_t task, void *cookie)
- {
- if (pause)
- {
- fprintf (stderr, "Translator pid: %d\nPausing...",
- task2pid (task));
- getchar ();
- }
-
- if (pid_file != NULL)
- {
- FILE *h;
- h = fopen (pid_file, "w");
- if (h == NULL)
- error (4, errno, "Failed to open pid file");
-
- fprintf (h, "%i\n", task2pid (task));
- fclose (h);
- }
-
- node = file_name_lookup (node_name, flags | lookup_flags, 0666);
- if (node == MACH_PORT_NULL)
- {
- open_err = errno;
- return open_err;
- }
-
- if (underlying_node_name)
- {
- *underlying = file_name_lookup (underlying_node_name,
- flags | underlying_lookup_flags,
- 0666);
- if (! MACH_PORT_VALID (*underlying))
- {
- /* For the error message. */
- node_name = underlying_node_name;
- open_err = errno;
- return open_err;
- }
- }
- else
- *underlying = node;
- *underlying_type = MACH_MSG_TYPE_COPY_SEND;
-
- return 0;
- }
- err = fshelp_start_translator (open_node, NULL, argz, argz, argz_len,
- timeout, &active_control);
- if (err)
- /* If ERR is due to a problem opening the translated node, we print
- that name, otherwise, the name of the translator. */
- error(4, err, "%s", (err == open_err) ? node_name : argz);
- }
- else
- {
- node = file_name_lookup(node_name, lookup_flags, 0666);
- if (node == MACH_PORT_NULL)
- error(1, errno, "%s", node_name);
- }
-
- if (active || passive)
+ err = settrans(flags);
+ if (err)
{
- err = file_set_translator (node,
- passive_flags, active_flags, goaway_flags,
- argz, argz_len,
- active_control, MACH_MSG_TYPE_COPY_SEND);
- if (err)
- error (5, err, "%s", node_name);
+ settrans_flags_cleanup(flags);
+ error(1, err, "Could not set translator");
}
- if (chroot_command)
- {
- pid_t child;
- int status;
- switch ((child = fork ()))
- {
- case -1:
- error (6, errno, "fork");
-
- case 0:; /* Child. */
- /* We will act as the parent filesystem would for a lookup
- of the active translator's root node, then use this port
- as our root directory while we exec the command. */
-
- char retry_name[1024]; /* XXX */
- retry_type do_retry;
- mach_port_t root;
- file_t executable;
- char *prefixed_name;
-
- err = get_credentials ();
- if (err)
- error (6, err, "getting credentials");
-
- err = fsys_getroot (active_control,
- MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND,
- uids, uids_len, gids, gids_len, 0,
- &do_retry, retry_name, &root);
- mach_port_deallocate (mach_task_self (), active_control);
- if (err)
- error (6, err, "fsys_getroot");
- err = hurd_file_name_lookup_retry (&_hurd_ports_use, &getdport, 0,
- do_retry, retry_name, 0, 0,
- &root);
- if (err)
- error (6, err, "cannot resolve root port");
-
- if (setcrdir (root))
- error (7, errno, "cannot install root port");
- mach_port_deallocate (mach_task_self (), root);
- if (chdir (chroot_chdir))
- error (8, errno, "%s", chroot_chdir);
-
- /* Lookup executable in PATH. */
- executable = file_name_path_lookup (chroot_command[0],
- getenv ("PATH"),
- O_EXEC, 0,
- &prefixed_name);
- if (MACH_PORT_VALID (executable))
- {
- err = mach_port_deallocate (mach_task_self (), executable);
- assert_perror (err);
- if (prefixed_name)
- chroot_command[0] = prefixed_name;
- }
-
- execvp (chroot_command[0], chroot_command);
- error (8, errno, "cannot execute %s", chroot_command[0]);
- break;
-
- default: /* Parent. */
- if (waitpid (child, &status, 0) != child)
- error (8, errno, "waitpid on %d", child);
-
- err = fsys_goaway (active_control, goaway_flags);
- if (err && err != EBUSY)
- error (9, err, "fsys_goaway");
-
- if (WIFSIGNALED (status))
- error (WTERMSIG (status) + 128, 0,
- "%s for child %d", strsignal (WTERMSIG (status)), child);
- if (WEXITSTATUS (status) != 0)
- error (WEXITSTATUS (status), 0,
- "Error %d for child %d", WEXITSTATUS (status), child);
- }
- }
+ settrans_flags_cleanup(flags);
return 0;
}
--
2.8.2