develooper Front page | perl.perl5.porters | Postings from January 2003

<> magic, open.pm, binmode

Thread Next
From:
Tye McQueen
Date:
January 30, 2003 16:08
Subject:
<> magic, open.pm, binmode
Message ID:
200301310011.h0V0B9r25010@metronet.com
1) I wanted to write a patch so I went to grab the latest
development release of Perl and got a 404 from

    http://www.cpan.org/src/devel.tar.gz

and found that

    http://www.cpan.org/src/5.0/devel/

didn't contain new stuff so I'm not sure if

    http://www.cpan.org/src/README.html

needs to be updated to reflect the new method for gettting a Perl
to patch or this is just a temporary situation.


2) In figuring out why my patch wasn't working I stumbled across
this lovely trick:

    % perl -ne 0 *
    % echo foo >"echo Perl is my bitch >&2 |"
    % perl -ne 0 *
    Perl is my bitch
    %

which is a nice little security hole.  Based on a search of the
p5p archive it appears that work is already underway to fix this.

If not, a big improvment could be had easily by reusing (and
improving) a trick from the -i code that opens the output files:

	sv_setpvn(sv,"< ",2*(!PL_inplace));
	sv_catpvn(sv,PL_oldname,oldlen);
	sv_catpvn(sv,"\0",!PL_inplace);


3) Attached is the current state of my patch.

It is meant to fix open.pm so that it works on files opened
by <> (the whole *ARGV magic stuff) so you can, for example,
write a filter for binary data simply with

    #!/usr/bin/perl -pi.sav
    use open IN=>":raw", OUT=>":raw";
    BEGIN { $/= \4096 }
    ...

The patch succeeds in this goal except for when -i is used.
This is because -i causes as_raw==1 in openn() which bypasses
the checking for open.pm hints.

Thus the fix for (2) will likely make my patch not work in
any situations.  Since I got the impression that someone was
already working on this, I figured this was a good point to
stop and check in for which direction to go next.

Some possible solutions:

    A)  Fix (2) by using the "> $file\0" trick instead of
	as_raw==1 and handle -i (PL_inplace) that way as well.

    B)  Extend as_raw so as_raw==-1 [or as_raw==2 or an additional
	parameter to openn()] means to use rawmode [like
	sysopen()] but also to pay attention to open.pm hints.

Advice appreciated.

Thanks,
Tye

diff -r -C3 perl-5.8.0/doio.c perl-5.8.0tye/doio.c
*** perl-5.8.0/doio.c	Thu Jan 30 17:39:07 2003
--- perl-5.8.0tye/doio.c	Thu Jan 30 18:07:53 2003
***************
*** 92,98 ****
      PL_forkprocess = 1;		/* assume true if no fork */
  
      /* Collect default raw/crlf info from the op */
!     if (PL_op && PL_op->op_type == OP_OPEN) {
  	/* set up disciplines */
  	U8 flags = PL_op->op_private;
  	in_raw = (flags & OPpOPEN_IN_RAW);
--- 92,100 ----
      PL_forkprocess = 1;		/* assume true if no fork */
  
      /* Collect default raw/crlf info from the op */
!     if (PL_op && ( PL_op->op_type == OP_OPEN
!                 || PL_op->op_type == OP_BACKTICK
!                 || PL_op->op_type == OP_READLINE )) {
  	/* set up disciplines */
  	U8 flags = PL_op->op_private;
  	in_raw = (flags & OPpOPEN_IN_RAW);
diff -r -C3 perl-5.8.0/op.c perl-5.8.0tye/op.c
*** perl-5.8.0/op.c	Thu Jan 30 17:39:53 2003
--- perl-5.8.0tye/op.c	Thu Jan 30 17:52:42 2003
***************
*** 6382,6388 ****
  		o->op_private |= OPpOPEN_OUT_CRLF;
  	}
      }
!     if (o->op_type == OP_BACKTICK)
  	return o;
      return ck_fun(o);
  }
--- 6382,6388 ----
  		o->op_private |= OPpOPEN_OUT_CRLF;
  	}
      }
!     if (o->op_type != OP_OPEN)
  	return o;
      return ck_fun(o);
  }
diff -r -C3 perl-5.8.0/op.h perl-5.8.0tye/op.h
*** perl-5.8.0/op.h	Thu Jan 30 17:42:58 2003
--- perl-5.8.0tye/op.h	Thu Jan 30 17:54:42 2003
***************
*** 202,208 ****
  /* Private for OP_THREADSV */
  #define OPpDONE_SVREF		64	/* Been through newSVREF once */
  
! /* Private for OP_OPEN and OP_BACKTICK */
  #define OPpOPEN_IN_RAW		16	/* binmode(F,":raw") on input fh */
  #define OPpOPEN_IN_CRLF		32	/* binmode(F,":crlf") on input fh */
  #define OPpOPEN_OUT_RAW		64	/* binmode(F,":raw") on output fh */
--- 202,208 ----
  /* Private for OP_THREADSV */
  #define OPpDONE_SVREF		64	/* Been through newSVREF once */
  
! /* Private for OP_OPEN, OP_BACKTICK, and OP_READLINE */
  #define OPpOPEN_IN_RAW		16	/* binmode(F,":raw") on input fh */
  #define OPpOPEN_IN_CRLF		32	/* binmode(F,":crlf") on input fh */
  #define OPpOPEN_OUT_RAW		64	/* binmode(F,":raw") on output fh */
Only in perl-5.8.0tye: opcode.h
diff -r -C3 perl-5.8.0/opcode.pl perl-5.8.0tye/opcode.pl
*** perl-5.8.0/opcode.pl	Thu Jan 30 17:44:52 2003
--- perl-5.8.0tye/opcode.pl	Thu Jan 30 17:55:10 2003
***************
*** 480,486 ****
  backtick	quoted execution (``, qx)	ck_open		t%	
  # glob defaults its first arg to $_
  glob		glob			ck_glob		t@	S?
! readline	<HANDLE>		ck_null		t%	F?
  rcatline	append I/O operator	ck_null		t$
  
  # Bindable operators.
--- 480,486 ----
  backtick	quoted execution (``, qx)	ck_open		t%	
  # glob defaults its first arg to $_
  glob		glob			ck_glob		t@	S?
! readline	<HANDLE>		ck_open		t%	F?
  rcatline	append I/O operator	ck_null		t$
  
  # Bindable operators.

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About