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

  ViewVC Help
Powered by ViewVC 1.1.5