blob: c128bb9a357d4f8149eeabc05f98f41304e35066 [file] [log] [blame]
Willy Tarreaubaaee002006-06-26 02:48:02 +02001/*
2 * Buffer management functions.
3 *
Willy Tarreaub97f1992010-02-25 23:54:31 +01004 * Copyright 2000-2010 Willy Tarreau <w@1wt.eu>
Willy Tarreaubaaee002006-06-26 02:48:02 +02005 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Krzysztof Piotr Oledzkiba8d7d32009-10-10 21:06:03 +020013#include <ctype.h>
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010014#include <stdarg.h>
15#include <stdio.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020016#include <string.h>
Willy Tarreaue3ba5f02006-06-29 18:54:54 +020017
18#include <common/config.h>
Willy Tarreau7341d942007-05-13 19:56:02 +020019#include <common/memory.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020020#include <proto/buffers.h>
Willy Tarreau27a674e2009-08-17 07:23:33 +020021#include <types/global.h>
Willy Tarreaubaaee002006-06-26 02:48:02 +020022
Willy Tarreau7341d942007-05-13 19:56:02 +020023struct pool_head *pool2_buffer;
24
25
26/* perform minimal intializations, report 0 in case of error, 1 if OK. */
27int init_buffer()
28{
Willy Tarreau27a674e2009-08-17 07:23:33 +020029 pool2_buffer = create_pool("buffer", sizeof(struct buffer) + global.tune.bufsize, MEM_F_SHARED);
Willy Tarreau7341d942007-05-13 19:56:02 +020030 return pool2_buffer != NULL;
31}
32
Willy Tarreaubaaee002006-06-26 02:48:02 +020033
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020034/* writes <len> bytes from message <msg> to buffer <buf>. Returns -1 in case of
Willy Tarreau078e2942009-08-18 07:19:39 +020035 * success, -2 if the message is larger than the buffer size, or the number of
36 * bytes available otherwise. The send limit is automatically adjusted with the
37 * amount of data written. FIXME-20060521: handle unaligned data.
Willy Tarreaubaaee002006-06-26 02:48:02 +020038 */
39int buffer_write(struct buffer *buf, const char *msg, int len)
40{
41 int max;
42
Willy Tarreauaeac3192009-08-31 08:09:57 +020043 if (len == 0)
44 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +020045
Willy Tarreau078e2942009-08-18 07:19:39 +020046 if (len > buf->size) {
47 /* we can't write this chunk and will never be able to, because
48 * it is larger than the buffer. This must be reported as an
49 * error. Then we return -2 so that writers that don't care can
50 * ignore it and go on, and others can check for this value.
51 */
52 return -2;
53 }
54
Willy Tarreauaeac3192009-08-31 08:09:57 +020055 max = buffer_realign(buf);
56
Willy Tarreaubaaee002006-06-26 02:48:02 +020057 if (len > max)
58 return max;
59
60 memcpy(buf->r, msg, len);
61 buf->l += len;
Willy Tarreauf890dc92008-12-13 21:12:26 +010062 buf->send_max += len;
Willy Tarreaubaaee002006-06-26 02:48:02 +020063 buf->r += len;
Willy Tarreau35d66b02007-01-02 00:28:21 +010064 buf->total += len;
Willy Tarreaua07a34e2009-08-16 23:27:46 +020065 if (buf->r == buf->data + buf->size)
Willy Tarreaubaaee002006-06-26 02:48:02 +020066 buf->r = buf->data;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020067
Willy Tarreauba0b63d2009-09-20 08:09:44 +020068 buf->flags &= ~(BF_OUT_EMPTY|BF_FULL);
Willy Tarreau7c3c5412009-12-13 15:53:05 +010069 if (buf->l >= buffer_max_len(buf))
Willy Tarreaue393fe22008-08-16 22:18:07 +020070 buf->flags |= BF_FULL;
71
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020072 return -1;
Willy Tarreaubaaee002006-06-26 02:48:02 +020073}
74
Willy Tarreauaeac3192009-08-31 08:09:57 +020075/* Try to write string <str> into buffer <buf> after length controls. This
76 * is the equivalent of buffer_write() except that to_forward and send_max
77 * are updated and that max_len is respected. Returns -1 in case of success,
Willy Tarreau078e2942009-08-18 07:19:39 +020078 * -2 if it is larger than the buffer size, or the number of bytes available
Willy Tarreauaeac3192009-08-31 08:09:57 +020079 * otherwise. The send limit is automatically adjusted with the amount of data
Willy Tarreau078e2942009-08-18 07:19:39 +020080 * written.
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010081 */
Willy Tarreau9bcc91e2009-10-10 18:01:44 +020082int buffer_feed2(struct buffer *buf, const char *str, int len)
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010083{
84 int max;
85
Willy Tarreauaeac3192009-08-31 08:09:57 +020086 if (len == 0)
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +020087 return -1;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +010088
Willy Tarreau591fedc2010-08-10 15:28:21 +020089 max = buffer_max_len(buf);
90 if (len > max - buf->l) {
91 /* we can't write this chunk right now because the buffer is
92 * almost full or because the block is too large. Return the
93 * available space or -2 if impossible.
Willy Tarreau078e2942009-08-18 07:19:39 +020094 */
Willy Tarreau591fedc2010-08-10 15:28:21 +020095 if (len > max)
96 return -2;
Willy Tarreau078e2942009-08-18 07:19:39 +020097
Willy Tarreau591fedc2010-08-10 15:28:21 +020098 return max - buf->l;
99 }
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100100
Willy Tarreau591fedc2010-08-10 15:28:21 +0200101 /* OK so the data fits in the buffer in one or two blocks */
102 max = buffer_contig_space_with_len(buf, max);
103 memcpy(buf->r, str, MIN(len, max));
Willy Tarreauaeac3192009-08-31 08:09:57 +0200104 if (len > max)
Willy Tarreau591fedc2010-08-10 15:28:21 +0200105 memcpy(buf->data, str + max, len - max);
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100106
Willy Tarreauaeac3192009-08-31 08:09:57 +0200107 buf->l += len;
108 buf->r += len;
109 buf->total += len;
Willy Tarreau31971e52009-09-20 12:07:52 +0200110 if (buf->to_forward) {
111 unsigned long fwd = len;
112 if (buf->to_forward != BUF_INFINITE_FORWARD) {
113 if (fwd > buf->to_forward)
114 fwd = buf->to_forward;
115 buf->to_forward -= fwd;
116 }
117 buf->send_max += fwd;
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200118 buf->flags &= ~BF_OUT_EMPTY;
Willy Tarreauaeac3192009-08-31 08:09:57 +0200119 }
120
Willy Tarreau591fedc2010-08-10 15:28:21 +0200121 if (buf->r >= buf->data + buf->size)
122 buf->r -= buf->size;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +0200123
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200124 buf->flags &= ~BF_FULL;
Willy Tarreau7c3c5412009-12-13 15:53:05 +0100125 if (buf->l >= buffer_max_len(buf))
Willy Tarreaue393fe22008-08-16 22:18:07 +0200126 buf->flags |= BF_FULL;
127
Willy Tarreaufb0e9202009-09-23 23:47:55 +0200128 /* notify that some data was read from the SI into the buffer */
129 buf->flags |= BF_READ_PARTIAL;
Krzysztof Piotr Oledzki8e4b21d2008-04-20 21:34:47 +0200130 return -1;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100131}
132
Willy Tarreau4fe7a2e2009-09-01 06:41:32 +0200133/* Get one text line out of a buffer from a stream interface.
134 * Return values :
135 * >0 : number of bytes read. Includes the \n if present before len or end.
136 * =0 : no '\n' before end found. <buf> is undefined.
137 * <0 : no more bytes readable + shutdown set.
138 * The buffer status is not changed. The caller must call buffer_skip() to
139 * update it. The '\n' is waited for as long as neither the buffer nor the
140 * output are full. If either of them is full, the string may be returned
141 * as is, without the '\n'.
142 */
143int buffer_si_peekline(struct buffer *buf, char *str, int len)
144{
145 int ret, max;
146 char *p;
147
148 ret = 0;
149 max = len;
150 if (!buf->send_max) {
151 if (buf->flags & (BF_SHUTW|BF_SHUTW_NOW))
152 ret = -1;
153 goto out;
154 }
155
156 p = buf->w;
157
158 if (max > buf->send_max) {
159 max = buf->send_max;
Willy Tarreau2e1dd3d2009-09-23 22:56:07 +0200160 str[max-1] = 0;
Willy Tarreau4fe7a2e2009-09-01 06:41:32 +0200161 }
162 while (max) {
163 *str++ = *p;
164 ret++;
165 max--;
166
167 if (*p == '\n')
168 break;
169 p++;
170 if (p == buf->data + buf->size)
171 p = buf->data;
172 }
Willy Tarreau2e1dd3d2009-09-23 22:56:07 +0200173 if (ret > 0 && ret < len && ret < buf->send_max &&
174 *(str-1) != '\n' &&
175 !(buf->flags & (BF_SHUTW|BF_SHUTW_NOW)))
Willy Tarreau4fe7a2e2009-09-01 06:41:32 +0200176 ret = 0;
177 out:
178 if (max)
179 *str = 0;
180 return ret;
181}
182
Willy Tarreaubaaee002006-06-26 02:48:02 +0200183/*
184 * this function writes the string <str> at position <pos> which must be in buffer <b>,
185 * and moves <end> just after the end of <str>.
Willy Tarreaubbfa7932010-01-25 01:49:57 +0100186 * <b>'s parameters (l, r, lr) are recomputed to be valid after the shift.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200187 * the shift value (positive or negative) is returned.
188 * If there's no space left, the move is not done.
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200189 * The function does not adjust ->send_max nor BF_OUT_EMPTY because it does not
190 * make sense to use it on data scheduled to be sent.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200191 *
192 */
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100193int buffer_replace(struct buffer *b, char *pos, char *end, const char *str)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200194{
195 int delta;
196 int len;
197
198 len = strlen(str);
199 delta = len - (end - pos);
200
Willy Tarreaua07a34e2009-08-16 23:27:46 +0200201 if (delta + b->r >= b->data + b->size)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200202 return 0; /* no space left */
203
Willy Tarreaubbfa7932010-01-25 01:49:57 +0100204 if (delta + b->r > b->w && b->w >= b->r && b->l)
205 return 0; /* no space left before wrapping data */
206
Willy Tarreaubaaee002006-06-26 02:48:02 +0200207 /* first, protect the end of the buffer */
Willy Tarreau019fd5b2009-12-28 18:37:54 +0100208 memmove(end + delta, end, b->r - end);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200209
210 /* now, copy str over pos */
211 memcpy(pos, str,len);
212
213 /* we only move data after the displaced zone */
214 if (b->r > pos) b->r += delta;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200215 if (b->lr > pos) b->lr += delta;
216 b->l += delta;
217
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200218 b->flags &= ~BF_FULL;
Willy Tarreaue393fe22008-08-16 22:18:07 +0200219 if (b->l == 0)
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200220 b->r = b->w = b->lr = b->data;
Willy Tarreau7c3c5412009-12-13 15:53:05 +0100221 if (b->l >= buffer_max_len(b))
Willy Tarreaue393fe22008-08-16 22:18:07 +0200222 b->flags |= BF_FULL;
223
Willy Tarreaubaaee002006-06-26 02:48:02 +0200224 return delta;
225}
226
227/*
228 * same except that the string length is given, which allows str to be NULL if
Willy Tarreauf890dc92008-12-13 21:12:26 +0100229 * len is 0. The send limit is *not* adjusted.
Willy Tarreaubaaee002006-06-26 02:48:02 +0200230 */
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100231int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200232{
233 int delta;
234
235 delta = len - (end - pos);
236
Willy Tarreaua07a34e2009-08-16 23:27:46 +0200237 if (delta + b->r >= b->data + b->size)
Willy Tarreaubaaee002006-06-26 02:48:02 +0200238 return 0; /* no space left */
239
Willy Tarreaubbfa7932010-01-25 01:49:57 +0100240 if (delta + b->r > b->w && b->w >= b->r && b->l)
241 return 0; /* no space left before wrapping data */
242
Willy Tarreaubaaee002006-06-26 02:48:02 +0200243 /* first, protect the end of the buffer */
Willy Tarreau019fd5b2009-12-28 18:37:54 +0100244 memmove(end + delta, end, b->r - end);
Willy Tarreaubaaee002006-06-26 02:48:02 +0200245
246 /* now, copy str over pos */
247 if (len)
248 memcpy(pos, str, len);
249
250 /* we only move data after the displaced zone */
251 if (b->r > pos) b->r += delta;
Willy Tarreaubaaee002006-06-26 02:48:02 +0200252 if (b->lr > pos) b->lr += delta;
253 b->l += delta;
254
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200255 b->flags &= ~BF_FULL;
Willy Tarreaue393fe22008-08-16 22:18:07 +0200256 if (b->l == 0)
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200257 b->r = b->w = b->lr = b->data;
Willy Tarreau7c3c5412009-12-13 15:53:05 +0100258 if (b->l >= buffer_max_len(b))
Willy Tarreaue393fe22008-08-16 22:18:07 +0200259 b->flags |= BF_FULL;
260
Willy Tarreaubaaee002006-06-26 02:48:02 +0200261 return delta;
262}
263
264
265/*
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100266 * Inserts <str> followed by "\r\n" at position <pos> in buffer <b>. The <len>
267 * argument informs about the length of string <str> so that we don't have to
268 * measure it. It does not include the "\r\n". If <str> is NULL, then the buffer
269 * is only opened for len+2 bytes but nothing is copied in. It may be useful in
Willy Tarreauf890dc92008-12-13 21:12:26 +0100270 * some circumstances. The send limit is *not* adjusted.
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100271 *
272 * The number of bytes added is returned on success. 0 is returned on failure.
273 */
274int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len)
275{
276 int delta;
277
278 delta = len + 2;
279
Willy Tarreaua07a34e2009-08-16 23:27:46 +0200280 if (delta + b->r >= b->data + b->size)
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100281 return 0; /* no space left */
282
283 /* first, protect the end of the buffer */
Willy Tarreau019fd5b2009-12-28 18:37:54 +0100284 memmove(pos + delta, pos, b->r - pos);
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100285
286 /* now, copy str over pos */
287 if (len && str) {
288 memcpy(pos, str, len);
289 pos[len] = '\r';
290 pos[len + 1] = '\n';
291 }
292
293 /* we only move data after the displaced zone */
294 if (b->r > pos) b->r += delta;
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100295 if (b->lr > pos) b->lr += delta;
296 b->l += delta;
297
Willy Tarreauba0b63d2009-09-20 08:09:44 +0200298 b->flags &= ~BF_FULL;
Willy Tarreau7c3c5412009-12-13 15:53:05 +0100299 if (b->l >= buffer_max_len(b))
Willy Tarreaue393fe22008-08-16 22:18:07 +0200300 b->flags |= BF_FULL;
301
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100302 return delta;
303}
304
305
Willy Tarreaub97f1992010-02-25 23:54:31 +0100306/* Realigns a possibly non-contiguous buffer by bouncing bytes from source to
307 * destination. It does not use any intermediate buffer and does the move in
308 * place, though it will be slower than a simple memmove() on contiguous data,
309 * so it's desirable to use it only on non-contiguous buffers. No pointers are
310 * changed, the caller is responsible for that.
311 */
312void buffer_bounce_realign(struct buffer *buf)
313{
314 int advance, to_move;
315 char *from, *to;
316
317 advance = buf->data + buf->size - buf->w;
318 if (!advance)
319 return;
320
321 from = buf->w;
322 to_move = buf->l;
323 while (to_move) {
324 char last, save;
325
326 last = *from;
327 to = from + advance;
328 if (to >= buf->data + buf->size)
329 to -= buf->size;
330
331 while (1) {
332 save = *to;
333 *to = last;
334 last = save;
335 to_move--;
336 if (!to_move)
337 break;
338
339 /* check if we went back home after rotating a number of bytes */
340 if (to == from)
341 break;
342
343 /* if we ended up in the empty area, let's walk to next place. The
344 * empty area is either between buf->r and from or before from or
345 * after buf->r.
346 */
347 if (from > buf->r) {
348 if (to >= buf->r && to < from)
349 break;
350 } else if (from < buf->r) {
351 if (to < from || to >= buf->r)
352 break;
353 }
354
355 /* we have overwritten a byte of the original set, let's move it */
356 to += advance;
357 if (to >= buf->data + buf->size)
358 to -= buf->size;
359 }
360
361 from++;
362 if (from >= buf->data + buf->size)
363 from -= buf->size;
364 }
365}
366
367
Willy Tarreau4af6f3a2007-03-18 22:36:26 +0100368/*
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100369 * Does an snprintf() at the end of chunk <chk>, respecting the limit of
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200370 * at most chk->size chars. If the chk->len is over, nothing is added. Returns
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100371 * the new chunk size.
372 */
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200373int chunk_printf(struct chunk *chk, const char *fmt, ...)
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100374{
375 va_list argp;
Willy Tarreaudceaa082007-07-25 14:38:45 +0200376 int ret;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100377
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200378 if (!chk->str || !chk->size)
379 return 0;
380
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100381 va_start(argp, fmt);
Krzysztof Piotr Oledzki78abe612009-09-27 13:23:20 +0200382 ret = vsnprintf(chk->str + chk->len, chk->size - chk->len, fmt, argp);
383 if (ret >= chk->size - chk->len)
Willy Tarreaudceaa082007-07-25 14:38:45 +0200384 /* do not copy anything in case of truncation */
385 chk->str[chk->len] = 0;
386 else
387 chk->len += ret;
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100388 va_end(argp);
389 return chk->len;
390}
391
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100392/*
Krzysztof Piotr Oledzkiba8d7d32009-10-10 21:06:03 +0200393 * Encode chunk <src> into chunk <dst>, respecting the limit of at most
394 * chk->size chars. Replace non-printable or special chracters with "&#%d;".
395 * If the chk->len is over, nothing is added. Returns the new chunk size.
396 */
397int chunk_htmlencode(struct chunk *dst, struct chunk *src) {
398
399 int i, l;
400 int olen, free;
401 char c;
402
403 olen = dst->len;
404
405 for (i = 0; i < src->len; i++) {
406 free = dst->size - dst->len;
407
408 if (!free) {
409 dst->len = olen;
410 return dst->len;
411 }
412
413 c = src->str[i];
414
Willy Tarreau88e05812010-03-03 00:16:00 +0100415 if (!isascii(c) || !isprint((unsigned char)c) || c == '&' || c == '"' || c == '\'' || c == '<' || c == '>') {
Krzysztof Piotr Oledzkiba8d7d32009-10-10 21:06:03 +0200416 l = snprintf(dst->str + dst->len, free, "&#%u;", (unsigned char)c);
417
418 if (free < l) {
419 dst->len = olen;
420 return dst->len;
421 }
422
423 dst->len += l;
424 } else {
425 dst->str[dst->len] = c;
426 dst->len++;
427 }
428 }
429
430 return dst->len;
431}
432
433/*
434 * Encode chunk <src> into chunk <dst>, respecting the limit of at most
435 * chk->size chars. Replace non-printable or char passed in qc with "<%02X>".
436 * If the chk->len is over, nothing is added. Returns the new chunk size.
437 */
438int chunk_asciiencode(struct chunk *dst, struct chunk *src, char qc) {
439 int i, l;
440 int olen, free;
441 char c;
442
443 olen = dst->len;
444
445 for (i = 0; i < src->len; i++) {
446 free = dst->size - dst->len;
447
448 if (!free) {
449 dst->len = olen;
450 return dst->len;
451 }
452
453 c = src->str[i];
454
Willy Tarreau88e05812010-03-03 00:16:00 +0100455 if (!isascii(c) || !isprint((unsigned char)c) || c == '<' || c == '>' || c == qc) {
Krzysztof Piotr Oledzkiba8d7d32009-10-10 21:06:03 +0200456 l = snprintf(dst->str + dst->len, free, "<%02X>", (unsigned char)c);
457
458 if (free < l) {
459 dst->len = olen;
460 return dst->len;
461 }
462
463 dst->len += l;
464 } else {
465 dst->str[dst->len] = c;
466 dst->len++;
467 }
468 }
469
470 return dst->len;
471}
472
473/*
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100474 * Dumps part or all of a buffer.
475 */
476void buffer_dump(FILE *o, struct buffer *b, int from, int to)
477{
478 fprintf(o, "Dumping buffer %p\n", b);
Willy Tarreaue09e0ce2007-03-18 16:31:29 +0100479 fprintf(o, " data=%p l=%d r=%p w=%p lr=%p\n",
480 b->data, b->l, b->r, b->w, b->lr);
Willy Tarreau8d5d7f22007-01-21 19:16:41 +0100481
482 if (!to || to > b->l)
483 to = b->l;
484
485 fprintf(o, "Dumping contents from byte %d to byte %d\n", from, to);
486 for (; from < to; from++) {
487 if ((from & 15) == 0)
488 fprintf(o, " %04x: ", from);
489 fprintf(o, "%02x ", b->data[from]);
490 if ((from & 15) == 7)
491 fprintf(o, "- ");
492 else if (((from & 15) == 15) && (from != to-1))
493 fprintf(o, "\n");
494 }
495 fprintf(o, "\n--\n");
496}
497
Willy Tarreauc0dde7a2007-01-01 21:38:07 +0100498
499/*
Willy Tarreaubaaee002006-06-26 02:48:02 +0200500 * Local variables:
501 * c-indent-level: 8
502 * c-basic-offset: 8
503 * End:
504 */