#!/usr/bin/perl -W

# exec2dot, build a graph from exec-notify output files
# (C) 2007 Sebastian Krahmer <krahmer@suse.de>
#

use IO::Handle;

my $exec_notify = shift || "./exec-notify|";
my $line = "";
my %childs = ();
my %cmdlines = ();
my $x = "";

$SIG{INT} = write_out;

open(E, $exec_notify) or die $!;
open(O, ">e.dot") or die $!;
print O<<EOO;
digraph G {
size="7,9";concentrate=true;
rankdir=LR;
ratio=fill;
node [shape=box,style=filled,fontsize=8];
EOO

O->autoflush(1);

for (;;) {
	$line = <E>;
	last if (!defined $line);
	next if ($line !~ /EXEC|FORK/);
	if ($line =~ /FORK:parent\(pid,tgid\)=(\d+),\d+\tchild\(pid,tgid\)=(\d+),\d+\t\[(.+)\]/) {
		push (@{$childs{$1}}, $2);
		$x = $3;
		$x =~ s/"/\\"/g;
		$cmdlines{$1} = $x;
		$cmdlines{$2} = $x;
	}
	if ($line =~ /EXEC:pid=(\d+),tgid=\d+\t\[Uid:.+\]\t\[(.+)\]/) {
		$x = $2;
		$x =~ s/"/\\"/g;
		$cmdlines{$1} = $x;
	}
}

# in case its not a piped command
write_out();

sub write_out
{
	foreach my $pid (keys %childs) {
		# %childs is a Hash of Arrays
		foreach (@{$childs{$pid}}) {
			# no bash forks for itself
			if ($cmdlines{$pid} ne $cmdlines{$_}) {
				print O "\"".$cmdlines{$pid}."\"->\"".$cmdlines{$_}."\";\n";
			}
		}
	}
	print O "}\n";
	close(E);
	close(O);
	exit;
}


