[7657] in Perl-Users-Digest
Perl-Users Digest, Issue: 1283 Volume: 8
daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Thu Nov 6 23:08:08 1997
Date: Thu, 6 Nov 97 20:00:22 -0800
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)
Perl-Users Digest Thu, 6 Nov 1997 Volume: 8 Number: 1283
Today's topics:
Alpha and Oracle On NT (Lee Sang Joon)
Re: An excellent example of perl madness (or "split stu (Jonathan Stowe)
Re: An excellent example of perl madness (or "split stu (Andrew M. Langmead)
Associative Array (HASH) problem <faerielands@geocities.com>
Re: Associative Array (HASH) problem (brian d foy)
Re: CPAN confusion (Martien Verbruggen)
Re: Extended REs in Perl 5.00401: /x extension failure (brian d foy)
Re: Help with ugly regex (Eric Bohlman)
Help! with CGI <medcon@euronet.nl>
Re: Help: Format > 80 char. w/ multiple variables wraps (Jason Gloudon)
Re: memory leak in POP3Client or something else? <rootbeer@teleport.com>
Mirror <hdcclan@geocities.com>
Re: Mirror (brian d foy)
Re: Puzzle: palindromep <doug@tc.net>
Re: Puzzle: palindromep (Eric Bohlman)
Re: Regular Expressions (Martien Verbruggen)
rlogin from script <turton@osprey.arc.nasa.gov>
Re: Seeking Year 2000 checker OR comment stripper for C <johnb@imagix.com>
Re: Self-Modifying Perl Scripts twod@not.valid
Tricky problem... how to use open3() in "open3.pl" ?? <T.Nugent@sct.gu.edu.au>
Re: unset an array (John Moreno)
Digest Administrivia (Last modified: 8 Mar 97) (Perl-Users-Digest Admin)
----------------------------------------------------------------------
Date: 7 Nov 1997 01:52:22 GMT
From: passman@taewool.co.kr (Lee Sang Joon)
Subject: Alpha and Oracle On NT
Message-Id: <63ts8m$le9$1@usenet.kreonet.re.kr>
Dear helper,
I need your big hand.
My Problem is, How can I upload a file and mail on NT .
Our system is alpha server and Data BASE is Oracle.
Web server is Oracle web server , tool sis PL/SQL.
Plz tell me. What can I do ?
Thanks in advance.
E-mail : passman@taewool.co.kr
------------------------------
Date: 7 Nov 1997 00:21:35 GMT
From: Gellyfish@btinternet.com (Jonathan Stowe)
Subject: Re: An excellent example of perl madness (or "split stupidity")
Message-Id: <63tmuf$49t@argon.btinternet.com>
In article <8cd8keufos.fsf@gadget.cscaper.com>, Randal
Schwartz (merlyn@stonehenge.com) says...
-----cut---
>
>>>>>> "Gary" == Gary Howland <ghowland@hotlava.com> writes:
>
>Gary> Three of the following work as expected. A pint for anyone who can
tell
>Gary> my which three (without running the code):
>
>(Five, actually...)
>
---cut----
>And how do you plan on getting me my pints?
>
It might be my code but I make that 1 and two third pints ;-}
you'll have to come to the UK both of you
(Arcane weights and measures Joke ?)
------------------------------
Date: Fri, 7 Nov 1997 02:40:20 GMT
From: aml@world.std.com (Andrew M. Langmead)
Subject: Re: An excellent example of perl madness (or "split stupidity")
Message-Id: <EJ98r9.Aqo@world.std.com>
bart.mediamind@tornado.be (Bart Lateur) writes:
>Let me prove you wrong by pointing at the documentation, ok? (I love it
>when this happens <grin>)
> If you look a bit further down in the same documentation, you can see:
>: The pattern PATTERN may be replaced with an expression to specify
>: patterns that vary at runtime. (To do runtime compilation only once,
>: use /$variable/o.)
But it (the result of the expression) is still a regular expression
pattern. I may have worded things poorly, and did mixed together
syntax issues with my personal stylistic preferences in my
examples. (But notice I said "the only one I would trust" and "would
find acceptable".) I wanted to deflect the argument away from the fact
that the compiler accepts all of the statements that were presented,
and towards why most of them were even tried.
Whenever I see code in which the first argument to split() is a
constant string (except a single space) or a single scalar variable, I
sincerely doubt the author knows what they are doing.
Why would anyone want to intentionally add the overhead of constant
regular expression compilation to their split() call? For the case
where the delimeter is in a variable and the variable should not be
optimized with the /o modifer, then you do have a case where both have
to be recompiled. If the programmer adds two extra keys before and
after the variable, but lets it be clear that they intend the variable
to be the pattern of a regular expression.
>"expression" means "a string" here (or, more general, a scalar).
Even more general than that. It means an expression.
sub tab { '\t' }
$_ = "a\tb";
print join ', ', split tab;
or
print join ', ', split chr(9);
>Just read the docs completely before slapping anybody around the ears
>with it, will you?
If he had read as much as I had quoted (its hard to miss the first
three lines if you look up what split does. In a heading, lots of
whitespace, made to stand out), he would have had a limited knowledge
of it, but would not have been confused. If he had read and understood
as far as you quoted, he would have a fuller knowledge and still would
not have been confused. I can't see any reason why someone would think
to write:
split "\|"
"Oh, I see that the argument to split doesn't have to be a constant
pattern. Let me put a double quoted string which will evaluate to a
single vertical bar, which will be evaluated at runtime into regular
expression which will match a null pattern."
--
Andrew Langmead
------------------------------
Date: Thu, 06 Nov 1997 15:48:32 -0800
From: Ryoko <faerielands@geocities.com>
Subject: Associative Array (HASH) problem
Message-Id: <34625739.1689@geocities.com>
I have a flat file that looks something like:
Paul::Jones::Houston::Texas::150
Jack::Jones::Houston::Texas::150
Paul::Jackson::Houston::Texas::150
Kelly::Maxwell::Detroit::Michigan::20
Matt::Howard::Pasadena::California::125
Matt::Howard::Pasadena::Arkansas::125
Oliver::Twist::Yonkers::New Jersey::5
Fred::Flinstone::Hollywood::Californiay::70
The numbers at the end are scores that each player received after
playing a game. I wish to set up an associative array with the scores as
the KEYs of this assoc. array. Can the score '150', for example, be
associated with 'Paul::Jones::Houston::Texas' in one instance, and
'Jack::Jones::Houston::Texas' in another? I would like the assoc. array
to look like this:
{ 150, 'Paul::Jones::Houston::Texas',
150, 'Jack::Jones::Houston::Texas',
5, 'Oliver::Twist::Yonkers::New Jersey',
etc... }
I placed the above flat file in an array '@data', and I try to make the
assoc. array as follows:
foreach $item (@data) {
@item_line = split("\0", $item);
$the_score = $item_line[4];
$the_rest = join("::", $item_line[0], $item_line[1], $item_line[2],
$item_line[3]);
$SCORE{$the_score} = $the_rest;
}
So, the first time around, the score '150' is associated with
'Paul::Jones::Houston::Texas'. The second time around, the score '150'
is associated with 'Jack::Jones::Houston::Texas', and the first
association is REPLACED. How can I write a piece of code that will allow
me to have two keys being the same, but have each one be associated with
a DIFFERENT value? Is this possible? Should I use pointers? the 'each'
command? Help!
My ultimate goal is to be able to SORT all the records according to
their score (in descending order -- I have that taken care of). For
players who have identical scores, they would appear next to each other
in the sorting process.
Thank you for your time!
------------------------------
Date: Thu, 06 Nov 1997 21:56:01 -0500
From: comdog@computerdog.com (brian d foy)
Subject: Re: Associative Array (HASH) problem
Message-Id: <comdog-ya02408000R0611972156010001@news.panix.com>
In article <34625739.1689@geocities.com>, faerielands@geocities.com wrote:
>Paul::Jones::Houston::Texas::150
>Jack::Jones::Houston::Texas::150
>Paul::Jackson::Houston::Texas::150
>The numbers at the end are scores that each player received after
>playing a game. I wish to set up an associative array with the scores as
>the KEYs of this assoc. array. Can the score '150', for example, be
>associated with 'Paul::Jones::Houston::Texas' in one instance, and
>'Jack::Jones::Houston::Texas' in another?
perhaps a hash of lists would work for you? see the perldsc
man page.
good luck :)
--
brian d foy <comdog@computerdog.com>
NY.pm - New York Perl M((o|u)ngers|aniacs)* <URL:http://ny.pm.org/>
CGI Meta FAQ <URL:http://computerdog.com/CGI_MetaFAQ.html>
------------------------------
Date: 7 Nov 1997 01:32:16 GMT
From: mgjv@comdyn.com.au (Martien Verbruggen)
Subject: Re: CPAN confusion
Message-Id: <63tr30$86t$2@comdyn.comdyn.com.au>
In article <waan2jkyss9.fsf@am.ucsc.edu>,
hermit@cats.ucsc.edu (William R. Ward) writes:
> Maybe I'm just missing something here, but I find CPAN to be a total
> pain in the ass to browse. If I access the module list I am unable to
No one is forcing you to use CPAN. You could always just write all the
modules yourself.
> Who maintains the CPAN web interface that I see mirrored all over the
> place and how can I get him/her to change this?
If you are going to request a change, I would suggest that you change
your tone of voice a bit. I for one (and obviously others) found it at
least slightly on the offensive side.
Martien
--
Martien Verbruggen |
Webmaster www.tradingpost.com.au |
Commercial Dynamics Pty. Ltd. | What's another word for Thesaurus?
NSW, Australia |
------------------------------
Date: Thu, 06 Nov 1997 20:35:03 -0500
From: comdog@computerdog.com (brian d foy)
Subject: Re: Extended REs in Perl 5.00401: /x extension failure or bogus code?
Message-Id: <comdog-ya02408000R0611972035030001@news.panix.com>
In article <comdog-ya02408000R0611971723200001@news.panix.com>, comdog@computerdog.com (brian d foy) wrote:
>In article <34621F07.22472776@analog.com>, willie.anderson@analog.com wrote:
>>Uncaught exception from user code:
>> / # in $b, replace:
>> (?=^) # null-width anchor
>> (#|{|/\*) # open comment .
>> (.*?) # mi
>> /: unmatched () in regexp at test.pl line 76, <> chunk 1.
>
>look what $c_open interpolated to! there's a / in there, not to
>mention all sorts of other meta characters!
Tom P. just pointed out to me that the problem, in this case, is the
#.
checking the owl book [1] i find a nifty figure on page 223 that
illustrates that path from program text to regular expression.
variable interpolation happens before \x processing, so it's possible
to interpolate commments into the regex.
[1]
Mastering Regular Expressions
Jeffrey Freidl
ISBN 1-56592-257-3
<URL:http://www.oreilly.com>
--
brian d foy <comdog@computerdog.com>
NY.pm - New York Perl M((o|u)ngers|aniacs)* <URL:http://ny.pm.org/>
CGI Meta FAQ <URL:http://computerdog.com/CGI_MetaFAQ.html>
thinks Eli will use this to some devious end
------------------------------
Date: Fri, 7 Nov 1997 01:31:08 GMT
From: ebohlman@netcom.com (Eric Bohlman)
Subject: Re: Help with ugly regex
Message-Id: <ebohlmanEJ95Jw.6r8@netcom.com>
schadsey@coralsys.com wrote:
: I have a rule that has (needs) a quite flexible format. The format can be
: any combination of the following :
: 1) word
: 2) word;word;word... # that is, multiple semicolon-separated words
: 3) word(number)
: 4) word(number);word(number)...
: 5) word(number, number, number...)
: 6) word(number,score number)
: 7) word(number, number, number..., score number)
: 8) word(number,number...,score number);word(number,number...,score
: number)...
[snip]
: here's my regex that *works* up to a point (should be a single line,no
: whitespace):
: /^\s*(\s*%?\w+(\((\s*-?\w+\s*,?)*(\s*score\s*\d+)?\))?;)*(\s*%?\w+
: (\((\s*-?\w+\s*,?)*(\s*score\s*\d+)?\))?)\s*$/
: 1 questions:
: 1) is there a simpler working regex?
Here's what I came up with:
^\w+\s*\(\s*\d+(\s*,\s*\d+)*(\s*score\s*\d+)?\)?(\s*;\s*\w+\s*\(\s*\d+(\s*,\s*
\d+)*(\s*score\s*\d+)?\)?)*$
How did I come up with it?
$elem="\\d+";
$list="$elem(\\s*,\\s*$elem)*(\\s*score\\s*$elem)?";
$term="\\w+\\s*\\(\\s*$list\\)?";
$exp="^$term(\\s*;\\s*$term)*\$";
print $exp,"\n";
Note that the expression would be a lot shorter if you could simply strip
whitespace out of a string before trying to match it.
Note also that the BNF-like method I used for building up a regex only
works if there's no recursion in the nonterminals; something like
$list="$elem(;$list)?";
won't expand properly (if it did, you could use Perl regexes to recognize
any context-free language with an LL(1) grammar, but you can't).
------------------------------
Date: 7 Nov 1997 02:11:51 GMT
From: "Alwin Bijvoet" <medcon@euronet.nl>
Subject: Help! with CGI
Message-Id: <01bceb1a$0175b6a0$693f86c2@default>
Hello,
I am using win95
I installed perl for Win32 Build 306 (apr 97)
I am using frontpage97
The problem:
When I try tu run a cgi-script I get the error message:
CGI Error
The specified CGI application misbehaved by not returning a complete set
of HTTP headers. The headers it did return are:
Can't open perl script "_vti_cnf": Permission denied
What to do?
Thanks
------------------------------
Date: 7 Nov 1997 00:04:56 GMT
From: jgloudon@bbn.remove.com (Jason Gloudon)
Subject: Re: Help: Format > 80 char. w/ multiple variables wraps
Message-Id: <63tlv8$6i$1@daily.bbnplanet.com>
Lyn Lewis (lynl@PROBLEM_WITH_INEWS_GATEWAY_FILE) wrote:
: @<<<<<<<<<<<<<<<<< @||||| @||||| @||||| @||||| @||||| @||||| @||||| @|||||
: $vname, $vasgn[0], $vasgn[1], $vasgn[2], $vasgn[3], $vasgn[4], $vasgn[5], $vasgn[6], $vasgn[7]
: .
: It is deliberately longer then 80 character columns, but even when I resize my
: X11 windows the output is still wrapped to 80.
Did you check whether other programs are wrapping at 80 columns as well ?
Jason Gloudon
------------------------------
Date: Thu, 6 Nov 1997 17:07:48 -0800
From: Tom Phoenix <rootbeer@teleport.com>
To: schadsey@coralsys.com
Subject: Re: memory leak in POP3Client or something else?
Message-Id: <Pine.GSO.3.96.971106170509.7105R-100000@usertest.teleport.com>
On Wed, 5 Nov 1997 schadsey@coralsys.com wrote:
> Can someone help explain why the following program:
[snipped]
> adds about 4K to its main memory image size every 5-10 seconds?
> this is with perl version 5.003_02
I think that's the reason. A lot (a _lot_) of memory leaks were purged
from Perl between that version and when 5.004 was released. If you're
still seeing this problem once you have the latest version (5.004_04)
installed, check with the author of the module. Good luck!
--
Tom Phoenix http://www.teleport.com/~rootbeer/
rootbeer@teleport.com PGP Skribu al mi per Esperanto!
Randal Schwartz Case: http://www.rahul.net/jeffrey/ovs/
Ask me about Perl trainings!
------------------------------
Date: 7 Nov 1997 02:17:52 GMT
From: HDC <hdcclan@geocities.com>
Subject: Mirror
Message-Id: <63ttog$e96$1@gte2.gte.net>
Does anyone know or a perl program called mirror?
--
HDC
Hammy
hdcclan@geocities.com
http://www.geocities.com/TimesSquare/Castle/1936/index.html
Mike Hammett
MHamme@aol.com
Hammy1@juno.com
Hammy69@geocities.com
FHammett@gte.net
http://members.aol.com/mhamme/index.html
------------------------------
Date: Thu, 06 Nov 1997 21:53:31 -0500
From: comdog@computerdog.com (brian d foy)
Subject: Re: Mirror
Message-Id: <comdog-ya02408000R0611972153310001@news.panix.com>
In article <63ttog$e96$1@gte2.gte.net>, HDC <hdcclan@geocities.com> wrote:
>Does anyone know or a perl program called mirror?
um, yeah, but it probably doesn't do what you want. what does the
program that you want do?
--
brian d foy <comdog@computerdog.com>
NY.pm - New York Perl M((o|u)ngers|aniacs)* <URL:http://ny.pm.org/>
CGI Meta FAQ <URL:http://computerdog.com/CGI_MetaFAQ.html>
------------------------------
Date: 06 Nov 1997 19:03:29 -0500
From: Douglas McNaught <doug@tc.net>
Subject: Re: Puzzle: palindromep
Message-Id: <m2affhvacu.fsf@ono.tc.net>
ebohlman@netcom.com (Eric Bohlman) writes:
> Steven W McDougall (swmcd@world.std.com) wrote:
> : In general, recognizing palindromes requires a stack.
> : Therefore, it can't be done with a regular expression alone.
>
> Note that Perl "regular expressions" can include backreferences, which
> allows them to recognize some constructs that can't be recognized by pure
> regular expressions.
>
> ^(.+)\1$ matches any even-length palindrome and ^(.+).\1$ matches any
> odd-length palindrome, so ^(.+).?\1$ should match any palindrome, albeit
> rather slowly for large palindromes (since it will have to backtrack once
> for every two characters). Recognizing palindromes embedded in longer
> strings would be much harder.
"abcabc" is not a palindrome.
"abccba" is, but is not matched by your regex.
Steven is right; you need a stack.
-Doug
--
sub g{my$i=index$t,$_[0];($i%5,int$i/5)}sub h{substr$t,5*$_[1]+$_[0],1}sub n{(
$_[0]+4)%5}$t='encryptabdfghjklmoqsuvwxz';$c='fxmdwbcmagnyubnyquohyhny';while(
$c=~s/(.)(.)//){($w,$x)=g$1;($y,$z)=g$2;$w==$y&&($p.=h($w,n$x).h($y,n$z))or$x==
$z&&($p.=h(n$w,$x).h(n$y,$z))or($p.=h($y,$x).h($w,$z))}$p=~y/x/ /;print$p,"\n";
------------------------------
Date: Fri, 7 Nov 1997 00:10:38 GMT
From: ebohlman@netcom.com (Eric Bohlman)
Subject: Re: Puzzle: palindromep
Message-Id: <ebohlmanEJ91tq.Kwz@netcom.com>
Eric Bohlman (ebohlman@netcom.com) wrote:
: Note that Perl "regular expressions" can include backreferences, which
: allows them to recognize some constructs that can't be recognized by pure
: regular expressions.
The previous paragraph was not damaged by lack of caffeine.
: ^(.+)\1$ matches any even-length palindrome and ^(.+).\1$ matches any
: odd-length palindrome, so ^(.+).?\1$ should match any palindrome, albeit
: rather slowly for large palindromes (since it will have to backtrack once
: for every two characters). Recognizing palindromes embedded in longer
: strings would be much harder.
But this one was. While those expressions do indeed recognize
expressions that cannot be recognized by pure regular expressions, they
don't recognize palindromes. Of course ^(.+).?(?&reverse(\1))$ *would*
work if only the "?&" extension for embedding a match-time expression in
a regex were implemented...
Still, it can be done without an explicit stack:
sub is_palindrome($) {
my $s=shift;
my $i,$j;
for ($i=0,$j=length($s)-1; $i<$j; $i++,$j--) {
return 0 if substr($s,$i,1) ne substr($s,$j,1);
}
return 1;
}
or, since TMTOWTDI:
sub is_palindrome($) {
my $l=int(length($_[0])/2);
substr($_[0],0,$l) eq reverse substr($_[0],-1,$l);
}
though this one really uses an implicit stack (the buffer used by
reverse() to do its dirty work).
------------------------------
Date: 7 Nov 1997 01:24:17 GMT
From: mgjv@comdyn.com.au (Martien Verbruggen)
Subject: Re: Regular Expressions
Message-Id: <63tqk1$86t$1@comdyn.comdyn.com.au>
In article <comdog-ya02408000R0611971707560001@news.panix.com>,
comdog@computerdog.com (brian d foy) writes:
>>Trying to send an individuals name through a regular expression that
>>will make sure the first letter in the First Middle and Last name are
>>all upper case no matter how they were given.
>
> i hate this sort of data manipulation - it seems that a lot of systems
> do this - and i should know :)
Yeah,
what if your last name is McBeth, O'Donnell, or Lloyd Webber ?
M.
--
Martien Verbruggen |
Webmaster www.tradingpost.com.au | That's not a lie, it's a terminological
Commercial Dynamics Pty. Ltd. | inexactitude.
NSW, Australia |
------------------------------
Date: Thu, 06 Nov 1997 18:39:18 -0600
From: Tom Turton <turton@osprey.arc.nasa.gov>
Subject: rlogin from script
Message-Id: <34626336.2466@osprey.arc.nasa.gov>
I am trying to rlogin from one machine to another (same
account on both machines) in order to chmod a file which I
have already ftp'd over. I can't for the life of me figure
out how to do this.
Ideally, I'd like to use variables for:
the server, $server
the target directory, $tgt_dir
the filename, $filename
chmod options, $chmod_opts
I have tried various methods of putting these in strings
and running these through system( ); but to no avail.
Also, need to input a password to the rlogin string.
Sample which didn't work:
$mode_command = sprintf("chmod %s %s/%s\n",
$chmod_opts,$tgt_dir,$filename);
$rlogin_command = sprintf("rlogin %s <<[
passwd
%s exit [", $server, $mode_command);
system($rlogin_command);
Also tried:
$rlogin_command = <<[
rlogin $server
passwd
chmod $chmod_opts $tgt_dir/$filename
[
system($rlogin_command);
I'm sure there is a simple way to do this, but I am obviously
overlooking
it. I'd appreciate any tips.
---Tom Turton
------------------------------
Date: Thu, 06 Nov 1997 15:03:15 -0800
From: John Blattner <johnb@imagix.com>
Subject: Re: Seeking Year 2000 checker OR comment stripper for C/C++
Message-Id: <34624CB3.5B21@imagix.com>
Bob Weissman wrote:
>
> I'm looking for a perl script to inspect C and C++ code for suspicious
> constructs with respect to the Year 2000 Problem. Such a script should
> strip comments and then look for suspicious strings such as "19", "365",
> "getdate", "strptime", etc.
>
> If such a beast does not exist, I'd be happy with a script which simply
> removes all comments from C and C++ source, including multi-line
> comments. Then I could code the rest myself, but I'm not enough of a
> perl wiz to know how to strip multi-line comments. (Yes, I know the C
> preprocessor will strip comments, but it also does other nasty things
> like expand #include directives, which I don't want to do.)
One tool I'd suggest you take a look at (partly because we make it,
partly because it's a good tool) is Imagix 2000. Rather than simply
look for strings in code, it does a full semantic parsing of the code,
so the searches are done on the symbols actual names. After identifying
suspect symbols, it then helps you understand where and how they're
used.
There's more info at http://www.imagix.com
John
--
--------------------------------------------------------
John Blattner
Imagix Corporation tel: 1.805.781.6002
6025 White Oak Lane fax: 1.805.781.6003
San Luis Obispo, CA 93401 email: johnb@imagix.com
------------------------------
Date: 7 Nov 1997 00:13:23 GMT
From: twod@not.valid
Subject: Re: Self-Modifying Perl Scripts
Message-Id: <63tmf3$bmi$1@vnetnews.value.net>
Dan Zink (zink@uiuc.edu) wrote:
: Is it possible to write a perl script that modifies itself? I tried to do
: this, but was unable to open the script file for write access while it was
: running. Is there any way to get around this?
Do you have write permission on the script and are you running under an
OS that allows you to write whilst the script is being run ?
This script works just fine on a Unix platform - the value of $val is bumped
by 1 after every run :
-- snip --
#!/opt/gnu/bin/perl
$val=1;
print "VAL = $val\n";
open(FILE, ${0}) || die;
@data = <FILE>;
close(FILE) || die;
open(FILE, ">${0}") || die;
foreach (@data)
{
if (/^\$val=/)
{
print FILE '$val=' . ++$val . ";\n";
}
else
{
print FILE;
}
}
close(FILE);
-- snip --
IAP
--
In an attempt to reduce junk email I use an invalid 'From' address.
My correct email address can be determined by replacing 'not.valid' with
'value.net'
------------------------------
Date: 7 Nov 1997 02:45:39 GMT
From: Tony Nugent <T.Nugent@sct.gu.edu.au>
Subject: Tricky problem... how to use open3() in "open3.pl" ??
Message-Id: <63tvcj$nbr$1@griffin.itc.gu.edu.au>
Keywords: perl cgi html
[Also posted into comp.infosystems.www.authoring.cgi]
[Any reply Cc'ed to my mailbox would be appreciated.]
In case it matters:
linux 2.0.30 (elf), perl5.003
Solaris 2.4/2.5, perl5.004
I've got a problem that I need to solve (not an assignment, but "for
real":). While I'm fluent in things like C/shell/awk/sed scripts, I'm
fairly new to perl (several months) so I'm still on a learning curve.
I've read the man pages, checked out what text books I could find,
some online tutorials and a bunch of perl scripts, with only a few
clues on how to solve this.
The problem seems simple...
I'm writing a series of perl CGI scripts that generate html/cgi forms
to act as a front-end user interface to a series of filter-like
programs (ie, take data and transform it into something else).
I have the cgi scripts themselves up and running, no problems. I'm
using the CGI.pm module to do much of the grunt work with handling the
form generation and cgi/environment parsing, and it is all working
well in this respect.
However, what I'm wanting to do is to run the actual filter programs
within the perl scripts so that:
- data from an array is fed (piped) into the program's standard input
to invoke it,
- whatever is issued from the program's standard output AND standard
error is captured by the calling perl script into two separate
arrays, along with the exit status into another variable.
So I have:
1. a program, say $FILTER, with a command line array in @OPTIONS.
2. an array variable, @DATA, that contains the data that needs to be
feed into the stdin of $FILTER.
I want to run the program and end up with two more arrays:
a. @RESULT - contains the data from $FILTER's stdout that is the result of
processing @DATA, and
b. @ERRORS - contains anything that was issued from $FILTER's stderr.
c. $STATUS - the exit code status of the program.
Surely perl is capable of solving this problem - and I'm sure that
others have done it before.
I need to directly open three file handles to that program (stdin,
stdout, stderr), as well as run the program itself and collect its
exit code.
I'm able to get part way and get @RESULT from running the filter
program like this, after @DATA has been written to a $TMPFILE...
open (FILE, "$FILTER @OPTIONS < $TMPFILE |") || die "Cannot run $FILTER\n";
This only gives me the stdout, not stderr or the exit status of the
program (or is that the return value of the open() function?) It also
gives me the added headache of a tmp file to get rid of after it's all
done.
This is a cgi program that I'm dealing with, and it would seem much
more secure if no file writing was done *at* *all*. Besides, I very
strongly suspect that using `open' like that implies use of /bin/sh,
and that is also something else to avoid (for security reasons, even
if $TMPFILE is set by the script, not via form variables).
As it is, anything issued to stderr is "missed" by the script, but it
does find its way into the httpd daemon's error logfile - yet another
thing I want to avoid :)
After fishing around, /usr/lib/perl5/open3.pl seems to offer something
promising along these lines. However, how do you use the open3()
function that it contains? This is the extent of the documentation in
that file (slightly reformatted)...
========8<--cut------------------------
# usage: $pid = open3('wtr', 'rdr', 'err' 'some cmd and args', 'optarg', ...);
#
# spawn the given $cmd and connect:
# rdr for reading,
# wtr for writing, and
# err for errors.
#
# if err is '', or the same as rdr, then
# stdout and stderr of the child are on the same fh.
# returns pid of child, or 0 on failure.
# if wtr begins with '>&', then
# wtr will be closed in the parent, and
# the child will read from it directly.
# if rdr or err begins with '>&', then
# the child will send output directly to that fd.
# In both cases, there will be a dup() instead of a pipe() made.
# WARNING: this is dangerous, as you may block forever unless you are
# very careful.
#
# $wtr is left unbuffered.
#
# abort program if
# rdr or wtr are null
# pipe or fork or exec fails
========8<--cut------------------------
`perldoc open3' isn't much more informative:
SYNOPSIS
$pid = open3(\*WTRFH, \*RDRFH, \*ERRFH
'some cmd and args', 'optarg', ...);
[It goes on to mention potential "blocking" problems (which I'm sure
that I'll be able to avoid) and reference to the perl2 page.]
========8<--cut------------------------
So exactly how do you use this function?
>From what I can make of it, the open3() opens AND closes the files,
after running the program, doing the writing to stdin and reading from
stdout and stderr as well, all in one hit.
# usage: $pid = open3('wtr', 'rdr', 'err' 'some cmd and args', 'optarg', ...);
And exactly what is `wtr' ($wtr), `rdr' ($rdr) and `err' ($err)? From
what I can make of it, they look like they should be FILEHANDLES, but
the perldoc page implies pointers? (Pointers to what?)
How do you "initialise" these variables (making sure that rdr and wtr
are NOT null), and then use them to access the generated output?
And what about the "<&" and ">&" syntax... will doing this help?
Ok, so we're given back the PID of the child process... how does this
help? Is this what you use to "get a handle" on the output? If so, how?
I'd be most grateful for any help with this, thanks.
BTW, there's a (very minor) typo in open3.pl....
if (($kidpid = fork) < 0) {
die "open2: fork failed: $!";
Of course, that should read "open3:", not "open2:".
Cheers .
Tony _--_|\
tony@trishul.sci.gu.edu.au / *\ T.Nugent@sct.gu.edu.au
ae.nugent@student.qut.edu.au\_.--._/ tnugent@cit.gu.edu.au
tony@sctnugen.ppp.gu.edu.au v Brisbane Qld Australia
-=*#*=-=*#*=-=*#*=-=*#*=-=*#*=-=*#*=-=*#*=-=*#*=-=*#*=-=*#*=-
========8<----cut------------------------------------------------------------
Below here are two small programs I've been using to test this...
1. open3test
- a perl script to experiment with open3()
2. rotate13.c
- a small C program for open3test to use
(an implementation of rot13)
- perhaps I should have use perl for the test program :)
(Has anyone got a perl implementation of rot13? :-)
========8<----insert-crowbar-here------------------------------
#!/usr/local/bin/perl
# open3test
#
# a quick'n'dirty hack to experiment with the open3() function.
#
# Tony Nugent <T.Nugent@sct.gu.edu.au>
# November 1997
#
require "open3.pl";
#
# Use any program will take from stdin and give to both stdout and stderr
$PROG = 'rotate13';
@OPTS = ('-v'); # produces output to stdout AND stderr
#
$DATAFILE = "/etc/hosts"; # any file that's "public" and available
open (INFILE, $DATAFILE);
@DATA = <INFILE>; # just gets some data into @DATA
close (INFILE);
#
# usage: $pid = open3('wtr', 'rdr', 'err' 'some cmd and args', 'optarg', ...);
# Note that if rdr or wtr are "null" THEN IT WILL DIE.
# So how do you set this up?
#
# This is ** NOT ** the way to do it:
$pid = open3(@INSEQ, RESULT, ERRORS, $PROG, @OPTS);
#
# After doing the "right thing" with that call, we need to
# - put stdout into @RESULT,
# - put stderr into @ERRORS, and
# - have the exit status of the program in $STATUS.
#
# So now we print the results:
#
print "\npid is $pid\n";
#
print "DATA\n\n";
#print @DATA;
foreach $key (@DATA) { print ".data.\t$key"; }
#
print "\nRESULT\n\n";
#print @RESULT;
foreach $key (@RESULT) { print ".result.\t$key"; }
#
print "ERRORS\n\n";
#print @ERRORS;
foreach $key (@ERRORS) { print ".errors.\t$key"; }
#
# end
========8<----insert-crowbar-here------------------------------
/*
* rotate13.c
*
* An inplementation of rot13
* Hacked to force output to stderr with `-v'
*/
#include <stdio.h>
/*const char ver[] = "Ver0.1 Sep95";*/
const char ver[] = "Ver0.1 Sep95 with -v hack, Oct97";
void whatami (char * progname) {
fprintf (stderr, "%s\n%s\n%s%s%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n",
progname, ver, "Usage:\t", progname, " [infile [outfile]]",
"** Rotate or de-rotate a file (or standard input) **",
"* This is an implementation of a simple encryption scheme *",
"* that involves rotating a character to the one 13th away *",
"* from it in the alphabet. Decryption is also simple - *",
"* repeat the rotation to recover the original text. *");
/* exit (1); */
}
void usage (char * progname) {
fprintf (stderr, "%s\tUsage:\t%s [infile [outfile]]\n%s\n", progname, ver);
fprintf (stderr, "\t%s [-h|--help] gives a help screen\n", progname);
exit(1);
}
int rotate (int conv) {
if ((conv>='A' && conv<='M') || (conv>='a' && conv<='m')) conv=conv+13;
else if ((conv>='N' && conv<='Z') || (conv>='n' && conv<='z')) conv=conv-13;
return conv;
}
int main (int argc, char *argv[]) {
char conv;
int argno = 1; /* hack */
FILE *infile = stdin, *outfile = stdout;
if (argc>3) usage (argv[0]);
if (argc>1) {
if (!strncmp (argv[argno],"-v",2)) { whatami (argv[0]); argno++; }
if (argv[argno]) {
if ((!strncmp (argv[argno],"-h",2)) || (!strncmp(argv[argno],"--help",6))) {
whatami (argv[0]);
exit (1);
}
if (argv[argno]) {
if (!(infile=fopen (argv[argno],"r"))) {
fprintf (stderr, "Cannot open %s for reading\n",argv[1]);
usage (argv[0]);
}
}
if (argv[++argno]) {
if (!(outfile=fopen (argv[argno],"w"))) {
fprintf (stderr, "Cannot open %s for writing\n",argv[1]);
usage(argv[0]);
}
}
}
}
while ((conv=fgetc (infile))!=EOF) putc (rotate (conv),outfile);
exit(0);
}
------------------------------
Date: Thu, 6 Nov 1997 16:23:59 -0500
From: phenix@interpath.com (John Moreno)
Subject: Re: unset an array
Message-Id: <19971106145422316202020N@roxboro-173.interpath.net>
Justin Wills <justin@nectar.com.au> wrote:
-snip html crap -
Please, fix you "newsreader" so that it's not spewing out htlm junk.
ps - It's even more annoying than usual (which is only barely possible)
when you apparently reply without including any new text.
--
John Moreno
------------------------------
Date: 8 Mar 97 21:33:47 GMT (Last modified)
From: Perl-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin)
Subject: Digest Administrivia (Last modified: 8 Mar 97)
Message-Id: <null>
Administrivia:
The Perl-Users Digest is a retransmission of the USENET newsgroup
comp.lang.perl.misc. For subscription or unsubscription requests, send
the single line:
subscribe perl-users
or:
unsubscribe perl-users
to almanac@ruby.oce.orst.edu.
To submit articles to comp.lang.perl.misc (and this Digest), send your
article to perl-users@ruby.oce.orst.edu.
To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.
To request back copies (available for a week or so), send your request
to almanac@ruby.oce.orst.edu with the command "send perl-users x.y",
where x is the volume number and y is the issue number.
The Meta-FAQ, an article containing information about the FAQ, is
available by requesting "send perl-users meta-faq". The real FAQ, as it
appeared last in the newsgroup, can be retrieved with the request "send
perl-users FAQ". Due to their sizes, neither the Meta-FAQ nor the FAQ
are included in the digest.
The "mini-FAQ", which is an updated version of the Meta-FAQ, is
available by requesting "send perl-users mini-faq". It appears twice
weekly in the group, but is not distributed in the digest.
For other requests pertaining to the digest, send mail to
perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
sending perl questions to the -request address, I don't have time to
answer them even if I did know the answer.
------------------------------
End of Perl-Users Digest V8 Issue 1283
**************************************