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);
}