#!/usr/bin/perl package threads::system; require Exporter; @ISA = qw{Exporter}; @EXPORT_OK = qw{system}; use threads::shared; use IO::Handle; use strict; use warnings; pipe my ($crh, $cwh) or die "Could not pipe: $!"; # Command string read/write handles pipe my ($erh, $ewh) or die "Could not pipe: $!"; # Exit status read/write handles $cwh->autoflush(1); $ewh->autoflush(1); my $sync : shared; my $child = fork; die "Could not fork: $!" if $child < 0; unless ($child) { # We are the child (daemon) - we handle system() calls for our parent close $erh; close $cwh; while (<$crh>) { # Read commands to exec my $child = fork; die "Could not fork: $!" if $child < 0; unless ($child) { # We are the child - we exec() for our parent exec $_; exit $!; } else { # Parent - communicate our child's failure with our own parent while (my $pid = waitpid $child, 0) { # Is all this really needed? if ($pid < 0) { die "Error: waitpid: $!" } elsif ($pid == 0) { next } else { print $ewh $?, "\n"; last } # Tell parent! } } } # Decide: is the following a feature or a bug? exit; # Should never happen, unless client does system(undef), or something } else { # Parent close $ewh; close $crh; } sub system { lock($sync); my $string = shift; # TODO: Accept a full list print $cwh $string, "\n" or die "Could not write: $!"; return <$erh>; } 1 #### #!/usr/bin/perl use threads::system qw{system}; use strict; use warnings; my $code = system("ls -al /etc"); print "Exited with code: $code\n";