summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c11
-rw-r--r--main.h1
-rw-r--r--rootdir.c44
3 files changed, 56 insertions, 0 deletions
diff --git a/main.c b/main.c
index 26f5248f..fee4867c 100644
--- a/main.c
+++ b/main.c
@@ -14,6 +14,7 @@
int opt_clk_tck;
mode_t opt_stat_mode;
pid_t opt_fake_self;
+pid_t opt_kernel_pid;
static error_t
argp_parser (int key, char *arg, struct argp_state *state)
@@ -44,6 +45,12 @@ argp_parser (int key, char *arg, struct argp_state *state)
else
opt_fake_self = 1;
break;
+
+ case 'k':
+ opt_kernel_pid = strtol (arg, &endp, 0);
+ if (*endp || ! *arg || (signed) opt_kernel_pid < 0)
+ error (1, 0, "--kernel-process: PID must be a positive integer");
+ break;
}
return 0;
@@ -64,6 +71,9 @@ struct argp argp = {
"Provide a fake \"self\" symlink to the given PID, for compatibility "
"purposes. If PID is omitted, \"self\" will point to init. "
"(default: no self link)" },
+ { "kernel-process", 'k', "PID", 0,
+ "Process identifier for the kernel, used to retreive its command line "
+ "(default: 2)" },
{}
},
.parser = argp_parser,
@@ -112,6 +122,7 @@ int main (int argc, char **argv)
opt_clk_tck = sysconf(_SC_CLK_TCK);
opt_stat_mode = 0400;
opt_fake_self = -1;
+ opt_kernel_pid = 2;
argp_parse (&argp, argc, argv, 0, 0, 0);
task_get_bootstrap_port (mach_task_self (), &bootstrap);
diff --git a/main.h b/main.h
index 361380b3..6ada229a 100644
--- a/main.h
+++ b/main.h
@@ -2,3 +2,4 @@
extern int opt_clk_tck;
extern mode_t opt_stat_mode;
extern pid_t opt_fake_self;
+extern pid_t opt_kernel_pid;
diff --git a/rootdir.c b/rootdir.c
index f5b43ff0..865342ce 100644
--- a/rootdir.c
+++ b/rootdir.c
@@ -5,6 +5,7 @@
#include <sys/time.h>
#include <sys/utsname.h>
#include <sys/stat.h>
+#include <argz.h>
#include <ps.h>
#include "procfs.h"
#include "procfs_dir.h"
@@ -231,6 +232,41 @@ rootdir_gc_vmstat (void *hook, void **contents, size_t *contents_len)
}
static error_t
+rootdir_gc_cmdline (void *hook, void **contents, size_t *contents_len)
+{
+ struct ps_context *pc = hook;
+ struct proc_stat *ps;
+ error_t err;
+
+ err = _proc_stat_create (opt_kernel_pid, pc, &ps);
+ if (err)
+ return EIO;
+
+ err = proc_stat_set_flags (ps, PSTAT_ARGS);
+ if (err || ! (proc_stat_flags (ps) & PSTAT_ARGS))
+ {
+ err = EIO;
+ goto out;
+ }
+
+ *contents_len = proc_stat_args_len (ps);
+ *contents = malloc (*contents_len);
+ if (! *contents)
+ {
+ err = ENOMEM;
+ goto out;
+ }
+
+ memcpy (*contents, proc_stat_args (ps), *contents_len);
+ argz_stringify (*contents, *contents_len, ' ');
+ ((char *) *contents)[*contents_len - 1] = '\n';
+
+out:
+ _proc_stat_free (ps);
+ return err;
+}
+
+static error_t
rootdir_gc_fakeself (void *hook, void **contents, size_t *contents_len)
{
*contents_len = asprintf ((char **) contents, "%d", opt_fake_self);
@@ -310,6 +346,14 @@ static const struct procfs_dir_entry rootdir_entries[] = {
.cleanup_contents = procfs_cleanup_contents_with_free,
},
},
+ {
+ .name = "cmdline",
+ .make_node = rootdir_file_make_node,
+ .hook = & (struct procfs_node_ops) {
+ .get_contents = rootdir_gc_cmdline,
+ .cleanup_contents = procfs_cleanup_contents_with_free,
+ },
+ },
{}
};