aboutsummaryrefslogtreecommitdiff
path: root/utils/settrans.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/settrans.c')
-rw-r--r--utils/settrans.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/utils/settrans.c b/utils/settrans.c
new file mode 100644
index 00000000..408849a3
--- /dev/null
+++ b/utils/settrans.c
@@ -0,0 +1,216 @@
+/* Set a file's translator.
+
+ Copyright (C) 1995, 96, 97, 98 Free Software Foundation, Inc.
+
+ Written by Miles Bader <miles@gnu.ai.mit.edu>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <hurd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <argp.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <error.h>
+#include <argz.h>
+#include <hurd/fshelp.h>
+#include <version.h>
+
+const char *argp_program_version = STANDARD_HURD_VERSION (settrans);
+
+#define DEFAULT_TIMEOUT 60
+
+#define _STRINGIFY(arg) #arg
+#define STRINGIFY(arg) _STRINGIFY (arg)
+
+static struct argp_option options[] =
+{
+ {"active", 'a', 0, 0, "Set NODE's active translator" },
+ {"passive", 'p', 0, 0, "Set NODE's passive translator" },
+ {"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"},
+
+ {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"},
+
+ {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"},
+ {"nosync", 'S', 0, 0, "Don't sync it before killing it"},
+
+ {0, 0}
+};
+static char *args_doc = "NODE [TRANSLATOR ARG...]";
+static char *doc = "Set the passive/active translator on NODE."
+"\vBy default the passive translator is set.";
+
+/* ---------------------------------------------------------------- */
+
+int
+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;
+ int 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;
+ int excl = 0;
+ int timeout = DEFAULT_TIMEOUT * 1000; /* ms */
+
+ /* 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 */
+ {
+ 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 '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 '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;
+ }
+ struct argp argp = {options, parse_opt, args_doc, doc};
+
+ argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0);
+
+ if (!active && !passive)
+ 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);
+
+ 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)
+ {
+ /* 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)
+ {
+ if (pause)
+ {
+ fprintf (stderr, "Pausing...");
+ getchar ();
+ }
+
+ node = file_name_lookup (node_name, flags | lookup_flags, 0666);
+ if (node == MACH_PORT_NULL)
+ {
+ 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);
+ 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);
+ }
+
+ 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);
+
+ return 0;
+}