10

The /proc filesystem contains details of running processes. For example on Linux if your PID is 123 then the command line of that process will be found in /proc/123/cmdline

The cmdline is using null-bytes to separate the arguments.

I suspect unpack should be used but I don't know how, my miserable attempts at it using various templates ("x", "z", "C*", "H*", "A*", etc.) just did not work.

emx
  • 1,295
  • 4
  • 17
  • 28
  • My end result (being able to read the original command line string) is achieved by doing `$line =~ s/\0/ /g;` (thanks to lanzz for the inspiration) – emx Jun 18 '12 at 14:34
  • `my @cmd = $line =~ /([^\0]+)/g` might be cleaner. Then you can simply reassemble the cmd with `"@cmd"` if you want. – TLP Jun 18 '12 at 14:44

4 Answers4

9

A simple split("\0", $line) would do the job just fine.

lanzz
  • 42,060
  • 10
  • 89
  • 98
5

You can set $/ to "\0". Example:

perl -ne 'INIT{ $/ = "\0"} chomp; print "$_\n";' < /proc/$$/environ
Vi.
  • 37,014
  • 18
  • 93
  • 148
3

I don't actually recommend using this, but just for your information: the unpack template that would have worked is unpack "(Z*)*", $cmdline. Z packs and unpacks null-terminated strings, but because it's a string type, a number or star after it is a length, not a repetition — Z* unpacks one null-terminated string of arbitrary length. To unpack any number of them requires wrapping it in parentheses and then applying repetition to the parenthesized-group, which gets you (Z*)*.

hobbs
  • 223,387
  • 19
  • 210
  • 288
3

This can be done with the command line switches -l and -0, or by manually changing $/.

-l and -0 are order dependent and can be used multiple times.

Thanks for inspiring me to read perlrun documentation.

examples:

# -0    : set input separator to null
# -l012 : chomp input separator (null) 
#         and set output separator explicitly to newline, octol 012.
# -p    : print each line
# -e0   : null program

perl -0 -l012 -pe0 < /proc/$$/environ

.

# -l    : chomp input separator (/n) (with -p / -n)
#         and set output separator to current input separator (/n)
# -0    : set input separator to null
# -p    : print each line
# -e0   : null program

perl -l -0 -pe0 < /proc/$$/environ

.

# partially manual version
# -l    : chomp input separator (/n) (with -p / -n)
#         and set output separator to current input separator (/n)
# -p    : print each line
# -e    : set input record separator ($/) explicitly to null
perl -lpe 'INIT{$/="\0"}'  < /proc/$$/environ

bundling issues:

# DOESN'T WORK:
# -l0   : chomp input separator (/n) (with -p / -n)
#         and set output separator to \0
# -e0   : null program
perl -l0 -pe0

.

# DOESN'T WORK:
# -0    : set input separator to null (\0)
# -l    : chomp input separator (\0) (with -p / -n)
#         and set output separator to current input separator (\0)
# -e0   : null program
perl -0l -pe1
spazm
  • 4,399
  • 31
  • 30