int modperl_errsv(pTHX_ int status, request_rec *r, server_rec *s) { SV *sv = ERRSV; STRLEN n_a; if (SvTRUE(sv)) { if (sv_derived_from(sv, "APR::Error") && SvIVx(sv) == MODPERL_RC_EXIT) { /* ModPerl::Util::exit was called */ return OK; } #if 0 if (modperl_sv_is_http_code(ERRSV, &status)) { return status; } #endif if (r) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s", SvPV(sv, n_a)); } else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "%s", SvPV(sv, n_a)); } return status; } return status; }
static int campher_get_sv_int(PerlInterpreter* my_perl, SV* sv) { PERL_SET_CONTEXT(my_perl); return SvIVx(sv); }
int modperl_callback(pTHX_ modperl_handler_t *handler, apr_pool_t *p, request_rec *r, server_rec *s, AV *args) { CV *cv = (CV *)NULL; I32 flags = G_EVAL|G_SCALAR; dSP; int count, status = OK; /* handler callbacks shouldn't affect each other's taintedness * state, so start every callback with a clear tainted status * before and after the callback one of the main problems we are * trying to solve is that when modperl_croak called (which calls * perl's croak((char *)NULL) to throw an error object) it leaves * the interpreter in the tainted state which later affects other * callbacks that call eval, etc., which triggers perl crash with: * Insecure dependency in eval while running setgid. Callback * called exit. */ TAINT_NOT; if ((status = modperl_handler_resolve(aTHX_ &handler, p, s)) != OK) { TAINT_NOT; return status; } ENTER;SAVETMPS; PUSHMARK(SP); if (MpHandlerMETHOD(handler)) { GV *gv; if (!handler->mgv_obj) { Perl_croak(aTHX_ "panic: %s method handler object is NULL!", modperl_handler_name(handler)); } gv = modperl_mgv_lookup(aTHX_ handler->mgv_obj); XPUSHs(modperl_mgv_sv(gv)); } if (args) { I32 items = AvFILLp(args) + 1; EXTEND(SP, items); Copy(AvARRAY(args), SP + 1, items, SV*); SP += items; } PUTBACK; if (MpHandlerANON(handler)) { #ifdef USE_ITHREADS cv = modperl_handler_anon_get(aTHX_ handler->mgv_obj); #else cv = handler->cv; #endif } else { GV *gv = modperl_mgv_lookup_autoload(aTHX_ handler->mgv_cv, s, p); if (gv) { cv = modperl_mgv_cv(gv); } else { const char *name; modperl_mgv_t *symbol = handler->mgv_cv; /* XXX: need to validate *symbol */ if (symbol && symbol->name) { name = modperl_mgv_as_string(aTHX_ symbol, p, 0); } else { name = handler->name; } MP_TRACE_h(MP_FUNC, "[%s %s] lookup of %s failed", modperl_pid_tid(p), modperl_server_desc(s, p), name); ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "lookup of '%s' failed", name); status = HTTP_INTERNAL_SERVER_ERROR; } } if (status == OK) { count = call_sv((SV*)cv, flags); SPAGAIN; if (count != 1) { /* XXX can this really happen with G_EVAL|G_SCALAR? */ status = OK; } else { SV *status_sv = POPs; if (status_sv == &PL_sv_undef) { /* ModPerl::Util::exit() and Perl_croak internally * arrange to return PL_sv_undef with G_EVAL|G_SCALAR */ status = OK; } else { status = SvIVx(status_sv); } } PUTBACK; } FREETMPS;LEAVE; if (SvTRUE(ERRSV)) { MP_TRACE_h(MP_FUNC, "$@ = %s", SvPV_nolen(ERRSV)); status = HTTP_INTERNAL_SERVER_ERROR; } if (status == HTTP_INTERNAL_SERVER_ERROR) { if (r && r->notes) { apr_table_merge(r->notes, "error-notes", SvPV_nolen(ERRSV)); } } TAINT_NOT; return status; }
SV * parse_in_chunks(char * filepath, size_t filesize) { char *buf; size_t bytes_read = 0; int max_buf = 1000; char *err_msg; int block = BLOCK_HEADER; int cur_event_type = 0; int event_type = 0; char event_block = 0; char *brnl, *breq; AV * data; AV * datawrapper; AV * events; char *line; char * nl = "\n"; char * eq = "="; int rewind_pos = 0; size_t cur_fpos = 0; SV * pbuf; SV * pmax_buf; AV * HANDLERS = get_av("Opsview::Utils::NDOLogsImporter::HANDLERS", 0); AV * INPUT_DATA_TYPE = get_av("Opsview::Utils::NDOLogsImporter::INPUT_DATA_TYPE", 0); int init_last_pos; int init_block; if ( first_read ) { if ( ! ( fh = PerlIO_open( filepath, "rb" ) ) ) { croak("Could not open file: %s\n", strerror(errno)); } bytes_left = filesize; init_last_pos = prev_pos = first_read = 0; init_block = block = BLOCK_HEADER; } else { init_block = block = BLOCK_EVENTS; init_last_pos = prev_pos; } read_begin: brnl = NULL; breq = NULL; pbuf = get_sv("Opsview::Utils::NDOLogsImporter::PARSE_BUF", 0); pmax_buf = get_sv("Opsview::Utils::NDOLogsImporter::MAX_BUF_SIZE", 0); buf = SvPVX(pbuf); max_buf = SvIVX(pmax_buf); if ( max_buf < 1024 * 1024 && ! automated_tests ) { max_buf = 1024*1024; SvIV_set( pmax_buf, max_buf ); SvGROW( pbuf, max_buf + 1); SvCUR_set( pbuf, max_buf); } if ( bytes_left > 0 ) { bytes_read = PerlIO_read(fh, buf + prev_pos, max_buf-prev_pos); cur_fpos = PerlIO_tell(fh); if ( bytes_read < 0 ) { err_msg = strerror(errno); PerlIO_close( fh ); croak("Could not read file: %s\n", err_msg); } bytes_left -= bytes_read; events = (AV *)sv_2mortal((SV *)newAV()); rewind_pos = last_999(buf+prev_pos, bytes_read); prev_pos = bytes_read + prev_pos - rewind_pos; buf[prev_pos] = '\0'; // avg ratio events:file_size = 0.21% if ( prev_pos > 1000 ) { av_extend( events, (int)(prev_pos * 0.0021) ); } for ( line = strtok_r(buf, nl, &brnl); line != NULL; line = strtok_r(NULL, nl, &brnl) ) { switch(block) { case BLOCK_HEADER: { if ( strEQ(line, "STARTDATADUMP") ) { block = BLOCK_EVENTS; } } break; case BLOCK_EVENTS: { if ( strEQ(line, "1000") ) { /* NDO_API_ENDDATADUMP */ block = BLOCK_FOOTER; continue; } cur_event_type = atoi(line); /* ignore events we are not handling */ if ( ! av_exists(HANDLERS, cur_event_type) ) { block = BLOCK_IGNORE_EVENT; continue; } event_block = BLOCK_EVENT_STARTED; if ( cur_event_type != event_type ) { datawrapper = (AV *)sv_2mortal((SV *)newAV()); data = (AV *)sv_2mortal((SV *)newAV()); av_push( events, newSViv( cur_event_type ) ); av_push( datawrapper, newRV( (SV *)data ) ); av_push( events, newRV( (SV *)datawrapper ) ); event_type = cur_event_type; } else { data = (AV *)sv_2mortal((SV *)newAV()); av_push( datawrapper, newRV( (SV *)data ) ); } block = BLOCK_EVENT; } break; case BLOCK_EVENT: { if ( strEQ(line, "999") ) { /* NDO_API_ENDDATA */ block = BLOCK_EVENTS; event_block = BLOCK_EVENT_ENDED; } else { char *k; char *v; int key; int key_type = 0; int v_len = 0; k = strtok_r(line, eq, &breq); v = strtok_r(NULL, "\0", &breq); key = atoi(k); /* invalid key, skip parsing */ if ( key == 0 ) { goto remove_invalid; } SV ** const k_type = av_fetch(INPUT_DATA_TYPE, key, 0 ); if ( k_type ) { key_type = SvIVx( *k_type ); } if ( v ) { if ( key_type & 1 ) { v_len = ndo_unescape_buffer( v ); } else { v_len = strlen(v); } } if ( key_type & 2 ) { AV * datanstptr; SV ** const datanst = av_fetch(data, key, 0 ); if ( datanst ) { datanstptr = (AV *)SvRV( *datanst ); } else { datanstptr = (AV *)sv_2mortal((SV *)newAV()); av_store( data, key, newRV( (SV *)datanstptr ) ); } if ( v ) { av_push( datanstptr, newSVpvn(v, v_len) ); } else { av_push( datanstptr, newSVpvn("", 0) ); } } else { if ( v ) { av_store( data, key, newSVpvn(v, v_len) ); } else { av_store( data, key, newSVpvn("", 0) ); } } } } break; case BLOCK_FOOTER: { if ( strEQ(line, "GOODBYE") ) { block = BLOCK_HEADER; } } break; case BLOCK_IGNORE_EVENT: { if ( strEQ(line, "999") ) { /* NDO_API_ENDDATA */ block = BLOCK_EVENTS; // go back to EVENTS continue; } } break; } }; /* there were some events */ if ( event_block != BLOCK_HEADER ) { if ( event_block != BLOCK_EVENT_ENDED ) { remove_invalid: av_pop( datawrapper ); } /* remove whole block if the last block has no events */ if ( av_len( datawrapper ) == -1 ) { av_pop( events ); av_pop( events ); } } if ( av_len(events) > 0 ) { if ( rewind_pos > 0 && cur_fpos < filesize ) { memmove(buf, buf+prev_pos+1, rewind_pos-1); } prev_pos = rewind_pos - 1; return newRV_inc((SV *) events); } else { if ( cur_fpos < filesize && event_block != BLOCK_HEADER && event_block != BLOCK_EVENT_ENDED ) { int new_max_buf = max_buf * 2; SvIV_set( pmax_buf, new_max_buf ); SvGROW( pbuf, new_max_buf + 1); SvCUR_set( pbuf, new_max_buf); //start again as previous buffer would be tokenized already prev_pos = 0; block = init_block; event_type = 0; PerlIO_close( fh ); if ( ! ( fh = PerlIO_open( filepath, "rb" ) ) ) { croak("Could not re-open file: %s\n", strerror(errno)); } PerlIO_seek(fh, cur_fpos-bytes_read-init_last_pos, SEEK_SET); bytes_left += bytes_read + init_last_pos; goto read_begin; } } } parser_reset_iterator(); return &PL_sv_undef; }