NAME
Argv - Provide an O-O interface to an ARGV
SYNOPSIS
use Argv;
# A roundabout way of getting perl's version.
my $pl = Argv->new(qw(perl -v));
$pl->exec;
# Run /bin/cat, showing how to provide "predigested" options.
Argv->new('/bin/cat', [qw(-u -n)], @ARGV)->system;
# A roundabout way of globbing.
my $echo = Argv->new(qw(echo M*));
$echo->glob;
my $globbed = $echo->qx;
print "'echo M*' globs to: $globbed";
# A demonstration of the builtin xargs-like behavior.
my @files = split(/\s+/, $globbed);
my $ls = Argv->new(qw(ls -d -l), @files);
$ls->parse(qw(d l));
$ls->dbglevel(1);
$ls->qxargs(1);
my @long = $ls->qx;
$ls->dbglevel(0);
print @long;
# A demonstration of how to use option sets in a wrapper program.
my $wrapper = Argv->new(qw(Who -y -x foo -r));
$wrapper->dbglevel(1);
$wrapper->optset(qw(ONE TWO THREE));
$wrapper->parseONE(qw(x=s));
$wrapper->parseTWO(qw(y z));
$wrapper->parseTHREE(qw(r));
$wrapper->prog(lc($wrapper->prog));
$wrapper->exec(qw(THREE));
## More advanced examples can be lifted from the test script.
RAISON D'ETRE
This module presents an O-O approach to command lines, allowing you to instantiate an 'argv object' and run it, e.g.:
my $ls = Argv->new(qw(ls -l));
my $rc = $ls->system; # or $ls->exec or $ls->qx
Which raises the immediate question - what value does this mumbo-jumbo add over Perl's native support such as:
my $rc = system(qw(ls -l));
The answer comes in a few parts:
STRUCTURE
First, by recognizing the underlying properties of an arg vector. Every argv begins with a program name which is followed by (potentially) options and operands. The object factors its raw argv into these three groups, and provides accessor methods which allow operations on each group independently.
OPTION SETS
Second, the module encapsulates and extends
Getopt::Long
to allow parsing of the argv's options into different option sets. This is useful in the case of wrapper programs which may, for instance, need to parse out one set of flags which direct the behavior of the wrapper itself, parse a different set and pass them to program X, then another for program Y, then exec program Z with the remainder. Doing this kind of thing on a basic @ARGV using indexing andsplice()
is do-able but leads to spaghetti-ish code and lots of off-by-one errors.EXTRA FEATURES
The execution methods
system, exec, and qx
extend their Perl builtin analogues in a few ways. These features could in theory be factored out into a separate module, but at least for now they're embedded here:- 1. An xargs-like capability.
-
You can set a maximum number of arguments to be processed at a time, which allows you to blithely invoke
$obj-
qx> on a list of any size without fear of exceeding your shell's limits. - 2. Unix-like exec behavior.
-
The Perl builtin exec() on Windows behaves differently from that of Unix; it returns to the shell after invoking the new process. In contrast, the Argv->exec method blocks until the new process is finished, which makes it "feel" like Unix exec().
- 3. Automatic quoting.
-
Win32 system() always uses the shell, whereas other systems offer ways to avoid a shell. The
$obj-
system> method automatically quotes its arguments on Win32 to protect against the shell in those cases where it wouldn't be used on more reasonable platforms. - 4. Automatic globbing.
-
On Win32 systems, the shell doesn't expand wildcards but rather leaves this to the application. Perl provides the glob() function for this purpose; this module can optionally apply glob() to each operand in the argv before execution, automatically.
- 5. Pathname conversion.
-
By default, the execution methods will convert pathnames to their native format before executing. I.e. pathnames containing / will be converted to \ on a Windows platform.
All of these behaviors can be toggled - see CLASS METHODS below.
DESCRIPTION
An Argv object treats its argv as 3 separate entities: the program, the options, and the args. The options may be futher subdivided into named option sets by use of the optset
method. When one of the execution methods is called, the parts are reassmbled into a single list and passed to the underlying Perl primitive.
Contrast this with the way Perl handles its own programs, putting the 0th element of the argv in $0
and the rest in @ARGV
.
By default there's one option set, known as the anonymous option set, whose name is the null string. All parsed options go there. The advanced user can define more option sets, parse options into them according to Getopt::Long-style descriptions, query the parsed values, and then reassemble them in any way desired at exec time. Declaring an option set automatically declares a set of methods for dealing with it (see below).
FUNCTIONAL INTERFACE
Because the extensions to system/exec described here may be useful for porting an existing script from Unix to Windows, they're made available for export without need of accompanying objects, thus:
use Argv qw(system exec);
will override the Perl builtins. There is no way to override the operator qx() so there's no functional interface to Argv->qx.
CONSTRUCTOR
my $obj = Argv->new(@list)
The @list
is what will be parsed/executed/etc by subsequent method calls. During initial construction, the first element of the list is separated off as the program; the rest is lumped together as part of the args until and unless option parsing is done, in which case matched options are shifted into collectors for their various option sets. You can also create a "predigested" instance by passing any of the prog, opt, or arg parts as array refs. E.g.
Argv->new([qw(cleartool ci)], [qw(-nc -ide)], qw(file1 file2 file3));
Predigested options are placed in the default (anonymous) option set.
METHODS
Unless otherwise indicated methods are of the traditional get/set variety, such that:
- 1. SET
-
If arguments are passed they become the new value of the referenced attribute, and this new value is returned.
- 2. GET
-
If no arguments are passed the current value is returned.
- 3. CLEAR
-
If no arguments are passed and the method is called in a void context, the attribute is cleared.
INSTANCE METHODS
prog()
Returns or sets the name of the program (the
"argv[0]"
). This can be a list, e.g.qw(cvs update)
.args()
Returns or sets the list of operands.
optset(<list-of-set-names>);
For each name NAME in the parameter list, an option set of that name is declared and 3 new methods are registered dynamically:
parseNAME(), optsNAME(), and flagNAME()
. These methods are described below: note that the anonymous option set (see OPTION SETS) is predefined, so the methodsparse(), opts(), and flag()
are always available. Most users won't need to define any other sets.parseNAME(...option-descriptions...)
Takes a list of option descriptions and uses Getopt::Long::GetOptions() to parse them out of the current argv and into option set NAME. Since it uses Getopt::Long, the opt-descs are exactly as supported by your version of that, except that no linkage argument is allowed.
optsNAME()
Returns or sets the list of options in the option set NAME.
flagname()
Returns or sets the value of flag name in the appropriate optset.
system([<optset-list>])
Reassembles the complete argv and invokes system() on it. Return value and value of $?, $!, etc. are just as described for "system" in perlfunc
Arguments to this method determine which of the parsed option-sets will be used in the executed argv. By default, only the anonymous option set is used. A different set of option sets may be requested by passing their names.
An option set may be requested by passing its name (with an optional leading '+') or explicitly rejected by using its name with a leading '-'. Thus, given the existence of option sets ONE, TWO, and THREE, the following are legal:
$obj->system; # use none $obj->system('+'); # use all $obj->system(qw(ONE -TWO +THREE); # use ONE and THREE
exec()
Similar to system above, but never returns. On Windows, it blocks until the new process finishes for a more Unix-like behavior than "exec" in perlfunc.
Option sets are handled as described in system above.
qx()
Same semantics as "qx" in perlfunc (aka backquotes) but has the capability to process only a set number of arguments at a time to avoid exceeding the shell's line-length limit. This value is settable with the qxargs method. No matter how many shell invocations are used, the total output is returned in a context-sensitive manner a la "qx" in perlfunc.
Option sets are handled as described in system above.
extract
Takes an optset name and a list of option descs; creates the named optset, extracts any of the named options, places them in the specified optset, and returns them.
quote(@list)
Protects the argument list against exposure to a shell by quoting each element. This method is invoked automatically by the system method on Windows platforms, where "system" in perlfunc always uses a shell, and by the qx method on all platforms since it always invokes a shell.
The automatic use of quote can be turned off via the autoquote method (see).
If passed a list, quotes that list; otherwise quotes the operands of its instance. In a void context, replaces its instance's operands with the quoted list. In a list context, returns the quoted list without modifying its instance.
glob
Expands the argument list using "glob" in perlfunc. Primarily useful on Windows where the invoking shell does not do this for you.
Automatic use of glob (on Windows) can be turned on with the autoglob method (see).
CLASS METHODS
The following are auto-generated accessor methods of the classic get/set variety; if arguments are passed they become the new value of the eponymous attribute, and the current value is returned whether said attribute was changed or not.
These also have the property that they may be used as either class or instance methods. If used as an instance method the attribute is set only on that instance; if used as a class method it sets or gets the default for all instances which haven't overridden it. This is an implementation of translucent attributes as described in Tom Christiansen's perltootc tutorial.
autoglob
If set, the
glob()
function is applied to the operands ($self-
args>) on Windows only.autoquote
If set, the operands are automatically quoted against shell expansion before
system()
on Windows andqx()
on all platforms (sinceqx
always invokes a shell, andsystem()
always does so on Windows).dbglevel
Sets the debug level. Level 0 (the default) is no debugging, 1 prints each command before executing it, and higher levels offer progressively more output.
dfltopts
Sets and/or returns the default set of option sets to be used. The default-default is the anonymous option set. Note: this method takes an array reference as its optional argument and returns an array ref as well.
execwait
If set,
$self-
exec> blocks until the new process is finished for a more consistent Unix-like behavior than the traditional Win32 Perl port.nativepath
If set, converts pathnames to their native format just before executing. This is set by default on Windows only, thus converting /x/y/z to \x\y\z.
noexec
Analogous to the
-n
flag to make; prints what it would execute without executing.qxargs
Gets or sets the number of arguments to process per shell invocation.
stdout
Default value is true which has no effect. When passed a false value, e.g:
$obj->stdout(0);
causes STDOUT to be closed during invocation of any of the execution methods
system, exec, and qx
, and restored when they finish. A fancy (and portable) way of saying 1>/dev/null without needing a shell.stderr
As above, for STDERR.
Defaults for all of the above may be provided in the environment, e.g. ARGV_QXARGS=128 or ARGV_STDERR=0;
PORTING
This module is known to work on Solaris 2.5-7 and Windows NT 4.0SP3-5. As these two platforms are quite different, this should take care of any major portability issues, but please send reports of tweaks needed for other platforms to the address below.
AUTHOR
David Boyce <dsb@world.std.com>
COPYRIGHT
Copyright (c) 1999 David Boyce. All rights reserved. This perl program is free software; you may redistribute it and/or modify it under the same terms as Perl itself.
SEE ALSO
perl(1), Getopt::Long(3)
2 POD Errors
The following errors were encountered while parsing the POD:
- Around line 469:
'=item' outside of any '=over'
- Around line 534:
You forgot a '=back' before '=head1'