1 Unit PTCfg;
2 
3 InterFace
4 
5 Uses
6   DOS,
7   Log, IniFile,
8   Types, GeneralP,
9   PTRegKey, TickType, TickCons, PTVar, PTProcs;
10 
11 Procedure ParseCfg;
12 
13 
14 Implementation
15 
16 Var
17   i: LongInt;
18   s, s1: String;
19 {$IfDef VIRTUALPASCAL}
20   Error: LongInt;
21 {$Else}
22   Error: Integer;
23 {$EndIf}
24 
25 Procedure IniError(s: String);
26   Begin
27   LogSetCurLevel(LogHandle, 1);
28   LogWriteLn(LogHandle, s);
29   MainDone;
30   Halt(Err_Ini);
31   End;
32 
33 
34 Procedure ParseFileAreas;
35 Var
36   f: Text;
37   si: Byte;
38 
39   Begin
40   With Ini do
41     Begin
42     If GetSecNum('FILEAREAS') = 0 then IniError('No FileAreas defined');
43     SetSection('FILEAREAS');
44     Cfg^.NumAreas := 0;
45     While UpStr(ReSecEnName) = 'AREA' do
46       begin
47       Inc(Cfg^.NumAreas);
48       If (Cfg^.NumAreas > 1) then
49         Begin
50         New(CurArea^.Next);
51         FillChar(CurArea^.Next^, SizeOf(TArea), 0);
52         CurArea^.Next^.Prev := CurArea;
53         CurArea := CurArea^.Next;
54         CurArea^.Next := Nil;
55         End
56       Else
57         Begin
58         New(Cfg^.Areas);
59         CurArea := Cfg^.Areas;
60         FillChar(CurArea^, SizeOf(TArea), 0);
61         CurArea^.Next := Nil;
62         CurArea^.Prev := Nil;
63         End;
64       s := ReSecEnValue;
65       CurArea^.Name := s;
66       If Debug then WriteLn('Area "', CurArea^.Name, '"');
67       If not SetNextOpt then Break;
68       While UpStr(ReSecEnName) <> 'AREA' do
69         Begin
70         s := UpStr(ReSecEnName);
71         If s = 'ADDR' then
72           Begin
73           s := UpStr(ReSecEnValue);
74           Str2Addr(s, CurArea^.Addr);
75           If Debug then WriteLn('Addr: ', Addr2Str(CurArea^.Addr));
76           End
77         Else If s = 'LEVEL' then
78           Begin
79           Val(ReSecEnValue, CurArea^.Level, Error);
80 {$IfDef FPC}
81           If Error > 1 then
82 {$Else}
83           If Error <> 0 then
84 {$EndIf}
85             Begin
86             LogWriteLn(LogHandle, 'Illegal level "'+ReSecEnValue+'" for Area "'+CurArea^.Name+'"');
87             End;
88           If Debug then WriteLn('Level: ', CurArea^.Level);
89           End
90         Else If s = 'GROUP' then
91           Begin
92           Val(ReSecEnValue, CurArea^.Group, Error);
93           If Error <> 0 then
94             Begin
95             LogWriteLn(LogHandle, 'Illegal group "'+ReSecEnValue+'" for Area "'+CurArea^.Name+'"');
96             End;
97           If Debug then WriteLn('Group: ', CurArea^.Group);
98           End
99         Else If s = 'COSTPERMB' then
100           Begin
101           Val(ReSecEnValue, CurArea^.CostPerMB, Error);
102 {$IfDef FPC}
103           If Error > 1 then
104 {$Else}
105           If Error <> 0 then
106 {$EndIf}
107             Begin
108             LogWriteLn(LogHandle, 'Illegal cost "'+ReSecEnValue+'" for Area "'+CurArea^.Name+'"');
109             End;
110           If Debug then WriteLn('CostPerMB: ', CurArea^.CostPerMB);
111           End
112         Else If s = 'LASTHATCH' then
113           Begin
114           Val('$'+ReSecEnValue, CurArea^.LastHatch, Error);
115           If Error <> 0 then
116             Begin
117             LogWriteLn(LogHandle, 'Illegal LastHatch time "'+ReSecEnValue+'" for Area "'+CurArea^.Name+'"');
118             End;
119           If Debug then WriteLn('LastHatch: ', CurArea^.LastHatch);
120           End
121         Else If s = 'DESC' then
122           Begin
123           CurArea^.Desc := ReSecEnValue;
124           If Debug then WriteLn('Desc: ', CurArea^.Desc);
125           End
126         Else If s = 'BBSAREA' then
127           Begin
128           CurArea^.BBSArea := ReSecEnValue;
129           If Debug then WriteLn('BBSArea: ', CurArea^.BBSArea);
130           End
131         Else If s = 'PATH' then
132           Begin
133           CurArea^.Path := RepEnv(ReSecEnValue);
134           If Debug then WriteLn('Path: ', CurArea^.Path);
135           If not DirExist(CurArea^.Path) then
136            Begin
137            If (Cfg^.CreateDirs) then
138             Begin
139             MakeDir(CurArea^.Path);
140             LogSetCurLevel(LogHandle, 2);
141             LogWriteLn(LogHandle, 'created directory "'+CurArea^.Path+'" for '+
142              'area "'+CurArea^.Name+'"');
143             End
144            Else
145             Begin
146             LogSetCurLevel(LogHandle, 2);
147             LogWriteLn(LogHandle, 'directory "'+CurArea^.Path+'" of '+
148              'area "'+CurArea^.Name+'" does not exist!');
149             End;
150            End;
151           End
152         Else If s = 'MOVETO' then
153           Begin
154           CurArea^.MoveTo := RepEnv(ReSecEnValue);
155           If Debug then WriteLn('MoveTo: ', CurArea^.MoveTo);
156           If (CurArea^.MoveTo <> '') and not DirExist(CurArea^.MoveTo) then
157            Begin
158            If (Cfg^.CreateDirs) then
159             Begin
160             MakeDir(CurArea^.MoveTo);
161             LogSetCurLevel(LogHandle, 2);
162             LogWriteLn(LogHandle, 'created oldfiles-directory "'+CurArea^.MoveTo+'" for '+
163              'area "'+CurArea^.Name+'"');
164             End
165            Else
166             Begin
167             LogWriteLn(LogHandle, 'oldfiles-directory "'+CurArea^.MoveTo+'" of '+
168              'area "'+CurArea^.Name+'" does not exist!');
169             End;
170            End;
171           End
172         Else If s = 'REPLACEEXT' then
173           Begin
174           CurArea^.ReplaceExt := ReSecEnValue;
175           If Debug then WriteLn('ReplaceExt: ', CurArea^.ReplaceExt);
176           End
177         Else If s = 'ANNOUNCE' then
178           Begin
179           s := ReSecEnValue;
180           If (s <> '') then
181             Begin
182             While (Pos(',', s) <> 0) Do
183               Begin
184               Val(Copy(s, 1, Pos(',', s) - 1), si, Error);
185               If (Error = 0) then CurArea^.AnnGroups := CurArea^.AnnGroups + [si]
186               Else
187                 Begin
188                 LogSetCurLevel(LogHandle, 1);
189                 LogWriteLn(LogHandle, 'Invalid Announcegroup "'+Copy(s, 1, Pos(',', s) - 1)+'" for area "'+CurArea^.Name+'"');
190                 End;
191               Delete(s, 1, Pos(',', s));
192               End;
193             Val(s, si, Error);
194             If (Error = 0) then CurArea^.AnnGroups := CurArea^.AnnGroups + [si]
195             Else
196               Begin
197               LogSetCurLevel(LogHandle, 1);
198               LogWriteLn(LogHandle, 'Invalid Announcegroup "'+s+'" for area "'+CurArea^.Name+'"');
199               End;
200             If Debug then
201               Begin
202               Write('AnnounceGroups: ');
203               For si := 1 to 255 do If (si in CurArea^.AnnGroups) then Write(si, ' ');
204               WriteLn;
205               End;
206             End;
207           End
208         Else If s = 'FLAGS' then
209           Begin
210           s := ReSecEnValue;
211           If (s <> '') then With CurArea^ do
212             Begin
213             While (s <> '') Do
214               Begin
215               If (Pos(',', s) <> 0) then
216                 Begin
217                 s1 := KillLeadingSpcs(UpStr(Copy(s, 1, Pos(',', s) - 1)));
218                 Delete(s, 1, Pos(',', s));
219                 End
220               Else
221                 Begin
222                 s1 := KillLeadingSpcs(UpStr(s));
223                 s := '';
224                 End;
225               If (s1 = 'DUPE') then Flags := Flags or fa_Dupe
226               Else If (s1 = 'DUPECHECK') then Flags := Flags or fa_Dupe
227               Else if (s1 = 'PASSTHROUGH') then Flags := Flags or fa_PT
228               Else if (s1 = 'PT') then Flags := Flags or fa_PT
229               Else if (s1 = 'CRC') then Flags := Flags or fa_CRC
230               Else if (s1 = 'TOUCH') then Flags := Flags or fa_Touch
231               Else if (s1 = 'MANDATORY') then Flags := Flags or fa_Mandatory
232               Else if (s1 = 'MAN') then Flags := Flags or fa_Mandatory
233               Else if (s1 = 'NOPAUSE') then Flags := Flags or fa_NoPause
234               Else if (s1 = 'NEWFILESHATCH') then Flags := Flags or fa_NewFilesHatch
235               Else if (s1 = 'NEW') then Flags := Flags or fa_NewFilesHatch
236               Else if (s1 = 'HATCH') then Flags := Flags or fa_NewFilesHatch
237               Else if (s1 = 'COSTSHARING') then Flags := Flags or fa_CS
238               Else if (s1 = 'CS') then Flags := Flags or fa_CS
239               Else if (s1 = 'HIDDEN') then Flags := Flags or fa_Hidden
240               Else if (s1 = 'HID') then Flags := Flags or fa_Hidden
241               Else if (s1 = 'REMOTECHANGE') then Flags := Flags or fa_RemoteChange
242               Else if (s1 = 'REMOTE') then Flags := Flags or fa_RemoteChange
243               Else if (s1 = 'REM') then Flags := Flags or fa_RemoteChange
244               Else
245                 Begin
246                 LogSetCurLevel(LogHandle, 1);
247                 LogWriteLn(LogHandle, 'Invalid flag "'+s1+'" for area "'+Name+'"');
248                 End;
249               End;
250             End;
251           End
252         Else
253           Begin
254           LogWriteLn(LogHandle, 'Unknown or out of sequence keyword: "'+ ReSecEnName+ '='+ReSecEnValue+'"');
255           End;
256         If not SetNextOpt then Break;
257         End;
258       If Debug then WriteLn;
259       end;
260     If Cfg^.NumAreas = 0 then IniError('No FileAreas defined');
261     If Debug then
262       Begin
263       WriteLn('<Return>');
264       ReadLn;
265       End;
266     End;
267   End;
268 
269 Procedure ParseAddrs;
270 Var
271  i: Word;
272 
273   Begin
274   With Ini do
275     Begin
276     If GetSecNum('ADDRESSES') = 0 then IniError('No Addresses defined');
277     SetSection('ADDRESSES');
278     I := 0;
279       Repeat
280       Inc(i);
281       Str2Addr(ReSecEnValue, Cfg^.Addrs[i]);
282       If Debug then WriteLn('Addr = '+Addr2Str(Cfg^.Addrs[i]));
283       Until not SetNextOpt;
284     Cfg^.NumAddrs := i;
285     End;
286   If Debug then
287     Begin
288     WriteLn('<Return>');
289     ReadLn;
290     End;
291   End;
292 
293 Procedure ParseDomains;
294 Var
295  s: String;
296  i: Byte;
297 
298   Begin
299   Cfg^.NumDomains := 0;
300   With Ini do
301     Begin
302     If GetSecNum('DOMAINS') = 0 then Exit;
303     SetSection('DOMAINS');
304     i := 0;
305       Repeat
306       Inc(i);
307       s := ReSecEnValue;
308       Cfg^.Domains[i].Domain := Copy(s, 1, Pos(',', s)-1);
309       Delete(s, 1, Pos(',', s));
310       Cfg^.Domains[i].Abbrev := s;
311       If Debug then WriteLn('Domain="'+Cfg^.Domains[i].Domain+'" Abbrev="'+
312        Cfg^.Domains[i].Abbrev+'"');
313       Until not SetNextOpt;
314     Cfg^.NumDomains := i;
315     End;
316   If Debug then
317     Begin
318     WriteLn('<Return>');
319     ReadLn;
320     End;
321   End;
322 
323 Procedure ParsePackers;
324   Begin
325   With Ini do
326     Begin
327     If GetSecNum('PACKER') = 0 then
328      Begin
329      Cfg^.NumPacker := 0;
330      Exit;
331      End;
332     SetSection('PACKER');
333     I := 0;
334       Repeat
335       Inc(i);
336       With Cfg^.Packer[i] do
337         Begin
338         s := ReSecEnValue;
339         Val(Copy(s, 1, Pos(',', s) - 1), Index, Error);
340         Delete(s, 1, Pos(',', s));
341         Ext := Copy(s, 1, Pos(',', s) - 1);
342         Delete(s, 1, Pos(',', s));
343         Cmd := s;
344         End;
345       Until not SetNextOpt;
346     Cfg^.NumPacker := i;
347     End;
348   If Debug then
349     Begin
350     WriteLn('<Return>');
351     ReadLn;
352     End;
353   End;
354 
355 Procedure ParseUnPackers;
356   Begin
357   With Ini do
358     Begin
359     If GetSecNum('UNPACKER') = 0 then
360      Begin
361      Cfg^.NumUnPacker := 0;
362      Exit;
363      End;
364     SetSection('UNPACKER');
365     I := 0;
366       Repeat
367       Inc(i);
368       With Cfg^.UnPacker[i] do
369         Begin
370         s := ReSecEnValue;
371         Val(Copy(s, 1, Pos(',', s) - 1), Index, Error);
372         Delete(s, 1, Pos(',', s));
373         Ext := Copy(s, 1, Pos(',', s) - 1);
374         Delete(s, 1, Pos(',', s));
375         Cmd := s;
376         End;
377       Until not SetNextOpt;
378     Cfg^.NumUnPacker := i;
379     End;
380   If Debug then
381     Begin
382     WriteLn('<Return>');
383     ReadLn;
384     End;
385   End;
386 
387 Procedure ParseGroups;
388   Begin
389   With Ini do
390     Begin
391     If GetSecNum('GROUPS') = 0 then IniError('No Groups defined');
392     SetSection('GROUPS');
393     I := 0;
394       Repeat
395       Inc(i);
396       With Cfg^.Groups[i] do
397         Begin
398         s := ReSecEnValue;
399         Val(Copy(s, 1, Pos(',', s) - 1), Index, Error);
400         Delete(s, 1, Pos(',', s));
401         Name := s;
402         End;
403       Until not SetNextOpt;
404     If (i = 0) then IniError('No Groups defined');
405     Cfg^.NumGroups := i;
406     End;
407   If Debug then
408     Begin
409     WriteLn('<Return>');
410     ReadLn;
411     End;
412   End;
413 
414 Procedure ParseAnnGroups;
415   Begin
416   Cfg^.AnnGroups := NIL;
417   With Ini do
418     Begin
419     If GetSecNum('ANNOUNCEGROUPS') = 0 then
420      Begin
421      Cfg^.NumAnnGroups := 0;
422      Exit;
423      End;
424     SetSection('ANNOUNCEGROUPS');
425     I := 0;
426     While UpStr(ReSecEnName) = 'GROUP' do
427       Begin
428       Inc(i);
429       If (i > 1) then
430         Begin
431         New(CurAnnGroup^.Next);
432         CurAnnGroup^.Next^.Prev := CurAnnGroup;
433         CurAnnGroup := CurAnnGroup^.Next;
434         CurAnnGroup^.Next := NIL;
435         End
436       Else
437         Begin
438         New(Cfg^.AnnGroups);
439         CurAnnGroup := Cfg^.AnnGroups;
440         CurAnnGroup^.Next := NIL;
441         CurAnnGroup^.Prev := NIL;
442         End;
443       With CurAnnGroup^ do
444         Begin
445         Index := 1;
446         Name := '';
447         Area := '';
448         Subj := '';
449         Typ := at_Echomail;
450         FromName := '';
451         ToName := '';
452         With FromAddr do
453           Begin
454           Zone := 0;
455           Net := 0;
456           Node := 0;
457           Domain := '';
458           End;
459         ToAddr := FromAddr;
460         HeaderFile := '';
461         FooterFile := '';
462         End;
463       s := RepEnv(ReSecEnValue);
464       Val(Copy(s, 1, Pos(',', s) - 1), CurAnnGroup^.Index, Error);
465       Delete(s, 1, Pos(',', s));
466       CurAnnGroup^.Name := s;
467       If Debug then WriteLn('AnnounceGroup ', CurAnnGroup^.Index, '(', CurAnnGroup^.Name, ')');
468 
469       If not SetNextOpt then Break;
470       With CurAnnGroup^ do
471         Begin
472         While UpStr(ReSecEnName) <> 'GROUP' do
473           Begin
474           s := UpStr(ReSecEnName);
475           If s = 'FROM' then
476             Begin
477             s := RepEnv(ReSecEnValue);
478             FromName := Copy(s, 1, Pos(',', s)-1);
479             Str2Addr(Copy(s, Pos(',', s)+1, Length(s)-Pos(',', s)), FromAddr);
480             If Debug then WriteLn('From: ', FromName, ' (', Addr2Str(FromAddr), ')');
481             End
482           Else If s = 'TO' then
483             Begin
484             s := RepEnv(ReSecEnValue);
485             ToName := Copy(s, 1, Pos(',', s)-1);
486             Str2Addr(Copy(s, Pos(',', s)+1, Length(s)-Pos(',', s)), ToAddr);
487             If Debug then WriteLn('To: ', ToName, ' (', Addr2Str(ToAddr), ')');
488             End
489           Else If s = 'AREA' then
490             Begin
491             Area := RepEnv(ReSecEnValue);
492             If Debug then WriteLn('Area: ', Area);
493             End
494           Else If s = 'SUBJ' then
495             Begin
496             Subj := RepEnv(ReSecEnValue);
497             If Debug then WriteLn('Subj: ', Subj);
498             End
499           Else If s = 'TYPE' then
500             Begin
501             s := UpStr(RepEnv(ReSecEnValue));
502             If (s = 'ECHOMAIL') then Typ := at_EchoMail
503             Else If (s = 'NETMAIL') then Typ := at_NetMail
504             Else
505              Begin
506              LogSetCurLevel(LogHandle, 1);
507              LogWriteLn(LogHandle, 'Invalid announcegroup-type: "'+s+'"!');
508              End;
509             If Debug then
510              Begin
511              Write('Type: ');
512              Case Typ of
513               at_Echomail: WriteLn('EchoMail');
514               at_Netmail: WriteLn('NetMail');
515               Else WriteLn('Invalid!');
516               End;
517              End;
518             End
519           Else If s = 'HEADERFILE' then
520             Begin
521             HeaderFile := RepEnv(ReSecEnValue);
522             If Debug then WriteLn('HeaderFile: ', HeaderFile);
523             End
524           Else If s = 'FOOTERFILE' then
525             Begin
526             FooterFile := RepEnv(ReSecEnValue);
527             If Debug then WriteLn('FooterFile: ', FooterFile);
528             End
529           Else
530             Begin
531             LogWriteLn(LogHandle, 'Unknown or out of sequence keyword: "'+ ReSecEnName+ '='+ReSecEnValue+'"');
532             End;
533           If not SetNextOpt then Break;
534           End;
535         End;
536       End;
537     Cfg^.NumAnnGroups := i;
538     End;
539   If Debug then
540     Begin
541     WriteLn('<Return>');
542     ReadLn;
543     End;
544   End;
545 
546 Procedure ParseUser;
547 Var
548  si: Byte;
549 
550   Begin
551   With Ini do
552     Begin
553     If GetSecNum('USER') = 0 then IniError('No Users defined');
554     SetSection('USER');
555     I := 0;
556     While UpStr(ReSecEnName) = 'USER' do
557       Begin
558       Inc(i);
559       If (i > 1) then
560         Begin
561         New(CurUser^.Next);
562         FillChar(CurUser^.Next^, SizeOf(TUser), 0);
563         CurUser^.Next^.Prev := CurUser;
564         CurUser := CurUser^.Next;
565         CurUser^.Next := Nil;
566         End
567       Else
568         Begin
569         New(Cfg^.Users);
570         CurUser := Cfg^.Users;
571         FillChar(CurUser^, SizeOf(TUser), 0);
572         CurUser^.Next := Nil;
573         CurUser^.Prev := Nil;
574         End;
575       s := ReSecEnValue;
576       CurUser^.Name := s;
577       If Debug then WriteLn('User "', CurUser^.Name, '"');
578 
579       If not SetNextOpt then Break;
580       While UpStr(ReSecEnName) <> 'USER' do
581         Begin
582         s := UpStr(ReSecEnName);
583         If s = 'ADDR' then
584           Begin
585           s := UpStr(ReSecEnValue);
586           Str2Addr(s, CurUser^.Addr);
587           CurUser^.ArcAddr := CurUser^.Addr;
588           If Debug then WriteLn('Addr: ', Addr2Str(CurUser^.Addr));
589           End
590         Else If s = 'ARCADDR' then
591           Begin
592           s := UpStr(ReSecEnValue);
593           Str2Addr(s, CurUser^.ArcAddr);
594           If Debug then WriteLn('ArcAddr: ', Addr2Str(CurUser^.ArcAddr));
595           End
596         Else If s = 'OWNADDR' then
597           Begin
598           s := UpStr(ReSecEnValue);
599           Str2Addr(s, CurUser^.OwnAddr);
600           If Debug then WriteLn('OwnAddr: ', Addr2Str(CurUser^.OwnAddr));
601           End
602         Else If s = 'ACTIVE' then
603           Begin
604           s := UpStr(ReSecEnValue);
605           CurUser^.Active := (s = 'TRUE') or (s = 'ON') or (s = '1') or (Pos('Y', s) <> 0);
606           If Debug then WriteLn('Active: ', CurUser^.Active);
607           End
608         Else If s = 'PWD' then
609           Begin
610           CurUser^.Pwd := UpStr(ReSecEnValue);
611           If Debug then WriteLn('Pwd: ', CurUser^.Pwd);
612           End
613         Else If s = 'LEVEL' then
614           Begin
615           Val(ReSecEnValue, CurUser^.Level, Error);
616 {$IfDef FPC}
617           If Error > 1 then
618 {$Else}
619           If Error <> 0 then
620 {$EndIf}
621             Begin
622             LogWriteLn(LogHandle, 'Illegal Level: "'+ReSecEnValue+'"');
623             End;
624           If Debug then WriteLn('Level: ', CurUser^.Level);
625           End
626         Else If s = 'GROUPS' then
627           Begin
628           s := ReSecEnValue;
629           If (s <> '') then
630             Begin
631             While (Pos(',', s) <> 0) Do
632               Begin
633               Val(Copy(s, 1, Pos(',', s) - 1), si, Error);
634               If (Error = 0) then CurUser^.Groups := CurUser^.Groups + [si]
635               Else
636                 Begin
637                 LogSetCurLevel(LogHandle, 1);
638                 LogWriteLn(LogHandle, 'Invalid group "'+Copy(s, 1, Pos(',', s) - 1)+'" for user '+CurUser^.Name+
639                   ' ('+Addr2Str(CurUser^.Addr)+')');
640                 End;
641               Delete(s, 1, Pos(',', s));
642               End;
643             Val(s, si, Error);
644             If (Error = 0) then CurUser^.Groups := CurUser^.Groups + [si]
645             Else
646               Begin
647               LogSetCurLevel(LogHandle, 1);
648               LogWriteLn(LogHandle, 'Invalid group "'+Copy(s, 1, Pos(',', s) - 1)+'" for user '+CurUser^.Name+
649                 ' ('+Addr2Str(CurUser^.Addr)+')');
650               End;
651             If Debug then
652               Begin
653               Write('Groups: ');
654               For si := 1 to 255 do If (si in CurUser^.Groups) then Write(si, ' ');
655               WriteLn;
656               End;
657             End;
658           End
659         Else If s = 'MAIL' then
660           Begin
661           s := UpStr(ReSecEnValue);
662           If (s = 'NORMAL') then CurUser^.MailFlags := ml_Normal
663           Else If (s = 'DIRECT') then CurUser^.MailFlags := ml_Direct
664           Else If (s = 'HOLD') then CurUser^.MailFlags := ml_Hold
665           Else If (s = 'CRASH') then CurUser^.MailFlags := ml_Crash
666           Else
667             Begin
668             LogSetCurLevel(LogHandle, 1);
669             LogWriteLn(LogHandle, 'Invalid mail status "'+s+'" for user '+CurUser^.Name);
670             End;
671           End
672         Else If s = 'FLAGS' then
673           Begin
674           s := ReSecEnValue;
675           If (s <> '') then With CurUser^ do
676             Begin
677             While (s <> '') Do
678               Begin
679               If (Pos(',', s) <> 0) then
680                 Begin
681                 s1 := KillLeadingSpcs(UpStr(Copy(s, 1, Pos(',', s) - 1)));
682                 Delete(s, 1, Pos(',', s));
683                 End
684               Else
685                 Begin
686                 s1 := KillLeadingSpcs(UpStr(s));
687                 s := '';
688                 End;
689               If (s1 = 'SENDTIC') then Flags := Flags or uf_SendTIC
690               Else If (s1 = 'TIC') then Flags := Flags or uf_SendTIC
691               Else if (s1 = 'NOTIFY') then Flags := Flags or uf_Notify
692               Else if (s1 = 'AUTOCREATE') then Flags := Flags or uf_AutoCreate
693               Else if (s1 = 'AC') then Flags := Flags or uf_AutoCreate
694               Else if (s1 = 'ADMIN') then Flags := Flags or uf_Admin
695               Else if (s1 = 'NMANNOUNCE') then Flags := Flags or uf_NMAnn
696               Else if (s1 = 'NMANN') then Flags := Flags or uf_NMAnn
697               Else
698                 Begin
699                 LogSetCurLevel(LogHandle, 1);
700                 LogWriteLn(LogHandle, 'Invalid flag "'+s1+'" for user '+Name+' ('+Addr2Str(Addr)+')');
701                 End;
702               End;
703             End;
704           End
705         Else If s = 'MAY' then
706           Begin
707           s := ReSecEnValue;
708           If (s <> '') then With CurUser^ do
709             Begin
710             While (s <> '') Do
711               Begin
712               If (Pos(',', s) <> 0) then
713                 Begin
714                 s1 := KillLeadingSpcs(UpStr(Copy(s, 1, Pos(',', s) - 1)));
715                 Delete(s, 1, Pos(',', s));
716                 End
717               Else
718                 Begin
719                 s1 := KillLeadingSpcs(UpStr(s));
720                 s := '';
721                 End;
722               If (s1 = 'CONNECT') then May := May or um_Connect
723               Else If (s1 = 'CONN') then May := May or um_Connect
724               Else if (s1 = 'DISCONNECT') then May := May or um_DisConnect
725               Else if (s1 = 'DISCONN') then May := May or um_DisConnect
726               Else if (s1 = 'PAUSE') then May := May or um_Pause
727               Else if (s1 = 'PASSWORD') then May := May or um_Pwd
728               Else if (s1 = 'PWD') then May := May or um_Pwd
729               Else if (s1 = 'COMPRESSION') then May := May or um_Compression
730               Else if (s1 = 'COMP') then May := May or um_Compression
731               Else if (s1 = 'TIC') then May := May or um_Tic
732               Else if (s1 = 'NOTIFY') then May := May or um_Notify
733               Else if (s1 = 'RESCAN') then May := May or um_Rescan
734               Else
735                 Begin
736                 LogSetCurLevel(LogHandle, 1);
737                 LogWriteLn(LogHandle, 'Invalid permission "'+s1+'" for user '+Name+' ('+Addr2Str(Addr)+')');
738                 End;
739               End;
740             End;
741           End
742         Else If s = 'RECEIVES' then
743           Begin
744           s := UpStr(ReSecEnValue);
745           CurUser^.Receives := (s = 'TRUE') or (s = 'ON') or (s = '1') or (Pos('Y', s) <> 0);
746           If Debug then WriteLn('Receives: ', CurUser^.Receives);
747           End
748         Else If s = 'SENDS' then
749           Begin
750           s := UpStr(ReSecEnValue);
751           CurUser^.Sends := (s = 'TRUE') or (s = 'ON') or (s = '1') or (Pos('Y', s) <> 0);
752           If Debug then WriteLn('Sends: ', CurUser^.Sends);
753           End
754         Else If s = 'PACKTICS' then
755           Begin
756           s := UpStr(ReSecEnValue);
757           CurUser^.PackTICs := (s = 'TRUE') or (s = 'ON') or (s = '1') or (Pos('Y', s) <> 0);
758           If Debug then WriteLn('PackTICs: ', CurUser^.PackTICs);
759           End
760         Else If s = 'PACKFILES' then
761           Begin
762           s := UpStr(ReSecEnValue);
763           CurUser^.PackFiles := (s = 'TRUE') or (s = 'ON') or (s = '1') or (Pos('Y', s) <> 0);
764           If Debug then WriteLn('PackFiles: ', CurUser^.PackFiles);
765           End
766         Else If s = 'PACKER' then
767           Begin
768           Val(ReSecEnValue, CurUser^.Packer, Error);
769           If Error <> 0 then
770             Begin
771             LogWriteLn(LogHandle, 'Illegal Packer: "'+ReSecEnValue+'"');
772             End;
773           If Debug then WriteLn('Packer: ', CurUser^.Packer);
774           End
775         Else If s = 'AUTOCREATE' then
776           Begin
777           Val(ReSecEnValue, CurUser^.ACGroup, Error);
778           If Error <> 0 then
779             Begin
780             LogWriteLn(LogHandle, 'Illegal Group: "'+ReSecEnValue+'"');
781             End;
782           If Debug then WriteLn('AutoCreate: ', CurUser^.ACGroup);
783           End
784         Else If s = 'AREA' then
785           Begin
786           If Pos(',', ReSecEnValue) <> 0 then s := UpStr(Copy(ReSecEnValue, 1, Pos(',', ReSecEnValue) - 1))
787           Else s := UpStr(ReSecEnValue);
788           CurArea := Cfg^.Areas;
789             While (UpStr(CurArea^.Name) <> s) do
790               If (CurArea^.Next <> Nil) then CurArea := CurArea^.Next
791               Else
792                 Begin
793                 LogWriteLn(LogHandle, 'Area '+s+' for User '+CurUser^.Name+' not found');
794                 Break;
795                 End;
796           If (UpStr(CurArea^.Name) = s) then
797             Begin
798             If (CurArea^.Users = NIL) then
799               Begin
800               New(CurArea^.Users);
801               CurConnUser := CurArea^.Users;
802               CurConnUser^.Next := Nil;
803               CurConnUser^.Prev := Nil;
804               End
805             Else
806               Begin
807               CurConnUser := CurArea^.Users;
808               While (CurConnUser^.Next <> Nil) do CurConnUser := CurConnUser^.Next;
809               New(CurConnUser^.Next);
810               CurConnUser^.Next^.Prev := CurConnUser;
811               CurConnUser := CurConnUser^.Next;
812               CurConnUser^.Next := Nil;
813               End;
814             With CurConnUser^ do
815               Begin
816               User := CurUser;
817               s := UpStr(ReSecEnValue);
818               If Pos(',', s) = 0 then
819                 Begin
820                 Receive := True;
821                 Send := False;
822                 End
823               Else
824                 Begin
825                 Delete(s, 1, Pos(',', s));
826                 Receive := (Pos('R', s) <> 0);
827                 Send := (Pos('S', s) <> 0);
828                 End;
829               End;
830             If Debug then
831               Begin
832               Write('Area ', CurArea^.Name, ': ');
833               If CurConnUser^.Send then Write('Send ');
834               If CurConnUser^.Receive then Write('Receive ');
835               WriteLn;
836               End;
837             End;
838           End
839         Else
840           Begin
841           LogWriteLn(LogHandle, 'Unknown or out of sequence keyword: "'+ ReSecEnName+ '='+ReSecEnValue+'"');
842           End;
843         If not SetNextOpt then Break;
844         End;
845       If Debug then WriteLn;
846       end;
847     If i = 0 then IniError('No Users defined');
848     Cfg^.NumUser := i;
849     If Debug then
850       Begin
851       WriteLn('<Return>');
852       ReadLn;
853       End;
854     End;
855   End;
856 
857 Procedure ParseUpLinks;
858   Begin
859   Cfg^.UpLinks := NIL;
860   With Ini do
861     Begin
862     If GetSecNum('UPLINKS') = 0 then
863      Begin
864      Cfg^.NumUpLinks := 0;
865      Exit;
866      End;
867     SetSection('UPLINKS');
868     I := 0;
869     While UpStr(ReSecEnName) = 'UPLINK' do
870       begin
871       Inc(i);
872       If (i > 1) then
873         Begin
874         New(CurUpLink^.Next);
875         CurUpLink^.Next^.Prev := CurUpLink;
876         CurUpLink := CurUpLink^.Next;
877         CurUpLink^.Next := Nil;
878         End
879       Else
880         Begin
881         New(Cfg^.UpLinks);
882         CurUpLink := Cfg^.UpLinks;
883         CurUpLink^.Next := Nil;
884         CurUpLink^.Prev := Nil;
885         End;
886       s := ReSecEnValue;
887       CurUpLink^.Comment := s;
888       If Debug then WriteLn('UpLink "', CurUpLink^.Comment, '"');
889       With CurUpLink^ do
890         Begin
891         Name := '';
892         Group:=0;
893         Level:=0;
894         With Addr do
895           Begin
896           Zone := 0;
897           Net := 0;
898           Node := 0;
899           Point := 0;
900           Domain := '';
901           End;
902         Pwd := '';
903         AreaList := '';
904         Unconditional := False;
905         End;
906 
907       If not SetNextOpt then Break;
908       While UpStr(ReSecEnName) <> 'UPLINK' do
909         Begin
910         s := UpStr(ReSecEnName);
911         If  s = 'CONFMGR' then
912           Begin
913           CurUpLink^.Name := ReSecEnValue;
914           If Debug then WriteLn('ConfMgr: ', CurUpLink^.Name);
915           End
916         Else If s = 'GROUP' then
917           Begin
918           s := ReSecEnValue;
919           Val(s, i, Error);
920           If Error <> 0 then
921             Begin
922             LogWriteLn(LogHandle, 'Illegal Group: "'+s+'"');
923             End
924           Else CurUpLink^.Group := i;
925           If Debug then
926             Begin
927             WriteLn('Group: ', CurUpLink^.Group);
928             End;
929           End
930         Else If s = 'LEVEL' then
931           Begin
932           Val(ReSecEnValue, CurUpLink^.Level, Error);
933 {$IfDef FPC}
934           If Error > 1 then
935 {$Else}
936           If Error <> 0 then
937 {$EndIf}
938             Begin
939             LogWriteLn(LogHandle, 'Illegal Level: "'+ReSecEnValue+'"');
940             End;
941           If Debug then WriteLn('Level: ', CurUpLink^.Level);
942           End
943         Else If s = 'ADDR' then
944           Begin
945           Str2Addr(ReSecEnValue, CurUpLink^.Addr);
946           If Debug then WriteLn('Addr: ', Addr2Str(CurUpLink^.Addr));
947           End
948         Else If s = 'PWD' then
949           Begin
950           CurUpLink^.Pwd := ReSecEnValue;
951           If Debug then WriteLn('Pwd: ', CurUpLink^.Pwd);
952           End
953         Else If s = 'AREALIST' then
954           Begin
955           CurUpLink^.AreaList := RepEnv(ReSecEnValue);
956           If Debug then WriteLn('AreaList: ', CurUpLink^.AreaList);
957           End
958         Else If s = 'UNCONDITIONAL' then
959           Begin
960           s := UpStr(ReSecEnValue);
961           CurUser^.Receives := (s = 'TRUE') or (s = 'ON') or (Pos('Y', s) <> 0);
962           If Debug then WriteLn('Unconditional: ', CurUser^.Receives);
963           End
964         Else
965           Begin
966           LogWriteLn(LogHandle, 'Unknown or out of sequence keyword: '+ ReSecEnName);
967           End;
968         If not SetNextOpt then Break;
969         End;
970       If Debug then WriteLn;
971       end;
972     Cfg^.NumUpLinks := i;
973     If Debug then
974       Begin
975       WriteLn('<Return>');
976       ReadLn;
977       End;
978     End;
979   End;
980 
981 Procedure ParseArcNames;
982   Begin
983   With Ini do
984     Begin
985     If GetSecNum('ARCNAMES') = 0 then
986      Begin
987      Cfg^.NumArcNames := 0;
988      Exit;
989      End;
990     SetSection('ARCNAMES');
991     I := 0;
992       Repeat
993       If UpStr(ReSecEnName) = 'ARCNAME' then
994         begin
995         Inc(i);
996         s := RepEnv(ReSecEnValue);
997         Cfg^.ArcNames[i].FileName := Copy(s, 1, Pos(',', s) - 1);
998         Val(Copy(s, Pos(',', s) + 1, Length(s) - Pos(',', s)), Cfg^.ArcNames[i].UnPacker, Error);
999         If Debug then WriteLn('ArcName: "', Cfg^.ArcNames[i].FileName, ',', Cfg^.ArcNames[i].UnPacker, '"');
1000         end;
1001       Until not SetNextOpt;
1002     Cfg^.NumArcNames := i;
1003 
1004     If Debug then
1005       Begin
1006       WriteLn('<Return>');
1007       ReadLn;
1008       End;
1009     End;
1010   End;
1011 
1012 Procedure ParseMgrNames;
1013   Begin
1014   With Ini do
1015     Begin
1016     If GetSecNum('MGRNAMES') = 0 then IniError('No MgrNames defined');
1017     SetSection('MGRNAMES');
1018     I := 0;
1019       Repeat
1020       If UpStr(ReSecEnName) = 'MGRNAME' then
1021         begin
1022         Inc(i);
1023         Cfg^.MgrNames[i] := RepEnv(ReSecEnValue);
1024         If Debug then WriteLn('MgrName: "', Cfg^.MgrNames[i], '"');
1025         end;
1026       Until not SetNextOpt;
1027     If i = 0 then IniError('No MgrNames defined');
1028     Cfg^.NumMgrNames := i;
1029     End;
1030   If Debug then
1031     Begin
1032     WriteLn('<Return>');
1033     ReadLn;
1034     End;
1035   End;
1036 
1037 Procedure ParseCfg;
1038   Begin
1039   Ini.Init(CfgName);
1040   With Ini do
1041     Begin
1042     s := RepEnv(ReadEntry('GENERAL', 'LOG'));
1043     If (s = '') then
1044       Begin
1045       WriteLn('No Log defined!');
1046       Ini.Done;
1047       FreeMem(HDesc, 65535);
1048       Halt(Err_NoLog);
1049       End;
1050     LogHandle := OpenLog(Binkley, s, 'PROTICK', 'ProTick'+Version);
1051     If (LogHandle = 0) then
1052       Begin
1053       WriteLn('Couldn''t open Log!');
1054       Ini.Done;
1055       FreeMem(HDesc, 65535);
1056       Halt(Err_NoLog);
1057       End;
1058     New(Cfg);
1059     Cfg^.Areas := Nil;
1060     Cfg^.Users := Nil;
1061     Cfg^.UpLinks := Nil;
1062     Cfg^.CheckDest := True;
1063     FSplit(CfgName, Cfg^.DataPath, s, s);
1064     s := RepEnv(ReadEntry('GENERAL', 'LogLevel'));
1065     If (s = '') then LogSetLogLevel(LogHandle, 5)
1066     Else
1067       Begin
1068       Val(s, i, Error);
1069       LogSetLogLevel(LogHandle, i);
1070       End;
1071 
1072     s := RepEnv(ReadEntry('GENERAL', 'DispLevel'));
1073     If (s = '') then LogSetScrLevel(LogHandle, 5)
1074     Else
1075       Begin
1076       Val(s, i, Error);
1077       LogSetScrLevel(LogHandle, i);
1078       End;
1079     If (ReadEntry('GENERAL', 'CREATEDIRS') <> '') then
1080       Begin
1081       s := UpStr(ReadEntry('GENERAL', 'CREATEDIRS'));
1082       Cfg^.CreateDirs := ((s = 'ON') or (s = 'Y') or (s = 'YES') or (s = '1') or
1083       (s = 'J') or (s = 'JA'));
1084       End
1085     Else Cfg^.CreateDirs := False;
1086 
1087     Cfg^.FlagDir := RepEnv(ReadEntry('GENERAL', 'FLAGDIR'));
1088     If (Cfg^.FlagDir = '') then IniError('No Semaphore directory defined!');
1089     If (not DirExist(Cfg^.FlagDir)) then
1090      Begin
1091      If Cfg^.CreateDirs then
1092       Begin
1093       MakeDir(Cfg^.FlagDir);
1094       LogSetCurLevel(LogHandle, 2);
1095       LogWriteLn(LogHandle, 'created semaphore-directory "'+Cfg^.FlagDir+'"');
1096       End
1097      Else
1098       Begin
1099       LogSetCurLevel(LogHandle, 2);
1100       LogWriteLn(LogHandle, 'semaphore-directory "'+Cfg^.FlagDir+'" does not exist!');
1101       End
1102      End;
1103 
1104     Cfg^.InBound := RepEnv(ReadEntry('GENERAL', 'INBOUND'));
1105     If (Cfg^.InBound = '') then IniError('No InBound defined!');
1106     If (not DirExist(Cfg^.Inbound)) then
1107      Begin
1108      If Cfg^.CreateDirs then
1109       Begin
1110       MakeDir(Cfg^.Inbound);
1111       LogSetCurLevel(LogHandle, 2);
1112       LogWriteLn(LogHandle, 'created inbound-directory "'+Cfg^.Inbound+'"');
1113       End
1114      Else
1115       Begin
1116       LogSetCurLevel(LogHandle, 2);
1117       LogWriteLn(LogHandle, 'inbound-directory "'+Cfg^.Inbound+'" does not exist!');
1118       End
1119      End;
1120 
1121     s := UpStr(ReadEntry('GENERAL', 'OBTYPE'));
1122     If (s = 'BT') then Cfg^.OBType := OB_BT
1123     Else If (s = 'FD') then Cfg^.OBType := OB_FD
1124     Else If (s = 'TMAIL') then Cfg^.OBType := OB_TMail
1125     Else IniError('invalid outbound-type "'+s+'"!');
1126 
1127     Cfg^.OutBound := RepEnv(ReadEntry('GENERAL', 'OUTBOUND'));
1128     If ((Cfg^.OutBound = '') and (Cfg^.OBType <> OB_TMail)) then
1129      IniError('No OutBound defined!');
1130     If (Cfg^.OBType = OB_BT) then
1131     If (not DirExist(Cfg^.Outbound)) then
1132      Begin
1133      If Cfg^.CreateDirs then
1134       Begin
1135       MakeDir(Cfg^.Outbound);
1136       LogSetCurLevel(LogHandle, 2);
1137       LogWriteLn(LogHandle, 'created outbound-directory "'+Cfg^.OutBound+'"');
1138       End
1139      Else
1140       Begin
1141       LogSetCurLevel(LogHandle, 2);
1142       LogWriteLn(LogHandle, 'outbound-directory "'+Cfg^.Outbound+'" does not exist!');
1143       End
1144      End;
1145 
1146     Cfg^.TicOut := RepEnv(ReadEntry('GENERAL', 'TICOUT'));
1147     If (Cfg^.TicOut = '') then Cfg^.TicOut := Cfg^.OutBound;
1148     If (not DirExist(Cfg^.TicOut)) then
1149      Begin
1150      If Cfg^.CreateDirs then
1151       Begin
1152       MakeDir(Cfg^.TicOut);
1153       LogSetCurLevel(LogHandle, 2);
1154       LogWriteLn(LogHandle, 'created tic-directory "'+Cfg^.TicOut+'"');
1155       End
1156      Else
1157       Begin
1158       LogSetCurLevel(LogHandle, 2);
1159       LogWriteLn(LogHandle, 'tic-directory "'+Cfg^.TicOut+'" does not exist!');
1160       End
1161      End;
1162 
1163     Cfg^.NetMail := RepEnv(ReadEntry('GENERAL', 'NETMAIL'));
1164     If (Cfg^.NetMail = '') then IniError('No NetMail area defined!');
1165 
1166     Cfg^.Bad := RepEnv(ReadEntry('GENERAL', 'BAD'));
1167     If (Cfg^.Bad = '') then IniError('No BadFiles directory defined!');
1168     If (not DirExist(Cfg^.Bad)) then
1169      Begin
1170      If Cfg^.CreateDirs then
1171       Begin
1172       MakeDir(Cfg^.Bad);
1173       LogSetCurLevel(LogHandle, 2);
1174       LogWriteLn(LogHandle, 'created badfiles-directory "'+Cfg^.Bad+'"');
1175       End
1176      Else
1177       Begin
1178       LogSetCurLevel(LogHandle, 2);
1179       LogWriteLn(LogHandle, 'badfiles-directory "'+Cfg^.Bad+'" does not exist!');
1180       End
1181      End;
1182 
1183     Cfg^.PT := RepEnv(ReadEntry('GENERAL', 'PASSTHROUGH'));
1184     If (Cfg^.PT = '') then IniError('No Passthrough directory defined!');
1185     If (not DirExist(Cfg^.PT)) then
1186      Begin
1187      If Cfg^.CreateDirs then
1188       Begin
1189       MakeDir(Cfg^.PT);
1190       LogSetCurLevel(LogHandle, 2);
1191       LogWriteLn(LogHandle, 'created passthrough-directory "'+Cfg^.PT+'"');
1192       End
1193      Else
1194       Begin
1195       LogSetCurLevel(LogHandle, 2);
1196       LogWriteLn(LogHandle, 'passthrough-directory "'+Cfg^.PT+'" does not exist!');
1197       End
1198      End;
1199 
1200     Val(RepEnv(ReadEntry('GENERAL', 'DESCPOS')), Cfg^.DescPos, Error);
1201 
1202     If (ReadEntry('GENERAL', 'LDESCSTRING') <> '') then
1203      Begin
1204      s := ReadEntry('GENERAL', 'LDESCSTRING');
1205      Cfg^.LDescString := s;
1206      End
1207     Else Cfg^.LDescString := ' ';
1208 
1209     If (ReadEntry('GENERAL', 'ADDDLCOUNT') <> '') then
1210      Begin
1211      s := UpStr(ReadEntry('GENERAL', 'ADDDLCOUNT'));
1212      Cfg^.AddDLC := ((s = 'ON') or (s = 'Y') or (s = 'YES') or (s = '1') or
1213      (s = 'J') or (s = 'JA'));
1214      End
1215     Else Cfg^.AddDLC := False;
1216 
1217     If (ReadEntry('GENERAL', 'SINGLEDESCLINE') <> '') then
1218      Begin
1219      s := UpStr(ReadEntry('GENERAL', 'SINGLEDESCLINE'));
1220      Cfg^.SingleDescLine := ((s = 'ON') or (s = 'Y') or (s = 'YES') or (s = '1') or
1221      (s = 'J') or (s = 'JA'));
1222      End
1223     Else Cfg^.SingleDescLine := False;
1224 
1225     Val(RepEnv(ReadEntry('GENERAL', 'DLCOUNTDIGITS')), Cfg^.DLCDig, Error);
1226     If (Cfg^.AddDLC and (Cfg^.DLCDig = 0)) then
1227      IniError('Invalid DLCountDigits!');
1228 
1229     Val(RepEnv(ReadEntry('GENERAL', 'MAXDUPEAGE')), Cfg^.MaxDupeAge, Error);
1230     If (Cfg^.MaxDupeAge = 0) then IniError('Invalid MaxDupeAge!');
1231 
1232     If (ReadEntry('GENERAL', 'CHECKDEST') <> '') then
1233       Begin
1234       s := UpStr(ReadEntry('GENERAL', 'CHECKDEST'));
1235       Cfg^.CheckDest := ((s = 'ON') or (s = 'Y') or (s = 'YES') or (s = '1') or
1236       (s = 'J') or (s = 'JA'));
1237       End
1238     Else Cfg^.CheckDest := True;
1239 
1240     If (ReadEntry('GENERAL', 'DELREQ') <> '') then
1241       Begin
1242       s := UpStr(ReadEntry('GENERAL', 'DELREQ'));
1243       Cfg^.DelReq := ((s = 'ON') or (s = 'Y') or (s = 'YES') or (s = '1') or
1244       (s = 'J') or (s = 'JA'));
1245       End
1246     Else Cfg^.DelReq := False;
1247 
1248     If (ReadEntry('GENERAL', 'DELRSP') <> '') then
1249       Begin
1250       s := UpStr(ReadEntry('GENERAL', 'DELRSP'));
1251       Cfg^.DelRsp := ((s = 'ON') or (s = 'Y') or (s = 'YES') or (s = '1') or
1252       (s = 'J') or (s = 'JA'));
1253       End
1254     Else Cfg^.DelRsp := False;
1255 
1256     Cfg^.LocalPwd := ReadEntry('GENERAL', 'LOCALPWD');
1257     If (Cfg^.LocalPwd = '') then IniError('No LocalPwd defined!');
1258 
1259     If (ReadEntry('GENERAL', 'LONGDIRNAMES') <> '') then
1260       Begin
1261       s := UpStr(ReadEntry('GENERAL', 'LONGDIRNAMES'));
1262       Cfg^.LongDirNames := ((s = 'ON') or (s = 'Y') or (s = 'YES') or (s = '1') or
1263       (s = 'J') or (s = 'JA'));
1264       End
1265     Else Cfg^.LongDirNames := False;
1266 
1267     If (ReadEntry('GENERAL', 'SPLITDIRS') <> '') then
1268       Begin
1269       s := UpStr(ReadEntry('GENERAL', 'SPLITDIRS'));
1270       Cfg^.SplitDirs := ((s = 'ON') or (s = 'Y') or (s = 'YES') or (s = '1') or
1271       (s = 'J') or (s = 'JA'));
1272       End
1273     Else Cfg^.SplitDirs := True;
1274 
1275     Cfg^.AreasLog := RepEnv(ReadEntry('GENERAL', 'AREASLOG'));
1276     If (Cfg^.AreasLog = '') then Cfg^.AreasLog := Cfg^.DataPath + 'areas.log';
1277 
1278     Cfg^.BBSAreaLog := RepEnv(ReadEntry('GENERAL', 'BBSAREALOG'));
1279     If (Cfg^.BBSAreaLog = '') then Cfg^.BBSAreaLog := Cfg^.DataPath + 'bbsarea.log';
1280 
1281     Cfg^.LNameLst := RepEnv(ReadEntry('GENERAL', 'LONGNAMELST'));
1282     If (Cfg^.LNameLst = '') then Cfg^.LNameLst := Cfg^.DataPath + 'longname.lst';
1283 
1284     Cfg^.NewAreasLst := RepEnv(ReadEntry('GENERAL', 'NEWAREASLST'));
1285     If (Cfg^.NewAreasLst = '') then Cfg^.NewAreasLst := Cfg^.DataPath + 'newareas.pt';
1286 
1287     Cfg^.ArcLst := RepEnv(ReadEntry('GENERAL', 'ARCLST'));
1288     If (Cfg^.ArcLst = '') then Cfg^.ArcLst := Cfg^.DataPath + 'arc.lst';
1289 
1290     Cfg^.PTLst := RepEnv(ReadEntry('GENERAL', 'PTLST'));
1291     If (Cfg^.PTLst = '') then Cfg^.PTLst := Cfg^.DataPath + 'pt.lst';
1292 
1293     Cfg^.MsgIDFile := RepEnv(ReadEntry('GENERAL', 'MSGIDFILE'));
1294     If (Cfg^.MsgIDFile = '') then
1295      Begin
1296      If (GetEnv('MSGID') <> '') then Cfg^.MsgIDFile :=
1297       AddDirSep(GetEnv('MSGID'))+'msgid.dat'
1298      Else Cfg^.MsgIDFile := Cfg^.DataPath + 'msgid.dat';
1299      End;
1300 
1301     Cfg^.DupeFile := RepEnv(ReadEntry('GENERAL', 'DUPEFILE'));
1302     If (Cfg^.DupeFile = '') then Cfg^.DupeFile := Cfg^.DataPath + 'protick.dup';
1303 
1304     If (ReadEntry('GENERAL', 'FILEUMASK') <> '') then
1305      Begin
1306      FilePerm := OctalStrToInt(RepEnv(ReadEntry('GENERAL', 'FILEUMASK')));
1307      FilePerm := 511 and not FilePerm;
1308      End
1309     Else FilePerm := 493; {Octal 755}
1310 
1311     If (ReadEntry('GENERAL', 'DIRUMASK') <> '') then
1312      Begin
1313      DirPerm := OctalStrToInt(RepEnv(ReadEntry('GENERAL', 'DIRUMASK')));
1314      DirPerm := 511 and not DirPerm;
1315      End
1316     Else DirPerm := FilePerm;
1317 
1318     Cfg^.SysOp := RepEnv(ReadEntry('GENERAL', 'SYSOP'));
1319     If (Cfg^.SysOp = '') then IniError('No SysOp name defined!');
1320     Cfg^.BBS := RepEnv(ReadEntry('GENERAL', 'BBS'));
1321     If (Cfg^.BBS = '') then IniError('No BBS name defined!');
1322 
1323     ParseAddrs;
1324     ParseDomains;
1325     ParsePackers;
1326     ParseUnPackers;
1327     ParseGroups;
1328     ParseAnnGroups;
1329     ParseFileAreas;
1330     ParseUser;
1331     ParseUpLinks;
1332     ParseArcNames;
1333     ParseMgrNames;
1334 
1335     If Debug then
1336       Begin
1337       WriteLn('<Return>');
1338       ReadLn;
1339       End;
1340 
1341     end;
1342   End;
1343 
1344 End.
1345