home *** CD-ROM | disk | FTP | other *** search
/ Hacker Chronicles 2 / HACKER2.BIN / 541.TNL3.C < prev    next >
Text File  |  1988-05-14  |  41KB  |  960 lines

  1. /*****************************************************************************/
  2. /*                                              */
  3. /*                                         */
  4. /*    *****              *****                      */
  5. /*     *****            *****                         */
  6. /*       *****          *****                         */
  7. /*         *****        *****                         */
  8. /*  ***************      ***************                     */
  9. /*  *****************    *****************                     */
  10. /*  ***************      ***************                     */
  11. /*         *****        *****       TheNet                    */
  12. /*       *****          *****       Portable. Compatible.         */
  13. /*     *****            *****       Public Domain             */
  14. /*    *****              *****    NORD><LINK                  */
  15. /*                                         */
  16. /* This software is public domain ONLY for non commercial use                */
  17. /*                                                                           */
  18. /*                                         */
  19. /*****************************************************************************/
  20.  
  21. /* Level 3, Routing                                 */
  22. /* Version 1.01                                                              */
  23. /* Hans Georg Giese, DF2AU, Hinter dem Berge 5, 3300 Braunschweig         */
  24. /* 14-MAY-88                                     */
  25.  
  26. # include "tndef.h"        /* Definition von Konstanten             */
  27. # include "tntyp.h"        /* Definition der Typen                 */
  28. # include "tnl3v.c"        /* Definition der eigenen Variablen         */
  29. # include "tnl3e.h"        /* externe Deklarationen             */
  30.  
  31. /*---------------------------------------------------------------------------*/
  32. /* Strings fuer Level3                                 */
  33. char    brodes[] =                 /* Ziel (Rundsprueche)       */
  34.                                                 /* ASCII Call                */
  35.                                                 /* SSID links geschoben      */
  36.            {'N','O','D','E','S',' ','\140'};
  37. char    brodil[] = {'\000'};            /* Digiliste (Rundsprueche)  */
  38.                                                 /* Call im Standardformat    */
  39.                                                 /* Listenende = 0            */        
  40. char    nulide[] =                /* leerer Ident             */
  41.                    {' ',' ',' ',' ',' ',' '};
  42.  
  43. /*---------------------------------------------------------------------------*/
  44. VOID    l3init()        /* Level 3 initialisieren             */
  45.   {
  46.   nbrtyp *nbrpoi;        /* Pointer auf Nachbarn                 */
  47.  
  48.   numdes =            /* Ziel Liste ist leer                 */
  49.   brotim = 0;            /* Uhr fuer Rundsprueche ruecksetzen         */
  50.   inithd(&l3rxfl);        /* Liste empfangene Frames loeschen         */
  51.   inithd(&l3txl);        /* Liste zu sendende Frames loeschen         */
  52.  
  53.   if (!iswarm())        /* nur im Kaltstart                 */
  54.     {
  55.       inithd(&destil);        /* Liste Ziele loeschen                 */
  56.       inithd(&neigbl);        /* Liste Nachbarn loeschen             */
  57.       maxdes = DEFDES;        /* Ziele maximal                 */
  58.       broint = DEFBRI;        /* Rundspruch Intervall                 */
  59.       obcini = DEFOBC;        /* Abwesenheitszaehler                 */
  60.       obcbro = DEFOBB;        /* maximale Abwesenheit fuer Rundspruch         */
  61.       worqua = DEFWQU;        /* Qualitaet fuer Rundspruch minimal         */
  62.       timliv = DEFTLI;        /* Paketlebensdauer                 */
  63.       ch0qua = DEFCH0;        /* Kanal 0 Qualitaet                 */
  64.       ch1qua = DEFCH1;        /* Kanal 1 Qualitaet                 */
  65.     }
  66.   else                /* Warmstart                     */
  67.     {
  68.       for (despoi  = (nodtyp *) destil.lnext;    /* Zielliste bearbeiten         */
  69.            despoi != (nodtyp *) &destil.lnext;
  70.            despoi  = (nodtyp *) despoi->nodlnk.lnext)
  71.         {
  72.           if (despoi->nodcal[0] != 0)    /* Eintrag belegt?             */
  73.             {
  74.               numdes += 1;        /* ein Ziel mehr             */
  75.               despoi->actrou = 0;    /* kein aktiver Weg             */
  76.               inithd(&despoi->nodinf);    /* keine Info fuer dieses Ziel         */
  77.             }
  78.           else                /* leerer Eintrag             */
  79.             {
  80.               unlink((despoi = (nodtyp *)despoi->nodlnk.lprev)->nodlnk.lnext);
  81.             }
  82.         }
  83.  
  84.     for (nbrpoi  = (nbrtyp *) neigbl.lnext;    /* Nachbarn Liste bearbeiten */
  85.          nbrpoi != (nbrtyp *) &neigbl.lnext;
  86.          nbrpoi  = (nbrtyp *) nbrpoi->nbrlnk.lnext)
  87.       {
  88.         nbrpoi->nbrl2l = 0;    /* Querverweis in L2Link loeschen         */
  89.       }
  90.     }
  91.   }
  92.  
  93. /*---------------------------------------------------------------------------*/
  94. VOID    l3serv()        /* Level 3 Service                 */
  95.   {
  96.   char       orgnod[7];        /* Call des Quellknotens             */
  97.   char       desnod[7];        /* Call des Zielknotens                 */
  98.   char       beaide[6];        /* Ident des Rundspruch sendenden Knotens    */
  99.   char       nbrcal[7];        /* Call des Nachbarn                 */
  100.   char       *rxnxt;        /* erstes Zeichen im Frame             */
  101.   char       *nxtsav;        /* Zwischenspeicher fuer erstes Zeichen         */
  102.   BOOLEAN  destin;        /* aktuelles Ziel                 */
  103.   unsigned cnt;            /* Scratch Zaehler                 */
  104.   unsigned chaqua;        /* Qualitaet des aktuellen Kanals         */
  105.   unsigned rxgetc;        /* Getcount des Frames                 */
  106.   unsigned getsav;        /* Zwischenspeicher fuer Getcount         */
  107.   mhtyp       *mbhd;        /* Kopf des aktuellen Frames             */
  108.  
  109. /*=== empfangene Frames verarbeiten                      ===*/
  110.   while ((mbhd = (mhtyp *) l3rxfl.lnext) != (mhtyp *) &l3rxfl) /* Liste leer?*/
  111.     {
  112.     unlink(mbhd);        /* Frame aus Kette loesen             */
  113.     if ((mbhd->pid & 0xff) == 0xcf) /* PID stimmt?                 */
  114.       {
  115.       rxnxt = mbhd->nxtchr;    /* erstes Zeichen des Frames und         */
  116.       rxgetc = mbhd->getcnt;    /* Getcount merken                 */
  117.  
  118.       if (mbhd->l2lnk != 0)    /* Info Frame?                     */
  119.  
  120. /*------------------------------*/
  121. /*--- Info Frame             ---*/
  122. /*------------------------------*/
  123.         {
  124.         if ((getfid(orgnod, mbhd) == 1) /* Call des Quellknotens holen         */
  125.           &&(getfid(desnod, mbhd) == 1) /* Call des Zielknotens holen         */
  126.           &&(mbhd->getcnt < mbhd->putcnt)) /* Info im Frame?             */
  127.           {
  128.             getchr(mbhd);    /* Restlebensdauer ueberlesen             */
  129.             nxtsav = mbhd->nxtchr; /* Position im Frame merken             */
  130.             getsav = mbhd->getcnt;
  131.             takfhd(mbhd);    /* Header zerlegen                 */
  132.             mbhd->nxtchr = nxtsav; /* wieder auf alten Stand             */
  133.             mbhd->getcnt = getsav;
  134.  
  135.             if ((cmpid(myid, orgnod) == 0)    /* kein eigenes Frames         */
  136.               &&(isgood() == TRUE)        /* und gute Qualitaet         */
  137.           &&(
  138.                 ((destin = iscall(orgnod)) == FALSE)
  139.             ||(istweg(&txfhdr[14], &rxfhdr[7], rxfprt) == ERROR)
  140.                 ))
  141.               {
  142.                 chgnod('+', obcini, 0, rxfprt, &txfhdr[14], &rxfhdr[7],
  143.                        (destin == FALSE)? &nulide[0] : &despoi->nodide[0],
  144.                        orgnod);        /* Zielliste auf neuen Stand bringen */
  145.               }
  146.  
  147.             if (cmpid(myid, desnod) == 1)    /* Frame fuer mich?         */
  148.               {
  149.                 relink(mbhd, l4rxfl.lprev);    /* dann an Level 4 geben     */
  150.                 continue;            /* naechstes Frame         */
  151.               }
  152.  
  153.             if (iscall(desnod) == 1)        /* Ziel bekannt?         */
  154.               {
  155.                 if (--*(mbhd->nxtchr -1) != 0)    /* noch Restlebensdauer?     */
  156.                   {
  157.                     mbhd->nxtchr = rxnxt;    /* auf Transportheader         */
  158.                     mbhd->getcnt = rxgetc;
  159.                     if ((despoi->actrou != 0)    /* aktiver Weg zum Ziel?     */
  160.                       &&(mbhd->l2lnk ==
  161.                          despoi->weg[despoi->wegnr].nachba->nbrl2l))
  162.                       {
  163.                         despoi->actrou &=0xfff8;
  164.                         despoi->actrou |= 0x02;
  165.                       }
  166.                     if ((cmpid(myid, orgnod) == 0)
  167.                       || ((despoi->actrou & 0x07) == 2))
  168.                       {
  169.                         todest(mbhd);   /* Info absetzen                     */
  170.                         continue;
  171.                       }            /* Info kann abgesetzt werden         */
  172.                   }            /* noch Restlebensdauer             */
  173.               }                /* Ziel ist bekannt             */
  174.          }                /* Info ist im Frame             */
  175.     }                    /* es ist ein I-Frame             */
  176.  
  177. /*--------------------------------------*/
  178.       else                /* UI Frame                 */
  179.         {
  180.           if (worqua != 0)        /* darf Auswertung erfolgen?         */
  181.             {
  182.               takfhd(mbhd);        /* Header zerlegen             */
  183.               mbhd->nxtchr = rxnxt;    /* zurueck auf Anfang             */
  184.               mbhd->getcnt = rxgetc;
  185.  
  186.               if (isgood() == TRUE)
  187.                 {
  188.                   if ((mbhd->getcnt < mbhd->putcnt)    /* Info im Frame?    */
  189.                     &&((getchr(mbhd) & 0xff) == 0xff)    /* stimmt Signatur?  */
  190.                     &&(ge6chr(beaide, mbhd) == 1)    /* Ident des Knotens */
  191.                     &&(chgnod('+', obcini, qualty, rxfprt, &txfhdr[14],
  192.                        &rxfhdr[7], &beaide[0], &rxfhdr[7]) == 1))
  193.                     {
  194.                       while ((getfid(desnod, mbhd) == 1) /* Rest des Frames  */
  195.                             && (ge6chr(beaide, mbhd) ==1)
  196.                             && (getfid(nbrcal, mbhd) == 1)
  197.                             && (mbhd->getcnt < mbhd->putcnt))
  198.                         {
  199.                           chaqua = getchr(mbhd) & 0xff;
  200.                           if (cmpid(myid, desnod) == 0)   /* selbst Ziel?    */
  201.                             {
  202.                               if ((chaqua = (((chaqua * qualty) +128) / 256))
  203.                                 >= worqua)
  204.                                 {
  205.                                   if (cmpid(myid, nbrcal) == 1) chaqua = 0;
  206.                                   if (chgnod('+', obcini, chaqua, rxfprt,
  207.                                       &txfhdr[14], &rxfhdr[7],
  208.                                       ((chaqua == 0) && (iscall(desnod) == 1))?
  209.                                         &despoi->nodide[0] : &beaide[0],
  210.                                       desnod) == 0) break;
  211.                                 }    /* Qualitaet gut genug fuer Update   */
  212.                             }        /* nicht selbst das Ziel         */
  213.                         }        /* bis Framenende             */
  214.  
  215.                       if (nbrpoi != NULL)
  216.                         {        /* Nachbar definiert             */
  217.                         for (despoi  = (nodtyp *) destil.lnext; /* Ziel?     */
  218.                              despoi != (nodtyp *) &destil.lnext;
  219.                              despoi  = (nodtyp *) despoi->nodlnk.lnext)
  220.                           {
  221.                             if (despoi->actrou != 0)
  222.                               {            /* aktiver Weg zum Ziel?     */
  223.                                 for (cnt = 0;    /* alle Wege des Zieles         */
  224.                                   despoi->wege > cnt;
  225.                                   ++cnt)
  226.                                   {
  227.                                     if (despoi->weg[cnt].nachba == nbrpoi)
  228.                                       {    /* fuehrt der Weg ueber diesen Nachb */
  229.                                         if (despoi->wegnr > cnt)
  230.                                           { /* gibt es einen besseren Weg?   */
  231.                                             despoi->wegnr = cnt;
  232.                                             makrou(); /* diesen Weg versuchen*/
  233.                                           }    /* es gibt einen besseren Weg*/
  234.                                         break;
  235.                                       }    /* Weg fuehrt ueber diesen Nachbarn  */
  236.                                   }    /* dieser Weg bearbeitet         */
  237.                               }        /* aktiver Weg existiert         */
  238.                           }        /* dieses Ziel bearbeitet         */
  239.                       }            /* Weg geht ueber einen Nachbarn     */
  240.                     }            /* Signatur ist gut             */
  241.                 }            /* Qualitaet des Kanals stimmt         */
  242.             }                /* Auswertung zulaessig             */
  243.         }                /* ist UI Frame                 */
  244.       }                    /* PID stimmt                 */
  245.     dealmb(mbhd);            /* Frame ist bearbeitet, wegwerfen   */
  246.   }                    /* Frames in der Kette             */
  247.  
  248. /*=== zu sendende Frames verarbeiten                      ===*/
  249.   while ((mbhd = (mhtyp *) l3txl.lnext) != (mhtyp *) &l3txl.lnext) { /* leer?*/
  250.     unlink(mbhd);        /* Frame aushaengen                 */
  251.     despoi = (nodtyp *) mbhd->l2lnk;    /* Pointer auf Nachbarn             */
  252.     if ((despoi->nodcal[0] != 0) /* Ziel definiert                 */
  253.       && (nmbfre > 64)) {    /* und Platz im Speicher             */
  254.       rwndmb(mbhd);        /* alle Pointer auf Ausgangsstellung         */
  255.       getchr(mbhd);        /* alles initialisieren                 */
  256.       --mbhd->nxtchr;
  257.       rxgetc = mbhd->putcnt;    /* Framelaenge merken                 */
  258.       mbhd->putcnt = 1;        /* auf Anfang                     */
  259.       putfid(myid, mbhd);    /* Absender ins Frame                 */
  260.       putfid(&despoi->nodcal[0], mbhd); /* Ziel ins Frame             */
  261.       *(mbhd->nxtchr -1) |= 1;    /* Ende der Adresse setzen             */
  262.       putchr(timliv, mbhd);    /* Lebensdauer setzen                 */
  263.       mbhd->putcnt = rxgetc;    /* Putcount zurueck                 */
  264.       rwndmb(mbhd);        /* Pointer wieder aufziehen             */
  265.       todest(mbhd);        /* weg damit                     */
  266.       }
  267.     else dealmb(mbhd);        /* geht nicht, Frame vernichten             */
  268.     }
  269.  
  270. /*=== sonstige Funktionen                          ===*/
  271.   for (despoi  = (nodtyp *) destil.lnext;        /* Zielliste bearbeiten                 */
  272.        despoi != (nodtyp *) &destil.lnext;
  273.        despoi  = (nodtyp *) despoi->nodlnk.lnext) {
  274.     switch (despoi->actrou & 0x07) { /* ueber Wegstatus verzweigen         */
  275. /*------------------------------*/
  276.       case 2:            /* Fehler aufgetreten, neuen Weg nehmen         */
  277.         if (++despoi->wegnr >= despoi->wege) {
  278.           if ((despoi->actrou & 0x80) == 0)
  279.             despoi->wegnr = 0;
  280.           else {
  281.             destot();        /* Ziel nicht erreichbar, Frames wegwerfen   */
  282.             break;
  283.           } }
  284.         makrou();        /* Weg aufbauen                     */
  285.         break;
  286.         
  287. /*------------------------------*/
  288.       case 3:            /* Info Transfer laeuft                 */
  289.         while ((mbhd = (mhtyp *) despoi->nodinf.lnext)
  290.                     != (mhtyp *) &despoi->nodinf)
  291.          {
  292.           unlink(mbhd);        /* Frame aus Kette holen             */
  293.           mbhd->pid = 0xcf;    /* PID setzen                     */
  294.           relink(mbhd,
  295.             (lnkpoi = despoi->weg[despoi->wegnr].nachba->nbrl2l)
  296.             ->sendil.lprev);    /* Frame in L2 umhaengen             */
  297.           ++lnkpoi->tosend;    /* ein Frame mehr senden             */
  298.           lnkpoi->noatou = ininat; /* Timeout setzen                 */
  299.           }
  300.         break;
  301.         
  302. /*------------------------------*/
  303.       case 4:            /* */
  304.         makrou();        /* Weg aufbauen                     */
  305.         break;
  306.  
  307. /*------------------------------*/
  308.       default:            /* leer oder connect laeuft             */
  309.         break;
  310.         
  311.   } } }
  312.  
  313. /*---------------------------------------------------------------------------*/
  314. VOID    l2tol3(status)        /* Level 2 meldet neuen Status             */
  315. unsigned status;        /* 0=nicht verwendet, 1=connected         */
  316.                 /* 2=disconnected, 3=busy, 4=Failure         */
  317.   {
  318.   unsigned  wegsts;        /* Status des aktuellen Weges             */
  319.   nbrtyp    *nbrpoi;        /* Pointer auf Nachbarn                 */
  320.  
  321.   if (status < 5)        /* nicht alles verwenden             */
  322.    {
  323.     for (despoi  = (nodtyp *) destil.lnext;    /* gemeldeten Link suchen    */
  324.          despoi != (nodtyp *) &destil.lnext;
  325.          despoi  = (nodtyp *) despoi->nodlnk.lnext)
  326.      {
  327.       if (((wegsts = despoi->actrou & 0x07) != 0) /* aktiver Weg?         */
  328.             && ((despoi->weg[despoi->wegnr].nachba)->nbrl2l == lnkpoi))
  329.             {
  330.               if (status == 1)        /* Connect gemeldet             */
  331.                 {
  332.                   if (wegsts == 1)    /* und war auch gefordert         */
  333.                     despoi->actrou = 3;    /* neuer Status des Zieles: connected*/
  334.                 }
  335.               else
  336.                 {
  337.                   if (wegsts != 4)
  338.                     {
  339.                       despoi->actrou &= 0xfff8;        /* Busy:         */
  340.                       despoi->actrou |= 0x02; /* neuer Status: anderen Weg   */
  341.                     }
  342.                 }
  343.             }
  344.         }
  345.       if (status != 1)            /* bei Busy / Failure             */
  346.         {
  347.           for (nbrpoi  = (nbrtyp *) neigbl.lnext; /* Nachbar Liste absuchen  */
  348.                nbrpoi != (nbrtyp *) &neigbl.lnext;
  349.                nbrpoi  = (nbrtyp *) nbrpoi->nbrlnk.lnext)
  350.             {
  351.               if (nbrpoi->nbrl2l == lnkpoi)
  352.                 nbrpoi->nbrl2l = 0;    /* Querverweis loeschen             */
  353.             }
  354.         }
  355.     }
  356.   }
  357.  
  358. /*---------------------------------------------------------------------------*/
  359. VOID    brosrv()        /* Rundspruchservice                 */
  360.                 /* jede Sekunde aufgerufen             */
  361.   {
  362.   unsigned cnt;            /* Zaehler                     */
  363.   mhtyp    *mbhd;        /* Buffer fuer Meldung                 */
  364.   wegtyp   *route;        /* aktueller Weg                 */
  365.  
  366.   if (broint != 0) {        /* Rundspruch erlaubt?                 */
  367.     if (++brotim >= broint) {    /* Zeit zum Senden gekommen?             */
  368.       brotim = 0;        /* Uhr ruecksetzen                 */
  369.       mbhd = brobuf();        /* Buffer besorgen                 */
  370.  
  371.       for (despoi  = (nodtyp *) destil.lnext;    /* Zielliste absuchen         */
  372.            despoi != (nodtyp *) &destil.lnext;
  373.            despoi  = (nodtyp *) despoi->nodlnk.lnext) {
  374.         if (despoi->nodcal[0] != 0) { /* Eintrag belegt?             */
  375.           if (obcini != 0) {    /* wenn Abwesenheitszaehler gefuehrt wird    */
  376.             for (cnt = 0;    /* alle Wege testen                 */
  377.                  cnt < despoi->wege;
  378.                  ++cnt) {
  379.               if (((route = &despoi->weg[cnt])->obscnt != 0) /* gueltig?     */
  380.                 &&(--(route->obscnt) == 0)) { /* gerade auf 0 angekommen?    */
  381.                 delrou(cnt);    /* dann loeschen                 */
  382.                 --cnt;        /* ein Weg weniger                 */
  383.               } }
  384.             if (despoi->nodcal[0] == 0) /* gibt es den Weg noch?         */
  385.               continue;
  386.             }
  387.           if (((route = &despoi->weg[0])->qualit != 0)        /* Qualitaet */
  388.             &&((route->obscnt == 0) /* muss sein, Eintrag permanent oder     */
  389.             || ((route->obscnt & 0xff) >= obcbro))){ /* gut genug         */
  390.  
  391.             if (mbhd == 0)    /* ggfs neuen Buffer besorgen             */
  392.               mbhd = brobuf();
  393.  
  394.             putfid(&despoi->nodcal[0], mbhd); /* Call des Zieles         */
  395.             pu6chr(&despoi->nodide[0], mbhd); /* Ident des Zieles         */
  396.             putfid(&route->nachba->nbrcal[0], mbhd); /* Nachbar des Zieles   */
  397.             putchr(route->qualit, mbhd); /* Qualitaet zum Ziel             */
  398.             if ((mbhd->putcnt + 21) > 256) { /* droht Ueberlauf?         */
  399.               sdbufr(mbhd);    /* dann Buffer senden                 */
  400.               mbhd = 0;        /* Buffer ist weg                 */
  401.               }
  402.             }
  403.         } }
  404.       if (mbhd != 0)        /* noch Reste im Buffer?             */
  405.         sdbufr(mbhd);        /* dann senden                     */
  406.   } } }
  407.  
  408. /*---------------------------------------------------------------------------*/
  409. mhtyp    *brobuf()        /* Buffer fuer Rundspruch besorgen         */
  410.   {
  411.   mhtyp    *mbhd;        /* Buffer fuer Meldung                 */
  412.  
  413.   putchr(0xff, (mbhd = allocb()));    /* Buffer besorgen, Signatur rein    */
  414.   pu6chr(alias, mbhd);            /* Ident in Buffer             */
  415.   return(mbhd);                /* Buffer als Rueckgabe             */
  416.   }
  417.  
  418. /*---------------------------------------------------------------------------*/
  419. VOID    sdbufr(mbhd)        /* Buffer als Rundspruch senden             */
  420. mhtyp    *mbhd;
  421.   {
  422.   unsigned kanal;        /* Kanal, auf dem gesendet wird             */
  423.  
  424.   mbhd->pid = 0xcf;        /* PID = Level3                     */
  425.   for (kanal = 0;
  426.        kanal < 2;        /* auf beiden Kanaelen senden             */
  427.        ++kanal)
  428.     {
  429.     rwndmb(mbhd);        /* Pointer aufziehen                 */
  430.     sdui(&brodil[0], &brodes[0], &myid[0], kanal, mbhd);   /* Level2 sendet  */
  431.     }
  432.   dealmb(mbhd);            /* Buffer wieder freigeben             */
  433.   }
  434.  
  435. /*---------------------------------------------------------------------------*/
  436. BOOLEAN    chgnod(mode, obci, quali, port, digis, nachb, iden, call)
  437.                 /* Zieleintrag aendern                 */
  438. unsigned mode;            /* '+'=neuer Eintrag, '-'=Eintrag loeschen   */
  439. unsigned obci;            /* Abwesenheitszaehler, Initialisierung         */
  440. unsigned quali;            /* Qualitaet des Weges                 */
  441. unsigned port;            /* Port zum Ziel                 */
  442. char     *digis;        /* Digipeaterliste                 */
  443. char     *nachb;        /* Nachbar zum Ziel                 */
  444. char     *iden;            /* Ident des Zieles                 */
  445. char     *call;            /* Rufzeichen des Zieles             */
  446.  
  447.                 /* Rueckgabe:                     */
  448.                 /* TRUE: loeschen verlangt, kein Eintrag da  */
  449.                 /*       aendern war erfolgreich         */
  450.                 /* FALSE: Liste voll                 */
  451.   {
  452.   char     *id1poi;        /* Pointer fuer Call-Ident Vergleich         */
  453.   char       *id2poi;        /* Pointer fuer Call-Ident Vergleich         */
  454.   unsigned rout;        /* aktueller Weg                 */
  455.   unsigned cnt;            /* Scratch Zaehler                 */
  456.   nodtyp   *ziel1;        /* Pointer auf Ziel                 */
  457.   nodtyp   *zielpt;        /* Pointer auf Ziel                 */
  458.  
  459.   zielpt = NULL;
  460.   for (despoi  = (nodtyp *) destil.lnext;    /* Zielliste absuchen         */
  461.        despoi != (nodtyp *) &destil.lnext;
  462.        despoi  = (nodtyp *) despoi->nodlnk.lnext)
  463.     {
  464.     if (despoi->nodcal[0] != 0) { /* Eintrag belegt?                 */
  465.       if (cmpid(&despoi->nodcal[0], call) == 1) break; /* und passt?         */
  466.       }
  467.     else {            /* freier Eintrag                 */
  468.       if (zielpt == NULL) zielpt = despoi; /* ersten freien Eintrag merken   */
  469.       }
  470.     }
  471.   if ((nodtyp *) &destil.lnext == despoi) {    /* passender Eintrag?         */
  472.     if (mode == '+') {        /* hinzufuegen?                     */
  473.       if (zielpt == 0) {    /* kein freier Platz bisher?             */
  474.         if (numdes < maxdes) {    /* Liste hat noch Platz?             */
  475.           (zielpt = (nodtyp *) allocb())->actrou = 0;   /* initialisieren    */
  476.           zielpt->wege = 0;    /* kein Weg bekannt                 */
  477.           inithd(&zielpt->nodinf); /* keine Info in der Schlange         */
  478.           relink(zielpt, destil.lprev); /* in Zielliste haengen             */
  479.           ++numdes;        /* Liste ist laenger geworden             */
  480.           }
  481.         else return (FALSE);    /* Liste ist voll                 */
  482.         }
  483.       despoi = zielpt;        /* freien (neuen) Platz nehmen             */
  484.       cpyid(&despoi->nodcal[0], call); /* Call eintragen, Rest spaeter         */
  485.       }
  486.     else return (TRUE);        /* loeschen verlangt, Eintrag existiert nicht*/
  487.     }
  488.  
  489. /*------------------------------ passender Eintrag existiert (CALL)         */
  490.   cpy6ch(&despoi->nodide[0], iden);    /* Ident umkopieren             */
  491.   unlink(despoi);        /* Eintrag aus Kette loesen             */
  492.  
  493.   for (ziel1  = (nodtyp *) destil.lnext;    /* Zielliste absuchen         */
  494.        ziel1 != (nodtyp *) &destil.lnext;
  495.        ziel1  = (nodtyp *) ziel1->nodlnk.lnext)
  496.     {
  497.       id1poi = (char *) &ziel1->nodide[0];
  498.       id2poi = (char *) &despoi->nodide[0];
  499.       for (cnt = 0; cnt < 13; ++cnt)
  500.         {                /* Call und Ident vergleichen         */
  501.           if (*id1poi == *id2poi)
  502.             {
  503.               ++id1poi;
  504.               ++id2poi;
  505.             }
  506.           else break;
  507.         }                /* Call und Ident verglichen         */
  508.       if (*id1poi > *id2poi) break;
  509.     }                    /* Zielliste abgesucht             */
  510.   relink(despoi, ziel1->nodlnk.lprev);
  511.   if ((rout = istweg(digis, nachb, port)) == -1)
  512.     {
  513.       if (mode == '+')
  514.         newnod(obci, quali, port, digis, nachb);
  515.     }
  516.   else
  517.     {
  518.       if (mode == '-')
  519.         delrou(rout);
  520.       else
  521.         {
  522.           if (despoi->weg[rout].obscnt != 0)
  523.             addweg(obci, quali, rout);
  524.         }
  525.     }
  526.   return (TRUE);
  527.   }
  528.  
  529. /*---------------------------------------------------------------------------*/
  530. VOID    newnod(obci, quali, port, digis, nachb)
  531.                 /* Zieleintrag in Liste aufnehmen         */
  532. unsigned obci;            /* Anwesenheitszaehler                 */
  533. unsigned quali;            /* Qualitaet des Weges                 */
  534. unsigned port;            /* Port zum Ziel                 */
  535. char     *digis;        /* Digipeaterliste                 */
  536. char     *nachb;        /* Nachbar zum Ziel                 */
  537.   {
  538.   unsigned  neuweg;        /* Position des neuen Weges in Liste         */
  539.   wegtyp    *wegptr;        /* Pointer auf Weg                 */
  540.   nbrtyp    *nbrptr;        /* Pointer auf Nachbarn                 */
  541.  
  542.   rouhin();            /* alle Wege in Arbeitsspeicher             */
  543.   (wegptr = &routmp[despoi->wege]) /* auf neuen Weg. wege zaehlt 1-2-3!         */
  544.          ->qualit = quali;    /* Qualitaet des neuen Weges             */
  545.   wegptr->obscnt = obci;    /* Anwesenheitszaehler                 */
  546.   wegptr->nachba = (nbrtyp *) -1; /* Zeiger auf Nachbarn loeschen         */
  547.   neuweg = srtrou(despoi->wege++); /* Wege sortieren                 */
  548.   rouher();            /* Wege zurueck in Liste             */
  549.   if (neuweg < 3)        /* steht der neue Weg in der Liste?         */
  550.     {
  551.       ++(nbrptr = updnbr(digis, nachb, port)) /* Nachbarnliste neuer Stand   */
  552.                   ->nbrrou;    /* ein Weg mehr ueber diesen Nachbarn         */
  553.       despoi->weg[neuweg].nachba = nbrptr; /* Nachbarn in Zielliste eintragen*/
  554.     }
  555.   if (despoi->wege > 3) {    /* nun mehr als 3 Wege vorhanden?         */
  556.     --despoi->wege;        /* darf nicht sein                 */
  557.     if (neuweg < 3)        /* wurde neuer Weg in die Liste aufgenommen? */
  558.       decrcn(&routmp[3]);    /* dann muss ein anderer entfernt werden     */
  559.     }
  560.   if ((despoi->actrou != 0)    /* besteht ein aktiver Weg?             */
  561.     && (despoi->wegnr > 2)) {    /* und ist es der nun schlechteste?         */
  562.     despoi->wegnr = 0;        /* dann den besten nehmen             */
  563.     makrou();            /* und Link neu aufbauen             */
  564.     }
  565.   }
  566.  
  567. /*---------------------------------------------------------------------------*/
  568. VOID    addweg(obci, quali, nummer)
  569.                 /* Weg in Liste aufnehmen             */
  570. unsigned obci;            /* Anwesenheitszaehler                 */
  571. unsigned quali;            /* Qualitaet des Weges                 */
  572. unsigned nummer;        /* Nummer des Eintrages                 */
  573.   {
  574.   wegtyp *wegptr;        /* Pointer auf Weg                 */
  575.  
  576.   (wegptr = &(despoi->weg[nummer]))->qualit = quali; /* Qualitaet         */
  577.   wegptr->obscnt = obci;    /* und Anwesenheitszaehler setzen         */
  578.   rouhin();            /* auslagern in Arbeitsspeicher             */
  579.   srtrou(-1);            /* sortieren                     */
  580.   rouher();            /* zurueck in Liste                 */
  581.   }
  582.  
  583. /*---------------------------------------------------------------------------*/
  584. VOID    delrou(nummer)        /* Weg aus Liste streichen             */
  585. unsigned nummer;        /* Nummer des Eintrages                 */
  586.   {
  587.   wegtyp *wegptr;        /* Pointer auf Weg                 */
  588.  
  589.   decrcn(wegptr = &(despoi->weg[nummer])); /* Weg in Nachbarnliste loeschen  */
  590.   if (despoi->wege > 1) {    /* nun noch Wege fuer dieses Ziel vorhanden? */
  591.     wegptr->nachba = 0;        /* ohne Nachbarn hat der Weg keine Qualitaet */
  592.     rouhin();            /* Wege in Arbeitsspeicher             */
  593.     srtrou(-1);            /* sortieren                     */
  594.     rouher();            /* wieder in Liste zurueck             */
  595.     }
  596.   else {            /* den letzten Weg entfernt             */
  597.     destot();            /* Ziel existiert nicht mehr             */
  598.     despoi->nodcal[0] = 0;    /* Eintrag ist wieder frei             */
  599.     }
  600.   if ((despoi->wegnr >= --despoi->wege) /* aktiven Weg geloescht?         */
  601.     && (despoi->actrou != 0)) {
  602.     despoi->wegnr = 0;        /* neuen Weg suchen                 */
  603.     makrou();
  604.     }
  605.   }
  606.  
  607. /*---------------------------------------------------------------------------*/
  608. VOID    decrcn(weg)        /* Weg aus Nachbarn-Liste streichen         */
  609. wegtyp    *weg;            /* zu loeschender Weg                 */
  610.   {
  611.   nbrtyp *nbrptr;        /* Pointer auf Nachbarn                 */
  612.  
  613.   if ((--(nbrptr = weg->nachba)->nbrrou == 0) /* den letzten Weg geloescht?  */
  614.     && (nbrptr->locked == 0))    /* und Eintrag nicht gesperrt             */
  615.     {
  616.       dealoc(unlink(nbrptr));    /* dann Nachbarn komplett loeschen         */
  617.     }
  618.   }
  619.  
  620. /*---------------------------------------------------------------------------*/
  621. VOID    rouhin()        /* Wege in Arbeitsspeicher auslagern         */
  622.   {
  623.   move4b(3, routmp, &despoi->weg[0]); /* 12 (=3*4) Bytes kopieren         */
  624.   }
  625.  
  626. /*---------------------------------------------------------------------------*/
  627. VOID    rouher()        /* Wege aus Arbeitsspeicher holen         */
  628.   {
  629.   move4b(3, &despoi->weg[0], routmp); /* 12 (=3*4) Bytes kopieren         */
  630.   }
  631.  
  632. /*---------------------------------------------------------------------------*/
  633. unsigned srtrou(wegneu)        /* Wegeliste in routmp sortieren         */
  634. int    wegneu;            /* Position des neuen Weges in routmp         */
  635.                 /* Rueckgabe: Position des neuen Weges         */
  636.   {
  637.   unsigned wegcnt;        /* Zahl der Wege in routmp             */
  638.   unsigned waktiv;        /* aktiver Weg dieses Zieles             */
  639.   unsigned akt;            /* aktuell untersuchter Weg (Nummer)         */
  640.   unsigned nxt;            /* naechster zu untersuchender Weg (Nummer)  */
  641.   wegtyp   *wakt;        /* aktueller Weg                 */
  642.   wegtyp   *wnxt;        /* naechster Weg                 */
  643.  
  644.   wegcnt = despoi->wege;    /* Zahl der Wege holen                 */
  645.   waktiv = despoi->wegnr;    /* aktiven Weg merken                 */
  646.   for (wakt = &routmp[akt = 0];    /* Bubble Sort ueber routmp             */
  647.        (wegcnt-1) > akt;
  648.        ++akt, ++wakt) {
  649.     for (wnxt = &routmp[nxt = akt + 1];
  650.          nxt < wegcnt;
  651.          ++nxt, ++wnxt) {
  652.       if ((! wakt->nachba)    /* der Weg muss einen Nachbarn haben         */
  653.         || ((wakt->qualit & 0xff) < (wnxt->qualit & 0xff))) { /* und besser  */
  654.         move4b(1, &rouwrk, wakt); /* als der vorherige sein             */
  655.         move4b(1, wakt, wnxt);    /* dann die Wege tauschen             */
  656.         move4b(1, wnxt, &rouwrk);
  657.         if (wegneu == akt) wegneu = nxt; /* neuen Weg merken             */
  658.         else if (wegneu == nxt) wegneu = akt;
  659.         if (waktiv == akt) waktiv = nxt; /* aktiven Weg merken             */
  660.         else if (waktiv == nxt) waktiv = akt;
  661.     } } }
  662.   despoi->wegnr = waktiv;    /* aktiven Weg in Liste korrigieren         */
  663.   return(wegneu);        /* mit Position des neuen Weges zurueck         */
  664.   }
  665.  
  666. /*---------------------------------------------------------------------------*/
  667. VOID    move4b(zahl, nach, von)    /* 4 * Zahl Bytes kopieren             */
  668. unsigned zahl;
  669. char     *nach;            /* Ziel                         */
  670. char     *von;            /* Quelle                     */
  671.   {
  672.   unsigned cnt;            /* Scratch Zaehler                 */
  673.  
  674.   for (cnt = 0; (zahl * 4) > cnt; ++cnt) {
  675.     *nach++ = *von++;
  676.     }
  677.   }
  678.  
  679. /*---------------------------------------------------------------------------*/
  680. VOID    todest(mbhd)        /* Info in Zielliste haengen             */
  681. mhtyp    *mbhd;            /* Info Header                     */
  682.   {
  683.   relink(mbhd, despoi->nodinf.lprev); /* Info umhaengen                 */
  684.   if (despoi->actrou == 0) {    /* kein aktiver Weg da?                 */
  685.     despoi->wegnr = 0;        /* mit dem besten Weg beginnend             */
  686.     makrou();            /* Link aufbauen                 */
  687.     }
  688.   }
  689.  
  690. /*---------------------------------------------------------------------------*/
  691. VOID    makrou()        /* Weg zu einem Ziel aufbauen             */
  692.   {
  693.   unsigned  cnt;        /* Scratch Zaehler                 */
  694.   l2ltyp    *l2poi;        /* Pointer auf Level2 Kontrollblock         */
  695.   nbrtyp    *nbrpoi;        /* Pointer auf Nachbarn                 */
  696.  
  697.   if (despoi->nodinf.lnext != (lhtyp *) &despoi->nodinf.lnext) { /* Info?    */
  698.     despoi->actrou &= 0xfff8;    /* Status: kein aktiver Weg             */
  699.     if ((lnkpoi =         /* schon - noch Eintrag fuer L2 vorhanden?   */
  700.       (nbrpoi = despoi->weg[despoi->wegnr].nachba)->nbrl2l)
  701.       == 0) {
  702.       for (l2poi = 0, cnt = 0, lnkpoi = &lnktbl[0];
  703.            cnt < MAXL2L;    /* nein, freien Eintrag suchen             */
  704.            ++cnt, ++lnkpoi) {
  705.         if (lnkpoi->state != 0) { /* Eintrag belegt                 */
  706.           if ((cmpid(nbrpoi->nbrcal, lnkpoi->dstid) == 1)
  707.             &&(cmpid(myid, lnkpoi->srcid) == 1)
  708.             &&(lnkpoi->liport == nbrpoi->nbrpor))
  709.             break;        /* passt er zufaellig? Dann benutzen         */
  710.           }
  711.         else {            /* Eintrag ist frei                 */
  712.           if ((l2poi == 0) && (lnkpoi->srcid[0] == 0))
  713.             l2poi = lnkpoi;          /* ersten freien Eintrag merken    */
  714.           }
  715.         }
  716.       if (cnt == MAXL2L) {    /* kein passender Eintrag gefunden?         */
  717.         if (l2poi != 0) {    /* freier Eintrag vorhanden?             */
  718.           lnkpoi = l2poi;    /* dann nehmen wir ihn                 */
  719.           cpyid(lnkpoi->srcid, myid); /* Quellcall eintragen             */
  720.           cpyid(lnkpoi->dstid, nbrpoi->nbrcal); /* Zielcall eintragen         */
  721.           cpyidl(lnkpoi->viaid, nbrpoi->nbrdil); /* Digiliste eintragen         */
  722.           lnkpoi->liport = nbrpoi->nbrpor; /* Port eintragen             */
  723.           newlnk();        /* im Level 2 eine Verbindung bestellen         */
  724.           }
  725.         else {            /* L2 Tabelle ist voll                 */
  726.           despoi->actrou |= 0x02; /* Fehler markieren                 */
  727.           return;        /* Abbruch                     */
  728.           }
  729.         }
  730.       nbrpoi->nbrl2l = lnkpoi;    /* in Nachbarnliste Querverweis eintragen    */
  731.       }
  732.     if (lnkpoi->state == 1)    /* Status = Connect laeuft?             */
  733.       despoi->actrou |= 0x01;    /* dann auch in Nachbarnliste so markieren   */
  734.     else
  735.       {
  736.         if (lnkpoi->state == 3)    /* Status: Disc-Requested?             */
  737.           despoi->actrou |= 0x04;
  738.         else
  739.           despoi->actrou = 3;    /* sonst Status = connected             */
  740.       }
  741.     if ((despoi->actrou == 1)    /* Connect laeuft und                 */
  742.       && (despoi->wegnr == 0))    /* noch kein Weg probiert             */
  743.       despoi->actrou |= 0x80;    /* markieren                     */
  744.     }
  745.   else despoi->actrou = 0;    /* keine aktive Route                 */
  746.   }
  747.  
  748. /*---------------------------------------------------------------------------*/
  749. VOID    destot()        /* Ziel ist nicht mehr erreichbar         */
  750.   {
  751.   dealml(&despoi->nodinf);    /* Info fuer das Ziel wegwerfen             */
  752.   despoi->actrou = 0;        /* kein aktiver Weg                  */
  753.   }
  754.  
  755. /*---------------------------------------------------------------------------*/
  756. BOOLEAN isgood()        /* Entscheidung ueber Qualitaet des Weges    */
  757.   {                /* TRUE: Qualitaet ist gut fuer Speicherung  */
  758.     return (            /* FALSE: schlechter Weg             */
  759.       (qualty = (
  760.       (nbrpoi = getnei(&txfhdr[14], &rxfhdr[7], rxfprt)) /* welcher Nachbar? */
  761.         == NULL)?            /* existiert er ueberhaupt?         */
  762.         ((rxfprt == 0)? ch0qua : ch1qua) /* Portqualitaet, wenn nicht da     */
  763.         :
  764.         (nbrpoi->pathqu & 0xff))    /* sonst aus Nachbarliste         */
  765.       >= worqua);            /* vergleichen mit Minimalqualitaet  */
  766.   }
  767.  
  768. /*---------------------------------------------------------------------------*/
  769. nbrtyp    *updnbr(digis, nachb, port)    /* Nachbar auf neuen Stand bringen   */
  770.   char       *digis;            /* Digiliste zum Nachbarn         */
  771.   char     *nachb;            /* Call des Nachbarn             */
  772.   unsigned port;            /* Port zum Nachbarn             */
  773.   {
  774.   nbrtyp   *nbrbuf;            /* Buffer fuer Eintrag             */
  775.  
  776.   if ((nbrbuf = getnei(digis, nachb, port)) == NULL)
  777.     {                    /* Eintrag existiert noch nicht         */
  778.       nbrbuf = (nbrtyp *) allocb();        /* Buffer beschaffen         */
  779.       cpyid(&nbrbuf->nbrcal[0], nachb);    /* Call eintragen             */
  780.       digis[14] = 0;            /* nur 2 Digis                 */
  781.       cpyidl(&nbrbuf->nbrdil[0], digis); /* Digiliste eintragen             */
  782.       nbrbuf->pathqu =
  783.         ((nbrbuf->nbrpor = port) == 0)?
  784.         ch0qua : ch1qua;
  785.       nbrbuf->locked =
  786.       nbrbuf->nbrrou = 0;
  787.       nbrbuf->nbrl2l = NULL;
  788.       relink(nbrbuf, neigbl.lprev);
  789.     }
  790.   return(nbrbuf);            /* mit Pointer auf Eintrag zurueck   */
  791.   }
  792.  
  793. /*---------------------------------------------------------------------------*/
  794. nbrtyp    *getnei(digis, name, port)    /* Nachbarn suchen             */
  795.   char       *digis;
  796.   char       *name;
  797.   unsigned port;
  798.   {
  799.   nbrtyp   *nachb;
  800.  
  801.     for (nachb  = (nbrtyp *) neigbl.lnext;
  802.          nachb != (nbrtyp *) &neigbl.lnext;
  803.          nachb  = (nbrtyp *) nachb->nbrlnk.lnext)
  804.       {
  805.         if (isneig(digis, name, port, nachb) == TRUE) return (nachb);
  806.       }
  807.     return(NULL);
  808.   }
  809.  
  810. /*---------------------------------------------------------------------------*/
  811. nbrprt(call)            /* Port fuer Ziel "call" suchen?         */
  812. char    *call;
  813.   {
  814.   nbrtyp   *nachb;        /* aktueller Nachbar                 */
  815.  
  816.   for (nachb  = (nbrtyp *) neigbl.lnext;    /* Nachbarnliste absuchen    */
  817.        nachb != (nbrtyp *) &neigbl.lnext;
  818.        nachb  = (nbrtyp *) nachb->nbrlnk.lnext)
  819.     {
  820.       if (cmpid(call, nachb->nbrcal) == TRUE)
  821.         {
  822.           return(nachb->nbrpor);
  823.         }
  824.     }
  825.  
  826.   if (isidnt(call) == TRUE)
  827.     {
  828.       for (nachb  = (nbrtyp *) neigbl.lnext;
  829.            nachb != (nbrtyp *) &neigbl.lnext;
  830.            nachb  = (nbrtyp *) nachb->nbrlnk.lnext)
  831.         {
  832.           if (cmpid(&nachb->nbrcal[0], &despoi->nodcal[0]) == TRUE)
  833.             return(nachb->nbrpor);
  834.         }
  835.     }
  836.   return(0);            /* HDLC als default                 */
  837.   }
  838.  
  839. /*---------------------------------------------------------------------------*/
  840. BOOLEAN    iscall(call)        /* ist Call als Ziel eingetragen?         */
  841. char    *call;
  842.   {
  843.   for (despoi  = (nodtyp *) destil.lnext;        /* Zielliste absuchen                 */
  844.        despoi != (nodtyp *) &destil.lnext;
  845.        despoi  = (nodtyp *) despoi->nodlnk.lnext) {
  846.     if (despoi->nodcal[0] != 0) { /* Eintrag definiert?                 */
  847.       if (cmpid(call, despoi->nodcal) == 1) /* dann testen             */
  848.         return(TRUE);
  849.     } }
  850.   return(FALSE);
  851.   }
  852.  
  853. /*---------------------------------------------------------------------------*/
  854. BOOLEAN    isidnt(ident)        /* ist Ident als Ziel eingetragen?         */
  855. char    *ident;
  856.   {
  857.   for (despoi  = (nodtyp *) destil.lnext;    /* Zielliste absuchen         */
  858.        despoi != (nodtyp *) &destil.lnext;
  859.        despoi  = (nodtyp *) despoi->nodlnk.lnext) {
  860.     if (despoi->nodcal[0] != 0) { /* Eintrag definiert?                 */
  861.       if (cmpcal(ident, despoi->nodide) == 1) /* dann testen             */
  862.         return(TRUE);
  863.     } }
  864.   return(FALSE);
  865.   }
  866.  
  867. /*---------------------------------------------------------------------------*/
  868. istweg(digis, call, port)        /* Test, ob ein Weg existiert         */
  869.   char       *digis;            /* Digiliste                 */
  870.   char       *call;            /* Call des Nachbarn             */
  871.   char       port;            /* Port fuer den Weg             */
  872.   {                    /* Rueckgabe: Weg-Nummer         */
  873.   unsigned cnt;                /* Scratch Zaehler             */
  874.  
  875.   for (cnt = 0;
  876.        cnt < despoi->wege;
  877.        ++cnt)                /* alle Wege zum Ziel testen         */
  878.     {
  879.       if (isneig(digis, call, port, despoi->weg[cnt].nachba) == TRUE)
  880.         return(cnt);
  881.     }
  882.   return(-1);                /* Fehler, nicht gefunden         */
  883.   }
  884.  
  885. /*---------------------------------------------------------------------------*/
  886. BOOLEAN    isrout(buffer)        /* Test, ob buffer in Weglisten ist         */
  887. nbrtyp    *buffer;
  888.   {
  889.   nbrtyp *nachb;
  890.  
  891.   for (nachb  = (nbrtyp *) neigbl.lnext;    /* Nachbarnliste absuchen    */
  892.        nachb != (nbrtyp *) &neigbl.lnext;
  893.        nachb  = (nbrtyp *) nachb->nbrlnk.lnext)
  894.     {
  895.       if (nachb == buffer) return(TRUE);
  896.     }
  897.  
  898.   for (despoi  = (nodtyp *) destil.lnext;    /* Zielliste absuchen         */
  899.        despoi != (nodtyp *) &destil.lnext;
  900.        despoi  = (nodtyp *) despoi->nodlnk.lnext)
  901.     {
  902.       if (despoi == (nodtyp *) buffer) return(TRUE);
  903.     }
  904.   return(FALSE);        /* nicht gefunden                 */
  905.   }
  906.  
  907. /*---------------------------------------------------------------------------*/
  908. BOOLEAN    isneig(digis, call, port, nachb) /* Test, ob Daten in Nachbarliste   */
  909. char    *digis;            /* Digipeaterliste                 */
  910. char    *call;            /* Call                         */
  911. char    port;            /* Port                         */
  912. nbrtyp    *nachb;            /* Pointer auf vermuteten Eintrag in Liste   */
  913.   {
  914.   return((nachb->nbrpor == port)
  915.       && (cmpid(nachb->nbrcal, call) == 1)
  916.       && (cmpidl(nachb->nbrdil, digis) == 1));
  917.   }
  918.  
  919. /*---------------------------------------------------------------------------*/
  920. BOOLEAN    ge6chr(buffer, mbhd)    /* 6 Zeichen aus mbhd nach Buffer         */
  921. char    *buffer;        /* Rueckgabe: TRUE=hat funktioniert         */
  922. mhtyp    *mbhd;
  923.   {
  924.   unsigned cnt;            /* Zaehler                     */
  925.  
  926.   if ((mbhd->putcnt - mbhd->getcnt) >= 6) { /* genug Zeichen da?         */
  927.     for (cnt = 0; cnt < 6; ++cnt) {
  928.       *buffer++ = getchr(mbhd);    /* Zeichen holen, ablegen             */
  929.       }
  930.     return(TRUE);        /* Erfolg melden                 */
  931.     }
  932.   else return(FALSE);        /* nicht genug Zeichen im mbhd             */
  933.   }
  934.  
  935. /*---------------------------------------------------------------------------*/
  936. VOID    pu6chr(buffer, mbhd)    /* 6 Zeichen aus Buffer in mbhd             */
  937. char    *buffer;
  938. mhtyp    *mbhd;
  939.   {
  940.   unsigned cnt;            /* Zaehler                     */
  941.  
  942.   for (cnt = 0; cnt < 6; ++cnt) {
  943.     putchr(*buffer++, mbhd);
  944.   } }
  945.  
  946. /*---------------------------------------------------------------------------*/
  947. VOID    cpy6ch(dest, src)
  948.   char    *src;
  949.   char    *dest;
  950.   {
  951.   unsigned cnt;
  952.  
  953.   for (cnt = 0; cnt < 6; ++cnt)
  954.     {
  955.       *dest++ = *src++;
  956.     }
  957.   }
  958.  
  959. /*- Ende Level 3 ------------------------------------------------------------*/
  960.