1 Program PMkNL;
2 {$Define MKNL}
3 {$I-}
4 {$IfDef SPEED}
5 {$Else}
6 {$IfDef VIRTUALPASCAL}
7 {$Define VP}
8 {$M 65520}
9 {$Else}
10 {$M 65520, 0, 655360}
11 {$EndIf}
12 {$EndIf}
13
14 Uses
15 {$IfDef VP}
16 OS2Base, OS2Def,
17 {$EndIf}
18 {$IfDef UNIX}
19 Linux,
20 {$EndIf}
21 dos,
22 mkglobt, mkmisc, mkmsgabs, mkmsgfid, mkmsgezy, mkmsgjam, mkmsghud, mkmsgsqu,
23 crc, types, generalp, log, inifile2;
24 {$IfDef VP}
25 {$IfDef VPDEMO}
26 {$Dynamic VP11DEMO.LIB}
27 {$EndIf}
28 {$EndIf}
29
30 Const
31 Name : String[7] = 'ProMkNL';
32 ShortName : String[5] = 'PMKNL';
33 {Current Version}
34 Version : String[20] =
35 {$IfDef OS2}
36 '/2 '
37 {$Else}
38 {$IfDef UNIX}
39 '/Lx '
40 {$Else}
41 {$IfDef DPMI}
42 '/16 '
43 {$Else}
44 '/8 '
45 {$EndIf}
46 {$EndIf}
47 {$EndIf}
48 +'0.9beta9';
49
50 cSunday = 0;
51 cMonday = 1;
52 cTuesday = 2;
53 cWednesday = 3;
54 cThursday = 4;
55 cFriday = 5;
56 cSaturday = 6;
57 cAll = 7;
58
59 cYes = 1;
60
61 cNIntl = 2; {Notify: force INTL}
62 cNCrash = 4; {Notify: set crash flag}
63 cNKillSent = 8; {Notify: set kill/sent flag}
64 cSIntl = 2; {Submit: force INTL}
65 cSCrash = 4; {Submit: set crash flag}
66 cSKillSent = 8; {Submit: set kill/sent flag}
67
68 cTComposite = 0;
69 cTZone = 1;
70 cTRegion = 2;
71 cTNet = 3;
72 cTHub = 4;
73 cTNode = 5;
74
75 cEInvalidType = 1;
76 cEEmptyAddr = 2;
77 cEInvalidAddr = 3;
78 cEEmptyPhone = 4;
79 cEInvalidPhone = 5;
80 cEEmptyBaud = 6;
81 cEInvalidBaud = 7;
82 cEEmptyFlag = 8;
83 cEInvalidFlag = 9;
84 cWEmptySysName = 128+1;
85 cWEmptyLocation = 128+2;
86 cWEmptySysOpName = 128+3;
87 cWInvalidComment = 128+4;
88 cWEmptyLine = 128+5;
89 cWEOF = 128+6;
90
91 cPhoneChars : Set of Char = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '.', '*', '#'];
92
93 cNumFlags = 49;
94 cFlags : Array[1..cNumFlags] of String[10] = (
95 'CM', 'MO', 'LO',
96 'MN', 'XA', 'XB', 'XC', 'XP', 'XR', 'XW', 'XX',
97 'V21', 'V22', 'V29', 'V32', 'V32B', 'V33', 'V34', 'V34+', 'H96', 'HST',
98 'H14', 'H16', 'MAX', 'PEP', 'CSP', 'ZYX', 'Z19', 'VFC', 'V32T',
99 'V90C', 'V90S', 'X2C', 'X2S',
100 'X75', 'V110H', 'V110L', 'ISDN', 'V120H', 'V120L',
101 'MNP', 'V42', 'V42B',
102 '#01', '#02', '#03', '#09', '#18', '#20');
103
104
105 Type
106 PCfg = ^TCfg;
107 PData = ^TData;
108 PFiles = ^TFiles;
109 PBaud = ^TBaud;
110
111 TNetAddr = {21 Byte}
112 Record
113 Zone, Net, Node, Point: Word;
114 Domain: String[12];
115 end;
116
117 TFile =
118 Record
119 Typ: Byte;
120 PartAddr: Word;
121 UPD: String[100];
122 NotifyAddr: TNetAddr;
123 SkipComments: Boolean;
124 End;
125
126 TData = Array[1..100] of String[255]; {25kb}
127 TFiles = Array[1..100] of TFile;
128 TBaud = Array[1..30] of Word;
129
130 TCfg =
131 Record
132 {Section GENERAL}
133 LogFile: String128;
134 LogLevel: Byte;
135 MasterDir: String128;
136 UpdateDir: String128;
137 BadDir: String128;
138 OutPath: String128;
139 MailDir: String128;
140 NetMail: String128;
141
142 {Section <SectionName>}
143 OutFile: String40;
144 OutDiff: String40;
145 Prolog: String128;
146 Epilog: String128;
147 CopyRight: String128;
148 ProcessDay: Byte;
149 NotifyErr: Byte;
150 NotifyOK: Byte;
151 OwnAddr: TNetAddr;
152 SubmitAddr: TNetAddr;
153 Submit: Byte;
154 NetName: String40;
155 NLType: Byte;
156 CreateBatch: String;
157 CallBatch: String;
158 Data: PData;
159 NumData: Byte;
160 Files: PFiles;
161 NumFiles: Byte;
162 Baud: PBaud;
163 NumBaud: Byte;
164 End;
165
166 Var
167 Ini: IniObj;
168 lh: Word; {LogHandle}
169 Cfg: PCfg;
170 SecName: String40;
171 NM: AbsMsgPtr;
172 NMOpen: Boolean;
173 DoProcess: Boolean;
174
Addr2Strnull175 Function Addr2Str(Addr: TNetAddr): String;
176 Var
177 s: String;
178
179 Begin
180 With Addr do
181 Begin
182 s := IntToStr(Zone) + ':' + IntToStr(Net) + '/' + IntToStr(Node);
183 If (Point <> 0) then s := s + '.' + IntToStr(Point);
184 If (Domain <> '') then s := s + '@' + Domain;
185 Addr2Str := s;
186 End;
187 End;
188
Addr2StrNDnull189 Function Addr2StrND(Addr: TNetAddr): String; {no domain}
190 Var
191 s: String;
192
193 Begin
194 With Addr do
195 Begin
196 s := IntToStr(Zone) + ':' + IntToStr(Net) + '/' + IntToStr(Node);
197 If (Point <> 0) then s := s + '.' + IntToStr(Point);
198 Addr2StrND := s;
199 End;
200 End;
201
202 Procedure PartStr2Addr(s: String; var Addr: TNetAddr);
203 Var
204 {$IfDef VIRTUALPASCAL}
205 i: LongInt;
206 {$Else}
207 i: Integer;
208 {$EndIf}
209
210 Begin
211 If (Pos(':', s) = 0) then Val(s, Addr.Zone, i)
212 Else
213 Begin
214 Val(Copy(s, 1, Pos(':', s)-1), Addr.Zone, i);
215 Delete(s, 1, Pos(':', s));
216 If (Pos('/', s) = 0) then Val(s, Addr.Net, i)
217 Else
218 Begin
219 Val(Copy(s, 1, Pos('/', s)-1), Addr.Net, i);
220 Delete(s, 1, Pos('/', s));
221 If (Pos('.', s) = 0) then Val(s, Addr.Node, i)
222 Else
223 Begin
224 Val(Copy(s, 1, Pos('.', s)-1), Addr.Node, i);
225 Delete(s, 1, Pos('.', s));
226 Val(s, Addr.Point, i);
227 End;
228 End;
229 End;
230 End;
231
232 Procedure Str2Addr(s: String; var Addr: TNetAddr);
233 Var
234 {$IfDef VIRTUALPASCAL}
235 i: LongInt;
236 {$Else}
237 i: Integer;
238 {$EndIf}
239
240 Begin
241 If (Pos(':', s) = 0) then Addr.Zone := 0
242 Else
243 Begin
244 Val(Copy(s, 1, Pos(':', s) - 1), Addr.Zone, i);
245 Delete(s, 1, Pos(':', s));
246 End;
247 If (Pos('/', s) = 0) then
248 Begin
249 End
250 Else
251 Begin
252 Val(Copy(s, 1, Pos('/', s) - 1), Addr.Net, i);
253 Delete(s, 1, Pos('/', s));
254 End;
255 If (Pos('.', s) = 0) or
256 ((Pos('.', s) > Pos('@', s)) and (Pos('@', s) > 0)) then
257 Begin
258 Addr.Point := 0;
259 If (Pos('@', s) = 0) then
260 Begin
261 Val(s, Addr.Node, i);
262 Addr.Domain := '';
263 End
264 Else
265 Begin
266 Val(Copy(s, 1, Pos('@', s) - 1), Addr.Node, i);
267 Delete(s, 1, Pos('@', s));
268 Addr.Domain := UpStr(s);
269 End;
270 End
271 Else
272 Begin
273 Val(Copy(s, 1, Pos('.', s) - 1), Addr.Node, i);
274 Delete(s, 1, Pos('.', s));
275 If (Pos('@', s) = 0) then
276 Begin
277 Val(s, Addr.Point, i);
278 Addr.Domain := '';
279 End
280 Else
281 Begin
282 Val(Copy(s, 1, Pos('@', s) - 1), Addr.Point, i);
283 Delete(s, 1, Pos('@', s));
284 Addr.Domain := UpStr(s);
285 End;
286 End;
287 End;
288
CompAddrnull289 Function CompAddr(A1, A2: TNetAddr): Boolean;
290 Var
291 C: Boolean;
292
293 Begin
294 c := ((A1.Zone = 0) or (A2.Zone = 0) or (A1.Zone = A2.Zone));
295 c := c and ((A1.Net = 0) or (A2.Net = 0) or (A1.Net = A2.Net));
296 c := c and (A1.Node = A2.Node);
297 c := c and (A1.Point = A2.Point);
298 c := c and ((A1.Domain = '') or (A2.Domain = '') or (UpStr(A1.Domain) = UpStr(A2.Domain)));
299 CompAddr := c;
300 End;
301
302 Procedure TNetAddr2MKAddr(A1: TNetAddr; Var MKAddr: AddrType);
303 Begin
304 MKAddr.Zone := A1.Zone;
305 MKAddr.Net := A1.Net;
306 MKAddr.Node := A1.Node;
307 MKAddr.Point := A1.Point;
308 MKAddr.Domain := A1.Domain;
309 End;
310
311
312 Procedure Syntax;
313 Begin
314 WriteLn('Syntax: '+ShortName+' <SectionName> [/P|/T]');
315 End;
316
ParseCfgnull317 Function ParseCfg: Boolean;
318 Var
319 {$IfDef VP}
320 Error: LongInt;
321 {$Else}
322 Error: Integer;
323 {$EndIf}
324 s, s1: String;
325 i: Byte;
326 p: Byte;
327 b: Boolean;
328
329 Begin
330 ParseCfg := True;
331 Cfg^.LogFile := Ini.ReadEntry('GENERAL', 'LOG');
332 If (Cfg^.LogFile = '') then
333 Begin
334 WriteLn('no Logfile defined!');
335 ParseCfg := False;
336 Exit;
337 End;
338 Val(Ini.ReadEntry('GENERAL', 'LOGLEVEL'), Cfg^.LogLevel, Error);
339 Cfg^.MasterDir := AddDirSep(Ini.ReadEntry('GENERAL', 'MASTER'));
340 Cfg^.UpdateDir := AddDirSep(Ini.ReadEntry('GENERAL', 'UPDATE'));
341 Cfg^.BadDir := AddDirSep(Ini.ReadEntry('GENERAL', 'BAD'));
342 Cfg^.OutPath := AddDirSep(Ini.ReadEntry('GENERAL', 'OUTPATH'));
343 Cfg^.MailDir := AddDirSep(Ini.ReadEntry('GENERAL', 'MAILDIR'));
344 Cfg^.Netmail := Ini.ReadEntry('GENERAL', 'NETMAIL');
345
346 If Ini.GetSecNum(SecName) = 0 then
347 Begin
348 WriteLn('Section "'+SecName+'" not found or empty!');
349 ParseCfg := False;
350 Exit;
351 End;
352 Cfg^.OutFile := Ini.ReadEntry(SecName, 'OUTFILE');
353 Cfg^.OutDiff := Ini.ReadEntry(SecName, 'OUTDIFF');
354 Cfg^.Prolog := Ini.ReadEntry(SecName, 'PROLOG');
355 Cfg^.Epilog := Ini.ReadEntry(SecName, 'EPILOG');
356 Cfg^.Copyright := Ini.ReadEntry(SecName, 'COPYRIGHT');
357 Cfg^.CreateBatch := Ini.ReadEntry(SecName, 'CREATEBATCH');
358 Cfg^.CallBatch := Ini.ReadEntry(SecName, 'CALLBATCH');
359 s := UpStr(Ini.ReadEntry(SecName, 'PROCESS'));
360 If (s = 'MONDAY') then Cfg^.ProcessDay := cMonday
361 Else If (s = 'TUESDAY') then Cfg^.ProcessDay := cTuesday
362 Else If (s = 'WEDNESDAY') then Cfg^.ProcessDay := cWednesday
363 Else If (s = 'THURSDAY') then Cfg^.ProcessDay := cThursday
364 Else If (s = 'FRIDAY') then Cfg^.ProcessDay := cFriday
365 Else If (s = 'SATURDAY') then Cfg^.ProcessDay := cSaturday
366 Else If (s = 'SUNDAY') then Cfg^.ProcessDay := cSunday
367 Else If (s = 'ALL') then Cfg^.ProcessDay := cAll
368 Else
369 Begin
370 WriteLn('Invalid ProcessDay: '+s);
371 Cfg^.ProcessDay := 0;
372 End;
373 s := UpStr(Ini.ReadEntry(SecName, 'NOTIFYERR'));
374 Cfg^.NotifyErr := 0;
375 If (Pos('YES', s) > 0) then Inc(Cfg^.NotifyErr, cYes);
376 If (Pos('CRASH', s) > 0) then Inc(Cfg^.NotifyErr, cNCrash);
377 If (Pos('INTL', s) > 0) then Inc(Cfg^.NotifyErr, cNIntl);
378 If (Pos('KILLSENT', s) > 0) then Inc(Cfg^.NotifyErr, cNKillSent);
379 s := UpStr(Ini.ReadEntry(SecName, 'NOTIFYOK'));
380 Cfg^.NotifyOK := 0;
381 If (Pos('YES', s) > 0) then Inc(Cfg^.NotifyOK, cYes);
382 If (Pos('CRASH', s) > 0) then Inc(Cfg^.NotifyOK, cNCrash);
383 If (Pos('INTL', s) > 0) then Inc(Cfg^.NotifyOK, cNIntl);
384 If (Pos('KILLSENT', s) > 0) then Inc(Cfg^.NotifyOK, cNKillSent);
385 Str2Addr(Ini.ReadEntry(SecName, 'OWNADDR'), Cfg^.OwnAddr);
386 s := UpStr(Ini.ReadEntry(SecName, 'SUBMIT'));
387 If (s <> '') then
388 Begin
389 Cfg^.Submit := cYes;
390 If (Pos(',', s) > 0) then
391 Begin
392 Str2Addr(Copy(s, 1, Pos(',', s)-1), Cfg^.SubmitAddr);
393 If (Pos('CRASH', s) > 0) then Inc(Cfg^.Submit, cSCrash);
394 If (Pos('INTL', s) > 0) then Inc(Cfg^.Submit, cSIntl);
395 If (Pos('KILLSENT', s) > 0) then Inc(Cfg^.Submit, cSKillSent);
396 End
397 Else Str2Addr(s, Cfg^.SubmitAddr);
398 End
399 Else Cfg^.Submit := 0;
400 Cfg^.NetName := Ini.ReadEntry(SecName, 'NETNAME');
401 s1 := UpStr(Ini.ReadEntry(SecName, 'TYPE'));
402 If (s1 = 'COMPOSITE') then Cfg^.NLType := cTComposite
403 Else If (s1 = 'ZONE') then Cfg^.NLType := cTZone
404 Else If (s1 = 'REGION') then Cfg^.NLType := cTRegion
405 Else If (s1 = 'NETWORK') then Cfg^.NLType := cTNet
406 Else If (s1 = 'NET') then Cfg^.NLType := cTNet
407 Else If (s1 = 'HUB') then Cfg^.NLType := cTHub
408 Else If (s1 = 'NODE') then Cfg^.NLType := cTNode
409 Else Cfg^.NLType := cTNode;
410 s := Ini.ReadEntry(SecName, 'ALLOWBAUD');
411 If (s = '') then Cfg^.NumBaud := 0
412 Else
413 Begin
414 i := 0;
415 p := Pos(',', s);
416 While (p > 0) do
417 Begin
418 Inc(i);
419 Val(Copy(s, 1, p-1), Cfg^.Baud^[i], Error);
420 Delete(s, 1, p);
421 p := Pos(',', s);
422 End;
423 Inc(i);
424 Val(Copy(s, 1, p-1), Cfg^.Baud^[i], Error);
425 Cfg^.NumBaud := i;
426 End;
427 i := 0;
428 Ini.SetSection(SecName);
429 With Ini do b := (UpStr(ReSecEnName) <> 'DATA') and (UpStr(ReSecEnName) <> 'FILE');
430 While b do
431 Begin
432 If not Ini.SetNextOpt then
433 Begin
434 Cfg^.NumData := 0;
435 Cfg^.NumFiles := 0;
436 Exit;
437 End;
438 b := (UpStr(Ini.ReSecEnName) <> 'DATA') ;
439 b := b and (UpStr(Ini.ReSecEnName) <> 'FILE')
440 End;
441 While UpStr(Ini.ReSecEnName) = 'DATA' do
442 Begin
443 Inc(i);
444 Cfg^.Data^[i] := Ini.ReSecEnValue;
445 s := Cfg^.Data^[i];
446 If not Ini.SetNextOpt then Break;
447 End;
448 Cfg^.NumData:= i;
449 While (UpStr(Ini.ReSecEnName) <> 'FILE') do
450 Begin
451 If not Ini.SetNextOpt then
452 Begin
453 Cfg^.NumFiles := 0;
454 Exit;
455 End;
456 End;
457 i := 0;
458 While UpStr(Ini.ReSecEnName) = 'FILE' do
459 Begin
460 Inc(i);
461 s := KillLeadingSpcs(Ini.ReSecEnValue);
462 With Cfg^.Files^[i] do
463 Begin
464 s1 := UpStr(Copy(s, 1, Pos(',', s)-1));
465 Delete(s, 1, Pos(',', s));
466 s := KillLeadingSpcs(s);
467 If (s1 = 'ZONE') then Typ := cTZone
468 Else If (s1 = 'REGION') then Typ := cTRegion
469 Else If (s1 = 'NETWORK') then Typ := cTNet
470 Else If (s1 = 'NET') then Typ := cTNet
471 Else If (s1 = 'HUB') then Typ := cTHub
472 Else If (s1 = 'NODE') then Typ := cTNode
473 Else Typ := cTNode;
474 Val(Copy(s, 1, Pos(',', s)-1), PartAddr, Error);
475 Delete(s, 1, Pos(',', s));
476 UPD := KillLeadingSpcs(Copy(s, 1, Pos(',', s)-1));
477 Delete(s, 1, Pos(',', s));
478 If (Pos(',', s) > 0) then
479 Begin
480 Str2Addr(Copy(s, 1, Pos(',', s)-1), NotifyAddr);
481 Delete(s, 1, Pos(',', s));
482 If (UpStr(s) = 'SKIPCOMMENTS') then SkipComments := True;
483 End
484 Else
485 Begin
486 Str2Addr(s, NotifyAddr);
487 SkipComments := False;
488 End;
489 End;
490 If not Ini.SetNextOpt then Break;
491 End;
492 Cfg^.NumFiles:= i;
493 End;
494
495 Procedure Init;
496 Var
497 DT: TimeTyp;
498 CfgName: String;
499 s: String;
500
501 Begin
502 WriteLn(Name+Version);
503 WriteLn;
504 If (ParamCount < 1) then
505 Begin
506 Syntax;
507 Halt(1);
508 End;
509 SecName := ParamStr(1);
510 If FileExist(GetEnv(ShortName)+DirSep+LowStr(ShortName)+'.cfg') then
511 CfgName := GetEnv(ShortName)+DirSep+LowStr(ShortName)+'.cfg'
512 Else CfgName := LowStr(ShortName)+'.cfg';
513 Ini.Init(CfgName);
514 New(Cfg);
515 New(Cfg^.Data);
516 New(Cfg^.Files);
517 New(Cfg^.Baud);
518 If not ParseCfg then
519 Begin
520 Dispose(Cfg^.Baud);
521 Dispose(Cfg^.Files);
522 Dispose(Cfg^.Data);
523 Dispose(Cfg);
524 Ini.Done;
525 Halt(2);
526 End;
527 Today(DT);
528 s := ParamStr(2);
529 DoProcess := (Upcase(s[2]) = 'P') or ((DT.DayOfWeek = Cfg^.Processday) or
530 (Cfg^.ProcessDay = cAll));
531 DoProcess := DoProcess and not (Upcase(s[2]) = 'T');
532 lh := OpenLog(Binkley, Cfg^.LogFile, ShortName, Name+Version);
533 LogSetScrLevel(lh, 5);
534 LogSetLogLevel(lh, Cfg^.LogLevel);
535 LogSetCurLevel(lh, 4);
536 LogWriteLn(lh, 'Section '+SecName);
537 LogSetCurLevel(lh, 1);
538 End;
539
540 Procedure Done;
541 Begin
542 CloseLog(lh);
543 Ini.Done;
544 Dispose(Cfg^.Files);
545 Dispose(Cfg^.Data);
546 Dispose(Cfg);
547 End;
548
OpenNMnull549 Function OpenNM: Boolean;
550 Begin
551 OpenNM := True;
552 Case UpCase(Cfg^.NetMail[1]) of
553 'H': NM := New(HudsonMsgPtr, Init);
554 'S': NM := New(SqMsgPtr, Init);
555 'F': NM := New(FidoMsgPtr, Init);
556 'E': NM := New(EzyMsgPtr, Init);
557 Else
558 Begin
559 LogSetCurLevel(LH, 1);
560 LogWriteLn(LH, 'Invalid type for netmail area!');
561 OpenNM := False;
562 Exit;
563 End;
564 End;
565 NM^.SetMsgPath(Copy(Cfg^.NetMail, 2, Length(Cfg^.NetMail) - 1));
566 If (NM^.OpenMsgBase <> 0) then
567 Begin
568 LogSetCurLevel(LH, 1);
569 LogWriteLn(LH, 'Couldn''t open netmail area!');
570 Dispose(NM, Done);
571 OpenNM := False;
572 Exit;
573 End;
574 If (UpCase(Cfg^.NetMail[1]) = 'F') then FidoMsgPtr(NM)^.SetDefaultZone(0);
575 NM^.SetMailType(mmtNetMail);
576 End;
577
578 Procedure CloseNM;
579 Begin
580 If (NM^.CloseMsgBase <> 0) then
581 Begin
582 LogSetCurLevel(LH, 1);
583 LogWriteLn(LH, 'Couldn''t close netmail area!');
584 End;
585 Dispose(NM, Done);
586 End;
587
GetMsgIDnull588 Function GetMsgID : String;
589 Var
590 MsgIDFile: Text;
591 CurMsgID: ULong;
592 Dir: String;
593 s: String;
594 Error: Integer;
595
596 begin
597 Dir := GetEnv('MSGID');
598 If (Dir = '') then Dir := AddDirSep(Cfg^.MasterDir)
599 Else Dir := AddDirSep(Dir);
600 Assign(MsgIDFile, Dir + 'msgid.dat');
601 {$I-} ReSet(MsgIDFile); {$I+}
602 If (IOResult = 0) then
603 begin
604 ReadLn(MsgIDFile, s);
605 While (s[Byte(s[0])] = #10) or (s[Byte(s[0])] = #13) do Dec(s[0]);
606 Val(s, CurMsgID, Error);
607 If (Error <> 0) or (CurMsgID = 0) then CurMsgID := 1;
608 Close(MsgIDFile);
609 end
610 Else CurMsgID := 1; {Reset MsgID if no MSGID.DAT is found}
611 GetMsgID := WordToHex(word(CurMsgID SHR 16)) + WordToHex(word(CurMsgID));
612 Inc(CurMsgID);
613 {$I-} ReWrite(MsgIDFile); {$I+}
614 If (IOResult = 0) then
615 Begin
616 Write(MsgIDFile, CurMsgID, #13#10);
617 Close(MsgIDFile);
618 End;
619 end;
620
621 Procedure SetDT(MB: AbsMsgPtr);
622 Var
623 DT: TimeTyp;
624 s: String;
625
626 Begin
627 With MB^ do
628 Begin
629 Today(DT);
630 If (DT.Year > 100) then DT.Year := DT.Year mod 100;
631 Now(DT);
632 If (DT.Month > 9) then s := IntToStr(DT.Month) + '-'
633 Else s := '0' + IntToStr(DT.Month) + '-';
634 If (DT.Day > 9) then s := s + IntToStr(DT.Day) + '-'
635 Else s := s + '0' + IntToStr(DT.Day) + '-';
636 If (DT.Year > 9) then s := s + IntToStr(DT.Year)
637 Else s := s + '0' + IntToStr(DT.Year);
638 SetDate(s);
639 If (DT.Hour > 9) then s := IntToStr(DT.Hour) + ':'
640 Else s := '0' + IntToStr(DT.Hour) + ':';
641 If (DT.Min > 9) then s := s + IntToStr(DT.Min)
642 Else s := s + '0' + IntToStr(DT.Min);
643 SetTime(s);
644 End;
645 End;
646
647 Procedure SendOK(e: TFile);
648 Var
649 MKAddr: AddrType;
650 s: String;
651
652 Begin
653 LogSetCurLevel(lh, 3);
654 LogWriteLn(lh, 'sending OK-receipt to '+Addr2Str(e.NotifyAddr));
655 If not OpenNM then Exit;
656 With NM^ do
657 Begin
658 StartNewMsg;
659 s := Name + Version;
660 SetFrom(s);
661 TNetAddr2MKAddr(Cfg^.OwnAddr, MKAddr);
662 SetOrig(MKAddr);
663 SetTo('Coordinator');
664 TNetAddr2MKAddr(e.NotifyAddr, MKAddr);
665 SetDest(MKAddr);
666 SetSubj(e.UPD+' received: No errors');
667 SetLocal(True);
668 SetCrash((Cfg^.NotifyOK and cNCrash) > 0);
669 SetKillSent((Cfg^.NotifyOK and cNKillSent) > 0);
670 SetDT(NM);
671 If (Cfg^.OwnAddr.Point <> 0) then DoStringLn(#1'FMPT '+IntToStr(Cfg^.OwnAddr.Point));
672 If (e.NotifyAddr.Point <> 0) then DoStringLn(#1'TOPT '+IntToStr(e.NotifyAddr.Point));
673 If (e.NotifyAddr.Zone <> Cfg^.OwnAddr.Zone) or ((Cfg^.NotifyOK and cNIntl) > 0) then
674 DoStringLn(#1'INTL '+Addr2StrND(e.NotifyAddr)+' '+Addr2StrND(Cfg^.OwnAddr));
675 DoStringLn(#1'MSGID: '+Addr2Str(Cfg^.OwnAddr)+' '+GetMsgID);
676 DoStringLn(#1'PID: '+Name+Version);
677 DoStringLn('Your nodelist update, '+e.UPD+', has been received and processsed without errors.');
678 DoStringLn('--- '+Name+Version);
679 If (WriteMsg <> 0) then
680 Begin
681 LogSetCurLevel(LH, 1);
682 LogWriteLn(LH, 'Couldn''t write to netmail area!');
683 End;
684 End;
685 CloseNM;
686 End;
687
688 Procedure Mark(e: TFile; lNum: Word; Line: String; Error: Byte; ErrStr: String);
689 Var
690 MKAddr: AddrType;
691 s: String;
692
693 Begin
694 If (Cfg^.NotifyErr and cYes) = 0 then Exit;
695 If not NMOpen then
696 Begin
697 LogSetCurLevel(lh, 3);
698 LogWriteLn(lh, 'sending ERROR-receipt to '+Addr2Str(e.NotifyAddr));
699 If not OpenNM then Exit;
700 With NM^ do
701 Begin
702 StartNewMsg;
703 s := Name + Version;
704 SetFrom(s);
705 TNetAddr2MKAddr(Cfg^.OwnAddr, MKAddr);
706 SetOrig(MKAddr);
707 SetTo('Coordinator');
708 TNetAddr2MKAddr(e.NotifyAddr, MKAddr);
709 SetDest(MKAddr);
710 SetSubj(e.UPD+' received: contained ERRORS!');
711 SetLocal(True);
712 SetCrash((Cfg^.NotifyErr and cNCrash) > 0);
713 SetKillSent((Cfg^.NotifyErr and cNKillSent) > 0);
714 SetDT(NM);
715 If (Cfg^.OwnAddr.Point <> 0) then DoStringLn(#1'FMPT '+IntToStr(Cfg^.OwnAddr.Point));
716 If (e.NotifyAddr.Point <> 0) then DoStringLn(#1'TOPT '+IntToStr(e.NotifyAddr.Point));
717 If (e.NotifyAddr.Zone <> Cfg^.OwnAddr.Zone) or ((Cfg^.NotifyOK and cNIntl) > 0) then
718 DoStringLn(#1'INTL '+Addr2StrND(e.NotifyAddr)+' '+Addr2StrND(Cfg^.OwnAddr));
719 DoStringLn(#1'MSGID: '+Addr2Str(Cfg^.OwnAddr)+' '+GetMsgID);
720 DoStringLn(#1'PID: '+Name+Version);
721 DoStringLn('Your nodelist update, '+e.UPD+', contained the following mistakes: ');
722 DoStringLn('');
723 End;
724 NMOpen := True;
725 End;
726 With NM^ do
727 Begin
728 DoStringLn('Line '+IntToStr(lNum)+' > '+Line);
729 Case Error of
730 cEInvalidType : DoStringLn('Error: Invalid type: "'+ErrStr+'"');
731 cEEmptyAddr : DoStringLn('Error: Empty address');
732 cEInvalidAddr : DoStringLn('Error: Invalid address: "'+ErrStr+'"');
733 cEEmptyPhone : DoStringLn('Error: Empty phonenumber');
734 cEInvalidPhone : DoStringLn('Error: Invalid phonenumber: "'+ErrStr+'"');
735 cEEmptyBaud : DoStringLn('Error: Empty baudrate');
736 cEInvalidBaud : DoStringLn('Error: Invalid baudrate: "'+ErrStr+'"');
737 cEEmptyFlag : DoStringLn('Error: Empty flag');
738 cEInvalidFlag : DoStringLn('Error: Invalid flag: "'+ErrStr+'"');
739 cWEmptySysName : DoStringLn('Warning: Empty systemname');
740 cWEmptyLocation : DoStringLn('Warning: Empty location');
741 cWEmptySysOpName : DoStringLn('Warning: Empty SysOp-name');
742 cWInvalidComment : DoStringLn('Warning: Invalid comment-type: "'+ErrStr+'"');
743 cWEmptyLine: DoStringLn('Warning: empty line');
744 cWEOF: DoStringLn('Warning: EOF-character (#26/#$19) found');
745 Else
746 Begin
747 DoStringLn('Error: unknown error #'+IntToStr(Error)+': "'+ErrStr+'". Please contact author!');
748 End;
749 End;
750 DoStringLn('');
751 End;
752 End;
753
CheckUPDnull754 Function CheckUPD(fn: FileStr; e: TFile): Boolean;
755 Var
756 line: String;
757 f: Text;
758 lNum: Word;
759 Bad: Boolean;
760 Warnings: Boolean;
761
762 Procedure ParseLine(Line: String);
763 Var
764 p: Byte;
765 s, l: String;
766 IsPvt: Boolean;
767 x, y: Word;
768 {$IfDef VP}
769 Error: LongInt;
770 {$Else}
771 Error: Integer;
772 {$EndIf}
773 UFlags: Boolean;
774
775 Begin
776 If (Line = '') then
777 Begin
778 Mark(e, lNum, Line, cWEmptyLine, '');
779 Warnings := True;
780 Exit;
781 End;
782 If (Line[1] = #26) then
783 Begin
784 Mark(e, lNum, Line, cWEOF, '');
785 Warnings := True;
786 Exit;
787 End;
788 If (Line[1] = ';') then
789 Begin
790 If (Length(Line) = 1) then Exit;
791 If not (UpCase(Line[2]) in ['S', 'U', 'F', 'A', 'E', ' ', #26]) then
792 Begin
793 Mark(e, lNum, Line, cWInvalidComment, Line[2]);
794 Warnings := True;
795 End;
796 Exit;
797 End;
798 IsPvt := False;
799 UFlags := False;
800 l := Line;
801 {type}
802 p := Pos(',', l);
803 If (p > 1) then
804 Begin
805 s := UpStr(Copy(l, 1, p-1));
806 If not ((s = 'ZONE') or (s = 'REGION') or (s = 'HOST') or (s = 'HUB') or
807 (s = 'PVT') or (s = 'HOLD') or (s = 'DOWN')) then
808 Begin
809 Bad := True;
810 Mark(e, lNum, Line, cEInvalidType, s);
811 End
812 Else if (s = 'PVT') then IsPvt := True;
813 End;
814 Delete(l, 1, p);
815 {address}
816 p := Pos(',', l);
817 s := Copy(l, 1, p-1);
818 If (s = '') then
819 Begin
820 Bad := True;
821 Mark(e, lNum, Line, cEEmptyAddr, '');
822 End
823 Else
824 Begin
825 Val(s, x, Error);
826 If (Error <> 0) then
827 Begin
828 Bad := True;
829 Mark(e, lNum, Line, cEInvalidAddr, s);
830 End;
831 End;
832 Delete(l, 1, p);
833 {SystemName}
834 p := Pos(',', l);
835 s := Copy(l, 1, p-1);
836 If (s = '') then
837 Begin
838 Mark(e, lNum, Line, cWEmptySysName, '');
839 Warnings := True;
840 End;
841 Delete(l, 1, p);
842 {Location}
843 p := Pos(',', l);
844 s := Copy(l, 1, p-1);
845 If (s = '') then
846 Begin
847 Mark(e, lNum, Line, cWEmptyLocation, '');
848 Warnings := True;
849 End;
850 Delete(l, 1, p);
851 {SysOpName}
852 p := Pos(',', l);
853 s := Copy(l, 1, p-1);
854 If (s = '') then
855 Begin
856 Mark(e, lNum, Line, cWEmptySysOpName, '');
857 Warnings := True;
858 End;
859 Delete(l, 1, p);
860 {Phone}
861 p := Pos(',', l);
862 s := UpStr(Copy(l, 1, p-1));
863 If not IsPvt then
864 Begin
865 If (s = '') then
866 Begin
867 Bad := True;
868 Mark(e, lNum, Line, cEEmptyPhone, '');
869 End
870 Else
871 Begin
872 Error := 0;
873 For x := 1 to Length(s) do If not (s[x] in cPhoneChars) then Error := 1;
874 If (Error > 0) then
875 Begin
876 Bad := True;
877 Mark(e, lNum, Line, cEInvalidPhone, s);
878 End;
879 Delete(l, 1, p);
880 End;
881 End;
882 {baud}
883 p := Pos(',', l);
884 s := Copy(l, 1, p-1);
885 If (s = '') then
886 Begin
887 Bad := True;
888 Mark(e, lNum, Line, cEEmptyBaud, '');
889 End
890 Else
891 Begin
892 Val(s, x, Error);
893 If (Error <> 0) then
894 Begin
895 Bad := True;
896 Mark(e, lNum, Line, cEInvalidBaud, s);
897 End;
898 If (Cfg^.NumBaud = 0) then
899 Begin
900 If not ((x = 300) or (x = 1200) or (x = 2400) or (x = 9600)) then
901 Begin
902 Bad := True;
903 Mark(e, lNum, Line, cEInvalidBaud, s);
904 End;
905 End
906 Else
907 Begin
908 Error := 1;
909 For y := 1 to Cfg^.NumBaud do If (x = Cfg^.Baud^[y]) then Error := 0;
910 If (Error = 1) then
911 Begin
912 Bad := True;
913 Mark(e, lNum, Line, cEInvalidBaud, s);
914 End;
915 End;
916 End;
917 Delete(l, 1, p);
918 {flags}
919 p := Pos(',', l);
920 While (p > 0) and not UFlags do
921 Begin
922 s := UpStr(Copy(l, 1, p-1));
923 Error := 1;
924 If (s = '') then
925 Begin
926 Bad := True;
927 Mark(e, lNum, Line, cEEmptyFlag, '');
928 Error := 0;
929 End
930 Else If (s = 'U') then
931 Begin
932 Error := 0;
933 UFlags := True
934 End
935 Else If (s[1] = 'G') then Error := 0
936 Else If (s[1] = 'U') then Error := 0
937 Else
938 Begin
939 For x := 1 to cNumFlags do If (s = cFlags[x]) then Error := 0;
940 End;
941 If (Error = 1) then
942 Begin
943 Bad := True;
944 Mark(e, lNum, Line, cEInvalidFlag, s);
945 End;
946 Delete(l, 1, p);
947 p := Pos(',', l);
948 End;
949 End;
950
951 Begin
952 CheckUPD := True;
953 Bad := False;
954 Warnings := False;
955 lNum := 0;
956 NMOpen := False;
957 Assign(f, fn);
958 {$I-} ReSet(f); {$I+}
959 If (IOResult <> 0) then
960 Begin
961 LogSetCurLevel(lh, 1);
962 LogWriteLn(lh, 'Could not open "'+fn+'"!');
963 CheckUPD := False;
964 Exit;
965 End;
966
967 While not EOF(f) do
968 Begin
969 Inc(lNum);
970 ReadLn(f, Line);
971 While ((Line[Byte(Line[0])] = #13) or (Line[Byte(Line[0])] = #10)) do
972 Line[0] := Char(Byte(Line[0])-1);
973 ParseLine(Line);
974 End;
975
976 {$I-} Close(f); {$I+}
977 If (IOResult <> 0) then
978 Begin
979 LogSetCurLevel(lh, 1);
980 LogWriteLn(lh, 'Could not close "'+fn+'"!');
981 End;
982
983 CheckUPD := not Bad;
984 If NMOpen then
985 Begin
986 NM^.DoStringLn('');
987 NM^.DoStringLn('--- '+Name+Version);
988 If (NM^.WriteMsg <> 0) then
989 Begin
990 LogSetCurLevel(LH, 1);
991 LogWriteLn(LH, 'Couldn''t write to netmail area!');
992 End;
993 CloseNM;
994 End;
995 NMOpen := False;
996 lNum := IOResult;
997 If (((not Warnings) and (not Bad)) and ((Cfg^.NotifyOK and cYes) > 0)) then SendOK(e);
998 lNum := IOResult;
999 End;
1000
1001 Procedure SubmitUPD(fn: FileStr);
1002 Var
1003 MKAddr: AddrType;
1004 s: String;
1005
1006 Begin
1007 LogSetCurLevel(lh, 3);
1008 LogWriteLn(lh, 'submitting '+fn+' to '+Addr2Str(Cfg^.SubmitAddr));
1009 If not OpenNM then Exit;
1010 With NM^ do
1011 Begin
1012 StartNewMsg;
1013 s := Name + Version;
1014 SetFrom(s);
1015 TNetAddr2MKAddr(Cfg^.OwnAddr, MKAddr);
1016 SetOrig(MKAddr);
1017 SetTo('Coordinator');
1018 TNetAddr2MKAddr(Cfg^.SubmitAddr, MKAddr);
1019 SetDest(MKAddr);
1020 SetSubj(fn);
1021 SetLocal(True);
1022 SetFAttach(True);
1023 SetCrash((Cfg^.Submit and cSCrash) > 0);
1024 SetKillSent((Cfg^.Submit and cSKillSent) > 0);
1025 SetDT(NM);
1026 If (Cfg^.OwnAddr.Point <> 0) then DoStringLn(#1'FMPT '+IntToStr(Cfg^.OwnAddr.Point));
1027 If (Cfg^.SubmitAddr.Point <> 0) then DoStringLn(#1'TOPT '+IntToStr(Cfg^.SubmitAddr.Point));
1028 If (Cfg^.SubmitAddr.Zone <> Cfg^.OwnAddr.Zone) or ((Cfg^.Submit and cSIntl) > 0) then
1029 DoStringLn(#1'INTL '+Addr2StrND(Cfg^.SubmitAddr)+' '+Addr2StrND(Cfg^.OwnAddr));
1030 DoStringLn(#1'MSGID: '+Addr2Str(Cfg^.OwnAddr)+' '+GetMsgID);
1031 DoStringLn(#1'PID: '+Name+Version);
1032 If (WriteMsg <> 0) then
1033 Begin
1034 LogSetCurLevel(LH, 1);
1035 LogWriteLn(LH, 'Couldn''t write to netmail area!');
1036 End;
1037 End;
1038 CloseNM;
1039 End;
1040
1041 Procedure LookForUPDs;
1042 Var
1043 i: LongInt;
1044
1045 Begin
1046 If (Cfg^.NumFiles = 0) then Exit;
1047 For i := 1 to Cfg^.NumFiles do
1048 Begin
1049 If FileExist(Cfg^.MailDir + Cfg^.Files^[i].UPD) then
1050 Begin
1051 LogSetCurLevel(lh, 3);
1052 LogWriteLn(lh, 'Found "'+Cfg^.MailDir + Cfg^.Files^[i].UPD+'" ('+Addr2Str(Cfg^.Files^[i].NotifyAddr)+')');
1053 If CheckUPD(Cfg^.MailDir + Cfg^.Files^[i].UPD, Cfg^.Files^[i]) then
1054 Begin
1055 If FileExist(Cfg^.UpdateDir + Cfg^.Files^[i].UPD) then DelFile(Cfg^.UpdateDir + Cfg^.Files^[i].UPD);
1056 If not MoveFile(Cfg^.MailDir + Cfg^.Files^[i].UPD, Cfg^.UpdateDir + Cfg^.Files^[i].UPD) then
1057 Begin
1058 LogSetCurLevel(lh, 1);
1059 LogWriteLn(lh, 'Could not move "'+Cfg^.MailDir + Cfg^.Files^[i].UPD+'"');
1060 LogWriteLn(lh, 'to "'+Cfg^.UpdateDir + Cfg^.Files^[i].UPD+'"!');
1061 End;
1062 End
1063 Else
1064 Begin
1065 If FileExist(Cfg^.BadDir + Cfg^.Files^[i].UPD) then DelFile(Cfg^.BadDir + Cfg^.Files^[i].UPD);
1066 If not MoveFile(Cfg^.MailDir + Cfg^.Files^[i].UPD, Cfg^.BadDir + Cfg^.Files^[i].UPD) then
1067 Begin
1068 LogSetCurLevel(lh, 1);
1069 LogWriteLn(lh, 'Could not move "'+Cfg^.MailDir + Cfg^.Files^[i].UPD+'"');
1070 LogWriteLn(lh, 'to "'+Cfg^.BadDir + Cfg^.Files^[i].UPD+'"!');
1071 End
1072 End;
1073 End;
1074 End;
1075 End;
1076
1077 Procedure DoBatch(UPDName: String; DayNum: Word);
1078 Var
1079 f: Text;
1080 d: DirStr;
1081 n: NameStr;
1082 s, s1: String;
1083 PrevDayNum: Word;
1084 DT: TimeTyp;
1085 DTUnx: ULong;
1086
1087 Begin
1088 Assign(f, Cfg^.CreateBatch);
1089 {$I-} ReWrite(f); {$I+}
1090 If (IOResult <> 0) then
1091 Begin
1092 LogSetCurLevel(lh, 1);
1093 LogWriteLn(lh, 'Could not open "'+Cfg^.CreateBatch+'"!');
1094 Exit;
1095 End;
1096
1097 FSplit(UPDName, d, n, s);
1098 Today(DT); Now(DT);
1099 DTUnx := DTToUnixDate(DT);
1100 DTUnx := DTUnx - 7*24*60*60;
1101 UnixToDT(DTUnx, DT);
1102 PrevDayNum := DayOfYear(DT);
1103 s1 := d+n + ' no-diff ' + IntToStr(DayNum div 100) + ' ' + IntToStr((DayNum div 10) mod 10) +
1104 ' ' + IntToStr(DayNum mod 10) + ' ' + IntToStr(PrevDayNum div 100) + ' ' +
1105 IntToStr((PrevDayNum div 10) mod 10) + ' ' + IntToStr(PrevDayNum mod 10);
1106 WriteLn(f, Cfg^.CallBatch + ' ' + s1);
1107
1108 {$I-} Close(f); {$I+}
1109 If (IOResult <> 0) then
1110 Begin
1111 LogSetCurLevel(lh, 1);
1112 LogWriteLn(lh, 'Could not close "'+Cfg^.CreateBatch+'"!');
1113 End;
1114 {$IfDef UNIX}
1115 ChMod(Cfg^.CreateBatch, 493); {Octal 755}
1116 {$EndIf}
1117 LogSetCurLevel(lh, 3);
1118 LogWriteLn(lh, 'created batch '+Cfg^.CreateBatch);
1119 End;
1120
1121 Procedure CreateUPD;
1122 Var
1123 f, f1: Text;
1124 i: Byte;
1125 DT: TimeTyp;
1126 s: String;
1127 fn: FileStr;
1128 fn2: PathStr;
1129 CRC: Word;
1130
1131 Procedure CopyFile(fname: String; IsCpy: Boolean; SkipComments: Boolean);
1132 Var
1133 ftc: Text;
1134 p: Byte;
1135
1136 Begin
1137 Assign(ftc, fname);
1138 {$I-} ReSet(ftc); {$I+}
1139 If (IOResult <> 0) then
1140 Begin
1141 LogSetCurLevel(lh, 1);
1142 LogWriteLn(lh, 'Could not open "'+fname+'"!');
1143 End
1144 Else
1145 Begin
1146 While not EOF(ftc) do
1147 Begin
1148 ReadLn(ftc, s);
1149 While ((s[Byte(s[0])] = #13) or (s[Byte(s[0])] = #10)) do
1150 s[0] := Char(Byte(s[0])-1);
1151 If (s = '') then Continue;
1152 If (s[1] = #26) then Continue; {skip EOF}
1153 If ((s[1] = ';') and SkipComments) then Continue;
1154 If IsCpy then If (Pos('####', s) > 0) then
1155 Begin
1156 p := Pos('####', s);
1157 Delete(s, p, 4);
1158 Insert(IntToStr(DT.Year), s, p);
1159 End;
1160 Write(f, s, #13#10);
1161 End;
1162 {$I-} Close(ftc); {$I+}
1163 If (IOResult <> 0) then
1164 Begin
1165 LogSetCurLevel(lh, 1);
1166 LogWriteLn(lh, 'Could not close "'+fname+'"!');
1167 End
1168 End;
1169 End;
1170
1171 Begin
1172 Today(DT); Now(DT);
1173 If (DT.Year < 38) then DT.Year := DT.Year + 2000
1174 Else If (DT.Year < 1900) then DT.Year := DT.Year + 1900;
1175 Write('Day #'+IntToStr(DayOfYear(DT)), #13#10);
1176 FSplit(Cfg^.OutFile, s, fn, s);
1177 Assign(f, Cfg^.OutPath+fn+'.tmp');
1178 {$I-} ReWrite(f); {$I+}
1179 If (IOResult <> 0) then
1180 Begin
1181 LogSetCurLevel(lh, 1);
1182 LogWriteLn(lh, 'Could not open "'+Cfg^.OutPath+fn+'.tmp"!');
1183 Exit;
1184 End;
1185
1186 If (Cfg^.NLType = cTcomposite) then
1187 Begin
1188 {copy copyright}
1189 If (Cfg^.CopyRight <> '') then CopyFile(Cfg^.CopyRight, True, False);
1190 {copy prolog}
1191 If (Cfg^.ProLog <> '') then CopyFile(Cfg^.ProLog, False, False);
1192 End;
1193
1194 {copy DATA-lines from config}
1195 If (Cfg^.NumData > 0) then For i := 1 to Cfg^.NumData do
1196 Begin
1197 Write(f, Cfg^.Data^[i], #13#10);
1198 End;
1199 Write(f, ';A', #13#10);
1200
1201 {copy FILES}
1202 If (Cfg^.NumFiles > 0) then For i := 1 to Cfg^.NumFiles do
1203 Begin
1204 if (pos(dirSep, cfg^.files^[i].upd) > 0) then
1205 Begin
1206 If FileExist(Cfg^.Files^[i].UPD) then
1207 Begin
1208 CopyFile(Cfg^.Files^[i].UPD, False, Cfg^.Files^[i].SkipComments);
1209 Write(f, ';A', #13#10);
1210 End;
1211 End
1212 Else
1213 Begin
1214 If FileExist(Cfg^.UpdateDir+Cfg^.Files^[i].UPD) then
1215 Begin
1216 CopyFile(Cfg^.UpdateDir+Cfg^.Files^[i].UPD, False, Cfg^.Files^[i].SkipComments);
1217 Write(f, ';A', #13#10);
1218 End;
1219 End;
1220 End;
1221
1222 If (Cfg^.NLType = cTcomposite) then
1223 Begin
1224 {copy epilog}
1225 If (Cfg^.EpiLog <> '') then CopyFile(Cfg^.Epilog, False, False);
1226 End;
1227
1228 {$I-} Close(f); {$I+}
1229 If (IOResult <> 0) then
1230 Begin
1231 LogSetCurLevel(lh, 1);
1232 LogWriteLn(lh, 'Could not close "'+Cfg^.OutPath+fn+'.tmp"!');
1233 End;
1234
1235 {calc CRC}
1236 CRC := GetCRC16(Cfg^.OutPath+fn+'.tmp');
1237
1238 {copy temp file to final file}
1239 If (Pos('.', Cfg^.OutFile) > 0) then fn2 := Cfg^.OutPath + Cfg^.OutFile
1240 Else fn2 := Cfg^.OutPath + Cfg^.OutFile + '.' + IntToStr03(DayOfYear(DT));
1241 Assign(f1, fn2);
1242 {$I-} ReWrite(f1); {$I+}
1243 If (IOResult <> 0) then
1244 Begin
1245 LogSetCurLevel(lh, 1);
1246 LogWriteLn(lh, 'Could not open "'+fn2+'"!');
1247 Exit;
1248 End;
1249 {$I-} ReSet(f); {$I+}
1250 If (IOResult <> 0) then
1251 Begin
1252 LogSetCurLevel(lh, 1);
1253 LogWriteLn(lh, 'Could not open "'+Cfg^.OutPath+fn+'.tmp"!');
1254 Exit;
1255 End;
1256
1257 {add copyright}
1258 If (Cfg^.NLType = cTcomposite) then
1259 Begin
1260 Write(f1, ';A '+Cfg^.NetName + ' Nodelist for '+WkDaysEng[DT.DayOfWeek]+', '+
1261 MonthsEng[DT.Month]+' '+IntToStr(DT.Day)+', '+IntToStr(DT.Year)+
1262 ' -- Day number '+IntToStr(DayOfYear(DT))+' : ' + IntToStr(CRC),
1263 #13#10);
1264 End;
1265
1266 While not EOF(f) do
1267 Begin
1268 ReadLn(f, s);
1269 While ((s[Byte(s[0])] = #13) or (s[Byte(s[0])] = #10)) do
1270 s[0] := Char(Byte(s[0])-1);
1271 If (s = '') then Continue;
1272 If (s[1] = #26) then Continue;
1273 Write(f1, s, #13#10);
1274 End;
1275
1276 {$I-} Close(f1); {$I+}
1277 If (IOResult <> 0) then
1278 Begin
1279 LogSetCurLevel(lh, 1);
1280 LogWriteLn(lh, 'Could not close "'+fn2+'"!');
1281 End;
1282 {$I-} Close(f); {$I+}
1283 If (IOResult <> 0) then
1284 Begin
1285 LogSetCurLevel(lh, 1);
1286 LogWriteLn(lh, 'Could not close "'+Cfg^.OutPath+fn+'.tmp"!');
1287 End;
1288 {$I-} Erase(f); {$I+}
1289 If (IOResult <> 0) then
1290 Begin
1291 LogSetCurLevel(lh, 1);
1292 LogWriteLn(lh, 'Could not delete "'+Cfg^.OutPath+fn+'.tmp"!');
1293 End;
1294 LogSetCurLevel(lh, 4);
1295 LogWriteLn(lh, 'created UPD '+fn2);
1296 If (Cfg^.Submit and cYes) > 0 then SubmitUPD(fn2);
1297 If (Cfg^.CreateBatch <> '') and (Cfg^.CallBatch <> '') then DoBatch(fn2, DayOfYear(DT));
1298 End;
1299
1300 Procedure Run;
1301 Begin
1302 LookForUPDs;
1303 If DoProcess then CreateUPD;
1304 End;
1305
1306
1307 Begin
1308 Init;
1309 Run;
1310 Done;
1311 End.
1312
1313