1 
2 /*
3  * fecfg146.c
4  *
5  * This module contains routines that read in structures from
6  * FASTEECHO configuration files in a portable way, i.E. they will even
7  * work in cases where a fread(&structure, sizeof(structure), 1, stream)
8  * would fail because of structure packing or big endian problems.
9  *
10  * Only those structures that are of importance to MsgEd have been
11  * implemented.
12  *
13  * Written 04-Oct-98 by Tobias Ernst and donated to the Public Domain.
14  *
15  */
16 
17 #include <assert.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 
22 #include "fecfg146.h"
23 
24 /*
25  *  get_dword
26  *
27  *  Reads in a 4 byte word that is stored in little endian (Intel) notation
28  *  and converts it to the local representation n an architecture-
29  *  independent manner
30  */
31 
32 #define get_dword(ptr) \
33    ((unsigned long)((ptr)[0]) | \
34     (((unsigned long)((ptr)[1])) << 8)  | \
35     (((unsigned long)((ptr)[2])) << 16) | \
36     (((unsigned long)((ptr)[3])) << 24))
37 
38 /*
39  *  get_word
40  *
41  *  Reads in a 2 byte word that is stored in little endian (Intel) notation
42  *  and converts it to the local representation in an architecture-
43  *  independent manner
44  */
45 
46 #define get_word(ptr) \
47     ((unsigned short)(ptr)[0] | \
48      (((unsigned short)(ptr)[1]) << 8 ))
49 
50 /*
51  * read_setup_ge
52  *
53  * reads a SETUP_GE structure.
54  *
55  */
56 
read_fe_config(CONFIG * c,FILE * fp)57 int read_fe_config(CONFIG *c, FILE *fp)
58 {
59     unsigned char *buffer = (unsigned char *) malloc(FE_CONFIG_SIZE);
60     unsigned char *pbuf;
61     int i;
62 
63     pbuf = buffer;
64 
65     if (buffer == NULL)
66     {
67         return -1;
68     }
69 
70     if (fread(buffer, FE_CONFIG_SIZE, 1, fp) != 1)
71     {
72         free(buffer);
73         return -1;
74     }
75 
76     c->revision = get_word(pbuf); pbuf += 2;
77     c->flags    = get_dword(pbuf); pbuf += 4;
78     c->NodeCnt  = get_word(pbuf); pbuf += 2;
79     c->AreaCnt  = get_word(pbuf); pbuf += 2;
80     c->unused1  = get_word(pbuf); pbuf += 2;
81 
82     memcpy(c->NetMPath, pbuf, _MAXPATH); pbuf += _MAXPATH;
83     memcpy(c->MsgBase, pbuf, _MAXPATH); pbuf += _MAXPATH;
84     memcpy(c->InBound, pbuf, _MAXPATH); pbuf += _MAXPATH;
85     memcpy(c->OutBound, pbuf, _MAXPATH); pbuf += _MAXPATH;
86     memcpy(c->Unpacker, pbuf, _MAXPATH); pbuf += _MAXPATH;
87     memcpy(c->LogFile, pbuf, _MAXPATH); pbuf += _MAXPATH;
88     memcpy(c->unused2, pbuf, 280); pbuf += 280;
89     memcpy(c->RulesDir, pbuf, _MAXPATH); pbuf += _MAXPATH;
90     memcpy(c->Unpacker2, pbuf, _MAXPATH); pbuf += _MAXPATH;
91     memcpy(c->UnprotInBound, pbuf, _MAXPATH); pbuf += _MAXPATH;
92     memcpy(c->StatFile, pbuf, _MAXPATH); pbuf += _MAXPATH;
93     memcpy(c->SwapPath, pbuf, _MAXPATH); pbuf += _MAXPATH;
94     memcpy(c->SemaphorePath, pbuf, _MAXPATH); pbuf += _MAXPATH;
95     memcpy(c->BBSConfigPath, pbuf, _MAXPATH); pbuf += _MAXPATH;
96     memcpy(c->QueuePath, pbuf, _MAXPATH); pbuf += _MAXPATH;
97     memcpy(c->RulesPrefix, pbuf, 32); pbuf += 32;
98     memcpy(c->RetearTo, pbuf, 40); pbuf += 40;
99     memcpy(c->LocalInBound, pbuf, _MAXPATH); pbuf += _MAXPATH;
100     memcpy(c->ExtAfter, pbuf, _MAXPATH - 4); pbuf += _MAXPATH - 4;
101     memcpy(c->ExtBefore, pbuf, _MAXPATH - 4); pbuf += _MAXPATH - 4;
102     memcpy(c->unused3, pbuf, 480); pbuf += 480;
103 
104     for (i = 0; i < 10; i++)
105     {
106         c->CC[i].what = *pbuf++;
107         memcpy(c->CC[i].object, pbuf, 31); pbuf += 31;
108         c->CC[i].conference = get_word(pbuf); pbuf += 2;
109     }
110 
111     c->security = *pbuf++;
112     c->loglevel = *pbuf++;
113     c->def_days = get_word(pbuf); pbuf += 2;
114     c->def_messages = get_word(pbuf); pbuf += 2;
115     memcpy(c->unused4, pbuf, 462); pbuf += 462;
116     c->autorenum = get_word(pbuf); pbuf += 2;
117     c->def_recvdays = get_word(pbuf); pbuf += 2;
118     c->openQQQs = *pbuf++;
119     c->Swapping = *pbuf++;
120     c->compressafter = get_word(pbuf); pbuf += 2;
121     c->afixmaxmsglen = get_word(pbuf); pbuf += 2;
122     c->compressfree = get_word(pbuf); pbuf += 2;
123 
124     memcpy(c->TempPath, pbuf, _MAXPATH); pbuf += _MAXPATH;
125 
126     c->graphics = *pbuf++;
127     c->BBSSoftware = *pbuf++;
128 
129     memcpy(c->AreaFixHelp, pbuf, _MAXPATH); pbuf += _MAXPATH;
130     memcpy(c->unused5, pbuf, 504); pbuf += 504;
131 
132     c->AreaFixFlags = get_word(pbuf); pbuf += 2;
133     c->QuietLevel = *pbuf++;
134     c->Buffers = *pbuf++;
135     c->FWACnt = *pbuf++;
136     c->GDCnt = *pbuf++;
137 
138     c->rescan_def.flags = get_word(pbuf); pbuf += 2;
139     c->rescan_def.days[0] = get_word(pbuf); pbuf += 2;
140     c->rescan_def.days[1] = get_word(pbuf); pbuf += 2;
141     c->rescan_def.msgs[0] = get_word(pbuf); pbuf += 2;
142     c->rescan_def.msgs[1] = get_word(pbuf); pbuf += 2;
143 
144     c->duperecords = get_dword(pbuf); pbuf += 4;
145 
146     c->arcext.inb = *pbuf++;
147     c->arcext.outb = *pbuf++;
148 
149     c->AFixRcptLen = get_word(pbuf); pbuf += 2;
150     c->AkaCnt = *pbuf++;
151     c->resv = *pbuf++;
152     c->maxPKT = get_word(pbuf); pbuf += 2;
153     c->sharing = *pbuf++;
154     c->sorting = *pbuf++;
155 
156     for (i=0; i < 11; i++)
157     {
158         memcpy(c->sysops[i].name, pbuf, 36); pbuf += 36;
159         c->sysops[i].resv = get_dword(pbuf); pbuf += 4;
160     }
161 
162     memcpy(c->AreaFixLog, pbuf, _MAXPATH); pbuf += _MAXPATH;
163     memcpy(c->TempInBound, pbuf, _MAXPATH); pbuf += _MAXPATH;
164 
165     c->maxPKTmsgs = get_word(pbuf); pbuf += 2;
166     c->RouteCnt = get_word(pbuf); pbuf += 2;
167     c->maxPACKratio = *pbuf++;
168     c->SemaphoreTimer = *pbuf++;
169     c->PackerCnt = *pbuf++;
170     c->UnpackerCnt = *pbuf++;
171     c->GroupCnt = *pbuf++;
172     c->OriginCnt = *pbuf++;
173     c->mailer = get_word(pbuf); pbuf += 2;
174     c->maxarcsize = get_word(pbuf); pbuf += 2;
175     c->maxarcdays = get_word(pbuf); pbuf += 2;
176     c->minInbPKTSize = get_word(pbuf); pbuf += 2;
177 
178     memcpy(c->reserved, pbuf, 804); pbuf += 804;
179 
180     c->AreaRecSize = get_word(pbuf); pbuf += 2;
181     c->GrpDefRecSize = get_word(pbuf); pbuf += 2;
182     c->MaxAreas = get_word(pbuf); pbuf += 2;
183     c->MaxNodes = get_word(pbuf); pbuf += 2;
184     c->NodeRecSize = get_word(pbuf); pbuf += 2;
185     c->offset = get_dword(pbuf); pbuf += 4;
186 
187     assert(pbuf - buffer == FE_CONFIG_SIZE);
188 
189     free(buffer);
190     return 0;
191 }
192 
read_fe_extension_header(ExtensionHeader * h,FILE * fp)193 int read_fe_extension_header(ExtensionHeader *h, FILE *fp)
194 {
195     unsigned char buffer[FE_EXTHEADER_SIZE];
196     unsigned char *pbuf;
197 
198     pbuf = buffer;
199 
200     if (fread(buffer, FE_EXTHEADER_SIZE, 1, fp) != 1)
201     {
202         return -1;
203     }
204 
205     h->type   = get_word(pbuf);  pbuf += 2;
206     h->offset = get_dword(pbuf); pbuf += 4;
207 
208     assert(pbuf - buffer == FE_EXTHEADER_SIZE);
209 
210     return 0;
211 }
212 
read_fe_address(FEAddress * a,FILE * fp)213 int read_fe_address(FEAddress *a, FILE *fp)
214 {
215     unsigned char buffer[FE_ADDRESS_SIZE];
216     unsigned char *pbuf;
217 
218     pbuf = buffer;
219 
220     if (fread(buffer, FE_ADDRESS_SIZE, 1, fp) != 1)
221     {
222         return -1;
223     }
224 
225     a->zone = get_word(pbuf); pbuf += 2;
226     a->net = get_word(pbuf); pbuf += 2;
227     a->node = get_word(pbuf); pbuf += 2;
228     a->point = get_word(pbuf); pbuf += 2;
229 
230     assert(pbuf - buffer == FE_ADDRESS_SIZE);
231 
232     return 0;
233 }
234 
235 
read_fe_sysaddress(SysAddress * a,FILE * fp)236 int read_fe_sysaddress(SysAddress *a, FILE *fp)
237 {
238     unsigned char buffer[FE_SYS_ADDRESS_SIZE];
239     unsigned char *pbuf;
240 
241     pbuf = buffer + FE_ADDRESS_SIZE;;
242 
243     if (read_fe_address(&(a->main), fp) == -1)
244     {
245         return -1;
246     }
247 
248     if (fread(pbuf, FE_SYS_ADDRESS_SIZE - FE_ADDRESS_SIZE, 1, fp) != 1)
249     {
250         return -1;
251     }
252 
253     memcpy(a->domain, pbuf, 28); pbuf += 28;
254 
255     a->pointnet = get_word(pbuf); pbuf += 2;
256     a->flags = get_dword(pbuf); pbuf += 4;
257 
258     assert(pbuf - buffer == FE_SYS_ADDRESS_SIZE);
259 
260     return 0;
261 }
262 
read_fe_area(Area * a,FILE * fp)263 int read_fe_area(Area *a, FILE *fp)
264 {
265     unsigned char buffer[FE_AREA_SIZE];
266     unsigned char *pbuf;
267     unsigned short temp;
268 
269     pbuf = buffer;
270 
271     if (fread(buffer, FE_AREA_SIZE, 1, fp) != 1)
272     {
273         return -1;
274     }
275 
276     memcpy(a->name, pbuf, 52); pbuf += 52;
277     a->board = get_word(pbuf); pbuf += 2;
278     a->conference = get_word(pbuf); pbuf += 2;
279     a->read_sec = get_word(pbuf); pbuf += 2;
280     a->write_sec = get_word(pbuf); pbuf += 2;
281 
282     temp = get_word(pbuf); pbuf += 2;
283     a->info.aka = temp & 0x00FF;
284     a->info.group = (temp >> 8) & 0x00FF;
285 
286     temp = get_word(pbuf); pbuf += 2;
287     a->flags.storage = temp & 0x000F;
288     a->flags.atype   = (temp >> 4) & 0x000F;
289     a->flags.origin  = (temp >> 8) & 0x001F;
290     a->flags.resv    = (temp >> 13) & 0x0007;
291 
292     temp = get_word(pbuf); pbuf += 2;
293     a->advflags.autoadded  = temp & 1;
294     a->advflags.tinyseen   = (temp >> 1) & 1;
295     a->advflags.cpd        = (temp >> 2) & 1;
296     a->advflags.passive    = (temp >> 3) & 1;
297     a->advflags.keepseen   = (temp >> 4) & 1;
298     a->advflags.mandatory  = (temp >> 5) & 1;
299     a->advflags.keepsysop  = (temp >> 6) & 1;
300     a->advflags.killread   = (temp >> 7) & 1;
301     a->advflags.disablepsv = (temp >> 8) & 1;
302     a->advflags.keepmails  = (temp >> 9) & 1;
303     a->advflags.hide       = (temp >> 10) & 1;
304     a->advflags.manual     = (temp >> 11) & 1;
305     a->advflags.umlaut     = (temp >> 12) & 1;
306     a->advflags.resv       = (temp >> 13) & 7;
307 
308     a->resv1 = get_word(pbuf); pbuf += 2;
309     a->seenbys = get_dword(pbuf); pbuf += 4;
310     a->resv2 = get_dword(pbuf); pbuf += 4;
311     a->days = get_word(pbuf); pbuf += 2;
312     a->messages = get_word(pbuf); pbuf += 2;
313     a->recvdays = get_word(pbuf); pbuf += 2;
314     memcpy(a->path, pbuf, _MAXPATH); pbuf += _MAXPATH;
315     memcpy(a->desc, pbuf, 52); pbuf += 52;
316 
317     assert(pbuf - buffer == FE_AREA_SIZE);
318 
319     return 0;
320 }
321 
read_fe_node(Node * n,FILE * fp,size_t length)322 int read_fe_node(Node *n, FILE *fp, size_t length)
323 {
324     unsigned char buffer[FE_NODE_SIZE];
325     unsigned char *pbuf;
326     unsigned long temp;
327 
328     if (read_fe_address(&(n->addr), fp) == -1) return -1;
329     if (read_fe_address(&(n->arcdest), fp) == -1) return -1;
330 
331     pbuf = buffer + (2 * FE_ADDRESS_SIZE);
332 
333     if (fread(buffer + 2 * FE_ADDRESS_SIZE, (FE_NODE_SIZE - (2 * FE_ADDRESS_SIZE)), 1, fp) != 1)
334     {
335         return -1;
336     }
337 
338     n->aka = *pbuf++;
339     n->autopassive = *pbuf++;
340     n->newgroup = *pbuf++;
341     n->resv1 = *pbuf++;
342                                 /* because pbuf is little endian, we can read a
343                                    whole dword even if it only contains a 24
344                                    bit value. */
345     temp = get_dword(pbuf) & 0x00FFFFFFUL; pbuf+=3;
346 
347     n->flags.passive          =temp & 1; temp>>=1;
348     n->flags.dddd             =temp & 1; temp>>=1;
349     n->flags.arcmail060       =temp & 1; temp>>=1;
350     n->flags.tosscan          =temp & 1; temp>>=1;
351     n->flags.umlautnet        =temp & 1; temp>>=1;
352     n->flags.exportbyname     =temp & 1; temp>>=1;
353     n->flags.allowareacreate  =temp & 1; temp>>=1;
354     n->flags.disablerescan    =temp & 1; temp>>=1;
355     n->flags.arc_status       =temp & 3; temp>>=2;
356     n->flags.arc_direct       =temp & 1; temp>>=1;
357     n->flags.noattach         =temp & 1; temp>>=1;
358     n->flags.mgr_status       =temp & 3; temp>>=2;
359     n->flags.mgr_direct       =temp & 1; temp>>=1;
360     n->flags.not_help         =temp & 1; temp>>=1;
361     n->flags.not_notify       =temp & 1; temp>>=1;
362     n->flags.packer           =temp & 15; temp>>=4;
363     n->flags.packpriority     =temp & 1; temp>>=1;
364     n->flags.resv             =temp & 3; temp>>=2;
365 
366     /* Possible here need bits parsing (n->afixflags is union: bit structure and short) */
367     n->afixflags.afixflags = get_word(pbuf); pbuf+=2;
368 
369     n->resv2 = get_word(pbuf); pbuf+=2;
370     memcpy(n->password, pbuf, 9); pbuf+=9;
371     memcpy(n->areafixpw, pbuf, 9); pbuf+=9;
372 
373     n->sec_level  = get_word(pbuf);  pbuf+=2;
374     n->groups     = get_dword(pbuf); pbuf+=4;
375     n->resv3      = get_dword(pbuf); pbuf+=4;
376     n->resv4      = get_word(pbuf);  pbuf+=2;
377     n->maxarcsize = get_word(pbuf);  pbuf+=2;
378 
379     memcpy(n->name, pbuf, 36); pbuf+=36;
380 
381     assert(pbuf - buffer == FE_NODE_SIZE);
382 
383                                 /* Now read the variable length part */
384 
385     if (length <= FE_NODE_SIZE ||
386         (n->areas = malloc(length - FE_NODE_SIZE)) == NULL ||
387         fread(n->areas, length - FE_NODE_SIZE, 1, fp) != 1)
388     {
389         return -1;
390     }
391 
392     return 0;
393 }
394 
free_fe_node(Node * n)395 void free_fe_node(Node *n)
396 {
397     if (n != NULL && n->areas != NULL)
398         free(n->areas);
399 }
400 
read_fe_packers(Packers * p,FILE * fp)401 int read_fe_packers(Packers *p, FILE *fp)
402 {
403     unsigned char buffer[FE_PACKERS_SIZE];
404     unsigned char *pbuf = buffer;
405 
406     if (fread(buffer, FE_PACKERS_SIZE, 1, fp) != 1)
407         return -1;
408 
409     memcpy(p->tag, pbuf, 6); pbuf+=6;
410     memcpy(p->command, pbuf, _MAXPATH); pbuf+=_MAXPATH;
411     memcpy(p->list, pbuf, 4); pbuf+=4;
412     p->ratio = *pbuf++;
413     memcpy(p->resv, pbuf, 7); pbuf+=7;
414 
415     assert(pbuf - buffer == FE_PACKERS_SIZE);
416 
417     return 0;
418 }
419 
read_fe_unpackers(Unpackers * p,FILE * fp)420 int read_fe_unpackers(Unpackers *p, FILE *fp)
421 {
422     unsigned char buffer[FE_UNPACKERS_SIZE];
423     unsigned char *pbuf = buffer;
424 
425     if (fread(buffer, FE_UNPACKERS_SIZE, 1, fp) != 1)
426         return -1;
427 
428     memcpy(p->command, pbuf, _MAXPATH); pbuf+=_MAXPATH;
429     p->callingconvention = *pbuf; pbuf++;
430     memcpy(p->resv, pbuf, 7); pbuf+=7;
431 
432     assert(pbuf - buffer == FE_UNPACKERS_SIZE);
433 
434     return 0;
435 }
436 
read_fe_groupdefaults(GroupDefaults * g,FILE * fp,size_t length)437 int read_fe_groupdefaults(GroupDefaults *g, FILE *fp, size_t length)
438 {
439     unsigned char buffer[FE_GROUPDEFAULTS_SIZE - FE_AREA_SIZE];
440     unsigned char *pbuf = buffer;
441 
442     if (fread(buffer, FE_GROUPDEFAULTS_SIZE - FE_AREA_SIZE, 1, fp) != 1)
443     {
444         return -1;
445     }
446 
447     g->group = *pbuf++;
448     memcpy(g->resv, pbuf, 15); pbuf+=15;
449 
450     if (read_fe_area(&(g->area), fp))
451         return -1;
452 
453     assert(pbuf - buffer == FE_GROUPDEFAULTS_SIZE - FE_AREA_SIZE);
454 
455     if (length <= FE_GROUPDEFAULTS_SIZE ||
456         (g->nodes = malloc(length - FE_GROUPDEFAULTS_SIZE)) == NULL ||
457         fread(g->nodes, length - FE_GROUPDEFAULTS_SIZE, 1, fp) != 1)
458     {
459         return -1;
460     }
461 
462     return 0;
463 }
464 
free_fe_groupdefaults(GroupDefaults * g)465 void free_fe_groupdefaults(GroupDefaults *g)
466 {
467     if (g != NULL && g->nodes != NULL)
468         free(g->nodes);
469 }
470 
read_fe_frequest(ForwardAreaFix * f,FILE * fp)471 int read_fe_frequest(ForwardAreaFix *f, FILE *fp)
472 {
473     unsigned char buffer[FE_FORWARD_AREAFIX_SIZE];
474     unsigned char *pbuf = buffer;
475 
476     if (fread(buffer, FE_FORWARD_AREAFIX_SIZE, 1, fp) != 1)
477     {
478         return -1;
479     }
480 
481     f->nodenr = get_word(pbuf); pbuf+=2;
482     f->flags.flags = get_word(pbuf); pbuf+=2;
483 
484     memcpy(f->file, pbuf, _MAXPATH); pbuf+=_MAXPATH;
485     memcpy(f->resv0, pbuf, 56); pbuf+=56;
486 
487     f->sec_level = get_word(pbuf); pbuf+=2;
488     f->resv1     = get_word(pbuf); pbuf+=2;
489 
490     memcpy(f->resv3, pbuf, 3); pbuf+=3;
491 
492     f->groups = get_dword(pbuf); pbuf+=4;
493 
494     memcpy(f->resv2, pbuf, 33); pbuf+=33;
495 
496     assert(pbuf - buffer == FE_FORWARD_AREAFIX_SIZE);
497 
498     return 0;
499 }
500