static apr_status_t fcgid_header_bucket_read()

in modules/fcgid/fcgid_bucket.c [74:255]


static apr_status_t fcgid_header_bucket_read(apr_bucket * b,
                                             const char **str,
                                             apr_size_t * len,
                                             apr_read_type_e block)
{
    fcgid_bucket_ctx *ctx = (fcgid_bucket_ctx *) b->data;
    apr_status_t rv;
    apr_size_t hasread, bodysize;
    FCGI_Header header;
    apr_bucket *curbucket = b;

    /* Keep reading until I get a fastcgi header */
    hasread = 0;
    while (hasread < sizeof(header)) {
        char *buffer;
        apr_size_t bufferlen, putsize;

        /* Feed some data if necessary */
        if ((rv =
             fcgid_feed_data(ctx, b->list, &buffer,
                             &bufferlen)) != APR_SUCCESS)
            return rv;

        /* Initialize header */
        putsize = fcgid_min(bufferlen, sizeof(header) - hasread);
        memcpy((apr_byte_t *)&header + hasread, buffer, putsize);
        hasread += putsize;

        /* Ignore the bytes that have read */
        fcgid_ignore_bytes(ctx, putsize);
    }

    /* Get the body size */
    bodysize = header.contentLengthB1;
    bodysize <<= 8;
    bodysize += header.contentLengthB0;

    /* Handle FCGI_STDERR body, write the content to log file */
    if (header.type == FCGI_STDERR) {
        char *logbuf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->list);
        char *line;
        apr_size_t hasput;

        memset(logbuf, 0, APR_BUCKET_BUFF_SIZE);

        hasread = 0;
        hasput = 0;
        while (hasread < bodysize) {
            char *buffer;
            apr_size_t bufferlen, canput, willput;

            /* Feed some data if necessary */
            if ((rv =
                 fcgid_feed_data(ctx, b->list, &buffer,
                                 &bufferlen)) != APR_SUCCESS) {
                apr_bucket_free(logbuf);
                return rv;
            }

            canput = fcgid_min(bufferlen, bodysize - hasread);
            willput =
                fcgid_min(canput, APR_BUCKET_BUFF_SIZE - hasput - 1);
            memcpy(logbuf + hasput, buffer, willput);
            hasread += canput;
            hasput += willput;

            /* Ignore the "canput" bytes */
            fcgid_ignore_bytes(ctx, canput);
        }

        /* Now I get the log data, write log and release the buffer */
        line = logbuf;
        while (*line) {
            char *end = strpbrk(line, "\r\n");

            if (end != NULL) {
                *end = '\0';
            }
            ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, ctx->ipc.request,
                          "mod_fcgid: stderr: %s", line);
            if (end == NULL) {
                break;
            }
            ++end;
            line = end + strspn(end, "\r\n");
        }

        apr_bucket_free(logbuf);
    }

    /* if( header.type==FCGI_STDERR ) */
    /* Now handle FCGI_STDOUT */
    else if (header.type == FCGI_STDOUT) {
        hasread = 0;
        while (hasread < bodysize) {
            char *buffer;
            apr_size_t bufferlen, canput;
            apr_bucket *buckettmp;

            /* Feed some data if necessary */
            if ((rv =
                 fcgid_feed_data(ctx, b->list, &buffer,
                                 &bufferlen)) != APR_SUCCESS)
                return rv;

            canput = fcgid_min(bufferlen, bodysize - hasread);

            /* Change the current bucket to refer to what we read */
            buckettmp = ctx->buffer;
            if (canput == (bodysize - hasread)) {
                apr_bucket_split(ctx->buffer, canput);
                ctx->buffer = APR_BUCKET_NEXT(ctx->buffer);
                APR_BUCKET_REMOVE(buckettmp);
            } else {
                /* canput==bufferlen */
                ctx->buffer = NULL;
            }

            APR_BUCKET_INSERT_AFTER(curbucket, buckettmp);
            curbucket = buckettmp;
            hasread += canput;
        }                       /* while( hasread<bodysize ) */
    }

    /* if( header.type==FCGI_STDOUT ) */
    /* Now FCGI_END_REQUEST */
    else if (header.type == FCGI_END_REQUEST) {
        /* Just ignore the body */
        hasread = 0;
        while (hasread < bodysize) {
            char *buffer;
            apr_size_t bufferlen, canignore;

            /* Feed some data if necessary */
            if ((rv =
                 fcgid_feed_data(ctx, b->list, &buffer,
                                 &bufferlen)) != APR_SUCCESS)
                return rv;

            canignore = fcgid_min(bufferlen, bodysize);
            hasread += canignore;

            /* Ignore the bytes */
            fcgid_ignore_bytes(ctx, canignore);
        }
    }

    /* Now ignore padding data */
    hasread = 0;
    while (hasread < header.paddingLength) {
        char *buffer;
        apr_size_t bufferlen, canignore;

        /* Feed some data if necessary */
        if ((rv =
             fcgid_feed_data(ctx, b->list, &buffer,
                             &bufferlen)) != APR_SUCCESS)
            return rv;

        canignore = fcgid_min(bufferlen, header.paddingLength - hasread);
        hasread += canignore;

        /* Ignore the bytes */
        fcgid_ignore_bytes(ctx, canignore);
    }

    /* Tail another fastcgi header bucket if it's not ending */
    if (header.type != FCGI_END_REQUEST) {
        apr_bucket *headerbucket =
            ap_bucket_fcgid_header_create(b->list, ctx);
        APR_BUCKET_INSERT_AFTER(curbucket, headerbucket);
    } else {
        /* Release the process ASAP */
        if ((rv = apr_pool_cleanup_run(ctx->ipc.request->pool,
                                       ctx,
                                       bucket_ctx_cleanup)) != APR_SUCCESS)
            return rv;
    }

    b = apr_bucket_immortal_make(b, "", 0);
    return apr_bucket_read(b, str, len, APR_BLOCK_READ);
}