Subject: | Enhancement: NULL separated files returned as arrays. |
Date: | Fri, 04 Dec 2009 13:37:15 -0600 |
To: | bug-Proc-ProcessTable [...] rt.cpan.org |
From: | "Zephaniah E. Hull" <zhull [...] jetpay.com> |
Under linux, /proc/<n>/ contains a number of files which are NULL
separated, to allow for precise breaks.
This is fairly important for a few cases, as simply replacing the NULLs
with spaces causes a loss of data, or, in some cases, makes it
impractical to even return the data.
And thus the attached patch, it provides cmdline (an array version of
cmndline, I'm not attached enough to the name to care), and environ (the
environment of the process in question) as arrays.
It additionally parses out TracerPid.
There's also some glue code for the A and a types, which ignores an
array of strings, or creates an array of strings.
It compiles and seems to work.
Zephaniah E. Hull.
diff -ur libproc-processtable-perl-0.45/os/Linux.c mine/libproc-processtable-perl-0.45/os/Linux.c
--- libproc-processtable-perl-0.45/os/Linux.c 2008-09-08 10:10:41.000000000 -0500
+++ mine/libproc-processtable-perl-0.45/os/Linux.c 2009-03-12 15:31:30.000000000 -0500
@@ -427,6 +427,34 @@
field_enable(format_str, F_CMNDLINE);
}
+static void get_proc_cmdline(char *pid, char *format_str, struct procstat* prs,
+ struct obstack *mem_pool)
+{
+ char *cmdline_text, *cur;
+ off_t cmdline_off;
+
+ if ((cmdline_text = read_file(pid, "cmdline", &cmdline_off, mem_pool)) == NULL)
+ return;
+
+ prs->cmdline = cmdline_text;
+ prs->cmdline_len = cmdline_off;
+ field_enable(format_str, F_CMDLINE);
+}
+
+static void get_proc_environ(char *pid, char *format_str, struct procstat* prs,
+ struct obstack *mem_pool)
+{
+ char *environ_text, *cur;
+ off_t environ_off;
+
+ if ((environ_text = read_file(pid, "environ", &environ_off, mem_pool)) == NULL)
+ return;
+
+ prs->environ = environ_text;
+ prs->environ_len = environ_off;
+ field_enable(format_str, F_ENVIRON);
+}
+
static void get_proc_status(char *pid, char *format_str, struct procstat* prs,
struct obstack *mem_pool)
{
@@ -458,10 +486,13 @@
} else if (strncmp(loc, "Gid:", 4) == 0) {
sscanf(loc + 4, " %d %d %d %d", &dummy_i, &prs->egid, &prs->sgid, &prs->fgid);
field_enable_range(format_str, F_EGID, F_FGID);
+ } else if (strncmp(loc, "TracerPid:", 10) == 0) {
+ sscanf(loc + 10, " %d", &prs->tracer);
+ field_enable(format_str, F_TRACER);
}
/* short circuit condition */
- if (islower(format_str[F_EUID]) && islower(format_str[F_EGID]))
+ if (islower(format_str[F_EUID]) && islower(format_str[F_EGID]) && islower(format_str[F_TRACER]))
goto done;
}
@@ -635,8 +666,14 @@
/* correct values (times) found in /proc/${pid}/stat */
fixup_stat_values(format_str, prs);
- /* get process' cmndline */
- get_proc_cmndline(dir_result->d_name, format_str, prs, &mem_pool);
+ /* get process' cmndline */
+ get_proc_cmndline(dir_result->d_name, format_str, prs, &mem_pool);
+
+ /* get process' cmdline */
+ get_proc_cmdline(dir_result->d_name, format_str, prs, &mem_pool);
+
+ /* get process' environ */
+ get_proc_environ(dir_result->d_name, format_str, prs, &mem_pool);
/* get process' cwd & exec values from the symblink */
eval_link(dir_result->d_name, "cwd", F_CWD, &prs->cwd, format_str,
@@ -687,7 +724,12 @@
prs->pctmem,
prs->cmndline,
prs->exec,
- prs->cwd
+ prs->cwd,
+ prs->cmdline,
+ prs->cmdline_len,
+ prs->environ,
+ prs->environ_len,
+ prs->tracer
);
/* we want a new prs, for the next itteration */
diff -ur libproc-processtable-perl-0.45/os/Linux.h mine/libproc-processtable-perl-0.45/os/Linux.h
--- libproc-processtable-perl-0.45/os/Linux.h 2008-09-08 10:08:41.000000000 -0500
+++ mine/libproc-processtable-perl-0.45/os/Linux.h 2009-03-12 15:28:41.000000000 -0500
@@ -20,6 +20,7 @@
int ppid;
int pgrp;
int sid;
+ int tracer;
int tty;
unsigned flags;
unsigned long minflt, cminflt, majflt, cmajflt;
@@ -40,6 +41,10 @@
/* cwd, cmdline & exec files; values allocated at the end of obstacks */
char *cwd;
char *cmndline;
+ char *cmdline;
+ int cmdline_len;
+ char *environ;
+ int environ_len;
char *exec;
/* other values */
char pctcpu[sizeof("100.00")]; /* precent cpu, without '%' char */
@@ -105,8 +110,11 @@
"cmndline\0"
"exec\0"
"cwd\0"
+ "cmdline\0"
+ "environ\0"
+ "tracer\0"
/* format string */
- "IIISIIIILLLLLJJJJIJLLLJJSIIIIIISSSSS\0"
+ "IIISIIIILLLLLJJJJIJLLLJJSIIIIIISSSSSAAI\0"
};
/* I generated this array with a perl script processing the above char array,
@@ -156,8 +164,11 @@
270,
279,
284,
+ 288,
+ 296,
+ 304,
/* default format string (pre lower casing) */
- 288
+ 311
};
enum string_name {
@@ -203,6 +214,9 @@
STR_FIELD_CMNDLINE,
STR_FIELD_EXEC,
STR_FIELD_CWD,
+ STR_FIELD_CMDLINE,
+ STR_FIELD_ENIVORN,
+ STR_FIELD_TRACER,
/* format string */
STR_DEFAULT_FORMAT
};
@@ -245,7 +259,10 @@
F_PCTMEM,
F_CMNDLINE,
F_EXEC,
- F_CWD
+ F_CWD,
+ F_CMDLINE,
+ F_ENVIRON,
+ F_TRACER
};
static const char* const field_names[] =
@@ -285,6 +302,9 @@
strings + 263,
strings + 270,
strings + 279,
- strings + 284
+ strings + 284,
+ strings + 288,
+ strings + 296,
+ strings + 304
};
diff -ur libproc-processtable-perl-0.45/ProcessTable.xs mine/libproc-processtable-perl-0.45/ProcessTable.xs
--- libproc-processtable-perl-0.45/ProcessTable.xs 2008-01-25 23:12:22.000000000 -0600
+++ mine/libproc-processtable-perl-0.45/ProcessTable.xs 2009-02-09 17:23:09.000000000 -0600
@@ -107,6 +107,8 @@
/* This gets called by OS-specific get_table */
/* format specifies what types are being passed in, in a string */
/* containing these specifiers: */
+/* A ignore this array of strings */
+/* a array of strings, delimated with NULL, next argument is len */
/* S ignore this string */
/* s string */
/* I ignore this int */
@@ -152,6 +154,27 @@
key = *fields;
switch(*format)
{
+ case 'A': /* ignore; creates an undef value for this key in the hash */
+ va_arg(args, char *);
+ va_arg(args, int);
+ hv_store(myhash, key, strlen(key), &PL_sv_undef, 0);
+ break;
+ case 'a': /* string */
+ s_val = va_arg(args, char *);
+ i_val = va_arg(args, int);
+ {
+ int len;
+ char *s;
+ AV *av = newAV();
+
+ for (s = s_val; s < (s_val + i_val); s += len + 1) {
+ len = strlen(s);
+ av_push (av, newSVpvn (s, len));
+ }
+ hv_store (myhash, key, strlen(key), newRV_noinc((SV *) av), 0);
+ }
+ break;
+
case 'S': /* ignore; creates an undef value for this key in the hash */
va_arg(args, char *);
hv_store(myhash, key, strlen(key), &PL_sv_undef, 0);
Message body not shown because it is not plain text.