make getpeername() return the original socket address which before it was intercepted
[hband-tools.git] / user-tools / maskfiles
blob600bcdafe14ade7922934fc8104dbc350b4b9f17
1 #!/usr/bin/env perl
3 =pod
5 =head1 NAME
7 maskfiles - Lay over several text files on top of each other like transparency sheets for overhead projectors
9 =head1 SYNOPSIS
11 maskfiles [I<OPTIONS>] [--] I<FILE_1> I<FILE_2> [I<FILE_3> ... I<< FILE_B<n> >>]
13 =head1 DESCRIPTION
15 Take files from 1 to B<n> and virtually put them on top of each other
16 by matching byte offsets.
17 If a file from the upper layer have a hole (space by default, otherwise see --hole-char option),
18 then the char on lower layers "looks through" it.
19 Non hole chars just block the lower layers, so they are visible at the end.
21 Output is STDOUT.
22 No input files are written.
24 =head1 OPTIONS
26 =over 4
28 =item -h, --hole-chars I<CHARS>
30 Which chars are to be looked through.
31 By default space is the only hole char.
32 Add underscore to it by example: --hole-chars=" _"
34 =item --nul-hole
36 Make NUL chars to look through as well.
38 =item --linewise
40 Respect line breaks.
42 =back
44 =cut
47 use Fcntl qw/:flock :seek/;
48 use Getopt::Long qw/:config no_ignore_case no_bundling no_getopt_compat no_auto_abbrev require_order/;
49 use Pod::Usage;
50 use POSIX;
51 no if ($] >= 5.018), 'warnings' => 'experimental::smartmatch';
54 $OptHoleChars = " ";
55 $OptHoleNUL = 0;
56 $OptLinewise = 0;
58 GetOptions(
59 'h|hole|holechar|hole-char|holechars|hole-chars=s' => \$OptHoleChars,
60 'nul-hole' => \$OptHoleNUL,
61 'l|linewise!' => \$OptLinewise,
62 'help' => sub { pod2usage(-exitval=>0, -verbose=>99); },
63 ) or pod2usage(-exitval=>2, -verbose=>99);
66 $OptHoleChars .= chr(0) if $OptHoleNUL;
68 @overlay_files = @ARGV;
69 @layers = ();
71 for my $path (reverse @overlay_files)
73 open my $fh, '<', $path or die "$0: open: $path: $!\n";
74 push @layers, {'fh'=>$fh, 'eol'=>0};
77 while(1)
79 my $char0;
80 my $char;
82 last if not grep {defined $_->{'fh'}} @layers;
84 if($OptLinewise and not grep {defined $_->{'fh'} and not $_->{'eol'}} @layers)
86 # all files are at EOL, reset flags
87 map {$_->{'eol'} = 0} @layers;
90 for my $layer (@layers)
92 my $fh = $layer->{'fh'};
93 next if not defined $fh;
94 next if $OptLinewise and $layer->{'eol'};
96 my $nbytes = read $fh, $char, 1;
97 if($nbytes != 1)
99 $layer->{'fh'} = undef;
100 next;
102 if($OptLinewise and $char eq "\n")
104 $layer->{'eol'} = 1;
105 next;
108 if(not defined $char0 and $OptHoleChars !~ /\Q$char\E/)
110 $char0 = $char;
114 $char0 = $char if not defined $char0; # there are holes all the way down to the lowermost layer
115 print $char0;