summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--debian/patches/rpcscan0001-utils-split-off-the-message-id-parsing.patch631
-rw-r--r--debian/patches/rpcscan0002-utils-rpcscan-new-utility.patch457
-rw-r--r--debian/patches/series2
3 files changed, 1090 insertions, 0 deletions
diff --git a/debian/patches/rpcscan0001-utils-split-off-the-message-id-parsing.patch b/debian/patches/rpcscan0001-utils-split-off-the-message-id-parsing.patch
new file mode 100644
index 00000000..128c212e
--- /dev/null
+++ b/debian/patches/rpcscan0001-utils-split-off-the-message-id-parsing.patch
@@ -0,0 +1,631 @@
+From 74fb5209f06edcf0b52bdf44ba805cb5f6cd41c8 Mon Sep 17 00:00:00 2001
+From: Justus Winter <4winter@informatik.uni-hamburg.de>
+Date: Sun, 31 May 2015 00:26:40 +0200
+Subject: [PATCH hurd 1/2] 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.
+---
+ utils/Makefile | 8 +-
+ utils/msgids.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ utils/msgids.h | 33 ++++++++
+ utils/rpctrace.c | 202 ++------------------------------------------
+ 4 files changed, 298 insertions(+), 197 deletions(-)
+ create mode 100644 utils/msgids.c
+ create mode 100644 utils/msgids.h
+
+diff --git a/utils/Makefile b/utils/Makefile
+index 1117be1..9ad2a40 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 0000000..4bc08de
+--- /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 0000000..6bd2372
+--- /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 48daa07..d53b510 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,
+--
+2.1.4
+
diff --git a/debian/patches/rpcscan0002-utils-rpcscan-new-utility.patch b/debian/patches/rpcscan0002-utils-rpcscan-new-utility.patch
new file mode 100644
index 00000000..5ea67a3d
--- /dev/null
+++ b/debian/patches/rpcscan0002-utils-rpcscan-new-utility.patch
@@ -0,0 +1,457 @@
+From 566a246f2c2881f1598d376032f9f73427790feb Mon Sep 17 00:00:00 2001
+From: Justus Winter <4winter@informatik.uni-hamburg.de>
+Date: Fri, 29 May 2015 16:37:00 +0200
+Subject: [PATCH hurd 2/2] utils/rpcscan: new utility
+
+* utils/rpcscan.c: New file.
+* utils/Makefile: Add `rpcscan'.
+---
+ utils/Makefile | 6 +-
+ utils/rpcscan.c | 404 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 407 insertions(+), 3 deletions(-)
+ create mode 100644 utils/rpcscan.c
+
+diff --git a/utils/Makefile b/utils/Makefile
+index 9ad2a40..955789b 100644
+--- a/utils/Makefile
++++ b/utils/Makefile
+@@ -22,7 +22,7 @@ targets = shd ps settrans showtrans syncfs fsysopts \
+ storeinfo login w uptime ids loginpr sush vmstat portinfo \
+ devprobe vminfo addauth rmauth unsu setauth ftpcp ftpdir storecat \
+ storeread msgport rpctrace mount gcore fakeauth fakeroot remap \
+- umount nullauth
++ umount nullauth rpcscan
+
+ special-targets = loginpr sush uptime fakeroot remap
+ SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \
+@@ -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 msgids.c
++ nullauth.c match-options.c msgids.c rpcscan.c
+
+ OBJS = $(filter-out %.sh,$(SRCS:.c=.o))
+ HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc
+@@ -68,7 +68,7 @@ ps w ids settrans syncfs showtrans fsysopts storeinfo login vmstat portinfo \
+ $(filter-out $(special-targets), $(targets)): %: %.o
+
+ rpctrace: ../libports/libports.a
+-rpctrace: msgids.o \
++rpctrace rpcscan: msgids.o \
+ ../libihash/libihash.a
+ msgids-CPPFLAGS = -DDATADIR=\"${datadir}\"
+
+diff --git a/utils/rpcscan.c b/utils/rpcscan.c
+new file mode 100644
+index 0000000..e32c016
+--- /dev/null
++++ b/utils/rpcscan.c
+@@ -0,0 +1,404 @@
++/* An RPC scanner for the Hurd.
++
++ Copyright (C) 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 <mach.h>
++#include <hurd.h>
++#include <hurd/ihash.h>
++#include <mach/message.h>
++#include <unistd.h>
++#include <argp.h>
++#include <error.h>
++#include <string.h>
++#include <version.h>
++#include <sys/wait.h>
++#include <inttypes.h>
++#include <stdbool.h>
++#include <stddef.h>
++#include <argz.h>
++
++#include "msgids.h"
++
++/* Send messages with arbitrary message ids. */
++struct Request {
++ mach_msg_header_t Head;
++} RequestTemplate;
++
++struct Reply {
++ mach_msg_header_t Head;
++ mach_msg_type_t RetCodeType;
++ kern_return_t RetCode;
++ char Body[4096];
++};
++
++union {
++ struct Request Request;
++ struct Reply Reply;
++} Message;
++
++error_t
++setup (mach_port_t request, mach_msg_type_name_t requestType)
++{
++ RequestTemplate.Head.msgh_remote_port = request;
++ if (! MACH_PORT_VALID (RequestTemplate.Head.msgh_local_port))
++ RequestTemplate.Head.msgh_local_port = mach_reply_port ();
++ RequestTemplate.Head.msgh_bits =
++ MACH_MSGH_BITS (requestType, MACH_MSG_TYPE_MAKE_SEND_ONCE);
++ return 0;
++}
++
++error_t
++send (mach_msg_id_t msgid)
++{
++ error_t err;
++ Message.Request = RequestTemplate;
++ Message.Request.Head.msgh_id = msgid;
++ err = mach_msg (&Message.Request.Head,
++ MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE,
++ sizeof Message.Request,
++ sizeof Message.Reply,
++ Message.Request.Head.msgh_local_port,
++ MACH_MSG_TIMEOUT_NONE,
++ MACH_PORT_NULL);
++ if (err)
++ return err;
++
++ // xxx typecheck
++ return Message.Reply.RetCode;
++}
++
++typedef error_t (*setup_function_t) ();
++setup_function_t setup_target;
++void *setup_argument;
++
++error_t
++setup_task_target (void)
++{
++ error_t err;
++ static task_t task;
++ static mach_msg_type_name_t taskType = MACH_MSG_TYPE_COPY_SEND;
++
++ if (MACH_PORT_VALID (task))
++ {
++ task_terminate (task);
++ mach_port_deallocate (mach_task_self (), task);
++ }
++
++ err = task_create (mach_task_self (), 0, &task);
++ if (err)
++ return err;
++
++ return setup (task, taskType);
++}
++
++error_t
++setup_thread_target (void)
++{
++ error_t err;
++ static task_t task;
++ static thread_t thread;
++
++ if (MACH_PORT_VALID (thread))
++ {
++ thread_terminate (thread);
++ mach_port_deallocate (mach_task_self (), thread);
++ }
++
++ if (MACH_PORT_VALID (task))
++ {
++ task_terminate (task);
++ mach_port_deallocate (mach_task_self (), task);
++ }
++
++ err = task_create (mach_task_self (), 0, &task);
++ if (err)
++ return err;
++
++ err = thread_create (task, &thread);
++ if (err)
++ return err;
++
++ return setup (thread, MACH_MSG_TYPE_COPY_SEND);
++}
++
++error_t
++setup_proc_target (void)
++{
++ error_t err;
++ static task_t task;
++ static process_t proc, target;
++ static mach_msg_type_name_t targetType = MACH_MSG_TYPE_COPY_SEND;
++
++ if (! MACH_PORT_VALID (proc))
++ proc = getproc ();
++ if (MACH_PORT_VALID (task))
++ mach_port_deallocate (mach_task_self (), task);
++ if (MACH_PORT_VALID (target))
++ mach_port_deallocate (mach_task_self (), target);
++
++ err = task_create (mach_task_self (), 0, &task);
++ if (err)
++ return err;
++
++ err = proc_task2proc (proc, task, &target);
++ if (err)
++ return err;
++
++ return setup (target, targetType);
++}
++
++error_t
++setup_auth_target (void)
++{
++ static auth_t auth;
++ static mach_msg_type_name_t authType = MACH_MSG_TYPE_COPY_SEND;
++
++ if (MACH_PORT_VALID (auth))
++ mach_port_deallocate (mach_task_self (), auth);
++
++ auth = getauth ();
++ if (! MACH_PORT_VALID (auth))
++ return errno;
++
++ return setup (auth, authType);
++}
++
++error_t
++setup_hurd_target (void)
++{
++ char *name = (char *) setup_argument;
++ mach_port_t request;
++ mach_msg_type_name_t requestType;
++
++ request = file_name_lookup (name, 0, 0);
++ if (! MACH_PORT_VALID (request))
++ return errno;
++ requestType = MACH_MSG_TYPE_COPY_SEND;
++
++ return setup (request, requestType);
++}
++
++task_t extract_target_task;
++mach_port_t extract_target_port;
++mach_msg_type_name_t extract_target_type;
++
++error_t
++setup_extract_target (void)
++{
++ error_t err;
++ char *name = (char *) setup_argument;
++ mach_port_t request;
++ mach_msg_type_name_t requestType;
++
++ err = mach_port_extract_right (extract_target_task,
++ extract_target_port,
++ extract_target_type,
++ &request,
++ &requestType);
++ if (err)
++ error (1, err, "mach_port_extract_right");
++ if (err)
++ return err;
++ requestType = MACH_MSG_TYPE_COPY_SEND;
++ return setup (request, requestType);
++}
++
++const char *argp_program_version = STANDARD_HURD_VERSION (rpcscan);
++
++char **cmd_argv;
++int verbose;
++int numeric;
++int subsystem;
++
++#define OPT_TARGET_TASK -1
++#define OPT_TARGET_THREAD -2
++#define OPT_TARGET_PROC -3
++#define OPT_TARGET_AUTH -4
++#define OPT_TARGET_EXTRACT -5
++
++static const struct argp_option options[] =
++{
++ {NULL, 0, NULL, OPTION_DOC, "Target selection", 1},
++ {"task", OPT_TARGET_TASK, NULL, 0, "target a task port", 1},
++ {"thread", OPT_TARGET_THREAD, NULL, 0, "target a thread port", 1},
++ {"proc", OPT_TARGET_PROC, NULL, 0, "target a proc port", 1},
++ {"auth", OPT_TARGET_AUTH, NULL, 0, "target an auth port", 1},
++ {"extract", OPT_TARGET_EXTRACT, "PID.PORT", 0, "target port PORT of PID", 1},
++
++ {NULL, 0, NULL, OPTION_DOC, "Options", 2},
++ {"verbose", 'v', NULL, 0, "be verbose", 2},
++ {"numeric", 'n', NULL, 0, "show numeric message ids", 2},
++ {"subsystem", 's', NULL, 0, "show subsystem names", 2},
++ {0}
++};
++
++static const char args_doc[] = "[FILE]";
++static const char doc[] = "Scan a given Mach port.";
++
++/* Parse our options... */
++error_t
++parse_opt (int key, char *arg, struct argp_state *state)
++{
++ error_t err;
++ switch (key)
++ {
++ case 'v':
++ verbose = 1;
++ break;
++
++ case 'n':
++ numeric = 1;
++ break;
++
++ case 's':
++ subsystem = 1;
++ break;
++
++#define SELECT_TARGET(target) \
++ if (setup_target) \
++ argp_error (state, "Multiple targets specified."); \
++ setup_target = target;
++
++ case OPT_TARGET_TASK:
++ SELECT_TARGET (setup_task_target);
++ break;
++
++ case OPT_TARGET_THREAD:
++ SELECT_TARGET (setup_thread_target);
++ break;
++
++ case OPT_TARGET_PROC:
++ SELECT_TARGET (setup_proc_target);
++ break;
++
++ case OPT_TARGET_AUTH:
++ SELECT_TARGET (setup_auth_target);
++ break;
++
++ case OPT_TARGET_EXTRACT:;
++ process_t proc;
++ pid_t pid;
++ char *end;
++
++ pid = strtol (arg, &end, 10);
++ if (arg == end || *end != '.')
++ argp_error (state, "Expected format PID.PORT, got `%s'.", arg);
++
++ arg = end + 1;
++ extract_target_port = strtol (arg, &end, 10);
++ if (arg == end || *end != '\0')
++ argp_error (state, "Expected format PORT, got `%s'.", arg);
++
++ proc = getproc ();
++ err = proc_pid2task (proc, pid, &extract_target_task);
++ if (err)
++ argp_failure (state, 1, err,
++ "Could not get task of process %d", pid);
++
++ extract_target_type = MACH_MSG_TYPE_COPY_SEND; /* XXX */
++ SELECT_TARGET (setup_extract_target);
++ break;
++
++ case ARGP_KEY_ARG:
++ SELECT_TARGET (setup_hurd_target);
++ setup_argument = arg;
++ break;
++#undef SELECT_TARGET
++
++ case ARGP_KEY_NO_ARGS:
++ if (setup_target == NULL)
++ argp_usage (state);
++ break;
++
++ default:
++ return ARGP_ERR_UNKNOWN;
++ }
++ return 0;
++}
++
++const struct argp_child children[] =
++ {
++ { .argp=&msgid_argp, },
++ { 0 }
++ };
++
++const struct argp argp = { options, parse_opt, args_doc, doc, &children };
++
++void
++format_msgid (char *buf, size_t len, mach_msg_id_t id)
++{
++ if (numeric)
++ numeric:
++ snprintf (buf, len, "%d", id);
++ else
++ {
++ const struct msgid_info *info;
++ info = msgid_info (id);
++ if (info == NULL)
++ goto numeric;
++
++ if (subsystem)
++ snprintf (buf, len, "%s/%s", info->subsystem, info->name);
++ else
++ snprintf (buf, len, "%s", info->name);
++ }
++}
++
++int
++main (int argc, char **argv, char **envp)
++{
++ error_t err;
++ mach_msg_id_t msgid;
++
++ /* Parse our arguments. */
++ argp_parse (&argp, argc, argv, ARGP_IN_ORDER, 0, 0);
++
++ err = setup_target ();
++ if (err)
++ /* Initial setup failed. Bail out. */
++ error (1, err, "%s",
++ setup_target == setup_hurd_target? (char *) setup_argument: "setup");
++
++ for (msgid = 0; msgid < 500000; msgid++)
++ {
++ err = send (msgid);
++ switch (err)
++ {
++ case MACH_SEND_INVALID_DEST:
++ err = setup_target ();
++ if (err)
++ error (1, err, "setup");
++ msgid--; /* redo */
++ continue;
++
++ case MIG_BAD_ID:
++ /* do nothing */
++ break;
++
++ default:;
++ char buf[80];
++ format_msgid (buf, sizeof buf, msgid);
++ if (verbose)
++ error (0, err, "%s", buf);
++ else
++ fprintf (stdout, "%s\n", buf);
++ }
++ }
++
++ return EXIT_SUCCESS;
++}
+--
+2.1.4
+
diff --git a/debian/patches/series b/debian/patches/series
index 14754761..bc3855a7 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -69,3 +69,5 @@ exec_filename_use.patch
exec_filename_fix.patch
huge-nodecache0001-xxx-huge-nodecache.patch
dde-enable-device.patch
+rpcscan0001-utils-split-off-the-message-id-parsing.patch
+rpcscan0002-utils-rpcscan-new-utility.patch