Пример #1
0
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;
}
Пример #2
0
static int campher_get_sv_int(PerlInterpreter* my_perl, SV* sv) {
  PERL_SET_CONTEXT(my_perl);
  return SvIVx(sv);
}
Пример #3
0
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;
}