Handle hostnames with upper-case letters
[webmin.git] / proc / index_search.cgi
1 #!/usr/local/bin/perl
2 # index_search.cgi
3 # Allows searching for processes by user or command
4
5 require './proc-lib.pl';
6 &ReadParse();
7 $in{'mode'} = 1 if ($in{'mode'} eq '');
8 $deffield = ("user", "match", "cpu", "sfs", "files", "port", "sip")
9             [$in{'mode'}];
10 &ui_print_header(undef, $text{'index_title'}, "", "search",
11                  !$no_module_config, 1, 0, undef, undef,
12                  "onLoad='document.forms[0].$deffield.focus()'");
13 &index_links("search");
14
15 # Javascript to select radio
16 print <<EOF;
17 <script>
18 function select_mode(m)
19 {
20 for(i=0; i<document.forms[0].mode.length; i++) {
21         document.forms[0].mode[i].checked = document.forms[0].mode[i].value == m;
22         }
23 }
24 </script>
25 EOF
26
27 # display search form
28 print &ui_form_start("index_search.cgi");
29 print &ui_table_start(undef, undef, 4);
30
31 # By user
32 print &ui_table_row(&ui_oneradio("mode", 0, &hlink($text{'search_user'}, "suser"),
33                               $in{'mode'} == 0),
34                     &ui_user_textbox("user", $in{'user'}, 0, 0,
35                                      &mode_selector(0)));
36
37 # By process name
38 print &ui_table_row(&ui_oneradio("mode", 1, &hlink($text{'search_match'},"smatch"),
39                               $in{'mode'} == 1),
40                     &ui_textbox("match", $in{'match'}, 30, 0, undef,
41                                 &mode_selector(1)));
42
43 if ($has_lsof_command) {
44         # TCP port
45         print &ui_table_row(&ui_oneradio("mode", 5,
46                 &hlink($text{'search_port'}, "ssocket"), $in{'mode'} == 5),
47                 &ui_textbox("port", $in{'port'}, 6, 0, undef,
48                             &mode_selector(5))." ".
49                 $text{'search_protocol'}." ".
50                 &ui_select("protocol", $in{'protocol'},
51                            [ [ 'tcp', 'TCP' ], [ 'udp', 'UDP' ] ], 1, 0, 0,
52                            0, &mode_selector(5, "onChange")));
53
54         # Using IP address
55         print &ui_table_row(&ui_oneradio("mode", 6,
56                 &hlink($text{'search_ip'}, "sip"), $in{'mode'} == 6),
57                 &ui_textbox("ip", $in{'ip'}, 20, 0, undef,
58                             &mode_selector(6)));
59         }
60
61 # By CPU used
62 print &ui_table_row(&ui_oneradio("mode", 2,
63                 &hlink($text{'search_cpupc2'}, "scpu"), $in{'mode'} == 2),
64                 &ui_textbox("cpu", $in{'cpu'}, 4, 0, undef,
65                             &mode_selector(2))."%");
66
67 if ($has_fuser_command) {
68         # Using filesystem
69         if (&foreign_check("mount")) {
70                 &foreign_require("mount", "mount-lib.pl");
71                 @opts = ( );
72                 foreach $fs (&foreign_call("mount", "list_mounted")) {
73                         next if ($fs->[2] eq "swap");
74                         push(@opts, $fs->[0]);
75                         }
76                 $fschooser = &ui_select("fs", $in{'fs'}, \@opts, 1, 0, 0, 0,
77                                         &mode_selector(3, "onChange"));
78                 }
79         else {
80                 $fschooser = &ui_textbox("fs", $in{'fs'}, 30, 0, undef,
81                                          &mode_selector(3));
82                 }
83         print &ui_table_row(&ui_oneradio("mode", 3,
84                 &hlink($text{'search_fs'}, "sfs"), $in{'mode'} == 3),
85                 $fschooser, 3);
86
87         # Using file
88         print &ui_table_row(&ui_oneradio("mode", 4,
89                 &hlink($text{'search_files'}, "sfiles"), $in{'mode'} == 4),
90                 &ui_textbox("files", $in{'files'}, 50, 0, undef,
91                             &mode_selector(4))." ".
92                 &file_chooser_button("files", 0), 3);
93         }
94
95 # Exclude own processes
96 print &ui_table_row(undef,
97         &ui_checkbox("ignore", 1,
98                 &hlink("<b>$text{'search_ignore'}</b>","signore"),
99                 $in{'ignore'} || !defined($in{'mode'})));
100
101 print &ui_table_end();
102 print &ui_form_end([ [ undef, $text{'search_submit'} ] ]);
103
104 if (%in) {
105         # search for processes
106         @procs = &list_processes();
107         @procs = grep { &can_view_process($_->{'user'}) } @procs;
108         if ($in{mode} == 0) {
109                 # search by user
110                 @dis = grep { $_->{'user'} eq $in{'user'} } @procs;
111                 }
112         elsif ($in{mode} == 1) {
113                 # search by regexp
114                 @dis = grep { $_->{'args'} =~ /\Q$in{match}\E/i } @procs;
115                 }
116         elsif ($in{mode} == 2) {
117                 # search by cpu
118                 @dis = grep { $_->{'cpu'} > $in{'cpu'} } @procs;
119                 @dis = sort { $b->{'cpu'} <=> $a->{'cpu'} } @dis;
120                 }
121         elsif ($in{mode} == 3 && $has_fuser_command) {
122                 # search by filesystem
123                 foreach $p (&find_mount_processes($in{'fs'})) { $using{$p}++; }
124                 @dis = grep { defined($using{$_->{'pid'}}) } @procs;
125                 }
126         elsif ($in{mode} == 4 && $has_fuser_command) {
127                 # search by files
128                 foreach $p (&find_file_processes(split(/\s+/, $in{'files'})))
129                         { $using{$p}++; }
130                 @dis = grep { defined($using{$_->{'pid'}}) } @procs;
131                 }
132         elsif ($in{mode} == 5 && $has_lsof_command) {
133                 foreach $p (&find_socket_processes($in{'protocol'},$in{'port'}))
134                         { $using{$p}++; }
135                 @dis = grep { defined($using{$_->{'pid'}}) } @procs;
136                 }
137         elsif ($in{mode} == 6 && $has_lsof_command) {
138                 foreach $p (&find_ip_processes($in{'ip'}))
139                         { $using{$p}++; }
140                 @dis = grep { defined($using{$_->{'pid'}}) } @procs;
141                 }
142
143         if ($in{'ignore'}) {
144                 # Ignore this process and any children
145                 @dis = grep { $_->{'pid'} != $$ && $_->{'ppid'} != $$ } @dis;
146                 }
147
148         # display matches
149         if (@dis) {
150                 print &ui_columns_start([
151                           $text{'pid'},
152                           $text{'owner'},
153                           $text{'cpu'},
154                           $info_arg_map{'_stime'} ? ( $text{'stime'} ) : ( ),
155                           $text{'command'} ], 100);
156                 foreach $d (@dis) {
157                         $p = $d->{'pid'};
158                         push(@pidlist, $p);
159                         local @cols;
160                         if (&can_edit_process($d->{'user'})) {
161                                 push(@cols, "<a href=\"edit_proc.cgi?$p\">$p</a>");
162                                 }
163                         else {
164                                 push(@cols, $p);
165                                 }
166                         push(@cols, $d->{user});
167                         push(@cols, $d->{cpu});
168                         if ($info_arg_map{'_stime'}) {
169                                 push(@cols, $d->{'_stime'});
170                                 }
171                         push(@cols, &html_escape(cut_string($d->{args})));
172                         print &ui_columns_row(\@cols);
173                         }
174                 print &ui_columns_end(),"<p>\n";
175                 }
176         else {
177                 print "<p><b>$text{'search_none'}</b><p>\n";
178                 }
179
180         if (@pidlist && $access{'simple'} && $access{'edit'}) {
181                 # display form for mass killing with selected signals
182                 print "<form action=kill_proc_list.cgi>\n";
183                 print "<input type=hidden name=args value=\"$in\">\n";
184                 printf "<input type=hidden name=pidlist value=\"%s\">\n",
185                         join(" ", @pidlist);
186                 print "<input type=hidden name=pid value=$pinfo{pid}>\n";
187                 foreach $s ('KILL', 'TERM', 'HUP', 'STOP', 'CONT') {
188                         printf "<input type=submit value=\"%s\" name=%s>\n",
189                                 $text{"kill_".lc($s)}, $s;
190                         }
191                 print "</form>\n";
192                 }
193         elsif (@pidlist && $access{'edit'}) {
194                 # display form for mass killing with any signal
195                 print "<form action=kill_proc_list.cgi>\n";
196                 print "<input type=submit value=\"$text{'search_kill'}\">\n";
197                 print "<input type=hidden name=args value=\"$in\">\n";
198                 printf "<input type=hidden name=pidlist value=\"%s\">\n",
199                         join(" ", @pidlist);
200                 print "<select name=signal>\n";
201                 foreach $s (&supported_signals()) {
202                         printf "<option value=\"$s\" %s> $s\n",
203                                 $s eq "HUP" ? "selected" : "";
204                         }
205                 print "</select>\n";
206
207                 print "&nbsp;" x 2;
208                 print "<input type=submit name=TERM ",
209                       "value='$text{'search_sigterm'}'>\n";
210                 print "&nbsp;" x 2;
211                 print "<input type=submit name=KILL ",
212                       "value='$text{'search_sigkill'}'>\n";
213                 print "</form>\n";
214                 }
215         }
216
217 &ui_print_footer("/", $text{'index'});
218
219 sub mode_selector
220 {
221 local ($m, $action) = @_;
222 $action ||= "onFocus";
223 return "$action='select_mode($m)'";
224 }
225