File Coverage

blib/lib/Sys/Prctl.pm
Criterion Covered Total %
statement 32 34 94.1
branch 4 6 66.6
condition 5 11 45.4
subroutine 9 9 100.0
pod 4 4 100.0
total 54 64 84.3


line stmt bran cond sub pod time code
1             package Sys::Prctl;
2 1     1   36983 use strict;
  1         3  
  1         38  
3 1     1   6 use warnings;
  1         2  
  1         60  
4              
5             our $VERSION = '1.02';
6              
7             # TODO: FreeBSD support "libc.call('setproctitle', 'hippy\0');"
8              
9             =head1 NAME
10              
11             Sys::Prctl - Give access to prctl system call from Perl
12              
13             =head1 DESCRIPTION
14              
15             This is simple module that wraps the prctl system call. Currently only the
16             PR_SET_NAME and PR_GET_NAME are implemented.
17              
18             This can be use to change the process name as reported by "ps -A" and be
19             killable will killall.
20              
21             =head1 SYNOPSIS
22            
23             use Sys::Prctl(prctl_name);
24            
25             #
26             # Use with functions
27             #
28              
29             # Process name is now "My long process name"
30             my $oldname = prctl_name();
31             prctl_name("My long process name");
32              
33             #
34             # Use as an object
35             #
36            
37             my $process = new Sys::Prctl();
38              
39             # Process name is now "Short name"
40             my $oldname = $process->name();
41             $process->name('Short name');
42              
43             #
44             # Real world use
45             #
46              
47             # instead of "perl helloworld.pl"
48             $0 = "helloworld"
49             prctl_name("helloworld");
50              
51             print "Hello World\n";
52             sleep 100;
53              
54             # Process can now be killed with "killall helloworld"
55              
56             =head1 METHODS
57              
58             =over
59              
60             =cut
61              
62 1     1   1274 use POSIX qw(uname);
  1         23057  
  1         11  
63 1     1   3421 use Config;
  1         5  
  1         52  
64              
65 1     1   6 use base "Exporter";
  1         2  
  1         3002  
66              
67             our @EXPORT_OK = qw(prctl_name prctl);
68             our %EXPORT_TAGS = ();
69              
70             #
71             # Detect what os we are running and set the correct SYS_* entries
72             #
73              
74             # Defined in linux/sched.h
75             our $TASK_COMM_LEN = 16;
76              
77             our $SYS_prctl;
78             our $SYS_PR_SET_NAME = 15;
79             our $SYS_PR_GET_NAME = 16;
80              
81             if($^O eq 'linux') {
82             my ($sysname, $nodename, $release, $version, $machine) = POSIX::uname();
83            
84             # if we're running on an x86_64 kernel, but a 32-bit process,
85             # we need to use the i386 syscall numbers.
86             if ($machine eq "x86_64" && $Config{ptrsize} == 4) {
87             $machine = "i386";
88             }
89              
90             if ($machine =~ /^i[3456]86$/) {
91             $SYS_prctl = 172;
92            
93             } elsif ($machine =~ /^blackfin|cris|frv|h8300|m32r|m68k|microblaze|mn10300|sh|s390|parisc$/) {
94             $SYS_prctl = 172;
95            
96             } elsif ($machine eq "x86_64") {
97             $SYS_prctl = 157;
98            
99             } elsif ($machine eq "sparc64") {
100             $SYS_prctl = 147;
101            
102             } elsif ($machine eq "ppc") {
103             $SYS_prctl = 171;
104              
105             } elsif ($machine eq "ia64") {
106             $SYS_prctl = 1170;
107              
108             } elsif ($machine eq "alpha") {
109             $SYS_prctl = 348;
110            
111             } elsif ($machine eq "arm") {
112             $SYS_prctl = 0x900000 + 172;
113            
114             } elsif ($machine eq "avr32") {
115             $SYS_prctl = 148;
116            
117             } elsif ($machine eq "mips") { # 32bit
118             $SYS_prctl = 4000 + 192;
119            
120             } elsif ($machine eq "mips64") { # 64bit
121             $SYS_prctl = 5000 + 153;
122            
123             } elsif ($machine eq "xtensa") {
124             $SYS_prctl = 130;
125              
126             } else {
127             delete @INC{qw
128             sys/syscall.ph>};
129             my $rv = eval { require 'syscall.ph'; 1 } ## no critic
130             or eval { require 'sys/syscall.ph'; 1 }; ## no critic
131             $SYS_prctl = eval { &SYS_prctl; }
132             or die "Could not find prctl for this system";
133             }
134             }
135              
136             =item new()
137              
138             Creates a new Sys::Prctl object.
139              
140             =cut
141              
142             sub new {
143 1     1 1 3 my ($class, %opts) = @_;
144              
145 1         2 my %self = (
146            
147             );
148            
149 1   33     9 return bless \%self, (ref $class || $class);
150             }
151              
152             =item name([$string])
153              
154             Set or get the process name.
155              
156             =cut
157              
158             sub name {
159 3     3 1 7 my ($self, $str) = @_;
160 3         6 return prctl_name($str);
161             }
162              
163             =item prctl_name([$string])
164              
165             Set or get the process name.
166              
167             $string can only be 15 chars long on Linux.
168              
169             Returns undef on error.
170              
171             =cut
172              
173             sub prctl_name {
174 7     7 1 59 my ($str) = @_;
175            
176 7 100       16 if(defined $str) {
177 3         9 my $rv = prctl($SYS_PR_SET_NAME, $str);
178 3 50       8 if($rv == 0) {
179 3         15 return 1;
180             } else {
181 0         0 return;
182             }
183              
184             } else {
185 4         11 $str = "\x00" x ($TASK_COMM_LEN + 1); # allocate $str
186 4         18 my $ptr = unpack( 'L', pack( 'P', $str ) );
187 4         8 my $rv = prctl($SYS_PR_GET_NAME, $ptr);
188 4 50       10 if($rv == 0) {
189 4         22 return substr($str, 0, index($str, "\x00"));
190             } else {
191 0         0 return;
192             }
193             }
194             }
195              
196             =item prctl($option, $arg2, $arg3, $arg4, $arg5)
197              
198             Direct wrapper for prctl call
199              
200             =cut
201              
202             sub prctl {
203 7     7 1 15 my ($option, $arg2, $arg3, $arg4, $arg5) = @_;
204 7   50     113 syscall($SYS_prctl, $option,
      50        
      50        
      50        
205             ($arg2 or 0), ($arg3 or 0), ($arg4 or 0), ($arg5 or 0));
206             }
207              
208             =back
209              
210             =head1 NOTES
211              
212             Currently only 32bit Linux has been tested. So test reports and patches are
213             wellcome.
214              
215             =head1 AUTHOR
216              
217             Troels Liebe Bentsen
218              
219             =head1 COPYRIGHT
220              
221             Copyright(C) 2005-2007 Troels Liebe Bentsen
222              
223             This library is free software; you can redistribute it and/or modify
224             it under the same terms as Perl itself.
225              
226             =cut
227              
228             1;