mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
146 lines
4.7 KiB
Perl
Executable file
146 lines
4.7 KiB
Perl
Executable file
#!/usr/bin/perl
|
|
require 5.002;
|
|
use Cwd;
|
|
use File::Basename;
|
|
use Getopt::Std;
|
|
|
|
$ENV{'PATH'} = "/bin:/usr/bin:/usr/local/sbin";
|
|
|
|
my($req_file, $req_name, $req_path, $req_filter);
|
|
my($trace_number, $trace_pid, $trace_path, $trace_filter);
|
|
|
|
getopts('kqPF') or die __FILE__, " [-kqPF] [<path>]<name> [<filter>]\n";
|
|
$req_file = shift or die "missing argument: <name>\n",
|
|
__FILE__, " [-kqPF] [<path>]<name> [<filter>]\n";
|
|
($req_name, $req_path) = fileparse($req_file);
|
|
if ($req_name ne $req_file) {
|
|
chdir $req_path;
|
|
$req_path = cwd."/";
|
|
} else {
|
|
$req_path = "";
|
|
}
|
|
$req_filter = join " ", @ARGV;
|
|
|
|
($trace_number, $trace_pid, $trace_path, $trace_filter) = scan_ps($req_name);
|
|
|
|
if ($trace_number) {
|
|
if ($opt_k) {
|
|
kill('TERM', $trace_pid) or
|
|
die __FILE__, ": couldn't kill ", $trace_pid, "\n";
|
|
$opt_q or print STDERR "killed ", $trace_pid, "\n";
|
|
exit;
|
|
}
|
|
$req_path = $trace_path unless ($req_path);
|
|
if ($req_path ne $trace_path) {
|
|
if ($opt_P) {
|
|
$opt_q or print STDERR "changing path from: ", $trace_path,
|
|
"\nto: ", $req_path, "\n";
|
|
} else {
|
|
die __FILE__, ": paths don't match\n",
|
|
$req_path, " != ", $trace_path, "\n";
|
|
}
|
|
}
|
|
$req_filter = $trace_filter unless ($req_filter);
|
|
if ($req_filter ne $trace_filter) {
|
|
if ($opt_F) {
|
|
$opt_q or print STDERR "changing filter from:\n", $trace_filter,
|
|
"\nto:\n", $req_filter, "\n";
|
|
} else {
|
|
die __FILE__, ": filters don't match\n",
|
|
$req_filter, "\n!=\n", $trace_filter, "\n";
|
|
}
|
|
}
|
|
start_trace($req_path, $req_name, ++$trace_number, $req_filter);
|
|
kill('TERM', $trace_pid) or
|
|
die __FILE__, ": couldn't kill ", $trace_pid, "\n";
|
|
} else {
|
|
die __FILE__, ": no such trace as ", $req_name, "\n" if ($opt_k);
|
|
$req_path = cwd."/" unless ($req_path);
|
|
$req_filter or die __FILE__, ": no filter specified\n";
|
|
start_trace($req_path, $req_name, 1, $req_filter);
|
|
}
|
|
|
|
# scan_ps <trace name>
|
|
# returns (<trace number>, <trace PID>, <trace path>, <trace filter>)
|
|
#
|
|
# runs ps looking for a trace running with the given name. If none is
|
|
# found <trace number> returns 0. Otherwise the process info is
|
|
# returned. If mor than one trace with the given name are found, the
|
|
# program terminates with an error.
|
|
#
|
|
sub scan_ps {
|
|
my($trace_name) = @_;
|
|
|
|
my($trace_number, $trace_filter, $trace_pid, $trace_path);
|
|
my($ps_pid, $ps_tt, $ps_stat, $ps_time,
|
|
$ps_cmd, $ps_cmd1, $ps_cmd2, $ps_cmd3, $ps_cmd4, $ps_filter);
|
|
my($ps_name, $ps_path, $ps_suffix);
|
|
|
|
open PS, "ps -axww |" or die __FILE__, ": can't run ps\n";
|
|
while (<PS>) {
|
|
($ps_pid, $ps_tt, $ps_stat, $ps_time,
|
|
$ps_cmd, $ps_cmd1, $ps_cmd2, $ps_cmd3, $ps_cmd4, $ps_cmd5, $ps_cmd6, $ps_filter) =
|
|
split(" ", $_, 12);
|
|
if ($ps_cmd eq "tcpdump" && $ps_cmd3 eq "-w" &&
|
|
$ps_cmd5 eq "-s" && $ps_cmd6 == "8192") {
|
|
$ps_cmd6 = 0;
|
|
($ps_name, $ps_path, $ps_suffix) = fileparse($ps_cmd4, '-\d+\.trace');
|
|
if ($ps_name eq $trace_name && $ps_suffix =~ /-(\d+)\.trace/) {
|
|
if ($trace_pid) {
|
|
die __FILE__, ": more than one $trace_name trace running\n";
|
|
}
|
|
$trace_number = $1;
|
|
$trace_filter = $ps_filter;
|
|
chomp $trace_filter;
|
|
$trace_pid = $ps_pid;
|
|
$trace_path = $ps_path;
|
|
}
|
|
}
|
|
}
|
|
return ($trace_number, $trace_pid, $trace_path, $trace_filter);
|
|
}
|
|
|
|
# start_trace <path>, <name>, <number>, <filter>
|
|
#
|
|
# fork off a new process running this trace. Nothing is returned.
|
|
# Any failure terminates the program.
|
|
#
|
|
sub start_trace {
|
|
my($path, $name, $number, $filter) = @_;
|
|
|
|
my($pid);
|
|
|
|
$number = next_file($path, $name, $number, ".trace", ".out");
|
|
$opt_q or print STDERR "starting ", $path.$name."-".$number, "\n";
|
|
if ($pid = fork) {
|
|
sleep 3;
|
|
unless ($opt_q) {
|
|
open OUTFILE, $path.$name."-".$number.".out" or
|
|
die __FILE__, ": no ", $path.$name."-".$number.".out\n";
|
|
print <OUTFILE>;
|
|
close OUTFILE;
|
|
}
|
|
return;
|
|
} elsif (defined $pid) {
|
|
exec "/bin/sh", "-c", "tcpdump -i em0 -w ".$path.$name."-".$number.".trace -s 8192 '".$filter.
|
|
"' > ".$path.$name."-".$number.".out 2>&1 &";
|
|
die __FILE__, ": couldn't exec\n";
|
|
} else {
|
|
die __FILE__, ": couldn't fork\n";
|
|
}
|
|
}
|
|
|
|
# next_file <path>, <name>, <number>, <suffix>...
|
|
# returns <number>
|
|
#
|
|
# searches for a number (beginning with the target number) for which
|
|
# no files of the form <path><name>-<number><suffix> exists.
|
|
# As many suffixes as needed can be passed in. The resulting number
|
|
# is returned.
|
|
#
|
|
sub next_file {
|
|
my($path, $name, $number, @suffixes) = @_;
|
|
|
|
++$number until grep (-e $path.$name."-".$number.$_, @suffixes) == 0;
|
|
return $number;
|
|
}
|