diff options
author | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-05-31 00:26:40 +0200 |
---|---|---|
committer | Justus Winter <4winter@informatik.uni-hamburg.de> | 2015-06-30 17:10:00 +0200 |
commit | 74fb5209f06edcf0b52bdf44ba805cb5f6cd41c8 (patch) | |
tree | 3481be39655a9f72626722dab60ba6be08285116 | |
parent | f57ed76faed9e9e922ba93dd3bf8740974eb718a (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/Makefile | 8 | ||||
-rw-r--r-- | utils/msgids.c | 252 | ||||
-rw-r--r-- | utils/msgids.h | 33 | ||||
-rw-r--r-- | utils/rpctrace.c | 202 |
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), ¬ify_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, |