1 // $Id$
2 //
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 2 of the License, or
6 // (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with this program. If not, see <http://www.gnu.org/licenses/>.
15
16 #if defined (__TSC__)
17 # pragma call(inline_max => 150)
18 #endif
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <ctype.h>
23 #include <time.h>
24 #if defined (__TSC__)
25 # include <alloc.h>
26 # include <dir.h>
27 # define EOLCHR "\n"
28 #elif defined (__WATCOMC__)
29 # include <malloc.h>
30 # include <direct.h>
31 # include <io.h>
32
33 # define fnsplit _splitpath
34 # define fnmerge _makepath
35
36 # define EOLCHR "\n"
37
38 # if defined (__OS2__)
39 # define _OS2 1
40 # endif
41 #elif defined(__GNUC__)
42 // #include <malloc.h>
43 # include <sys/param.h> // for MAXPATHLEN
44 # include <dirent.h>
45 # include <unistd.h>
46 # include <glob.h>
47
48 # define strnicmp(x,y,z) strncasecmp(x,y,z)
49 # define stricmp(x,y) strcasecmp(x,y)
50 # define itoa(i,a,base) (sprintf(a,"%i",i),a)
51
52 # define EOLCHR "\n"
53 # define link linkd
54
55 #elif defined (__MSVC__)
56 # include <io.h>
57 # define EOLCHR "\n"
58 # define MAXDRIVE 3
59 # define fnsplit _splitpath
60 # define fnmerge _makepath
61 #endif
62
63 #define VERSION "1.37"
64 #define CREATED "%c %s routing for %d:%d/%d. Created by Hubroute generator "VERSION""EOLCHR"%c %45s%c"EOLCHR""
65 #ifdef _TARGET
66 # if defined (__GNUC__)
67 # define TARGET "GNU/" _TARGET
68 # else
69 # define TARGET _TARGET
70 # endif
71 #else /*defined (__GNUC__) */
72 # if defined(_OS2) || defined (__OS2__)
73 # define TARGET "OS/2"
74 # elif defined (__NT__) && defined (_WIN64)
75 # define TARGET "w64"
76 # elif defined (__NT__)
77 # define TARGET "w32"
78 # elif defined (__DJGPP__)
79 # define TARGET "dpmi-djgpp"
80 # elif defined (__GNUC__)
81 # define TARGET "GNU/Unix"
82 # else
83 # define TARGET "DOS"
84 # endif
85 #endif
86
87 #ifdef boolean
88 # undef boolean
89 #endif
90
91 typedef unsigned short ushort;
92 typedef unsigned long ulong;
93 typedef unsigned short boolean;
94
95 struct nodeaddr
96 {
97 ushort z, n, f;
nodeaddrnodeaddr98 nodeaddr( ushort zz = 0, ushort nn = 0, ushort ff = 0 ):z( zz ), n( nn ), f( ff )
99 {
100 };
operator ==nodeaddr101 boolean operator==( nodeaddr & a )
102 {
103 return z == a.z && n == a.n && f == a.f;
104 };
CleanUpnodeaddr105 void CleanUp( void )
106 {
107 z = n = f = 0;
108 }
109 };
110
111 struct listitem
112 {
113 ushort idx; // uplink index in file
114 ushort is_uplink; // is first in route.raw
115 nodeaddr addr;
116 };
117
118 struct link
119 {
120 ushort flavor;
121 nodeaddr addr;
122 };
123
124 struct CfgValue
125 {
126 const char *Name;
127 void *Value;
128 ushort Pass;
129 boolean( *LoadVal ) ( char *in, void *out );
130 };
131
132 static const char *ErrNoMemory = EOLCHR "Unable to allocate memory.";
133 static const char *ErrOpenCfg = EOLCHR "Unable to open config file.";
134 static const char *ErrNoFile = "Unable to open file.";
135 static const char *ErrOpenTmp = EOLCHR "Unable to open temp file.";
136 static const char *ErrOpenTmpX = EOLCHR "Unable to open temp file \"%s\"." EOLCHR;
137 static const char *ErrOpenDest = EOLCHR "Unable to open dest file.";
138 static const char *ErrUnknownRouteType = EOLCHR "Unsupported route type.";
139 static const char *ErrUnknownMinType = EOLCHR "Illegal value of \"Minimized\".";
140 static const char *ErrQuoteString = "Illegal quoted string.";
141 static const char *ErrMissMainAddr = EOLCHR "Missing or illegal main address.";
142 static const char *ErrMissRouteType = EOLCHR "Missing \"RouteType\" keyword.";
143 static const char *ErrMissMinType = EOLCHR "Missing \"Minimize\" keyword. YES Accepted.";
144 static const char *ErrNoReplEnd = EOLCHR "Missing \"RouteEnd\" in dest file.";
145 static const char *ErrNoReplBeg = EOLCHR "Missing \"RouteBegin\" in dest file.";
146 static const char *ErrBadNdlType = "Bad \"HubRoute\" definition.";
147 static const char *ErrMissDirect =
148 EOLCHR "%s is routed via us, but missing in \"Link\" definitions." EOLCHR
149 " \'DefaultFlavor\' assumed.";
150 static const char *ErrReroute = EOLCHR "Rerouting for %s.";
151 static const char *ErrLoop = EOLCHR "RouteLoop detected for %s. Try to route by default";
152 static const char *WarnNoMin = EOLCHR "Unable to minimize tree - out of memory";
153
154 #define Error(s) fprintf(stderr,"%s" EOLCHR,s)
155 #define ErrorS(s,str) fprintf(stderr,s,str)
156 #define ErrorL(s) fprintf(stderr, "%s %d: %s" EOLCHR, CfgFile, CfgLine, s)
157
158 #define true 1
159 #define false 0
160
161 #define ItemNum(arr) (sizeof(arr)/sizeof(arr[0]))
162
163 #define MAXNODES 5000
164 #define MAXWILD 2000
165 #define MAXLINKS 1000
166 #define MAXAKAS 50
167 #define BUFFLEN 30000
168 #define PATHLEN 100
169 #define WILDVALUE 0xFFFF
170 #define DEADLOCK_DEPTH 10
171 int MAX_ROUTE_LEN = 64;
172
173 enum
174 {
175 DIRECT_FLAVOR = 1, CRASH_FLAVOR = 2, HOLD_FLAVOR = 4,
176 NORMAL_FLAVOR = 16, FILE_FLAVOR = 32, NOARC_FLAVOR = 64
177 };
178
179 static ushort DefaultFlavor = HOLD_FLAVOR;
180
181 #if defined (__WATCOMC__)
182 # define MAXPATH 256
183 # define MAXDRIVE 3
184 # define MAXDIR 256
185 # define MAXFILE NAME_MAX
186 # define MAXEXT NAME_MAX
187 #elif defined (__GNUC__) || (__MSVC__)
188 # ifdef MAXPATHLEN
189 # define MAXPATH MAXPATHLEN
190 # else
191 # define MAXPATH 512
192 # endif
193 # define MAXDIR MAXPATH
194 # define MAXFILE MAXPATH
195 # define MAXEXT MAXPATH
196 #endif
197
198 #if defined(__GNUC__)
199 static char TempFile[MAXPATH];
200
201 #else
202 static char TempFile[MAXPATH];
203 static char OutDrv[MAXDRIVE];
204 #endif
205
206 #if !defined (__GNUC__)
207 static char OutDir[MAXDIR];
208 static char OutName[MAXFILE];
209 static char OutExt[MAXEXT];
210 #endif
211
212 #define SQUISH 1
213 #define ITRACK 2
214 #define TMAIL 3
215 #define BPACK 4
216 #define IMBINK 5
217 #define XMAIL 6
218 #define IFMAIL 7
219 #define BIP 8
220 #define UNIMAIL 9
221 #define QECHO 10
222 #define FIDOGATE 11
223 #define FTRACK 12
224 #define HUSKY 13
225 static ushort RouteMode = 0;
226 static ushort MinMode = 0;
227 static ushort KillTransit = 0;
228
229 #if defined (__GNUC__)
230 glob_t globbuf;
231 #endif
232
233 static char *Buff;
234 static char *Prefix;
235 static nodeaddr PrevNode;
236 static nodeaddr *MyNode = NULL;
237 static nodeaddr UpNode( 0, 0, 0 ); // t-mail routing only
238 static link *Link;
239 static listitem *Node;
240 static listitem *WildNode; // Wildcards in nodelist
241 static ushort nNodes = 0, nLinks = 0, nAKAs = 0, nWilds = 0;
242 static ushort level; // 0 - node, 1 - net, 2 - zone, 3 - world
243 static time_t currtime;
244 static char *CfgFile;
245 static ushort CfgLine;
246 static char WriteTo[PATHLEN];
247 static FILE *NewRoute;
248 static FILE *OldRoute;
249
250 #define Spit(s) { fputs(s, NewRoute); fputs(EOLCHR, NewRoute); }
251 static char RouteBegin[100];
252 static char RouteEnd[100];
253 static boolean StarWild, AddPoint, DefaultFromMe, FullAddr, FillRoute, WithSlash, TmailAddFor;
254 static char CmntSym = '#';
255
InMemory(nodeaddr addr)256 static ushort InMemory( nodeaddr addr )
257 {
258 for( ushort i = 0; i < nNodes; i++ )
259 if( Node[i].addr == addr )
260 return i;
261 return 0xFFFF;
262 }
263
IsMyNode(nodeaddr addr)264 static boolean IsMyNode( nodeaddr addr )
265 {
266 int i;
267 for( i = 0; i < nAKAs; i++ )
268 if( MyNode[i] == addr )
269 return true;
270 return false;
271 }
272
DirectLink(ushort Idx)273 static boolean DirectLink( ushort Idx )
274 {
275 int i;
276 for( i = 0; i < nLinks; i++ )
277 if( Link[i].addr == Node[Idx].addr )
278 return true;
279 return false;
280 }
281
DirectLink(nodeaddr n)282 static boolean DirectLink( nodeaddr n )
283 {
284 int i;
285 for( i = 0; i < nLinks; i++ )
286 if( Link[i].addr == n )
287 return true;
288 return false;
289 }
290
skipws(char ** p)291 inline void skipws( char **p )
292 {
293 while( **p == ' ' || **p == '\t' || **p == '\r' )
294 ( *p )++;
295 }
296
getnum(char ** p)297 static ushort getnum( char **p )
298 {
299 int i = 0;
300 while( isdigit( **p ) )
301 i = i * 10 + ( *( ( *p )++ ) - '0' );
302 return ( ushort ) i;
303 }
304
ScanNode(char ** p)305 static nodeaddr ScanNode( char **p )
306 {
307 nodeaddr addr = PrevNode;
308 ushort tmp, mode;
309
310 #define START 1
311 #define SCAN 2
312 #define DONE 3
313 skipws( p );
314 mode = START;
315 while( mode != DONE )
316 {
317 switch ( mode )
318 {
319 case START:
320 if( strnicmp( *p, "World", 5 ) == 0 )
321 {
322 addr.z = addr.n = addr.f = WILDVALUE;
323 PrevNode = *MyNode; // _Main_ aka
324 *p += 5;
325 return addr;
326 }
327 case SCAN:
328 skipws( p );
329 if( strnicmp( *p, "All", 3 ) == 0 )
330 {
331 tmp = WILDVALUE;
332 *p += 3;
333 }
334 else if( **p == '*' )
335 {
336 tmp = WILDVALUE;
337 *p += 1;
338 }
339 else
340 tmp = getnum( p );
341 switch ( **p )
342 {
343 case ':':
344 addr.z = tmp;
345 mode = SCAN;
346 ( *p )++;
347 break;
348 case '/':
349 addr.n = tmp;
350 mode = SCAN;
351 ( *p )++;
352 break;
353 default:
354 addr.f = tmp;
355 mode = DONE;
356 }
357 }
358 }
359 PrevNode = addr;
360
361 // Skip unnesessary tail such as point address etc.
362 while( **p != ' ' && **p != '\t' && **p != '\r' && **p != '\n' && **p != '\0' )
363 ( *p )++;
364 return addr;
365
366 #undef START
367 #undef SCAN
368 #undef DONE
369 }
370
WriteNode(nodeaddr Node,char * out,short addrtype)371 static ushort WriteNode( nodeaddr Node, char *out, short addrtype )
372 {
373 char tmp[10];
374 ushort wildlevel = 0;
375 if( Node.f == WILDVALUE )
376 wildlevel++;
377 if( Node.n == WILDVALUE )
378 wildlevel++;
379 if( Node.z == WILDVALUE )
380 wildlevel++;
381 if( wildlevel == level || addrtype == 1 )
382 {
383 const char *Wild = ( StarWild ) ? "*" : "All";
384 strcat( out, " " );
385 if( Node.z == WILDVALUE && Node.n == WILDVALUE && Node.n == WILDVALUE )
386 strcat( out, StarWild ? "*:*/*" : "World" );
387 else
388 {
389 if( addrtype || FullAddr || Node.z != PrevNode.z )
390 {
391 strcat( out, itoa( Node.z, tmp, 10 ) );
392 strcat( out, ":" );
393 }
394 if( addrtype || FullAddr || Node.n != PrevNode.n || Node.f == WILDVALUE )
395 {
396 strcat( out, Node.n != WILDVALUE ? itoa( Node.n, tmp, 10 ) : Wild );
397 if( !WithSlash )
398 strcat( out, "/" );
399 }
400 if( WithSlash )
401 strcat( out, "/" );
402 strcat( out, Node.f != WILDVALUE ? itoa( Node.f, tmp, 10 ) : Wild );
403 }
404 if( AddPoint && !addrtype )
405 strcat( out, ".*" );
406 if( DefaultFromMe )
407 PrevNode = *MyNode; // Main aka
408 else
409 PrevNode = Node;
410 }
411 return ( ushort ) strlen( out );
412 }
413
StrNode(nodeaddr Node)414 static char *StrNode( nodeaddr Node )
415 {
416 static char buff[40];
417 boolean tmp = FullAddr;
418 buff[0] = '\0';
419 FullAddr = true;
420 buff[WriteNode( Node, buff, 1 )] = '\0';
421 FullAddr = tmp;
422 return buff;
423 }
424
TestCmpQuality(nodeaddr & S,nodeaddr & D)425 static ushort TestCmpQuality( nodeaddr & S, nodeaddr & D )
426 {
427 ushort Q = 0;
428 if( ( D.z != WILDVALUE && S.z != D.z ) ||
429 ( D.n != WILDVALUE && S.n != D.n ) || ( D.f != WILDVALUE && S.f != D.f ) )
430 return 0; // Not match
431
432 if( D.z == WILDVALUE )
433 Q++;
434 else
435 Q += 2;
436
437 if( D.n == WILDVALUE )
438 Q += 10;
439 else
440 Q += 20;
441
442 if( D.f == WILDVALUE )
443 Q += 100;
444 else
445 Q += 200; // Who cares... :)
446
447 return Q;
448 }
449
FixWildcard(void)450 static void FixWildcard( void )
451 {
452 ushort i;
453 for( i = 0; i < nNodes; i++ )
454 {
455 // Fix wildcard such as All:5020/All to All:All/All etc.
456 if( Node[i].addr.z == WILDVALUE )
457 Node[i].addr.n = WILDVALUE;
458 if( Node[i].addr.n == WILDVALUE )
459 Node[i].addr.f = WILDVALUE;
460 ushort MaxQuality, MaxQualityIdx, cmp;
461 MaxQuality = 0;
462
463 // Try to route unrouted items to nearest wildcard
464 if( Node[i].idx == WILDVALUE && !DirectLink( i ) ) // not routed
465 {
466 ushort j;
467 for( j = 0; j < nNodes; j++ )
468 if( Node[j].idx != WILDVALUE ) // is routed
469 if( ( cmp = TestCmpQuality( Node[i].addr, Node[j].addr ) ) > MaxQuality )
470 {
471 MaxQuality = cmp;
472 MaxQualityIdx = j;
473 }
474 if( MaxQuality > 0 ) // found correct match
475 {
476 boolean deadlock = false;
477 ushort idx = MaxQualityIdx;
478
479 // Try to recognize route-loop such as 2:5020/50 <= 2:5020/All
480 for( j = 0; j < DEADLOCK_DEPTH && !deadlock; j++ )
481 if( i == idx ) // We catch the same node
482 deadlock = true;
483
484 else if( idx != WILDVALUE ) // Catch unrouted
485 idx = Node[idx].idx;
486
487 else // idx == WILDVALUE - unrouted (may be direct)
488 break;
489 if( !deadlock )
490 Node[i].idx = MaxQualityIdx;
491 }
492 }
493 }
494
495 // Fixup my downlinks if they are undefined as Direct links
496 for( i = 0; i < nNodes; i++ ) // Look for my downlinks
497 {
498 if( Node[i].idx != WILDVALUE && IsMyNode( Node[Node[i].idx].addr ) && !DirectLink( i ) )
499 {
500 Link[nLinks].addr = Node[i].addr;
501 Link[nLinks].flavor = DefaultFlavor;
502 nLinks++;
503 ErrorS( ErrMissDirect, StrNode( Node[i].addr ) );
504 }
505 }
506
507 // Make the tree one-leveled
508 for( i = 0; i < nNodes; i++ )
509 {
510 if( Node[i].idx != WILDVALUE ) // routed
511 {
512 nodeaddr Orig = Node[i].addr;
513 while( !( Node[Node[i].idx].idx == WILDVALUE ||
514 ( DirectLink( Node[i].idx ) && Node[Node[i].idx].addr.f != 0xFFFF ) ) )
515 {
516 Node[i].idx = Node[Node[i].idx].idx;
517 if( Node[Node[i].idx].addr == Orig ) // Loop detected
518 {
519 ErrorS( ErrLoop, StrNode( Node[Node[i].idx].addr ) );
520 Node[Node[i].idx].idx = WILDVALUE;
521 break;
522 }
523 }
524 }
525 }
526 }
527
IsWild(nodeaddr n)528 static boolean IsWild( nodeaddr n )
529 {
530 return ( n.z == WILDVALUE || n.n == WILDVALUE || n.f == WILDVALUE ) ? true : false;
531 }
532
CmpWild(void const * l1,void const * l2)533 int CmpWild( void const *l1, void const *l2 )
534 {
535 if( ( ( listitem * ) l1 )->addr.z > ( ( listitem * ) l2 )->addr.z )
536 return 1;
537
538 else if( ( ( listitem * ) l1 )->addr.z < ( ( listitem * ) l2 )->addr.z )
539 return -1;
540
541 else if( ( ( listitem * ) l1 )->addr.n > ( ( listitem * ) l2 )->addr.n )
542 return 1;
543
544 else if( ( ( listitem * ) l1 )->addr.n < ( ( listitem * ) l2 )->addr.n )
545 return -1;
546
547 else if( ( ( listitem * ) l1 )->addr.f > ( ( listitem * ) l2 )->addr.f )
548 return 1;
549
550 else if( ( ( listitem * ) l1 )->addr.f < ( ( listitem * ) l2 )->addr.f )
551 return -1;
552
553 else
554 return 0;
555 }
556
RemoveUnnecessary(void)557 static void RemoveUnnecessary( void )
558 {
559 ushort i, j;
560
561 // Remove double-routed nodes if it's up-wild routed by the same way
562 if( MinMode )
563 {
564 WildNode = ( listitem * ) calloc( MAXWILD, sizeof( listitem ) );
565 if( WildNode != NULL )
566 {
567 for( i = 0; i < nNodes; i++ )
568 if( IsWild( Node[i].addr ) )
569 WildNode[nWilds++] = Node[i];
570 qsort( WildNode, nWilds, sizeof( listitem ), CmpWild );
571 for( i = 0; i < nNodes; i++ )
572 {
573 if( Node[i].idx != WILDVALUE ) // routed
574 {
575 for( j = 0; j < nWilds; j++ )
576 {
577 if( !( Node[i].addr == WildNode[j].addr ) &&
578 TestCmpQuality( Node[i].addr, WildNode[j].addr ) > 0 )
579 {
580 if( Node[i].idx == WildNode[j].idx && !DirectLink( i ) )
581 Node[i].idx = 0xFFFE;
582 break;
583 }
584 }
585 }
586 }
587 free( WildNode );
588 }
589 else
590 Error( WarnNoMin );
591 }
592 }
593
GetFlavor(link * pLink,const char * Flav[])594 static const char *GetFlavor( link * pLink, const char *Flav[] )
595 {
596 if( pLink->flavor & CRASH_FLAVOR )
597 return Flav[0];
598
599 else if( pLink->flavor & DIRECT_FLAVOR )
600 return Flav[1];
601
602 else if( pLink->flavor & HOLD_FLAVOR )
603 return Flav[2];
604
605 else
606 return Flav[3];
607 }
608
609 const char *SqFlavors[] = {
610 "Crash ", "Direct", "Hold ", "Normal"
611 };
612
MakeSqPrefix(link * pLink,char * out)613 static void MakeSqPrefix( link * pLink, char *out )
614 {
615 strcpy( out, "Route " );
616 strcat( out, GetFlavor( pLink, SqFlavors ) );
617 if( pLink->flavor & FILE_FLAVOR )
618 strcat( out, " file" );
619 else
620 strcat( out, " " );
621
622 if( pLink->flavor & NOARC_FLAVOR )
623 strcat( out, " NoArc" );
624 else
625 strcat( out, " " );
626
627 WriteNode( pLink->addr, out, 1 );
628 strcat( out, " " );
629 }
630
PutDirects(ushort mask,ushort pattern,const char * Pfix)631 static void PutDirects( ushort mask, ushort pattern, const char *Pfix )
632 {
633 int i;
634 PrevNode = *MyNode; // Main aka
635 strcpy( Buff, Pfix );
636 strcpy( Prefix, Pfix );
637 for( i = 0; i < nLinks; i++ )
638 {
639 if( ( Link[i].flavor & mask ) == pattern )
640 if( WriteNode( Link[i].addr, Buff, 0 ) >= MAX_ROUTE_LEN )
641 {
642 Spit( Buff ); // Spit out
643 strcpy( Buff, Prefix );
644 PrevNode = *MyNode; // Main aka
645 }
646 }
647 if( strcmp( Buff, Prefix ) != 0 )
648 Spit( Buff );
649 }
650
PutDownLinksGeneric(ushort UpIdx,ushort type,ushort (* wrtnode)(nodeaddr,char *,ushort))651 static void PutDownLinksGeneric( ushort UpIdx, ushort type,
652 ushort( *wrtnode ) ( nodeaddr, char *, ushort ) )
653 {
654 ushort i;
655 for( i = 0; i < nNodes; i++ )
656 {
657 if( Node[i].idx == UpIdx && !DirectLink( i ) && !IsMyNode( Node[i].addr ) &&
658 ( ( UpIdx != WILDVALUE && Node[i].idx != i ) ||
659 ( UpIdx == WILDVALUE && Node[i].is_uplink ) ) )
660 {
661 if( wrtnode( Node[i].addr, Buff, type ) >= MAX_ROUTE_LEN )
662 {
663 if( UpNode.z != 0 )
664 {
665 wrtnode( UpNode, Buff, 1 );
666 PrevNode = *MyNode;
667 }
668 Spit( Buff ); // Spit out
669 strcpy( Buff, Prefix );
670 if( UpIdx != WILDVALUE && UpNode.z == 0 )
671 PrevNode = Node[UpIdx].addr;
672 }
673 if( FillRoute ) // Prevents duplication in 'Unrouted'
674 Node[i].idx = 0;
675 else
676 PutDownLinksGeneric( i, type, wrtnode );
677 }
678 }
679 }
680
PutDownLinks(ushort UpIdx,ushort type)681 static void PutDownLinks( ushort UpIdx, ushort type )
682 {
683 ushort i;
684 for( i = 0; i < nNodes; i++ )
685 {
686 if( Node[i].idx == UpIdx && !DirectLink( i ) && !IsMyNode( Node[i].addr ) &&
687 ( ( UpIdx != WILDVALUE && Node[i].idx != i ) ||
688 ( UpIdx == WILDVALUE && Node[i].is_uplink ) ) )
689 {
690 if( WriteNode( Node[i].addr, Buff, type ) >= MAX_ROUTE_LEN )
691 {
692 if( UpNode.z != 0 )
693 {
694 WriteNode( UpNode, Buff, 1 );
695 PrevNode = *MyNode;
696 }
697 Spit( Buff ); // Spit out
698 strcpy( Buff, Prefix );
699 if( UpIdx != WILDVALUE && UpNode.z == 0 )
700 PrevNode = Node[UpIdx].addr;
701 }
702
703 if( FillRoute ) // Prevents duplication in 'Unrouted'
704 Node[i].idx = 0;
705 else
706 PutDownLinks( i, type );
707 }
708 }
709 }
710
711 static const char *RouteType[] = {
712 "Nodes", "Nets", "Zones", "Default"
713 };
714
DirectsSQ(void)715 static void DirectsSQ( void )
716 {
717 PutDirects( CRASH_FLAVOR | NOARC_FLAVOR, CRASH_FLAVOR, "Send Crash " );
718 PutDirects( DIRECT_FLAVOR | NOARC_FLAVOR, DIRECT_FLAVOR, "Send Direct " );
719 PutDirects( HOLD_FLAVOR | NOARC_FLAVOR, HOLD_FLAVOR, "Send Hold " );
720 PutDirects( NORMAL_FLAVOR | NOARC_FLAVOR, NORMAL_FLAVOR, "Send Normal " );
721 PutDirects( CRASH_FLAVOR | NOARC_FLAVOR, CRASH_FLAVOR | NOARC_FLAVOR, "Send Crash NoArc " );
722 PutDirects( DIRECT_FLAVOR | NOARC_FLAVOR, DIRECT_FLAVOR | NOARC_FLAVOR, "Send Direct NoArc " );
723 PutDirects( HOLD_FLAVOR | NOARC_FLAVOR, HOLD_FLAVOR | NOARC_FLAVOR, "Send Hold NoArc " );
724 PutDirects( NORMAL_FLAVOR | NOARC_FLAVOR, NORMAL_FLAVOR | NOARC_FLAVOR, "Send Normal NoArc " );
725 }
726
PutRoutingSq(void)727 static void PutRoutingSq( void )
728 {
729 StarWild = false;
730 AddPoint = false;
731 DefaultFromMe = false;
732 FullAddr = false;
733 FillRoute = false;
734 WithSlash = false;
735 fprintf( NewRoute, CREATED, ';', "Squish", MyNode->z, MyNode->n, MyNode->f,
736 ';', ctime( &currtime ), ';' );
737 Spit( "; *** Direct links" EOLCHR ";" );
738 DirectsSQ( );
739 Spit( ";" EOLCHR "; *** Route" EOLCHR ";" );
740 for( level = 0; level < 4; level++ )
741 {
742 fprintf( NewRoute, "; *** %s" EOLCHR "", RouteType[level] );
743 if( level )
744 DirectsSQ( );
745 for( ushort i = 0; i < nLinks; i++ )
746 {
747 MakeSqPrefix( Link + i, Prefix );
748 strcpy( Buff, Prefix );
749 PutDownLinks( InMemory( Link[i].addr ), 0 );
750 if( strcmp( Buff, Prefix ) != 0 )
751 Spit( Buff ); // Spit short but significant line
752 }
753 }
754 }
755
756
757 // Make Routing for ITrack
758 const char *ItrFlavors[] = {
759 "Crash", "Dir ", "Hold ", " "
760 };
761
PutRoutingItr(void)762 static void PutRoutingItr( void )
763 {
764 StarWild = true;
765 AddPoint = true;
766 DefaultFromMe = false;
767 FullAddr = true;
768 FillRoute = false;
769 WithSlash = false;
770 fprintf( NewRoute, CREATED, ';', "iTrack", MyNode->z, MyNode->n, MyNode->f,
771 ';', ctime( &currtime ), ';' );
772 for( level = 0; level < 4; level++ )
773 {
774 int i;
775 fprintf( NewRoute, "; *** %s" EOLCHR "", RouteType[level] );
776 for( i = 0; i < nLinks; i++ )
777 {
778 strcpy( Prefix, ( char * ) GetFlavor( Link + i, ItrFlavors ) );
779 WriteNode( Link[i].addr, Prefix, 1 );
780 strcat( Prefix, " " );
781 strcpy( Buff, Prefix );
782 WriteNode( Link[i].addr, Buff, 0 );
783 PutDownLinks( InMemory( Link[i].addr ), 0 );
784 if( strcmp( Buff, Prefix ) != 0 ) // We added any downlinks
785 Spit( Buff ); // Spit short but significant line
786 }
787 }
788 }
789
790
791 // Make Routing for T-mail
DirectsTmail(void)792 static void DirectsTmail( void )
793 {
794 AddPoint = true;
795 PrevNode = *MyNode; // Main AKA
796 PutDirects( CRASH_FLAVOR, CRASH_FLAVOR, "Direct " );
797 PutDirects( DIRECT_FLAVOR, DIRECT_FLAVOR, "Direct " );
798 PutDirects( NORMAL_FLAVOR, NORMAL_FLAVOR, "Direct " );
799 PutDirects( HOLD_FLAVOR, HOLD_FLAVOR, "Direct " );
800 AddPoint = false;
801 PutDirects( CRASH_FLAVOR, CRASH_FLAVOR, "Priority " );
802 PutDirects( HOLD_FLAVOR, HOLD_FLAVOR, "Hold " );
803 }
804
PutRoutingTmail(void)805 static void PutRoutingTmail( void )
806 {
807 StarWild = true;
808 AddPoint = false;
809 DefaultFromMe = true;
810 FullAddr = false;
811 FillRoute = false;
812 WithSlash = true;
813 fprintf( NewRoute, CREATED, ';', "T-mail", MyNode->z, MyNode->n, MyNode->f,
814 ';', ctime( &currtime ), ';' );
815 Spit( "; *** Direct links" );
816 DirectsTmail( );
817 for( level = 0; level < 4; level++ )
818 {
819 fprintf( NewRoute, "; *** %s" EOLCHR "", RouteType[level] );
820 if( level )
821 DirectsTmail( );
822 int i;
823 for( i = 0; i < nLinks; i++ )
824 {
825 if( TmailAddFor )
826 strcpy( Prefix, "Mail-For " );
827 else
828 strcpy( Prefix, "Mail " );
829 strcpy( Buff, Prefix );
830 UpNode = Link[i].addr;
831 PutDownLinks( InMemory( Link[i].addr ), 0 );
832 if( strcmp( Buff, Prefix ) != 0 )
833 {
834 WriteNode( UpNode, Buff, 1 );
835 Spit( Buff ); // Spit short but significant line
836 }
837 // 'Files'
838 if( Link[i].flavor & FILE_FLAVOR )
839 {
840 if( TmailAddFor )
841 strcpy( Prefix, "Files-For " );
842 else
843 strcpy( Prefix, "Files " );
844 strcpy( Buff, Prefix );
845 UpNode = Link[i].addr;
846 PutDownLinks( InMemory( Link[i].addr ), 0 );
847 if( strcmp( Buff, Prefix ) != 0 )
848 {
849 WriteNode( UpNode, Buff, 1 );
850 Spit( Buff ); // Spit short but significant line
851 }
852 }
853 }
854 }
855 }
856
857
858 // Make Routing for BPACK
DirectsBpack(void)859 static void DirectsBpack( void )
860 {
861 PrevNode = *MyNode;
862 PutDirects( CRASH_FLAVOR, CRASH_FLAVOR, "Direct crash " );
863 PutDirects( DIRECT_FLAVOR, DIRECT_FLAVOR, "Direct direct " );
864 PutDirects( NORMAL_FLAVOR, NORMAL_FLAVOR, "Direct " );
865 PutDirects( HOLD_FLAVOR, HOLD_FLAVOR, "Direct hold " );
866 PutDirects( NOARC_FLAVOR, NOARC_FLAVOR, "NoArcSend " );
867 }
868
PutRoutingBpack(void)869 static void PutRoutingBpack( void )
870 {
871 StarWild = true;
872 AddPoint = false;
873 DefaultFromMe = false;
874 FullAddr = true;
875 FillRoute = false;
876 WithSlash = false;
877 fprintf( NewRoute, CREATED, ';', "BPack", MyNode->z, MyNode->n, MyNode->f,
878 ';', ctime( &currtime ), ';' );
879 Spit( "; *** Direct links" );
880 DirectsBpack( );
881 for( level = 0; level < 4; level++ )
882 {
883 fprintf( NewRoute, "; *** %s" EOLCHR "", RouteType[level] );
884 if( level )
885 DirectsBpack( );
886 int i;
887 for( i = 0; i < nLinks; i++ )
888 {
889 strcpy( Prefix, "Route " );
890 strcat( Prefix, GetFlavor( Link + i, SqFlavors ) );
891 WriteNode( Link[i].addr, Prefix, 1 );
892 strcat( Prefix, " " );
893 strcpy( Buff, Prefix );
894 PutDownLinks( InMemory( Link[i].addr ), 0 );
895 if( strcmp( Buff, Prefix ) != 0 )
896 Spit( Buff ); // Spit short but significant line
897 }
898 }
899 }
900
901
902 // Make Routing for IMBINK
PutRoutingImb(void)903 static void PutRoutingImb( void )
904 {
905 StarWild = true;
906 AddPoint = true;
907 DefaultFromMe = false;
908 FullAddr = false;
909 FillRoute = false;
910 WithSlash = false;
911 CmntSym = '#';
912 fprintf( NewRoute, CREATED, '#', "Imbink", MyNode->z, MyNode->n, MyNode->f,
913 '#', ctime( &currtime ), '#' );
914 PutDirects( FILE_FLAVOR, FILE_FLAVOR, "FSENDTO " );
915 PutDirects( NOARC_FLAVOR, 0, "Compress ZIP " );
916 for( level = 0; level < 4; level++ )
917 {
918 fprintf( NewRoute, "# *** %s" EOLCHR "", RouteType[level] );
919 int i;
920 for( i = 0; i < nLinks; i++ )
921 {
922 strcpy( Prefix, "Static " );
923 strcat( Prefix, GetFlavor( Link + i, SqFlavors ) );
924 WriteNode( Link[i].addr, Prefix, 1 );
925 strcat( Prefix, " " );
926 strcpy( Buff, Prefix );
927 WriteNode( Link[i].addr, Buff, 0 );
928 PutDownLinks( InMemory( Link[i].addr ), 0 );
929 if( strcmp( Buff, Prefix ) != 0 )
930 Spit( Buff ); // Spit short but significant line
931 }
932 }
933 }
934
935
936 // Make Routing for XMAIL
PutRoutingXmail(void)937 static void PutRoutingXmail( void )
938 {
939 StarWild = false;
940 AddPoint = false;
941 DefaultFromMe = false;
942 FullAddr = true;
943 FillRoute = false;
944 WithSlash = false;
945 CmntSym = ';';
946 fprintf( NewRoute, CREATED, ';', "Xmail", MyNode->z, MyNode->n, MyNode->f,
947 ';', ctime( &currtime ), ';' );
948 fprintf( NewRoute, "; *** Directs" EOLCHR "" );
949 level = 0;
950 int i;
951 for( i = 0; i < nLinks; i++ )
952 {
953 Buff[0] = 0;
954 WriteNode( Link[i].addr, Buff, 0 );
955 if( Buff[0] )
956 Spit( Buff + 1 );
957 }
958 for( level = 0; level < 4; level++ )
959 {
960 fprintf( NewRoute, "; *** %s" EOLCHR "", RouteType[level] );
961 ushort i;
962 if( level )
963 {
964 for( i = 0; i < nLinks; i++ )
965 {
966 Buff[0] = 0;
967 WriteNode( Link[i].addr, Buff, 0 );
968 if( Buff[0] )
969 Spit( Buff + 1 );
970 }
971 }
972 for( i = 0; i < nNodes; i++ )
973 {
974 Buff[0] = 0;
975 if( Node[i].idx != WILDVALUE && Node[i].idx != ( WILDVALUE - 1 ) && !DirectLink( i ) )
976 {
977 WriteNode( Node[i].addr, Buff, 0 );
978 if( Buff[0] )
979 {
980 strcat( Buff, " VIA " );
981 WriteNode( Node[Node[i].idx].addr, Buff, 1 );
982 strcat( Buff, " /NC" );
983 Spit( Buff + 1 );
984 }
985 }
986 }
987 }
988 }
989
990
991 // Make Routing for ifmail
GetIfFlavor(link * pLink)992 static const char *GetIfFlavor( link * pLink )
993 {
994 if( pLink->flavor & CRASH_FLAVOR )
995 return "c";
996
997 else if( pLink->flavor & DIRECT_FLAVOR )
998 return "n";
999
1000 else if( pLink->flavor & HOLD_FLAVOR )
1001 return "h";
1002
1003 else
1004 return "n";
1005 }
1006
AddInt(char * where,ushort value)1007 static char *AddInt( char *where, ushort value )
1008 {
1009 itoa( value, where, 10 );
1010 return ( where + strlen( where ) );
1011 }
1012
WriteIfNode(nodeaddr Node,char * out,ushort wmode)1013 static boolean WriteIfNode( nodeaddr Node, char *out, ushort wmode )
1014 {
1015 char *p = out + strlen( out );
1016 ushort wildlevel = 0;
1017 if( Node.f == WILDVALUE )
1018 wildlevel++;
1019 if( Node.n == WILDVALUE )
1020 wildlevel++;
1021 if( Node.z == WILDVALUE )
1022 wildlevel++;
1023 if( wildlevel == level || wmode )
1024 {
1025 if( Node.f != WILDVALUE )
1026 {
1027 *p++ = 'f';
1028 p = AddInt( p, Node.f );
1029 *p = '.';
1030 *( ++p ) = '\0';
1031 }
1032 if( Node.n != WILDVALUE )
1033 {
1034 *p++ = 'n';
1035 p = AddInt( p, Node.n );
1036 *p = '.';
1037 *( ++p ) = '\0';
1038 }
1039 if( Node.z != WILDVALUE )
1040 {
1041 *p++ = 'z';
1042 p = AddInt( p, Node.z );
1043 *p++ = '.';
1044 }
1045 strcpy( p, "fidonet.org" );
1046 return true;
1047 }
1048 else
1049 return false;
1050 }
1051
PutRoutingIfmail(void)1052 static void PutRoutingIfmail( void )
1053 {
1054 StarWild = false;
1055 AddPoint = false;
1056 DefaultFromMe = false;
1057 FullAddr = true;
1058 FillRoute = false;
1059 WithSlash = false;
1060 CmntSym = '#';
1061 fprintf( NewRoute, CREATED, '#', "sendmail", MyNode->z, MyNode->n,
1062 MyNode->f, '#', ctime( &currtime ), '#' );
1063 for( level = 0; level < 4; level++ )
1064 {
1065 fprintf( NewRoute, "# *** %s" EOLCHR "", RouteType[level] );
1066 ushort i;
1067 for( i = 0; i < nNodes; i++ )
1068 {
1069 Buff[0] = 0;
1070 if( Node[i].idx != WILDVALUE && // routed
1071 Node[i].idx != ( WILDVALUE - 1 ) && // not joined with wildcard
1072 ( Node[Node[i].idx].idx != WILDVALUE &&
1073 Node[Node[i].idx].idx != WILDVALUE - 1 ||
1074 DirectLink( Node[i].idx ) ) && !IsMyNode( Node[Node[i].idx].addr ) || DirectLink( i ) )
1075 {
1076 strcpy( Buff, "." );
1077 if( WriteIfNode( Node[i].addr, Buff, 0 ) )
1078 {
1079 listitem Dest;
1080 strcat( Buff, "\tifmail-" );
1081 Dest = DirectLink( i ) ? Node[i] : Node[Node[i].idx];
1082 int j;
1083 for( j = 0; j < nLinks; j++ )
1084 if( Link[j].addr == Dest.addr )
1085 strcat( Buff, GetIfFlavor( Link + j ) );
1086 strcat( Buff, ":" );
1087 WriteIfNode( Dest.addr, Buff, 1 );
1088 if( !level )
1089 Spit( Buff + 1 );
1090 Spit( Buff );
1091 }
1092 }
1093 }
1094 }
1095 }
1096
1097
1098 // Make Routing for BiP
1099 const char *BipFlavors[] = {
1100 "Crash", "Dir ", "Hold ", "Norm "
1101 };
1102
PutRoutingBip(void)1103 static void PutRoutingBip( void )
1104 {
1105 StarWild = true;
1106 AddPoint = true;
1107 DefaultFromMe = true;
1108 FullAddr = false;
1109 FillRoute = false;
1110 WithSlash = false;
1111 fprintf( NewRoute, CREATED, ';', "BiP", MyNode->z, MyNode->n, MyNode->f,
1112 ';', ctime( &currtime ), ';' );
1113 for( level = 3; level != 0xFFFF; level-- )
1114 {
1115 fprintf( NewRoute, "; *** %s" EOLCHR "", RouteType[level] );
1116 int i;
1117 for( i = 0; i < nLinks; i++ )
1118 {
1119 strcpy( Prefix, "Route" );
1120 strcat( Prefix, ( char * ) GetFlavor( Link + i, BipFlavors ) );
1121 WriteNode( Link[i].addr, Prefix, 1 );
1122 strcat( Prefix, " " );
1123 strcpy( Buff, Prefix );
1124 WriteNode( Link[i].addr, Buff, 0 );
1125 PutDownLinks( InMemory( Link[i].addr ), 0 );
1126 if( strcmp( Buff, Prefix ) != 0 )
1127 Spit( Buff ); // Spit short but significant line
1128 if( Link[i].flavor & FILE_FLAVOR )
1129 {
1130 strcpy( Prefix, "File" );
1131 strcat( Prefix, GetFlavor( Link + i, BipFlavors ) );
1132 WriteNode( Link[i].addr, Prefix, 1 );
1133 strcat( Prefix, " " );
1134 strcpy( Buff, Prefix );
1135 WriteNode( Link[i].addr, Buff, 0 );
1136 PutDownLinks( InMemory( Link[i].addr ), 0 );
1137 if( strcmp( Buff, Prefix ) != 0 )
1138 Spit( Buff ); // Spit short but significant line
1139 }
1140 }
1141 }
1142 }
1143
1144
1145 // Make Routing for Unimail
PutRoutingUnimail(void)1146 static void PutRoutingUnimail( void )
1147 {
1148 StarWild = true;
1149 AddPoint = true;
1150 DefaultFromMe = false;
1151 FullAddr = true;
1152 FillRoute = false;
1153 WithSlash = false;
1154 fprintf( NewRoute, CREATED, ';', "Unimail", MyNode->z, MyNode->n, MyNode->f,
1155 ';', ctime( &currtime ), ';' );
1156 Spit( ";" EOLCHR "; *** Route" EOLCHR ";" );
1157 for( level = 0; level < 4; level++ )
1158 {
1159 fprintf( NewRoute, "; *** %s" EOLCHR "", RouteType[level] );
1160 int i;
1161 for( i = 0; i < nLinks; i++ )
1162 {
1163 strcpy( Prefix, "Route" );
1164 strcat( Prefix, GetFlavor( Link + i, SqFlavors ) );
1165 WriteNode( Link[i].addr, Prefix, 1 );
1166 strcpy( Buff, Prefix );
1167 WriteNode( Link[i].addr, Buff, 0 );
1168 PutDownLinks( InMemory( Link[i].addr ), 0 );
1169 if( strcmp( Buff, Prefix ) != 0 )
1170 Spit( Buff ); // Spit short but significant line
1171 }
1172 }
1173 }
1174
1175
1176 // Make Routing for QECHO
WriteNodeQecho(nodeaddr Node,char * out,ushort addrtype)1177 ushort WriteNodeQecho( nodeaddr Node, char *out, ushort addrtype )
1178 {
1179 char tmp[20];
1180 ushort wildlevel = 0;
1181 if( Node.f == WILDVALUE )
1182 wildlevel++;
1183 if( Node.n == WILDVALUE )
1184 wildlevel++;
1185 if( Node.z == WILDVALUE )
1186 wildlevel++;
1187 if( wildlevel == level || addrtype == 1 )
1188 {
1189 if( wildlevel == 3 )
1190 {
1191 strcat( out, "1: 2: 3: 4: 5: 6: 7:" );
1192 }
1193 else
1194 {
1195 strcat( out, " " );
1196 strcat( out, itoa( Node.z, tmp, 10 ) );
1197 strcat( out, ":" );
1198 if( wildlevel < 2 )
1199 {
1200 strcat( out, itoa( Node.n, tmp, 10 ) );
1201 }
1202 if( wildlevel < 1 )
1203 {
1204 strcat( out, "/" );
1205 strcat( out, itoa( Node.f, tmp, 10 ) );
1206 }
1207 }
1208 }
1209 return ushort( strlen( out ) );
1210 }
1211
PutRoutingQecho(void)1212 static void PutRoutingQecho( void )
1213 {
1214 StarWild = false;
1215 AddPoint = false;
1216 DefaultFromMe = false;
1217 FullAddr = true;
1218 FillRoute = false;
1219 WithSlash = false;
1220 CmntSym = '#';
1221 MAX_ROUTE_LEN = 100;
1222 fprintf( NewRoute, CREATED, '#', "QECHO", MyNode->z, MyNode->n, MyNode->f,
1223 '#', ctime( &currtime ), '#' );
1224 Spit( "#" EOLCHR "# *** Route" EOLCHR "#" );
1225 for( level = 0; level < 3; level++ )
1226 {
1227 fprintf( NewRoute, "# *** %s" EOLCHR "", RouteType[level] );
1228 int i;
1229 for( i = 0; i < nLinks; i++ )
1230 {
1231 sprintf( Prefix, "RouteVia\t%d:%d/%d@fidonet" EOLCHR "RouteFor\t",
1232 Link[i].addr.z, Link[i].addr.n, Link[i].addr.f );
1233 strcpy( Buff, Prefix );
1234 if( level == 0 )
1235 {
1236 WriteNodeQecho( Link[i].addr, Buff, 1 );
1237 }
1238 PutDownLinksGeneric( InMemory( Link[i].addr ), 0, WriteNodeQecho );
1239 if( strcmp( Buff, Prefix ) != 0 )
1240 {
1241 Spit( Buff ); // Spit non-empty line
1242 }
1243 }
1244 }
1245 }
1246
1247
1248 // Make Routing for Fidogate
1249 const char *FidogateFlavors[] = {
1250 "crash ", "direct", "hold ", "normal"
1251 };
1252
MakeFidogatePrefix(link * pLink,char * out)1253 static void MakeFidogatePrefix( link * pLink, char *out )
1254 {
1255 strcpy( out, "route " );
1256 strcat( out, ( char * ) GetFlavor( pLink, FidogateFlavors ) );
1257
1258 if( pLink->flavor & FILE_FLAVOR )
1259 strcat( out, " file" );
1260 else
1261 strcat( out, " " );
1262
1263 if( pLink->flavor & NOARC_FLAVOR )
1264 strcat( out, " noarc" );
1265 else
1266 strcat( out, " " );
1267
1268 WriteNode( pLink->addr, out, 1 );
1269 strcat( out, " " );
1270 }
1271
DirectsFidogate(void)1272 static void DirectsFidogate( void )
1273 {
1274 PutDirects( CRASH_FLAVOR, CRASH_FLAVOR, "send crash " );
1275 PutDirects( DIRECT_FLAVOR, DIRECT_FLAVOR, "send direct " );
1276 PutDirects( HOLD_FLAVOR, HOLD_FLAVOR, "send hold " );
1277 PutDirects( NORMAL_FLAVOR, NORMAL_FLAVOR, "send normal " );
1278 }
1279
PutRoutingFidogate(void)1280 static void PutRoutingFidogate( void )
1281 {
1282 StarWild = false;
1283 AddPoint = false;
1284 DefaultFromMe = false;
1285 FullAddr = true;
1286 FillRoute = false;
1287 WithSlash = false;
1288 CmntSym = '#';
1289 fprintf( NewRoute, CREATED, CmntSym, "Fidogate", MyNode->z, MyNode->n,
1290 MyNode->f, '#', ctime( &currtime ), '#' );
1291 Spit( "# *** Direct links" EOLCHR "#" );
1292 DirectsFidogate( );
1293 Spit( "#" EOLCHR "# *** Route" EOLCHR "#" );
1294 for( level = 0; level < 4; level++ )
1295 {
1296 fprintf( NewRoute, "# *** %s" EOLCHR "", RouteType[level] );
1297 if( level )
1298 DirectsFidogate( );
1299 for( ushort i = 0; i < nLinks; i++ )
1300 {
1301 MakeFidogatePrefix( Link + i, Prefix );
1302 strcpy( Buff, Prefix );
1303 PutDownLinks( InMemory( Link[i].addr ), 0 );
1304 if( strcmp( Buff, Prefix ) != 0 )
1305 Spit( Buff ); // Spit short but significant line
1306 }
1307 }
1308 }
1309
1310 // Make Routing for FTRACK
1311 static int counter = 0;
WriteNodeFtrack(nodeaddr Node,char * out,ushort addrtype)1312 ushort WriteNodeFtrack( nodeaddr Node, char *out, ushort addrtype )
1313 {
1314 static const char *prefix = "Mask: * * * ";
1315 static const char *postfix = " * *";
1316 ushort wildlevel = 0;
1317 if( Node.f == WILDVALUE )
1318 wildlevel++;
1319 if( Node.n == WILDVALUE )
1320 wildlevel++;
1321 if( Node.z == WILDVALUE )
1322 wildlevel++;
1323 if( wildlevel == level || addrtype == 1 )
1324 {
1325 counter++;
1326 strcpy( out, prefix );
1327 if( level == 3 )
1328 strcat( out, "*" );
1329 else
1330 WriteNode( Node, out + strlen( prefix ), addrtype );
1331 strcat( out, postfix );
1332 }
1333 else if( wildlevel == 1 && addrtype == 0 && level == 0 )
1334 {
1335 strcpy( out, prefix );
1336 WriteNode( Node, out + strlen( prefix ), 1 );
1337 strcat( out, postfix );
1338 }
1339 return ushort( strlen( out ) );
1340 }
1341
PutRoutingFtrack(void)1342 static void PutRoutingFtrack( void )
1343 {
1344 StarWild = true;
1345 AddPoint = true;
1346 DefaultFromMe = true;
1347 FullAddr = true;
1348 FillRoute = false;
1349 WithSlash = true;
1350 CmntSym = '\\';
1351 Prefix[0] = CmntSym;
1352 Prefix[1] = 0;
1353 nodeaddr tmpNode;
1354 MAX_ROUTE_LEN = 10;
1355 fprintf( NewRoute, CREATED, CmntSym, "Ftrack", MyNode->z, MyNode->n,
1356 MyNode->f, CmntSym, ctime( &currtime ), CmntSym );
1357 for( level = 0; level < 4; level++ )
1358 {
1359 counter = 0;
1360 fprintf( NewRoute, "%c *** %s" EOLCHR "", CmntSym, RouteType[level] );
1361 int i;
1362 for( i = 0; i < nLinks; i++ )
1363 {
1364 counter = 0;
1365 Buff[0] = 0;
1366 if( level == 0 )
1367 {
1368 WriteNodeFtrack( Link[i].addr, Buff, 0 );
1369 Spit( Buff );
1370 counter++;
1371 Buff[0] = 0;
1372 }
1373 PutDownLinksGeneric( InMemory( Link[i].addr ), 0, WriteNodeFtrack );
1374 if( counter )
1375 {
1376 sprintf( Buff, "Action: Route %s", GetFlavor( Link + i, SqFlavors ) );
1377 AddPoint = false;
1378 tmpNode = Link[i].addr;
1379 if( DirectLink( tmpNode ) && MyNode->z == tmpNode.z && MyNode->n == tmpNode.n
1380 && tmpNode.f == WILDVALUE )
1381 {
1382 strcat( Buff, "%.0" );
1383 }
1384 else
1385 {
1386 WriteNode( Link[i].addr, Buff, 1 );
1387 }
1388 AddPoint = true;
1389 strcat( Buff, "\n\\" );
1390 Spit( Buff );
1391 }
1392 }
1393 }
1394 }
1395
1396 // Make Routing for HPT
1397 const char *HuskyFlavors[] = {
1398 "crash", "direct", "hold", "normal"
1399 };
1400
PutRoutingHusky(void)1401 static void PutRoutingHusky( void )
1402 {
1403 StarWild = true;
1404 AddPoint = true;
1405 DefaultFromMe = false;
1406 FullAddr = true;
1407 FillRoute = false;
1408 WithSlash = false;
1409 CmntSym = '#';
1410 fprintf( NewRoute, CREATED, '#', "Husky", MyNode->z, MyNode->n, MyNode->f,
1411 '#', ctime( &currtime ), '#' );
1412 for( level = 0; level < 4; level++ )
1413 {
1414 fprintf( NewRoute, "# *** %s" EOLCHR "", RouteType[level] );
1415 int i;
1416 for( i = 0; i < nLinks; i++ )
1417 {
1418 strcpy( Prefix, "route " );
1419 strcat( Prefix, ( char * ) GetFlavor( Link + i, HuskyFlavors ) );
1420 WriteNode( Link[i].addr, Prefix, 1 );
1421 strcpy( Buff, Prefix );
1422 WriteNode( Link[i].addr, Buff, 0 );
1423 PutDownLinks( InMemory( Link[i].addr ), 0 );
1424 if( strcmp( Buff, Prefix ) != 0 )
1425 Spit( Buff );
1426 }
1427 }
1428 }
1429
1430 //-----------------------------------------------------------------
PutUnRouted(void)1431 static void PutUnRouted( void )
1432 {
1433 FillRoute = true;
1434 FullAddr = true;
1435 fprintf( NewRoute,
1436 "%c" EOLCHR "%c !!! Undefined !!!" EOLCHR "%c ----------------"
1437 EOLCHR "", CmntSym, CmntSym, CmntSym );
1438 level = 0;
1439 Prefix[0] = CmntSym;
1440 Prefix[1] = 0;
1441 strcat( Prefix, " >>> " );
1442 strcpy( Buff, Prefix );
1443 PutDownLinks( WILDVALUE, 0 );
1444 if( strcmp( Buff, Prefix ) != 0 )
1445 Spit( Buff ); // Spit short but significant line
1446 }
1447
1448
1449 // Config parser
LoadAddress(char * p,void *)1450 static boolean LoadAddress( char *p, void * )
1451 {
1452 MyNode[nAKAs++] = ScanNode( &p );
1453 return true;
1454 }
1455
GetRouteType(char * p,void *)1456 static boolean GetRouteType( char *p, void * )
1457 {
1458 if( strnicmp( p, "squish", 6 ) == 0 )
1459 RouteMode = SQUISH;
1460
1461 else if( strnicmp( p, "itrack", 6 ) == 0 )
1462 RouteMode = ITRACK;
1463
1464 else if( strnicmp( p, "tmail", 5 ) == 0 )
1465 {
1466 RouteMode = TMAIL;
1467 if( ( strnicmp( p, "tmailn", 6 ) == 0 ) )
1468 TmailAddFor = true;
1469 else
1470 TmailAddFor = false;
1471 }
1472
1473 else if( strnicmp( p, "bpack", 5 ) == 0 )
1474 RouteMode = BPACK;
1475
1476 else if( strnicmp( p, "imbink", 6 ) == 0 )
1477 RouteMode = IMBINK;
1478
1479 else if( strnicmp( p, "xmail", 5 ) == 0 )
1480 RouteMode = XMAIL;
1481
1482 else if( strnicmp( p, "ifmail", 6 ) == 0 )
1483 RouteMode = IFMAIL;
1484
1485 else if( strnicmp( p, "bip", 3 ) == 0 )
1486 RouteMode = BIP;
1487
1488 else if( strnicmp( p, "unimail", 7 ) == 0 )
1489 RouteMode = UNIMAIL;
1490
1491 else if( strnicmp( p, "qecho", 5 ) == 0 )
1492 RouteMode = QECHO;
1493
1494 else if( strnicmp( p, "fidogate", 8 ) == 0 )
1495 RouteMode = FIDOGATE;
1496
1497 else if( strnicmp( p, "ftrack", 6 ) == 0 )
1498 RouteMode = FTRACK;
1499
1500 else if( strnicmp( p, "husky", 5 ) == 0 )
1501 RouteMode = HUSKY;
1502
1503 else
1504 {
1505 ErrorL( ErrUnknownRouteType );
1506 return false;
1507 }
1508 return true;
1509 }
1510
GetBoolean(char * p,void * target)1511 static boolean GetBoolean( char *p, void *target )
1512 {
1513 if( strnicmp( p, "yes", 3 ) == 0 || strnicmp( p, "on", 2 ) == 0 || strnicmp( p, "1", 1 ) == 0 )
1514 *( ushort * ) target = 1;
1515
1516 else if( strnicmp( p, "no", 2 ) == 0 || strnicmp( p, "off", 3 ) == 0
1517 || strnicmp( p, "0", 1 ) == 0 )
1518 *( ushort * ) target = 0;
1519
1520 else
1521 {
1522 ErrorL( ErrUnknownMinType );
1523 return false;
1524 }
1525 return true;
1526 }
1527
GetFile(char * p,void * Name)1528 static boolean GetFile( char *p, void *Name )
1529 {
1530 char *p1 = ( char * ) Name;
1531 while( !isspace( *p ) )
1532 *( p1++ ) = *( p++ );
1533 *p1 = 0;
1534 return true;
1535 }
1536
GetQuotedString(char * p,void * str)1537 static boolean GetQuotedString( char *p, void *str )
1538 {
1539 char *p1 = ( char * ) str;
1540 if( *p == '\"' )
1541 {
1542 p++;
1543 while( *p != '\"' )
1544 {
1545 if( *p == '\n' || *p == '\0' )
1546 {
1547 ErrorL( ErrQuoteString );
1548 return false;
1549 }
1550 else
1551 *( p1++ ) = *( p++ );
1552 }
1553 *p1 = 0;
1554 }
1555 return true;
1556 }
1557
GetDestFile(char * p,void * Name)1558 static boolean GetDestFile( char *p, void *Name )
1559 {
1560 GetFile( p, Name );
1561 if( ( OldRoute = fopen( ( char * ) Name, "rt" ) ) == NULL )
1562 {
1563 Error( ErrOpenDest );
1564 return false;
1565 }
1566
1567 if( TempFile[0] == '\0' )
1568 {
1569 #if !defined(__GNUC__)
1570 fnsplit( ( char * ) Name, OutDrv, OutDir, OutName, OutExt );
1571 fnmerge( TempFile, OutDrv, OutDir, "MK$ROUTE", "$$$" );
1572 #else
1573 strcpy( TempFile, ( char * ) Name );
1574 strcat( TempFile, ".$$$" );
1575 #endif
1576 }
1577
1578 if( ( NewRoute = fopen( TempFile, "wt" ) ) == NULL )
1579 {
1580 // Error(ErrOpenTmp);
1581 ErrorS( ErrOpenTmpX, TempFile );
1582 return false;
1583 }
1584 boolean ReplaceArea = false;
1585 size_t beglen = strlen( RouteBegin );
1586 size_t endlen = strlen( RouteEnd );
1587 while( fgets( Buff, BUFFLEN - 1, OldRoute ) )
1588 {
1589 if( !ReplaceArea )
1590 fputs( Buff, NewRoute );
1591 if( strncmp( Buff, RouteBegin, beglen ) == 0 )
1592 ReplaceArea = true;
1593 if( ReplaceArea && ( strncmp( Buff, RouteEnd, endlen ) == 0 ) )
1594 return true;
1595 }
1596 Error( ReplaceArea ? ErrNoReplEnd : ErrNoReplBeg );
1597 fclose( OldRoute );
1598 fclose( NewRoute );
1599 unlink( TempFile );
1600 return false;
1601 }
1602
GetFlavor(char * p,void * mask)1603 static boolean GetFlavor( char *p, void *mask )
1604 {
1605 while( *p != '\n' && *p != '\0' && *p != ';' )
1606 {
1607 if( tolower( *p ) == 'd' )
1608 *( ushort * ) mask |= DIRECT_FLAVOR;
1609
1610 else if( tolower( *p ) == 'c' )
1611 *( ushort * ) mask |= CRASH_FLAVOR;
1612
1613 else if( tolower( *p ) == 'h' )
1614 *( ushort * ) mask |= HOLD_FLAVOR;
1615
1616 else if( tolower( *p ) == 'n' )
1617 *( ushort * ) mask |= NORMAL_FLAVOR;
1618
1619 else if( tolower( *p ) == 'f' )
1620 *( ushort * ) mask |= FILE_FLAVOR;
1621
1622 else if( tolower( *p ) == 'a' )
1623 *( ushort * ) mask |= NOARC_FLAVOR;
1624 p++;
1625 }
1626 if( ( *( ushort * ) mask & ( DIRECT_FLAVOR | CRASH_FLAVOR | HOLD_FLAVOR ) ) == 0 )
1627 *( ushort * ) mask |= NORMAL_FLAVOR;
1628 return true;
1629 }
1630
GetLink(char * p,void *)1631 static boolean GetLink( char *p, void * )
1632 {
1633 memset( Link + nLinks, 0, sizeof( Link[0] ) );
1634 Link[nLinks].addr = ScanNode( &p );
1635 GetFlavor( p, &Link[nLinks].flavor );
1636 if( InMemory( Link[nLinks].addr ) == WILDVALUE ) // Not in Node[]
1637 {
1638 Node[nNodes].addr = Link[nLinks].addr;
1639 Node[nNodes++].idx = WILDVALUE;
1640 }
1641 nLinks++;
1642 return true;
1643 }
1644
StoreUplink(nodeaddr tmpNode)1645 static ushort StoreUplink( nodeaddr tmpNode )
1646 {
1647 ushort Uplink = InMemory( tmpNode );
1648 if( Uplink == WILDVALUE ) // Not in memory yet
1649 {
1650 Uplink = nNodes;
1651 Node[nNodes].addr = tmpNode;
1652 Node[nNodes].is_uplink = true;
1653 Node[nNodes++].idx = WILDVALUE;
1654 }
1655 return Uplink;
1656 }
1657
StoreDownLink(ushort Uplink,nodeaddr tmpNode)1658 static void StoreDownLink( ushort Uplink, nodeaddr tmpNode )
1659 {
1660 if( !IsMyNode( tmpNode ) )
1661 {
1662 ushort Downlink = InMemory( tmpNode );
1663 if( !( Downlink == Uplink ) )
1664 {
1665 if( Downlink == WILDVALUE ) // New node
1666 {
1667 Downlink = nNodes;
1668 Node[nNodes].addr = tmpNode;
1669 Node[nNodes++].idx = Uplink;
1670 }
1671 else
1672 {
1673 if( Node[Downlink].idx != WILDVALUE && // Already routed
1674 Node[Downlink].idx != Uplink ) // differently
1675 {
1676 ErrorS( ErrReroute, StrNode( tmpNode ) );
1677 }
1678 Node[Downlink].idx = Uplink;
1679 }
1680 Node[Downlink].is_uplink = false;
1681 }
1682 }
1683 }
1684
GetRouteStr(char * p,void *)1685 static boolean GetRouteStr( char *p, void * )
1686 {
1687 boolean ViaRoute;
1688 skipws( &p );
1689 if( !( *p == ';' || *p == '\n' || *p == '\0' ) )
1690 {
1691 PrevNode = *MyNode; // Main AKA
1692 if( *p == '>' ) // 'via'-routing
1693 {
1694 p++;
1695 skipws( &p );
1696 ViaRoute = true;
1697 }
1698 else
1699 ViaRoute = false;
1700 nodeaddr tmpNode = ScanNode( &p );
1701 if( ViaRoute )
1702 {
1703 if( IsMyNode( tmpNode ) )
1704 {
1705 tmpNode = ScanNode( &p ); // skip myself
1706 StoreDownLink( StoreUplink( MyNode[0] ), tmpNode );
1707 }
1708 else if( KillTransit )
1709 {
1710 ScanNode( &p ); // skip transit node
1711 }
1712 }
1713 ushort Uplink = StoreUplink( tmpNode );
1714 while( *p != '\n' && *p != '\0' && *p != ';' )
1715 {
1716 tmpNode = ScanNode( &p );
1717 StoreDownLink( Uplink, tmpNode );
1718 skipws( &p );
1719 }
1720 }
1721 return true;
1722 }
1723
GetRouteFile(char * p,void *)1724 static boolean GetRouteFile( char *p, void * )
1725 {
1726 char Name[100];
1727 GetFile( p, Name );
1728 FILE *nodes;
1729 if( ( nodes = fopen( Name, "rt" ) ) != NULL )
1730 {
1731 fprintf( stderr, "" EOLCHR "Scanning route file %s...", Name );
1732 while( fgets( Buff, BUFFLEN, nodes ) )
1733 GetRouteStr( Buff, NULL );
1734 fclose( nodes );
1735 return true;
1736 }
1737 else
1738 {
1739 ErrorL( ErrNoFile );
1740 return false;
1741 }
1742 }
1743
GetTrustStr(char * p,void *)1744 static boolean GetTrustStr( char *p, void * )
1745 {
1746 if( !( *p == ';' || *p == '\n' || *p == '\0' ) )
1747 {
1748 PrevNode = *MyNode; // Main AKA
1749 nodeaddr tmpNode = ScanNode( &p ); // scan network
1750 while( *p != '\n' && *p != '\0' && *p != ';' )
1751 {
1752 nodeaddr TrustedNode = ScanNode( &p );
1753 if( DirectLink( TrustedNode ) )
1754 {
1755 ushort idx = StoreUplink( TrustedNode );
1756 StoreDownLink( idx, tmpNode );
1757 }
1758 skipws( &p );
1759 }
1760 }
1761 return true;
1762 }
1763
GetTrustFile(char * p,void *)1764 static boolean GetTrustFile( char *p, void * )
1765 {
1766 char Name[100];
1767 GetFile( p, Name );
1768 FILE *nodes;
1769 if( ( nodes = fopen( Name, "rt" ) ) != NULL )
1770 {
1771 fprintf( stderr, "" EOLCHR "Scanning route file %s...", Name );
1772 while( fgets( Buff, BUFFLEN, nodes ) )
1773 GetTrustStr( Buff, NULL );
1774 fclose( nodes );
1775 return true;
1776 }
1777 else
1778 {
1779 ErrorL( ErrNoFile );
1780 return false;
1781 }
1782 }
1783
1784 const char *Dash = "-/|\\";
1785 static ushort DashCnt = 0;
1786
DrawDash(void)1787 static void DrawDash( void )
1788 {
1789 putc( Dash[DashCnt++], stderr );
1790 putc( '\b', stderr );
1791 DashCnt &= 3;
1792 }
1793
GetHubRoute(char * p,void *)1794 static boolean GetHubRoute( char *p, void * )
1795 {
1796 char Name[MAXPATH];
1797 FILE *ndl;
1798 strcpy( Name, strtok( p, " \t" ) );
1799
1800 #if !defined(__GNUC__)
1801 fnsplit( Name, OutDrv, OutDir, OutName, OutExt );
1802 #endif
1803
1804 if( strchr( Name, '?' ) || strchr( Name, '*' ) )
1805 {
1806 short maxext = ( -1 );
1807
1808 #if defined (__TSC__)
1809 short ext;
1810 int rc;
1811 ffblk ff;
1812 for( rc = findfirst( Name, &ff, 0 ); rc != ( -1 ); rc = findnext( &ff ) )
1813 {
1814 char bb[MAXFILE];
1815 strcpy( bb, ff.ff_name );
1816 *( strrchr( bb, '.' ) ) = '\0';
1817 char *p1 = bb;
1818 char *p2 = bb + strlen( bb ) + 1;
1819 ext = atoi( p2 );
1820 if( ext > maxext )
1821 {
1822 maxext = ext;
1823 strcpy( OutName, p1 );
1824 strcpy( OutExt, p2 );
1825 }
1826 }
1827 #elif defined (__MSVC__)
1828 long handle;
1829 int rc;
1830 struct _finddata_t fdata;
1831 short ext;
1832 if((handle = _findfirst( Name, &fdata )) != -1L)
1833 {
1834 do
1835 {
1836 char bb[MAXFILE];
1837 strcpy( bb, fdata.name );
1838 *( strrchr( bb, '.' ) ) = '\0';
1839 char *p1 = bb;
1840 char *p2 = bb + strlen( bb ) + 1;
1841 ext = (short)atoi( p2 );
1842 if( ext > maxext )
1843 {
1844 maxext = ext;
1845 strcpy( OutName, p1 );
1846 strcpy( OutExt, p2 );
1847 }
1848 rc = _findnext( handle, &fdata );
1849 } while(rc != -1);
1850 }
1851 #elif defined (__WATCOMC__)
1852 short ext;
1853 DIR *ff;
1854 if( ( ff = opendir( Name ) ) != 0 )
1855 {
1856 while( readdir( ff ) != NULL )
1857 {
1858 char bb[MAXFILE];
1859 strcpy( bb, ff->d_name );
1860 *( strrchr( bb, '.' ) ) = '\0';
1861 char *p1 = bb;
1862 char *p2 = bb + strlen( bb ) + 1;
1863 ext = ( short ) atoi( p2 );
1864 if( ext > maxext )
1865 {
1866 maxext = ext;
1867 strcpy( OutName, p1 );
1868 strcpy( OutExt, p2 );
1869 }
1870 }
1871 closedir( ff );
1872 }
1873 #endif
1874
1875 #if defined (__GNUC__)
1876 if( !glob( Name, GLOB_ERR, NULL, &globbuf ) )
1877 maxext = 0;
1878 #endif
1879
1880 if( maxext > ( -1 ) ) // found!
1881 #if !defined(__GNUC__)
1882 fnmerge( Name, OutDrv, OutDir, OutName, OutExt );
1883 #else
1884 {
1885 strcpy( Name, globbuf.gl_pathv[globbuf.gl_pathc - 1] );
1886 globfree( &globbuf );
1887 }
1888 #endif
1889 else
1890 {
1891 ErrorL( ErrNoFile );
1892 return false;
1893 }
1894 }
1895 if( ( ndl = fopen( Name, "rt" ) ) == NULL )
1896 {
1897 ErrorL( ErrNoFile );
1898 return false;
1899 }
1900 else
1901 {
1902 setvbuf( ndl, NULL, _IOFBF, 0x8000 ); // Max buffering for speed
1903 char *p1 = strtok( NULL, " \t" ); // possible ndl type
1904 if( strlen( p1 ) != 1 )
1905 {
1906 ErrorL( ErrBadNdlType );
1907 fclose( ndl );
1908 return false;
1909 }
1910 else
1911 {
1912 ushort level, found = 0, z, n, f, Uplink;
1913 switch ( toupper( *p1 ) )
1914 {
1915 case 'Z':
1916 level = 0;
1917 break;
1918 case 'R':
1919 case 'N':
1920 level = 1;
1921 found = 1;
1922 break;
1923 default:
1924 ErrorL( ErrBadNdlType );
1925 fclose( ndl );
1926 return false;
1927 }
1928 p1 = strtok( NULL, " \t" );
1929 if( p1 == NULL )
1930 {
1931 ErrorL( ErrBadNdlType );
1932 fclose( ndl );
1933 return false;
1934 }
1935 ushort mz = ( ushort ) atoi( p1 );
1936 p1 = strtok( NULL, " \t" );
1937 if( p1 == NULL )
1938 {
1939 ErrorL( ErrBadNdlType );
1940 fclose( ndl );
1941 return false;
1942 }
1943 ushort mn = ( ushort ) atoi( p1 );
1944 fprintf( stderr, "" EOLCHR "Scanning nodelist %s for %d:%d hubroute...", Name, mz, mn );
1945 ushort count = 0;
1946 ushort step = level ? 20 : 1000;
1947 while( fgets( Buff, BUFFLEN, ndl ) != NULL )
1948 {
1949 if( ++count > step )
1950 {
1951 DrawDash( );
1952 count = 0;
1953 }
1954 if( Buff[0] != ';' )
1955 {
1956 if( level == 0 && strnicmp( Buff, "zone", 4 ) == 0 )
1957 {
1958 found = 0;
1959 if( ( z = ( ushort ) atoi( Buff + 5 ) ) == mz )
1960 found |= 0x01;
1961 }
1962 else if( ( found & 0x01 ) && strnicmp( Buff, "region", 6 ) == 0 )
1963 {
1964 found &= 0x01;
1965 if( ( n = ( ushort ) atoi( Buff + 7 ) ) == mn )
1966 found |= 0x02;
1967 }
1968 else if( ( found & 0x01 ) && strnicmp( Buff, "host", 4 ) == 0 )
1969 {
1970 found &= 0x01;
1971 if( ( n = ( ushort ) atoi( Buff + 5 ) ) == mn )
1972 found |= 0x02;
1973 }
1974 else if( ( found & 0x3 ) == 3 && strnicmp( Buff, "hub", 3 ) == 0 )
1975 {
1976 found &= 0x03;
1977 f = ( ushort ) atoi( Buff + 4 );
1978 found |= 0x04;
1979 }
1980 else if( ( found & 0x03 ) == 3 )
1981 {
1982 found |= 0x08;
1983 if( strnicmp( Buff, "pvt", 3 ) == 0 )
1984 f = ( ushort ) atoi( Buff + 4 );
1985 else if( ( strnicmp( Buff, "hold", 4 ) == 0 ) || ( strnicmp( Buff, "down", 4 ) == 0 ) )
1986 f = ( ushort ) atoi( Buff + 5 );
1987 else if( Buff[0] == ',' )
1988 f = ( ushort ) atoi( Buff + 1 );
1989 else
1990 {
1991 found &= 7;
1992 continue;
1993 }
1994 }
1995 if( found == 3 ) // host routing
1996 Uplink = StoreUplink( nodeaddr( level ? mz : z, n, 0 ) );
1997 else if( found == 7 ) // hub routing
1998 Uplink = StoreUplink( nodeaddr( level ? mz : z, n, f ) );
1999 else if( found >= 0x0B ) // node
2000 StoreDownLink( Uplink, nodeaddr( level ? mz : z, n, f ) );
2001 }
2002 }
2003 }
2004 }
2005 fclose( ndl );
2006 return true;
2007 }
2008
2009
2010 #define CFG_PASSES 6
2011 static CfgValue CfgTab[] = {
2012 {"Address", NULL, 1, LoadAddress}
2013 ,
2014 {"Hubroute", NULL, 3, GetHubRoute}
2015 ,
2016 {"RouteFile", NULL, 3, GetRouteFile}
2017 ,
2018 {"TrustFile", NULL, 4, GetTrustFile}
2019 ,
2020 {"RouteType", &RouteMode, 1, GetRouteType}
2021 ,
2022 {"WriteTo", WriteTo, 2, GetDestFile}
2023 ,
2024 {"Minimize", &MinMode, 1, GetBoolean}
2025 ,
2026 {"KillTransit", &KillTransit, 1, GetBoolean}
2027 ,
2028 {"DefaultFlavor", &DefaultFlavor, 2, GetFlavor}
2029 ,
2030 {"DefaultRoute", NULL, 5, GetRouteStr}
2031 ,
2032 {"Link", NULL, 2, GetLink}
2033 ,
2034 {"RouteBegin", RouteBegin, 1, GetQuotedString}
2035 ,
2036 {"RouteEnd", RouteEnd, 1, GetQuotedString}
2037 ,
2038 {"TempFile", TempFile, 1, GetFile}
2039 };
2040
PassOK(ushort Pass)2041 static boolean PassOK( ushort Pass )
2042 {
2043 switch ( Pass )
2044 {
2045 case 0:
2046 break;
2047 case 1:
2048 // Existing main address
2049 if( MyNode->z == 0 || MyNode->n == 0 )
2050 {
2051 Error( ErrMissMainAddr );
2052 return false;
2053 }
2054 // Existing RouteType keyword
2055 if( !RouteMode )
2056 {
2057 Error( ErrMissRouteType );
2058 return false;
2059 }
2060 // Existing "Minimize"
2061 if( MinMode == 2 )
2062 Error( ErrMissMinType );
2063 break;
2064 case 2:
2065 case 3:
2066 case 4:
2067 break;
2068 case 5:
2069 fprintf( stderr, EOLCHR "Adjusting routing..." );
2070 FixWildcard( );
2071 RemoveUnnecessary( );
2072 break;
2073 }
2074 return true;
2075 }
2076
LoadConfig(void)2077 static boolean LoadConfig( void )
2078 {
2079 FILE *cfg;
2080 boolean KeyWordFailed;
2081 if( ( cfg = fopen( CfgFile, "rt" ) ) != 0 )
2082 {
2083 char tmp[50];
2084 fprintf( stderr, "" EOLCHR "Scanning config file... " );
2085 ushort i;
2086 for( i = 0; i < CFG_PASSES; i++ )
2087 {
2088 CfgLine = 0;
2089 KeyWordFailed = false;
2090 while( fgets( Buff, BUFFLEN - 1, cfg ) )
2091 {
2092 CfgLine++;
2093 char *p = Buff;
2094 skipws( &p );
2095 if( *p == '#' || *p == ';' || *p == '\n' || *p == '\0' )
2096 continue; // skip blank line or comment
2097 char *p1 = tmp;
2098 while( !isspace( *p ) )
2099 *( p1++ ) = *( p++ );
2100 *p1 = 0;
2101 unsigned int j;
2102 for( j = 0; j < ItemNum( CfgTab ); j++ )
2103 {
2104 if( CfgTab[j].Pass == i && stricmp( CfgTab[j].Name, tmp ) == 0 )
2105 {
2106 skipws( &p );
2107 KeyWordFailed |= !CfgTab[j].LoadVal( p, CfgTab[j].Value );
2108 }
2109 }
2110 }
2111 if( KeyWordFailed || !PassOK( i ) )
2112 {
2113 fclose( cfg );
2114 return false;
2115 }
2116 rewind( cfg );
2117 }
2118 fclose( cfg );
2119 return true;
2120 }
2121 else
2122 Error( ErrOpenCfg );
2123 return false;
2124 }
2125
main(int argc,char ** argv)2126 int main( int argc, char **argv )
2127 {
2128 char REVISION[] = "$Revision$";
2129 REVISION[strlen(REVISION)-1]=0;
2130 if( strlen(REVISION) > 10 )
2131 strcpy(REVISION,REVISION+10);
2132 else
2133 REVISION[0]=0;
2134 fprintf( stderr,
2135 "Hubroute generator v." VERSION "(" TARGET ")%s%s" EOLCHR
2136 "Copyright (c) 1994-2003 Yuri Safronov 2:5020/204" EOLCHR
2137 "Copyright (c) 2009-2016 Husky Project development team" EOLCHR,
2138 REVISION[0]?"rev.":"", REVISION );
2139 if( argc > 1 )
2140 {
2141 if( !stricmp( argv[1], "--help" ) || !stricmp( argv[1], "-h" ) || !stricmp( argv[1], "/h" ) )
2142 {
2143 fprintf( stderr, "" EOLCHR "Usage: fidoroute [config.file]" EOLCHR "" );
2144 return 0;
2145 }
2146 }
2147 PrevNode.CleanUp( );
2148
2149 // Allocate buffers
2150 Buff = ( char * ) malloc( BUFFLEN );
2151 Prefix = ( char * ) malloc( 500 );
2152 Node = ( listitem * ) calloc( MAXNODES, sizeof( listitem ) );
2153 Link = ( link * ) calloc( MAXLINKS, sizeof( link ) );
2154 CfgFile = ( char * ) calloc( 1, PATHLEN );
2155 MyNode = ( nodeaddr * ) calloc( MAXAKAS, sizeof( nodeaddr ) );
2156 if( Buff == NULL || Prefix == NULL || Node == NULL || Link == NULL
2157 || CfgFile == NULL || MyNode == NULL )
2158 {
2159 Error( ErrNoMemory );
2160 return 2;
2161 }
2162 else
2163 {
2164 nNodes = 0;
2165 nLinks = 0;
2166 TempFile[0] = '\0';
2167 if( argc == 1 )
2168 #if defined(__DJGPP__) || defined(__OS2__) || defined(__NT__)
2169 strcpy( CfgFile, "fidoroute.cfg" );
2170 #else
2171 strcpy( CfgFile, "fidoroute.conf" );
2172 #endif
2173 else
2174 strcpy( CfgFile, argv[1] );
2175 if( LoadConfig( ) )
2176 {
2177 fprintf( stderr, "" EOLCHR "Writing routing... " );
2178 time( &currtime );
2179 switch ( RouteMode )
2180 {
2181 case SQUISH:
2182 PutRoutingSq( );
2183 break;
2184 case ITRACK:
2185 PutRoutingItr( );
2186 break;
2187 case TMAIL:
2188 PutRoutingTmail( );
2189 break;
2190 case BPACK:
2191 PutRoutingBpack( );
2192 break;
2193 case IMBINK:
2194 PutRoutingImb( );
2195 break;
2196 case XMAIL:
2197 PutRoutingXmail( );
2198 break;
2199 case IFMAIL:
2200 PutRoutingIfmail( );
2201 break;
2202 case BIP:
2203 PutRoutingBip( );
2204 break;
2205 case UNIMAIL:
2206 PutRoutingUnimail( );
2207 break;
2208 case QECHO:
2209 PutRoutingQecho( );
2210 break;
2211 case FIDOGATE:
2212 PutRoutingFidogate( );
2213 break;
2214 case FTRACK:
2215 PutRoutingFtrack( );
2216 break;
2217 case HUSKY:
2218 PutRoutingHusky( );
2219 break;
2220 }
2221 PutUnRouted( );
2222 Spit( RouteEnd );
2223 while( fgets( Buff, BUFFLEN - 1, OldRoute ) )
2224 fputs( Buff, NewRoute );
2225 fclose( OldRoute );
2226 fclose( NewRoute );
2227 unlink( WriteTo );
2228 rename( TempFile, WriteTo );
2229 fprintf( stderr, "" EOLCHR "Done - %d rules for %d links." EOLCHR "", nNodes, nLinks );
2230 return 0;
2231 }
2232 else
2233 return 1;
2234 }
2235 }
2236