Why is this legacy code using cat in the filename in the open () call?
I ran into a very strange line of code in a legacy Perl application. The code here is part of a built-in RSS reader that does some caching to prevent blacklisting.
open(CAT, "/usr/bin/cat -v /tmp/cat-cache 2>&1|");
Is it possible that the original author followed the results with cat -v
to strip non-printable characters to handle any number of character sets? Doesn't it make sense to use a regular expression in Perl? Also, the pipe at the end puzzles me the most.
a source to share
Functionally
this code will do something similar to this:
open my $fh, '<' , '/tmp/cat-cache' or Carp::croak("Cant open file $@ $! ");
sub lessquote {
my $x = shift;
my $meta = shift; # meta means were repeating thise code for >128
# Special Case for whitespace
if(( not defined $meta ) && ( $x == 9 or $x == 10 ) ){
return chr($x);
}
# Null and M-^@
if( $x == 0 ){
return "^@";
}
# ^A to ^Z as well as M-^A to M-^Z
if( ( 0 <= $x ) && ( $x <= 31 )){
return "^" . chr( $x + ord('A') - 1 );
}
# Also M-^?
if( $x == 127 ){
return "^?";
}
# Does the M- Family
if( $x >= 128 && $x <= 255 ){
return "M-" . lessquote( $x - 128 , 1);
}
return chr( $x );
}
while( my $line = <$fh> ){
$line =~ s{(.)}{ lessquote( ord( $1 ) ) }eg;
}
Not identical, but similar.
NB: lessquote seems to match my cat -v output.
But as you can see, the same case is a little less than trivial and not suitable for regex, but still I don't understand why they fired at the "cat".
As for their style
They get around badly, the code style is 1990 and should be avoided.
open my $fh , '-|' , 'cat' , '-v' , '/tmp/cat-cache' or Carp::croak("Cant open file $@ $! ");
Syntax:
open my $ FILEHANDLE, $ OPENMODE, $ FILENAME || Carp :: croak ($ ERRORMESSAGE) open my $ FILEHANDLE, $ OPENMODE, $ SHELLCOMMAND || Carp :: croak ($ ERRORMESSAGE) open my $ FILEHANDLE, $ OPENMODE, $ SHELLPROGRAM, @ARGS || Carp :: croak ($ ERRORMESSAGE)
Is the "preferred" designation these days for a variety of reasons. Of course, you wouldn't REALLY want to use a cat, but I left it here for a clear example.
a source to share
You can take a look at the perl open tutorial .
Basically, the pipe at the end of the "filename", passed to open, calls the program named as the executable and the output received in perl. Likewise, you can use a pipe at the beginning of a "filename" to output the output to an external program.
It might make sense to do it inside the perl program itself, but the cited code is more compatible with two of the three main strengths of the Perl programmer .
a source to share
The original author was confused at some point or had a setuid cat :)
Some confusion about what "cat -v" does ...
-v, --show-nonprinting
use ^ and M- notation, except for LFD and TAB
... its not like "strings" (strings - print strings of printable characters in files) ...
$ strings /bin/rm | head
/lib/ld-linux.so.2
e="?
__gmon_start__
libc.so.6
_IO_stdin_used
fflush
setlocale
mbrtowc
strncmp
optind
a source to share