Skip Menu |

This queue is for tickets about the Proc-ProcessTable CPAN distribution.

Report information
The Basics
Id: 52442
Status: resolved
Priority: 0/
Queue: Proc-ProcessTable

People
Owner: cpan [...] bargsten.org
Requestors: zhull [...] jetpay.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



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);
Download signature.asc
application/pgp-signature 197b

Message body not shown because it is not plain text.

Thanks for that patch. I'm currently working on cleaning up the module to get it extensible more easy. I hope I get it finished this year - but maybe it's getting January ...
On 2009-12-08 08:53:23, REHSACK wrote: Show quoted text
> Thanks for that patch. I'm currently working on cleaning up the module > to get it extensible more easy. > > I hope I get it finished this year - but maybe it's getting January ...
This enhancement is also possible for other operating systems, e.g. FreeBSD (both implementations, kvm and procfs) and OpenBSD — so if the patch for Linux is accepted, I would also like to provide patches at least for FreeBSD.
Subject: [rt.cpan.org #52442] Enhancement: NULL separated files returned as arrays.
Date: Tue, 4 Apr 2017 20:34:11 +0200
To: bug-Proc-ProcessTable [...] rt.cpan.org
From: Christoph Biedl <debian.axhn [...] manchmal.in-ulm.de>
Any progress on this? The current implementation replaces NUL with spaces with makes it impossible to parse the command line reliably. This hit me badly today, and I had to switch to reading /proc/$pid/cmdline which is a horrible hack. Christoph
Download signature.asc
application/pgp-signature 819b

Message body not shown because it is not plain text.

Applied the patch and it seems to work. Did not create any tests, though. Changed code is now in github and will be part of the next release.