source: for-distributions/trunk/bin/windows/perl/lib/Shell.pm@ 14489

Last change on this file since 14489 was 14489, checked in by oranfry, 17 years ago

upgrading to perl 5.8

File size: 6.8 KB
Line 
1package Shell;
2use 5.006_001;
3use strict;
4use warnings;
5use File::Spec::Functions;
6
7our($capture_stderr, $raw, $VERSION, $AUTOLOAD);
8
9$VERSION = '0.6';
10
11sub new { bless \my $foo, shift }
12sub DESTROY { }
13
14sub import {
15 my $self = shift;
16 my ($callpack, $callfile, $callline) = caller;
17 my @EXPORT;
18 if (@_) {
19 @EXPORT = @_;
20 } else {
21 @EXPORT = 'AUTOLOAD';
22 }
23 foreach my $sym (@EXPORT) {
24 no strict 'refs';
25 *{"${callpack}::$sym"} = \&{"Shell::$sym"};
26 }
27}
28
29sub AUTOLOAD {
30 shift if ref $_[0] && $_[0]->isa( 'Shell' );
31 my $cmd = $AUTOLOAD;
32 $cmd =~ s/^.*:://;
33 my $null = File::Spec::Functions::devnull();
34 $Shell::capture_stderr ||= 0;
35 eval <<"*END*";
36 sub $AUTOLOAD {
37 shift if ref \$_[0] && \$_[0]->isa( 'Shell' );
38 if (\@_ < 1) {
39 \$Shell::capture_stderr == 1 ? `$cmd 2>&1` :
40 \$Shell::capture_stderr == -1 ? `$cmd 2>$null` :
41 `$cmd`;
42 } elsif ('$^O' eq 'os2') {
43 local(\*SAVEOUT, \*READ, \*WRITE);
44
45 open SAVEOUT, '>&STDOUT' or die;
46 pipe READ, WRITE or die;
47 open STDOUT, '>&WRITE' or die;
48 close WRITE;
49
50 my \$pid = system(1, '$cmd', \@_);
51 die "Can't execute $cmd: \$!\\n" if \$pid < 0;
52
53 open STDOUT, '>&SAVEOUT' or die;
54 close SAVEOUT;
55
56 if (wantarray) {
57 my \@ret = <READ>;
58 close READ;
59 waitpid \$pid, 0;
60 \@ret;
61 } else {
62 local(\$/) = undef;
63 my \$ret = <READ>;
64 close READ;
65 waitpid \$pid, 0;
66 \$ret;
67 }
68 } else {
69 my \$a;
70 my \@arr = \@_;
71 unless( \$Shell::raw ){
72 if ('$^O' eq 'MSWin32') {
73 # XXX this special-casing should not be needed
74 # if we do quoting right on Windows. :-(
75 #
76 # First, escape all quotes. Cover the case where we
77 # want to pass along a quote preceded by a backslash
78 # (i.e., C<"param \\""" end">).
79 # Ugly, yup? You know, windoze.
80 # Enclose in quotes only the parameters that need it:
81 # try this: c:\> dir "/w"
82 # and this: c:\> dir /w
83 for (\@arr) {
84 s/"/\\\\"/g;
85 s/\\\\\\\\"/\\\\\\\\"""/g;
86 \$_ = qq["\$_"] if /\\s/;
87 }
88 } else {
89 for (\@arr) {
90 s/(['\\\\])/\\\\\$1/g;
91 \$_ = \$_;
92 }
93 }
94 }
95 push \@arr, '2>&1' if \$Shell::capture_stderr == 1;
96 push \@arr, '2>$null' if \$Shell::capture_stderr == -1;
97 open(SUBPROC, join(' ', '$cmd', \@arr, '|'))
98 or die "Can't exec $cmd: \$!\\n";
99 if (wantarray) {
100 my \@ret = <SUBPROC>;
101 close SUBPROC; # XXX Oughta use a destructor.
102 \@ret;
103 } else {
104 local(\$/) = undef;
105 my \$ret = <SUBPROC>;
106 close SUBPROC;
107 \$ret;
108 }
109 }
110 }
111*END*
112
113 die "$@\n" if $@;
114 goto &$AUTOLOAD;
115}
116
1171;
118
119__END__
120
121=head1 NAME
122
123Shell - run shell commands transparently within perl
124
125=head1 SYNOPSIS
126
127 use Shell qw(cat ps cp);
128 $passwd = cat('</etc/passwd');
129 @pslines = ps('-ww'),
130 cp("/etc/passwd", "/tmp/passwd");
131
132 # object oriented
133 my $sh = Shell->new;
134 print $sh->ls('-l');
135
136=head1 DESCRIPTION
137
138=head2 Caveats
139
140This package is included as a show case, illustrating a few Perl features.
141It shouldn't be used for production programs. Although it does provide a
142simple interface for obtaining the standard output of arbitrary commands,
143there may be better ways of achieving what you need.
144
145Running shell commands while obtaining standard output can be done with the
146C<qx/STRING/> operator, or by calling C<open> with a filename expression that
147ends with C<|>, giving you the option to process one line at a time.
148If you don't need to process standard output at all, you might use C<system>
149(in preference of doing a print with the collected standard output).
150
151Since Shell.pm and all of the aforementioned techniques use your system's
152shell to call some local command, none of them is portable across different
153systems. Note, however, that there are several built in functions and
154library packages providing portable implementations of functions operating
155on files, such as: C<glob>, C<link> and C<unlink>, C<mkdir> and C<rmdir>,
156C<rename>, C<File::Compare>, C<File::Copy>, C<File::Find> etc.
157
158Using Shell.pm while importing C<foo> creates a subroutine C<foo> in the
159namespace of the importing package. Calling C<foo> with arguments C<arg1>,
160C<arg2>,... results in a shell command C<foo arg1 arg2...>, where the
161function name and the arguments are joined with a blank. (See the subsection
162on Escaping magic characters.) Since the result is essentially a command
163line to be passed to the shell, your notion of arguments to the Perl
164function is not necessarily identical to what the shell treats as a
165command line token, to be passed as an individual argument to the program.
166Furthermore, note that this implies that C<foo> is callable by file name
167only, which frequently depends on the setting of the program's environment.
168
169Creating a Shell object gives you the opportunity to call any command
170in the usual OO notation without requiring you to announce it in the
171C<use Shell> statement. Don't assume any additional semantics being
172associated with a Shell object: in no way is it similar to a shell
173process with its environment or current working directory or any
174other setting.
175
176=head2 Escaping Magic Characters
177
178It is, in general, impossible to take care of quoting the shell's
179magic characters. For some obscure reason, however, Shell.pm quotes
180apostrophes (C<'>) and backslashes (C<\>) on UNIX, and spaces and
181quotes (C<">) on Windows.
182
183=head2 Configuration
184
185If you set $Shell::capture_stderr to true, the module will attempt to
186capture the standard error output of the process as well. This is
187done by adding C<2E<gt>&1> to the command line, so don't try this on
188a system not supporting this redirection.
189
190If you set $Shell::raw to true no quoting whatsoever is done.
191
192=head1 BUGS
193
194Quoting should be off by default.
195
196It isn't possible to call shell built in commands, but it can be
197done by using a workaround, e.g. shell( '-c', 'set' ).
198
199Capturing standard error does not work on some systems (e.g. VMS).
200
201=head1 AUTHOR
202
203 Date: Thu, 22 Sep 94 16:18:16 -0700
204 Message-Id: <[email protected]>
205 To: [email protected]
206 From: Larry Wall <[email protected]>
207 Subject: a new module I just wrote
208
209Here's one that'll whack your mind a little out.
210
211 #!/usr/bin/perl
212
213 use Shell;
214
215 $foo = echo("howdy", "<funny>", "world");
216 print $foo;
217
218 $passwd = cat("</etc/passwd");
219 print $passwd;
220
221 sub ps;
222 print ps -ww;
223
224 cp("/etc/passwd", "/etc/passwd.orig");
225
226That's maybe too gonzo. It actually exports an AUTOLOAD to the current
227package (and uncovered a bug in Beta 3, by the way). Maybe the usual
228usage should be
229
230 use Shell qw(echo cat ps cp);
231
232Larry Wall
233
234Changes by [email protected] and Dave Cottle <[email protected]>.
235
236Changes for OO syntax and bug fixes by Casey West <[email protected]>.
237
238C<$Shell::raw> and pod rewrite by Wolfgang Laun.
239
240=cut
Note: See TracBrowser for help on using the repository browser.