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', manipulate it, and eventually run it, e.g.:

my $ls = Argv->new('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 and splice() 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:

    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 e.g. $obj-qx> on a list of any size without fear of exceeding your shell's limits.

    2. Unix-like exec behavior on Windows.

    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 of system()

    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. Automatic chomping.

    The module can be set to automatically chomp the results of $obj-qx>, though by default lines are un-chomped.

    6. 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 the command line 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 or set 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/qx described here may be useful for aid in writing portable programs, they're made available for export without need of accompanying objects, thus:

use Argv qw(system exec qv);

will override the Perl builtins. There is no way to override the operator qx() so we provide an alias qv().

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 or all 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. In this case the object is returned.

2. GET

If no arguments are passed the current value of the attribute 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(rcs co).

  • args()

    Returns or sets the list of operands (aka arguments).

  • 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 methods parse(), 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 and qx() on all platforms (since qx always invokes a shell, and system() 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> on Windows 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 would be executed without executing anything.

  • qxargs

    Gets or sets the number of arguments to process per shell invocation in the qx method. Setting this value to 0 suppresses the behavior.

  • systemxargs

    Analogous to qxargs but turned off (set to 0) by default. The reason for this is that qx() is typically used to read data whereas system() is more often used to make stateful changes. Consider that "ls foo bar" produces the same result if broken up into "ls foo" and "ls bar" but the same cannot be said for "mv foo bar".

  • 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=32 or ARGV_STDERR=0;

IPC::ChildSafe (COPROCESS) SUPPORT

A method ipc is defined which will cause processes to be run under control of the IPC::ChildSafe module (see). This keeps one instance of a given utility running in the background and feeds commands to it rather than forking/exec-ing each time. The utility being controlled must conform to the standards defined in the IPC::ChildSafe PODs.

This method may be used as either a class or instance method; the scope of the change in behavior varies accordingly. Parameters passed to this method are passed directly to the IPC::ChildSafe constructor. Typical usage (sample from ClearCase) would be:

$self->ipc('cleartool', 'pwd -h', 'Usage: pwd');

The first arg is the program name, the 2nd must be a cheap command providing a well-known one-line output, the 3rd is that output. The coprocess can be ended explicitly via:

$self->ipc(0);

Note: this feature is in alpha state and may change.

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, there should be no major portability issues, but please send reports of tweaks needed for other platforms to the address below.

The coprocess support is not available for Windows since IPC::ChildSafe hasn't been ported there.

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 and/or modify it under the same terms as Perl itself.

SEE ALSO

perl(1), Getopt::Long(3), IPC::ChildSafe(3)

2 POD Errors

The following errors were encountered while parsing the POD:

Around line 580:

'=item' outside of any '=over'

Around line 648:

You forgot a '=back' before '=head1'