void mop_get_package_symbols (HV *stash, type_filter_t filter, get_package_symbols_cb_t cb, void *ud) { HE *he; (void)hv_iterinit(stash); if (filter == TYPE_FILTER_NONE) { while ( (he = hv_iternext(stash)) ) { STRLEN keylen; const char *key = HePV(he, keylen); if (!cb(key, keylen, HeVAL(he), ud)) { return; } } return; } while ( (he = hv_iternext(stash)) ) { GV * const gv = (GV*)HeVAL(he); STRLEN keylen; const char * const key = HePV(he, keylen); SV *sv = NULL; if(isGV(gv)){ switch (filter) { case TYPE_FILTER_CODE: sv = (SV *)GvCVu(gv); break; case TYPE_FILTER_ARRAY: sv = (SV *)GvAV(gv); break; case TYPE_FILTER_IO: sv = (SV *)GvIO(gv); break; case TYPE_FILTER_HASH: sv = (SV *)GvHV(gv); break; case TYPE_FILTER_SCALAR: sv = (SV *)GvSV(gv); break; default: croak("Unknown type"); } } /* expand the gv into a real typeglob if it * contains stub functions or constants and we * were asked to return CODE references */ else if (filter == TYPE_FILTER_CODE) { gv_init(gv, stash, key, keylen, GV_ADDMULTI); sv = (SV *)GvCV(gv); } if (sv) { if (!cb(key, keylen, sv, ud)) { return; } } } }
OP * Perl_do_readline(pTHX_ GV* gv) { dVAR; dSP; dTARGETSTACKED; register SV *sv; STRLEN tmplen = 0; STRLEN offset; PerlIO *fp; register IO * const io = GvIO(gv); register const I32 type = PL_op->op_type; const I32 gimme = GIMME_V; PERL_ARGS_ASSERT_DO_READLINE; fp = NULL; if (io) { fp = IoIFP(io); if (!fp) { if (IoFLAGS(io) & IOf_ARGV) { if (IoFLAGS(io) & IOf_START) { IoLINES(io) = 0; if (av_len(GvAVn(gv)) < 0) { IoFLAGS(io) &= ~IOf_START; do_openn(io,"-",1,FALSE,O_RDONLY,0,NULL,NULL,0); sv_setpvn(GvSVn(gv), "-", 1); SvSETMAGIC(GvSV(gv)); fp = IoIFP(io); goto have_fp; } } fp = nextargv(gv); if (!fp) { /* Note: fp != IoIFP(io) */ (void)do_close(gv, FALSE); /* now it does*/ } } } else if (ckWARN(WARN_IO) && IoTYPE(io) == IoTYPE_WRONLY) { report_evil_fh(io, OP_phoney_OUTPUT_ONLY); } } if (!fp) { if ((!io || !(IoFLAGS(io) & IOf_START)) && ckWARN2(WARN_GLOB, WARN_CLOSED)) { if (type == OP_GLOB) Perl_warner(aTHX_ packWARN(WARN_GLOB), "glob failed (can't start child: %s)", Strerror(errno)); else report_evil_fh(io, PL_op->op_type); } if (gimme == G_SCALAR) { /* undef TARG, and push that undefined value */ if (type != OP_RCATLINE) { SV_CHECK_THINKFIRST_COW_DROP(TARG); if ( ! SvPVOK(TARG) ) sv_upgrade(TARG, SVt_PV); SvOK_off(TARG); } PUSHTARG; } RETURN; } have_fp: if (gimme == G_SCALAR) { sv = TARG; if (type == OP_RCATLINE) { NOOP; } else { if ( SvOK(sv) && ! SvPVOK(sv) ) sv_clear_body(sv); } if (SvROK(sv)) { if (type == OP_RCATLINE) SvPV_force_nolen(sv); else sv_unref(sv); } else if (isGV_with_GP(sv)) { SvPV_force_nolen(sv); } SvUPGRADE(sv, SVt_PV); tmplen = SvLEN(sv); /* remember if already alloced */ if (!tmplen && !SvREADONLY(sv)) Sv_Grow(sv, 80); /* try short-buffering it */ offset = 0; if (type == OP_RCATLINE && SvOK(sv)) { if (!SvPOK(sv)) { SvPV_force_nolen(sv); } offset = SvCUR(sv); } } else { sv = sv_2mortal(newSV(80)); offset = 0; } /* delay EOF state for a snarfed empty file */ #define SNARF_EOF(gimme,rs,io,sv) \ (gimme != G_SCALAR || SvCUR(sv) \ || (IoFLAGS(io) & IOf_NOLINE) || !RsSNARF(rs)) for (;;) { PUTBACK; if (!sv_gets(sv, fp, offset) && (type == OP_GLOB || SNARF_EOF(gimme, PL_rs, io, sv) || PerlIO_error(fp))) { PerlIO_clearerr(fp); if (IoFLAGS(io) & IOf_ARGV) { fp = nextargv(gv); if (fp) continue; (void)do_close(gv, FALSE); } else if (type == OP_GLOB) { if (!do_close(gv, FALSE) && ckWARN(WARN_GLOB)) { Perl_warner(aTHX_ packWARN(WARN_GLOB), "glob failed (child exited with status %d%s)", (int)(STATUS_CURRENT >> 8), (STATUS_CURRENT & 0x80) ? ", core dumped" : ""); } } if (gimme == G_SCALAR) { if (type != OP_RCATLINE) { SV_CHECK_THINKFIRST_COW_DROP(TARG); SvOK_off(TARG); } SPAGAIN; PUSHTARG; } RETURN; }
int psgi_response(struct wsgi_request *wsgi_req, AV *response) { SV **status_code, **hitem ; AV *headers, *body =NULL; STRLEN hlen; struct http_status_codes *http_sc; int i,vi, base; char *chitem; SV **harakiri; #ifdef UWSGI_ASYNC if (wsgi_req->async_status == UWSGI_AGAIN) { wsgi_req->async_force_again = 0; wsgi_req->switches++; SV *chunk = uwsgi_perl_obj_call(wsgi_req->async_placeholder, "getline"); if (!chunk) { internal_server_error(wsgi_req, "exception raised"); return UWSGI_OK; } if (wsgi_req->async_force_again) { SvREFCNT_dec(chunk); return UWSGI_AGAIN; } chitem = SvPV( chunk, hlen); if (hlen <= 0) { SvREFCNT_dec(chunk); SV *closed = uwsgi_perl_obj_call(wsgi_req->async_placeholder, "close"); if (closed) { SvREFCNT_dec(closed); } // check for psgix.harakiri harakiri = hv_fetch((HV*)SvRV( (SV*)wsgi_req->async_environ), "psgix.harakiri.commit", 21, 0); if (harakiri) { if (SvTRUE(*harakiri)) wsgi_req->async_plagued = 1; } SvREFCNT_dec(wsgi_req->async_environ); SvREFCNT_dec(wsgi_req->async_result); return UWSGI_OK; } wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, chitem, hlen); SvREFCNT_dec(chunk); return UWSGI_AGAIN; } #endif status_code = av_fetch(response, 0, 0); if (!status_code) { uwsgi_log("invalid PSGI status code\n"); return UWSGI_OK;} wsgi_req->hvec[0].iov_base = "HTTP/1.1 "; wsgi_req->hvec[0].iov_len = 9; wsgi_req->hvec[1].iov_base = SvPV(*status_code, hlen); wsgi_req->hvec[1].iov_len = 3; wsgi_req->status = atoi(wsgi_req->hvec[1].iov_base); wsgi_req->hvec[2].iov_base = " "; wsgi_req->hvec[2].iov_len = 1; wsgi_req->hvec[3].iov_len = 0; // get the status code for (http_sc = hsc; http_sc->message != NULL; http_sc++) { if (!strncmp(http_sc->key, wsgi_req->hvec[1].iov_base, 3)) { wsgi_req->hvec[3].iov_base = (char *) http_sc->message; wsgi_req->hvec[3].iov_len = http_sc->message_size; break; } } if (wsgi_req->hvec[3].iov_len == 0) { wsgi_req->hvec[3].iov_base = "Unknown"; wsgi_req->hvec[3].iov_len = 7; } wsgi_req->hvec[4].iov_base = "\r\n"; wsgi_req->hvec[4].iov_len = 2; hitem = av_fetch(response, 1, 0); if (!hitem) { uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;} headers = (AV *) SvRV(*hitem); if (!headers) { uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;} base = 5; // put them in hvec for(i=0; i<=av_len(headers); i++) { vi = (i*2)+base; hitem = av_fetch(headers,i,0); chitem = SvPV(*hitem, hlen); wsgi_req->hvec[vi].iov_base = chitem; wsgi_req->hvec[vi].iov_len = hlen; wsgi_req->hvec[vi+1].iov_base = ": "; wsgi_req->hvec[vi+1].iov_len = 2; hitem = av_fetch(headers,i+1,0); chitem = SvPV(*hitem, hlen); wsgi_req->hvec[vi+2].iov_base = chitem; wsgi_req->hvec[vi+2].iov_len = hlen; wsgi_req->hvec[vi+3].iov_base = "\r\n"; wsgi_req->hvec[vi+3].iov_len = 2; wsgi_req->header_cnt++; i++; } vi = (i*2)+base; wsgi_req->hvec[vi].iov_base = "\r\n"; wsgi_req->hvec[vi].iov_len = 2; wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, vi+1); hitem = av_fetch(response, 2, 0); if (!hitem) { return UWSGI_OK; } if (!SvRV(*hitem)) { uwsgi_log("invalid PSGI response body\n") ; return UWSGI_OK; } if (SvTYPE(SvRV(*hitem)) == SVt_PVGV || SvTYPE(SvRV(*hitem)) == SVt_PVHV || SvTYPE(SvRV(*hitem)) == SVt_PVMG) { // respond to fileno ? if (uwsgi.async < 2) { // check for fileno() method, IO class or GvIO if (uwsgi_perl_obj_can(*hitem, "fileno", 6) || uwsgi_perl_obj_isa(*hitem, "IO") || (uwsgi_perl_obj_isa(*hitem, "GLOB") && GvIO(SvRV(*hitem))) ) { SV *fn = uwsgi_perl_obj_call(*hitem, "fileno"); if (fn) { if (SvTYPE(fn) == SVt_IV && SvIV(fn) >= 0) { wsgi_req->sendfile_fd = SvIV(fn); SvREFCNT_dec(fn); wsgi_req->response_size += uwsgi_sendfile(wsgi_req); // no need to close here as perl GC will do the close() return UWSGI_OK; } SvREFCNT_dec(fn); } } // check for path method if (uwsgi_perl_obj_can(*hitem, "path", 4)) { SV *p = uwsgi_perl_obj_call(*hitem, "path"); wsgi_req->sendfile_fd = open(SvPV_nolen(p), O_RDONLY); SvREFCNT_dec(p); wsgi_req->response_size += uwsgi_sendfile(wsgi_req); close(wsgi_req->sendfile_fd); return UWSGI_OK; } } for(;;) { wsgi_req->switches++; SV *chunk = uwsgi_perl_obj_call(*hitem, "getline"); if (!chunk) { internal_server_error(wsgi_req, "exception raised"); break; } chitem = SvPV( chunk, hlen); #ifdef UWSGI_ASYNC if (uwsgi.async > 1 && wsgi_req->async_force_again) { SvREFCNT_dec(chunk); wsgi_req->async_status = UWSGI_AGAIN; wsgi_req->async_placeholder = (SV *) *hitem; return UWSGI_AGAIN; } #endif if (hlen <= 0) { SvREFCNT_dec(chunk); break; } wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, chitem, hlen); SvREFCNT_dec(chunk); #ifdef UWSGI_ASYNC if (uwsgi.async > 1) { wsgi_req->async_status = UWSGI_AGAIN; wsgi_req->async_placeholder = (SV *) *hitem; return UWSGI_AGAIN; } #endif } SV *closed = uwsgi_perl_obj_call(*hitem, "close"); if (closed) { SvREFCNT_dec(closed); } } else if (SvTYPE(SvRV(*hitem)) == SVt_PVAV) { body = (AV *) SvRV(*hitem); for(i=0; i<=av_len(body); i++) { hitem = av_fetch(body,i,0); chitem = SvPV(*hitem, hlen); wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, chitem, hlen); } } else { uwsgi_log("unsupported response body type: %d\n", SvTYPE(SvRV(*hitem))); } return UWSGI_OK; }