88a8864abc1e3afd1f630976c64d42f2dabf4508
[infodrom/dtaus] / dtaus.c
1 /*
2     dtaus.c - Datenträgeraustausch mit einer Bank
3     Copyright (c) 1996,8,2001  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 /*
32  *  First: Some control structures
33  */
34
35 typedef struct
36 {
37   char *name;
38   unsigned short int pos;
39   unsigned short int len;
40   int type;
41 } dtaus_record;
42
43 #define REC_A   1
44 #define REC_C   2
45 #define REC_E   3
46
47 #define REQ     1
48 #define OPT     2
49 #define IGN     3
50
51 dtaus_record recA[] = {
52   {"Art", 5, 2, REQ},
53   {"Name", 23, 27, REQ},
54   {"Konto", 60, 10, REQ},
55   {"BLZ", 7, 8, REQ},
56   {"Referenz", 70, 10, OPT},
57   {"Datum", 50, 6, IGN},
58   {"Euro", 127, 1, OPT},
59   {NULL, 0, 0}
60 };
61
62 #define A_TRANS 0
63 #define A_NAME  1
64 #define A_KTO   2
65 #define A_BLZ   3
66 #define A_REF   4
67 #define A_DATE  5
68 #define A_EURO  6
69 #define A_LEN   7
70
71 dtaus_record recC[] = {
72   {"Name", 93, 27, REQ},
73   {"Konto", 21, 10, REQ},
74   {"BLZ", 13, 8, REQ},
75   {"Transaktion", 44, 5, REQ},
76   {"Betrag", 50, 11, REQ},
77   {"Zweck", 155, 27, REQ},
78   {"myName", 128, 27, OPT},
79   {"myKonto", 69, 10, OPT},
80   {"myBLZ", 61, 8, OPT},
81   {"Euro", 182, 1, IGN},
82   {"Text", 187, 29, OPT},
83   {"Extension", 216, 29, OPT},
84   {NULL, 0, 0}
85 };
86
87 #define C_NAME  0
88 #define C_KTO   1
89 #define C_BLZ   2
90 #define C_TRANS 3
91 #define C_VAL   4
92 #define C_ZWECK 5
93 #define C_MYNAM 6
94 #define C_MYKTO 7
95 #define C_MYBLZ 8
96 #define C_EURO  9
97 #define C_TEXT 10
98 #define C_EXT  11
99 #define C_LEN  12
100
101 #define MAX_TEXT 61
102
103 dtaus_record recE[] = {
104   {"Anzahl", 10, 7, IGN},
105   {"Summe", 17, 13, IGN},
106   {"Kontos", 30, 17, IGN},
107   {"BLZs", 47, 17, IGN},
108   {NULL, 0, 0}
109 };
110
111 #define E_COUNT 0
112 #define E_VAL   1
113 #define E_KTO   2
114 #define E_BLZ   3
115 #define E_LEN   0
116
117 /*
118  *  Second: Some low level routines
119  */
120
121 size_t dtaus_nextrec (void **buf, FILE *f)
122 {
123   bzero (buf, 128);
124   return fread(buf, 128, 1, f);
125 }
126
127 char *upcase(char *s)
128 {
129   static char x[100];
130   static char *xp;
131   char *cp;
132
133   for (cp=s,xp=x; *cp; cp++,xp++) {
134     if (strchr(" 0123456789.,&-/+*$%ABCDEFGHIJKLMNOPQRSTUVWXYZ",*cp)) {
135         *xp = *cp;
136     } else if (strchr("abcdefghijklmnopqrstuvwxyz",*cp)) {
137       *xp = toupper(*cp);
138     } else if (strchr ("üÜäÄöÖß", *cp)) {
139       switch (*cp) {
140       case 'ü': *(xp++) = 'U'; *xp='E'; break;
141       case 'Ü': *(xp++) = 'U'; *xp='E'; break;
142       case 'ä': *(xp++) = 'A'; *xp='E'; break;
143       case 'Ä': *(xp++) = 'A'; *xp='E'; break;
144       case 'ö': *(xp++) = 'O'; *xp='E'; break;
145       case 'Ö': *(xp++) = 'O'; *xp='E'; break;
146       case 'ß': *(xp++) = 'S'; *xp='S'; break;
147       }
148     } else
149       /*
150        * Filter out all other characters since credit institutes won't
151        * accept the file otherwise.
152        */
153       *xp = ' ';
154   }
155   *xp = '\0';
156
157   return x;
158 }
159
160 char *downcase(char *s)
161 {
162   static char x[100];
163   char *cp;
164
165   memset (x, 0, sizeof (x));
166   strncpy (x, s, 99);
167   
168   for (cp=x;*cp;cp++)
169     if (isupper(*cp))
170       *cp = tolower(*cp);
171   return x;
172 }
173
174 char *strip_spaces (char *s)
175 {
176   int i;
177   char *p;
178
179   for (i=strlen(s);(s[i-1] == ' '||s[i-1] == '\t')&&i>0; i--)
180     s[i-1] = '\0';
181   for (p=s; *p==' '; p++);
182   return p;
183 }
184
185 char *strip_zeros (char *s)
186 {
187   char *p;
188
189   for (p=s; *p=='0'; p++);
190   return p;
191 }
192
193 char *strip_nondigits (char *s)
194 {
195   char *p;
196   char *x;
197
198   for (x=s,p=s;*x;x++)
199     if (isdigit (*x))
200       *(p++) = *x;
201   *(p++) = '\0';
202
203   return s;
204 }
205
206 char dtaus_char (void *buf, unsigned int pos)
207 {
208   static char res;
209   char *bufp = buf;
210
211   bufp+=pos;
212   memcpy(&res, bufp, 1);
213   return res;
214 }
215
216 char *string2real(char *s)
217 {
218   static char res[20];
219   char *cp = s;
220
221   cp+=strlen(s)-2;
222   strncpy(res, s, strlen(s)-2);
223   res[strlen(s)-2] = '.';
224   res[strlen(s)-1] = s[strlen(s)-2];
225   res[strlen(s)] = s[strlen(s)-1];
226   return res;
227 }
228
229 char *real2string(char *s)
230 {
231   static char res[20];
232   char *cp;
233
234   strcpy(res, s);
235   for (cp=res; *cp&&!(*cp == ',')&&!(*cp == '.');cp++);
236   *(cp++) = *(cp+1);
237   *(cp++) = *(cp+1);
238   *cp = '\0';
239   return res;
240 }
241
242 char *string2trans (char *s)
243 {
244   static char res[30];
245
246   res[0] = '\0';
247   if (!strcmp(s, "04000"))
248     sprintf (res, "Abbuchung");
249   else if (!strcmp(s, "05000"))
250     sprintf (res, "Einzug");
251   else if (!strcmp(s, "05005"))
252     sprintf (res, "E-Cash");
253   else if (!strcmp(s, "05006"))
254     sprintf (res, "E-Cash-A");
255   else if (!strcmp(s, "51000"))
256     sprintf (res, "Gutschrift");
257   else if (!strcmp(s, "53000"))
258     sprintf (res, "Lohn");
259   else if (!strncmp(s, "5400", 4))
260     sprintf (res, "Vermögen");
261   /*  else if (!strcmp(s, "56000"))
262     sprintf (res, ""); / * Überweisung öffentlicher Kassen */
263   return res;
264 }
265
266 char *trans2string (char *s)
267 {
268   static char res[30];
269
270   res[0] = '\0';
271   if (!strcmp(s, "Abbuchung"))
272     sprintf (res, "04000");
273   else if (!strcmp(s, "Einzug"))
274     sprintf (res, "05000");
275   else if (!strcmp(s, "E-Cash"))
276     sprintf (res, "05005");
277   else if (!strcmp(s, "E-Cash-A"))
278     sprintf (res, "05006");
279   else if (!strcmp(s, "Gutschrift"))
280     sprintf (res, "51000");
281   else if (!strcmp(s, "Lohn"))
282     sprintf (res, "53000");
283   else if (!strncmp(s, "Vermögen", 4))
284     sprintf (res, "5400");
285   /*  else if (!strcmp(s, ""))
286     sprintf (res, "56000"); / * Überweisung öffentlicher Kassen */
287   return res;
288 }
289
290 char *string2ext (char *s)
291 {
292   static char res[30];
293
294   res[0] = '\0';
295   if (!strcmp(s, "01"))
296     sprintf (res, "Kunde");
297   else if (!strcmp(s, "02"))
298     sprintf (res, "Text");
299   else if (!strcmp(s, "03"))
300     sprintf (res, "Auftraggeber");
301   return res;
302 }
303
304 char *ext2string (char *s)
305 {
306   static char res[3];
307
308   res[0] = '\0';
309   if (!strcmp(s, "Kunde"))
310     sprintf (res, "01");
311   else if (!strcmp(s, "Text"))
312     sprintf (res, "02");
313   else if (!strcmp(s, "Auftraggeber"))
314     sprintf (res, "03");
315   return res;
316 }
317     
318 unsigned long int dtaus_int(void *buf, unsigned int pos, unsigned int len)
319 {
320   char tmp[30];
321   char *bufp = buf;
322   static unsigned long int res;
323
324   bufp+=pos;
325   memcpy(tmp, bufp, len);
326   tmp[len] = '\0';
327   sscanf(tmp, "%lu", &res);
328   return res;
329 }
330
331 /*
332  * returns the first word in this line, returns it and shortens the
333  * line.
334  */
335 char *extract_ident (char *line)
336 {
337   char *c, *x, *y;
338   static char word[30];
339
340   if (strlen(line) > 0) {
341     x = index (line, ' ');
342     y = index (line, '\t');
343
344     if (!x && !y) {
345         strncpy(word, line, 29);
346         line[0] = '\0';
347         return word;
348     }
349
350     /* Check which index returns the lower value, and check if the
351        value is non-NULL */
352     if ((c = (x && x<y)?x:(y?y:x))) { 
353       strncpy(word, line, c - line);
354       word[c-line] = '\0';
355       for (;*c == '\t' || *c == ' '; c++);
356       for (x=line; *c; c++,x++)
357         *x = *c;
358       *x = '\0';
359       strcpy(word, downcase(word));
360       return word;
361     }
362     return NULL;
363   }
364   return line;
365 }
366
367 /*
368  * Pads a string with zero's on the left side.
369  */
370 char *padzeroclip (char *s, int len)
371 {
372   char *p, *q;
373
374   if (strlen(s) == len) return s;
375   if (strlen(s) > len) {
376       q=s+len;
377       *(q--) = '\0';
378       return s;
379   }
380
381   q=s+len;
382   *(q--) = '\0';
383   for (p=s+strlen(s)-1;p>=s;p--)
384     *(q--)=*p;
385   for (;q>=s;) *(q--)='0';
386   return s;
387 }
388
389 int rec_index(char *ident, int type)
390 {
391   int i;
392   dtaus_record *rec = NULL;
393
394   switch (type) {
395   case REC_A:   rec = recA; break;
396   case REC_C:   rec = recC; break;
397   case REC_E:   rec = recE; break;
398   }
399
400   for (i=0; (rec[i].name); i++) {
401     if (!strcmp(ident, downcase(rec[i].name)))
402       return i;
403   }
404
405   return -1;
406 }
407
408 size_t control_nextline (void **buf, int len, FILE *f)
409 {
410   char line[100];
411   char tmp[100];
412   char *cp;
413   int i;
414
415   bzero (line, sizeof(line));
416   bzero (buf, len);
417   cp = line;
418
419   while (!strlen(line) && (cp = fgets(line, 100, f))) {
420     if (strlen(line)) {
421       if (line[0] != '#') {
422         if (line[strlen(line)-1] != '\n') { 
423           strcpy(tmp, line);
424           while (tmp[strlen(tmp)-1] != '\n' && (cp = fgets(tmp, 100, f)));
425         } else
426           line[strlen(line)-1] = '\0';
427         if (line[strlen(line)-1] == '\r')
428           line[strlen(line)-1] = '\0';
429         for (i=strlen(line);(line[i-1] == ' '||line[i-1] == '\t')&&i>0; i--)
430           line[i-1] = '\0';
431         if (line[0] == '#')
432           line[0] = '\0';
433       } else
434         line[0] = '\0';
435     }
436   }
437   for (cp=line; *cp==' '; cp++);
438
439   if (strlen(cp)) {
440     memcpy(buf, cp, strlen(cp));
441     return 1;
442   } else
443     return 0;
444 }
445
446 char *get_date()
447 {
448   static char res[10];
449   time_t timer;
450   struct tm *loctime;
451
452   timer = time ( NULL );
453   loctime = localtime(&timer);
454   sprintf(res, "%02d.%02d.%02d", loctime->tm_mday, loctime->tm_mon+1, loctime->tm_year % 100);
455   return res;
456 }
457
458 void dtaus_prepareA (char *buf)
459 {
460   int i;
461   time_t timer;
462   struct tm *loctime;
463   char tmp[10];
464
465   bzero (buf, 129);
466   timer = time ( NULL );
467   loctime = localtime(&timer);
468
469   buf[0] = '0';
470   buf[1] = '1';
471   buf[2] = '2';
472   buf[3] = '8';
473   buf[4] = 'A';
474   for (i=15;i<15+8; i++) buf[i] = '0';
475   sprintf(tmp, "%02d%02d%02d", loctime->tm_mday, loctime->tm_mon+1, loctime->tm_year % 100);
476   for (i=0; i<6; i++) buf[50+i] = tmp[i];
477   for (i=56;i<56+4; i++) buf[i] = ' ';
478   for (i=70;i<70+10; i++) buf[i] = '0';
479   for (i=80;i<80+48; i++) buf[i] = ' ';
480 }
481
482 void dtaus_prepareC (char *buf, int normaltext, int maxtext)
483 {
484   int i;
485   int appendix = 0;
486   div_t res;
487
488   bzero (buf, 257);
489   buf[0] = '0';
490
491   if (normaltext)
492     appendix = 1;
493   if (maxtext) {
494     res = div (maxtext-1, 4);
495     appendix += res.quot;
496     if (res.rem) appendix++;
497   }
498   i = 187 + (appendix * 29);
499
500   /* Bail out if the number is too large, shouldn't be possible though */
501   if (i>1000)
502     exit (1);
503
504   buf[1] = (i/100)+48;i-=(i/100)*100;
505   buf[2] = (i/10)+48;i-=(i/10)*10;
506   buf[3] = i+48;
507   buf[4] = 'C';
508
509   for (i=31;i<31+13; i++) buf[i] = '0';
510   buf[49] = ' ';
511   for (i=79;i<79+11; i++) buf[i] = '0';
512   for (i=90;i<90+3; i++) buf[i] = ' ';
513   for (i=120;i<120+8; i++) buf[i] = ' ';
514   for (i=182;i<182+3; i++) buf[i] = ' ';
515   for (i=185;i<185+2; i++) buf[i] = '0';
516   for (i=187;i<187+(29*2); i++) buf[i] = ' ';
517   for (i=245;i<245+11; i++) buf[i] = ' ';
518 }
519
520 void dtaus_prepareE (char *buf)
521 {
522   int i;
523
524   bzero (buf, 129);
525   buf[0] = '0';
526   buf[1] = '1';
527   buf[2] = '2';
528   buf[3] = '8';
529   buf[4] = 'E';
530   for (i=5;i<5+5; i++) buf[i] = ' ';
531   for (i=64;i<64+13; i++) buf[i] = '0';
532   for (i=77;i<77+51; i++) buf[i] = ' ';
533 }
534
535 int dtaus_writeA(FILE *f, char **values)
536 {
537   char buf[129];
538   char tmp[30];
539   int i;
540   
541   for (i=0; (recA[i].name); i++)
542     if ((recA[i].type == REQ) && !values[i]) {
543       fprintf (stderr, "Anfangsdatensatz ist nicht vollständig, kein %s.\n", recA[i].name);
544       return 0;
545     }
546   if (!(((values[A_TRANS][0] == 'L')||(values[A_TRANS][0] == 'G'))
547         &&((values[A_TRANS][1] == 'B')||(values[A_TRANS][1] == 'K')))) {
548     fprintf (stderr, "Ungültiger Typ, nur LK, GK, LB oder GB erlaubt.\n");
549     return 0;
550   }
551
552   i=A_NAME;if (values[i] && strlen(values[i]) > recA[i].len)
553     values[i][recA[i].len] = '\0';
554
555   dtaus_prepareA(buf);
556   buf[5] = values[A_TRANS][0];
557   buf[6] = values[A_TRANS][1];
558   sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[A_BLZ]),8));
559   for (i=0; i<8; i++) buf[recA[A_BLZ].pos+i] = tmp[i];
560   sprintf (tmp, "%-27s", upcase(values[A_NAME]));
561   for (i=0; i<27; i++) buf[recA[A_NAME].pos+i] = tmp[i];
562   sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[A_KTO]),10));
563   for (i=0; i<10; i++) buf[recA[A_KTO].pos+i] = tmp[i];
564
565   fputs(buf, f);
566   return 1;
567 }
568
569 int dtaus_writeC(FILE *f, char **valuesA, char **values, char **text)
570 {
571   char buf[257];
572   char appendix[129];
573   char tmp[30];
574   int i, k;
575   int maxtext = 0;
576   int fieldnr;
577   div_t res;
578
579   if (text)
580     for (maxtext=0;text[maxtext];maxtext++);
581
582 #if DEBUG
583   for (i=0; (recC[i].name); i++)
584     if (values[i])
585       printf ("%s: %s\n", recC[i].name, values[i]);
586 #endif
587
588   for (i=0; (recC[i].name); i++)
589     if ((recC[i].type == REQ) && !values[i]) {
590       fprintf (stderr, "Datensatz ist nicht vollständig, kein %s.\n", recC[i].name);
591       return 0;
592     }
593   sprintf (tmp, "%s", trans2string(values[C_TRANS]));
594   if (!strlen(tmp)) {
595     fprintf (stderr, "Ungültiger Typ, nur Abbuchung, Einzug, E-Cash, E-Cash-A, Gutschrift und Lohn erlaubt.\n");
596     return 0;
597   }
598
599   i=C_TEXT;if (values[i] && strlen(values[i]) > recC[i].len)
600     values[i][recC[i].len] = '\0';
601   i=C_ZWECK;if (values[i] && strlen(values[i]) > recC[i].len)
602     values[i][recC[i].len] = '\0';
603   i=C_MYNAM;if (values[i] && strlen(values[i]) > recC[i].len)
604     values[i][recC[i].len] = '\0';
605   i=C_TEXT;if (values[i] && strlen(values[i]) > recC[i].len)
606     values[i][recC[i].len] = '\0';
607   i=C_EXT;if (values[i] && strlen(values[i]) > recC[i].len)
608     values[i][recC[i].len] = '\0';
609
610   dtaus_prepareC (buf, values[C_TEXT] != NULL, maxtext);
611   for (i=0; i<5; i++) buf[recC[C_TRANS].pos+i] = tmp[i];
612   if (values[C_MYBLZ])
613     sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[C_MYBLZ]),8));
614   else
615     sprintf (tmp, "%s", padzeroclip (strip_nondigits (valuesA[A_BLZ]),8));
616   for (i=0; i<recC[C_MYBLZ].len; i++) buf[5+i] = tmp[i];
617   for (i=0; i<recC[C_MYBLZ].len; i++) buf[recC[C_MYBLZ].pos+i] = tmp[i];
618   sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[C_BLZ]),8));
619   for (i=0; i<recC[C_BLZ].len; i++) buf[recC[C_BLZ].pos+i] = tmp[i];
620   sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[C_KTO]),10));
621   for (i=0; i<recC[C_KTO].len; i++) buf[recC[C_KTO].pos+i] = tmp[i];
622   sprintf (tmp, "%s", padzeroclip (real2string(values[C_VAL]),11));
623   for (i=0; i<recC[C_VAL].len; i++) buf[recC[C_VAL].pos+i] = tmp[i];
624   if (values[C_MYKTO])
625     sprintf (tmp, "%s", padzeroclip (strip_nondigits (values[C_MYKTO]),10));
626   else
627     sprintf (tmp, "%s", padzeroclip (strip_nondigits (valuesA[A_KTO]),10));
628   for (i=0; i<recC[C_MYKTO].len; i++) buf[recC[C_MYKTO].pos+i] = tmp[i];
629   sprintf (tmp, "%-27s", upcase(values[C_NAME]));
630   for (i=0; i<recC[C_NAME].len; i++) buf[recC[C_NAME].pos+i] = tmp[i];
631   if (values[C_MYNAM])
632     sprintf (tmp, "%-27s", upcase(values[C_MYNAM]));
633   else
634     sprintf (tmp, "%-27s", upcase(valuesA[A_NAME]));
635   for (i=0; i<recC[C_MYNAM].len; i++) buf[recC[C_MYNAM].pos+i] = tmp[i];
636   sprintf (tmp, "%-27s", upcase(values[C_ZWECK]));
637   for (i=0; i<recC[C_ZWECK].len; i++) buf[recC[C_ZWECK].pos+i] = tmp[i];
638
639   if (values[C_TEXT]) {
640     buf[recC[C_TEXT].pos+0] = '0';
641     buf[recC[C_TEXT].pos+1] = '2';
642     sprintf (tmp, "%-27s", upcase(values[C_TEXT]));
643     for (i=0; i<recC[C_TEXT].len-2; i++) buf[recC[C_TEXT].pos+2+i] = tmp[i];
644   }
645
646   if (text) {
647     buf[recC[C_EXT].pos+0] = '0';
648     buf[recC[C_EXT].pos+1] = '2';
649     sprintf (tmp, "%-27s", upcase(text[0]));
650     for (i=0; i<recC[C_EXT].len-2; i++) buf[recC[C_EXT].pos+2+i] = tmp[i];
651
652     res = div (maxtext-1, 4);
653     i=res.quot;
654     if (res.rem) i++;
655
656     buf[185+0] = (i/10)+48;i-=(i/10)*10;
657     buf[185+1] = i+48;
658   }
659
660   fputs(buf, f);
661
662   if (text && maxtext > 1) {
663     fieldnr=1;
664     while (fieldnr<maxtext) {
665       memset (appendix, ' ', 128);
666       appendix[128] = '\0';
667       for (k=0; k<4 && (fieldnr+k)<maxtext; k++) {
668         sprintf (tmp, "%-27s", upcase(text[fieldnr+k]));
669         appendix[k*29] = '0';
670         appendix[(k*29)+1] = '2';
671         for (i=0; i<recC[C_TEXT].len-2; i++) appendix[(k*29)+2+i] = tmp[i];
672       }
673       fputs(appendix, f);
674       fieldnr += k;
675     }
676   }
677
678   return 1;
679 }
680
681 int dtaus_writeE(FILE *f, int count, bigint sum, bigint blz, bigint kto)
682 {
683   char buf[129];
684   char tmp[30];
685   int i;
686   
687   dtaus_prepareE(buf);
688
689   sprintf (tmp, "%07d", count);
690   for (i=0; i<recE[E_COUNT].len; i++) buf[recE[E_COUNT].pos+i] = tmp[i];
691   bigint_sprintf (tmp, "%s", sum);
692   padzeroclip (tmp,13);
693   for (i=0; i<recE[E_VAL].len; i++) buf[recE[E_VAL].pos+i] = tmp[i];
694   bigint_sprintf (tmp, "%s", sum);
695   padzeroclip (tmp,13);
696   for (i=0; i<recE[E_VAL].len; i++) buf[recE[E_VAL].pos+i] = tmp[i];
697   bigint_sprintf (tmp, "%s", kto);
698   padzeroclip (tmp,17);
699   for (i=0; i<recE[E_KTO].len; i++) buf[recE[E_KTO].pos+i] = tmp[i];
700   bigint_sprintf (tmp, "%s", blz);
701   padzeroclip (tmp,17);
702   for (i=0; i<recE[E_BLZ].len; i++) buf[recE[E_BLZ].pos+i] = tmp[i];
703
704   fputs(buf, f);
705   return 1;
706 }
707
708 void printctln(FILE *f, char *field, char *value)
709 {
710   if (strlen(field) && strlen(value))
711     fprintf(f, "  %s\t%s\n", field, value);
712 }
713
714
715 /*
716  *  Third: Some high level routines
717  */
718
719 void dtaus2control (char *cdtaus, char *ccontrol)
720 {
721   FILE *fdtaus, *fcontrol;
722   void *buf;
723   void *bufp;
724   char tmp[30];
725   char x[30];
726   int index;
727   int extC;
728
729   if (!cdtaus) {
730     if (!(fdtaus = fopen("DTAUS0.TXT", "r")))
731       if (!(fdtaus = fopen("dtaus0.txt", "r")))
732         return;
733   } else {
734     if (!strcmp (cdtaus, "-"))
735       fdtaus = stdin;
736     else
737       if (!(fdtaus = fopen(cdtaus, "r")))
738         return;
739   }
740   if (!ccontrol) 
741     fcontrol = stdout;
742   else
743     if (!strcmp (ccontrol, "-"))
744       fcontrol = stdout;
745     else
746       if (!(fcontrol = fopen(ccontrol, "w")))
747         return;
748   if (!(buf = (char *)malloc (512)))
749     return;
750
751   /* 
752    * Record A lesen
753    */
754   if (dtaus_nextrec(buf, fdtaus) == 1) {
755     if (dtaus_char(buf,4) == 'A') {
756       fprintf(fcontrol, "BEGIN {\n");
757       bufp = buf;
758
759       for (index=A_TRANS; index < A_DATE; index++) {
760         bufp = buf + recA[index].pos;
761         memcpy(tmp, bufp, recA[index].len); tmp[recA[index].len] = '\0';
762         printctln(fcontrol, recA[index].name, strip_zeros(strip_spaces(tmp)));
763       }
764
765       index = A_DATE; bufp = buf + recA[index].pos;
766       memcpy(tmp, bufp, recA[index].len); tmp[recA[index].len] = '\0';
767       printctln(fcontrol, recA[index].name, strip_spaces(tmp));
768
769       index = A_EURO; bufp = buf + recA[index].pos;
770       memcpy(tmp, bufp, recA[index].len); tmp[recA[index].len] = '\0';
771       printctln(fcontrol, recA[index].name, strip_zeros(strip_spaces(tmp)));
772
773       fprintf(fcontrol, "}\n\n");
774     } else {
775       fprintf (stderr, "Datei fängt nicht mit dem Anfangsdatensatz an.\n");
776       return;
777     }
778   } else {
779     fprintf (stderr, "Der Anfangsdatensatz ist kaputt.\n");
780     return;
781   }
782
783   /*
784    * Record C lesen
785    */
786   if (dtaus_nextrec(buf, fdtaus) == 1) {
787     while (dtaus_char(buf,4) == 'C') {
788       bufp = buf + 128;
789       if (dtaus_nextrec(bufp, fdtaus) != 1) {
790         fprintf (stderr, "Der zweite Teil der Transaktion ist kaputt.\n");
791         return;
792       } else {
793         fprintf(fcontrol, "{\n");
794
795         for (index=C_NAME; index <= C_EURO; index++) {
796           bufp = buf + recC[index].pos;
797           memcpy(tmp, bufp, recC[index].len); tmp[recC[index].len] = '\0';
798           if (index == C_VAL)
799             printctln(fcontrol, recC[index].name, strip_zeros(string2real(tmp)));
800           else if (index == C_TRANS)
801             printctln(fcontrol, recC[index].name, strip_zeros(string2trans(tmp)));
802           else
803             printctln(fcontrol, recC[index].name, strip_zeros(strip_spaces(tmp)));
804         }
805
806         for (index=C_TEXT; index <= C_EXT; index++) {
807           if (!(dtaus_char(buf,recC[index].pos) == ' ')) {
808             bufp = buf + recC[index].pos;
809             memcpy(x, bufp, 2); tmp[2] = '\0'; bufp+=2;
810             memcpy(tmp, bufp, recC[index].len-2); tmp[recC[index].len-2] = '\0';
811             printctln(fcontrol, string2ext(x), strip_spaces(tmp));
812           }
813         }
814
815         /* Number of extension records for this C record */
816         extC = dtaus_int(buf, 185, 2);
817
818       }
819       if (dtaus_nextrec(buf, fdtaus) != 1)
820         bzero (buf, sizeof(buf));
821
822       /*
823        * Are there extension records that we have to check?
824        *
825        * 2nd half of the AND is wrong, but since dtaus < 0.5 wrote 01
826        *     instead of 00 we should let it in so it can read its own
827        *     old files...  *sigh*
828        */
829       while (extC > 0 && dtaus_char(buf,4) != 'C' && dtaus_char(buf,4) != 'E') {
830         for (index=0; index < 4; index++) {
831           if ((dtaus_char(buf,index*29) != ' ')) {
832             bufp = buf + index*29;
833             memcpy(x, bufp, 2); tmp[2] = '\0'; bufp+=2;
834             memcpy(tmp, bufp, recC[C_TEXT].len-2); tmp[recC[C_TEXT].len-2] = '\0';
835             printctln(fcontrol, string2ext(x), strip_spaces(tmp));
836           }
837         }
838         if (dtaus_nextrec(buf, fdtaus) != 1)
839           bzero (buf, sizeof(buf));
840         extC--;
841       }
842       fprintf(fcontrol, "}\n");
843     }
844   }
845
846   /*
847    * Record E lesen
848    *   (gelesen ist er eigentlich schon...)
849    */
850   if (dtaus_char(buf,4) == 'E') {
851     if (dtaus_char(buf,4) == 'E') {
852       fprintf(fcontrol, "\nEND {\n");
853
854       for (index=E_COUNT; index <= E_BLZ; index++) {
855         bufp = buf + recE[index].pos;
856         memcpy(tmp, bufp, recE[index].len); tmp[recE[index].len] = '\0';
857         if (index == E_VAL)
858           printctln(fcontrol, recE[index].name, strip_zeros(string2real(tmp)));
859         else
860           printctln(fcontrol, recE[index].name, strip_zeros(tmp));
861       }
862
863       fprintf(fcontrol, "}\n");
864     } else {
865       fprintf (stderr, "Das ist kein Abschlußdatensatz.\n");
866       return;
867     }
868   } else {
869     fprintf (stderr, "Der Abschlußdatensatz ist leer oder kaputt.\n");
870     return;
871   }
872   fclose(fcontrol);
873   fclose(fdtaus);
874 }
875
876 int control2dtaus (char *ccontrol, char *cdtaus, char *cbeleg, char *ccheck)
877 {
878   FILE *fdtaus, *fcontrol, *fbeleg, *fcheck;
879   void *buf;
880   char *ident;
881   int  recindex;
882   char tmp[30];
883   char line[100];
884   char *valA[A_LEN], *valC[C_LEN];
885   int count;
886   bigint sum_val, sum_blz, sum_kto, bi;
887   char **text = NULL;
888   char *cp;
889   int textindex = 0;
890
891   if (!cdtaus) {
892     if (!(fdtaus = fopen("dtaus0.txt", "w")))
893       return 0;
894   } else {
895     if (!strcmp (cdtaus, "-"))
896       fdtaus = stdout;
897     else
898       if (!(fdtaus = fopen(cdtaus, "w")))
899         return 0;
900   }
901   if (!ccontrol) {
902     if (!(fcontrol = fopen("dtaus0.ctl", "r")))
903       if (!(fcontrol = fopen("DTAUS0.CTL", "r")))
904         return 0;
905   } else {
906     if (!strcmp (ccontrol, "-"))
907       fcontrol = stdin;
908     else
909       if (!(fcontrol = fopen(ccontrol, "r")))
910         return 0;
911   }
912   if (!cbeleg) {
913     if (!(fbeleg = fopen("dtaus0.doc", "w")))
914       return 0;
915   } else {
916     if (!(fbeleg = fopen(cbeleg, "w")))
917       return 0;
918   }
919   if (!ccheck)
920     fcheck = stdout;
921   else
922     if (!(fcheck = fopen(ccheck, "w")))
923       return 0;
924
925
926   if (!(buf = (char *)malloc (512)))
927     return 0;
928
929   /* 
930    * Record A lesen
931    */
932   bzero(valA, sizeof(valA));
933   control_nextline ((void *)line, 100, fcontrol);
934   ident = extract_ident(line);
935   if (!strcmp(ident, "begin") && (line[0] == '{')) {
936     control_nextline ((void *)line, 100, fcontrol);
937     while (strlen(line) && line[0] != '}') {
938       ident = extract_ident(line);
939       if ((recindex = rec_index(ident, REC_A)) != -1)
940         if (recA[recindex].type != IGN)
941           if ((valA[recindex] = (char *)malloc (strlen(line)+1)))
942             strcpy(valA[recindex], line);
943       control_nextline ((void *)line, 100, fcontrol);
944     }
945     if (((recindex = rec_index("art", REC_A)) != -1) && valA[recindex] && strlen(valA[recindex])) {
946       fprintf(fbeleg, "\n\n");
947       fprintf(fbeleg, "\n    Begleitzettel\n\n");
948       fprintf(fbeleg, "\n    Belegloser Datentraegeraustausch\n\n");
949       if (valA[recindex][0] == 'L')
950         fprintf(fbeleg, "\n    Sammeleinziehungsauftrag\n\n");
951       else if (valA[recindex][0] == 'G')
952         fprintf(fbeleg, "\n    Sammelueberweisungsauftrag\n\n");
953       else
954         fprintf(fbeleg, "\n    Sammelauftrag\n\n");
955       fprintf(fbeleg, "\n    VOL ........................:\n");
956       fprintf(fbeleg, "\n    Erstellungsdatum ...........: %s\n", get_date());
957       fprintf(fbeleg, "\n    Waehrung ...................: DM\n");
958     }
959     if (!dtaus_writeA(fdtaus, valA)) {
960       fprintf (stderr, "Konnte den Anfangsdatensatz nicht schreiben.\n");
961       return 0;
962     }
963
964     fprintf (fcheck, "\n\n\n");
965     if (valA[recindex][0] == 'L')
966       fprintf (fcheck, "    Sammeleinziehungsauftrag\n\n");
967     else if (valA[recindex][0] == 'G')
968       fprintf (fcheck, "    Sammelueberweisungsauftrag\n\n");
969     else
970       fprintf (fcheck, "    Sammelauftrag\n\n");
971     fprintf (fcheck, "    Erstellungsdatum : %s\n\n", get_date());
972     fprintf (fcheck, "    Waehrung         : DM\n\n\n");
973     fprintf (fcheck, "     %-10s  %-8s  %-30s   %12s\n", "Kontonr.", "BLZ", "Name", "Betrag");
974     fprintf (fcheck, "    --------------------------------------------------------------------\n");
975   } else {
976     fprintf (stderr, "Datei fängt nicht mit dem Anfangsdatensatz (BEGIN) an.\n");
977     return 0;
978   }
979
980   /* 
981    * Record C lesen
982    */
983   count = 0;
984   sum_val = bigint_int(0);
985   sum_blz = bigint_int(0);
986   sum_kto = bigint_int(0);
987   bzero(valC, sizeof(valC));
988   control_nextline ((void *)line, 100, fcontrol);
989   if (line[0] == '{') {
990     while (strlen(line) && line[0] == '{') {
991       control_nextline ((void *)line, 100, fcontrol);
992       if (text) {
993         for (textindex=0; textindex < MAX_TEXT && text[textindex]; textindex++)
994           free (text[textindex]);
995         free (text);
996         text = NULL;
997       }
998       while (strlen(line) && line[0] != '}') {
999         ident = extract_ident(line);
1000         if ((recindex = rec_index(ident, REC_C)) != -1)
1001           if (recC[recindex].type != IGN) {
1002             /*
1003              * Special exception to support multiple Text fields
1004              */
1005             if (recindex == C_TEXT && valC[recindex]) {
1006               if (!text) {
1007                 if ((text = (char **)malloc ((MAX_TEXT+1) * sizeof (char *))) == NULL)
1008                   return 0;
1009                 else {
1010                   textindex = 0;
1011                   memset (text, 0, (MAX_TEXT+1) * sizeof (char *));
1012                 }
1013               }
1014               if (textindex < MAX_TEXT) {
1015                 if ((cp = (char *)malloc (strlen (line) + 1))) {
1016                   strcpy (cp, line);
1017                   cp[strlen (line)] = '\0';
1018                   text[textindex++] = cp;
1019                 }
1020               }
1021             } else {
1022               if ((valC[recindex] = (char *)malloc (strlen(line)+1)))
1023                 strcpy(valC[recindex], line);
1024               else
1025                 return 0;
1026             }
1027           }
1028         control_nextline ((void *)line, 100, fcontrol);
1029       }
1030       if (!dtaus_writeC(fdtaus, valA, valC, text)) {
1031         fprintf (stderr, "Konnte den regulären Datensatz nicht schreiben.\n");
1032         return 0;
1033       }
1034       count++;
1035       bi = bigint_string(real2string(valC[C_VAL])); sum_val = bigint_add(sum_val, bi);
1036       bi = bigint_string(valC[C_BLZ]); sum_blz = bigint_add(sum_blz, bi);
1037       bi = bigint_string(valC[C_KTO]); sum_kto = bigint_add(sum_kto, bi);
1038
1039       fprintf (fcheck, "     %10s  %8s  %-30s   %12s\n", valC[C_KTO], valC[C_BLZ], valC[C_NAME], valC[C_VAL]);
1040       for (recindex=0; recindex<C_LEN; recindex++)
1041         if (valC[recindex])
1042           free(valC[recindex]);
1043       bzero(valC, sizeof(valC));
1044       control_nextline ((void *)line, 100, fcontrol);
1045     }
1046   } else {
1047     fprintf (stderr, "Kein regulärer Datensatz?\n");
1048     return 0;
1049   }
1050
1051   /* 
1052    * Record E lesen
1053    */
1054   dtaus_writeE(fdtaus, count, sum_val, sum_blz, sum_kto);
1055   fprintf (fcheck, "    --------------------------------------------------------------------\n");
1056   bigint_sprintf (tmp, "%s", sum_val);
1057   fprintf (fbeleg, "\n    Anzahl .....................: %d\n", count);
1058   recindex=strlen(tmp);
1059   tmp[recindex+1] = '\0';
1060   tmp[recindex] = tmp[recindex-1];
1061   tmp[recindex-1] = tmp[recindex-2];
1062   tmp[recindex-2] = '.';
1063   fprintf (fcheck, "     %-52s %14s\n", "Summe", tmp);
1064   fprintf (fbeleg, "\n    Summe ......................: %s\n", tmp);
1065   bigint_sprintf (tmp, "%s", sum_kto);
1066   fprintf (fbeleg, "\n    Kontrollsumme Kontonummern .: %s\n", tmp);
1067   bigint_sprintf (tmp, "%s", sum_blz);
1068   fprintf (fbeleg, "\n    Kontrollsumme Bankleitzahlen: %s\n", tmp);
1069   fprintf (fbeleg, "\n    Unsere Kontonummer .........: %s\n", valA[A_KTO]);
1070   fprintf (fbeleg, "\n    Unsere Bankleitzahl ........: %s\n", valA[A_BLZ]);
1071   fprintf (fbeleg, "\n\n\n\n\n    __________________________________________________\n");
1072   fprintf (fbeleg, "    Ort, Datum                     Unterschrift\n");
1073   for (recindex=0; recindex<A_LEN; recindex++)
1074     if (valA[recindex])
1075       free(valA[recindex]);
1076   fclose(fdtaus);
1077   fclose(fcontrol);
1078   fclose(fbeleg);
1079   if (ccheck)
1080     fclose(fcheck);
1081   return count;
1082 }