Example #1
0
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;
            }
        }
    }
}
Example #2
0
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;
	}
Example #3
0
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;

}