/[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 - (hide 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 rabbi 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 weaselp 116 $Id: buffers.c,v 1.2 2002/07/29 23:52:00 weaselp Exp $ */
10 rabbi 1
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 weaselp 116 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 rabbi 1 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 weaselp 116 for (i = 0; i < line->length; i++) {
483     if (line->data[i] == ' ' || line->data[i] == '\t')
484     break;
485 rabbi 1 if (line->data[i] == ':') {
486     err = 0;
487     break;
488     }
489 weaselp 116 }
490 rabbi 1 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