1 
2 %{
3 
4 /*
5  *  RNtrack - FTN message tracker/router
6  *
7  *  cfg.(y|hpp|cpp) - Config file parser
8  *
9  *  Copyright (c) 2003-2005 Alex Soukhotine, 2:5030/1157
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  $Id: cfg.y,v 1.6 2005/06/22 22:18:14 ph0enix Exp $
17  */
18 
19 #define YYDEBUG 0
20 /* #define YYERROR_VERBOSE */
21 #ifdef HAVE_CONFIG_H
22 # include "aconfig.h"
23 #endif
24 
25 #include <stdlib.h>
26 #ifdef HAVE_MALLOC_H
27    #include <malloc.h>
28 #endif
29 #include "msg.hpp"
30 #include "outbound.hpp"
31 #include "fidoaddr.hpp"
32 #include "vars.hpp"
33 #include "configure.hpp"
34 #include "constant.hpp"
35 #include "log.hpp"
36 #include "aka.hpp"
37 #include "age.hpp"
38 #include "scandir.hpp"
39 #include "attach.hpp"
40 #include "badpkt.hpp"
41 #include "badmsg.hpp"
42 #include "domain.hpp"
43 #include "filebox.hpp"
44 #include "passwd.hpp"
45 #include "nodelist.hpp"
46 #include "script.hpp"
47 
48 #undef YYSTYPE               /* Perl also uses bison? damn! */
49 
50 extern int DetectError;
51 extern bool NoTokensF;
52 
53 extern FA   cffa;
54 extern FA   cffa1;
55 extern FA   cffa2;
56 
57 static int brf = FALSE, arf = FALSE, renumberf = FALSE, unpackf = FALSE, freshf = FALSE;
58 static ScanDir *wsd = NULL;
59 static char *FileName = NULL;
60 static char *BPktDir = NULL;
61 static char *ScriptBefore = NULL;
62 static char *ScriptAfter = NULL;
63 static tTimes *tt;
64 static IndBiList<tTimes> *_TTimes;
65 static MSGBASE *mbase;
66 static Mask *msk = NULL;
67 static int MaskMode;
68 static int rc;
69 static int FlagMode = 0;
70 static Action *act = NULL;
71 
CheckETTime(void)72 static void CheckETTime(void) {
73 time_t tmt;
74    if (tt->_ETime != 0 && tt->_ETime < tt->_STime) {
75       tmt = tt->_ETime;
76       tt->_ETime = (23*60*60)+(59*60)+59;
77       tt->_ETime += TimeOfBeginOfDay(-1);
78       _TTimes->AddToEnd(tt);
79       tt = new tTimes;
80       tt->_STime = TimeOfBeginOfDay(-1);
81       tt->_ETime = tmt;
82    }
83 }
84 
PrepareMask(Mask & m)85 static int PrepareMask(Mask &m) {
86 ScanDir *sd;
87 char ErrMess[128];
88 
89    CHP = 23700;
90    sd = ScanDirs.GetLast();
91    if (sd == NULL) {
92       strcpy(ErrMess,"'");
93       strcat(ErrMess,m.MaskName());
94       strcat(ErrMess,":' without 'ScanDir:'");
95       yyerror(ErrMess);
96       return -1;
97    }
98    m.sd = sd;
99    return 0;
100 }
101 
AddReadyMask(Mask & m)102 static void AddReadyMask(Mask &m) {
103 ScanDir *sd;
104 
105    switch (PrevMask) {
106       case 0: // first mask.
107       case 1: // after action.
108          LastDo = new DoList();
109          sd = ScanDirs.GetLast();
110          sd->_DoLists.AddToEnd(LastDo);
111          PrevMask = 2;
112          break;
113       case 2: // after MASK.
114          break;
115    }
116    LastDo->AddMask(m);
117 }
118 
119 
CheckMaskMode(char * f)120 static int CheckMaskMode(char *f) {
121 char Buff[128];
122    if (MaskMode != 0) {
123       strcpy(Buff,"You can use '");
124       strcat(Buff,f);
125       strcat(Buff,"' flag only in 'Mask:'.");
126       yyerror(Buff);
127       return -1;
128    }
129    return 0;
130 }
131 
132 
ctoi(char * s)133 static int ctoi(char *s) {
134    char *foo;
135    int res = 0;
136 
137    res = strtoul(s, &foo, 0);
138    if (*foo)    /* parse error */
139       return 0;
140    return res;
141 }
142 
143 
144 
145 %}
146 
147 %union {
148    int          in;
149    char         *ch;
150    long         ln;
151    KillModeT    kmode;
152    CheckPointsT pmode;
153    tBadMsgMode  bmode;
154    tBadMsgMode  bpmode;
155    fileboxType  fbtype;
156    time_t       t;
157    PKTMode      pktmode;
158 };
159 
160 
161 
162 %token _LOGFILE            _LOGLEVEL    _NODELIST    _INDEXFILE    _NODELISTPATH
163        _ADDRESS            _SYSOPNAME   _USEOWNZONE  _FORCEINTL    _LOOPSTR
164        _SCANDIR            _MASK        _SMASK       _PMASK        _BODYMASK
165        _SBODYMASK          _PBODYMASK   _KLUDGEMASK  _SKLUDGEMASK  _PKLUDGEMASK
166        _ACTION             _MAXAGE      _BADMESSAGES _NOLOGIGNORE  _AKA
167        _SKIPHIDDENFILES    _FILEINBOUND _OUTBOUND    _ADDTONULLPKT _TEMPMAIL
168        _TRAFFICLOG         _PASSWORD    _UTC         _ORIGIN       _TEARLINE
169        _INCLUDE            _APKTDIR     _CHECKPOINTS _SETVIAALWAYS _FRESH
170        _CREATEMISSINGBASE  _USENEWVIA   _SCRIPTMASK  _SSCRIPTMASK  _PSCRIPTMASK
171        _MAXATTACHSIZE      _SEMAPHORE   _SCRIPTFILE  _USEASO _USEBRAKE _FILEBOXDIR
172        _KILLROUTEDMESSAGE  _IGNOREBSY   _AFTERSCRIPT _BEFORESCRIPT _AGEFROMVIA
173        _MAXNODELISTAGE _USEFILEBOXES _FILEBOXTYPE _LONG _TMLONG _TMSHORT _BRAKE
174        _SOFTCHECKINNODELIST _BADPACKETS _IGNOREATTACHPATH _MAXPKTSIZE _MAXMSGSIZE
175        _TIMESTAMPFILE _DOMAIN_ _FILEBOX
176        _TRAFFICLOGTEMPLATE
177          _STRIPPATHINPKT
178 
179        _CRLF        _SKIP _DELETE _EXIT _MOVE __EOF
180        _STRING      _BEFOREROUTE _AFTERROUTE
181        _DIGIT_
182        _RENUMBER    _UNPACK _DAILY _WEEKLY _FLAG
183        _NEVER _HARD _SOFT _ALWAYS
184 /* Actions */
185        _ADDNOTE _COPY  _REWRITE _IGNORE _DISPLAY _DELFILE _NEWMSG _WRITEFILE
186        _APPENDTOFILE _CALL _ROUTE _ROUTEFBOX _ROUTEHUB _POLL _DELETEATTACH _CHANGEPATH _MOVEATTACH
187        _ASCRIPT _TOLOWERPATH _TOUPPERPATH _COPYATTACHFBOX _MOVEATTACHFBOX
188        _COPYATTACH _SPLIT _RECODE _ADDKLUDGE _HOLD _CRASH _DIRECT _NORMAL _IMMEDIATE
189     LEXERR
190 
191 %start  Conf
192 
193 %%
194 
195 Conf     :   /* empty */
196          |   Conf ConfLine
197          ;
198 
199 
200 ConfLine :  Action _CRLF
201          |  IncludeF _CRLF {
202             if (SetInclude($<ch>1) != 0) {
203                YYABORT;
204             }
205          }
206          |  TimeStampFile _CRLF
207          |  Address _CRLF
208          |  _ADDTONULLPKT _CRLF
209             {
210                if (SetAddToNullPkt() != 0) {
211                   YYABORT;
212                }
213             }
214          |  Aka _CRLF
215          |  APktDir _CRLF
216          |  BodyMask _CRLF
217          |  SBodyMask _CRLF
218          |  PBodyMask _CRLF
219          |  CheckPoints _CRLF
220          |  _CREATEMISSINGBASE _CRLF
221             {
222                if (SetCreateMissingBase() != 0) {
223                   YYABORT;
224                }
225             }
226          |  FileInbound _CRLF
227          |  _FORCEINTL  _CRLF
228             {
229                if (SetForceINTL() != 0) {
230                   YYABORT;
231                }
232             }
233          |  Origin _CRLF
234          |  IndexFile _CRLF
235          |  KillRoutedMessage _CRLF
236          |  KludgeMask _CRLF
237          |  SKludgeMask _CRLF
238          |  PKludgeMask _CRLF
239          |  LogFile _CRLF
240          |  LogLevel _CRLF
241          |  LoopStr _CRLF
242          |  Mask _CRLF
243          |  SMask _CRLF
244          |  PMask _CRLF
245          |  MaxAge _CRLF
246          |  MaxAttachSize _CRLF
247      |  MaxMsgSize _CRLF
248      |  MaxPktSize _CRLF
249          |  MaxNodelistAge _CRLF
250          |  Nodelist _CRLF
251          |  NodelistPath _CRLF
252          |  _NOLOGIGNORE _CRLF
253             {
254                if (SetNoLogIgnore() != 0) {
255                   YYABORT;
256                }
257             }
258          |  Outbound _CRLF
259          |  Password _CRLF
260      |  Domain _CRLF
261      |  FileBox _CRLF
262          |  ScriptMask _CRLF
263          |  SScriptMask _CRLF
264          |  PScriptMask _CRLF
265          |  _IGNOREBSY _CRLF
266             {
267                if (SetIgnoreBSY() != 0) {
268                   YYABORT;
269                }
270             }
271          |  _IGNOREATTACHPATH _CRLF
272             {
273                if (SetIgnoreAttachPath() != 0) {
274                   YYABORT;
275                }
276             }
277          |  _SETVIAALWAYS _CRLF
278             {
279                if (SetSetViaAlways() != 0) {
280                   YYABORT;
281                }
282             }
283          |  _SKIPHIDDENFILES _CRLF
284             {
285                if (SetSkipHiddenFiles() != 0) {
286                   YYABORT;
287                }
288             }
289          |  _SOFTCHECKINNODELIST _CRLF
290             {
291                if (SetSoftCheckInNodelists() != 0) {
292                   YYABORT;
293                }
294             }
295          |  SysopName _CRLF
296          |  TearLine _CRLF
297          |  _USENEWVIA _CRLF
298             {
299                if (SetNewVia() != 0) {
300                   YYABORT;
301                }
302             }
303          |  _USEOWNZONE _CRLF
304             {
305                if (SetUseOwnZone() != 0) {
306                   YYABORT;
307                }
308             }
309          |  _USEASO _CRLF
310              {
311                 if (SetUseASO() != 0) {
312                   YYABORT;
313                 }
314              }
315      | _USEBRAKE _CRLF
316              {
317             if (SetUseBrake() != 0) {
318           YYABORT;
319             }
320          }
321      |  _USEFILEBOXES _CRLF
322              {
323                 if (SetUseFileBoxes() != 0) {
324                   YYABORT;
325                 }
326              }
327          | _STRIPPATHINPKT _CRLF
328                {
329                    if (SetStripPathInPkt() != 0) {
330                        YYABORT;
331                }
332             }
333          |  _AGEFROMVIA _CRLF
334             {
335                if (SetAgeFromVia() != 0) {
336                   YYABORT;
337                }
338             }
339          |  Utc _CRLF
340          |  TempMail _CRLF
341          |  TrafficLog _CRLF
342          |  BadMessages _CRLF
343          |  BadPackets _CRLF
344          |  ScanDir _CRLF
345          |  Semaphore _CRLF
346          |  TrafficLogTemplate _CRLF
347          |  ScriptFile _CRLF
348      |  FileBoxDir _CRLF
349      |  FileBoxType _CRLF
350          |   error _CRLF { YYABORT; }
351          { DetectError = TRUE;
352          }
353          | _CRLF
354          {
355             avail = 0;
356          }
357          ;
358 
359 ScriptFile : _SCRIPTFILE _STRING {
360                if (LoadScriptFile($<ch>2) != 0) {
361                   YYABORT;
362                }
363              }
364            ;
365 
366 FileBoxDir : _FILEBOXDIR _STRING {
367                if (SetFileBoxDir($<ch>2) != 0) {
368                   YYABORT;
369                }
370              }
371            ;
372 
373 FileBoxType: _FILEBOXTYPE FBOXTYPE
374               {
375                 if (SetFileBoxType($<fbtype>2) != 0) {
376           YYABORT;
377                 }
378               }
379             ;
380 FBOXTYPE  : _LONG { $<fbtype>$ = FILEBOXLONG}
381             | _TMLONG { $<fbtype>$ = FILEBOXTMLONG }
382             | _TMSHORT { $<fbtype>$ = FILEBOXTMSHORT }
383         | _BRAKE { $<fbtype>$ = FILEBOXBRAKE }
384             ;
385 
386 
387 TrafficLogTemplate : _TRAFFICLOGTEMPLATE _STRING {
388                       if (SetTrafficLogTemplate($<ch>2) != 0) {
389                          YYABORT;
390                       }
391                    }
392                    ;
393 
394 Semaphore : _SEMAPHORE _DIGIT_ _STRING {
395              if (SetSemaphoreName($<ch>3, $<ln>2) != 0) {
396                 YYABORT;
397              }
398           }
399           ;
400 
401 
402 IncludeF : _INCLUDE _STRING { $<ch>$ = $<ch>2; }
403          ;
404 
405 Aka      : _AKA { cffa.Clean(); } faddress { cffa1 = cffa; cffa.Clean(); } faddress
406             {
407                if (SetAka(cffa1, cffa) != 0) {
408                   YYABORT;
409                }
410                cffa.Clean();
411                cffa1.Clean();
412             }
413          ;
414 
415 TimeStampFile : _TIMESTAMPFILE _STRING
416             {
417                if (SetTimeStampFile($<ch>2) != 0) {
418                   YYABORT;
419                }
420             }
421               ;
422 
423 APktDir  : _APKTDIR _STRING
424             {
425                if (SetAPktDir($<ch>2) != 0) {
426                   YYABORT;
427                }
428             }
429          ;
430 
431 Address  : _ADDRESS { cffa.Clean(); } faddress
432             {
433                if (SetMyAddr(cffa) != 0) {
434                   YYABORT;
435                }
436                cffa.Clean();
437             }
438          ;
439 
440 CheckPoints : _CHECKPOINTS ChkPntMode { SetCheckPoints($<pmode>2); }
441             ;
442 
443 ChkPntMode  : _NEVER { $<pmode>$ = CHECKPNT_NEVER; }
444             | _HARD  { $<pmode>$ = CHECKPNT_HARD; }
445             | _SOFT  { $<pmode>$ = CHECKPNT_SOFT; }
446             ;
447 
448 KillRoutedMessage : _KILLROUTEDMESSAGE KillRMode { SetKillRoutedMessages($<kmode>2); }
449                   ;
450 
451 KillRMode         : _ALWAYS { $<kmode>$ = KILL_ALWAYS; }
452                   | _NEVER  { $<kmode>$ = KILL_NEVER; }
453                   | _FLAG   { $<kmode>$ = KILL_FLAG; }
454                   ;
455 
456 SysopName: _SYSOPNAME _STRING
457             {
458                if (SetSysopName($<ch>2) != 0) {
459                   YYABORT;
460                }
461             }
462          ;
463 
464 TearLine : _TEARLINE _STRING
465             {
466                if (SetTearline($<ch>2) != 0) {
467                   YYABORT;
468                }
469             }
470          ;
471 
472 LogFile  : _LOGFILE _STRING
473             {
474                if (SetLogFile($<ch>2) != 0) {
475                   YYABORT;
476                }
477             }
478          ;
479 
480 LogLevel : _LOGLEVEL _DIGIT_
481             {
482                if (SetLogLevel($<ln>2) != 0) {
483                   YYABORT;
484                }
485             }
486          ;
487 
488 Origin   : _ORIGIN _STRING
489             {
490                if (SetOrigin($<ch>2) != 0) {
491                   YYABORT;
492                }
493             }
494          ;
495 
496 Nodelist : _NODELIST _STRING NdlZone
497             {
498                if (SetNodelist($<ch>2,$<ln>3) != 0) {
499                   YYABORT;
500                }
501             }
502          ;
503 
504 NdlZone  : { $<ln>$ = -3; }
505          | _DIGIT_  { $<ln>$ = $<ln>1; }
506          ;
507 
508 NodelistPath : _NODELISTPATH _STRING
509             {
510                if (SetNodelistPath($<ch>2) != 0) {
511                   YYABORT;
512                }
513             }
514              ;
515 
516 IndexFile: _INDEXFILE _STRING
517             {
518                if (SetIndexFile($<ch>2) != 0) {
519                   YYABORT;
520                }
521             }
522          ;
523 
524 LoopStr  : _LOOPSTR _STRING
525             {
526                if (SetLoopStr($<ch>2) != 0) {
527                   YYABORT;
528                }
529             }
530          ;
531 
532 MaxAttachSize : _MAXATTACHSIZE _DIGIT_
533             {
534                if (SetMaxAttach($<ln>2) != 0) {
535                   YYABORT;
536                }
537             }
538               ;
539 
540 MaxNodelistAge : _MAXNODELISTAGE _DIGIT_
541             {
542                if (SetMaxNodelistAge($<ln>2) != 0) {
543                   YYABORT;
544                }
545             }
546                ;
547 
548 Outbound : _OUTBOUND _STRING
549             {
550                if (SetOutbound($<ch>2) != 0) {
551                   YYABORT;
552                }
553             }
554          ;
555 
556 TempMail : _TEMPMAIL _STRING
557             {
558                if (SetTempMail($<ch>2) != 0) {
559                   YYABORT;
560                }
561             }
562          ;
563 
564 TrafficLog : _TRAFFICLOG _STRING
565             {
566                if (SetTrafficLog($<ch>2) != 0) {
567                   YYABORT;
568                }
569             }
570            ;
571 
572 FileInbound : _FILEINBOUND _STRING
573             {
574                if (SetFileInbound($<ch>2) != 0) {
575                   YYABORT;
576                }
577             }
578             ;
579 
580 MaxAge      : _MAXAGE _DIGIT_
581             {
582                if (SetMaxAge($<ln>2) != 0) {
583                   YYABORT;
584                }
585                cffa.Clean();
586             }
587             ;
588 
589 MaxMsgSize   : _MAXMSGSIZE _DIGIT_
590             {
591                if (SetMaxMsgSize($<ln>2) != 0) {
592                   YYABORT;
593                }
594                cffa.Clean();
595             }
596             ;
597 
598 MaxPktSize   : _MAXPKTSIZE _DIGIT_
599             {
600                if (SetMaxPktSize($<ln>2) != 0) {
601                   YYABORT;
602                }
603                cffa.Clean();
604             }
605             ;
606 
607 Password    : _PASSWORD _STRING
608             {
609                if (strlen($<ch>2) > 8){
610                   yyerror("Password too long. Max password length is a 8 characters.");
611                   YYABORT;
612                }
613                cffa.Clean();
614             }
615               faddress
616             {
617                if (SetPasswd(cffa, $<ch>2) != 0) {
618                   YYABORT;
619                }
620                cffa.Clean();
621             }
622             ;
623 
624 Domain    : _DOMAIN_ _STRING
625             {
626                if (strlen($<ch>2) > 10){
627                   yyerror("Domain too long. Max domain length is a 10 characters.");
628                   YYABORT;
629                }
630                cffa.Clean();
631             }
632               faddress
633             {
634                if (SetDomain(cffa, $<ch>2) != 0) {
635                   YYABORT;
636                }
637                cffa.Clean();
638             }
639             ;
640 
641 FileBox    : _FILEBOX _STRING
642             {
643                if (strlen($<ch>2) > 100){
644                   yyerror("Path too long. Max path length is a 100 characters.");
645                   YYABORT;
646                }
647                cffa.Clean();
648             }
649               faddress
650             {
651                if (SetFilebox(cffa, $<ch>2) != 0) {
652                   YYABORT;
653                }
654                cffa.Clean();
655             }
656             ;
657 
658 
659 BadMessages : _BADMESSAGES BadMsgMode
660               {
661                 if (SetBadMode($<bmode>2,FileName) != 0) {
662                   YYABORT;
663                 }
664                 FileName = NULL;
665               }
666             ;
667 BadMsgMode  : _SKIP { $<bmode>$ = SKIP; FileName = NULL;}
668             | _EXIT { $<bmode>$ = EXIT; FileName = NULL;}
669             | _DELETE { $<bmode>$ = REMOVE; FileName = NULL;}
670             | _MOVE _STRING { $<bmode>$ = MOVE; FileName = $<ch>2;}
671             ;
672 
673 BadPackets  : _BADPACKETS BadPktMode
674               {
675                 if (SetBadPktMode($<bpmode>2,BPktDir) != 0) {
676                   YYABORT;
677                 }
678         BPktDir = NULL;
679               }
680             ;
681 BadPktMode  : _SKIP { $<bpmode>$ = SKIP; BPktDir = NULL;}
682             | _EXIT { $<bpmode>$ = EXIT; BPktDir = NULL;}
683             | _DELETE { $<bpmode>$ = REMOVE; BPktDir = NULL;}
684             | _MOVE _STRING { $<bpmode>$ = MOVE; BPktDir = $<ch>2;}
685             ;
686 
687 Utc         : _UTC UtcOffs
688               {
689                 if (SetUTC($<ln>2) != 0) {
690                   YYABORT;
691                 }
692               }
693             ;
694 
695 UtcOffs     : _DIGIT_ { $<ln>$ = $<ln>1; }
696             | '+' _DIGIT_ { $<ln>$ = $<ln>2; }
697             | '-' _DIGIT_ { $<ln>$ = -$<ln>2; }
698             ;
699 
700 /* ScanDir --------- */
701 
702 ScanDir  : _SCANDIR
703            {
704               wsd = new ScanDir();
705               CheckMem((char *)wsd);
706               renumberf = FALSE;
707               unpackf = FALSE;
708               freshf = FALSE;
709               arf = FALSE;
710               brf = FALSE;
711               _TTimes = &wsd->_Times;
712               mbase = NULL;
713               PrevMask = 0;
714               ScriptBefore = NULL;
715               ScriptAfter = NULL;
716               FileName = NULL;
717            }
718            SDType
719            {
720               wsd->SetBase(mbase);
721               wsd->_Renumber = renumberf;
722               wsd->_Unpack = unpackf;
723               wsd->_Fresh = freshf;
724               wsd->_FlagFile = FileName;
725               wsd->_ScriptBefore = ScriptBefore;
726               wsd->_ScriptAfter = ScriptAfter;
727               ScanDirs.AddToEnd(wsd);
728               if (brf) BeforeRoute = wsd;
729               if (arf) AfterRoute = wsd;
730            }
731          ;
732 
733 SDType  : BeforeAfter Flag
734         | _STRING
735           {
736              mbase = MakeBase($<ch>1);
737              if (mbase == NULL) {
738                 YYABORT;
739              }
740              if (!mbase->Set($<ch>1,BASE_IN)) {
741                 delete mbase;
742                 mbase = NULL;
743                 yyerror("Unable to open message base.");
744                 YYABORT;
745              }
746              if (!mbase->CheckIn()) {
747                 delete mbase;
748                 YYABORT;
749              }
750           }
751           AddSdParam Flag
752         ;
753 
754 BeforeAfter : _BEFOREROUTE { brf = TRUE; }
755             | _AFTERROUTE { arf = TRUE; }
756             ;
757 
758 AddSdParam  :
759             | AddSdParam SdParam
760             ;
761 
762 SdParam     : _RENUMBER
763                {
764                   if (renumberf == TRUE) {
765                      yyerror("Renumber for this base already set.");
766                      YYABORT;
767                   } else {
768                     renumberf = TRUE;
769                   }
770                }
771             | _BEFORESCRIPT _STRING
772                {
773                   if (!ScriptWordExists($<ch>2)) {
774                      yyerror("Script function not found.");
775                      YYABORT;
776                   }
777                   ScriptBefore = strdup($<ch>2);
778                }
779             | _AFTERSCRIPT  _STRING
780                {
781                   if (!ScriptWordExists($<ch>2)) {
782                      yyerror("Script function not found.");
783                      YYABORT;
784                   }
785                   ScriptAfter = strdup($<ch>2);
786                }
787             | _FRESH
788                {
789                   if (freshf == TRUE) {
790                      yyerror("Fresh scripts for this base already set.");
791                      YYABORT;
792                   } else {
793                      freshf = TRUE;
794                   }
795                }
796             | _UNPACK
797                {
798                   if (unpackf == TRUE) {
799                      yyerror("Unpack for this base already set.");
800                      YYABORT;
801                   } else {
802                      unpackf = TRUE;
803                   }
804                   if (Outbound == NULL) {
805                      yyerror("Outbound directory not specified.");
806                      YYABORT;
807                   }
808                }
809             | STime
810                {
811                   if (TimeStampFile == NULL) {
812                      yyerror("You can't set scanning time without Timestamp File.");
813                      YYABORT;
814                   }
815 
816                }
817             ;
818 
819 STime       : _DAILY
820                {
821                   tt = new tTimes;
822                   tt->_STime = TimeOfBeginOfDay(-1);
823                   tt->_ETime = 0;
824                }
825               DaySTime
826                {
827                   if (tt->_STime != 0) {
828                      CheckETTime();
829                      _TTimes->AddToEnd(tt);
830                   }
831                }
832             | _WEEKLY
833                {
834                   tt = new tTimes;
835                   tt->_STime = TimeOfBeginOfDay(0);
836                   tt->_ETime = 0;
837                }
838               WeekSTime
839                {
840                   if (tt->_STime != 0) {
841                      CheckETTime();
842                      _TTimes->AddToEnd(tt);
843                   }
844                }
845             ;
846 
847 DaySTime    :
848             | DaySTime DaySSTime
849                {
850                   if (tt->_STime != 0) {
851                      CheckETTime();
852                      _TTimes->AddToEnd(tt);
853                      tt = new tTimes;
854                   }
855                }
856             ;
857 
858 DaySSTime   : Time
859                {
860                   tt->_STime = $<t>1 + TimeOfBeginOfDay(-1);
861                }
862             | Time '-' Time
863                {
864                   tt->_STime = $<t>1 + TimeOfBeginOfDay(-1);
865                   tt->_ETime = $<t>3 + TimeOfBeginOfDay(-1) + 59;
866                }
867             | AnyP '.' Time {
868                   time_t i_time;
869                   time_t b_time;
870                   if ($<t>3 == (time_t) 0) {
871                      yyerror("Time of pereodical event should be between 00:01 and 23:59");
872                      YYABORT;
873                   }
874                   tt->_STime = TimeOfBeginOfDay(-1);
875                   b_time = tt->_STime;
876                   do {
877                      i_time = tt->_STime;
878                      CheckETTime();
879                      _TTimes->AddToEnd(tt);
880                      tt = new tTimes;
881                      tt->_ETime = 0;
882                      tt->_STime = i_time + $<t>3;
883                   } while (tt->_STime < (b_time + (23*60*60)+(59*60)+60));
884                   tt->_STime = 0;
885             }
886             ;
887 
888 AnyP        : 'p'
889             | 'P'
890             ;
891 
892 Time        : _DIGIT_
893               {
894                  if ($<ln>1 < 0 || $<ln>1 > 23) {
895                     yyerror("Hour should be between 00 and 23");
896                     YYABORT;
897                  } else {
898                     $<t>$ = (time_t) ($<ln>1 * 60);
899                  }
900               }
901               ':' _DIGIT_
902               {
903                  if ($<ln>4 < 0 || $<ln>4 > 59 || $<t>2 == (time_t) -1) {
904                     $<t>$ = (time_t)-1;
905                     yyerror("Minutes should be between 00 and 59");
906                     YYABORT;
907                  } else {
908                     $<t>$ = $<t>2 + (time_t) $<ln>4;
909                     $<t>$ *= 60;
910                  }
911               }
912             ;
913 
914 WeekSTime   :
915             | WeekSTime WeekSSTime
916                {
917                   CheckETTime();
918                   _TTimes->AddToEnd(tt);
919                   tt = new tTimes;
920                }
921             ;
922 
923 WeekSSTime  : _DIGIT_
924               {
925                  if ($<ln>1 < 0 || $<ln>1 > 6) {
926                     yyerror("Day of week should be between 0 and 6");
927                     YYABORT;
928                  } else {
929                     tt->_STime = TimeOfBeginOfDay($<ln>1);
930                  }
931               }
932             | _DIGIT_ '-' _DIGIT_
933               {
934                  if ($<ln>1 < 0 || $<ln>1 > 6 || $<ln>3 < 0 || $<ln>3 > 6) {
935                     yyerror("Day of week should be between 0 and 6");
936                     YYABORT;
937                  } else {
938                     tt->_STime = TimeOfBeginOfDay($<ln>1);
939                     tt->_ETime = TimeOfBeginOfDay($<ln>3) + (23*60*60)+(59*60)+59;
940                  }
941               }
942             ;
943 
944 Flag        : { FileName = NULL; }
945             | AFlag { FileName = strdup($<ch>1); }
946             ;
947 
948 /* -------------- */
949 
950 Mask        : _MASK { MaskMode = 0; } MParam {
951                msk->_Type = MASK_NORMAL;
952                AddReadyMask(*(NormalMask *)msk);
953             }
954             ;
955 
956 SMask       : _SMASK { MaskMode = 0; } MParam {
957                msk->_Type = MASK_SKIP;
958                AddReadyMask(*(NormalMask *)msk);
959             }
960             ;
961 
962 PMask       : _PMASK { MaskMode = 0; } MParam {
963                msk->_Type = MASK_ADD;
964                AddReadyMask(*(NormalMask *)msk);
965             }
966             ;
967 
968 MParam      : {
969                msk = new NormalMask();
970                CheckMem((char *)msk);
971                msk->_Type = MASK_NORMAL;
972                if (PrepareMask(*msk) != 0) {
973                   YYABORT;
974                }
975             }
976             SyName {
977                ((NormalMask *)msk)->_FromName = strdup($<ch>2);
978                cffa.Clean();
979             }
980             faddress {
981                ((NormalMask *)msk)->_FromAddr = cffa;
982                if (MaskMode == 0) {
983                   rc = ((NormalMask *)msk)->_FromAddr.MaskValid();
984                } else {
985                   rc = ((NormalMask *)msk)->_FromAddr.ActValid();
986                }
987                if (!rc) {
988                   yyerror("Invalid 'From' Address.");
989                   YYABORT;
990                }
991             }
992             SyName  {
993                ((NormalMask *)msk)->_ToName = strdup($<ch>6);
994                cffa.Clean();
995             }
996             faddress {
997                ((NormalMask *)msk)->_ToAddr = cffa;
998                if (MaskMode == 0) {
999                   rc = ((NormalMask *)msk)->_ToAddr.MaskValid();
1000                } else {
1001                   rc = ((NormalMask *)msk)->_ToAddr.ActValid();
1002                }
1003                if (!rc) {
1004                   yyerror("Invalid 'To' Address.");
1005                   YYABORT;
1006                }
1007                if ((((NormalMask *)msk)->_ToAddr.Zone() & (FA_LSTMASK|FA_HOLDMASK|FA_DOWNMASK|FA_PVTMASK|FA_HUBMASK)) && (!Ndl.Enabled())) {
1008                   yyerror("You can't use '#','H','D','U' or 'P' mask without nodelist.");
1009                   YYABORT;
1010                }
1011                if ((((NormalMask *)msk)->_ToAddr.Point() & FA_SUBMASK) && (!Ndl.Enabled())) {
1012                   yyerror("You can't use '&' mask without nodelist.");
1013                   YYABORT;
1014                }
1015             }
1016             MString {
1017                ((NormalMask *)msk)->_Subject = strdup($<ch>10);
1018                NoTokensF = TRUE;
1019             }
1020             MsgAttr {
1021                NoTokensF = FALSE;
1022             }
1023             ;
1024 
1025 SyName      : _STRING
1026             | '$' { $<ch>$ = "$"; }
1027             | '*' { $<ch>$ = "*"; }
1028             | '%' { $<ch>$ = "%"; }
1029             ;
1030 
1031 MString     : _STRING
1032             | '*' { $<ch>$ = "*"; }
1033             ;
1034 
1035 MDigit      : MNot _DIGIT_ {
1036                if ($<ln>2 > 65535) {
1037                   yyerror("Parameter shoul be less that 65535");
1038                   YYABORT;
1039                }
1040                $<ln>$ = $<ln>1 | $<ln>2;
1041             }
1042             | '*' { $<ln>$ = -1; }
1043             ;
1044 
1045 MNot        : { $<ln>$ = 0; }
1046             | '!' { $<ln>$ = 0x08000000; }
1047             ;
1048 
1049 MsgAttr     : '*'
1050             | { FlagMode = 1; } MsgFAttr
1051             ;
1052 MsgFAttr    : FlagsMode
1053             | MsgFAttr FlagsMode
1054             ;
1055 
1056 FlagsMode   : FlagsChar
1057             | '+' { FlagMode = 1; } FlagsChar
1058             | '-' { FlagMode = 2; } FlagsChar
1059             ;
1060 
1061 FlagsChar   : 'a' { ((NormalMask *)msk)->fFileAttach = (FlagMode == 2) ? 2 : 1; }
1062             | 'A' { /* Check MaxAttach size*/
1063                if (CheckMaskMode("A") != 0) {
1064                   YYABORT;
1065                }
1066                if (((NormalMask *)msk)->sd->_MaxAttachSize == 0 && MaxAttachSize == 0) {
1067                   yyerror("Not one (global or local) MaxAttachSize is not defined.");
1068                   YYABORT;
1069                }
1070                ((NormalMask *)msk)->fMaxAttach = (FlagMode == 2) ? 2 : 1;
1071             }
1072             | 'M' { /* Check MaxMsg size*/
1073                if (CheckMaskMode("M") != 0) {
1074                   YYABORT;
1075                }
1076                if (((NormalMask *)msk)->sd->_MaxMsgSize == 0 && MaxMsgSize == 0) {
1077                   yyerror("Not one (global or local) MaxMsgSize is not defined.");
1078                   YYABORT;
1079                }
1080                ((NormalMask *)msk)->fMaxMsg = (FlagMode == 2) ? 2 : 1;
1081             }
1082             | 'b' { ((NormalMask *)msk)->fARQ = (FlagMode == 2) ? 2 : 1; }
1083             | 'c' { ((NormalMask *)msk)->fCrash = (FlagMode == 2) ? 2 : 1; }
1084             | 'd' { ((NormalMask *)msk)->fDIR = (FlagMode == 2) ? 2 : 1; }
1085             | 'e' { /* Empty message */
1086                if (CheckMaskMode("e") != 0) {
1087                   YYABORT;
1088                }
1089                ((NormalMask *)msk)->fEmpty = (FlagMode == 2) ? 2 : 1;
1090             }
1091             | 'E' { /* Check echomail */
1092                if (CheckMaskMode("E") != 0) {
1093                   YYABORT;
1094                }
1095                ((NormalMask *)msk)->fEchomail = (FlagMode == 2) ? 2 : 1;
1096             }
1097             | 'f' { ((NormalMask *)msk)->fFileRequest = (FlagMode == 2) ? 2 : 1; }
1098             | 'g' { /* Check age */
1099                if (CheckMaskMode("g") != 0) {
1100                   YYABORT;
1101                }
1102                if (((NormalMask *)msk)->sd->_MaxAge == 0 && MaxAge == 0) {
1103                   yyerror("Not one (global or local) MaxAge is not defined.");
1104                   YYABORT;
1105                }
1106                ((NormalMask *)msk)->fMaxAge = (FlagMode == 2) ? 2 : 1;
1107             }
1108             | 'h' { ((NormalMask *)msk)->fHold = (FlagMode == 2) ? 2 : 1; }
1109             | 'i' { ((NormalMask *)msk)->fTransit = (FlagMode == 2) ? 2 : 1; }
1110             | 'j' { ((NormalMask *)msk)->fKFS = (FlagMode == 2) ? 2 : 1; }
1111             | 'k' { ((NormalMask *)msk)->fKillSend = (FlagMode == 2) ? 2 : 1; }
1112             | 'l' { ((NormalMask *)msk)->fLocal = (FlagMode == 2) ? 2 : 1; }
1113             | 'L' { ((NormalMask *)msk)->fLok = (FlagMode == 2) ? 2 : 1; }
1114             | 'm' { ((NormalMask *)msk)->fIMM = (FlagMode == 2) ? 2 : 1; }
1115             | 'n' { ((NormalMask *)msk)->fCFM = (FlagMode == 2) ? 2 : 1; }
1116             | 'o' { ((NormalMask *)msk)->fOrphan = (FlagMode == 2) ? 2 : 1; }
1117             | 'p' { ((NormalMask *)msk)->fPrivate = (FlagMode == 2) ? 2 : 1; }
1118             | 'q' { ((NormalMask *)msk)->fRRQ = (FlagMode == 2) ? 2 : 1; }
1119             | 'r' { ((NormalMask *)msk)->fReceived = (FlagMode == 2) ? 2 : 1; }
1120             | 's' { ((NormalMask *)msk)->fSend = (FlagMode == 2) ? 2 : 1; }
1121             | 'S' { ((NormalMask *)msk)->fAS = (FlagMode == 2) ? 2 : 1; }
1122             | 't' { ((NormalMask *)msk)->fTFS = (FlagMode == 2) ? 2 : 1; }
1123             | 'u' { ((NormalMask *)msk)->fFURQ = (FlagMode == 2) ? 2 : 1; }
1124             | 'v' { ((NormalMask *)msk)->fScanned = (FlagMode == 2) ? 2 : 1; }
1125             | 'x' { /* Check existing attach */
1126                if (CheckMaskMode("x") != 0) {
1127                   YYABORT;
1128                }
1129                ((NormalMask *)msk)->fAttExists = (FlagMode == 2) ? 2 : 1;
1130             }
1131             | 'y' { ((NormalMask *)msk)->fIRR = (FlagMode == 2) ? 2 : 1; }
1132             | _DIGIT_ {
1133                if (CheckMaskMode("loop flag") != 0) {
1134                   YYABORT;
1135                }
1136                ((NormalMask *)msk)->fLoop = (FlagMode == 2) ? 2 : 1;
1137                if (((NormalMask *)msk)->Loops != (unsigned int)-1) {
1138                   yyerror("Only one loop count should be in mask.");
1139                   YYABORT;
1140                }
1141                ((NormalMask *)msk)->Loops = $<ln>1;
1142             }
1143             ;
1144 
1145 /* -------------- */
1146 
1147 KludgeMask  : _KLUDGEMASK KMParam {
1148                msk->_Type = MASK_NORMAL;
1149                AddReadyMask(*(KludgeMask *)msk);
1150             }
1151             ;
1152 
1153 SKludgeMask : _SKLUDGEMASK KMParam {
1154                msk->_Type = MASK_SKIP;
1155                AddReadyMask(*(KludgeMask *)msk);
1156             }
1157             ;
1158 
1159 PKludgeMask : _PKLUDGEMASK KMParam {
1160                msk->_Type = MASK_ADD;
1161                AddReadyMask(*(KludgeMask *)msk);
1162             }
1163             ;
1164 
1165 KMParam     : {
1166                msk = new KludgeMask();
1167                CheckMem((char *)msk);
1168                msk->_Type = MASK_NORMAL;
1169                if (PrepareMask(*msk) != 0) {
1170                   YYABORT;
1171                }
1172             }
1173             MString MString MDigit {
1174                ((KludgeMask *)msk)-> _KludgeName = strdup($<ch>2);
1175                ((KludgeMask *)msk)-> _KludgeBody = strdup($<ch>3);
1176                ((KludgeMask *)msk)-> _Times = $<ln>4;
1177             }
1178             ;
1179 
1180 /* -------------- */
1181 
1182 BodyMask    : _BODYMASK BMParam {
1183                msk->_Type = MASK_NORMAL;
1184                AddReadyMask(*(BodyMask *)msk);
1185             }
1186             ;
1187 
1188 SBodyMask   : _SBODYMASK BMParam {
1189                msk->_Type = MASK_SKIP;
1190                AddReadyMask(*(BodyMask *)msk);
1191             }
1192             ;
1193 
1194 PBodyMask   : _PBODYMASK BMParam {
1195                msk->_Type = MASK_ADD;
1196                AddReadyMask(*(BodyMask *)msk);
1197             }
1198             ;
1199 
1200 BMParam     : {
1201                msk = new BodyMask();
1202                CheckMem((char *)msk);
1203                msk->_Type = MASK_NORMAL;
1204                if (PrepareMask(*msk) != 0) {
1205                   YYABORT;
1206                }
1207             }
1208             MString MDigit MDigit {
1209                ((BodyMask *)msk)-> _Body = strdup($<ch>2);
1210                ((BodyMask *)msk)-> _Lines = $<ln>3;
1211                ((BodyMask *)msk)-> _Bytes = $<ln>4;
1212             }
1213             ;
1214 
1215 
1216 /* -------------- */
1217 
1218 ScriptMask  : _SCRIPTMASK SCRMParam {
1219                msk->_Type = MASK_NORMAL;
1220                AddReadyMask(*(ScriptMask *)msk);
1221             }
1222             ;
1223 
1224 SScriptMask : _SSCRIPTMASK SCRMParam {
1225                msk->_Type = MASK_SKIP;
1226                AddReadyMask(*(ScriptMask *)msk);
1227             }
1228             ;
1229 
1230 PScriptMask : _PSCRIPTMASK SCRMParam {
1231                msk->_Type = MASK_ADD;
1232                AddReadyMask(*(ScriptMask *)msk);
1233             }
1234             ;
1235 
1236 SCRMParam   : {
1237                msk = new ScriptMask();
1238                CheckMem((char *)msk);
1239                msk->_Type = MASK_NORMAL;
1240                if (PrepareMask(*msk) != 0) {
1241                   YYABORT;
1242                }
1243             }
1244             _STRING {
1245                ((ScriptMask *)msk)->_ScriptName = strdup($<ch>2);
1246                if (!ScriptWordExists($<ch>2)) {
1247                   yyerror("Subroutine not found in scripts.");
1248                   YYABORT;
1249                }
1250             }
1251             ;
1252 
1253 /* -------------- */
1254 
1255 Action : _ACTION {
1256           if (PrevMask == 0) {
1257              yyerror("Action without Mask.");
1258              YYABORT;
1259           }
1260           wsd = ScanDirs.GetLast();
1261           PrevMask = 1;
1262           act = new Action();
1263           act->sd = wsd;
1264           act->Before = BeforeRoute;
1265           act->After = AfterRoute;
1266          _TTimes = &act->_Times;
1267        }
1268        ActionCmd {
1269           LastDo->AddAction(*act);
1270        }
1271        MayBeActTime
1272        ;
1273 
1274 MayBeActTime  :
1275               | '[' STime ']'
1276               ;
1277 
1278 ActionCmd : AAddNote
1279           | _DELETE { act->_Act = ACT_DELETE; }
1280           | AMove
1281           | ACopy
1282           | ARewrite
1283           | _IGNORE { act->_Act = ACT_IGNORE; }
1284           | ADisplay
1285           | AAFlag
1286           | ADelFile
1287           | ANewMsg
1288           | AWriteFile
1289           | AAppendToFile
1290           | ACall
1291           | ARoute
1292       | ARouteFbox
1293       | ARouteHub
1294           | APoll
1295           | _DELETEATTACH { act->_Act = ACT_DELETEATTACH; }
1296           | AChangePath
1297       | AToLowerPath
1298       | AToUpperPath
1299           | AMoveAttach
1300       | AMoveAttachFbox
1301           | ACopyAttach
1302       | ACopyAttachFbox
1303           | ASplit
1304           | ARecode
1305           | AScript
1306       | AAddKludge
1307           ;
1308 
1309 AAddNote : _ADDNOTE _STRING {
1310             act->_Act = ACT_ADDNOTE;
1311             act->_Tpl = new Template();
1312             if (!act->_Tpl->Set($<ch>2)) {
1313                yyerror("Template file is not accesible.");
1314                delete act->_Tpl;
1315                act->_Tpl = NULL;
1316                YYABORT;
1317             }
1318             act->_Tpl->sd = ScanDirs.GetLast();
1319          }
1320          ;
1321 
1322 AMove    : _MOVE _STRING {
1323             act->_Act = ACT_MOVE;
1324             act->_Base = MakeBase($<ch>2);
1325             if (act->_Base == NULL) {
1326                YYABORT;
1327             }
1328             if (!act->_Base->Set($<ch>2,BASE_OUT)) {
1329                yyerror("Invalid message base name.");
1330                delete act->_Base;
1331                act->_Base = NULL;
1332                YYABORT;
1333             }
1334             if (!act->_Base->CheckOut()) {
1335                delete act->_Base;
1336                act->_Base = NULL;
1337                YYABORT;
1338             }
1339             act->_Base->Rewind();
1340          }
1341          ;
1342 
1343 ACopy    : _COPY _STRING {
1344             act->_Act = ACT_COPY;
1345             act->_Base = MakeBase($<ch>2);
1346             if (act->_Base == NULL) {
1347                YYABORT;
1348             }
1349             if (!act->_Base->Set($<ch>2,BASE_OUT)) {
1350                yyerror("Invalid message base name.");
1351                delete act->_Base;
1352                act->_Base = NULL;
1353                YYABORT;
1354             }
1355             if (!act->_Base->CheckOut()) {
1356                delete act->_Base;
1357                act->_Base = NULL;
1358                YYABORT;
1359             }
1360             act->_Base->Rewind();
1361          }
1362          ;
1363 
1364 ARewrite : _REWRITE {
1365               MaskMode = 1;
1366               act->_Act = ACT_REWRITE;
1367            }
1368            MParam {
1369               act->_Mask = msk;
1370            }
1371          ;
1372 
1373 ADisplay : _DISPLAY _STRING {
1374             act->_Act = ACT_DISPLAY;
1375             act->_TplName = strdup($<ch>2);
1376          }
1377          ;
1378 
1379 AScript  : _ASCRIPT _STRING {
1380             act->_Act = ACT_SCRIPT;
1381             if (!ScriptWordExists($<ch>2)) {
1382                yyerror("Script function not found.");
1383                YYABORT;
1384             }
1385             act->_TplName = strdup($<ch>2);
1386          }
1387          ;
1388 
1389 AAFlag   : AFlag {
1390             act->_Act = ACT_FLAG;
1391             act->_OutDir = strdup($<ch>1);
1392          }
1393          ;
1394 
1395 AFlag    : _FLAG _STRING { $<ch>$ = $<ch>2; }
1396          ;
1397 
1398 ADelFile : _DELFILE _STRING {
1399             act->_Act = ACT_DELFILE;
1400             act->_OutDir = strdup($<ch>2);
1401          }
1402          ;
1403 
1404 ANewMsg  : _NEWMSG  {
1405             MaskMode = 1;
1406             act->_Act = ACT_NEWMSG;
1407          }
1408          _STRING _STRING MParam {
1409             act->_Tpl = new Template();
1410             if (!act->_Tpl->Set($<ch>3)) {
1411                yyerror("Template file is not accesible.");
1412                delete act->_Tpl;
1413                act->_Tpl = NULL;
1414                delete msk;
1415                msk = NULL;
1416                YYABORT;
1417             }
1418             act->_Tpl->sd =  ScanDirs.GetLast();
1419             act->_Base = MakeBase($<ch>4);
1420             if (act->_Base == NULL || !act->_Base->Set($<ch>4,BASE_OUT)) {
1421                yyerror("Invalid message base name.");
1422                delete act->_Tpl;
1423                act->_Tpl = NULL;
1424                delete msk;
1425                msk = NULL;
1426                delete act->_Base;
1427                act->_Base = NULL;
1428                YYABORT;
1429             }
1430             if (!act->_Base->CheckOut()) {
1431                delete act->_Tpl;
1432                act->_Tpl = NULL;
1433                delete msk;
1434                msk = NULL;
1435                delete act->_Base;
1436                act->_Base = NULL;
1437                YYABORT;
1438             }
1439             act->_Base->Rewind();
1440             act->_Mask = msk;
1441 
1442          }
1443          ;
1444 
1445 AWriteFile : _WRITEFILE _STRING _STRING {
1446               act->_Act = ACT_WRITEFILE;
1447               act->_Tpl = new Template();
1448               if (!act->_Tpl->Set($<ch>2)) {
1449                  yyerror("Template file is not accesible.");
1450                  delete act->_Tpl;
1451                  act->_Tpl = NULL;
1452                  YYABORT;
1453               }
1454               act->_Tpl->sd =  ScanDirs.GetLast();
1455               act->_OutDir = strdup($<ch>3);
1456            }
1457            ;
1458 
1459 AAppendToFile : _APPENDTOFILE _STRING _STRING {
1460                    act->_Act = ACT_ADDFILE;
1461                    act->_Tpl = new Template();
1462                    if (!act->_Tpl->Set($<ch>2)) {
1463                       yyerror("Template file is not accesible.");
1464                       delete act->_Tpl;
1465                       act->_Tpl = NULL;
1466                       YYABORT;
1467                    }
1468                    act->_Tpl->sd =  ScanDirs.GetLast();
1469                    act->_OutDir = strdup($<ch>3);
1470               }
1471               ;
1472 
1473 ACall : _CALL _STRING _STRING _STRING {
1474            act->_Act = ACT_CALL;
1475            act->_Tpl = new Template();
1476            if (!act->_Tpl->Set($<ch>2)) {
1477               yyerror("Template file is not accesible.");
1478               delete act->_Tpl;
1479               act->_Tpl = NULL;
1480               YYABORT;
1481            }
1482            act->_Tpl->sd =  ScanDirs.GetLast();
1483            act->_OutDir = strdup($<ch>3);
1484            act->_TplName = strdup($<ch>4);
1485       }
1486       | _CALL _STRING {
1487            act->_Act = ACT_CALL;
1488            act->_TplName = strdup($<ch>2);
1489       }
1490       ;
1491 
1492 ARoute : _ROUTE RouMode { cffa.Clean(); } faddress {
1493           act->_Act = ACT_ROUTE;
1494           if (act->sd == act->Before|| act->sd == act->After) {
1495              yyerror("You can not use the Action Route in 'ScanDir: @AfterRoute|@BeforeRoute'");
1496              YYABORT;
1497           }
1498           act->_Flav = $<pktmode>2;
1499           act->_f = cffa;
1500           if (act->_f.Point() & FA_NOTDEF) {
1501              act->_f.Point(0);
1502           }
1503           if (!act->_f.RouValid()) {
1504              yyerror("Invalid routing address.");
1505              YYABORT;
1506           }
1507        }
1508        ;
1509 
1510 ARouteFbox : _ROUTEFBOX RouMode { cffa.Clean(); } faddress {
1511           act->_Act = ACT_ROUTEFBOX;
1512       if (FileBoxDir == NULL)
1513       {
1514        yyerror("You must define FileBoxDir before using Action: RouteFilebox.");
1515        YYABORT;
1516       }
1517           if (act->sd == act->Before|| act->sd == act->After) {
1518              yyerror("You can not use the Action RouteFilebox in 'ScanDir: @AfterRoute|@BeforeRoute'");
1519              YYABORT;
1520           }
1521           act->_Flav = $<pktmode>2;
1522           act->_f = cffa;
1523           if (act->_f.Point() & FA_NOTDEF) {
1524              act->_f.Point(0);
1525           }
1526           if (!act->_f.RouValid()) {
1527              yyerror("Invalid routing address.");
1528              YYABORT;
1529           }
1530        }
1531        ;
1532 
1533 ARouteHub : _ROUTEHUB RouMode { cffa.Clean(); } {
1534           act->_Act = ACT_ROUTEHUB;
1535           if (act->sd == act->Before|| act->sd == act->After) {
1536              yyerror("You can not use the Action RouteHub in 'ScanDir: @AfterRoute|@BeforeRoute'");
1537              YYABORT;
1538           }
1539           act->_Flav = $<pktmode>2;
1540        }
1541        ;
1542 
1543 
1544 ACopyAttachFbox : _COPYATTACHFBOX RouMode { cffa.Clean(); } faddress {
1545           act->_Act = ACT_COPYATTACHFBOX;
1546       if (FileBoxDir == NULL)
1547       {
1548        yyerror("You must define FileBoxDir before using Action: CopyAttachFilebox.");
1549        YYABORT;
1550       }
1551           act->_Flav = $<pktmode>2;
1552           act->_f = cffa;
1553        }
1554        ;
1555 
1556 AMoveAttachFbox : _MOVEATTACHFBOX RouMode { cffa.Clean(); } faddress {
1557           act->_Act = ACT_MOVEATTACHFBOX;
1558       if (FileBoxDir == NULL)
1559       {
1560        yyerror("You must define FileBoxDir before using Action: MoveAttachFilebox.");
1561        YYABORT;
1562       }
1563           act->_Flav = $<pktmode>2;
1564           act->_f = cffa;
1565        }
1566        ;
1567 
1568 RouMode : _HOLD   { $<pktmode>$ = F_HOLD; }
1569         | _CRASH  { $<pktmode>$ = F_CRASH; }
1570         | _DIRECT { $<pktmode>$ = F_DIRECT; }
1571         | _NORMAL { $<pktmode>$ = F_NORMAL; }
1572     | _IMMEDIATE{ $<pktmode>$ = F_IMMEDIATE; }
1573         ;
1574 
1575 APoll : _POLL RouMode { cffa.Clean(); } faddress {
1576           act->_Act = ACT_POLL;
1577           act->_Flav = $<pktmode>2;
1578           act->_f = cffa;
1579           if (act->_f.Point() & FA_NOTDEF) {
1580              act->_f.Point(0);
1581           }
1582           if (!act->_f.RouValid()) {
1583              yyerror("Invalid poll address.");
1584              YYABORT;
1585           }
1586        }
1587       ;
1588 
1589 AChangePath : _CHANGEPATH _STRING {
1590                act->_Act = ACT_CHANGEPATH;
1591                if (strlen($<ch>2) > 72) {
1592                   yyerror("New path too long");
1593                   YYABORT;
1594                }
1595                act->_OutDir = strdup($<ch>2);
1596             }
1597             ;
1598 
1599 AToLowerPath : _TOLOWERPATH {
1600                act->_Act = ACT_TOLOWERPATH;
1601             }
1602             ;
1603 
1604 
1605 AToUpperPath : _TOUPPERPATH {
1606                act->_Act = ACT_TOUPPERPATH;
1607             }
1608             ;
1609 
1610 AAddKludge : _ADDKLUDGE _STRING _STRING {
1611                act->_Act = ACT_ADDKLUDGE;
1612            act->_OutDir = strdup($<ch>2);
1613            act->_TplName = strdup($<ch>3);
1614             }
1615             ;
1616 
1617 
1618 AMoveAttach : _MOVEATTACH _STRING {
1619                act->_Act = ACT_MOVEATTACH;
1620                if (!DirExists($<ch>2)) {
1621              Log.Level(LOGE) << "Target directory '" << $<ch>2 << "' not found." << EOL;
1622                }
1623                if (strlen($<ch>2) > 72) {
1624                   yyerror("New path too long");
1625                   YYABORT;
1626                }
1627                act->_OutDir = strdup($<ch>2);
1628             }
1629             ;
1630 
1631 ACopyAttach : _COPYATTACH _STRING {
1632                act->_Act = ACT_COPYATTACH;
1633                if (!DirExists($<ch>2)) {
1634              Log.Level(LOGE) << "Target directory '" << $<ch>2 << "' not found." << EOL;
1635                }
1636                if (strlen($<ch>2) > 72) {
1637                   yyerror("New path too long");
1638                   YYABORT;
1639                }
1640                act->_OutDir = strdup($<ch>2);
1641             }
1642             ;
1643 
1644 ASplit      : _SPLIT _DIGIT_ {
1645                act->_Act = ACT_SPLIT;
1646                if ($<ln>2 < 1 || $<ln>2 > 65535) {
1647                   yyerror("Parameter 'Lines' should be positive integer between 1 and 65535");
1648                   YYABORT;
1649                }
1650                act->_Lines = $<ln>2;
1651             }
1652             ;
1653 
1654 ARecode     : _RECODE _STRING {
1655                FILE *fp = NULL;
1656                char buf[512],*p,*q;
1657                int in,on,count;
1658                int line = 0;
1659 
1660                   act->_Act = ACT_RECODE;
1661                   fp = fopen($<ch>2,"r");
1662                   if (fp == NULL) {
1663                      yyerror("Unable to open file");
1664                      YYABORT;
1665                   }
1666                   act->_TplName = (char *)malloc(256);
1667                   CheckMem(act->_TplName);
1668                   for (count = 0; count < 256; count++) act->_TplName[count] = (char) count;
1669                   count = 0;
1670                   line = 0;
1671 
1672                   while (fgets((char*)buf,sizeof(buf),fp)) {
1673                      line++;
1674                      p = strtok((char*)buf," \t\n#");
1675                      q = strtok(NULL," \t\n#");
1676                      if (p != NULL && q != NULL) {
1677                         in = ctoi((char *)p);
1678                         if (in > 255) {
1679                            sprintf(buf, "%s: Error in line %d.", $<ch>2, line);
1680                            yyerror(buf);
1681                            fclose(fp);
1682                            free(act->_TplName);
1683                            YYABORT;
1684                         }
1685                         on=ctoi((char *)q);
1686                         if (in != 0 && on != 0) {
1687                            if (count++ < 256 ) {
1688                               act->_TplName[in]=on;
1689                            } else {
1690                               sprintf(buf,"Char map table \"%s\" is big",$<ch>2);
1691                               yyerror(buf);
1692                               fclose(fp);
1693                               free(act->_TplName);
1694                               YYABORT;
1695                            }
1696                         }
1697                      } /* if */
1698                   } /* While */
1699                   fclose(fp);
1700             }
1701             ;
1702 
1703 
1704 /* -------------- */
1705 
1706 faddress : FullFtnAddr
1707          | '!' FullFtnAddr { cffa.Zone(cffa.Zone() | FA_NOTMASK); }
1708          ;
1709 
1710 FullFtnAddr : nodeaddr
1711             | pointaddr
1712             | '*'
1713                {
1714                   cffa.Zone(FA_ANYMASK);
1715                   cffa.Net(FA_ANYMASK);
1716                   cffa.Node(FA_ANYMASK);
1717                   cffa.Point(FA_ANYMASK);
1718                }
1719             | '#'
1720                {
1721                   cffa.Zone(FA_LSTMASK);
1722                   cffa.Net(FA_LSTMASK);
1723                   cffa.Node(FA_LSTMASK);
1724                   cffa.Point(FA_LSTMASK);
1725                }
1726             | 'H'
1727                {
1728                   cffa.Zone(FA_HOLDMASK);
1729                   cffa.Net(FA_HOLDMASK);
1730                   cffa.Node(FA_HOLDMASK);
1731                   cffa.Point(FA_HOLDMASK);
1732                }
1733             | 'U'
1734                {
1735                   cffa.Zone(FA_HUBMASK);
1736                   cffa.Net(FA_HUBMASK);
1737                   cffa.Node(FA_HUBMASK);
1738                   cffa.Point(FA_HUBMASK);
1739                }
1740             | 'D'
1741                {
1742                   cffa.Zone(FA_DOWNMASK);
1743                   cffa.Net(FA_DOWNMASK);
1744                   cffa.Node(FA_DOWNMASK);
1745                   cffa.Point(FA_DOWNMASK);
1746                }
1747             | 'P'
1748                {
1749                   cffa.Zone(FA_PVTMASK);
1750                   cffa.Net(FA_PVTMASK);
1751                   cffa.Node(FA_PVTMASK);
1752                   cffa.Point(FA_PVTMASK);
1753                }
1754             | '@'
1755                {
1756                   cffa.Zone(FA_OURMASK);
1757                   cffa.Net(FA_OURMASK);
1758                   cffa.Node(FA_OURMASK);
1759                   cffa.Point(FA_OURMASK);
1760                }
1761             | '$'
1762                {
1763                   cffa.Zone(FA_FROMMASK);
1764                   cffa.Net(FA_FROMMASK);
1765                   cffa.Node(FA_FROMMASK);
1766                   cffa.Point(FA_FROMMASK);
1767                }
1768             | '%'
1769                {
1770                   cffa.Zone(FA_TOMASK);
1771                   cffa.Net(FA_TOMASK);
1772                   cffa.Node(FA_TOMASK);
1773                   cffa.Point(FA_TOMASK);
1774                }
1775             | '%' '.' _DIGIT_
1776                {
1777                   if ($<ln>3 != 0) {
1778                      yyerror("parse error");
1779                      YYABORT;
1780                   }
1781                   cffa.Zone(FA_TOMASK);
1782                   cffa.Net(FA_TOMASK);
1783                   cffa.Node(FA_TOMASK);
1784                   cffa.Point(0);
1785                }
1786             ;
1787 
1788 pointaddr: nodeaddr '.' PntAddr
1789          ;
1790 
1791 PntAddr  : dw   { cffa.Point($<ln>1); }
1792          | '&'  { cffa.Point(FA_SUBMASK); }
1793          ;
1794 
1795 nodeaddr : dw ':' dw '/' dw
1796             {
1797                cffa.Zone($<ln>1);
1798                cffa.Net($<ln>3);
1799                cffa.Node($<ln>5);
1800                cffa.Point(0);
1801             }
1802          ;
1803 
1804 dw       : _DIGIT_ { $<ln>$ = $<ln>1; }
1805          | '*' { $<ln>$ = FA_ANYMASK; }
1806          ;
1807 
1808 
1809 %%
1810 
1811 
1812