2 # Functions for parsing sysv-style ps output
4 $has_stime = $gconfig{'os_type'} eq 'solaris';
5 $has_task = $gconfig{'os_type'} eq 'solaris' && $gconfig{'os_version'} >= 10;
6 $has_zone = $gconfig{'os_type'} eq 'solaris' && $gconfig{'os_version'} >= 10;
8 # list_processes([pid]*)
11 local($line, $dummy, @w, $i, $_, $pcmd, @plist);
12 foreach (@_) { $pcmd .= " -p $_"; }
13 if (!$pcmd) { $pcmd = " -e"; }
14 $ENV{'COLUMNS'} = 10000; # needed on AIX
15 local @cols = ( "user","ruser","group","rgroup","pid","ppid","pgid","pcpu","vsz",
16 "nice","etime","time",
17 ($has_stime ? ("stime") : ( )),
18 ($has_task ? ("taskid") : ( )),
19 ($has_zone ? ("zone") : ( )),
21 open(PS, "ps -o ".join(",", @cols)." $pcmd |");
23 for($i=0; $line=<PS>; $i++) {
26 @w = split(/\s+/, $line);
27 if ($line =~ /ps -o user,ruser/) {
31 $plist[$i]->{"pid"} = $w[4];
32 $plist[$i]->{"ppid"} = $w[5];
33 $plist[$i]->{"user"} = $w[0];
34 $plist[$i]->{"cpu"} = "$w[7] %";
35 $plist[$i]->{"size"} = "$w[8] kB";
38 $plist[$i]->{"_stime"} = $w[12+$ofs];
39 $plist[$i]->{"_stime"} =~ s/_/ /g;
43 $plist[$i]->{"_task"} = $w[12+$ofs];
47 $plist[$i]->{"_zone"} = $w[12+$ofs];
50 $plist[$i]->{"time"} = $w[11];
51 $plist[$i]->{"nice"} = $w[9] =~ /\d+/ ? $w[9]-20 : $w[9];
52 $plist[$i]->{"args"} = @w<14+$ofs ? "defunct"
53 : join(' ', @w[13+$ofs..$#w]);
54 $plist[$i]->{"_group"} = $w[2];
55 $plist[$i]->{"_ruser"} = $w[1];
56 $plist[$i]->{"_rgroup"} = $w[3];
57 $plist[$i]->{"_pgid"} = $w[6];
58 $plist[$i]->{"_tty"} = $w[12+$ofs] =~ /\?/ ? $text{'edit_none'}
65 # find_mount_processes(mountpoint)
66 # Find all processes under some mount point
67 sub find_mount_processes
70 $out = `fuser -c $_[0] 2>/dev/null`;
71 $out =~ s/^\s+//g; $out =~ s/\s+$//g;
72 return split(/\s+/, $out);
75 # find_file_processes([file]+)
76 # Find all processes with some file open
77 sub find_file_processes
80 $files = join(' ', map { quotemeta($_) } map { glob($_) } @_);
81 $out = &backquote_command("fuser $files 2>/dev/null");
82 $out =~ s/^\s+//g; $out =~ s/\s+$//g;
83 return split(/\s+/, $out);
86 # renice_proc(pid, nice)
89 return undef if (&is_readonly_mode());
90 local $out = &backquote_logged("renice $_[1] -p $_[0] 2>&1");
91 if ($?) { return $out; }
96 # Returns the filehandles and names for a pty and tty
99 if (!-e "/dev/ptyp0") {
100 # Must use IO::Pty :(
101 &error("IO::Pty Perl module is not installed");
104 # Need to search through pty files
105 opendir(DEV, "/dev");
106 local @ptys = map { "/dev/$_" } (grep { /^pty/ } readdir(DEV));
109 foreach $pty (@ptys) {
110 open(PTY, "+>$pty") || next;
111 local $tty = $pty; $tty =~ s/pty/tty/;
112 open(TTY, "+>$tty") || next;
113 local $old = select(PTY); $| = 1;
114 select(TTY); $| = 1; select($old);
115 return (*PTY, *TTY, $pty, $tty);
121 $has_trace_command = $gconfig{'os_type'} eq 'solaris' &&
122 &has_command("truss");
124 # open_process_trace(pid, [&syscalls])
125 # Starts tracing on some process, and returns a trace object
126 sub open_process_trace
128 local $fh = time().$$;
131 $sc = "-t ".join(",", @{$_[1]});
133 local $tpid = open($fh, "truss $sc -i -p $_[0] 2>&1 |");
135 return { 'pid' => $_[0],
140 # close_process_trace(&trace)
141 # Halts tracing on some trace object
142 sub close_process_trace
144 kill('TERM', $_[0]->{'tpid'}) if ($_[0]->{'tpid'});
145 close($_[0]->{'fh'});
148 # read_process_trace(&trace)
149 # Returns an action structure representing one action by traced process, or
150 # undef if an error occurred
151 sub read_process_trace
153 local $fh = $_[0]->{'fh'};
154 local @tm = localtime(time());
157 return undef if (!$line);
158 if ($line =~ /^([^\(]+)\((.*)\)(\s*=\s*(\-?\d+)|\s+(Err\S+))?/) {
159 local $action = { 'time' => time(),
161 'rv' => $4 ne "" ? $4 : $5 };
165 if ($args =~ /^[ ,]*(\{[^}]*\})(.*)$/) {
170 elsif ($args =~ /^[ ,]*"([^"]*)"\.*(.*)$/) {
175 elsif ($args =~ /^[ ,]*\[([^\]]*)\](.*)$/) {
176 # A square-bracket number
180 elsif ($args =~ /^[ ,]*\<([^\>]*)\>(.*)$/) {
181 # An angle-bracketed string
185 elsif ($args =~ /[ ,]*([^, ]+)(.*)$/) {
194 $action->{'args'} = \@args;
201 # Returns a list containing the 5, 10 and 15 minute load averages
204 local $out = `uptime 2>&1`;
205 if ($out =~ /load average:\s+(\S+),\s+(\S+),\s+(\S+)/) {
214 # Returns a list containing the real mem, free real mem, swap and free swap
218 if (!&has_command("kstat")) {
222 foreach my $s ("physmem", "freemem") {
223 local $out = &backquote_command("kstat -p -m unix -s $s");
224 if ($out =~ /\s+(\d+)/) {
228 local ($swaptotal, $swapfree);
229 &open_execute_command(SWAP, "swap -l", 1);
231 if (/^\S+\s+\d+,\d+\s+\d+\s+(\d+)\s+(\d+)/) {
237 local $pagesize = &backquote_command("pagesize 2>/dev/null");
238 $pagesize = int($pagesize)/1024;
239 $pagesize ||= 8; # Fallback
240 return ($stat{'physmem'}*$pagesize, $stat{'freemem'}*$pagesize,
241 $swaptotal/2, $swapfree/2);
245 foreach $ia (keys %text) {
246 if ($ia =~ /^sysv(_\S+)/) {
247 $info_arg_map{$1} = $text{$ia};
250 delete($info_arg_map{'_stime'}) if (!$has_stime);
252 @nice_range = (-20 .. 19);
254 $has_fuser_command = 1;