Lines 20-25
Link Here
|
20 |
#include "fcgid_bridge.h" |
20 |
#include "fcgid_bridge.h" |
21 |
|
21 |
|
22 |
#define FCGID_FEED_LEN 8192 |
22 |
#define FCGID_FEED_LEN 8192 |
|
|
23 |
/* fcgid_feed_data reads up to 8k from the fastcgi process into |
24 |
* a heap bucket */ |
23 |
static apr_status_t fcgid_feed_data(fcgid_bucket_ctx * ctx, |
25 |
static apr_status_t fcgid_feed_data(fcgid_bucket_ctx * ctx, |
24 |
apr_bucket_alloc_t * bucketalloc, |
26 |
apr_bucket_alloc_t * bucketalloc, |
25 |
char **buffer, apr_size_t * bufferlen) |
27 |
char **buffer, apr_size_t * bufferlen) |
Lines 43-49
Link Here
|
43 |
apr_bucket_free, bucketalloc); |
45 |
apr_bucket_free, bucketalloc); |
44 |
if (*bufferlen != FCGID_FEED_LEN) { |
46 |
if (*bufferlen != FCGID_FEED_LEN) { |
45 |
apr_bucket *buckettmp; |
47 |
apr_bucket *buckettmp; |
46 |
|
48 |
/* not all of the newly created bucket was used, so |
|
|
49 |
* split the bucket and remove the remainder */ |
47 |
apr_bucket_split(ctx->buffer, *bufferlen); |
50 |
apr_bucket_split(ctx->buffer, *bufferlen); |
48 |
buckettmp = APR_BUCKET_NEXT(ctx->buffer); |
51 |
buckettmp = APR_BUCKET_NEXT(ctx->buffer); |
49 |
apr_bucket_delete(buckettmp); |
52 |
apr_bucket_delete(buckettmp); |
Lines 112-161
Link Here
|
112 |
if (header.type == FCGI_STDERR) { |
115 |
if (header.type == FCGI_STDERR) { |
113 |
char *logbuf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->list); |
116 |
char *logbuf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->list); |
114 |
char *line; |
117 |
char *line; |
115 |
apr_size_t hasput; |
118 |
apr_size_t hasputbuf; |
116 |
|
119 |
|
|
|
120 |
/* 0-pad the logbuf */ |
117 |
memset(logbuf, 0, APR_BUCKET_BUFF_SIZE); |
121 |
memset(logbuf, 0, APR_BUCKET_BUFF_SIZE); |
118 |
|
122 |
|
119 |
hasread = 0; |
123 |
hasread = 0; |
120 |
hasput = 0; |
124 |
hasputbuf = 0; |
121 |
while (hasread < bodysize) { |
125 |
while (hasread < bodysize) { |
122 |
char *buffer; |
126 |
char *buffer; |
123 |
apr_size_t bufferlen, canput, willput; |
|
|
124 |
|
127 |
|
125 |
/* Feed some data if necessary */ |
128 |
while (hasread < bodysize |
126 |
if ((rv = |
129 |
&& hasputbuf < (APR_BUCKET_BUFF_SIZE-1)) { |
127 |
fcgid_feed_data(ctx, b->list, &buffer, |
130 |
apr_size_t bufferlen, canput, willput; |
128 |
&bufferlen)) != APR_SUCCESS) { |
131 |
|
129 |
apr_bucket_free(logbuf); |
132 |
/* Feed some data if necessary */ |
130 |
return rv; |
133 |
if ((rv = |
|
|
134 |
fcgid_feed_data(ctx, b->list, &buffer, |
135 |
&bufferlen)) != APR_SUCCESS) { |
136 |
apr_bucket_free(logbuf); |
137 |
return rv; |
138 |
} |
139 |
|
140 |
/* canput is how much data is available for reading, |
141 |
* either the remaining body size or the max buffer size. |
142 |
* This because we can read more than the bodysize |
143 |
* (the nex factcgi packet) */ |
144 |
canput = fcgid_min(bufferlen, bodysize - hasread); |
145 |
/* willput is what we will actually write to the |
146 |
* buffer (which is limited by buffer size) the |
147 |
* remaining data will stay in the bucket */ |
148 |
willput = fcgid_min(canput, |
149 |
APR_BUCKET_BUFF_SIZE - hasputbuf - 1); |
150 |
memcpy(logbuf + hasputbuf, buffer, willput); |
151 |
hasread += willput; |
152 |
hasputbuf += willput; |
153 |
|
154 |
/* Ignore the "willput" bytes */ |
155 |
fcgid_ignore_bytes(ctx, willput); |
131 |
} |
156 |
} |
132 |
|
157 |
|
133 |
canput = fcgid_min(bufferlen, bodysize - hasread); |
158 |
/* Now I get the log data, write log and release the buffer */ |
134 |
willput = |
159 |
line = logbuf; |
135 |
fcgid_min(canput, APR_BUCKET_BUFF_SIZE - hasput - 1); |
160 |
while (*line) { |
136 |
memcpy(logbuf + hasput, buffer, willput); |
161 |
/* find the first occurence of \r or \n */ |
137 |
hasread += canput; |
162 |
char *end = strpbrk(line, "\r\n"); |
138 |
hasput += willput; |
163 |
/* and replace by string terminator */ |
139 |
|
164 |
if (end != NULL) { |
140 |
/* Ignore the "canput" bytes */ |
165 |
*end = '\0'; |
141 |
fcgid_ignore_bytes(ctx, canput); |
166 |
} else { |
142 |
} |
167 |
/* did not detect anymore newlines */ |
143 |
|
168 |
if(line != logbuf && hasread < bodysize){ |
144 |
/* Now I get the log data, write log and release the buffer */ |
169 |
/* if not yet done with the body because buffer was |
145 |
line = logbuf; |
170 |
* full AND we did detect at least one linebreak |
146 |
while (*line) { |
171 |
* then we try to get more STDERR data so we won't |
147 |
char *end = strpbrk(line, "\r\n"); |
172 |
* break up errorlines unnessesary */ |
148 |
|
173 |
hasputbuf = strlen(line); |
149 |
if (end != NULL) { |
174 |
memmove(logbuf, line, hasputbuf); |
150 |
*end = '\0'; |
175 |
memset(logbuf + hasputbuf, 0, |
151 |
} |
176 |
APR_BUCKET_BUFF_SIZE - hasputbuf); |
152 |
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, ctx->ipc.request, |
177 |
break; |
153 |
"mod_fcgid: stderr: %s", line); |
178 |
} |
154 |
if (end == NULL) { |
179 |
} |
155 |
break; |
180 |
ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, ctx->ipc.request, |
|
|
181 |
"mod_fcgid: stderr: %s", line); |
182 |
/* if we did not find \r or \n then we're done |
183 |
* (we hit the end of the logbuf) */ |
184 |
if (end == NULL) { |
185 |
/* 0-pad the logbuf */ |
186 |
memset(logbuf, 0, APR_BUCKET_BUFF_SIZE); |
187 |
hasputbuf = 0; |
188 |
break; |
189 |
} |
190 |
/* skip past our inserted string terminator */ |
191 |
++end; |
192 |
/* and skip all \r or \n characters at the beginning |
193 |
* of the next part of logbuf */ |
194 |
line = end + strspn(end, "\r\n"); |
195 |
if(!*line && hasread < bodysize){ |
196 |
/* okay, our logbuf ends with a newline but we still |
197 |
* need to process some more data. This is an edge |
198 |
* case but we need to clear the logbuf. */ |
199 |
memset(logbuf, 0, APR_BUCKET_BUFF_SIZE); |
200 |
hasputbuf = 0; |
201 |
} |
156 |
} |
202 |
} |
157 |
++end; |
203 |
|
158 |
line = end + strspn(end, "\r\n"); |
|
|
159 |
} |
204 |
} |
160 |
|
205 |
|
161 |
apr_bucket_free(logbuf); |
206 |
apr_bucket_free(logbuf); |