bfb2dfb1003f567dee93a0196956f2e2d1040ae6
[infodrom/dtaus] / dtaus.c
1 /*
2     dtaus.c - Belegloser Datenträgeraustausch mit einer Bank
3     Copyright (c) 1996,8,2001-4  Martin Schulze <joey@infodrom.org>
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
18
19     $Id$
20  */
21
22 #include "dtaus.h"
23 #include "bigint.h"
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <time.h>
29 #include <malloc.h>
30
31 #define DEFAULT_EURO
32 #ifndef DEFAULT_EURO
33 int use_euro = 0;
34 #else
35 int use_euro = 1;
36 #endif
37
38 /*
39  *  First: Some control structures
40  */
41
42 typedef struct
43 {
44   char *name;
45   unsigned short int pos;
46   unsigned short int len;
47   int type;
48 } dtaus_record;
49
50 #define REC_A   1
51 #define REC_C   2
52 #define REC_E   3
53
54 #define REQ     1
55 #define OPT     2
56 #define IGN     3
57
58 dtaus_record recA[] = {
59   {"Art", 5, 2, REQ},
60   {"Name", 23, 27, REQ},
61   {"Konto", 60, 10, REQ},
62   {"BLZ", 7, 8, REQ},
63   {"Referenz", 70, 10, OPT},
64   {"Datum", 50, 6, IGN},
65   {"Ausfuehrung", 95, 8, OPT},
66   {"Currency", 127, 1, OPT},
67   {"Euro", 127, 1, OPT},
68   {"DM", 127, 1, OPT},
69   {NULL, 0, 0}
70 };
71
72 #define A_TRANS 0
73 #define A_NAME  1
74 #define A_KTO   2
75 #define A_BLZ   3
76 #define A_REF   4
77 #define A_DATE  5
78 #define A_TODO  6
79 #define A_CURR  7
80 #define A_EURO  8
81 #define A_DM    9
82 #define A_LEN   10
83 #define A_LOOP  7
84
85 dtaus_record recC[] = {
86   {"Name", 93, 27, REQ},
87   {"Konto", 21, 10, REQ},
88   {"BLZ", 13, 8, REQ},
89   {"Transaktion", 44, 5, REQ},
90 #ifndef DEFAULT_EURO
91   {"Betrag", 50, 11, REQ},
92 #else
93   {"Betrag", 79, 11, REQ},
94 #endif
95   {"Zweck", 155, 27, REQ},
96   {"myName", 128, 27, OPT},
97   {"myKonto", 69, 10, OPT},
98   {"myBLZ", 61, 8, OPT},
99   {"Text", 187, 29, OPT},
100   {"Extension", 216, 29, OPT},
101   {"Currency", 182, 1, IGN},
102 #ifndef DEFAULT_EURO
103   {"Betrag-Euro", 79, 11, IGN},
104 #else
105   {"Betrag-DM", 50, 11, IGN},
106 #endif
107   {NULL, 0, 0}
108 };
109
110 #define C_NAME  0
111 #define C_KTO   1
112 #define C_BLZ   2
113 #define C_TRANS 3
114 #define C_VAL   4
115 #define C_ZWECK 5
116 #define C_MYNAM 6
117 #define C_MYKTO 7
118 #define C_MYBLZ 8
119 #define C_TEXT  9
120 #define C_EXT  10
121 #define C_EURO 11
122 #ifndef DEFAULT_EURO
123 #define C_EUR  12
124 #else
125 #define C_DM   12
126 #endif
127 #define C_LEN  13
128 #define C_LOOP 11
129
130 #define MAX_TEXT 14
131
132 dtaus_record recE[] = {
133   {"Anzahl", 10, 7, IGN},
134 #ifndef DEFAULT_EURO
135   {"Summe", 17, 13, IGN},
136 #else
137   {"Summe", 64, 13, IGN},
138 #endif
139   {"Kontos", 30, 17, IGN},
140   {"BLZs", 47, 17, IGN},
141 #ifndef DEFAULT_EURO
142   {"Summe-Euro", 64, 13, IGN},
143 #else
144   {"Summe-DM", 17, 13, IGN},
145 #endif
146   {NULL, 0, 0}
147 };
148
149 #define E_COUNT 0
150 #define E_VAL   1
151 #define E_KTO   2
152 #define E_BLZ   3
153 #ifndef DEFAULT_EURO
154 #define E_EUR   4
155 #else
156 #define E_DM    4
157 #endif
158 #define E_LEN   5
159
160 /*
161  *  Second: Some low level routines
162  */
163
164 size_t dtaus_nextrec (void **buf, FILE *f)
165 {
166   memset (buf, 0, 128);
167   return fread(buf, 128, 1, f);
168 }
169
170 char *upcase(char *s)
171 {
172   static char x[100];
173   static char *xp;
174   char *cp;
175
176   for (cp=s,xp=x; *cp; cp++,xp++) {
177     if (strchr(" 0123456789.,&-/+*$%ABCDEFGHIJKLMNOPQRSTUVWXYZ",*cp)) {
178         *xp = *cp;
179     } else if (strchr("abcdefghijklmnopqrstuvwxyz",*cp)) {
180       *xp = toupper(*cp);
181     } else if (strchr ("üÜäÄöÖß", *cp)) {
182       switch (*cp) {
183       case 'ü': *(xp++) = 'U'; *xp='E'; break;
184       case 'Ü': *(xp++) = 'U'; *xp='E'; break;
185       case 'ä': *(xp++) = 'A'; *xp='E'; break;
186       case 'Ä': *(xp++) = 'A'; *xp='E'; break;
187       case 'ö': *(xp++) = 'O'; *xp='E'; break;
188       case 'Ö': *(xp++) = 'O'; *xp='E'; break;
189       case 'ß': *(xp++) = 'S'; *xp='S'; break;
190       }
191     } else
192       /*
193        * Filter out all other characters since credit institutes won't
194        * accept the file otherwise.
195        */
196       *xp = ' ';
197   }
198   *xp = '\0';
199
200   return x;
201 }
202
203 char *downcase(char *s)
204 {
205   static char x[100];
206   char *cp;
207
208   memset (x, 0, sizeof (x));
209   strncpy (x, s, 99);
210   
211   for (cp=x;*cp;cp++)
212     if (isupper(*cp))
213       *cp = tolower(*cp);
214   return x;
215 }
216
217 char *strip_spaces (char *s)
218 {
219   int i;
220   char *p;
221
222   for (i=strlen(s);(s[i-1] == ' '||s[i-1] == '\t')&&i>0; i--)
223     s[i-1] = '\0';
224   for (p=s; *p==' '; p++);
225   return p;
226 }
227
228 char *strip_zeros (char *s)
229 {
230   char *p;
231
232   for (p=s; *p=='0'; p++);
233   return p;
234 }
235
236 char *strip_nondigits (char *s)
237 {
238   char *p;
239   char *x;
240
241   for (x=s,p=s;*x;x++)
242     if (isdigit (*x))
243       *(p++) = *x;
244   *(p++) = '\0';
245
246   return s;
247 }
248
249 char dtaus_char (void *buf, unsigned int pos)
250 {
251   static char res;
252   char *bufp = (char *)buf;
253
254   bufp+=pos;
255   memcpy(&res, bufp, 1);
256   return res;
257 }
258
259 char *string2real(char *s)
260 {
261   static char res[20];
262   char *cp = s;
263
264   cp+=strlen(s)-2;
265   strncpy(res, s, strlen(s)-2);
266   res[strlen(s)-2] = '.';
267   res[strlen(s)-1] = s[strlen(s)-2];
268   res[strlen(s)] = s[strlen(s)-1];
269   return res;
270 }
271
272 char *real2string(char *s)
273 {
274   static char res[20];
275   char *cp;
276   char *xp;     /* only to avoid a GCC warning */
277
278   strncpy(res, s, sizeof(res)-1);
279   res[sizeof(res)-1] = 0;
280   for (cp=res; *cp&&!(*cp == ',')&&!(*cp == '.');cp++);
281
282   if ((cp-res) >= (sizeof(res)-3)) { 
283     /* Bail out, since the number is too large, shouldn't be possible though. */
284     fprintf (stderr, "Value %s too large.\n", res);
285     exit (1);
286   }
287
288   if (*cp == '.' || *cp == ',') {
289     if (*(cp+1)) {
290       /* 1st decimal place */
291       xp = cp+1;
292       if (*xp && isdigit(*xp))
293         *(cp++) = *xp;
294       else
295         *(cp++) = '0';
296       /* 2nd decimal place */
297       xp = cp+1;
298       if (*xp && isdigit(*xp))
299         *(cp++) = *xp;
300       else
301         *(cp++) = '0';
302     } else {
303       *(cp++) = '0';
304       *(cp++) = '0';
305     }
306   } else {
307     *(cp++) = '0';
308     *(cp++) = '0';
309   }
310   *cp = '\0';
311   return res;
312 }
313
314 /*
315  * Return the last digit of the year as character
316  */
317 char get_date_lastdigit()
318 {
319   time_t timer;
320   struct tm *loctime;
321
322   timer = time ( NULL );
323   loctime = localtime(&timer);
324   return loctime->tm_year % 10 + '0';
325 }
326
327 char *string2trans (char *s)
328 {
329   static char res[30];
330
331   res[0] = '\0';
332   if (!strcmp(s, "04000"))
333     sprintf (res, "Abbuchung");
334   else if (!strcmp(s, "05000"))
335     sprintf (res, "Einzug");
336   else if (!strcmp(s, "05005"))
337     sprintf (res, "E-Cash");
338   else if (!strcmp(s, "05006"))
339     sprintf (res, "E-Cash-A");
340   else if (!strcmp(s, "51000"))
341     sprintf (res, "Gutschrift");
342   else if (!strcmp(s, "53000"))
343     sprintf (res, "Lohn");
344   else if (!strncmp(s, "5400", 4))
345     sprintf (res, "Vermögen %c",s[4]);
346   /*  else if (!strcmp(s, "56000"))
347     sprintf (res, ""); / * Überweisung öffentlicher Kassen */
348   return res;
349 }
350
351 char *trans2string (char *s)
352 {
353   static char res[30];
354   char *cp;
355
356   res[0] = '\0';
357   if (!strcmp(s, "Abbuchung"))
358     sprintf (res, "04000");
359   else if (!strcmp(s, "Einzug"))
360     sprintf (res, "05000");
361   else if (!strcmp(s, "E-Cash"))
362     sprintf (res, "05005");
363   else if (!strcmp(s, "E-Cash-A"))
364     sprintf (res, "05006");
365   else if (!strcmp(s, "Gutschrift"))
366     sprintf (res, "51000");
367   else if (!strcmp(s, "Lohn"))
368     sprintf (res, "53000");
369   else {
370     cp = NULL;
371     if (!strncmp(s, "Vermögen", 8))
372       cp = s+8;
373     if (!strncmp(s, "Vermoegen", 9))
374       cp = s+9;
375
376     if (!cp) {
377       fprintf (stderr, "Unbekannte Transaktion `%s'\n", res);
378       exit (1);
379     }
380
381     /*
382       Vermögen --> 5400<heutiges Jahr>
383       Vermögen 8 -> 5400<8>
384       Vermögen 2003 -> 5400<3>
385      */
386
387     if (*cp) while (!isspace(*cp)) cp++;
388     while (isspace(*cp)) cp++;
389
390     if (!*cp || !isdigit(*cp))
391       sprintf (res, "5400%c",get_date_lastdigit());
392     else {
393       while (isdigit(*cp)) cp++;
394       sprintf (res, "5400%c",*(cp-1));
395     }
396   }
397   /*  else if (!strcmp(s, ""))
398     sprintf (res, "56000"); / * Überweisung öffentlicher Kassen */
399   return res;
400 }
401
402 char *string2ext (char *s)
403 {
404   static char res[30];
405
406   res[0] = '\0';
407   if (!strcmp(s, "01"))
408     sprintf (res, "Kunde");
409   else if (!strcmp(s, "02"))
410     sprintf (res, "Text");
411   else if (!strcmp(s, "03"))
412     sprintf (res, "Auftraggeber");
413   return res;
414 }
415
416 char *ext2string (char *s)
417 {
418   static char res[3];
419
420   res[0] = '\0';
421   if (!strcmp(s, "Kunde"))
422     sprintf (res, "01");
423   else if (!strcmp(s, "Text"))
424     sprintf (res, "02");
425   else if (!strcmp(s, "Auftraggeber"))
426     sprintf (res, "03");
427   return res;
428 }
429     
430 unsigned long int dtaus_int(void *buf, unsigned int pos, unsigned int len)
431 {
432   char tmp[30];
433   char *bufp = (char *)buf;
434   static unsigned long int res;
435
436   bufp+=pos;
437   memcpy(tmp, bufp, len);
438   tmp[len] = '\0';
439   sscanf(tmp, "%lu", &res);
440   return res;
441 }
442
443 /*
444  * returns the first word in this line, returns it and shortens the
445  * line.
446  */
447 char *extract_ident (char *line)
448 {
449   char *c, *x, *y;
450   static char word[30];
451
452   if (strlen(line) > 0) {
453     x = strchr (line, ' ');
454     y = strchr (line, '\t');
455
456     if (!x && !y) {
457         strncpy(word, line, 29);
458         line[0] = '\0';
459         return word;
460     }
461
462     /* Check which index returns the lower value, and check if the
463        value is non-NULL */
464     if ((c = (x && x<y)?x:(y?y:x))) { 
465       strncpy(word, line, c - line);
466       word[c-line] = '\0';
467       for (;*c == '\t' || *c == ' '; c++);
468       for (x=line; *c; c++,x++)
469         *x = *c;
470       *x = '\0';
471       strcpy(word, downcase(word));
472       return word;
473     }
474     return NULL;
475   }
476   return line;
477 }
478
479 /*
480  * Pads a string with zero's on the left side.
481  */
482 char *padzeroclip (char *s, int len)
483 {
484   char *p, *q;
485
486   if (strlen(s) == len) return s;
487   if (strlen(s) > len) {
488       q=s+len;
489       *(q--) = '\0';
490       return s;
491   }
492
493   q=s+len;
494   *(q--) = '\0';
495   for (p=s+strlen(s)-1;p>=s;p--)
496     *(q--)=*p;
497   for (;q>=s;) *(q--)='0';
498   return s;
499 }
500
501 int rec_index(char *ident, int type)
502 {
503   int i;
504   dtaus_record *rec = NULL;
505
506   switch (type) {
507   case REC_A:   rec = recA; break;
508   case REC_C:   rec = recC; break;
509   case REC_E:   rec = recE; break;
510   }
511
512   for (i=0; (rec[i].name); i++) {
513     if (!strcmp(ident, downcase(rec[i].name)))
514       return i;
515   }
516
517   return -1;
518 }
519
520 size_t control_nextline (void **buf, int len, FILE *f)
521 {
522   char line[100];
523   char tmp[100];
524   char *cp;
525   int i;
526
527   memset (line, 0, sizeof(line));
528   memset (buf, 0, len);
529   cp = line;
530
531   while (!strlen(line) && (cp = fgets(line, 100, f))) {
532     if (strlen(line)) {
533       if (line[0] != '#') {
534         if (line[strlen(line)-1] != '\n') { 
535           strcpy(tmp, line);
536           while (tmp[strlen(tmp)-1] != '\n' && (cp = fgets(tmp, 100, f)));
537         } else
538           line[strlen(line)-1] = '\0';
539         if (line[strlen(line)-1] == '\r')
540           line[strlen(line)-1] = '\0';
541         for (i=strlen(line);(line[i-1] == ' '||line[i-1] == '\t')&&i>0; i--)
542           line[i-1] = '\0';
543         if (line[0] == '#')
544           line[0] = '\0';
545       } else
546         line[0] = '\0';
547     }
548   }
549   for (cp=line; *cp==' '; cp++);
550
551   if (strlen(cp)) {
552     memcpy(buf, cp, strlen(cp));
553     return 1;
554   } else
555     return 0;
556 }
557
558 /*
559  * Return the current date nicely formatted
560  */
561 char *get_date()
562 {
563   static char res[10];
564   time_t timer;
565   struct tm *loctime;
566
567   timer = time ( NULL );
568   loctime = localtime(&timer);
569   sprintf(res, "%02d.%02d.%02d", loctime->tm_mday, loctime->tm_mon+1, loctime->tm_year % 100);
570   return res;
571 }
572
573 /*
574  *  Prepare a record A according to the specs.
575  *  See dtaus.txt for explanation
576  */
577 void dtaus_prepareA (char *buf)
578 {
579   int i;
580   time_t timer;
581   struct tm *loctime;
582   char tmp[10];
583
584   memset (buf, 0, 129);
585   timer = time ( NULL );
586   loctime = localtime(&timer);
587
588   buf[0] = '0';
589   buf[1] = '1';
590   buf[2] = '2';
591   buf[3] = '8';
592   buf[4] = 'A';
593   for (i=15;i<15+8; i++) buf[i] = '0';          /* A5 */
594   sprintf(tmp, "%02d%02d%02d", loctime->tm_mday, loctime->tm_mon+1, loctime->tm_year % 100);
595   for (i=0; i<6; i++) buf[50+i] = tmp[i];       /* A7 (Date) */
596   for (i=56;i<56+4; i++) buf[i] = ' ';          /* A8 */
597   for (i=70;i<70+10; i++) buf[i] = '0';         /* A10 */
598   for (i=80;i<80+48; i++) buf[i] = ' ';         /* A11 */
599   if (use_euro)
600     buf[recA[A_CURR].pos] = '1';                                /* A12 (Currency) */
601   else
602     buf[recA[A_CURR].pos] = ' ';                                /* A12 (Currency) */
603 }
604
605 /*
606  *  Prepare a record C according to the specs.
607  *  See dtaus.txt for explanation
608  */
609 void dtaus_prepareC (char *buf, int normaltext, int maxtext)
610 {
611   int i;
612   int appendix = 0;
613
614   memset (buf, 0, 257);
615
616   if (normaltext)
617     appendix = 1;
618   appendix += maxtext;
619   i = 187 + (appendix * 29);
620
621   /* Bail out if the number is too large, shouldn't be possible though */
622   if (i >= 1000)
623     exit (1);
624
625   buf[0] = (i/1000)+48;i-=(i/1000)*100;
626   buf[1] = (i/100)+48;i-=(i/100)*100;
627   buf[2] = (i/10)+48;i-=(i/10)*10;
628   buf[3] = i+48;
629   buf[4] = 'C';
630
631   for (i=31;i<31+13; i++) buf[i] = '0';         /* C6 */
632   buf[49] = ' ';                                /* C8 */
633   for (i=50;i<50+11; i++) buf[i] = '0';         /* C9 (Betrag) */
634   for (i=79;i<79+11; i++) buf[i] = '0';         /* C12 (Betrag Euro) */
635   for (i=90;i<90+3; i++) buf[i] = ' ';          /* C13 */
636   for (i=93;i<90+27; i++) buf[i] = ' ';         /* C14a (Kunde) */
637   for (i=120;i<120+8; i++) buf[i] = ' ';        /* C14b */
638   if (use_euro)
639     buf[recC[C_EURO].pos] = '1';                                /* C17a (Currency) */
640   else
641     buf[recC[C_EURO].pos] = ' ';                                /* C17a (Currency) */
642   for (i=183;i<183+2; i++) buf[i] = ' ';        /* C17b */
643   for (i=187;i<187+(29*2); i++) buf[i] = ' ';   /* C19-C22 (misc text) */
644   for (i=245;i<245+11; i++) buf[i] = ' ';       /* C23 */
645
646   buf[185+0] = (appendix/10)+48;appendix-=(appendix/10)*10;
647   buf[185+1] = appendix+48;
648 }
649
650 /*
651  *  Prepare a record E according to the specs.
652  *  See dtaus.txt for explanation
653  */
654 void dtaus_prepareE (char *buf)
655 {
656   int i;
657
658   memset (buf, 0, 129);
659   buf[0] = '0';
660   buf[1] = '1';
661   buf[2] = '2';
662   buf[3] = '8';
663   buf[4] = 'E';
664   for (i=5;i<5+5; i++) buf[i] = ' ';    /* E3 */
665   for (i=17;i<17+13; i++) buf[i] = '0'; /* E8 (Check Betrag) */
666   for (i=64;i<64+13; i++) buf[i] = '0'; /* E8 (Check Euro) */
667   for (i=77;i<77+51; i++) buf[i] = ' '; /* E9 */
668 }
669
670 int dtaus_writeA(FILE *f, char **values)
671 {
672   char buf[129];
673   char tmp[30];
674   int i;
675   
676   for (i=0; (recA[i].name); i++)
677     if ((recA[i].type == REQ) && !values[i]) {
678       fprintf (stderr, "Anfangsdatensatz ist nicht vollständig, kein %s.\n", recA[i].name);
679       return 0;
680     }
681   if (!(((values[A_TRANS][0] == 'L')||(values[A_TRANS][0] == 'G'))
682         &&((values[A_TRANS][1] == 'B')||(values[A_TRANS][1] == 'K')))) {
683     fprintf (stderr, "Ungültiger Typ, nur LK, GK, LB oder GB erlaubt.\n");
684     return 0;
685   }
686
687   i=A_NAME;if (values[i] && strlen(values[i]) > recA[i].len)
688     values[i][recA[i].len] = '\0';
689
690   dtaus_prepareA(buf);
691   buf[5] = values[A_TRANS][0];
692   buf[6] = values[A_TRANS][1];
693   sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[A_BLZ]),recA[A_BLZ].len));
694   for (i=0; i<recA[A_BLZ].len; i++) buf[recA[A_BLZ].pos+i] = tmp[i];
695   sprintf (tmp, "%-27.27s", upcase(values[A_NAME]));
696   for (i=0; i<27; i++) buf[recA[A_NAME].pos+i] = tmp[i];
697   if (values[A_TODO]) {
698     sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[A_TODO]),recA[A_TODO].len));
699     for (i=0; i<recA[A_TODO].len; i++) buf[recA[A_TODO].pos+i] = tmp[i];
700   }
701   sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[A_KTO]),recA[A_KTO].len));
702   for (i=0; i<recA[A_KTO].len; i++) buf[recA[A_KTO].pos+i] = tmp[i];
703
704   fputs(buf, f);
705   return 1;
706 }
707
708 int dtaus_writeC(FILE *f, char **valuesA, char **values, char **text)
709 {
710   char buf[257];
711   char appendix[129];
712   char tmp[30];
713   int i, k;
714   int maxtext = 0;
715   int fieldnr;
716
717   /* Just count */
718   if (text) for (maxtext=0;text[maxtext];maxtext++);
719
720 #if DEBUG
721   for (i=0; (recC[i].name); i++)
722     if (values[i])
723       printf ("%s: %s\n", recC[i].name, values[i]);
724 #endif
725
726   for (i=0; (recC[i].name); i++)
727     if ((recC[i].type == REQ) && !values[i]) {
728       fprintf (stderr, "Datensatz ist nicht vollständig, kein %s.\n", recC[i].name);
729       return 0;
730     }
731   sprintf (tmp, "%s", trans2string(values[C_TRANS]));
732   if (!strlen(tmp)) {
733     fprintf (stderr, "Ungültige Transaktion, nur Abbuchung, Einzug, E-Cash, E-Cash-A, Gutschrift und Lohn erlaubt.\n");
734     return 0;
735   }
736
737   i=C_TEXT;if (values[i] && strlen(values[i]) > recC[i].len)
738     values[i][recC[i].len-2] = '\0';
739   i=C_ZWECK;if (values[i] && strlen(values[i]) > recC[i].len)
740     values[i][recC[i].len] = '\0';
741   i=C_MYNAM;if (values[i] && strlen(values[i]) > recC[i].len)
742     values[i][recC[i].len] = '\0';
743   i=C_TEXT;if (values[i] && strlen(values[i]) > recC[i].len)
744     values[i][recC[i].len] = '\0';
745
746   dtaus_prepareC (buf, values[C_TEXT] != NULL, maxtext);
747   for (i=0; i<5; i++) buf[recC[C_TRANS].pos+i] = tmp[i];
748   if (values[C_MYBLZ])
749     sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[C_MYBLZ]),8));
750   else
751     sprintf (tmp, "%s", padzeroclip (strip_nondigits (valuesA[A_BLZ]),8));
752   for (i=0; i<recC[C_MYBLZ].len; i++) buf[5+i] = tmp[i];
753   for (i=0; i<recC[C_MYBLZ].len; i++) buf[recC[C_MYBLZ].pos+i] = tmp[i];
754   sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[C_BLZ]),8));
755   for (i=0; i<recC[C_BLZ].len; i++) buf[recC[C_BLZ].pos+i] = tmp[i];
756   sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[C_KTO]),10));
757   for (i=0; i<recC[C_KTO].len; i++) buf[recC[C_KTO].pos+i] = tmp[i];
758   sprintf (tmp, "%s", padzeroclip (real2string(values[C_VAL]),11));
759 #ifndef DEFAULT_EURO
760   if (!use_euro)
761     for (i=0; i<recC[C_VAL].len; i++) buf[recC[C_VAL].pos+i] = tmp[i];
762   else
763     for (i=0; i<recC[C_EUR].len; i++) buf[recC[C_EUR].pos+i] = tmp[i];
764 #else
765   if (use_euro)
766     for (i=0; i<recC[C_VAL].len; i++) buf[recC[C_VAL].pos+i] = tmp[i];
767   else
768     for (i=0; i<recC[C_DM].len; i++) buf[recC[C_DM].pos+i] = tmp[i];
769 #endif
770   if (values[C_MYKTO])
771     sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[C_MYKTO]),10));
772   else
773     sprintf (tmp, "%s", padzeroclip (strip_nondigits (valuesA[A_KTO]),10));
774   for (i=0; i<recC[C_MYKTO].len; i++) buf[recC[C_MYKTO].pos+i] = tmp[i];
775   sprintf (tmp, "%-27.27s", upcase(values[C_NAME]));
776   for (i=0; i<recC[C_NAME].len; i++) buf[recC[C_NAME].pos+i] = tmp[i];
777   if (values[C_MYNAM])
778     sprintf (tmp, "%-27.27s", upcase(values[C_MYNAM]));
779   else
780     sprintf (tmp, "%-27.27s", upcase(valuesA[A_NAME]));
781   for (i=0; i<recC[C_MYNAM].len; i++) buf[recC[C_MYNAM].pos+i] = tmp[i];
782   sprintf (tmp, "%-27.27s", upcase(values[C_ZWECK]));
783   for (i=0; i<recC[C_ZWECK].len; i++) buf[recC[C_ZWECK].pos+i] = tmp[i];
784
785   if (values[C_TEXT]) {
786     buf[recC[C_TEXT].pos+0] = '0';
787     buf[recC[C_TEXT].pos+1] = '2';
788     sprintf (tmp, "%-27.27s", upcase(values[C_TEXT]));
789     for (i=0; i<recC[C_TEXT].len-2; i++) buf[recC[C_TEXT].pos+2+i] = tmp[i];
790   }
791
792   if (text) {
793     buf[recC[C_EXT].pos+0] = '0';
794     buf[recC[C_EXT].pos+1] = '2';
795     sprintf (tmp, "%-27.27s", upcase(text[0]));
796     for (i=0; i<recC[C_EXT].len-2; i++) buf[recC[C_EXT].pos+2+i] = tmp[i];
797   }
798
799   fputs(buf, f);
800
801   if (text && maxtext > 1) {
802     fieldnr=1;
803     while (fieldnr<maxtext) {
804       memset (appendix, ' ', 128);
805       appendix[128] = '\0';
806       for (k=0; k<4 && (fieldnr+k)<maxtext; k++) {
807         sprintf (tmp, "%-27.27s", upcase(text[fieldnr+k]));
808         appendix[k*29] = '0';
809         appendix[(k*29)+1] = '2';
810         for (i=0; i<recC[C_TEXT].len-2; i++) appendix[(k*29)+2+i] = tmp[i];
811       }
812       fputs(appendix, f);
813       fieldnr += k;
814     }
815   }
816
817   return 1;
818 }
819
820 int dtaus_writeE(FILE *f, int count, bigint sum, bigint blz, bigint kto)
821 {
822   char buf[129];
823   char tmp[30];
824   int i;
825   
826   dtaus_prepareE(buf);
827
828   sprintf (tmp, "%07d", count);
829   for (i=0; i<recE[E_COUNT].len; i++) buf[recE[E_COUNT].pos+i] = tmp[i];
830   bigint_sprintf (tmp, "%s", sum);
831   padzeroclip (tmp,13);
832 #ifndef DEFAULT_EURO
833   if (!use_euro)
834     for (i=0; i<recE[E_VAL].len; i++) buf[recE[E_VAL].pos+i] = tmp[i];
835   else
836     for (i=0; i<recE[E_EUR].len; i++) buf[recE[E_EUR].pos+i] = tmp[i];
837 #else
838   if (use_euro)
839     for (i=0; i<recE[E_VAL].len; i++) buf[recE[E_VAL].pos+i] = tmp[i];
840   else
841     for (i=0; i<recE[E_DM].len; i++) buf[recE[E_DM].pos+i] = tmp[i];
842 #endif
843   bigint_sprintf (tmp, "%s", kto);
844   padzeroclip (tmp,17);
845   for (i=0; i<recE[E_KTO].len; i++) buf[recE[E_KTO].pos+i] = tmp[i];
846   bigint_sprintf (tmp, "%s", blz);
847   padzeroclip (tmp,17);
848   for (i=0; i<recE[E_BLZ].len; i++) buf[recE[E_BLZ].pos+i] = tmp[i];
849
850   fputs(buf, f);
851   return 1;
852 }
853
854 void printctln(FILE *f, char *field, char *value)
855 {
856   if (strlen(field) && strlen(value))
857     fprintf(f, "  %s\t%s\n", field, value);
858 }
859
860 /*
861  * one date line, format it properly
862  */
863 void printctlndate(FILE *f, char *field, char *value)
864 {
865   char mydate[11];
866   int i;
867
868   if (!strlen(field) || !strlen(value))
869     return;
870
871   for (i=0;isspace (value[i]) && i<= strlen (value); i++);
872   if (i == strlen (value))
873     return;
874
875   memset (mydate, 0, sizeof (mydate));
876   if (strlen (value) == 6) {
877     mydate[0] = value[0];
878     mydate[1] = value[1];
879     mydate[2] = '.';
880     mydate[3] = value[2];
881     mydate[4] = value[3];
882     mydate[5] = '.';
883     mydate[6] = value[4];
884     mydate[7] = value[5];
885     fprintf(f, "  %s\t%s\n", field, mydate);
886   } else if (strlen (value) == 8) {
887     mydate[0] = value[0];
888     mydate[1] = value[1];
889     mydate[2] = '.';
890     mydate[3] = value[2];
891     mydate[4] = value[3];
892     mydate[5] = '.';
893     mydate[6] = value[4];
894     mydate[7] = value[5];
895     mydate[8] = value[6];
896     mydate[9] = value[7];
897     fprintf(f, "  %s\t%s\n", field, mydate);
898   } else {
899     fprintf (stderr, "Broken date field: %s\n", value);
900     fprintf(f, "  %s\t%s\n", field, value);
901   }
902 }
903
904
905 /*
906  *  Third: Some high level routines
907  */
908
909 void dtaus2control (char *cdtaus, char *ccontrol)
910 {
911   FILE *fdtaus, *fcontrol;
912   char *buf;
913   char *bufp;
914   char tmp[30];
915   char x[30];
916   int index;
917   int extC;
918   div_t res;
919
920   if (!cdtaus) {
921     if (!(fdtaus = fopen("DTAUS0.TXT", "r")))
922       if (!(fdtaus = fopen("dtaus0.txt", "r")))
923         return;
924   } else {
925     if (!strcmp (cdtaus, "-"))
926       fdtaus = stdin;
927     else
928       if (!(fdtaus = fopen(cdtaus, "r")))
929         return;
930   }
931   if (!ccontrol) 
932     fcontrol = stdout;
933   else
934     if (!strcmp (ccontrol, "-"))
935       fcontrol = stdout;
936     else
937       if (!(fcontrol = fopen(ccontrol, "w")))
938         return;
939   if (!(buf = (char *)malloc (512)))
940     return;
941
942   /* 
943    * Record A lesen
944    */
945   if (dtaus_nextrec((void *)buf, fdtaus) == 1) {
946     if (dtaus_char(buf,4) == 'A') {
947       fprintf(fcontrol, "BEGIN {\n");
948       bufp = buf;
949
950       for (index=A_TRANS; index < A_LOOP; index++) {
951         bufp = buf + recA[index].pos;
952         memcpy(tmp, bufp, recA[index].len); tmp[recA[index].len] = '\0';
953         if (index == A_DATE || index == A_TODO)
954           printctlndate(fcontrol, recA[index].name, tmp);
955         else
956           printctln(fcontrol, recA[index].name, strip_zeros(strip_spaces(tmp)));
957       }
958
959       bufp = buf + recA[A_CURR].pos;
960       if (*bufp == '1') {
961         use_euro = 1;
962         fprintf(fcontrol, "  Euro\n");
963       } else {
964         use_euro = 0;
965         fprintf(fcontrol, "  DM\n");
966       }
967
968       fprintf(fcontrol, "}\n\n");
969     } else {
970       fprintf (stderr, "Datei fängt nicht mit dem Anfangsdatensatz an.\n");
971       return;
972     }
973   } else {
974     fprintf (stderr, "Der Anfangsdatensatz ist kaputt.\n");
975     return;
976   }
977
978   /*
979    * Record C lesen
980    */
981   if (dtaus_nextrec((void *)buf, fdtaus) == 1) {
982     while (dtaus_char(buf,4) == 'C') {
983       bufp = buf + 128;
984       if (dtaus_nextrec((void *)bufp, fdtaus) != 1) {
985         fprintf (stderr, "Der zweite Teil der Transaktion ist kaputt.\n");
986         return;
987       } else {
988         fprintf(fcontrol, "{\n");
989
990         for (index=C_NAME; index < C_LOOP; index++) {
991 #ifndef DEFAULT_EURO
992           if (use_euro && index == C_VAL)
993             index = C_EUR;
994 #else
995           if (!use_euro && index == C_VAL)
996             index = C_DM;
997 #endif
998           bufp = buf + recC[index].pos;
999           memcpy(tmp, bufp, recC[index].len); tmp[recC[index].len] = '\0';
1000
1001           /*
1002            * C_EUR and C_DM are outside of the loop, can only be
1003            * selected for the non-default currency, but the value
1004            * should be stored in the normal record field.
1005            */
1006 #ifndef DEFAULT_EURO
1007           if (index == C_EUR)
1008 #else
1009           if (index == C_DM)
1010 #endif
1011             printctln(fcontrol, recC[C_VAL].name, strip_zeros(string2real(tmp)));
1012           else if (index == C_VAL)
1013             printctln(fcontrol, recC[index].name, strip_zeros(string2real(tmp)));
1014           else if (index == C_TRANS)
1015             printctln(fcontrol, recC[index].name, strip_zeros(string2trans(tmp)));
1016           else
1017             printctln(fcontrol, recC[index].name, strip_zeros(strip_spaces(tmp)));
1018 #ifndef DEFAULT_EURO
1019           if (use_euro && index == C_EUR)
1020             index = C_VAL;
1021 #else
1022           if (!use_euro && index == C_DM)
1023             index = C_VAL;
1024 #endif
1025         }
1026
1027         for (index=C_TEXT; index <= C_EXT; index++) {
1028           if (!(dtaus_char(buf,recC[index].pos) == ' ')) {
1029             bufp = buf + recC[index].pos;
1030             memcpy(x, bufp, 2); tmp[2] = '\0'; bufp+=2;
1031             memcpy(tmp, bufp, recC[index].len-2); tmp[recC[index].len-2] = '\0';
1032             printctln(fcontrol, string2ext(x), strip_spaces(tmp));
1033           }
1034         }
1035
1036         /* Number of extension records for this C record */
1037         extC = dtaus_int(buf, 185, 2);
1038         extC -= 2;
1039         if (extC > 0) {
1040           res = div (extC, 4);
1041           extC = res.quot;
1042           if (res.rem) extC++;
1043         }
1044       }
1045       if (dtaus_nextrec((void *)buf, fdtaus) != 1)
1046         memset (buf, 0, sizeof(buf));
1047
1048       /*
1049        * Are there extension records that we have to check?
1050        *
1051        * 2nd half of the AND is wrong, but since dtaus < 0.5 wrote 01
1052        *     instead of 00 we should let it in so it can read its own
1053        *     old files...  *sigh*
1054        */
1055       while (extC > 0 && dtaus_char(buf,4) != 'C' && dtaus_char(buf,4) != 'E') {
1056         for (index=0; index < 4; index++) {
1057           if ((dtaus_char(buf,index*29) != ' ')) {
1058             bufp = buf + index*29;
1059             memcpy(x, bufp, 2); tmp[2] = '\0'; bufp+=2;
1060             memcpy(tmp, bufp, recC[C_TEXT].len-2); tmp[recC[C_TEXT].len-2] = '\0';
1061             printctln(fcontrol, string2ext(x), strip_spaces(tmp));
1062           }
1063         }
1064         if (dtaus_nextrec((void *)buf, fdtaus) != 1)
1065           memset (buf, 0, sizeof(buf));
1066         extC--;
1067       }
1068       fprintf(fcontrol, "}\n");
1069     }
1070   }
1071
1072   /*
1073    * Record E lesen
1074    *   (gelesen ist er eigentlich schon...)
1075    */
1076   if (dtaus_char(buf,4) == 'E') {
1077     if (dtaus_char(buf,4) == 'E') {
1078       fprintf(fcontrol, "\nEND {\n");
1079
1080       for (index=E_COUNT; index <= E_BLZ; index++) {
1081 #ifndef DEFAULT_EURO
1082         if (use_euro && index == E_VAL)
1083           index = E_EUR;
1084 #else
1085         if (!use_euro && index == E_VAL)
1086           index = E_DM;
1087 #endif
1088
1089         bufp = buf + recE[index].pos;
1090         memcpy(tmp, bufp, recE[index].len); tmp[recE[index].len] = '\0';
1091
1092 #ifndef DEFAULT_EURO
1093         if (index == E_VAL || index == E_EUR)
1094 #else
1095         if (index == E_VAL || index == E_DM)
1096 #endif
1097           printctln(fcontrol, recE[E_VAL].name, strip_zeros(string2real(tmp)));
1098         else
1099           printctln(fcontrol, recE[index].name, strip_zeros(tmp));
1100 #ifndef DEFAULT_EURO
1101           if (use_euro && index == E_EUR)
1102             index = E_VAL;
1103 #else
1104           if (!use_euro && index == E_DM)
1105             index = E_VAL;
1106 #endif
1107       }
1108
1109       fprintf(fcontrol, "}\n");
1110     } else {
1111       fprintf (stderr, "Das ist kein Abschlußdatensatz.\n");
1112       return;
1113     }
1114   } else {
1115     fprintf (stderr, "Der Abschlußdatensatz ist leer oder kaputt.\n");
1116     return;
1117   }
1118   fclose(fcontrol);
1119   fclose(fdtaus);
1120 }
1121
1122 int control2dtaus (char *ccontrol, char *cdtaus, char *cbeleg, char *ccheck)
1123 {
1124   FILE *fdtaus, *fcontrol, *fbeleg, *fcheck;
1125   void *buf;
1126   char *ident;
1127   int  recindex;
1128   char tmp[30];
1129   char line[100];
1130   char *valA[A_LEN], *valC[C_LEN];
1131   int count;
1132   bigint sum_val, sum_blz, sum_kto, bi;
1133   char **text = NULL;
1134   char *cp;
1135   int textindex = 0;
1136   int len, i;
1137
1138   if (!cdtaus) {
1139     if (!(fdtaus = fopen("dtaus0.txt", "w")))
1140       return 0;
1141   } else {
1142     if (!strcmp (cdtaus, "-"))
1143       fdtaus = stdout;
1144     else
1145       if (!(fdtaus = fopen(cdtaus, "w")))
1146         return 0;
1147   }
1148   if (!ccontrol) {
1149     if (!(fcontrol = fopen("dtaus0.ctl", "r")))
1150       if (!(fcontrol = fopen("DTAUS0.CTL", "r")))
1151         return 0;
1152   } else {
1153     if (!strcmp (ccontrol, "-"))
1154       fcontrol = stdin;
1155     else
1156       if (!(fcontrol = fopen(ccontrol, "r")))
1157         return 0;
1158   }
1159   if (!cbeleg) {
1160     if (!(fbeleg = fopen("dtaus0.doc", "w")))
1161       return 0;
1162   } else {
1163     if (!(fbeleg = fopen(cbeleg, "w")))
1164       return 0;
1165   }
1166   if (!ccheck)
1167     fcheck = stdout;
1168   else
1169     if (!(fcheck = fopen(ccheck, "w")))
1170       return 0;
1171
1172
1173   if (!(buf = (char *)malloc (512)))
1174     return 0;
1175
1176   /* 
1177    * Record A lesen
1178    */
1179   memset (valA, 0, sizeof(valA));
1180   control_nextline ((void *)line, 100, fcontrol);
1181   ident = extract_ident(line);
1182   if (!strcmp(ident, "begin") && (line[0] == '{')) {
1183     control_nextline ((void *)line, 100, fcontrol);
1184     while (strlen(line) && line[0] != '}') {
1185       ident = extract_ident(line);
1186       if ((recindex = rec_index(ident, REC_A)) != -1)
1187         {
1188         if (recA[recindex].type != IGN)
1189           if ((valA[recindex] = (char *)malloc (strlen(line)+1)))
1190             strcpy(valA[recindex], line);
1191         } else {
1192           if (! strcasecmp (ident, "euro"))
1193             use_euro = 1;
1194           if (! strcasecmp (ident, "dm"))
1195             use_euro = 0;
1196         }
1197       control_nextline ((void *)line, 100, fcontrol);
1198     }
1199     if (((recindex = rec_index("art", REC_A)) != -1) && valA[recindex] && strlen(valA[recindex])) {
1200       fprintf(fbeleg, "\n\n");
1201       fprintf(fbeleg, "\n    Begleitzettel\n\n");
1202       fprintf(fbeleg, "\n    Belegloser Datentraegeraustausch\n\n");
1203       if (valA[recindex][0] == 'L')
1204         fprintf(fbeleg, "\n    Sammeleinziehungsauftrag\n\n");
1205       else if (valA[recindex][0] == 'G')
1206         fprintf(fbeleg, "\n    Sammelueberweisungsauftrag\n\n");
1207       else
1208         fprintf(fbeleg, "\n    Sammelauftrag\n\n");
1209       fprintf(fbeleg, "\n    VOL ........................:\n");
1210       fprintf(fbeleg, "\n    Erstellungsdatum ...........: %s\n", get_date());
1211       if (valA[A_TODO]) {
1212         fprintf(fbeleg, "\n    Ausfuehrungsdatum ..........: %s\n", valA[A_TODO]);
1213       }
1214       if (use_euro)
1215         fprintf(fbeleg, "\n    Waehrung ...................: Euro\n");
1216       else
1217         fprintf(fbeleg, "\n    Waehrung ...................: DM\n");
1218     }
1219     if (!dtaus_writeA(fdtaus, valA)) {
1220       fprintf (stderr, "Konnte den Anfangsdatensatz nicht schreiben.\n");
1221       return 0;
1222     }
1223
1224     fprintf (fcheck, "\n\n\n");
1225     if (valA[recindex][0] == 'L')
1226       fprintf (fcheck, "    Sammeleinziehungsauftrag\n\n");
1227     else if (valA[recindex][0] == 'G')
1228       fprintf (fcheck, "    Sammelueberweisungsauftrag\n\n");
1229     else
1230       fprintf (fcheck, "    Sammelauftrag\n\n");
1231     fprintf (fcheck, "    Erstellungsdatum : %s\n\n", get_date());
1232     if (use_euro)
1233       fprintf (fcheck, "    Waehrung         : Euro\n\n\n");
1234     else
1235       fprintf (fcheck, "    Waehrung         : DM\n\n\n");
1236     fprintf (fcheck, "     %-10s  %-8s  %-30s   %12s\n", "Kontonr.", "BLZ", "Name", "Betrag");
1237     fprintf (fcheck, "    --------------------------------------------------------------------\n");
1238   } else {
1239     fprintf (stderr, "Datei fängt nicht mit dem Anfangsdatensatz (BEGIN) an.\n");
1240     return 0;
1241   }
1242
1243   /* 
1244    * Record C lesen
1245    */
1246   count = 0;
1247   sum_val = bigint_int(0);
1248   sum_blz = bigint_int(0);
1249   sum_kto = bigint_int(0);
1250   memset (valC, 0, sizeof(valC));
1251   control_nextline ((void *)line, 100, fcontrol);
1252   if (line[0] == '{') {
1253     while (strlen(line) && line[0] == '{') {
1254       control_nextline ((void *)line, 100, fcontrol);
1255       if (text) {
1256         for (textindex=0; textindex < MAX_TEXT && text[textindex]; textindex++)
1257           free (text[textindex]);
1258         free (text);
1259         text = NULL;
1260       }
1261       while (strlen(line) && line[0] != '}') {
1262         ident = extract_ident(line);
1263         if ((recindex = rec_index(ident, REC_C)) != -1)
1264           if (recC[recindex].type != IGN) {
1265             /*
1266              * Special exception to support multiple Text fields
1267              */
1268             if (recindex == C_TEXT && valC[recindex]) {
1269               if (!text) {
1270                 if ((text = (char **)malloc ((MAX_TEXT+1) * sizeof (char *))) == NULL)
1271                   return 0;
1272                 else {
1273                   textindex = 0;
1274                   memset (text, 0, (MAX_TEXT+1) * sizeof (char *));
1275                 }
1276               }
1277               if (textindex < MAX_TEXT) {
1278                 if ((cp = (char *)malloc (strlen (line) + 1))) {
1279                   strcpy (cp, line);
1280                   cp[strlen (line)] = '\0';
1281                   text[textindex++] = cp;
1282                 }
1283               }
1284             } else {
1285               len = strlen(line);
1286               if (recindex == C_VAL) {
1287                 /* Convert commast to dots for later processing */
1288                 for (i=0; line[i]; i++) if (line[i] == ',') line[i] = '.';
1289
1290                 if ((cp = index (line, '.')) == NULL) {
1291                   if (!(valC[recindex] = (char *)malloc (strlen(line)+4)))
1292                     return 0;
1293                   sprintf (valC[recindex], "%s.00", line);
1294                 } else if ( ((len = cp - line + 3)) < strlen (line)) {
1295                   if (!(valC[recindex] = (char *)malloc (len+1)))
1296                     return 0;
1297                   strncpy (valC[recindex], line, len);
1298                   valC[recindex][len] = '\0';
1299                 } else {
1300                   if (!(valC[recindex] = (char *)malloc (strlen(line)+1)))
1301                     return 0;
1302                   strcpy(valC[recindex], line);
1303                 }
1304               } else {
1305                 if ((valC[recindex] = (char *)malloc (strlen(line)+1)))
1306                   strcpy(valC[recindex], line);
1307                 else
1308                   return 0;
1309               }
1310             }
1311           }
1312         control_nextline ((void *)line, 100, fcontrol);
1313       }
1314       if (!dtaus_writeC(fdtaus, valA, valC, text)) {
1315         fprintf (stderr, "Konnte den regulären Datensatz nicht schreiben.\n");
1316         return 0;
1317       }
1318       count++;
1319       bi = bigint_string(real2string(valC[C_VAL])); sum_val = bigint_add(sum_val, bi);
1320       bi = bigint_string(valC[C_BLZ]); sum_blz = bigint_add(sum_blz, bi);
1321       bi = bigint_string(valC[C_KTO]); sum_kto = bigint_add(sum_kto, bi);
1322
1323       fprintf (fcheck, "     %10s  %8s  %-30s   %12s\n", valC[C_KTO], valC[C_BLZ], valC[C_NAME], valC[C_VAL]);
1324       for (recindex=0; recindex<C_LEN; recindex++)
1325         if (valC[recindex])
1326           free(valC[recindex]);
1327       memset (valC, 0, sizeof(valC));
1328       control_nextline ((void *)line, 100, fcontrol);
1329     }
1330   } else {
1331     fprintf (stderr, "Kein regulärer Datensatz?\n");
1332     return 0;
1333   }
1334
1335   /* 
1336    * Record E lesen
1337    */
1338   dtaus_writeE(fdtaus, count, sum_val, sum_blz, sum_kto);
1339   fprintf (fcheck, "    --------------------------------------------------------------------\n");
1340   bigint_sprintf (tmp, "%s", sum_val);
1341   fprintf (fbeleg, "\n    Anzahl .....................: %d\n", count);
1342   recindex=strlen(tmp);
1343   tmp[recindex+1] = '\0';
1344   tmp[recindex] = tmp[recindex-1];
1345   tmp[recindex-1] = tmp[recindex-2];
1346   tmp[recindex-2] = '.';
1347   fprintf (fcheck, "     %-52s %14s\n", "Summe", tmp);
1348   fprintf (fbeleg, "\n    Summe ......................: %s\n", tmp);
1349   bigint_sprintf (tmp, "%s", sum_kto);
1350   fprintf (fbeleg, "\n    Kontrollsumme Kontonummern .: %s\n", tmp);
1351   bigint_sprintf (tmp, "%s", sum_blz);
1352   fprintf (fbeleg, "\n    Kontrollsumme Bankleitzahlen: %s\n", tmp);
1353   fprintf (fbeleg, "\n    Unsere Kontonummer .........: %s\n", valA[A_KTO]);
1354   fprintf (fbeleg, "\n    Unsere Bankleitzahl ........: %s\n", valA[A_BLZ]);
1355   fprintf (fbeleg, "\n\n\n\n\n    __________________________________________________\n");
1356   fprintf (fbeleg, "    Ort, Datum                     Unterschrift\n");
1357   for (recindex=0; recindex<A_LEN; recindex++)
1358     if (valA[recindex])
1359       free(valA[recindex]);
1360   fclose(fdtaus);
1361   fclose(fcontrol);
1362   fclose(fbeleg);
1363   if (ccheck)
1364     fclose(fcheck);
1365   return count;
1366 }