Hello,
The attached patch adds support for /proc/pid/exe. It does so by making
exec set the binary path it used through proc_set_exe, and making libps
use proc_get_exe to retrieve it. I'm notably wondering about the RPC:
should we be using string_t or data_t ?
Samuel
Index: hurd-debian/exec/exec.c
===================================================================
--- hurd-debian.orig/exec/exec.c
+++ hurd-debian/exec/exec.c
@@ -1312,6 +1312,9 @@ do_exec (file_t file,
if (e.error)
goto out;
+ if (filename)
+ proc_set_exe (boot->portarray[INIT_PORT_PROC], filename);
+
set_name (newtask, argv, pid);
}
else
Index: hurd-debian/hurd/process.defs
===================================================================
--- hurd-debian.orig/hurd/process.defs
+++ hurd-debian/hurd/process.defs
@@ -413,3 +413,14 @@ routine proc_get_code (
routine proc_make_task_namespace (
process: process_t;
notify: mach_port_send_t);
+
+/* Set the process binary executable path. */
+routine proc_set_exe (
+ process: process_t;
+ path: string_t);
+
+/* Get the process binary executable path. */
+routine proc_get_exe (
+ process: process_t;
+ which: pid_t;
+ out path: data_t, dealloc);
Index: hurd-debian/proc/info.c
===================================================================
--- hurd-debian.orig/proc/info.c
+++ hurd-debian/proc/info.c
@@ -799,3 +799,46 @@ S_proc_getnports (struct proc *callerp,
return err;
}
+
+/* Implement proc_set_path as described in <hurd/process.defs>. */
+kern_return_t
+S_proc_set_exe (struct proc *p,
+ char *path)
+{
+ char *copy;
+
+ if (!p)
+ return EOPNOTSUPP;
+
+ copy = strdup(path);
+ if (! copy)
+ return ENOMEM;
+
+ free(p->exe);
+ p->exe = copy;
+ return 0;
+}
+
+/* Implement proc_get_path as described in <hurd/process.defs>. */
+kern_return_t
+S_proc_get_exe (struct proc *callerp,
+ pid_t pid,
+ char **path,
+ size_t *pathlen)
+{
+ struct proc *p = pid_find (pid);
+
+ /* No need to check CALLERP here; we don't use it. */
+
+ if (!p)
+ return ESRCH;
+ if (!*pathlen)
+ return 0;
+
+ if (p->exe)
+ snprintf (*path, *pathlen, "%s", p->exe);
+ else
+ **path = 0;
+ return 0;
+}
+
Index: hurd-debian/proc/proc.h
===================================================================
--- hurd-debian.orig/proc/proc.h
+++ hurd-debian/proc/proc.h
@@ -68,6 +68,7 @@ struct proc
pthread_cond_t p_wakeup;
/* Miscellaneous information */
+ char *exe; /* path to binary executable */
vm_address_t p_argv, p_envp;
vm_address_t start_code; /* all executable segments are in this range */
vm_address_t end_code;
Index: hurd-debian/procfs/process.c
===================================================================
--- hurd-debian.orig/procfs/process.c
+++ hurd-debian/procfs/process.c
@@ -95,6 +95,13 @@ static int args_filename_length (const c
/* Actual content generators */
static ssize_t
+process_file_gc_exe (struct proc_stat *ps, char **contents)
+{
+ *contents = proc_stat_exe(ps);
+ return proc_stat_exe_len(ps);
+}
+
+static ssize_t
process_file_gc_cmdline (struct proc_stat *ps, char **contents)
{
*contents = proc_stat_args(ps);
@@ -410,6 +417,14 @@ process_file_make_node (void *dir_hook,
return np;
}
+static struct node *
+process_file_symlink_make_node (void *dir_hook, const void *entry_hook)
+{
+ struct node *np = process_file_make_node (dir_hook, entry_hook);
+ if (np) procfs_node_chtype (np, S_IFLNK);
+ return np;
+}
+
/* Stat needs its own constructor in order to set its mode according to
the --stat-mode command-line option. */
static struct node *
@@ -425,6 +440,17 @@ process_stat_make_node (void *dir_hook,
static struct procfs_dir_entry entries[] = {
{
+ .name = "exe",
+ .hook = & (struct process_file_desc) {
+ .get_contents = process_file_gc_exe,
+ .needs = PSTAT_EXE,
+ .no_cleanup = 1,
+ },
+ .ops = {
+ .make_node = process_file_symlink_make_node,
+ },
+ },
+ {
.name = "cmdline",
.hook = & (struct process_file_desc) {
.get_contents = process_file_gc_cmdline,
Index: hurd-debian/libps/procstat.c
===================================================================
--- hurd-debian.orig/libps/procstat.c
+++ hurd-debian/libps/procstat.c
@@ -956,6 +956,27 @@ proc_stat_set_flags (struct proc_stat *p
}
}
+ /* The process's path to binary executable */
+ if (NEED (PSTAT_EXE, PSTAT_PID))
+ {
+ char *buf = malloc (100);
+ ps->exe_len = 100;
+ ps->exe = buf;
+ if (ps->exe)
+ {
+ error_t err;
+ if (err = proc_get_exe (server, ps->pid, &ps->exe, &ps->exe_len))
+ free (buf);
+ else
+ {
+ have |= PSTAT_EXE;
+ ps->exe_vm_alloced = (ps->exe != buf);
+ if (ps->exe_vm_alloced)
+ free (buf);
+ }
+ }
+ }
+
/* The ctty id port; note that this is just a magic cookie;
we use it to fetch a port to the actual terminal -- it's not useful for
much else. */
Index: hurd-debian/libps/ps.h
===================================================================
--- hurd-debian.orig/libps/ps.h
+++ hurd-debian/libps/ps.h
@@ -272,6 +272,7 @@ struct proc_stat
unsigned thread_waits_vm_alloced : 1;
unsigned args_vm_alloced : 1;
unsigned env_vm_alloced : 1;
+ unsigned exe_vm_alloced : 1;
/* Various libc ports: */
@@ -305,6 +306,11 @@ struct proc_stat
size_t env_len;
unsigned num_ports;
+
+ /* The path to process's binary executable. */
+ char *exe;
+ /* The length of EXE. */
+ size_t exe_len;
};
/* Proc_stat flag bits; each bit is set in the FLAGS field if that
@@ -344,12 +350,13 @@ struct proc_stat
#define PSTAT_HOOK 0x800000 /* Has a non-zero hook */
#define PSTAT_NUM_PORTS 0x4000000 /* Number of Mach ports in the task */
#define PSTAT_TIMES 0x8000000 /* Task/thread user and system times */
+#define PSTAT_EXE 0x10000000 /* Path to binary executable */
/* Flag bits that don't correspond precisely to any field. */
#define PSTAT_NO_MSGPORT 0x1000000 /* Don't use the msgport at all */
/* Bits from PSTAT_USER_BASE on up are available for user-use. */
-#define PSTAT_USER_BASE 0x10000000
+#define PSTAT_USER_BASE 0x20000000
#define PSTAT_USER_MASK ~(PSTAT_USER_BASE - 1)
/* If the PSTAT_STATE flag is set, then the proc_stats state field holds a
@@ -448,6 +455,8 @@ extern char *proc_stat_state_tags;
#define proc_stat_tty(ps) ((ps)->tty)
#define proc_stat_task_events_info(ps) ((ps)->task_events_info)
#define proc_stat_num_ports(ps) ((ps)->num_ports)
+#define proc_stat_exe(ps) ((ps)->exe)
+#define proc_stat_exe_len(ps) ((ps)->exe_len)
#define proc_stat_has(ps, needs) (((ps)->flags & needs) == needs)
/* True if PS refers to a thread and not a process. */
Index: hurd-debian/libps/spec.c
===================================================================
--- hurd-debian.orig/libps/spec.c
+++ hurd-debian/libps/spec.c
@@ -357,6 +357,14 @@ ps_get_num_ports (struct proc_stat *ps)
const struct ps_getter ps_num_ports_getter =
{"num_ports", PSTAT_NUM_PORTS, (vf) ps_get_num_ports};
+static void
+ps_get_exe (struct proc_stat *ps, char **exe_p, int *exe_len_p)
+{
+ *exe_p = proc_stat_exe (ps);
+ *exe_len_p = proc_stat_exe_len (ps);
+}
+const struct ps_getter ps_exe_getter =
+{"exe", PSTAT_EXE, ps_get_exe};
/* ---------------------------------------------------------------- */
/* some printing functions */
@@ -1165,6 +1173,8 @@ static const struct ps_fmt_spec specs[]
&ps_zero_fills_getter, ps_emit_int, ps_cmp_ints,
ps_nominal_zint},
{"Ports", 0, -5, -1, 0,
&ps_num_ports_getter, ps_emit_int, ps_cmp_ints, 0},
+ {"Exe", 0, 0, -1, 0,
+ &ps_exe_getter, ps_emit_string, ps_cmp_strings,ps_nominal_string},
{0}
};
Index: hurd-debian/exec/Makefile
===================================================================
--- hurd-debian.orig/exec/Makefile
+++ hurd-debian/exec/Makefile
@@ -22,7 +22,7 @@ makemode := server
SRCS = exec.c main.c hashexec.c hostarch.c
OBJS = main.o hostarch.o exec.o hashexec.o \
- execServer.o exec_startupServer.o exec_experimentalServer.o
+ execServer.o exec_startupServer.o exec_experimentalServer.o
processUser.o
target = exec exec.static
HURDLIBS = trivfs fshelp iohelp ports ihash shouldbeinlibc
Index: hurd-debian/libps/Makefile
===================================================================
--- hurd-debian.orig/libps/Makefile
+++ hurd-debian/libps/Makefile
@@ -29,7 +29,7 @@ installhdrs = ps.h
installhdrsubdir = .
HURDLIBS=ihash shouldbeinlibc
-OBJS = $(SRCS:.c=.o) msgUser.o termUser.o
+OBJS = $(SRCS:.c=.o) msgUser.o termUser.o processUser.o
msg-MIGUFLAGS = -D'MSG_IMPORTS=waittime 1000;' -DUSERPREFIX=ps_
term-MIGUFLAGS = -D'TERM_IMPORTS=waittime 1000;' -DUSERPREFIX=ps_
Index: hurd-debian/hurd/process_reply.defs
===================================================================
--- hurd-debian.orig/hurd/process_reply.defs
+++ hurd-debian/hurd/process_reply.defs
@@ -194,3 +194,5 @@ simpleroutine proc_get_code_reply (
end_code: vm_address_t);
skip; /* proc_make_task_namespace */
+skip; /* proc_set_exe */
+skip; /* proc_get_exe */
Index: hurd-debian/hurd/process_request.defs
===================================================================
--- hurd-debian.orig/hurd/process_request.defs
+++ hurd-debian/hurd/process_request.defs
@@ -417,3 +417,6 @@ simpleroutine proc_make_task_namespace_r
process: process_t;
ureplyport reply: reply_port_t;
notify: mach_port_send_t);
+
+skip; /* proc_set_exe */
+skip; /* proc_get_exe */
Index: hurd-debian/proc/mgt.c
===================================================================
--- hurd-debian.orig/proc/mgt.c
+++ hurd-debian/proc/mgt.c
@@ -770,6 +770,8 @@ process_has_exited (struct proc *p)
if (!--p->p_login->l_refcnt)
free (p->p_login);
+ free (p->exe);
+ p->exe = NULL;
ids_rele (p->p_id);