stas 2003/08/20 16:20:14
Modified: src/modules/perl mod_perl.c mod_perl.h modperl_io.c
modperl_io.h
lib/ModPerl Code.pm
xs/tables/current/ModPerl FunctionTable.pm
. Changes
Added: src/modules/perl modperl_io_apache.c modperl_io_apache.h
t/modperl print_utf8.t
t/response/TestModperl print_utf8.pm
Log:
when perl is built with perlio enabled (5.8+) the new PerlIO Apache
layer is used, so now one can push layers onto STDIN, STDOUT handles
e.g. binmode(STDOUT, ':utf8');
Revision Changes Path
1.179 +7 -5 modperl-2.0/src/modules/perl/mod_perl.c
Index: mod_perl.c
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/mod_perl.c,v
retrieving revision 1.178
retrieving revision 1.179
diff -u -r1.178 -r1.179
--- mod_perl.c 19 Aug 2003 05:01:22 -0000 1.178
+++ mod_perl.c 20 Aug 2003 23:20:14 -0000 1.179
@@ -238,6 +238,8 @@
modperl_hash_seed_set(aTHX);
+ modperl_io_apache_init(aTHX);
+
PL_perl_destruct_level = 2;
MP_boot_data_set(p, s);
@@ -909,19 +911,19 @@
modperl_global_request_set(r);
}
- h_stdout = modperl_io_tie_stdout(aTHX_ r);
- h_stdin = modperl_io_tie_stdin(aTHX_ r);
+ h_stdin = modperl_io_override_stdin(aTHX_ r);
+ h_stdout = modperl_io_override_stdout(aTHX_ r);
modperl_env_request_tie(aTHX_ r);
retval = modperl_response_handler_run(r, FALSE);
- modperl_io_handle_untie(aTHX_ h_stdout);
- modperl_io_handle_untie(aTHX_ h_stdin);
-
modperl_env_request_untie(aTHX_ r);
modperl_perl_global_request_restore(aTHX_ r);
+
+ modperl_io_restore_stdin(aTHX_ h_stdin);
+ modperl_io_restore_stdout(aTHX_ h_stdout);
#ifdef USE_ITHREADS
if (MpInterpPUTBACK(interp)) {
1.60 +1 -0 modperl-2.0/src/modules/perl/mod_perl.h
Index: mod_perl.h
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/mod_perl.h,v
retrieving revision 1.59
retrieving revision 1.60
diff -u -r1.59 -r1.60
--- mod_perl.h 24 Apr 2003 01:51:37 -0000 1.59
+++ mod_perl.h 20 Aug 2003 23:20:14 -0000 1.60
@@ -59,6 +59,7 @@
#include "modperl_options.h"
#include "modperl_directives.h"
#include "modperl_io.h"
+#include "modperl_io_apache.h"
#include "modperl_filter.h"
#include "modperl_bucket.h"
#include "modperl_pcw.h"
1.10 +154 -40 modperl-2.0/src/modules/perl/modperl_io.c
Index: modperl_io.c
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_io.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- modperl_io.c 22 Jan 2003 03:19:43 -0000 1.9
+++ modperl_io.c 20 Aug 2003 23:20:14 -0000 1.10
@@ -6,22 +6,6 @@
#define TIED(handle) \
modperl_io_handle_tied(aTHX_ handle, "Apache::RequestRec")
-MP_INLINE void modperl_io_handle_untie(pTHX_ GV *handle)
-{
-#ifdef MP_TRACE
- if (mg_find(TIEHANDLE_SV(handle), 'q')) {
- MP_TRACE_g(MP_FUNC, "untie *%s(0x%lx), REFCNT=%d\n",
- GvNAME(handle), (unsigned long)handle,
- SvREFCNT(TIEHANDLE_SV(handle)));
- }
- else {
- return;
- }
-#endif
-
- sv_unmagic(TIEHANDLE_SV(handle), 'q');
-}
-
MP_INLINE void modperl_io_handle_tie(pTHX_ GV *handle,
char *classname, void *ptr)
{
@@ -38,29 +22,27 @@
SvREFCNT(TIEHANDLE_SV(handle)));
}
-MP_INLINE int modperl_io_handle_tied(pTHX_ GV *handle, char *classname)
+MP_INLINE GV *modperl_io_tie_stdin(pTHX_ request_rec *r)
{
- MAGIC *mg;
- SV *sv = TIEHANDLE_SV(handle);
-
- if (SvMAGICAL(sv) && (mg = mg_find(sv, 'q'))) {
- char *package = HvNAME(SvSTASH((SV*)SvRV(mg->mg_obj)));
+#if defined(MP_IO_TIE_SFIO)
+ /* XXX */
+#else
+ dHANDLE("STDIN");
- if (!strEQ(package, classname)) {
- MP_TRACE_g(MP_FUNC, "%s tied to %s\n", GvNAME(handle), package);
- return TRUE;
- }
+ if (TIED(handle)) {
+ return handle;
}
- return FALSE;
+ TIEHANDLE(handle, r);
+
+ return handle;
+#endif
}
MP_INLINE GV *modperl_io_tie_stdout(pTHX_ request_rec *r)
{
#if defined(MP_IO_TIE_SFIO)
/* XXX */
-#elif defined(MP_IO_TIE_PERLIO)
- /* XXX */
#else
dHANDLE("STDOUT");
@@ -76,21 +58,153 @@
#endif
}
-MP_INLINE GV *modperl_io_tie_stdin(pTHX_ request_rec *r)
+MP_INLINE int modperl_io_handle_tied(pTHX_ GV *handle, char *classname)
{
-#if defined(MP_IO_TIE_SFIO)
- /* XXX */
-#elif defined(MP_IO_TIE_PERLIO)
- /* XXX */
-#else
- dHANDLE("STDIN");
+ MAGIC *mg;
+ SV *sv = TIEHANDLE_SV(handle);
- if (TIED(handle)) {
- return handle;
+ if (SvMAGICAL(sv) && (mg = mg_find(sv, 'q'))) {
+ char *package = HvNAME(SvSTASH((SV*)SvRV(mg->mg_obj)));
+
+ if (!strEQ(package, classname)) {
+ MP_TRACE_g(MP_FUNC, "%s tied to %s\n", GvNAME(handle), package);
+ return TRUE;
+ }
}
- TIEHANDLE(handle, r);
+ return FALSE;
+}
- return handle;
+MP_INLINE void modperl_io_handle_untie(pTHX_ GV *handle)
+{
+#ifdef MP_TRACE
+ if (mg_find(TIEHANDLE_SV(handle), 'q')) {
+ MP_TRACE_g(MP_FUNC, "untie *%s(0x%lx), REFCNT=%d\n",
+ GvNAME(handle), (unsigned long)handle,
+ SvREFCNT(TIEHANDLE_SV(handle)));
+ }
#endif
+
+ sv_unmagic(TIEHANDLE_SV(handle), 'q');
+}
+
+MP_INLINE GV *modperl_io_perlio_override_stdin(pTHX_ request_rec *r)
+{
+ dHANDLE("STDIN");
+ int status;
+ GV *handle_save = gv_fetchpv("STDIN_SAVED", TRUE, SVt_PVIO);
+ SV *sv = sv_newmortal();
+
+ sv_setref_pv(sv, "Apache::RequestRec", (void*)r);
+ MP_TRACE_o(MP_FUNC, "start");
+
+ /* open my $oldout, ">&STDIN" or die "Can't dup STDIN: $!"; */
+ status = Perl_do_open(aTHX_ handle_save, ">&STDIN", 8, FALSE, O_RDONLY,
+ 0, Nullfp);
+ if (status == 0) {
+ STRLEN n_a;
+ Perl_croak(aTHX_ "Failed to dup STDIN: %s",
+ SvTRUE(ERRSV) ? SvPV(ERRSV, n_a) : "unknown error");
+ }
+
+ /* similar to PerlIO::scalar, the PerlIO::Apache layer doesn't
+ * have file descriptors, so STDOUT must be closed before it can
+ * be reopened */
+ Perl_do_close(aTHX_ handle, TRUE);
+ status = Perl_do_open9(aTHX_ handle, "<:Apache", 8, FALSE, O_RDONLY,
+ 0, Nullfp, sv, 1);
+ if (status == 0) {
+ STRLEN n_a;
+ Perl_croak(aTHX_ "Failed to open STDIN: %s",
+ SvTRUE(ERRSV) ? SvPV(ERRSV, n_a) : "unknown error");
+ }
+
+ MP_TRACE_o(MP_FUNC, "end\n");
+
+ return handle_save;
+}
+
+/* XXX: refactor to merge with the previous function */
+MP_INLINE GV *modperl_io_perlio_override_stdout(pTHX_ request_rec *r)
+{
+ dHANDLE("STDOUT");
+ int status;
+ GV *handle_save = gv_fetchpv("STDOUT_SAVED", TRUE, SVt_PVIO);
+ SV *sv = sv_newmortal();
+
+ MP_TRACE_o(MP_FUNC, "start");
+
+ sv_setref_pv(sv, "Apache::RequestRec", (void*)r);
+
+ /* open my $oldout, ">&STDOUT" or die "Can't dup STDOUT: $!"; */
+ status = Perl_do_open(aTHX_ handle_save, ">&STDOUT", 8, FALSE, O_RDONLY,
+ 0, Nullfp);
+ if (status == 0) {
+ STRLEN n_a;
+ Perl_croak(aTHX_ "Failed to dup STDOUT: %s",
+ SvTRUE(ERRSV) ? SvPV(ERRSV, n_a) : "unknown error");
+ }
+
+ /* similar to PerlIO::scalar, the PerlIO::Apache layer doesn't
+ * have file descriptors, so STDOUT must be closed before it can
+ * be reopened */
+ Perl_do_close(aTHX_ handle, TRUE);
+ status = Perl_do_open9(aTHX_ handle, ">:Apache", 8, FALSE, O_RDONLY,
+ 0, Nullfp, sv, 1);
+ if (status == 0) {
+ STRLEN n_a;
+ Perl_croak(aTHX_ "Failed to open STDOUT: %s",
+ SvTRUE(ERRSV) ? SvPV(ERRSV, n_a) : "unknown error");
+ }
+
+ MP_TRACE_o(MP_FUNC, "end\n");
+
+ IoFLUSH_off(handle); /* STDOUT's $|=0 */
+
+ return handle_save;
+
+}
+
+MP_INLINE void modperl_io_perlio_restore_stdin(pTHX_ GV *handle)
+{
+ GV *handle_orig = gv_fetchpv("STDIN", FALSE, SVt_PVIO);
+ int status;
+
+ MP_TRACE_o(MP_FUNC, "start");
+
+ /* Perl_do_close(aTHX_ handle_orig, FALSE); */
+
+ /* open STDIN, ">&STDIN_SAVED" or die "Can't dup STDIN_SAVED: $!"; */
+ status = Perl_do_open9(aTHX_ handle_orig, "<&", 2, FALSE, O_RDONLY,
+ 0, Nullfp, (SV*)handle, 1);
+ if (status == 0) {
+ STRLEN n_a;
+ Perl_croak(aTHX_ "Failed to restore STDIN: %s",
+ SvTRUE(ERRSV) ? SvPV(ERRSV, n_a) : "unknown error");
+ }
+
+ IoFLUSH_off(handle); /* STDIN's $|=0 */
+
+ MP_TRACE_o(MP_FUNC, "end\n");
+}
+
+MP_INLINE void modperl_io_perlio_restore_stdout(pTHX_ GV *handle)
+{
+ GV *handle_orig = gv_fetchpv("STDOUT", FALSE, SVt_PVIO);
+ int status;
+
+ MP_TRACE_o(MP_FUNC, "start");
+
+ /* Perl_do_close(aTHX_ handle_orig, FALSE); */
+
+ /* open STDOUT, ">&STDOUT_SAVED" or die "Can't dup STDOUT_SAVED: $!"; */
+ status = Perl_do_open9(aTHX_ handle_orig, ">&", 2, FALSE, O_RDONLY,
+ 0, Nullfp, (SV*)handle, 1);
+ if (status == 0) {
+ STRLEN n_a;
+ Perl_croak(aTHX_ "Failed to restore STDOUT: %s",
+ SvTRUE(ERRSV) ? SvPV(ERRSV, n_a) : "unknown error");
+ }
+
+ MP_TRACE_o(MP_FUNC, "end\n");
}
1.3 +28 -4 modperl-2.0/src/modules/perl/modperl_io.h
Index: modperl_io.h
===================================================================
RCS file: /home/cvs/modperl-2.0/src/modules/perl/modperl_io.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- modperl_io.h 22 Jan 2003 03:19:43 -0000 1.2
+++ modperl_io.h 20 Aug 2003 23:20:14 -0000 1.3
@@ -1,6 +1,8 @@
#ifndef MODPERL_IO_H
#define MODPERL_IO_H
+#include "modperl_io_apache.h"
+
/*
* bleedperl change #11639 switch tied handle magic
* from living in the gv to the GvIOp(gv), so we have to deal
@@ -23,15 +25,37 @@
#define IoFLUSH(gv) \
(IoFLAGS(GvIOp((gv))) & IOf_FLUSH)
-MP_INLINE void modperl_io_handle_untie(pTHX_ GV *handle);
-
MP_INLINE void modperl_io_handle_tie(pTHX_ GV *handle,
char *classname, void *ptr);
+MP_INLINE GV *modperl_io_tie_stdout(pTHX_ request_rec *r);
+
+MP_INLINE GV *modperl_io_tie_stdin(pTHX_ request_rec *r);
MP_INLINE int modperl_io_handle_tied(pTHX_ GV *handle, char *classname);
-MP_INLINE GV *modperl_io_tie_stdout(pTHX_ request_rec *r);
+MP_INLINE void modperl_io_handle_untie(pTHX_ GV *handle);
+
+MP_INLINE GV *modperl_io_perlio_override_stdin(pTHX_ request_rec *r);
+
+MP_INLINE GV *modperl_io_perlio_override_stdout(pTHX_ request_rec *r);
+
+MP_INLINE void modperl_io_perlio_restore_stdin(pTHX_ GV *handle);
+
+MP_INLINE void modperl_io_perlio_restore_stdout(pTHX_ GV *handle);
+
+#if defined(MP_IO_TIE_SFIO)
+ /* XXX */
+#elif defined(MP_IO_TIE_PERLIO)
+#define modperl_io_override_stdin modperl_io_perlio_override_stdin
+#define modperl_io_override_stdout modperl_io_perlio_override_stdout
+#define modperl_io_restore_stdin modperl_io_perlio_restore_stdin
+#define modperl_io_restore_stdout modperl_io_perlio_restore_stdout
+#else
+#define modperl_io_override_stdin modperl_io_tie_stdin
+#define modperl_io_override_stdout modperl_io_tie_stdout
+#define modperl_io_restore_stdin modperl_io_handle_untie
+#define modperl_io_restore_stdout modperl_io_handle_untie
+#endif
-MP_INLINE GV *modperl_io_tie_stdin(pTHX_ request_rec *r);
#endif /* MODPERL_IO_H */
1.1 modperl-2.0/src/modules/perl/modperl_io_apache.c
Index: modperl_io_apache.c
===================================================================
#include "mod_perl.h"
#ifdef MP_IO_TIE_PERLIO
/***************************
* The PerlIO Apache layer *
***************************/
/* PerlIO ":Apache" layer is used to use the Apache callbacks to read
* from STDIN and write to STDOUT. The PerlIO API is documented in
* perliol.pod */
/*
* XXX: Since we cannot snoop on the internal apr_file_io buffer
* currently the IO is not buffered on the Perl side so every read
* requests a char at a time, which is slow. Consider copying the
* relevant code from PerlIOBuf to implement our own buffer, similar
* to what PerlIOBuf does or push :perlio layer on top of this layer
*/
typedef struct {
struct _PerlIO base;
request_rec *r;
} PerlIOApache;
/* _open just allocates the layer, _pushed does the real job of
* filling the data in */
static PerlIO *
PerlIOApache_open(pTHX_ PerlIO_funcs *self, PerlIO_list_t *layers, IV n,
const char *mode, int fd, int imode, int perm,
PerlIO *f, int narg, SV **args)
{
if (!f) {
f = PerlIO_allocate(aTHX);
}
if ( (f = PerlIO_push(aTHX_ f, self, mode, args[0])) ) {
PerlIOBase(f)->flags |= PERLIO_F_OPEN;
}
MP_TRACE_o(MP_FUNC, "mode %s", mode);
return f;
}
/* this callback is used by pushed() and binmode() to add the layer */
static IV
PerlIOApache_pushed(pTHX_ PerlIO *f, const char *mode, SV *arg,
PerlIO_funcs *tab)
{
IV code;
PerlIOApache *st = PerlIOSelf(f, PerlIOApache);
if (arg) {
st->r = modperl_sv2request_rec(aTHX_ arg);
}
else {
Perl_croak(aTHX_ "$r wasn't passed");
/* XXX: try to get Apache->request? */
}
/* this method also sets the right flags according to the
* 'mode' */
code = PerlIOBase_pushed(aTHX_ f, mode, Nullsv, tab);
MP_TRACE_o(MP_FUNC, "done");
return code;
}
static IV
PerlIOApache_fileno(pTHX_ PerlIO *f)
{
/* XXX: we could return STDIN => 0, STDOUT => 2, but that wouldn't
* be correct, as the IO goes through the socket, may be we should
* return the filedescriptor of the socket?
*
* -1 in this case indicates that the layer cannot provide fileno
*/
MP_TRACE_o(MP_FUNC, "did nothing");
return -1;
}
/* XXX: FIXME */
static MP_INLINE
apr_status_t mpxs_setup_client_block(request_rec *r)
{
if (!r->read_length) {
apr_status_t rc;
/* only do this once per-request */
if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
"mod_perl: ap_setup_client_block failed: %d", rc);
return rc;
}
}
return APR_SUCCESS;
}
#define mpxs_should_client_block(r) \
(r->read_length || ap_should_client_block(r))
static SSize_t
PerlIOApache_read(pTHX_ PerlIO *f, void *vbuf, Size_t count)
{
PerlIOApache *st = PerlIOSelf(f, PerlIOApache);
request_rec *r = st->r;
long total = 0;
int rc;
if (!(PerlIOBase(f)->flags & PERLIO_F_CANREAD) ||
PerlIOBase(f)->flags & (PERLIO_F_EOF|PERLIO_F_ERROR)) {
return 0;
}
if ((rc = mpxs_setup_client_block(r)) != APR_SUCCESS) {
return 0;
}
if (mpxs_should_client_block(r)) {
total = ap_get_client_block(r, vbuf, count);
MP_TRACE_o(MP_FUNC, "wanted %db, read %db [%s]",
count, total, (char *)vbuf);
if (total < 0) {
/*
* XXX: as stated in ap_get_client_block, the real
* error gets lots, so we only know that there was one
*/
ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
"mod_perl: $r->read failed to read");
}
}
return total;
}
static SSize_t
PerlIOApache_write(pTHX_ PerlIO *f, const void *vbuf, Size_t count)
{
PerlIOApache *st = PerlIOSelf(f, PerlIOApache);
modperl_config_req_t *rcfg = modperl_config_req_get(st->r);
apr_size_t bytes = 0;
apr_status_t rv;
if (!(PerlIOBase(f)->flags & PERLIO_F_CANWRITE)) {
return 0;
}
MP_CHECK_WBUCKET_INIT("print");
MP_TRACE_o(MP_FUNC, "%d bytes [%s]", count, (char *)vbuf);
rv = modperl_wbucket_write(aTHX_ rcfg->wbucket, vbuf, &count);
if (rv != APR_SUCCESS) {
Perl_croak(aTHX_ modperl_apr_strerror(rv));
}
bytes += count;
return (SSize_t) bytes;
}
static IV
PerlIOApache_flush(pTHX_ PerlIO *f)
{
PerlIOApache *st = PerlIOSelf(f, PerlIOApache);
modperl_config_req_t *rcfg = modperl_config_req_get(st->r);
/* no flush on readonly io handle */
if (! (PerlIOBase(f)->flags & PERLIO_F_CANWRITE) ) {
return -1;
}
MP_CHECK_WBUCKET_INIT("flush");
MP_TRACE_o(MP_FUNC, "%d bytes [%s]", rcfg->wbucket->outcnt,
apr_pstrmemdup(rcfg->wbucket->pool, rcfg->wbucket->outbuf,
rcfg->wbucket->outcnt));
MP_FAILURE_CROAK(modperl_wbucket_flush(rcfg->wbucket, FALSE));
return 0;
}
/* 5.8.0 doesn't export PerlIOBase_noop_fail, so we duplicate it here */
static IV PerlIOApache_noop_fail(pTHX_ PerlIO *f)
{
return -1;
}
static IV
PerlIOApache_close(pTHX_ PerlIO *f)
{
/* XXX: just temp for tracing */
MP_TRACE_o(MP_FUNC, "done");
return PerlIOBase_close(aTHX_ f);
}
static IV
PerlIOApache_popped(pTHX_ PerlIO *f)
{
/* XXX: just temp for tracing */
MP_TRACE_o(MP_FUNC, "done");
return PerlIOBase_popped(aTHX_ f);
}
static PerlIO_funcs PerlIO_Apache = {
sizeof(PerlIO_funcs),
"Apache",
sizeof(PerlIOApache),
PERLIO_K_MULTIARG,
PerlIOApache_pushed,
PerlIOApache_popped,
PerlIOApache_open,
PerlIOBase_binmode,
NULL, /* no getarg needed */
PerlIOApache_fileno,
PerlIOBase_dup,
PerlIOApache_read,
PerlIOBase_unread,
PerlIOApache_write,
NULL, /* can't seek on STD{IN|OUT}, fail on call*/
NULL, /* can't tell on STD{IN|OUT}, fail on call*/
PerlIOApache_close,
PerlIOApache_flush,
PerlIOApache_noop_fail, /* fill */
PerlIOBase_eof,
PerlIOBase_error,
PerlIOBase_clearerr,
PerlIOBase_setlinebuf,
NULL, /* get_base */
NULL, /* get_bufsiz */
NULL, /* get_ptr */
NULL, /* get_cnt */
NULL, /* set_ptrcnt */
};
/* ***** End of PerlIOApache tab ***** */
MP_INLINE void modperl_io_apache_init(pTHX)
{
PerlIO_define_layer(aTHX_ &PerlIO_Apache);
}
#endif /* defined MP_IO_TIE_PERLIO */
1.1 modperl-2.0/src/modules/perl/modperl_io_apache.h
Index: modperl_io_apache.h
===================================================================
#ifndef MODPERL_IO_APACHE_H
#define MODPERL_IO_APACHE_H
#ifdef PERLIO_LAYERS
#include "perliol.h"
/* XXX: should this be a Makefile.PL config option? */
#define MP_IO_TIE_PERLIO
#include "apr_portable.h"
#include "apr_file_io.h"
#include "apr_errno.h"
typedef enum {
MODPERL_IO_APACHE_HOOK_READ,
MODPERL_IO_APACHE_HOOK_WRITE
} modperl_io_apache_hook_e;
#define PERLIO_Apache_DEBUG
MP_INLINE void modperl_io_apache_init(pTHX);
#else /* #ifdef PERLIO_LAYERS */
#define modperl_io_apache_init(pTHX)
#endif /* #ifdef PERLIO_LAYERS */
#endif /* MODPERL_IO_APACHE_H */
1.1 modperl-2.0/t/modperl/print_utf8.t
Index: print_utf8.t
===================================================================
use strict;
use warnings FATAL => 'all';
use Apache::Test;
use Apache::TestRequest;
use Apache::TestUtil;
# utf encode/decode was added only in 5.8.0
# currently binmode is only available with perlio
plan tests => 1, have have_min_perl_version(5.008), have_perl('perlio');
#use bytes;
#use utf8;
my $location = "/TestModperl__print_utf8";
my $received = GET_BODY_ASSERT $location;
# the external stream already include wide-chars, but perl doesn't
# know about it
utf8::decode($received);
binmode(STDOUT, ':utf8');
my $expected = "Hello Ayhan \x{263A} perlio rules!";
print "$expected\n";
print "$received\n";
#ok $expected eq $received;
ok t_cmp($expected, $received, 'UTF8 encoding');
1.1 modperl-2.0/t/response/TestModperl/print_utf8.pm
Index: print_utf8.pm
===================================================================
package TestModperl::print_utf8;
use strict;
use warnings FATAL => 'all';
use Apache::RequestIO ();
use Apache::RequestRec ();
use Apache::Const -compile => 'OK';
use utf8;
sub handler {
my $r = shift;
$r->content_type('text/plain; charset=UTF-8');
#Apache::RequestRec::BINMODE
binmode(STDOUT, ':utf8');
# must be non-$r->print(), so we go through the tied STDOUT
print "Hello Ayhan \x{263A} perlio rules!";
Apache::OK;
}
1;
__DATA__
# must test against a tied STDOUT
SetHandler perl-script
1.104 +2 -2 modperl-2.0/lib/ModPerl/Code.pm
Index: Code.pm
===================================================================
RCS file: /home/cvs/modperl-2.0/lib/ModPerl/Code.pm,v
retrieving revision 1.103
retrieving revision 1.104
diff -u -r1.103 -r1.104
--- Code.pm 19 Aug 2003 07:26:47 -0000 1.103
+++ Code.pm 20 Aug 2003 23:20:14 -0000 1.104
@@ -606,8 +606,8 @@
);
my @c_src_names = qw(interp tipool log config cmd options callback handler
- gtop util io filter bucket mgv pcw global env cgi
- perl perl_global perl_pp sys module svptr_table
+ gtop util io io_apache filter bucket mgv pcw global env
+ cgi perl perl_global perl_pp sys module svptr_table
const constants apache_compat);
my @h_src_names = qw(perl_unembed);
my @g_c_names = map { "modperl_$_" } qw(hooks directives flags xsinit);
1.119 +81 -0 modperl-2.0/xs/tables/current/ModPerl/FunctionTable.pm
Index: FunctionTable.pm
===================================================================
RCS file: /home/cvs/modperl-2.0/xs/tables/current/ModPerl/FunctionTable.pm,v
retrieving revision 1.118
retrieving revision 1.119
diff -u -r1.118 -r1.119
--- FunctionTable.pm 11 Aug 2003 20:34:22 -0000 1.118
+++ FunctionTable.pm 20 Aug 2003 23:20:14 -0000 1.119
@@ -2783,6 +2783,40 @@
]
},
{
+ 'return_type' => 'void',
+ 'name' => 'modperl_io_perlio_restore_stdin',
+ 'attr' => [
+ '__inline__'
+ ],
+ 'args' => [
+ {
+ 'type' => 'PerlInterpreter *',
+ 'name' => 'my_perl'
+ },
+ {
+ 'type' => 'GV *',
+ 'name' => 'handle'
+ }
+ ]
+ },
+ {
+ 'return_type' => 'void',
+ 'name' => 'modperl_io_perlio_restore_stdout',
+ 'attr' => [
+ '__inline__'
+ ],
+ 'args' => [
+ {
+ 'type' => 'PerlInterpreter *',
+ 'name' => 'my_perl'
+ },
+ {
+ 'type' => 'GV *',
+ 'name' => 'handle'
+ }
+ ]
+ },
+ {
'return_type' => 'GV *',
'name' => 'modperl_io_tie_stdin',
'attr' => [
@@ -2814,6 +2848,53 @@
'type' => 'request_rec *',
'name' => 'r'
}
+ ]
+ },
+ {
+ 'return_type' => 'GV *',
+ 'name' => 'modperl_io_perlio_override_stdin',
+ 'attr' => [
+ '__inline__'
+ ],
+ 'args' => [
+ {
+ 'type' => 'PerlInterpreter *',
+ 'name' => 'my_perl'
+ },
+ {
+ 'type' => 'request_rec *',
+ 'name' => 'r'
+ }
+ ]
+ },
+ {
+ 'return_type' => 'GV *',
+ 'name' => 'modperl_io_perlio_override_stdout',
+ 'attr' => [
+ '__inline__'
+ ],
+ 'args' => [
+ {
+ 'type' => 'PerlInterpreter *',
+ 'name' => 'my_perl'
+ },
+ {
+ 'type' => 'request_rec *',
+ 'name' => 'r'
+ }
+ ]
+ },
+ {
+ 'return_type' => 'void',
+ 'name' => 'modperl_io_apache_init',
+ 'attr' => [
+ '__inline__'
+ ],
+ 'args' => [
+ {
+ 'type' => 'PerlInterpreter *',
+ 'name' => 'my_perl'
+ },
]
},
{
1.209 +4 -0 modperl-2.0/Changes
Index: Changes
===================================================================
RCS file: /home/cvs/modperl-2.0/Changes,v
retrieving revision 1.208
retrieving revision 1.209
diff -u -r1.208 -r1.209
--- Changes 11 Aug 2003 20:34:56 -0000 1.208
+++ Changes 20 Aug 2003 23:20:14 -0000 1.209
@@ -12,6 +12,10 @@
=item 1.99_10-dev
+when perl is built with perlio enabled (5.8+) the new PerlIO Apache
+layer is used, so now one can push layers onto STDIN, STDOUT handles
+e.g. binmode(STDOUT, ':utf8'); [Stas]
+
alter stacked handler interface so that mod_perl follows Apache
as closely as possible with respect to VOID/RUN_FIRST/RUN_ALL
handler types. now, for phases where OK ends the Apache