summaryrefslogtreecommitdiff
path: root/utils/msgport.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/msgport.c')
-rw-r--r--utils/msgport.c284
1 files changed, 183 insertions, 101 deletions
diff --git a/utils/msgport.c b/utils/msgport.c
index 10449e04..eed174b7 100644
--- a/utils/msgport.c
+++ b/utils/msgport.c
@@ -32,13 +32,13 @@
#include <version.h>
#include "pids.h"
+/* From libc (not in hurd.h) */
char *
_hurd_canonicalize_directory_name_internal (file_t thisdir,
char *buf,
size_t size);
const char *argp_program_version = STANDARD_HURD_VERSION (msgport);
-
static const struct argp_option options[] =
{
@@ -53,40 +53,73 @@ static const char args_doc[] =
+/* All command functions match this prototype. */
typedef error_t (*cmd_func_t) (pid_t pid, mach_port_t msgport,
int argc, char *argv[]);
+/* One of these is created for each command given in the command line. */
typedef struct cmd {
+ /* Function to execute for this command */
cmd_func_t f;
+
+ /* Array of arguments that will be passed to function F */
char **args;
size_t num_args;
} cmd_t;
-struct cmds_argp_params
+
+/* Execute command CMD on process PID */
+error_t
+do_cmd (pid_t pid, cmd_t cmd)
{
- cmd_t **cmds;
- size_t *num_cmds;
-};
+ error_t err;
+ mach_port_t msgport;
+ process_t proc = getproc ();
+ /* Get a msgport for PID, to which we can send requests. */
+ err = proc_getmsgport (proc, pid, &msgport);
+ if (err)
+ error (1, err, "%d: Cannot get process msgport", pid);
-
+ err = (*cmd.f) (pid, msgport, cmd.num_args, cmd.args);
+ if (err)
+ error (2, err, "%d: Cannot execute command", pid);
-static error_t
+ mach_port_deallocate (mach_task_self (), msgport);
+ return 0;
+}
+
+
+/* All these functions, whose name start with cmd_, execute some
+ commands on the process PID, by sending messages (see msg.defs) to
+ its message port, which is MSGPORT. ARGC and ARGV are as in main.
+ They return zero iff successful. */
+
+/* Print the name and value of the environment variable ARGV[0].
+ Without arguments (ARGC==0), print the names and values of all
+ environment variables. */
+error_t
cmd_getenv (pid_t pid, mach_port_t msgport, int argc, char *argv[])
{
error_t err;
+
+ /* Memory will be vm_allocated by msg_get_* if the result does not
+ fit in buf. */
char buf[1024], *data = buf;
mach_msg_type_number_t len = sizeof (buf);
+
if (argc)
{
- if ((err = msg_get_env_variable (msgport, argv[0], &data, &len)))
+ err = msg_get_env_variable (msgport, argv[0], &data, &len);
+ if (err)
return err;
printf ("%d: %s=%s\n", pid, argv[0], data);
}
- else
+ else /* get the whole environment */
{
char *p;
- if ((err = msg_get_environment (msgport, &data, &len)))
+ err = msg_get_environment (msgport, &data, &len);
+ if (err)
return err;
for (p=data; p < data + len; p = strchr (p, '\0') + 1)
printf ("%d: %s\n", pid, p);
@@ -96,35 +129,42 @@ cmd_getenv (pid_t pid, mach_port_t msgport, int argc, char *argv[])
return err;
}
-static error_t
+/* Set environment variable ARGV[0] to the value ARGV[1]. */
+error_t
cmd_setenv (pid_t pid, mach_port_t msgport, int argc, char *argv[])
{
error_t err;
task_t task;
process_t proc = getproc ();
- if ((err = proc_pid2task (proc, pid, &task)))
+ err = proc_pid2task (proc, pid, &task);
+ if (err)
return err;
err = msg_set_env_variable (msgport, task, argv[0], argv[1], 1);
mach_port_deallocate (mach_task_self (), task);
return err;
}
-static error_t
+/* Clear environment. */
+error_t
cmd_clearenv (pid_t pid, mach_port_t msgport, int argc, char *argv[])
{
error_t err;
task_t task;
process_t proc = getproc ();
- if ((err = proc_pid2task (proc, pid, &task)))
+ err = proc_pid2task (proc, pid, &task);
+ if (err)
return err;
err = msg_set_environment (msgport, task, 0, 0);
mach_port_deallocate (mach_task_self (), task);
return err;
}
-static int
+/* Convert string STR in flags for file access modes. STR should be a
+ combination of `r', `w' and `x' (for read, write and execute modes
+ respectively). Other chars are ignored. */
+int
str2flags (char *str)
{
int flags = 0;
@@ -143,21 +183,28 @@ str2flags (char *str)
return flags;
}
-static error_t
+/* Set port associated to file descriptor FD of process PID, whose
+ message port is MSGPORT, to FILE. Used by
+ cmd_{setfd,stdin,stdout,stderr}. */
+error_t
do_setfd (pid_t pid, mach_port_t msgport, size_t fd, file_t file)
{
error_t err;
task_t task;
process_t proc = getproc ();
- if ((err = proc_pid2task (proc, pid, &task)))
+ err = proc_pid2task (proc, pid, &task);
+ if (err)
return err;
err = msg_set_fd (msgport, task, fd, file, MACH_MSG_TYPE_MOVE_SEND);
mach_port_deallocate (mach_task_self (), task);
return err;
}
-static error_t
+/* Set port associated to file descriptor ARGV[0] to the file ARGV[1].
+ File access mode is given by ARGV[2] (see str2flags). If no access
+ mode is given, the default is O_RDONLY. */
+error_t
cmd_setfd (pid_t pid, mach_port_t msgport, int argc, char *argv[])
{
error_t err;
@@ -166,15 +213,18 @@ cmd_setfd (pid_t pid, mach_port_t msgport, int argc, char *argv[])
if (argc > 2)
flags = str2flags(argv[2]);
- if ((file = file_name_lookup (argv[1], flags, 0666)) ==
- MACH_PORT_NULL)
+ file = file_name_lookup (argv[1], flags, 0666);
+ if (file == MACH_PORT_NULL)
return errno;
- if ((err = do_setfd (pid, msgport, atoi (argv[0]), file)))
+ err = do_setfd (pid, msgport, atoi (argv[0]), file);
+ if (err)
mach_port_deallocate (mach_task_self (), file);
return err;
}
-static error_t
+/* Set standard input to ARGV[0]. Optionally, ARGV[1] may specify the
+ file access mode (see str2flags). The default is O_RDONLY */
+error_t
cmd_stdin (pid_t pid, mach_port_t msgport, int argc, char *argv[])
{
error_t err;
@@ -183,15 +233,18 @@ cmd_stdin (pid_t pid, mach_port_t msgport, int argc, char *argv[])
if (argc > 1)
flags = str2flags(argv[1]);
- if ((file = file_name_lookup (argv[0], flags, 0666)) ==
- MACH_PORT_NULL)
+ file = file_name_lookup (argv[0], flags, 0666);
+ if (file == MACH_PORT_NULL)
return errno;
- if ((err = do_setfd (pid, msgport, 0, file)))
+ err = do_setfd (pid, msgport, 0, file);
+ if (err)
mach_port_deallocate (mach_task_self (), file);
return err;
}
-static error_t
+/* Set standard output to ARGV[0]. Optionally, ARGV[1] may specify the
+ file access mode (see str2flags). The default is O_WRONLY */
+error_t
cmd_stdout (pid_t pid, mach_port_t msgport, int argc, char *argv[])
{
error_t err;
@@ -200,15 +253,18 @@ cmd_stdout (pid_t pid, mach_port_t msgport, int argc, char *argv[])
if (argc > 1)
flags = str2flags(argv[1]);
- if ((file = file_name_lookup (argv[0], flags, 0666)) ==
- MACH_PORT_NULL)
+ file = file_name_lookup (argv[0], flags, 0666);
+ if (file == MACH_PORT_NULL)
return errno;
- if ((err = do_setfd (pid, msgport, 1, file)))
+ err = do_setfd (pid, msgport, 1, file);
+ if (err)
mach_port_deallocate (mach_task_self (), file);
return err;
}
-static error_t
+/* Set standard error to ARGV[0]. Optionally, ARGV[1] may specify the
+ file access mode (see str2flags). The default is O_RDONLY */
+error_t
cmd_stderr (pid_t pid, mach_port_t msgport, int argc, char *argv[])
{
error_t err;
@@ -217,15 +273,17 @@ cmd_stderr (pid_t pid, mach_port_t msgport, int argc, char *argv[])
if (argc > 1)
flags = str2flags(argv[1]);
- if ((file = file_name_lookup (argv[0], flags, 0666)) ==
- MACH_PORT_NULL)
+ file = file_name_lookup (argv[0], flags, 0666);
+ if (file == MACH_PORT_NULL)
return errno;
- if ((err = do_setfd (pid, msgport, 2, file)))
+ err = do_setfd (pid, msgport, 2, file);
+ if (err)
mach_port_deallocate (mach_task_self (), file);
return err;
}
-static error_t
+/* Change current working directory to ARGV[0]. */
+error_t
cmd_chcwdir (pid_t pid, mach_port_t msgport, int argc, char *argv[])
{
error_t err;
@@ -233,21 +291,25 @@ cmd_chcwdir (pid_t pid, mach_port_t msgport, int argc, char *argv[])
task_t task;
process_t proc = getproc ();
- if ((dir = file_name_lookup (argv[0], 0, 0)) == MACH_PORT_NULL)
+ dir = file_name_lookup (argv[0], 0, 0);
+ if (dir == MACH_PORT_NULL)
return errno;
- if ((err = proc_pid2task (proc, pid, &task)))
+ err = proc_pid2task (proc, pid, &task);
+ if (err)
{
mach_port_deallocate (mach_task_self (), dir);
return err;
}
- if ((err = msg_set_init_port (msgport, task, INIT_PORT_CWDIR, dir,
- MACH_MSG_TYPE_MOVE_SEND)))
+ err = msg_set_init_port (msgport, task, INIT_PORT_CWDIR, dir,
+ MACH_MSG_TYPE_MOVE_SEND);
+ if (err)
mach_port_deallocate (mach_task_self (), dir);
mach_port_deallocate (mach_task_self (), task);
return err;
}
-static error_t
+/* Change current working directory to current root directory. */
+error_t
cmd_cdroot (pid_t pid, mach_port_t msgport, int argc, char *argv[])
{
error_t err;
@@ -255,21 +317,25 @@ cmd_cdroot (pid_t pid, mach_port_t msgport, int argc, char *argv[])
task_t task;
process_t proc = getproc ();
- if ((err = proc_pid2task (proc, pid, &task)))
+ err = proc_pid2task (proc, pid, &task);
+ if (err)
return err;
- if ((err = msg_get_init_port (msgport, task, INIT_PORT_CRDIR, &dir)))
+ err = msg_get_init_port (msgport, task, INIT_PORT_CRDIR, &dir);
+ if (err)
{
mach_port_deallocate (mach_task_self (), task);
return err;
}
- if ((err = msg_set_init_port (msgport, task, INIT_PORT_CWDIR, dir,
- MACH_MSG_TYPE_MOVE_SEND)))
+ err = msg_set_init_port (msgport, task, INIT_PORT_CWDIR, dir,
+ MACH_MSG_TYPE_MOVE_SEND);
+ if (err)
mach_port_deallocate (mach_task_self (), dir);
mach_port_deallocate (mach_task_self (), task);
return err;
}
-static error_t
+/* Change current root directory to ARGV[0]. */
+error_t
cmd_chcrdir (pid_t pid, mach_port_t msgport, int argc, char *argv[])
{
error_t err;
@@ -277,21 +343,25 @@ cmd_chcrdir (pid_t pid, mach_port_t msgport, int argc, char *argv[])
task_t task;
process_t proc = getproc ();
- if ((dir = file_name_lookup (argv[0], 0, 0)) == MACH_PORT_NULL)
+ dir = file_name_lookup (argv[0], 0, 0);
+ if (dir == MACH_PORT_NULL)
return errno;
- if ((err = proc_pid2task (proc, pid, &task)))
+ err = proc_pid2task (proc, pid, &task);
+ if (err)
{
mach_port_deallocate (mach_task_self (), dir);
return err;
}
- if ((err = msg_set_init_port (msgport, task, INIT_PORT_CRDIR, dir,
- MACH_MSG_TYPE_MOVE_SEND)))
+ err = msg_set_init_port (msgport, task, INIT_PORT_CRDIR, dir,
+ MACH_MSG_TYPE_MOVE_SEND);
+ if (err)
mach_port_deallocate (mach_task_self (), dir);
mach_port_deallocate (mach_task_self (), task);
return err;
}
-static error_t
+/* Print current working directory. */
+error_t
cmd_pwd (pid_t pid, mach_port_t msgport, int argc, char *argv[])
{
error_t err;
@@ -299,9 +369,11 @@ cmd_pwd (pid_t pid, mach_port_t msgport, int argc, char *argv[])
task_t task;
process_t proc = getproc ();
- if ((err = proc_pid2task (proc, pid, &task)))
+ err = proc_pid2task (proc, pid, &task);
+ if (err)
return err;
- if ((err = msg_get_init_port (msgport, task, INIT_PORT_CWDIR, &dir)))
+ err = msg_get_init_port (msgport, task, INIT_PORT_CWDIR, &dir);
+ if (err)
{
mach_port_deallocate (mach_task_self (), task);
return err;
@@ -313,7 +385,8 @@ cmd_pwd (pid_t pid, mach_port_t msgport, int argc, char *argv[])
return 0;
}
-static error_t
+/* Print current root directory */
+error_t
cmd_getroot (pid_t pid, mach_port_t msgport, int argc, char *argv[])
{
error_t err;
@@ -321,9 +394,11 @@ cmd_getroot (pid_t pid, mach_port_t msgport, int argc, char *argv[])
task_t task;
process_t proc = getproc ();
- if ((err = proc_pid2task (proc, pid, &task)))
+ err = proc_pid2task (proc, pid, &task);
+ if (err)
return err;
- if ((err = msg_get_init_port (msgport, task, INIT_PORT_CRDIR, &dir)))
+ err = msg_get_init_port (msgport, task, INIT_PORT_CRDIR, &dir);
+ if (err)
{
mach_port_deallocate (mach_task_self (), task);
return err;
@@ -335,7 +410,9 @@ cmd_getroot (pid_t pid, mach_port_t msgport, int argc, char *argv[])
return 0;
}
-static error_t
+/* Change umask to ARGV[0] (octal value). Without arguments, print
+ the value of current umask. */
+error_t
cmd_umask (pid_t pid, mach_port_t msgport, int argc, char *argv[])
{
error_t err;
@@ -343,15 +420,20 @@ cmd_umask (pid_t pid, mach_port_t msgport, int argc, char *argv[])
task_t task;
process_t proc = getproc ();
- if ((err = proc_pid2task (proc, pid, &task)))
+ err = proc_pid2task (proc, pid, &task);
+ if (err)
return err;
if (argc)
{
umask = strtol(argv[0], 0, 8);
err = msg_set_init_int (msgport, task, INIT_UMASK, umask);
}
- else if (!(err = msg_get_init_int (msgport, task, INIT_UMASK, &umask)))
- printf ("%d: %03o\n", pid, umask);
+ else
+ {
+ err = msg_get_init_int (msgport, task, INIT_UMASK, &umask);
+ if (!err)
+ printf ("%d: %03o\n", pid, umask);
+ }
mach_port_deallocate (mach_task_self (), task);
return err;
}
@@ -373,6 +455,14 @@ cmd_umask (pid_t pid, mach_port_t msgport, int argc, char *argv[])
#define CMD_PWD 1011
#define CMD_GETROOT 1012
+/* Params to be passed as the input when parsing CMDS_ARGP. */
+struct cmds_argp_params
+{
+ /* Array to be extended with parsed cmds. */
+ cmd_t **cmds;
+ size_t *num_cmds;
+};
+
static const struct argp_option cmd_options[] =
{
{"getenv", CMD_GETENV, "VAR", OA, "Get environment variable"},
@@ -394,8 +484,15 @@ static const struct argp_option cmd_options[] =
{0, 0}
};
+/* Add a new command to the array of commands already parsed
+ reallocating it in malloced memory. FUNC is the command function.
+ MINARGS and MAXARGS are the minimum and maximum number of arguments
+ the parser will accept for this command. Further checking of the
+ arguments should be done in FUNC. ARG is the next argument in the
+ command line (probably the first argument for this command). STATE
+ is the argp parser state as used in parse_cmd_opt. */
static error_t
-cmd_add (cmd_func_t func, size_t minargs, size_t maxargs,
+add_cmd (cmd_func_t func, size_t minargs, size_t maxargs,
char *arg, struct argp_state *state)
{
cmd_t *cmd;
@@ -416,9 +513,9 @@ cmd_add (cmd_func_t func, size_t minargs, size_t maxargs,
cmd->args = malloc (maxargs * sizeof (char *));
if (arg)
cmd->args[i++] = arg;
- while (i < maxargs &&
- state->argv[state->next] &&
- state->argv[state->next][0] != '-')
+ while (i < maxargs
+ && state->argv[state->next]
+ && state->argv[state->next][0] != '-')
cmd->args[i++] = state->argv[state->next++];
}
if (i < minargs || i > maxargs)
@@ -427,8 +524,9 @@ cmd_add (cmd_func_t func, size_t minargs, size_t maxargs,
return 0;
}
+/* Parse one option/arg for the argp parser cmds_argp (see argp.h). */
static error_t
-cmd_parse_opt (int key, char *arg, struct argp_state *state)
+parse_cmd_opt (int key, char *arg, struct argp_state *state)
{
/* A buffer used for rewriting command line arguments without dashes
for the parser to understand them. It gets realloced for each
@@ -439,8 +537,9 @@ cmd_parse_opt (int key, char *arg, struct argp_state *state)
{
case ARGP_KEY_ARG: /* Non-option argument. */
if (!isdigit (*arg) && !state->quoted)
- /* Prepend 2 dashes and feed back to getopt. */
{
+ /* Make state->next point to the just parsed argument to
+ re-parse it with 2 dashes prepended. */
size_t len = strlen (arg) + 1;
arg_hack_buf = realloc (arg_hack_buf, 2 + len);
state->argv[--state->next] = arg_hack_buf;
@@ -452,43 +551,43 @@ cmd_parse_opt (int key, char *arg, struct argp_state *state)
else
return ARGP_ERR_UNKNOWN;
case CMD_CHCWDIR:
- cmd_add (&cmd_chcwdir, 0, 1, arg, state);
+ add_cmd (&cmd_chcwdir, 0, 1, arg, state);
break;
case CMD_CHCRDIR:
- cmd_add (&cmd_chcrdir, 1, 1, arg, state);
+ add_cmd (&cmd_chcrdir, 1, 1, arg, state);
break;
case CMD_CDROOT:
- cmd_add (&cmd_cdroot, 0, 0, arg, state);
+ add_cmd (&cmd_cdroot, 0, 0, arg, state);
break;
case CMD_PWD:
- cmd_add (&cmd_pwd, 0, 0, arg, state);
+ add_cmd (&cmd_pwd, 0, 0, arg, state);
break;
case CMD_GETROOT:
- cmd_add (&cmd_getroot, 0, 0, arg, state);
+ add_cmd (&cmd_getroot, 0, 0, arg, state);
break;
case CMD_UMASK:
- cmd_add (&cmd_umask, 0, 1, arg, state);
+ add_cmd (&cmd_umask, 0, 1, arg, state);
break;
case CMD_GETENV:
- cmd_add (&cmd_getenv, 0, 1, arg, state);
+ add_cmd (&cmd_getenv, 0, 1, arg, state);
break;
case CMD_SETENV:
- cmd_add (&cmd_setenv, 2, 2, arg, state);
+ add_cmd (&cmd_setenv, 2, 2, arg, state);
break;
case CMD_CLRENV:
- cmd_add (&cmd_clearenv, 0, 0, arg, state);
+ add_cmd (&cmd_clearenv, 0, 0, arg, state);
break;
case CMD_SETFD:
- cmd_add (&cmd_setfd, 2, 3, arg, state);
+ add_cmd (&cmd_setfd, 2, 3, arg, state);
break;
case CMD_STDIN:
- cmd_add (&cmd_stdin, 1, 2, arg, state);
+ add_cmd (&cmd_stdin, 1, 2, arg, state);
break;
case CMD_STDOUT:
- cmd_add (&cmd_stdout, 1, 2, arg, state);
+ add_cmd (&cmd_stdout, 1, 2, arg, state);
break;
case CMD_STDERR:
- cmd_add (&cmd_stderr, 1, 2, arg, state);
+ add_cmd (&cmd_stderr, 1, 2, arg, state);
break;
default:
return ARGP_ERR_UNKNOWN;
@@ -496,6 +595,9 @@ cmd_parse_opt (int key, char *arg, struct argp_state *state)
return 0;
}
+/* Filtering of help output strings for cmds_argp parser. Return a
+ malloced replacement for TEXT as the arguments doc string. See
+ argp.h for details. */
static char *
help_filter (int key, const char *text, void *input)
{
@@ -505,31 +607,11 @@ help_filter (int key, const char *text, void *input)
return (char *)text;
}
-/* A parser for selecting a command. */
-struct argp cmds_argp = { cmd_options, cmd_parse_opt, 0, 0, 0, help_filter };
-
-static error_t
-do_cmd (pid_t pid, cmd_t cmd)
-{
- error_t err;
- mach_port_t msgport;
- process_t proc = getproc ();
-
- /* Get a msgport for PID, to which we can send requests. */
- err = proc_getmsgport (proc, pid, &msgport);
- if (err)
- error (1, err, "%d: Cannot get process msgport", pid);
-
- err = (*cmd.f) (pid, msgport, cmd.num_args, cmd.args);
- if (err)
- error (2, err, "%d: Cannot execute command", pid);
-
- mach_port_deallocate (mach_task_self (), msgport);
- return 0;
-}
-
+/* An argp parser for selecting a command (see argp.h). */
+struct argp cmds_argp = { cmd_options, parse_cmd_opt, 0, 0, 0, help_filter };
+
int
main(int argc, char *argv[])
{
@@ -586,7 +668,7 @@ main(int argc, char *argv[])
for (j = 0; j < num_cmds; ++j)
{
cmd = cmds[j];
- if ((err = do_cmd(pid, cmd)))
+ if ((err = do_cmd (pid, cmd)))
error (2, err, "%d: Cannot execute command", pid);
}
}