/[pkg-mixmaster]/trunk/Mix/Src/buffers.c
ViewVC logotype

Contents of /trunk/Mix/Src/buffers.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 116 - (show annotations) (download)
Mon Jul 29 23:52:00 2002 UTC (10 years, 9 months ago) by weaselp
File MIME type: text/plain
File size: 14644 byte(s)
Make smtp sending similar to local /usr/lib/sendmail sending (wrt header/body seperation; Closes: #482052).
Add X-Loop header on mailbox forwarded messages.
1 /* Mixmaster version 3 -- (C) 1999 Anonymizer Inc.
2
3 Mixmaster may be redistributed and modified under certain conditions.
4 This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF
5 ANY KIND, either express or implied. See the file COPYRIGHT for
6 details.
7
8 Dynamically allocated buffers
9 $Id: buffers.c,v 1.2 2002/07/29 23:52:00 weaselp Exp $ */
10
11
12 #include "mix3.h"
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <ctype.h>
17 #include <stdarg.h>
18 #ifdef WIN32
19 #include <io.h>
20 #endif
21 #include <assert.h>
22
23 static void fail(void)
24 {
25 errlog(ERRORMSG, "Out of memory!\n");
26 abort();
27 }
28
29 #define space 128 /* allocate some additional space */
30
31 static void alloc(BUFFER *b)
32 {
33 b->data = malloc(space);
34 if (b->data == NULL)
35 fail();
36 b->data[0] = 0;
37 b->size = space;
38 }
39
40 #undef buf_new /* DEBUG */
41 BUFFER *buf_new(void)
42 {
43 BUFFER *b;
44
45 b = malloc(sizeof(BUFFER));
46 if (b == NULL)
47 fail();
48 alloc(b);
49 b->length = 0;
50 b->ptr = 0;
51 b->sensitive = 0;
52
53 return (b);
54 }
55
56 #ifdef DEBUG
57 static void sanity_check(BUFFER *b)
58 {
59 assert(b != NULL);
60 assert(b->size > 0);
61 assert(b->data != NULL);
62 assert(b->length >= 0 && b->length < b->size);
63 assert(b->ptr >= 0 && b->ptr <= b->length);
64 }
65 #else
66 #define sanity_check(arg)
67 #endif
68
69 int buf_reset(BUFFER *buffer)
70 {
71 sanity_check(buffer);
72
73 buffer->length = 0;
74 buffer->ptr = 0;
75 if (buffer->sensitive)
76 memset(buffer->data, 0, buffer->size);
77 free(buffer->data);
78 alloc(buffer);
79 return (0);
80 }
81
82 int buf_free(BUFFER *buffer)
83 {
84 int err = 0;
85
86 if (buffer->sensitive)
87 memset(buffer->data, 0, buffer->size);
88 free(buffer->data);
89 free(buffer);
90 return (err);
91 }
92
93 int buf_clear(BUFFER *buffer)
94 {
95 sanity_check(buffer);
96 buffer->data[0] = '\0';
97 buffer->length = 0;
98 buffer->ptr = 0;
99 return (0);
100 }
101
102 int buf_append(BUFFER *buffer, byte *msg, int len)
103 {
104 assert(len >= 0);
105 sanity_check(buffer);
106
107 if (buffer->length + len >= buffer->size) {
108 register byte *new;
109 register long newsize;
110
111 newsize = 2 * buffer->length; /* double buffer size */
112 if (newsize < buffer->length + len + space)
113 newsize = buffer->length + len + space;
114 new = malloc(newsize);
115 if (new == NULL)
116 fail();
117 memcpy(new, buffer->data, buffer->length);
118 if (buffer->sensitive)
119 memset(buffer->data, 0, buffer->size);
120 free(buffer->data);
121 buffer->data = new;
122 buffer->size = newsize;
123 }
124 if (msg != NULL)
125 memcpy(buffer->data + buffer->length, msg, len);
126 buffer->length += len;
127
128 buffer->data[buffer->length] = 0;
129 return (0);
130 }
131
132 int buf_appendrnd(BUFFER *to, int n)
133 {
134 buf_append(to, NULL, n);
135 rnd_bytes(to->data + to->length - n, n);
136 return (0);
137 }
138
139 int buf_appendzero(BUFFER *to, int n)
140 {
141 buf_append(to, NULL, n);
142 memset(to->data + to->length - n, 0, n);
143 return (0);
144 }
145
146 int buf_setrnd(BUFFER *b, int n)
147 {
148 buf_prepare(b, n);
149 rnd_bytes(b->data, n);
150 return (0);
151 }
152
153 int buf_cat(BUFFER *to, BUFFER *from)
154 {
155 return (buf_append(to, from->data, from->length));
156 }
157
158 int buf_set(BUFFER *to, BUFFER *from)
159 {
160 buf_reset(to);
161 return (buf_cat(to, from));
162 }
163
164 int buf_appendc(BUFFER *to, byte b)
165 {
166 return (buf_append(to, &b, 1));
167 }
168
169 int buf_rest(BUFFER *to, BUFFER *from)
170 {
171 assert(from != to);
172 return (buf_append(to, from->data + from->ptr, from->length - from->ptr));
173 }
174
175 int buf_appends(BUFFER *buffer, char *s)
176 {
177 return (buf_append(buffer, s, strlen(s)));
178 }
179
180 int buf_sets(BUFFER *buffer, char *s)
181 {
182 buf_clear(buffer);
183 return (buf_appends(buffer, s));
184 }
185
186 int buf_setc(BUFFER *buffer, byte c)
187 {
188 buf_clear(buffer);
189 return (buf_appendc(buffer, c));
190 }
191
192 int buf_nl(BUFFER *b)
193 {
194 return (buf_append(b, "\n", 1));
195 }
196
197 int buf_vappendf(BUFFER *b, char *fmt, va_list args)
198 {
199 for (; *fmt != '\0'; fmt++)
200 if (*fmt == '%') {
201 int lzero = 0;
202 int longvar = 0;
203 int len = 0;
204
205 for (;;) {
206 if (*++fmt == '\0')
207 return (-1);
208 if (*fmt == '%') {
209 buf_appendc(b, '%');
210 break;
211 } else if (*fmt == 'b') { /* extension of printf */
212 buf_cat(b, va_arg(args, BUFFER *));
213
214 break;
215 } else if (*fmt == 'c') {
216 buf_appendc(b, va_arg(args, int));
217
218 break;
219 } else if (*fmt == 's') {
220 buf_appends(b, va_arg(args, char *));
221
222 break;
223 } else if (*fmt == 'd' || *fmt == 'X') {
224 int base, val, sign = 0;
225 BUFFER *out;
226
227 out = buf_new();
228 base = *fmt == 'd' ? 10 : 16;
229 if (longvar)
230 val = va_arg(args, long);
231
232 else
233 val = va_arg(args, int);
234
235 if (val < 0)
236 sign = 1, val = -val;
237 do {
238 if (val % base > 9)
239 buf_appendc(out, val % base - 10 + 'A');
240 else
241 buf_appendc(out, val % base + '0');
242 val /= base;
243 } while (val > 0);
244 if (sign)
245 len--;
246 while (len-- > out->length)
247 buf_appendc(b, lzero ? '0' : ' ');
248 if (sign)
249 buf_appendc(b, '-');
250 for (len = out->length - 1; len >= 0; len--)
251 buf_appendc(b, out->data[len]);
252 buf_free(out);
253 break;
254 } else if (*fmt == 'l')
255 longvar = 1;
256 else if (*fmt == '0' && len == 0)
257 lzero = 1;
258 else if (isdigit(*fmt))
259 len = len * 10 + *fmt - '0';
260 else
261 assert(0);
262 }
263 } else
264 buf_appendc(b, *fmt);
265 return (0);
266 }
267
268 int buf_setf(BUFFER *b, char *fmt, ...)
269 {
270 va_list args;
271 int ret;
272
273 va_start(args, fmt);
274 buf_clear(b);
275 ret = buf_vappendf(b, fmt, args);
276 va_end(args);
277 return (ret);
278 }
279
280 int buf_appendf(BUFFER *b, char *fmt, ...)
281 {
282 va_list args;
283 int ret;
284
285 va_start(args, fmt);
286 ret = buf_vappendf(b, fmt, args);
287 va_end(args);
288 return (ret);
289 }
290
291 int buf_pad(BUFFER *buffer, int size)
292 {
293 assert(size - buffer->length >= 0);
294 buf_appendrnd(buffer, size - buffer->length);
295 return (0);
296 }
297
298 int buf_prepare(BUFFER *buffer, int size)
299 {
300 buf_clear(buffer);
301 buf_append(buffer, NULL, size);
302 return (0);
303 }
304
305 int buf_read(BUFFER *outmsg, FILE *infile)
306 {
307 char buf[BUFSIZE];
308 int n;
309 int err = -1;
310
311 assert(infile != NULL);
312 sanity_check(outmsg);
313
314 for (;;) {
315 n = fread(buf, 1, BUFSIZE, infile);
316 if (n > 0)
317 err = 0;
318 buf_append(outmsg, buf, n);
319 if (n < BUFSIZE)
320 break;
321 #ifdef BUFFER_MAX
322 if (outmsg->length > BUFFER_MAX) {
323 errlog(ERRORMSG, "Message file too large. Giving up.\n");
324 return (1);
325 }
326 #endif
327 }
328
329 #ifdef WIN32
330 if (isatty(fileno(infile)) && isatty(fileno(stdout)))
331 printf("\n");
332 #endif
333
334 return (err);
335 }
336
337 int buf_write(BUFFER *buffer, FILE *out)
338 {
339 assert(out != NULL);
340 sanity_check(buffer);
341
342 return (fwrite(buffer->data, 1, buffer->length, out) == buffer->length
343 ? 0 : -1);
344 }
345
346 int buf_rewind(BUFFER *buffer)
347 {
348 sanity_check(buffer);
349
350 buffer->ptr = 0;
351 return (0);
352 }
353
354 int buf_get(BUFFER *buffer, BUFFER *to, int n)
355 {
356 sanity_check(buffer);
357 sanity_check(to);
358 assert(n > 0);
359 assert(buffer != to);
360
361 buf_clear(to);
362 if (buffer->length - buffer->ptr < n)
363 return (-1);
364 buf_append(to, buffer->data + buffer->ptr, n);
365 buffer->ptr += n;
366 return (0);
367 }
368
369 int buf_getc(BUFFER *buffer)
370 {
371 sanity_check(buffer);
372 if (buffer->ptr == buffer->length)
373 return (-1);
374 else
375 return (buffer->data[buffer->ptr++]);
376 }
377
378 void buf_ungetc(BUFFER *buffer)
379 {
380 sanity_check(buffer);
381 if (buffer->ptr > 0)
382 buffer->ptr--;
383 }
384
385 int buf_getline(BUFFER *buffer, BUFFER *line)
386 {
387 register int i;
388 int ret = 0;
389 int nl = 0;
390
391 sanity_check(buffer);
392
393 if (line != NULL)
394 buf_clear(line);
395 if (buffer->ptr == buffer->length)
396 return (-1);
397
398 for (i = buffer->ptr; i < buffer->length; i++) {
399 if (buffer->data[i] > '\r')
400 continue;
401 if (buffer->data[i] == '\0' || buffer->data[i] == '\n') {
402 nl = 1;
403 break;
404 }
405 if (buffer->data[i] == '\r' &&
406 i + 1 <= buffer->length && buffer->data[i + 1] == '\n') {
407 nl = 2;
408 break;
409 }
410 }
411
412 if (line != NULL)
413 buf_append(line, buffer->data + buffer->ptr, i - buffer->ptr);
414 if (i == buffer->ptr)
415 ret = 1;
416 buffer->ptr = i + nl;
417
418 return (ret);
419 }
420
421 int buf_chop(BUFFER *b)
422 {
423 int i;
424
425 sanity_check(b);
426
427 for (i = 0; i < b->length; i++)
428 if (b->data[i] == '\0' || b->data[i] == '\n' ||
429 (b->data[i] == '\r' && i + 1 < b->length &&
430 b->data[i + 1] == '\n'))
431 b->length = i;
432 b->data[b->length] = 0;
433 return (0);
434 }
435
436 int buf_isheader(BUFFER *buffer)
437 {
438 BUFFER *line;
439 long p;
440 int i;
441 int err;
442 int ret;
443
444 line = buf_new();
445 p = buffer->ptr;
446 ret = 0;
447 err = buf_getline(buffer, line);
448 if (err != 0)
449 goto end;
450
451 for (i = 0; i < line->length; i++) {
452 if (line->data[i] == ' ' || line->data[i] == '\t')
453 break;
454 if (line->data[i] == ':') {
455 ret = 1;
456 break;
457 }
458 }
459
460 end:
461 buffer->ptr = p;
462 buf_free(line);
463 return(ret);
464 }
465
466 int buf_getheader(BUFFER *buffer, BUFFER *field, BUFFER *content)
467 {
468 BUFFER *line;
469 long p;
470 int i;
471 int err;
472
473 line = buf_new();
474 buf_reset(field);
475 buf_reset(content);
476
477 err = buf_getline(buffer, line);
478 if (err != 0)
479 goto end;
480
481 err = -1;
482 for (i = 0; i < line->length; i++) {
483 if (line->data[i] == ' ' || line->data[i] == '\t')
484 break;
485 if (line->data[i] == ':') {
486 err = 0;
487 break;
488 }
489 }
490 if (err == -1) {
491 /* badly formatted message -- try to process anyway */
492 buf_sets(field, "X-Invalid");
493 buf_set(content, line);
494 err = 0;
495 goto end;
496 }
497 buf_append(field, line->data, i);
498 if (i < line->length)
499 i++;
500 else
501 err = 1;
502 while (i < line->length &&
503 (line->data[i] == ' ' || line->data[i] == '\t'))
504 i++;
505 buf_append(content, line->data + i, line->length - i);
506
507 for (;;) {
508 p = buffer->ptr;
509 if (buf_getline(buffer, line) != 0)
510 break;
511 if (line->data[0] != ' ' && line->data[0] != '\t')
512 break;
513 #if 1
514 buf_nl(content);
515 buf_cat(content, line);
516 #else
517 buf_appendc(content, ' ');
518 buf_appends(content, line->data + 1);
519 #endif
520 }
521 buffer->ptr = p;
522 end:
523 buf_free(line);
524 return (err);
525 }
526
527 int buf_appendheader(BUFFER *buffer, BUFFER *field, BUFFER *content)
528 {
529 return buf_appendf(buffer, "%b: %b\n", field, content);
530 }
531
532 int buf_lookahead(BUFFER *buffer, BUFFER *line)
533 {
534 long p;
535 int e;
536
537 p = buffer->ptr;
538 e = buf_getline(buffer, line);
539 buffer->ptr = p;
540 return (e);
541 }
542
543 int buf_eq(BUFFER *b1, BUFFER *b2)
544 {
545 sanity_check(b1);
546 sanity_check(b2);
547
548 if (b1->length != b2->length)
549 return (0);
550 if (b1->length > 0 && memcmp(b1->data, b2->data, b1->length) != 0)
551 return (0);
552 return (1);
553 }
554
555 int buf_ieq(BUFFER *b1, BUFFER *b2)
556 {
557 int i;
558 sanity_check(b1);
559 sanity_check(b2);
560
561 if (b1->length != b2->length)
562 return (0);
563 for (i = 0; i < b1->length; i++)
564 if (tolower(b1->data[i]) != tolower(b2->data[i]))
565 return (0);
566 return (1);
567 }
568
569 void buf_move(BUFFER *dest, BUFFER *src)
570 /* equivalent to buf_set(dest, src); buf_reset(src); */
571 {
572 BUFFER temp;
573 sanity_check(src);
574 buf_reset(dest);
575 temp.data = dest->data, temp.size = dest->size;
576 dest->data = src->data, dest->size = src->size, dest->length = src->length;
577 src->data = temp.data, src->size = temp.size, src->length = 0;
578 dest->ptr = 0, src->ptr = 0;
579 }
580
581 int buf_appendl(BUFFER *b, long l)
582 {
583 buf_appendc(b, (l >> 24) & 255);
584 buf_appendc(b, (l >> 16) & 255);
585 buf_appendc(b, (l >> 8) & 255);
586 buf_appendc(b, l & 255);
587 return (0);
588 }
589
590 int buf_appendl_lo(BUFFER *b, long l)
591 {
592 buf_appendc(b, l & 255);
593 buf_appendc(b, (l >> 8) & 255);
594 buf_appendc(b, (l >> 16) & 255);
595 buf_appendc(b, (l >> 24) & 255);
596 return (0);
597 }
598
599 long buf_getl(BUFFER *b)
600 {
601 long l;
602
603 if (b->ptr + 4 > b->length)
604 return (-1);
605 l = buf_getc(b) << 24;
606 l += buf_getc(b) << 16;
607 l += buf_getc(b) << 8;
608 l += buf_getc(b);
609 return (l);
610 }
611
612 long buf_getl_lo(BUFFER *b)
613 {
614 long l;
615
616 if (b->ptr + 4 > b->length)
617 return (-1);
618 l = buf_getc(b);
619 l += buf_getc(b) << 8;
620 l += buf_getc(b) << 16;
621 l += buf_getc(b) << 24;
622
623 return (l);
624 }
625
626 int buf_appendi(BUFFER *b, int i)
627 {
628 buf_appendc(b, (i >> 8) & 255);
629 buf_appendc(b, i & 255);
630 return (0);
631 }
632
633 int buf_appendi_lo(BUFFER *b, int i)
634 {
635 buf_appendc(b, i & 255);
636 buf_appendc(b, (i >> 8) & 255);
637 return (0);
638 }
639
640 int buf_geti(BUFFER *b)
641 {
642 int i;
643
644 if (b->ptr + 2 > b->length)
645 return (-1);
646 i = buf_getc(b) << 8;
647 i += buf_getc(b);
648 return (i);
649 }
650
651 int buf_geti_lo(BUFFER *b)
652 {
653 int i;
654
655 if (b->ptr + 2 > b->length)
656 return (-1);
657 i = buf_getc(b);
658 i += buf_getc(b) << 8;
659 return (i);
660 }
661
662 int buf_getb(BUFFER *b, BUFFER *p)
663 {
664 long l;
665
666 l = buf_getl(b);
667 return (buf_get(b, p, l));
668 }
669
670 int buf_appendb(BUFFER *b, BUFFER *p)
671 {
672 long l;
673
674 l = p->length;
675 buf_appendl(b, l);
676 return (buf_cat(b, p));
677 }
678
679 int bufleft(BUFFER *b, char *k) {
680 return(strleft(b->data, k));
681 }
682
683 int bufileft(BUFFER *b, char *k) {
684 return(strileft(b->data, k));
685 }
686
687 int buffind(BUFFER *b, char *k) {
688 return(strfind(b->data, k));
689 }
690
691 int bufifind(BUFFER *b, char *k) {
692 return(strifind(b->data, k));
693 }
694
695 int bufiright(BUFFER *b, char *k) {
696 int l = strlen(k);
697 if (l >= b->length)
698 return (strieq(b->data + b->length - l, k));
699 return(0);
700 }
701
702 int bufeq(BUFFER *b, char *k) {
703 return(streq(b->data, k));
704 }
705
706 int bufieq(BUFFER *b, char *k) {
707 return(strieq(b->data, k));
708 }
709
710 /* void buf_cut_out(BUFFER *buffer, BUFFER *cut_out, BUFFER *rest,
711 * int from, int len);
712 *
713 * Cut a chunk out of the buffer.
714 *
715 * Starting with from, len bytes are cut out of buffer. The chunk
716 * of text that has been cut out is returned in cut_out, the
717 * remainings of buffer are returned in rest.
718 *
719 * This function was added by Gerd Beuster. (gb@uni-koblenz.de)
720 */
721
722 void buf_cut_out(BUFFER *buffer, BUFFER *cut_out, BUFFER *rest,
723 int from, int len){
724
725 assert((len >= 0) && (from >= 0));
726 assert(from+len <= buffer->length);
727 assert(cut_out != rest);
728
729 buffer->ptr = 0;
730 if(from > 0)
731 buf_get(buffer, rest, from);
732 buf_get(buffer, cut_out, len);
733 buf_rest(rest, buffer);
734 }
735
736
737 #ifdef DEBUG
738 /* check for memory leaks */
739 #undef malloc
740 #undef free
741 void *malloc(size_t size);
742 void free(void *ptr);
743 #define max 100000
744 static int n=0;
745 static void *m[max];
746 static char *mm[max];
747
748 void mix3_leaks(void) {
749 int i, ok=1;
750 for (i = 0; i < n; i++)
751 if (m[i]) {
752 fprintf(stderr, "Leak [%d] %s\n", i, mm[i]);
753 ok = 0;
754 }
755 if (ok)
756 fprintf(stderr, "No memory leaks.\n");
757 }
758
759 void *mix3_malloc(size_t size) {
760 void *ptr;
761 if (n == 0)
762 atexit(mix3_leaks);
763 ptr = malloc(size);
764 if (n >= max) abort();
765 m[n++] = ptr;
766 mm[n] = "?";
767 return(ptr);
768 }
769
770 void mix3_free(void *ptr) {
771 int i;
772 for (i = 0; i < n; i++)
773 if (m[i] == ptr) {
774 m[i] = 0;
775 break;
776 }
777 free(ptr);
778 }
779
780 BUFFER *mix3_bufnew(char *file, int line, char *func) {
781 mm[n] = malloc(strlen(file) + strlen(func) + 15);
782 sprintf(mm[n], "in %s %s:%d", func, file, line);
783 return(buf_new());
784 }
785 #endif /* DEBUG */

  ViewVC Help
Powered by ViewVC 1.1.5