make getpeername() return the original socket address which before it was intercepted
[hband-tools.git] / user-tools / args2stdin
blob2ac7fb380a59dc66f3b4fef7ac16b8dcbc926c98
1 #!/usr/bin/env perl
3 =pod
5 =head1 NAME
7 args2stdin - Turns command arguments into input stream on STDIN
9 =head1 SYNOPSIS
11 args2stdin [I<OPTIONS>] I<COMMAND> I<ARG_1> [I<ARG_2> [...]]
13 =head1 DESCRIPTION
15 Execute I<COMMAND> command with I<ARG_n> arguments,
16 except remove those which are specified in I<OPTIONS> and write them on the command's STDIN instead.
18 =head1 OPTIONS
20 =over 4
22 =item -a, --arg I<NUM>
24 Remove the I<NUM>th argument and write it on STDIN.
25 Counting starts from 1.
26 The 0th argument would be the I<COMMAND> itself.
27 I<NUM> may be negative number, in which case it's counted from the end backwards.
29 =item -r, --right-arg I<NUM>
31 Same as B<< --arg -I<NUM> >>.
33 =item -A, --all
35 Move all arguments to STDIN.
37 =item -e, --all-after I<STRING>
39 I<STRING> marks the end of arguments.
40 All arguments after this will be passed in STDIN.
41 This argument won't be passed to I<COMMAND> anywhere.
42 It's usually C<-->.
43 args2stdin(1) does not have any default for this, so no particular argument makes the rest of them go to STDIN.
45 =item -k, --keep I<NUM>
47 Keep the first I<NUM> arguments as arguments, and move the rest of them.
48 Don't use it with B<-A>, B<-a>, or B<-r>.
50 =item -d, --delimiter I<STRING>
52 Delimit arguments by I<STRING> string.
53 Default is linefeed (B<\n>).
55 =item -t, --tab-delimiter
57 Delimit arguments by TAB char.
59 =item -0, --null
61 Delimit arguments by NUL char.
63 =back
65 =head1 SEE ALSO
67 args2env(1)
69 =cut
72 use Data::Dumper;
73 use Errno qw/:POSIX/;
74 use Getopt::Long qw/:config no_ignore_case no_bundling no_getopt_compat no_auto_abbrev require_order/;
75 use Pod::Usage;
76 no if ($] >= 5.018), 'warnings' => 'experimental::smartmatch';
78 @args_to_move = ();
79 $OptDelimiter = "\n";
80 $OptKeepArgs = undef;
81 $OptEndMark = undef;
83 GetOptions(
84 'a|arg=i@' => \@args_to_move,
85 'A|all' => sub { $OptKeepArgs = 0; },
86 'k|keep=i' => \$OptKeepArgs,
87 'r|right-arg=i@' => sub {
88 my ($getopt, $param) = @_;
89 push @args_to_move, -$param;
91 'e|all-after=s' => \$OptEndMark,
92 'd|delimiter=s' => \$OptDelimiter,
93 't|tab-delimiter' => sub { $OptDelimiter = "\t"; },
94 '0|null' => sub { $OptDelimiter = chr 0; },
95 'help' => sub { pod2usage(-exitval=>0, -verbose=>99); },
96 ) or pod2usage(-exitval=>2, -verbose=>99);
98 if(defined $OptEndMark)
100 my $mark_arg_num = undef;
101 for my $arg_num (1..$#ARGV)
103 if(defined $mark_arg_num)
105 push @args_to_move, $arg_num-1;
107 elsif($ARGV[$arg_num] eq $OptEndMark)
109 $mark_arg_num = $arg_num;
112 if(defined $mark_arg_num)
114 @ARGV = (@ARGV[0..($mark_arg_num-1)], @ARGV[($mark_arg_num+1)..$#ARGV]);
118 if(defined $OptKeepArgs)
120 @args_to_move = (($OptKeepArgs+1) .. $#ARGV);
123 if(grep {$_ == 0} @args_to_move)
125 warn "The 0th argument is the command itself, better not to remove.\n";
126 pod2usage(-exitval=>2, -verbose=>99);
129 pipe($stdin_r, $stdin_w) or die "$0: pipe: $!\n";
131 for my $arg_num (@args_to_move)
133 print {$stdin_w} $ARGV[$arg_num] . $OptDelimiter;
135 for my $arg_num (@args_to_move)
137 $ARGV[$arg_num] = undef;
139 @ARGV = grep {defined} @ARGV;
141 close $stdin_w;
142 open STDIN, '<&=', fileno $stdin_r or die "$0: open: $!\n";
144 exec {$ARGV[0]} @ARGV;
145 ($errno, $errstr) = (int $!, $!);
146 warn "$0: ${ARGV[0]}: $errstr\n";
147 exit 125+$errno;