#include "mod_perl.h"
#define dHANDLE(name) GV *handle = gv_fetchpv(name, TRUE, SVt_PVIO)
#define TIEHANDLE(name,obj) \
{ \
dHANDLE(name); \
sv_unmagic((SV*)handle,
'q'
); \
sv_magic((SV*)handle, obj,
'q'
, Nullch, 0); \
}
#if 0
#define TIED tied_handle
static
int
tied_handle(
char
*name)
{
dHANDLE(name);
MAGIC *mg;
if
(SvMAGICAL(handle) && (mg = mg_find((SV*)handle,
'q'
))) {
char
*package = HvNAME(SvSTASH((SV*)SvRV(mg->mg_obj)));
if
(!strEQ(package,
"Apache"
)) {
fprintf
(stderr,
"%s tied to %s\n"
, GvNAME(handle), package);
return
TRUE;
}
}
return
FALSE;
}
#else
#define TIED(name) 0
#endif
#ifdef USE_SFIO
typedef
struct
{
Sfdisc_t disc;
request_rec *r;
} Apache_t;
static
int
sfapachewrite(f, buffer, n, disc)
Sfio_t* f;
char
* buffer;
int
n;
Sfdisc_t* disc;
{
CV *cv = GvCV(gv_fetchpv(
"Apache::print"
, FALSE, SVt_PVCV));
dSP;
ENTER;
SAVETMPS;
PUSHMARK(sp);
XPUSHs(perl_bless_request_rec(((Apache_t*)disc)->r));
XPUSHs(sv_2mortal(newSVpv(buffer,n)));
PUTBACK;
(
void
)(*CvXSUB(cv))(aTHXo_ cv);
FREETMPS;
LEAVE;
return
n;
}
static
int
sfapacheread(f, buffer, bufsiz, disc)
Sfio_t* f;
char
* buffer;
int
bufsiz;
Sfdisc_t* disc;
{
dSP;
int
count;
int
nrd;
SV *sv = sv_newmortal();
request_rec *r = ((Apache_t*)disc)->r;
MP_TRACE_g(
fprintf
(stderr,
"sfapacheread: want %d bytes\n"
, bufsiz));
ENTER;SAVETMPS;
PUSHMARK(sp);
XPUSHs(perl_bless_request_rec(r));
XPUSHs(sv);
XPUSHs(sv_2mortal(newSViv(bufsiz)));
PUTBACK;
count = perl_call_pv(
"Apache::read"
, G_SCALAR|G_EVAL);
SPAGAIN;
if
(SvTRUE(ERRSV)) {
fprintf
(stderr,
"Apache::read died %s\n"
, SvPV(ERRSV, na));
nrd = -1;
POPs;
}
else
{
char
*tmpbuf = SvPV(sv, nrd);
if
(count == 1) {
nrd = POPi;
}
MP_TRACE_g(
fprintf
(stderr,
"sfapacheread: got %d \"%.*s\"\n"
,
nrd, nrd > 40 ? 40 : nrd, tmpbuf));
if
(nrd > bufsiz) {
abort
();
}
memcpy
(buffer, tmpbuf, nrd);
}
PUTBACK;
FREETMPS;LEAVE;
return
nrd;
}
Sfdisc_t * sfdcnewapache(request_rec *r)
{
Apache_t* disc;
if
(!(disc = (Apache_t*)
malloc
(
sizeof
(Apache_t))) )
return
(Sfdisc_t *)disc;
MP_TRACE_g(
fprintf
(stderr,
"sfdcnewapache(r)\n"
));
disc->disc.readf = (Sfread_f)sfapacheread;
disc->disc.writef = (Sfwrite_f)sfapachewrite;
disc->disc.seekf = (Sfseek_f)NULL;
disc->disc.exceptf = (Sfexcept_f)NULL;
disc->r = r;
return
(Sfdisc_t *)disc;
}
#endif
void
perl_soak_script_output(request_rec *r)
{
SV *sv = sv_newmortal();
sv_setref_pv(sv,
"Apache::FakeRequest"
, (
void
*)r);
if
(!perl_get_cv(
"Apache::FakeRequest::PRINT"
, FALSE))
(
void
)perl_eval_pv(
"package Apache::FakeRequest; sub PRINT {}; sub PRINTF {}"
, TRUE);
#ifdef USE_SFIO
sfdisc(PerlIO_stdout(), SF_POPDISC);
#endif
TIEHANDLE(
"STDOUT"
, sv);
mod_perl_sent_header(r, TRUE);
}
void
perl_stdout2client(request_rec *r)
{
dTHR;
#ifdef USE_SFIO
sfdisc(PerlIO_stdout(), SF_POPDISC);
sfdisc(PerlIO_stdout(), sfdcnewapache(r));
IoFLAGS(GvIOp(defoutgv)) |= IOf_FLUSH;
#else
IoFLAGS(GvIOp(defoutgv)) &= ~IOf_FLUSH;
if
(TIED(
"STDOUT"
))
return
;
MP_TRACE_g(
fprintf
(stderr,
"tie *STDOUT => Apache\n"
));
TIEHANDLE(
"STDOUT"
, perl_bless_request_rec(r));
#endif
}
void
perl_stdin2client(request_rec *r)
{
#ifdef USE_SFIO
sfdisc(PerlIO_stdin(), SF_POPDISC);
sfdisc(PerlIO_stdin(), sfdcnewapache(r));
sfsetbuf(PerlIO_stdin(), NULL, 0);
#else
if
(TIED(
"STDIN"
))
return
;
MP_TRACE_g(
fprintf
(stderr,
"tie *STDIN => Apache\n"
));
TIEHANDLE(
"STDIN"
, perl_bless_request_rec(r));
#endif
}