diff options
Diffstat (limited to 'utils/settrans.c')
-rw-r--r-- | utils/settrans.c | 171 |
1 files changed, 130 insertions, 41 deletions
diff --git a/utils/settrans.c b/utils/settrans.c index ff264a5b..a8814016 100644 --- a/utils/settrans.c +++ b/utils/settrans.c @@ -1,8 +1,7 @@ /* Set a file's translator. - Copyright (C) 1995, 1996 Free Software Foundation, Inc. - - Written by Miles Bader <miles@gnu.ai.mit.edu> + Copyright (C) 1995,96,97,98,2001,02 Free Software Foundation, Inc. + Written by Miles Bader <miles@gnu.org> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -23,14 +22,21 @@ #include <stdlib.h> #include <string.h> #include <argp.h> +#include <error.h> #include <fcntl.h> #include <unistd.h> #include <error.h> #include <argz.h> #include <hurd/fshelp.h> +#include <hurd/process.h> +#include <version.h> + +#include <hurd/lookup.h> +#include <hurd/fsys.h> + -char *argp_program_version = "settrans 1.0 (GNU " HURD_RELEASE ")"; +const char *argp_program_version = STANDARD_HURD_VERSION (settrans); #define DEFAULT_TIMEOUT 60 @@ -39,33 +45,41 @@ char *argp_program_version = "settrans 1.0 (GNU " HURD_RELEASE ")"; static struct argp_option options[] = { - {"active", 'a', 0, 0, "Set NODE's active translator", 1}, - {"passive", 'p', 0, 0, "Set NODE's passive translator"}, - {"create", 'c', 0, 0, "Create NODE if it doesn't exist"}, + {"active", 'a', 0, 0, "Start TRANSLATOR and set it as NODE's active translator" }, + {"passive", 'p', 0, 0, "Change NODE's passive translator record (default)" }, + {"create", 'c', 0, 0, "Create NODE if it doesn't exist" }, {"dereference", 'L', 0, 0, "If a translator exists, put the new one on top"}, {"pause", 'P', 0, 0, "When starting an active translator, prompt and" " wait for a newline on stdin before completing the startup handshake"}, {"timeout", 't',"SEC",0, "Timeout for translator startup, in seconds" " (default " STRINGIFY (DEFAULT_TIMEOUT) "); 0 means no timeout"}, - {"exclusive", 'x', 0, 0, "Only set the translator if there is none already"}, + {"exclusive", 'x', 0, 0, "Only set the translator if there is not one already"}, + {"orphan", 'o', 0, 0, "Disconnect old translator from the filesystem " + "(do not ask it to go away)"}, + + {"chroot", 'C', 0, 0, + "Instead of setting the node's translator, take following arguments up to" + " `--' and run that command chroot'd to the translated node."}, {0,0,0,0, "When setting the passive translator, if there's an active translator:"}, - {"goaway", 'g', 0, 0, "Make the active translator go away"}, - {"keep-active", 'k', 0, 0, "Leave the existing active translator running"}, + {"goaway", 'g', 0, 0, "Ask the active translator to go away"}, + {"keep-active", 'k', 0, 0, "Leave any existing active translator running"}, - {0,0,0,0, "When an active translator is told to go away:", 2}, + {0,0,0,0, "When an active translator is told to go away:"}, {"recursive", 'R', 0, 0, "Shutdown its children too"}, - {"force", 'f', 0, 0, "If it doesn't want to die, force it"}, + {"force", 'f', 0, 0, "Ask it to ignore current users and shutdown " + "anyway." }, {"nosync", 'S', 0, 0, "Don't sync it before killing it"}, {0, 0} }; static char *args_doc = "NODE [TRANSLATOR ARG...]"; -static char *doc = "By default the passive translator is set."; +static char *doc = "Set the passive/active translator on NODE." +"\vBy default the passive translator is set."; /* ---------------------------------------------------------------- */ -void +int main(int argc, char *argv[]) { error_t err; @@ -76,7 +90,7 @@ main(int argc, char *argv[]) /* The translator's arg vector, in '\0' separated format. */ char *argz = 0; - int argz_len = 0; + size_t argz_len = 0; /* The control port for any active translator we start up. */ fsys_t active_control = MACH_PORT_NULL; @@ -88,9 +102,11 @@ main(int argc, char *argv[]) int goaway_flags = 0; /* Various option flags. */ - int passive = 0, active = 0, keep_active = 0, pause = 0, kill_active = 0; + int passive = 0, active = 0, keep_active = 0, pause = 0, kill_active = 0, + orphan = 0; int excl = 0; int timeout = DEFAULT_TIMEOUT * 1000; /* ms */ + char **chroot_command = 0; /* Parse our options... */ error_t parse_opt (int key, char *arg, struct argp_state *state) @@ -120,6 +136,32 @@ main(int argc, char *argv[]) case 'g': kill_active = 1; break; case 'x': excl = 1; break; case 'P': pause = 1; break; + case 'o': orphan = 1; 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 'c': lookup_flags |= O_CREAT; break; case 'L': lookup_flags &= ~O_NOTRANS; break; @@ -140,49 +182,63 @@ main(int argc, char *argv[]) argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0); - if (!active && !passive) + 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); + 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 (active && argz_len > 0) { + /* 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 ((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) + mach_msg_type_name_t *underlying_type, + task_t task, void *cookie) { if (pause) { - fprintf (stderr, "Pausing..."); + fprintf (stderr, "Translator pid: %d\nPausing...", + task2pid (task)); getchar (); } node = file_name_lookup (node_name, flags | lookup_flags, 0666); if (node == MACH_PORT_NULL) - return errno; + { + open_err = errno; + return open_err; + } *underlying = node; *underlying_type = MACH_MSG_TYPE_COPY_SEND; return 0; } - err = fshelp_start_translator (open_node, argz, argz, argz_len, timeout, - &active_control); + err = fshelp_start_translator (open_node, NULL, argz, argz, argz_len, + timeout, &active_control); if (err) - error(4, err, "%s", argz); + /* 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 { @@ -191,13 +247,46 @@ main(int argc, char *argv[]) error(1, errno, "%s", node_name); } - 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 (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) + { + /* 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; + err = fsys_getroot (active_control, + MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND, + NULL, 0, NULL, 0, 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 ("/")) + error (8, errno, "cannot chdir to new root"); + + execvp (chroot_command[0], chroot_command); + error (8, errno, "cannot execute %s", chroot_command[0]); + } - exit(0); + return 0; } |