2 # Functions for managing processes
6 do "$config{ps_style}-lib.pl";
8 %access = &get_module_acl();
9 map { $hide{$_}++ } split(/\s+/, $access{'hide'});
13 local @plist = &list_processes($_[0]);
14 return @plist ? %{$plist[0]} : ();
17 # index_links(current)
21 print "<b>$text{'index_display'} : </b> \n";
22 foreach $l ("tree", "user", "size", "cpu", "search", "run") {
23 next if ($l eq "run" && !$access{'run'});
24 if ($l ne $_[0]) { print "<a href=index_$l.cgi>"; }
26 print $text{"index_$l"};
27 if ($l ne $_[0]) { print "</a>"; }
28 else { print "</b>"; }
32 open(INDEX, "> $module_config_directory/index");
34 print INDEX "$1?$in\n";
40 if (length($_[0]) > $_[1]) {
41 return substr($_[0], 0, $_[1])." ...";
49 if ($access{'uid'} < 0) {
50 local @u = getpwnam($remote_user);
51 $( = $u[3]; $) = "$u[3] $u[3]";
52 ($>, $<) = ($u[2], $u[2]);
54 elsif ($access{'uid'}) {
55 local @u = getpwuid($access{'uid'});
56 $( = $u[3]; $) = "$u[3] $u[3]";
57 ($>, $<) = ($u[2], $u[2]);
61 # safe_process_exec(command, uid, gid, handle, input, fixtags, bsmode)
62 # Executes the given command as the given user/group and writes all output
63 # to the given file handle. Finishes when there is no more output or the
64 # process stops running. Returns the number of bytes read.
67 # setup pipes and fork the process
68 local $chld = $SIG{'CHLD'};
69 $SIG{'CHLD'} = \&safe_exec_reaper;
79 open(STDOUT, ">&OUTw");
80 open(STDERR, ">&OUTw");
82 close(OUTr); close(INw);
86 # switch to given UID and GID
87 $( = $_[2]; $) = "$_[2] $_[2]";
88 ($>, $<) = ($_[1], $_[1]);
91 # switch to UID and all GIDs
92 local @u = getpwuid($_[1]);
94 $) = "$u[3] ".join(" ", $u[3], &other_groups($u[0]));
95 ($>, $<) = ($u[2], $u[2]);
100 delete($ENV{'FOREIGN_MODULE_NAME'});
101 delete($ENV{'SCRIPT_NAME'});
102 exec("/bin/sh", "-c", $_[0]);
103 print "Exec failed : $!\n";
106 close(OUTw); close(INr);
108 # Feed input (if any)
112 # Read and show output
113 local $fn = fileno(OUTr);
118 local ($rmask, $buf);
119 vec($rmask, $fn, 1) = 1;
120 local $sel = select($rmask, undef, undef, 1);
121 if ($sel > 0 && vec($rmask, $fn, 1)) {
122 # got something to read.. print it
123 sysread(OUTr, $buf, 1024) || last;
124 $got += length($buf);
126 $buf = &html_escape($buf);
129 # Convert backspaces and returns
131 while($line =~ s/^([^\n]*\n)//) {
133 while($one =~ s/.\010//) { }
142 # nothing to read. maybe the process is done, and a subprocess
143 # is hanging things up
144 last if (!kill(0, $pid));
149 $SIG{'CHLD'} = $chld;
153 # safe_process_exec_logged(..)
154 # Like safe_process_exec, but also logs the command
155 sub safe_process_exec_logged
157 &additional_log('exec', undef, $_[0]);
158 return &safe_process_exec(@_);
164 do { local $oldexit = $?;
165 $xp = waitpid(-1, WNOHANG);
166 $? = $oldexit if ($? < 0);
170 # pty_process_exec(command, [uid, gid])
171 # Starts the given command in a new pty and returns the pty filehandle and PID
174 local ($ptyfh, $ttyfh, $pty, $tty) = &get_new_pty();
177 close(STDIN); close(STDOUT); close(STDERR);
178 untie(*STDIN); untie(*STDOUT); untie(*STDERR);
182 $( = $u[3]; $) = "$_[2] $_[2]";
183 ($>, $<) = ($_[1], $_[1]);
185 open(STDIN, "<$tty");
186 open(STDOUT, ">&$ttyfh");
187 open(STDERR, ">&STDOUT");
190 print "Exec failed : $!\n";
194 return ($ptyfh, $pid);
197 # pty_process_exec_logged(..)
198 # Like pty_process_exec, but logs the command as well
199 sub pty_process_exec_logged
201 &additional_log('exec', undef, $_[0]);
202 return &pty_process_exec(@_);
206 # Returns an array of all processes matching some name
210 local @rv = grep { $_->{'args'} =~ /$name/ } &list_processes();
211 return wantarray ? @rv : $rv[0];
214 $has_lsof_command = &has_command("lsof");
216 # find_socket_processes(protocol, port)
217 # Returns all processes using some port and protocol
218 sub find_socket_processes
221 open(LSOF, "lsof -i '$_[0]:$_[1]' |");
223 if (/^(\S+)\s+(\d+)/) {
231 # find_process_sockets(pid)
232 # Returns all network connections made by some process
233 sub find_process_sockets
236 open(LSOF, "lsof -i tcp -i udp -n |");
238 if (/^(\S+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+).*(TCP|UDP)\s+(.*)/
240 local $n = { 'fd' => $4,
244 if ($m =~ /^([^:\s]+):([^:\s]+)\s+\(listen\)/i) {
249 elsif ($m =~ /^([^:\s]+):([^:\s]+)->([^:\s]+):([^:\s]+)\s+\((\S+)\)/) {
256 elsif ($m =~ /^([^:\s]+):([^:\s]+)/) {
267 # find_process_files(pid)
268 # Returns all files currently held open by some process
269 sub find_process_files
272 open(LSOF, "lsof -p '$_[0]' |");
274 if (/^(\S+)\s+(\d+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\d+),(\d+)\s+(\d+)\s+(\d+)\s+(.*)/) {
275 push(@rv, { 'fd' => lc($4),
277 'device' => [ $6, $7 ],