1 /*****************************************************************************/
2 /*                                                                           */
3 /*                 (C) Copyright 1992-1997  Alberto Pasquale                 */
4 /*                 Portions (C) Copyright 1999 Per Lundberg                  */
5 /*                                                                           */
6 /*                   A L L   R I G H T S   R E S E R V E D                   */
7 /*                                                                           */
8 /*****************************************************************************/
9 /*                                                                           */
10 /* How to contact the author:  Alberto Pasquale of 2:332/504@fidonet         */
11 /*                             Viale Verdi 106                               */
12 /*                             41100 Modena                                  */
13 /*                             Italy                                         */
14 /*                                                                           */
15 /*****************************************************************************/
16 
17 #include "apgenlib.hpp"
18 #include <limits.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <ctype.h>
22 #include "crc16.hpp"
23 #include "data.hpp"
24 #include "inpblk.hpp"
25 #include "misc.hpp"
26 #include "cfgdata.hpp"
27 #include "parse.hpp"
28 #include "field.hpp"
29 #include "parsetyp.hpp"
30 #include "export.hpp"
31 #include "inmem.hpp"
32 
33 const char UnpublishedPhone[] = "-Unpublished-";
34 
InpAll(InpAll * ia)35 InpAll::InpAll (InpAll *ia)
36 {
37     Init (ia);
38 }
39 
Init(InpAll * ia)40 void InpAll::Init (InpAll *ia)
41 {
42     if (ia) {
43         *this = *ia;
44         ArcMethHead = CopyArcMethod (ia->ArcMethHead);
45         ArcDiffMethHead = CopyArcMethod (ia->ArcDiffMethHead);
46     } else
47         memset (this, 0, sizeof (*this));
48 }
49 
50 
InpNnc(InpNnc * in)51 InpNnc::InpNnc (InpNnc *in)
52 {
53     if (in)
54         *this = *in;
55     else
56         memset (this, 0, sizeof (*this));
57 }
58 
59 
InpOut(void)60 InpOut::InpOut (void)
61 {
62     memset (this, 0, sizeof (*this));
63 }
64 
65 
InpLoc(void)66 InpLoc::InpLoc (void)
67 {
68     memset (this, 0, sizeof (*this));
69 }
70 
71 
InpVar(void)72 InpVar::InpVar (void)
73 {
74     memset (this, 0, sizeof (*this));
75     crcchk = TRUE;
76 }
77 
78 
InpSave(void)79 InpSave::InpSave (void)
80 {
81     Init ();
82 }
83 
84 
Init()85 void InpSave::Init ()
86 {
87     memset (this, 0, sizeof (*this));
88     NodeDay = -1;
89 }
90 
91 
InpncBlk(InpAll * ia)92 InpncBlk::InpncBlk (InpAll *ia)
93 {
94     a = new InpAll (ia);
95     l = new InpLoc;
96     v = new InpVar;
97     s = new InpSave;
98     next = NULL;
99 }
100 
101 
savinit(void)102 void InpncBlk::savinit (void)
103 {
104     s->Init ();
105 }
106 
107 
INPBLK(InpAll * ia,InpNnc * in,SegAll * isa)108 INPBLK::INPBLK (InpAll *ia, InpNnc *in, SegAll *isa)      // constructor initializer
109 {
110     a->Init (ia);
111     n = new InpNnc (in);
112     o = new InpOut;
113     sa = new SegAll (isa);
114     SegExpHead = NULL;
115 }
116 
117 
Process(OUTCUR * ocp,OUTBLK * cob,BOOL * SomeNeeded)118 BOOL INPBLK::Process (OUTCUR *ocp, OUTBLK *cob, BOOL *SomeNeeded)
119 {
120     INPCUR inpcur (o);
121 
122     Open (&inpcur);
123 
124     if (n->BeforeCompile)
125         RunCmd (n->BeforeCompile, RCf, "l", l->NodeList);
126 
127     BOOL ret = ProcessFile (l->NodeList, &inpcur, ocp, cob, SomeNeeded);
128     writersp (MsgLogRsp, "\"%s\" processed%s\r\r", l->NodeList, ret ? "." : " with ERRORS.");
129 
130     if (n->AfterCompile)
131         RunCmd (n->AfterCompile, RCf, "l", l->NodeList);
132 
133     Close (&inpcur);
134 
135     return ret;
136 }
137 
138 
TxtHeader(INPCUR * icp)139 static void TxtHeader (INPCUR *icp)
140 {
141     if (icp->txt_pagenum != 0) {
142         if (icp->nodelist_txt)
143             fprintf (icp->nodelist_txt, "");
144         if (icp->nodelist_prn)
145             fprintf (icp->nodelist_prn, "");
146     }
147     icp->txt_pagenum ++;
148     if (icp->nodelist_txt)
149         fprintf (icp->nodelist_txt, "%s %-4hd\n\n", icp->header, icp->txt_pagenum);
150     if (icp->nodelist_prn)
151         fprintf (icp->nodelist_prn, "%s %-4hd\n\n", icp->header, icp->txt_pagenum);
152     icp->txt_pg_lines = 2;
153 }
154 
155 
TxtLine(INPCUR * icp,char * text)156 static void TxtLine (INPCUR *icp, char *text)
157 {
158     icp->txt_pg_lines ++;
159     if (icp->nodelist_txt)
160         fprintf (icp->nodelist_txt, "%s\n", text);
161     if (icp->nodelist_prn)
162         fprintf (icp->nodelist_prn, "%s\n", text);
163 }
164 
165 
MkSysopComma(pcsz sysopname,char * sysop_comma)166 static void MkSysopComma (pcsz sysopname, char *sysop_comma)
167 {
168     int l = strlen (sysopname);
169 
170     if (l > SYSOPSIZE-2) {
171         strcpy (sysop_comma, "Too_Long, Name");
172         return;
173     }
174 
175     if (l == 0) {
176         strcpy (sysop_comma, "Empty, Name");
177         return;
178     }
179 
180     pcsz lastname = strrchr (sysopname, '_');
181     if (lastname)
182         lastname ++;
183     else
184         lastname = sysopname;
185 
186     char *d = fl_stpcpy (sysop_comma, lastname);
187 
188     if (sysopname != lastname) {    /* if there is a first name */
189         const char *s = sysopname;
190         lastname--;     /* skip blank that precede last name */
191         *d++ = ',';
192         *d++ = ' ';
193         while (s < lastname) {
194             if (*s == '_') {        // change underscore to blank
195                 *d++ = ' ';
196                 s++;
197             } else
198                 *d++ = *s++;
199         }
200         *d = '\0';
201     }
202 }
203 
204 
Pack(word * outp,char * inp,byte * count)205 static void Pack (word *outp, char *inp, byte *count)
206 {
207                                  /* for name compression */
208     static byte unwrk[84] = {
209         28,  0,  0,  0,  0,  0, 27,  0,  0,     // ' ( 39) -> / ( 47)
210         29, 30, 31, 32, 33, 34, 35, 36, 37, 38, // 0 ( 48) -> 9 ( 57)
211          0,  0,  0,  0,  0,  0,  0,             // : ( 58) -> @ ( 64)
212          2, 12, 10, 13,  1, 21, 16, 11,         // A ( 65) -> H ( 72)
213          8, 23, 18,  9, 14,  3,  5, 17,         // I ( 73) -> P ( 80)
214         26,  4,  6,  7, 15, 22, 20, 24,         // Q ( 81) -> X ( 88)
215         19, 25,  0,  0,  0,  0,  0, 28,         // Y ( 89) -> ` ( 96)
216          2, 12, 10, 13,  1, 21, 16, 11,         // a ( 97) -> h (104)
217          8, 23, 18,  9, 14,  3,  5, 17,         // i (105) -> p (112)
218         26,  4,  6,  7, 15, 22, 20, 24,         // q (113) -> x (120)
219         19, 25 };                               // y (121) -> z (122)
220 
221 
222     char c;
223     word totcode = 0;
224     short j = 0;
225     *count = 0;
226 
227     while ((c = (char) (*inp++)) != 0) {
228         word code;
229         if ((c < 39) || (c > 122))
230             code = 0;
231         else
232             code = unwrk[c-39];
233         totcode = (word)((word)(totcode * 40) + code);
234         j++;
235         if (j == 3) {
236             *outp++ = totcode;
237             (*count) += 2;
238             j = 0;
239             totcode = 0;
240         }
241     }
242 
243     if (j != 0) {
244         for (; j < 3; j++)
245             totcode = (word)(totcode * 40);
246         *outp = totcode;
247         (*count) += 2;
248     }
249 
250 }
251 
252 
Open(INPCUR * icp)253 void INPBLK::Open (INPCUR *icp)
254 {
255     if (n->FidoTxt || n->FidoPrn) {
256         if (n->FidoTxt)
257             icp->nodelist_txt = SmartOpen (n->FidoTxt, "");
258         if (n->FidoPrn)
259             icp->nodelist_prn = SmartOpen (n->FidoPrn, "");
260     }
261 }
262 
263 
Close(INPCUR * icp)264 void INPBLK::Close (INPCUR *icp)
265 {
266 
267     if (icp->nodelist_prn)
268         fclose (icp->nodelist_prn);
269     if (icp->nodelist_txt)
270         fclose (icp->nodelist_txt);
271 
272 }
273 
274 
InSegment(const EXTADR * adr,ADRLST * cobIncAddr,ADRLST * cobExcAddr,ADRLST * IncAddr,ADRLST * ExcAddr)275 BOOL INPBLK::InSegment (const EXTADR *adr, ADRLST *cobIncAddr, ADRLST *cobExcAddr, ADRLST *IncAddr, ADRLST *ExcAddr)
276 {
277     if (cobIncAddr)
278         if (!InPartAdrLst (adr, cobIncAddr))
279             return FALSE;
280 
281     if (cobExcAddr)
282         if (InPartAdrLst (adr, cobExcAddr))
283             return FALSE;
284 
285     if (IncAddr)
286         if (!InPartAdrLst (adr, IncAddr))
287             return FALSE;
288 
289     if (ExcAddr)
290         if (InPartAdrLst (adr, ExcAddr))
291             return FALSE;
292 
293     return TRUE;
294 }
295 
296 
297 
WantRem(char * MsgRem,char * rem)298 static BOOL WantRem (char *MsgRem, char *rem)
299 {
300     if (!MsgRem)
301         return FALSE;           // No MsgRem statement
302     if (*rem == '\0')           // Empty Comment
303         return FALSE;
304     if (*MsgRem == '\0')        // MsgRem with no char list: all comments
305         return TRUE;
306     if (*rem == ' ')            // "; word" comment
307         return (strchr (MsgRem, ';') != NULL);
308     if (*(rem+1) != ' ')                    // ";word" comment
309         return (strchr (MsgRem, ';') != NULL);
310     return (strchr (MsgRem, *rem) != NULL);     // ";<l>" comment
311 }
312 
313 
314 
315                 // for GetPhoneType
316 
317 
318 #define PT_PSTN             0x01
319 #define PT_Unpublished      0x02
320 #define PT_Verbatim         0x03
321 #define PT_FIDOIP           0x04
322 
323 
GetPhoneType(pcsz phone)324 static int GetPhoneType (pcsz phone)
325 {
326     if (*phone == '\0')
327         return PT_Unpublished;
328 
329     int numlen = strspn (phone, "-0123456789");
330     if (phone[numlen] == '\0') {
331         if (strncmp (phone, "000-", 4) == 0)
332             return PT_FIDOIP;
333         return PT_PSTN;
334     }
335 
336     if (stricmp (phone, UnpublishedPhone) == 0)
337         return PT_Unpublished;
338 
339     return PT_Verbatim;
340 }
341 
342 
MkPhone(pcsz orig_phone,psz phone)343 CO *MkPhone (pcsz orig_phone, psz phone)
344 {
345     CO *co = NULL;
346     DL *dl = dl_head;
347     while (dl) {
348         char *pp = strdcmp (orig_phone, dl->mstr);
349         if (pp) {   // first part match (area code)
350             bool match;
351 
352             if (dl->Exchange_head) {  // exch to match
353                 match = false;
354                 StrChain *ple = dl->Exchange_head;
355                 do {
356                     if (strdcmp (pp, ple->text)) { // is Local
357                         match = true;
358                         break;
359                     }
360                     ple = ple->next;
361                 } while (ple);
362             } else                  // no exch to match
363                 match = true;
364 
365             if (match) {
366                 strzcat (phone, PHONESIZE, dl->pre, pp, dl->post, NULL);
367                 if (dl->co)
368                     co = dl->co;
369                 break;
370             }
371 
372         }
373         dl = dl->next;
374     }
375 
376     return co;
377 }
378 
379 
380 
ProcessFile(char * fname,INPCUR * icp,OUTCUR * ocp,OUTBLK * cob,BOOL * SomeNeeded)381 BOOL INPBLK::ProcessFile (char *fname, INPCUR *icp, OUTCUR *ocp, OUTBLK *cob, BOOL *SomeNeeded)
382 {
383 
384     char    PackBuf[LINESIZE];
385     byte    buffer[sizeof(_vers7) + LINESIZE];
386     _vers7  *vers7 = (_vers7 *) buffer;
387 
388     word    official_crc = 0, calc_crc = 0;
389     FILE    *f;
390     word    n_num;
391     word    n_cost, u_cost;
392     byte    n_modem;
393     dword   n_baud;
394     int     coord_lev, cur_addr_lev;
395     char    def_phone[PHONESIZE];
396     byte    def_modem = 0;
397     word    def_cost = 0, def_ucost = 0;
398     dword   def_baud = 0;
399     word    def_flags = 0;
400     char    buff[LINESIZE]; char verbuff[LINESIZE]; char *p, *q, *r;
401     char    *modifier, *boardname, *cityname,
402             *sysopname; /* no comma */
403     char    phone[PHONESIZE], phonendx[PHONESIZE];
404     char    sysop_comma[SYSOPSIZE];  // SysOp Name: "LastName[, FirstName]"
405     int     pnt, hold;
406     int     tmplen;
407     ADRDATA *ph, *pw, *ad;
408 
409     char *origline = NULL; // pointer to original nodelist line
410 
411 
412     if (SegExpHead) {
413         if (SEGEXPORT::OpenAll (SegExpHead, s->NodeTime, s->NodeDay, fname))
414             *SomeNeeded = TRUE;
415         origline = new char[LINESIZE];
416     }
417 
418     BOOL SegmentSel = cob->o->IncAddr || cob->o->ExcAddr || o->IncAddr || o->ExcAddr;
419 
420 
421            // initialization for "constant" variables
422 
423     char *sysop4ndx = (cob->l->v7data.sysopndx || cob->l->FidoUserLst) ?
424                       sysop_comma : NullStr;
425 
426     char const *phone4ndx = (cob->l->v7data.flags & V7PDX_F) ? phonendx : NullStr;
427 
428 
429 
430            //
431 
432     ADRDATA *def_pw = NULL;
433     *def_phone = '\0';
434 
435     cur_addr_lev = NONE;
436     if ((f = fopen (fname, "rb")) == NULL) {
437         vprintlog ("Could not open Nodelist File \"%s\"\n", fname);
438         myexit (NO_NODELIST);
439     }
440     setvbuf (f, NULL, _IOFBF, BufSize);
441 
442     if (!fgets (buff, LINESIZE, f)) {
443         vprintlog ("Could not read Nodelist File \"%s\"\n", fname);
444         fclose (f);
445         myexit (NO_NODELIST);
446     }
447 
448     if (strncmp (buff, ";A ", 3) == 0)
449         p = strrchr (buff, ':');
450     else
451         p = NULL;
452 
453     if (p) {
454         if (v->crcchk) {
455             official_crc = (word) atoi (p+1);
456             calc_crc = 0;
457         }
458         strzcpy (icp->header, buff + 3, HeaderSize - 8);
459         p = strrchr (icp->header, ':');
460         if (!p)
461             p = icp->header + strlen (icp->header);
462         strcpy (p, "- P");
463 
464         if(!fgets (buff, LINESIZE, f)) {
465             vprintlog ("Empty Nodelist File \"%s\"\n", fname);
466             myexit (NO_NODELIST);
467         }
468     } else {
469         v->crcchk = FALSE;
470         strcpy (icp->header, "Private List - P");
471     }
472 
473     TxtHeader (icp);
474 
475     vprintlogrsp (MsgLogRsp, "Processing \"%s\"\n", fname);
476 
477     if (n->MsgRem)
478         writersp (MsgRemRsp, "\r\rComments in \"%s\"\r\r", fname);
479 
480                         /* set initial defaults */
481     EXTADR adr = l->PartAddr;
482     if ((n->flags & GermanPointLst) && (adr.zone == word(-1)))
483         adr.zone = 2;
484 
485     do {            /* while fgets */
486         if (buff[0] == 0x1A)        // ^Z
487             break;
488         if (v->crcchk)
489             calc_crc = crcstr (buff, calc_crc, &tmplen);
490         else
491             tmplen = strlen (buff);
492 
493         if (tmplen < 2)        // skip empty lines
494             continue;
495 
496         p = buff + tmplen - 2; // remove trailing CR+LF
497         if (*p == '\r')
498             *p = '\0';
499 
500         strcpy (verbuff, buff); // make verbatim copy of nodelist line
501 
502         pnt = 0;
503         coord_lev = NONE;
504         hold = 0;
505 
506         p = buff;
507 
508         if (*p == ';') {
509             p ++;
510             if (n->MsgRem)
511                 if (WantRem (n->MsgRem, p))
512                     writersp (MsgRemRsp, "%s\r", p);
513             if ((*p == 'A') || (*p == 'F') || (*p == 'U'))
514                 TxtLine (icp, p+1);
515             continue;
516         }
517 
518         if (SegExpHead)
519             strcpy (origline, p);
520 
521         /* Modifier (Host, Region, etc.) */
522         modifier = nextfield (p);
523         fl_strupr (modifier);
524 
525         /* Node number (or region or zone) */
526         p = nextfield (NULL);
527         n_num = (word) atoi (p);
528 
529         if (n_num == 0)
530             continue;     // if empty line don't overwrite coord !
531 
532         /* Did we get anything? */
533         if (*modifier) { /* Is it something we need to worry about? */
534             if (strcmp (modifier, "ZONE") == 0) {
535                 ocp->nzones ++;
536                 coord_lev = ZONE;
537             } else if (strcmp (modifier, "REGION") == 0) {
538                 if (!(n->flags & GermanPointLst))
539                     ocp->nregions ++;
540                 coord_lev = REGION;
541             } else if (strcmp (modifier, "HOST") == 0) {
542                 if (!(n->flags & GermanPointLst))
543                     ocp->nnets ++;
544                 coord_lev = HOST;
545             } else if (strcmp (modifier, "HUB") == 0) {
546                 ocp->nhubs ++;
547                 coord_lev = HUB;
548             } else if (strcmp (modifier, "BOSS") == 0) {
549                 /* It is a PointList Boss */
550                 coord_lev = BOSS;
551             } else if (strcmp (modifier, "NODE") == 0) {
552                 /* It is a node address */
553                 coord_lev = NODE;
554             } else if (strcmp (modifier, "POINT") == 0) {
555                 pnt = 1;
556             } else if (strcmp (modifier, "PVT") == 0) {
557                 /* It is just a private node */
558                 *modifier = '\0';
559             } else if (strcmp (modifier, "HOLD") == 0) {
560                 *modifier = '\0';
561                 hold = 1;
562             } else if (strcmp (modifier, "DOWN") == 0) {
563                 ocp->ndown ++;
564                 continue;
565             } else {
566                 ocp->nunknown ++;
567                 continue;
568             }
569         }
570 
571         /* Board name */
572         boardname = nextfield (NULL);
573 
574 
575         if (coord_lev == NONE) {
576             if (cur_addr_lev == BOSS)
577                 pnt = 1;
578             if (!pnt) {
579                 adr.node = n_num;
580                 adr.point = 0;
581             } else
582                 adr.point = n_num;
583         } else {
584             cur_addr_lev = coord_lev;
585             adr.point = 0;
586             switch (coord_lev) {
587 
588                 case ZONE:
589                     adr.zone = n_num;
590                     adr.region = 0;
591                     goto HostLabel;
592 
593                 case REGION:
594                     if (n->flags & GermanPointLst)
595                         continue;
596                     adr.region = n_num;
597 
598                 case HOST:
599    HostLabel:       adr.hub = 0;
600                     if (n->flags & GermanPointLst) {
601                         get_addr_2d (boardname, &adr);  // get net/node from system name
602                         cur_addr_lev = BOSS;
603                     } else {
604                         adr.net = n_num;
605                         adr.node = 0;
606                     }
607                     printflush ("%5hd:%-5hd\r", adr.zone, adr.net);
608                     if (n->flags & GermanPointLst)
609                         continue;
610                     break;
611 
612                 case HUB:
613                     adr.hub = adr.node = n_num;
614                     break;
615 
616                 case BOSS:
617                 case NODE:
618 
619                     strcpy (def_phone, "");
620                     def_flags = 0;
621                     def_baud = 300;
622                     def_modem = 0;
623                     def_cost = CostNullPhone.cost;
624                     def_ucost = CostNullPhone.ucost;
625                     def_pw = NULL;
626                     get_addr ((const char **)&p, &adr);
627                     adr.region = adr.hub = 0;
628 
629                     if (coord_lev == BOSS) {
630                         printflush ("%5hd:%-5hd          \r", adr.zone, adr.net);
631                         continue;   /* stop here */
632                     } else {     // NODE
633                         sscanf (p, "%hu %hu", &adr.region, &adr.hub);
634                         coord_lev = NONE;
635                         break;
636                     }
637             }
638         }
639 
640         if (adr.point) {
641             ocp->npoints ++;
642             pnt = 1;
643         } else {
644             ocp->nnodes ++;
645             pnt = 0;
646         }
647 
648         if (SegExpHead)
649             SEGEXPORT::WriteAll (SegExpHead, &adr, origline);
650 
651         if (SegmentSel)
652             if (!InSegment (&adr, cob->o->IncAddr, cob->o->ExcAddr, o->IncAddr, o->ExcAddr) &&
653                 (coord_lev < n->IncCoord)) {
654                 ocp->nexcluded ++;
655                 continue;
656             }
657 
658         /* Location */
659         cityname = nextfield (NULL);
660 
661         /* Sysop name */
662         sysopname = nextfield (NULL);
663 
664         /* Phone number */
665         pcsz orig_phone = nextfield (NULL);
666 
667         /* Baud rate */
668         p = nextfield (NULL);
669         n_baud = atol (p);
670 
671         /* Flags */
672         char *flags = remainder;     // remainder of current text line
673 
674         /* Print out the Nodelist.Txt/Prn file */
675         if ((icp->nodelist_txt) || (icp->nodelist_prn))
676         if ((cur_addr_lev != NODE) && (cur_addr_lev != BOSS)) {
677             icp->txt_pg_lines ++;
678 
679             if ((coord_lev >= HOST) && (icp->txt_pg_lines >= 40) ||
680                 (icp->txt_pg_lines >= 60))
681                 TxtHeader (icp);
682 
683             if (icp->nodelist_txt)
684                 fprintf (icp->nodelist_txt,
685                   "%-7.7s%5hd %-19.19s %-20.20s %-19.19s %5lu\n",
686                   modifier, n_num, boardname, orig_phone, cityname, n_baud);
687 
688             if (icp->nodelist_prn)
689                 fprintf (icp->nodelist_prn,
690                   "%-7.7s%5hd %-19.19s %-20.20s %-19.19s %-20.20s %5lu %-30.30s\n",
691                   modifier, n_num, boardname, orig_phone, cityname, sysopname,
692                   n_baud, flags);
693         }
694 
695 
696         PackBuf[0] = '\0';
697 
698      // Process Flags
699 
700             // Override the Flags if necessary
701 
702         ad = GetData (&adr, icp->tab->nf, o->nfn, ocp->tab->nf, cob->o->nfn);
703         if (ad)
704             flags = ad->txt;
705 
706         fl_strupr (flags);     // Convert FLAGS to upper case
707 
708         PT *pt = NULL;      // Phone translation (for Verbatim phones)
709         byte tdinfo = 0;
710                             // Check Modem Type
711         n_modem = 0;
712         TD *td = td_head;
713         while (td) {
714             if (FindFlag (flags, td->flag)) {
715                 n_modem |= td->type;
716                 if (!BitType) {
717                     pt = td->pt;
718                     tdinfo = td->info;
719                     break;
720                 }
721             }
722             td = td->next;
723         }
724 
725 
726         word n_flags = 0;           // node flags
727 
728         switch (coord_lev) {        // coord flags
729             case NONE:
730                 break;
731             case ZONE:
732                 n_flags |= B_zone;
733                 break;
734             case REGION:
735                 n_flags |= B_region;
736                 break;
737             case HOST:
738                 n_flags |= B_host;
739                 break;
740             case HUB:
741                 n_flags |= B_hub;
742                 break;
743         }
744 
745         if (pnt)
746             n_flags |= B_point;
747 
748         if (FindFlag (flags, "CM"))
749             n_flags |= B_CM;
750 
751         FD *fd = fd_head;       // user flags from node flags
752         while (fd) {
753             if (FindFlag (flags, fd->flag))
754                 n_flags |= fd->flag_w;
755             fd = fd->next;
756         }
757 
758                                 // User Flags from address
759         ad = GetData (&adr, icp->tab->fl, o->fln, ocp->tab->fl, cob->o->fln);
760         if (ad)
761             n_flags |= ad->w.w1;
762 
763 
764      // Find out a password if present
765 
766         pw = GetData (&adr, icp->tab->pw, o->pwn, ocp->tab->pw, cob->o->pwn);
767 
768 
769     // Process the phone number
770 
771             // Override the phone number if necessary
772 
773         if ((cur_addr_lev == BOSS) && (n->flags & NoPointLstPhone))
774             orig_phone = UnpublishedPhone;
775 
776         ph = GetData (&adr, icp->tab->ph, o->phn, ocp->tab->ph, cob->o->phn);
777         if (ph)
778             orig_phone = ph->txt;
779 
780         int phone_type = GetPhoneType (orig_phone);
781         bool undialable = (hold && !ph);
782 
783         // process the number and related cost
784 
785         switch (phone_type) {
786 
787           case PT_FIDOIP:
788 
789             strzcpy (phonendx, orig_phone+4, PHONESIZE);
790             dot_it (phonendx);
791             goto VerbPhone;
792 
793           case PT_Verbatim:
794 
795             strzcpy (phonendx, orig_phone, PHONESIZE);
796 
797 VerbPhone:
798             if (undialable)
799                 break;
800 
801             if (pt)
802                 pt->Apply (&n_cost, &u_cost, phone, phonendx, PHONESIZE);
803             else {
804                 strzcpy (phone, phonendx, PHONESIZE);
805                 n_cost = CostVerbatimPhone.cost;
806                 u_cost = CostVerbatimPhone.ucost;
807             }
808 
809                                 // cost override on address
810             ad = GetData (&adr, icp->tab->cs, o->csn, ocp->tab->cs, cob->o->csn);
811             if (ad) {
812                 n_cost = ad->w.w1;
813                 u_cost = ad->w.w2;
814             }
815 
816             break;
817 
818           case PT_Unpublished:
819 
820             strcpy (phonendx, orig_phone);
821 
822             break;
823 
824           case PT_PSTN:
825 
826             CO *co = MkPhone (orig_phone, phone);
827 
828             CopyUndash (phone, phonendx);
829 
830             if (undialable)
831                 break;
832 
833             if (dash2comma)
834                 comma_it (phone);
835 
836             ad = GetData (&adr, icp->tab->cs, o->csn, ocp->tab->cs, cob->o->csn);
837             if (ad) {                   // cost override
838                 n_cost = ad->w.w1;
839                 u_cost = ad->w.w2;
840                 break;
841             }
842 
843             if (!co) {
844                 co = co_head;   // separate cost table
845                 while (co) {
846                     if (strdcmp (orig_phone, co->mstr) != NULL)
847                         break;
848                     co = co->next;
849                 }
850             }
851 
852             if (tdinfo & TD_DIGITAL) {
853                 n_cost = co->costdig;
854                 u_cost = co->ucostdig;
855             } else {
856                 n_cost = co->cost;
857                 u_cost = co->ucost;
858             }
859 
860             break;  // phone_type == PT_PSTN
861 
862         }   // switch (phone_type)
863 
864 
865         if (undialable ||
866             (phone_type == PT_Unpublished)) {
867 
868             phone[0] = '\0';
869 
870             if (NoRedir || pnt || pw || def_pw ||
871                (*def_phone == '\0') || (coord_lev > NONE)) {  // empty phone
872 
873                 n_flags &= B_admin;
874                 n_modem = 0;
875                 n_cost = CostNullPhone.cost;
876                 u_cost = CostNullPhone.ucost;
877 
878                 if (n->MsgLog & MsgLogNullPhone)
879                     if ((!pnt) || (n->MsgLog & MsgLogPoints))
880                         writersp (MsgLogRsp, "%d:%d/%d.%d Null Phone\r", adr.zone, adr.net, adr.node, adr.point);
881 
882                 ocp->nnullphone ++;
883 
884             } else {           // Redirected (only simple nodes)
885 
886                 strcpy (PackBuf, "-R-");    // prefix the board name
887 
888                                     // use defaults for redirected nodes
889                 strcpy (phone, def_phone);
890                 n_flags = def_flags;  // There are no admin flags to save
891                 n_baud = def_baud;
892                 n_modem = def_modem;
893                 n_cost = def_cost;
894                 u_cost = def_ucost;
895 
896                 if (n->MsgLog & MsgLogRedirected)
897                     writersp (MsgLogRsp, "%d:%d/%d.%d Redirected\r", adr.zone, adr.net, adr.node, adr.point);
898 
899                 ocp->nredirect ++;
900             }
901         }
902 
903 
904         if (!NoRedir) {
905 
906             if (coord_lev > NONE) {    // save defaults for redirected nodes
907                 strcpy (def_phone, phone);
908                 def_flags = n_flags & ~B_admin;  // saved without coord flags !
909                 def_baud = n_baud;
910                 def_modem = n_modem;
911                 def_cost = n_cost;
912                 def_ucost = u_cost;
913                 def_pw = pw;
914             }
915 
916         }
917 
918 
919     // Put the results into the proper files
920 
921         if (sysop4ndx == sysop_comma)
922             MkSysopComma (sysopname, sysop4ndx);
923 
924         ocp->heap->Write (&adr, ocp->datofs, ocp->dtpofs,
925                           sysop4ndx, phone4ndx);
926 
927         int error = 0; /* check disk full */
928 
929         /* Print out the results in NODEX.DAT format */
930 
931         vers7->Zone         = adr.zone;
932         vers7->Net          = adr.net;
933         vers7->Node         = adr.node;
934         vers7->HubNode      = (pnt) ? adr.point : adr.hub;
935         vers7->CallCost     = n_cost;
936         vers7->MsgFee       = u_cost;
937         vers7->NodeFlags    = n_flags;
938         vers7->ModemType    = n_modem;
939         vers7->BaudRate     = (byte) (n_baud / 300);
940 
941         q = (char *) (buffer + sizeof (_vers7));
942         p = fl_stpcpy (q, phone);
943         vers7->Phone_len = (byte) (p - q);
944 
945         /* Stick in a password if there is one */
946         if (pw != NULL) {
947             r = fl_stpcpy (p, pw->txt);
948             vers7->Password_len = (byte) (r - p);
949         } else {
950             r = p;
951             vers7->Password_len = 0;
952         }
953 
954         p = PackBuf + strlen (PackBuf);
955         q = fl_stpcpy (p, boardname);
956         vers7->Bname_len = (byte) (q - PackBuf);        /* board name */
957 
958         p = fl_stpcpy (q, sysopname);
959         vers7->Sname_len = (byte) (p - q);           /* SysOp name */
960 
961         q = fl_stpcpy (p, cityname);
962         vers7->Cname_len = (byte) (q - p);           /* City name */
963 
964         if (cob->l->v7data.flags & V7DTP_F) {       // DTP data
965 
966             const _DTPLnk DTPFix = {
967                {
968                  0x0000,     // Region
969                  0x0000,     // Hub
970                  OfsNoLink,  // DAT pointer for next same-sysop entry
971                  OfsNoLink,  // DAT pointer for next same-phone entry
972                  OfsNoLink,  // DAT pointer for next same-level entry
973                  0xff,       // number of SysOp entry
974                  0xff        // number of Phone entry
975                },
976                {
977                  0xffff,     // systems in lower level
978                  OfsNoLink   // DAT pointer for lower level
979                }
980             };
981                              // DTP ptr into Pack
982             sprintf (q, "%08lX", ocp->dtpofs);
983 
984             byte DTPFixSize = pnt ? sizeof (_DTPAllLnk) : sizeof (_DTPLnk);
985 
986             error |= (fwrite (&DTPFix, DTPFixSize, 1, ocp->nodex_dtp) != 1);
987 
988             word dtpflen = (word) (1 + strlen (verbuff));  // raw nodelist line
989             error |= (fwrite (&dtpflen, sizeof (dtpflen), 1, ocp->nodex_dtp) != 1);
990             error |= (fwrite (verbuff, dtpflen, 1, ocp->nodex_dtp) != 1);
991 
992             size_t dtpelen = DTPFixSize + sizeof (dtpflen) + dtpflen;
993             ocp->dtpofs += dtpelen;
994 
995         }
996 
997         Pack ((word *)r, PackBuf, &(vers7->pack_len));
998 
999         size_t entrylen = sizeof (_vers7) + vers7->Phone_len +
1000                                 vers7->Password_len + vers7->pack_len;
1001         error |= (fwrite (buffer, entrylen, 1, ocp->nodex_dat) != 1);
1002 
1003         ocp->datofs += entrylen;
1004 
1005         if (error || Break) {
1006 
1007             ftrunczero (ocp->nodex_dat);
1008 
1009             if (cob->l->v7data.flags & V7DTP_F)
1010                 ftrunczero (ocp->nodex_dtp);
1011 
1012             if (error) {
1013                 vprintlog ("\n\nDisk Full writing nodelist files !\n\n");
1014                 myexit (DISK_FULL);
1015             } else
1016                 myexit (USER_BREAK);
1017         }
1018 
1019     } while (fgets (buff, LINESIZE, f));
1020 
1021     fclose (f);
1022 
1023     if (SegExpHead) {
1024         delete[] origline;
1025         SEGEXPORT::CloseAll (SegExpHead);
1026     }
1027 
1028     if (v->crcchk)
1029         if (official_crc != calc_crc) {
1030             vprintlog ("\n\nCRC ERROR: actual/expected CRC: %05hu/%05hu !\n\n", calc_crc, official_crc);
1031             errorlevel = CRC_ON_LIST;
1032             if (!nocrcexit)
1033                 return FALSE;
1034         }
1035 
1036     return TRUE;
1037 }
1038 
1039 
KillSource(void)1040 void INPBLK::KillSource (void)
1041 {
1042     InpncBlk::KillSource ();
1043     SEGEXPORT::KillSource (SegExpHead);
1044 }
1045 
1046 
KillSource(void)1047 void InpncBlk::KillSource (void)
1048 {
1049     if (l->ArcList && (l->ArcListKeep > 0) && (!l->NodeDiff || a->ArcMethHead))
1050         DeleteFile (l->NodeList, CHK_EXIST);
1051 
1052     if (l->ArcDiff && a->ArcDiffMethHead) {
1053         DAYDIR DayDir (NODEDIFF, this);
1054         DayDir.KillAll ();
1055     }
1056 }
1057 
1058