summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustus Winter <4winter@informatik.uni-hamburg.de>2015-05-31 00:26:40 +0200
committerJustus Winter <4winter@informatik.uni-hamburg.de>2015-06-30 17:10:00 +0200
commit74fb5209f06edcf0b52bdf44ba805cb5f6cd41c8 (patch)
tree3481be39655a9f72626722dab60ba6be08285116
parentf57ed76faed9e9e922ba93dd3bf8740974eb718a (diff)
utils: split-off the message id parsing
* utils/rpctrace.c: Move all the code handling the message id files... * utils/msgids.c: ... to a new file. * utils/msgids.h: And add the relevand declarations. * utils/Makefile (SRCS): Add the new file.
-rw-r--r--utils/Makefile8
-rw-r--r--utils/msgids.c252
-rw-r--r--utils/msgids.h33
-rw-r--r--utils/rpctrace.c202
4 files changed, 298 insertions, 197 deletions
diff --git a/utils/Makefile b/utils/Makefile
index 1117be16..9ad2a40e 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -31,7 +31,7 @@ SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \
parse.c frobauth.c frobauth-mod.c setauth.c pids.c nonsugid.c \
unsu.c ftpcp.c ftpdir.c storeread.c storecat.c msgport.c \
rpctrace.c mount.c gcore.c fakeauth.c fakeroot.sh remap.sh \
- nullauth.c match-options.c
+ nullauth.c match-options.c msgids.c
OBJS = $(filter-out %.sh,$(SRCS:.c=.o))
HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc
@@ -67,8 +67,10 @@ ps w ids settrans syncfs showtrans fsysopts storeinfo login vmstat portinfo \
$(filter-out $(special-targets), $(targets)): %: %.o
-rpctrace: ../libports/libports.a ../libihash/libihash.a
-rpctrace-CPPFLAGS = -DDATADIR=\"${datadir}\"
+rpctrace: ../libports/libports.a
+rpctrace: msgids.o \
+ ../libihash/libihash.a
+msgids-CPPFLAGS = -DDATADIR=\"${datadir}\"
fakeauth: authServer.o auth_requestUser.o interruptServer.o \
../libports/libports.a ../libihash/libihash.a \
diff --git a/utils/msgids.c b/utils/msgids.c
new file mode 100644
index 00000000..4bc08ded
--- /dev/null
+++ b/utils/msgids.c
@@ -0,0 +1,252 @@
+/* Translate message ids to symbolic names.
+
+ Copyright (C) 1998-2015 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 the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <argp.h>
+#include <argz.h>
+#include <dirent.h>
+#include <errno.h>
+#include <error.h>
+#include <fnmatch.h>
+#include <hurd/ihash.h>
+#include <mach.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "msgids.h"
+
+static void
+msgid_ihash_cleanup (void *element, void *arg)
+{
+ struct msgid_info *info = element;
+ free (info->name);
+ free (info->subsystem);
+ free (info);
+}
+
+static struct hurd_ihash msgid_ihash
+ = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP);
+
+/* Parse a file of RPC names and message IDs as output by mig's -list
+ option: "subsystem base-id routine n request-id reply-id". Put each
+ request-id value into `msgid_ihash' with the routine name as its value. */
+static error_t
+parse_msgid_list (const char *filename)
+{
+ FILE *fp;
+ char *buffer = NULL;
+ size_t bufsize = 0;
+ unsigned int lineno = 0;
+ char *name, *subsystem;
+ unsigned int msgid;
+ error_t err;
+
+ fp = fopen (filename, "r");
+ if (fp == NULL)
+ return errno;
+
+ while (getline (&buffer, &bufsize, fp) > 0)
+ {
+ ++lineno;
+ if (buffer[0] == '#' || buffer[0] == '\0')
+ continue;
+ if (sscanf (buffer, "%ms %*u %ms %*u %u %*u\n",
+ &subsystem, &name, &msgid) != 3)
+ error (0, 0, "%s:%u: invalid format in RPC list file",
+ filename, lineno);
+ else
+ {
+ struct msgid_info *info = malloc (sizeof *info);
+ if (info == 0)
+ error (1, errno, "malloc");
+ info->name = name;
+ info->subsystem = subsystem;
+ err = hurd_ihash_add (&msgid_ihash, msgid, info);
+ if (err)
+ return err;
+ }
+ }
+
+ free (buffer);
+ fclose (fp);
+ return 0;
+}
+
+/* Look for a name describing MSGID. We check the table directly, and
+ also check if this looks like the ID of a reply message whose request
+ ID is already in the table. */
+const struct msgid_info *
+msgid_info (mach_msg_id_t msgid)
+{
+ const struct msgid_info *info = hurd_ihash_find (&msgid_ihash, msgid);
+ if (info == 0 && (msgid / 100) % 2 == 1)
+ {
+ /* This message ID is not in the table, and its number makes it
+ what should be an RPC reply message ID. So look up the message
+ ID of the corresponding RPC request and synthesize a name from
+ that. Then stash that name in the table so the next time the
+ lookup will match directly. */
+ info = hurd_ihash_find (&msgid_ihash, msgid - 100);
+ if (info != 0)
+ {
+ struct msgid_info *reply_info = malloc (sizeof *info);
+ if (reply_info != 0)
+ {
+ reply_info->subsystem = strdup (info->subsystem);
+ reply_info->name = 0;
+ asprintf (&reply_info->name, "%s-reply", info->name);
+ hurd_ihash_add (&msgid_ihash, msgid, reply_info);
+ info = reply_info;
+ }
+ else
+ info = 0;
+ }
+ }
+ return info;
+}
+
+static int
+msgids_file_p (const struct dirent *eps)
+{
+ return fnmatch ("*.msgids", eps->d_name, 0) != FNM_NOMATCH;
+}
+
+static void
+scan_msgids_dir (char **argz, size_t *argz_len, char *dir, bool append)
+{
+ struct dirent **eps;
+ int n;
+
+ n = scandir (dir, &eps, msgids_file_p, NULL);
+ if (n >= 0)
+ {
+ for (int cnt = 0; cnt < n; ++cnt)
+ {
+ char *msgids_file;
+
+ if (asprintf (&msgids_file, "%s/%s", dir, eps[cnt]->d_name) < 0)
+ error (1, errno, "asprintf");
+
+ if (append == TRUE)
+ {
+ if (argz_add (argz, argz_len, msgids_file) != 0)
+ error (1, errno, "argz_add");
+ }
+ else
+ {
+ if (argz_insert (argz, argz_len, *argz, msgids_file) != 0)
+ error (1, errno, "argz_insert");
+ }
+ free (msgids_file);
+ }
+ }
+
+ /* If the directory couldn't be scanned for whatever reason, just ignore
+ it. */
+}
+
+/* Argument parsing. */
+
+static char *msgids_files_argz = NULL;
+static size_t msgids_files_argz_len = 0;
+static bool nostdinc = FALSE;
+
+#define STD_MSGIDS_DIR DATADIR "/msgids/"
+#define OPT_NOSTDINC -1
+
+static const struct argp_option options[] =
+{
+ {"nostdinc", OPT_NOSTDINC, 0, 0,
+ "Do not search inside the standard system directory, `" STD_MSGIDS_DIR
+ "', for `.msgids' files.", 0},
+ {"rpc-list", 'i', "FILE", 0,
+ "Read FILE for assocations of message ID numbers to names.", 0},
+ {0, 'I', "DIR", 0,
+ "Add the directory DIR to the list of directories to be searched for files "
+ "containing message ID numbers.", 0},
+ {0}
+};
+
+/* Parse our options... */
+static error_t parse_opt (int key, char *arg, struct argp_state *state)
+{
+ switch (key)
+ {
+ case ARGP_KEY_INIT:
+ hurd_ihash_set_cleanup (&msgid_ihash, msgid_ihash_cleanup, 0);
+ break;
+
+ case OPT_NOSTDINC:
+ nostdinc = TRUE;
+ break;
+
+ case 'i':
+ if (argz_add (&msgids_files_argz, &msgids_files_argz_len,
+ arg) != 0)
+ error (1, errno, "argz_add");
+ break;
+
+ case 'I':
+ scan_msgids_dir (&msgids_files_argz, &msgids_files_argz_len,
+ arg, TRUE);
+ break;
+
+ case ARGP_KEY_NO_ARGS:
+ return 0;
+
+ case ARGP_KEY_ARG:
+ return EINVAL;
+
+ case ARGP_KEY_END:
+ /* Insert the files from STD_MSGIDS_DIR at the beginning of the
+ list, so that their content can be overridden by subsequently
+ parsed files. */
+ if (nostdinc == FALSE)
+ scan_msgids_dir (&msgids_files_argz, &msgids_files_argz_len,
+ STD_MSGIDS_DIR, FALSE);
+
+ if (msgids_files_argz != NULL)
+ {
+ error_t err = 0;
+ char *msgids_file = NULL;
+
+ while (! err
+ && (msgids_file = argz_next (msgids_files_argz,
+ msgids_files_argz_len,
+ msgids_file)))
+ err = parse_msgid_list (msgids_file);
+
+ free (msgids_files_argz);
+ if (err)
+ argp_failure (state, 1, err, "%s", msgids_file);
+ }
+ break;
+
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+const struct argp msgid_argp = {
+ .options = options,
+ .parser = parse_opt,
+ .doc = "msgid doc",
+};
diff --git a/utils/msgids.h b/utils/msgids.h
new file mode 100644
index 00000000..6bd23720
--- /dev/null
+++ b/utils/msgids.h
@@ -0,0 +1,33 @@
+/* Translate message ids to symbolic names.
+
+ Copyright (C) 1998-2015 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 the GNU Hurd. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef _HURD_MSGIDS_H_
+#define _HURD_MSGIDS_H_
+
+/* We map message ids to procedure and subsystem names. */
+struct msgid_info
+{
+ char *name;
+ char *subsystem;
+};
+
+const struct msgid_info *msgid_info (mach_msg_id_t msgid);
+const struct argp msgid_argp;
+
+#endif /* _HURD_MSGIDS_H_ */
diff --git a/utils/rpctrace.c b/utils/rpctrace.c
index 48daa078..d53b510f 100644
--- a/utils/rpctrace.c
+++ b/utils/rpctrace.c
@@ -26,9 +26,7 @@
#include <mach/message.h>
#include <assert.h>
#include <fcntl.h>
-#include <fnmatch.h>
#include <sys/stat.h>
-#include <dirent.h>
#include <unistd.h>
#include <argp.h>
#include <error.h>
@@ -41,24 +39,15 @@
#include <argz.h>
#include <envz.h>
-const char *argp_program_version = STANDARD_HURD_VERSION (rpctrace);
+#include "msgids.h"
-#define STD_MSGIDS_DIR DATADIR "/msgids/"
+const char *argp_program_version = STANDARD_HURD_VERSION (rpctrace);
static unsigned strsize = 80;
-#define OPT_NOSTDINC -1
static const struct argp_option options[] =
{
{"output", 'o', "FILE", 0, "Send trace output to FILE instead of stderr."},
- {"nostdinc", OPT_NOSTDINC, 0, 0,
- "Do not search inside the standard system directory, `" STD_MSGIDS_DIR
- "', for `.msgids' files."},
- {"rpc-list", 'i', "FILE", 0,
- "Read FILE for assocations of message ID numbers to names."},
- {0, 'I', "DIR", 0,
- "Add the directory DIR to the list of directories to be searched for files "
- "containing message ID numbers."},
{0, 's', "SIZE", 0, "Specify the maximum string size to print (the default is 80)."},
{0, 'E', "var[=value]", 0,
"Set/change (var=value) or remove (var) an environment variable among the "
@@ -71,23 +60,6 @@ static const struct argp_option options[] =
static const char args_doc[] = "COMMAND [ARG...]";
static const char doc[] = "Trace Mach Remote Procedure Calls.";
-/* The msgid_ihash table maps msgh_id values to names. */
-
-struct msgid_info
-{
- char *name;
- char *subsystem;
-};
-
-static void
-msgid_ihash_cleanup (void *element, void *arg)
-{
- struct msgid_info *info = element;
- free (info->name);
- free (info->subsystem);
- free (info);
-}
-
/* This structure stores the information of the traced task. */
struct task_info
{
@@ -95,9 +67,6 @@ struct task_info
boolean_t threads_wrapped; /* All threads of the task has been wrapped? */
};
-static struct hurd_ihash msgid_ihash
- = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP);
-
static struct hurd_ihash task_ihash
= HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP);
@@ -126,86 +95,6 @@ remove_task (task_t task)
hurd_ihash_remove (&task_ihash, task);
}
-/* Parse a file of RPC names and message IDs as output by mig's -list
- option: "subsystem base-id routine n request-id reply-id". Put each
- request-id value into `msgid_ihash' with the routine name as its value. */
-static void
-parse_msgid_list (const char *filename)
-{
- FILE *fp;
- char *buffer = NULL;
- size_t bufsize = 0;
- unsigned int lineno = 0;
- char *name, *subsystem;
- unsigned int msgid;
- error_t err;
-
- fp = fopen (filename, "r");
- if (fp == 0)
- {
- error (2, errno, "%s", filename);
- return;
- }
-
- while (getline (&buffer, &bufsize, fp) > 0)
- {
- ++lineno;
- if (buffer[0] == '#' || buffer[0] == '\0')
- continue;
- if (sscanf (buffer, "%ms %*u %ms %*u %u %*u\n",
- &subsystem, &name, &msgid) != 3)
- error (0, 0, "%s:%u: invalid format in RPC list file",
- filename, lineno);
- else
- {
- struct msgid_info *info = malloc (sizeof *info);
- if (info == 0)
- error (1, errno, "malloc");
- info->name = name;
- info->subsystem = subsystem;
- err = hurd_ihash_add (&msgid_ihash, msgid, info);
- if (err)
- error (1, err, "hurd_ihash_add");
- }
- }
-
- free (buffer);
- fclose (fp);
-}
-
-/* Look for a name describing MSGID. We check the table directly, and
- also check if this looks like the ID of a reply message whose request
- ID is already in the table. */
-static const struct msgid_info *
-msgid_info (mach_msg_id_t msgid)
-{
- const struct msgid_info *info = hurd_ihash_find (&msgid_ihash, msgid);
- if (info == 0 && (msgid / 100) % 2 == 1)
- {
- /* This message ID is not in the table, and its number makes it
- what should be an RPC reply message ID. So look up the message
- ID of the corresponding RPC request and synthesize a name from
- that. Then stash that name in the table so the next time the
- lookup will match directly. */
- info = hurd_ihash_find (&msgid_ihash, msgid - 100);
- if (info != 0)
- {
- struct msgid_info *reply_info = malloc (sizeof *info);
- if (reply_info != 0)
- {
- reply_info->subsystem = strdup (info->subsystem);
- reply_info->name = 0;
- asprintf (&reply_info->name, "%s-reply", info->name);
- hurd_ihash_add (&msgid_ihash, msgid, reply_info);
- info = reply_info;
- }
- else
- info = 0;
- }
- }
- return info;
-}
-
static const char *
msgid_name (mach_msg_id_t msgid)
{
@@ -1781,55 +1670,9 @@ traced_spawn (char **argv, char **envp)
return pid;
}
-
-static void
-scan_msgids_dir (char **argz, size_t *argz_len, char *dir, bool append)
-{
- struct dirent **eps;
- int n;
-
- int
- msgids_file_p (const struct dirent *eps)
- {
- if (fnmatch ("*.msgids", eps->d_name, 0) != FNM_NOMATCH)
- return 1;
- return 0;
- }
-
- n = scandir (dir, &eps, msgids_file_p, NULL);
- if (n >= 0)
- {
- for (int cnt = 0; cnt < n; ++cnt)
- {
- char *msgids_file;
-
- if (asprintf (&msgids_file, "%s/%s", dir, eps[cnt]->d_name) < 0)
- error (1, errno, "asprintf");
-
- if (append == TRUE)
- {
- if (argz_add (argz, argz_len, msgids_file) != 0)
- error (1, errno, "argz_add");
- }
- else
- {
- if (argz_insert (argz, argz_len, *argz, msgids_file) != 0)
- error (1, errno, "argz_insert");
- }
- free (msgids_file);
- }
- }
-
- /* If the directory couldn't be scanned for whatever reason, just ignore
- it. */
-}
-
int
main (int argc, char **argv, char **envp)
{
- char *msgids_files_argz = NULL;
- size_t msgids_files_argz_len = 0;
- bool nostdinc = FALSE;
const char *outfile = 0;
char **cmd_argv = 0;
pthread_t thread;
@@ -1847,21 +1690,6 @@ main (int argc, char **argv, char **envp)
outfile = arg;
break;
- case OPT_NOSTDINC:
- nostdinc = TRUE;
- break;
-
- case 'i':
- if (argz_add (&msgids_files_argz, &msgids_files_argz_len,
- arg) != 0)
- error (1, errno, "argz_add");
- break;
-
- case 'I':
- scan_msgids_dir (&msgids_files_argz, &msgids_files_argz_len,
- arg, TRUE);
- break;
-
case 's':
strsize = atoi (arg);
break;
@@ -1908,7 +1736,12 @@ main (int argc, char **argv, char **envp)
}
return 0;
}
- const struct argp argp = { options, parse_opt, args_doc, doc };
+ const struct argp_child children[] =
+ {
+ { .argp=&msgid_argp, },
+ { 0 }
+ };
+ const struct argp argp = { options, parse_opt, args_doc, doc, &children };
/* Parse our arguments. */
argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0);
@@ -1917,23 +1750,6 @@ main (int argc, char **argv, char **envp)
&unknown_task);
assert_perror (err);
- /* Insert the files from STD_MSGIDS_DIR at the beginning of the list, so that
- their content can be overridden by subsequently parsed files. */
- if (nostdinc == FALSE)
- scan_msgids_dir (&msgids_files_argz, &msgids_files_argz_len,
- STD_MSGIDS_DIR, FALSE);
-
- if (msgids_files_argz != NULL)
- {
- char *msgids_file = NULL;
-
- while ((msgids_file = argz_next (msgids_files_argz,
- msgids_files_argz_len, msgids_file)))
- parse_msgid_list (msgids_file);
-
- free (msgids_files_argz);
- }
-
if (outfile)
{
ostream = fopen (outfile, "w");
@@ -1951,8 +1767,6 @@ main (int argc, char **argv, char **envp)
sizeof (*notify_pi), &notify_pi);
assert_perror (err);
- hurd_ihash_set_cleanup (&msgid_ihash, msgid_ihash_cleanup, 0);
-
/* Spawn a single thread that will receive intercepted messages, print
them, and interpose on the ports they carry. The access to the
`traced_info' and ihash data structures is all single-threaded,