home *** CD-ROM | disk | FTP | other *** search
/ Hacker Chronicles 2 / HACKER2.BIN / 554.TNL7U.C < prev    next >
Text File  |  1988-05-14  |  26KB  |  656 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 7, Utilities                                 */
  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 "tnl7ue.h"        /* externe Definitionen                 */
  29.  
  30. /*---------------------------------------------------------------------------*/
  31. VOID    kilusr()        /* User abwerfen                 */
  32.   {
  33.   mhtyp    *bufpoi;        /* MBHD fuer Meldungen                 */
  34.  
  35.   if ((bufpoi = userpo->mbhd) != 0) /* noch Info im Buffer?             */
  36.     dealmb(bufpoi);        /* dann vernichten                 */
  37.  
  38.   dealoc(unlink(userpo));    /* User Kontrollblock auch wieder frei         */
  39.   userpo = 0;            /* Userpointer ungueltig machen             */
  40.   }
  41.  
  42. /*---------------------------------------------------------------------------*/
  43. VOID    invcal()        /* ungueltiges Rufzeichen melden         */
  44.   {
  45.   putmsg("Invalid Call");
  46.   }
  47.  
  48. /*---------------------------------------------------------------------------*/
  49. VOID    makcon(usrp)        /* Verbindung melden, Eintrag herstellen     */
  50. usrtyp *usrp;                /* Userkontrollblock             */
  51.   {
  52.   msgfrm('U', (ptcrdp->luserl = usrp->cblk_u),
  53.               (ptcrdp->lusert = usrp->typ_u), conmsg);
  54.   }
  55.  
  56. /*---------------------------------------------------------------------------*/
  57. VOID    msgfrm(seite, link, user, msg) /* Systemstatus melden             */
  58. unsigned seite;            /* Uplink - Downlink                 */
  59. ctyp     *link;            /* Kontrollblock des Users             */
  60. unsigned user;            /* Usertyp: 0=Host, 2=Level2, 4=Circuit         */
  61. char     *msg;            /* Meldung                     */
  62.   {
  63.   mhtyp    *bufpoi;                /* MBHD der Meldung         */
  64.  
  65.   bufpoi = putals(msg);                /* Meldung ausgeben         */
  66.   if (seite == 'D')                /* Downlink?             */
  67.    {
  68.     if (user == 4)                /* User ist Circuit?         */
  69.       putalt(link->l3blk.l3node->nodide, bufpoi);    /* dann Ident vorweg         */
  70.     else                    /* Level2 oder Host?         */
  71.      if (user == 0)
  72.        putalt(alias, bufpoi);            /* bei Host auch Ident         */
  73.    }
  74.   putid(calofs(seite, link, user), bufpoi);    /* Call immer ausgeben         */
  75.   seteom(bufpoi);                /* Ende Kennung dazu         */
  76.   }
  77.  
  78. /*---------------------------------------------------------------------------*/
  79. VOID    puttfu(name)        /* Tabelle voll melden                 */
  80. char    *name;            /* Tabellenname                     */
  81.   {
  82.   mhtyp    *bufpoi;        /* MBHD der Meldung                 */
  83.  
  84.   putstr(" table full", (bufpoi = putals(name))); /* Meldung             */
  85.   seteom(bufpoi);        /* Ende Kennung dazu                 */
  86.   }
  87.  
  88. /*---------------------------------------------------------------------------*/
  89. VOID    putmsg(string)        /* Meldung an User ausgeben             */
  90. char    *string;
  91.   {
  92.   seteom(putals(string));    /* Meldung mit Endekennung raus             */
  93.   }
  94.  
  95. /*---------------------------------------------------------------------------*/
  96. mhtyp    *putals(string)        /* String nach Nodeident in neuen Buffer     */
  97. char    *string;        /* Rueckgabe: Pointer auf neuen Buffer         */
  98.   {
  99.   mhtyp    *bufpoi;        /* neuer Buffer                     */
  100.  
  101.   bufpoi = (mhtyp *) allocb();        /* neuen Buffer holen                 */
  102.   bufpoi->l2lnk = userpo->cblk_u; /* Level2 Kontrollblock in Buffer eintragen*/
  103.   bufpoi->usrtyp = userpo->typ_u; /* Usertyp                     */
  104.  
  105.   putalt(alias, bufpoi);    /* Ident schreiben                 */
  106.   putid(myid, bufpoi);        /* Call schreiben                 */
  107.   putstr("> ", bufpoi);        /* Trennzeichen                     */
  108.   putstr(string, bufpoi);    /* String dazu                     */
  109.   return(bufpoi);
  110.   }
  111.  
  112. /*---------------------------------------------------------------------------*/
  113. VOID    putrou(neigb, mbhd)    /* Weg zu einem Nachbarn ausgeben         */
  114. nbrtyp  *neigb;                /* Pointer auf den Nachbarn         */
  115. mhtyp   *mbhd;                /* Buffer fuer die Meldung         */
  116.   {
  117.   putstr((neigb->nbrl2l == NULL)? "\015 " : "\015>", mbhd); /* aktiver Weg?  */
  118.   putnbr(neigb, mbhd);                /* Nachbarn ausgeben         */
  119.   putchr(' ', mbhd);                /* Leerraum             */
  120.   putnum((neigb->pathqu & 0xff), mbhd);        /* Qualitaet des Weges         */
  121.   putchr(' ', mbhd);                /* Leerraum             */
  122.   putnum(neigb->nbrrou, mbhd);            /* Zahl der Links         */
  123.   if (neigb->locked == TRUE)            /* Eintrag blockiert?         */
  124.     putstr(" !", mbhd);                /* dann markieren         */
  125.   }
  126.  
  127. /*---------------------------------------------------------------------------*/
  128. VOID    putnbr(neigb, mbhd)    /* Daten eines Nachbarn ausgeben         */
  129. nbrtyp  *neigb;                /* Pointer auf den Nachbarn         */
  130. mhtyp   *mbhd;                /* Buffer fuer die Meldung         */
  131.   {
  132.   putchr(' ', mbhd);            /* Trennzeichen                 */
  133.   putnum(neigb->nbrpor, mbhd);        /* Port Nummer                 */
  134.   putchr(' ', mbhd);            /* Trennzeichen                 */
  135.   putid(neigb->nbrcal, mbhd);        /* Call                     */
  136.   putdil(neigb->nbrdil, mbhd);        /* Digiliste                 */
  137.   }
  138.  
  139. /*---------------------------------------------------------------------------*/
  140. VOID    putuse(seite, link, typ, mbhd) /* User Daten in MBHD legen         */
  141. mhtyp     *mbhd;            /* Kopf der Messageliste             */
  142. unsigned typ;            /* Usertyp: 0=Host, 2=Level2, 4=Circuit         */
  143. ctyp     *link;            /* Kontrollblock                 */
  144. unsigned seite;            /* L=uplink, R=downlink                 */
  145.   {
  146.   switch (typ) {
  147. /*==============================*/
  148.   case 4:            /* User ist Circuit                 */
  149.     putstr("Circuit(", mbhd);
  150.     putalt(link->l3blk.l3node->nodide, mbhd); /* Node ID                 */
  151.     putid(link->l3blk.downca, mbhd);    /* Node Call                     */
  152.     putchr(' ', mbhd);
  153.     putid(link->l3blk.upcall, mbhd);    /* User Call                     */
  154.     putchr(')', mbhd);        /* Ende dieser Seite                 */
  155.     break;
  156.  
  157. /*==============================*/
  158.   case 2:            /* User ist Level2                 */
  159.     if (seite == 'L') {        /* Uplink oder Downlink?             */
  160.       putstr("Uplink(", mbhd);    /* Uplink:                     */
  161.       putid(link->l2blk.dstid, mbhd);    /* User Call                     */
  162.       putchr(')', mbhd);
  163.       }
  164.     else {            /* Downlink:                     */
  165.       putstr("Downlink(", mbhd);
  166.       putid(link->l2blk.srcid, mbhd);    /* User Call                     */
  167.       putchr(' ', mbhd);
  168.       putid(link->l2blk.dstid, mbhd);    /* Gegenstation                     */
  169.       putchr(')', mbhd);
  170.       }
  171.     break;
  172.  
  173. /*==============================*/
  174.   default:            /* User ist Host                 */
  175.     putstr("Host(", mbhd);
  176.     putalt(alias, mbhd);    /* Host ID                     */
  177.     putid(myid, mbhd);        /* Host Call                     */
  178.     putchr(')', mbhd);
  179.     break;
  180.     }
  181.   }
  182.  
  183. /*---------------------------------------------------------------------------*/
  184. VOID    putdil(liste, mbhd)    /* Digiliste in MBHD legen             */
  185. mhtyp    *mbhd;            /* Kopf der Messageliste             */
  186. char    *liste;            /* Digiliste, 0 am Ende                 */
  187.   {
  188.   if (*liste != 0) {        /* existiert die Liste?                 */
  189.     putstr(" via", mbhd);
  190.     while (*liste != 0) {    /* so lange der Vorrat reicht             */
  191.       putchr(' ', mbhd);    /* Trennzeichen                     */
  192.       putid(liste, mbhd);    /* Digi ausgeben                 */
  193.       liste += 7;        /* naechster Digi                 */
  194.       }
  195.     }
  196.   }
  197.  
  198. /*---------------------------------------------------------------------------*/
  199. VOID    putid(call, mbhd)    /* Call mit SSID in MBHD legen             */
  200. mhtyp    *mbhd;            /* Kopf der Messageliste             */
  201. char    *call;            /* Call                         */
  202.   {
  203.   char       ssid;        /* SSID des Calls                 */
  204.   char       zeichen;        /* Scratch bei Ausgabe                 */
  205.   unsigned cnt;            /* zaehlt Zeichen                 */
  206.  
  207.   for (cnt = 0; cnt < 6; ++cnt) { /* 6 Zeichen Call                 */
  208.     zeichen = *call++;        /* naechstes Zeichen holen             */
  209.  
  210.     if (zeichen > ' ')        /* druckbar?                     */
  211.       putchr(zeichen, mbhd);    /* dann raus                     */
  212.  
  213.     else {            /* nicht druckbar:                 */
  214.       if (zeichen < ' ') {    /* Leerzeichen uebergehen             */
  215.         putchr('^', mbhd);    /* Kontrollzeichen mit Prefix             */
  216.         putchr((zeichen + '@'), mbhd);
  217.         }
  218.       }
  219.     }
  220.   ssid = (*call >> 1) & 0x0f;    /* SSID passend schieben             */
  221.   if (ssid != 0) {        /* nur SSID != 0 ausgeben             */
  222.     putchr('-', mbhd);        /* mit Trennstrich                 */
  223.     putnum(ssid, mbhd);
  224.     }
  225.   }
  226.  
  227. /*---------------------------------------------------------------------------*/
  228. VOID    putnod(mbhd)        /* Knoten Info in MBHD legen             */
  229. mhtyp    *mbhd;            /* Kopf der Messageliste             */
  230.   {
  231.   putalt(despoi->nodide, mbhd);    /* Ident ausgeben                 */
  232.   putid(despoi->nodcal, mbhd);    /* und Call                     */
  233.   }
  234.  
  235. /*---------------------------------------------------------------------------*/
  236. VOID    putalt(ident, mbhd)    /* Ident in Buffer MBHD legen             */
  237. mhtyp    *mbhd;            /* Kopf der Messageliste             */
  238. char    *ident;            /* auszugebender Ident                 */
  239.   {
  240.   if (*ident != ' ') {        /* ueberhaupt definiert?             */
  241.     putcal(ident, mbhd);    /* dann ausgeben                 */
  242.     putchr(':', mbhd);        /* Trennzeichen hinterher             */
  243.     }
  244.   }
  245.  
  246. /*---------------------------------------------------------------------------*/
  247. VOID    putcal(call, mbhd)    /* Call in Buffer MBHD legen             */
  248. mhtyp    *mbhd;            /* Kopf der Messageliste             */
  249. char    call[];            /* auszugebendes Call                 */
  250.   {
  251.   char       zeichen;        /* Scratch fuer aktuelles Zeichen         */
  252.   unsigned cnt;            /* Zaehler fuer Zeichen im Call             */
  253.  
  254.   for (cnt = 0; cnt < 6; ++cnt) { /* Call ist immer 6 Zeichen lang         */
  255.     zeichen = call[cnt];
  256.     if (zeichen == ' ')        /* Leerzeichen nicht ausgeben             */
  257.       break;
  258.     putchr(zeichen, mbhd);
  259.     }
  260.   }
  261.  
  262. /*---------------------------------------------------------------------------*/
  263. VOID    putnum(zahl, mbhd)    /* Zahl in Buffer MBHD legen             */
  264. mhtyp     *mbhd;            /* Kopf der Messageliste             */
  265. unsigned zahl;            /* auszugebende Zahl                 */
  266.   {
  267.   unsigned notnul;        /* fuehrende Null j/n                 */
  268.   unsigned diviso;        /* Stellenwert der aktuellen Stelle         */
  269.   unsigned ziffer;        /* aktuelle Ziffer                 */
  270.   unsigned numcnt;        /* Zahl der ausgegebenen Ziffern         */
  271.  
  272.   notnul = 0;
  273.   diviso = 10000;
  274.   for(numcnt = 0; numcnt < 5; ++numcnt) {
  275.     ziffer = zahl / diviso;
  276.     if ((ziffer != 0) || (notnul == 1) || (diviso == 1)) {
  277.       putchr((ziffer + '0'), mbhd); /* Stelle ausgeben                 */
  278.       notnul = 1;
  279.       }
  280.     zahl %= diviso;
  281.     diviso /= 10;
  282.     }
  283.   }
  284.  
  285. /*---------------------------------------------------------------------------*/
  286. VOID    putstr(string, mbhd)    /* String in Buffer MBHD legen             */
  287. mhtyp    *mbhd;            /* Kopf der Messageliste             */
  288. char    *string;        /* auszugebender String                 */
  289.   {
  290.   while (*string != 0) {    /* so lange der Vorrat reicht             */
  291.     putchr(*string++, mbhd);    /* weg damit                     */
  292.     }
  293.   }
  294.  
  295. /*---------------------------------------------------------------------------*/
  296. VOID    putspa(stop, mbhd)    /* bis stop die Zeile mit Space fuellen         */
  297. unsigned stop;                /* Ende der Leerraeume             */
  298. mhtyp    *mbhd;                /* Buffer der Meldung             */
  299.   {
  300.   unsigned cnt;                /* Scratch Zaehler             */
  301.  
  302.   cnt = mbhd->l4time + stop - mbhd->putcnt;
  303.   while (cnt--)
  304.    {
  305.     putchr(' ', mbhd);
  306.    }
  307.   }
  308.  
  309. /*---------------------------------------------------------------------------*/
  310. BOOLEAN getqua()
  311.   {
  312.    return (
  313.               (skipsp(&clicnt, &clipoi) == TRUE)
  314.            && ((nquali = nxtnum(&clicnt, &clipoi)) <= 255)
  315.           );
  316.   }
  317.  
  318.  
  319. /*---------------------------------------------------------------------------*/
  320. BOOLEAN getpar()        /* Parameter fuer Ziel holen             */
  321.   {
  322.    return (
  323.              (skipsp(&clicnt, &clipoi) == TRUE)
  324.            && ((nport = nxtnum(&clicnt, &clipoi)) < 2)
  325.            && (getcal(&clicnt, &clipoi, VCpar, ncall) == TRUE)
  326.            && (getdig(&clicnt, &clipoi, FALSE, ndigi) != ERROR)
  327.            );
  328.   }
  329.  
  330. /*---------------------------------------------------------------------------*/
  331. getdig(laenge, inbuf, pflag, outbuf)          /* Digiliste aus Buffer holen  */
  332. unsigned *laenge;        /* Laenge des Eingabebuffers             */
  333. char     *(*inbuf);        /* Eingabebuffer                 */
  334. char     pflag;            /* Call-pruefen Flag                 */
  335. char     *outbuf;        /* Ziel fuer das Call                 */
  336.   {
  337.   char       liste[8*7 +1];    /* Zwischenspeicher                 */
  338.   char       *lispoi;        /* Pointer in liste                 */
  339.   char       *ibufer;        /* Kopie von inbuf                 */
  340.   unsigned ilaeng;        /* Kopie von laenge                 */
  341.   unsigned cnt;            /* Zaehler, Scratch                 */
  342.   unsigned zeichen;        /* Scratch                     */
  343.   unsigned caltyp;        /* Typ des letzten Call: 0=leer, -1=niO, 1=OK*/
  344.  
  345.   ibufer = *inbuf;        /* eine Indirektion weniger             */
  346.   ilaeng = *laenge;
  347.   if (getcal(&ilaeng, &ibufer, 0, liste) == 1) { /* Call da?             */
  348.     lispoi = liste;        /* koennte "VIA" vorher sein             */
  349.     if (*lispoi++ == 'V') {    /* stimmt erstes Zeichen?             */
  350.       for (cnt = 0; cnt < 5; ++cnt) { /* ja: max 5 Zeichen testen         */
  351.         zeichen = *lispoi++;    /* naechstes Zeichen                 */
  352.         if (zeichen != ' ') {    /* Ende von "VIA"?                 */
  353.           if (!((cnt == 0) && (zeichen == 'I') ||
  354.               (cnt == 1) && (zeichen == 'A')))
  355.             break;        /* Rechtschreibung muss stimmen             */
  356.           }
  357.         }
  358.       if (cnt == 5) {        /* VIA + ' ' = 4                 */
  359.         *inbuf = ibufer;    /* wenn nicht VIA gefunden, korrigieren         */
  360.         *laenge = ilaeng;
  361.         }
  362.       }
  363.     }
  364.  
  365.   for (cnt = 0, lispoi = liste; cnt < 8; ++cnt, lispoi +=7)
  366.    {                        /* maximal 8 Digis         */
  367.     if (*laenge != 0)
  368.      {
  369.       if (((zeichen = *(*inbuf)) == '+')
  370.          ||(zeichen == '-'))
  371.         break;
  372.      }
  373.     if ((caltyp = getcal(laenge, inbuf, pflag, lispoi)) == -1) /* ungueltig? */
  374.       return(-1);                /* Abbruch             */
  375.     if (caltyp == 0) break;            /* nichts mehr da: Ende         */
  376.    }
  377.  
  378.   *lispoi = 0;                    /* Endekennung             */
  379.   cpyidl(outbuf, liste);            /* in Ziel kopieren         */
  380.   return(*outbuf != 0);                /* Erfolg melden         */
  381.   }
  382.  
  383. /*---------------------------------------------------------------------------*/
  384. getcal(laenge, inbuf, pflag, outbuf) /* Call aus Buffer holen             */
  385. unsigned *laenge;        /* Laenge des Eingabebuffers             */
  386. char     *(*inbuf);        /* Eingabebuffer                 */
  387. char     pflag;            /* Call-pruefen Flag                 */
  388. char     *outbuf;        /* Ziel fuer das Call                 */
  389.   {
  390.   char       call[7];        /* Zwischenspeicher                 */
  391.   char       binsid;        /* SSID, binaer                     */
  392.   char       *bufpoi;        /* Pointer in Call                 */
  393.   char       zeichen;        /* Scratch                     */
  394.   unsigned cnt;            /* Zaehler, Scratch                 */
  395.  
  396.   bufpoi = call;        /* auf Anfang                     */
  397.   for (cnt = 0; cnt < 6; ++cnt)    /* Zwischenspeicher loeschen             */
  398.     *bufpoi++ = ' ';
  399.   *bufpoi = 0x60;        /* kein SSID                     */
  400.  
  401.   skipsp(laenge, inbuf);    /* auf erstes Zeichen != ' '             */
  402.  
  403.   bufpoi = call;        /* wieder nach vorn                 */
  404.   cnt = 0;            /* gelesene Zeichen = 0                 */
  405.   while (*laenge != 0) {    /* so lange Zeichen da sind             */
  406.     if (((zeichen = upcase(*(*inbuf)))/* und gueltig                 */
  407.        == ' ' ) || (zeichen == ',')) break;
  408.     if (zeichen < ' ') return(ERROR);
  409.     if (zeichen == '-') {    /* Trennung zum SSID?                 */
  410.       if ((cnt == 0) || (*laenge == 0))
  411.         return(ERROR);        /* Fehler: kein Call oder SSID             */
  412.       ++(*inbuf);        /* Trennung uebergehen                 */
  413.       --(*laenge);
  414.       if (*laenge == 0) return (ERROR); /* SSID angesagt, kommt aber nicht   */
  415.       zeichen = *(*(inbuf));    /* erste Ziffer SSID holen             */
  416.       if ((zeichen < '0') || (zeichen > '9'))
  417.         return(ERROR);        /* ungueltige Ziffer                 */
  418.       ++(*inbuf);
  419.       --(*laenge);        /* Ziffer ist verbraucht             */
  420.       binsid = (zeichen + 0xffd0); /* Binaer merken                 */
  421.       if (*laenge != 0) {    /* noch Zeichen da?                 */
  422.         zeichen = *(*inbuf);    /* holen                     */
  423.         if ((zeichen >= '0') && (zeichen <= '9')) { /* gueltige Ziffer?         */
  424.           binsid *= 10;        /* erste Ziffer eine Stelle nach links         */
  425.           binsid += (zeichen + 0xffd0) ; /* + neue Ziffer             */
  426.           if (binsid > 15)
  427.             return(ERROR);        /* ungueltiger SSID             */
  428.           ++(*inbuf);        /* letzte Ziffer verbrauchen             */
  429.           --(*laenge);
  430.           }
  431.         }
  432.       call[6] = (binsid << 1) | 0x60; /* SSID merken                 */
  433.       break;
  434.       }
  435.     else {            /* kein SSID, anderes Zeichen             */
  436.       if (cnt++ == 6)
  437.         return(ERROR);        /* Call zu lang                     */
  438.       *bufpoi++ = zeichen;    /* Zeichen merken                 */
  439.       ++(*inbuf);        /* Lesepointer rauf                 */
  440.       --(*laenge);
  441.       }
  442.     }
  443.                 /* Call ist im Buffer                 */
  444.   while (*laenge != 0) {    /* Rest des Buffers ansehen             */
  445.     zeichen = *(*inbuf);    /* Zeichen holen                 */
  446.     if ((zeichen != ' ') && (zeichen != ','))
  447.       break;            /* kein Trennzeichen, stop             */
  448.     ++(*inbuf);            /* naechstes Zeichen                 */
  449.     --(*laenge);
  450.     if (zeichen == ',') break;    /* Leerraum uebergehen                 */
  451.     }
  452.   if (cnt == 0) return(0);    /* Call war leer                 */
  453.   if (fvalca(pflag, call) == ERROR)
  454.     return(ERROR);            /* Call war ungueltig             */
  455.   cpyid(outbuf, call);        /* Call kopieren                 */
  456.   return(1);            /* ok melden                     */
  457.   }
  458.  
  459. /*---------------------------------------------------------------------------*/
  460. unsigned getide(buffer)        /* Ident aus cli-Buffer holen             */
  461. char    buffer[];        /* -1=kein Erfolg, 0=leer, 1=Erfolg         */
  462.   {
  463.   char       ident[6];        /* Zwischenspeicher                 */
  464.   char       zeichen;        /* Scratch                     */
  465.   unsigned cnt;            /* Zaehler, Scratch                 */
  466.  
  467.   cpy6ch(ident, nulide);            /* Zwichenspeicher loeschen  */
  468.  
  469.   for (cnt = 0; (cnt < 6) && (clicnt != 0); ++cnt)
  470.     {
  471.       --clicnt;            /* so lange Zeichen da und Buffer nicht voll */
  472.       zeichen = upcase(*clipoi++);/* Zeichen aus CLI-Buffer holen         */
  473.       if (zeichen != ' ')        /* Schluss bei Trennzeichen         */
  474.         {
  475.           if (((zeichen >= 'A') && (zeichen <= 'Z'))
  476.              || ((zeichen >= '0') && (zeichen <= '9'))
  477.              || ((cnt == 0) && (zeichen == '#'))) /* gueltiges Zeichen?         */
  478.             {
  479.               ident[cnt] = zeichen;
  480.               continue;
  481.             }
  482.           if ((cnt != 0) || (zeichen != '*')) return(-1); /* '*' als Ident   */
  483.         }
  484.       break;
  485.     }
  486.  
  487.   if ((cnt == 6) && (clicnt != 0) && (*clipoi) != ' ')
  488.     return(-1);            /* Ident zu lang? Fehler melden             */
  489.  
  490.   if (valcal(ident) == 1)
  491.     return(-1);            /* Ident darf kein Call sein             */
  492.  
  493.   cpy6ch(buffer, ident);            /* umkopieren             */
  494.  
  495.   return(ident[0] != ' ');
  496.   }
  497.  
  498. /*---------------------------------------------------------------------------*/
  499. unsigned nxtnum(laenge, buffer)    /* Zahl aus Buffer holen             */
  500. char     *(*buffer);        /* Buffer                     */
  501. unsigned *laenge;        /* Laenge des Buffers                 */
  502.   {
  503.   unsigned temp;        /* Scratch                     */
  504.  
  505.   skipsp(laenge, buffer);    /* auf erstes Zeichen != ' '             */
  506.   temp = 0;            /* Ergebniss = 0                 */
  507.   while ((*laenge != 0) && (*(*buffer) >= '0') && (*(*buffer) <='9')) {
  508.     --*laenge;            /* mitzaehlen                     */
  509.     temp *= 10;            /* Ergebniss eine Stelle weiter             */
  510.     temp += (*(*buffer)++ + 0xffd0);/* + naechstes Digit             */
  511.     }
  512.   return (temp);        /* mit Ergebniss zurueck             */
  513.   }
  514.  
  515. /*---------------------------------------------------------------------------*/
  516. fvalca(pflag, call)        /* Call pruefen: 0=leeres call, ohne Flag    */
  517. char    *call;            /* -1=niO (m. Flag), 1=ok oder o. Flag         */
  518. BOOLEAN pflag;
  519.   {
  520.   if (*call == ' ' ) return(0);    /* leer                         */
  521.   if (!pflag) return (1);    /* nicht pruefen                 */
  522.   return (valcal(call));    /* pruefen, valcal liefert Ergebniss         */
  523.   }
  524.  
  525. /*---------------------------------------------------------------------------*/
  526. valcal(call)            /* Call auf Gueltigkeit pruefen             */
  527. char    *call;            /* -1=ungueltiges Zeichen, 1=Call ist ok     */
  528.   {
  529.   char       *numpos;        /* Position der Zahl im Call             */
  530.   char       *actual;        /* Pointer auf aktuelles Zeichen         */
  531.   char       zeichen;        /* aktuelles Zeichen                 */
  532.   unsigned zahl;        /* Zahlen im Call                 */
  533.   unsigned cnt;            /* gepruefte Zeichen                 */
  534.  
  535.   for (
  536.     zahl = 0,            /* keine Zahl gefunden                 */
  537.     cnt = 0,            /* nichts geprueft                 */
  538.     actual = call;        /* auf Anfang                     */
  539.     cnt < 6;            /* maximal 6 Zeichen Call             */
  540.     ++cnt, ++actual) {
  541.     if ((zeichen = *actual) == ' ') /* Ende des Calls?                 */
  542.       break;
  543.     if (!((zeichen >= 'A') && (zeichen <= 'Z'))){ /* Alfa ist immer gut         */
  544.       if ((zeichen >= '0') && (zeichen <= '9')) {
  545.         zahl += 1;        /* Zahlen zaehlen                 */
  546.         numpos = actual;    /* Position merken                 */
  547.       }
  548.       else return(-1);        /* ungueltiges Zeichen im Call             */
  549.       }
  550.     }
  551.   if (
  552.        ((actual - call) < 4)    /* minimal 4 Zeichen                 */
  553.     || (zahl == 0)        /* mindestens 1 Zahl                 */
  554.     || (zahl > 2)        /* maximal 2 Zahlen                 */
  555.     || (numpos == call)        /* keine Zahl an erster Stelle             */
  556.     || (numpos == (actual -1)))    /* mindestens 2 Buchstaben Suffix         */
  557.     return(-1);            /* Call ist ungueltig                 */
  558.   else return(+1);        /* Call ist gueltig                 */
  559.   }
  560.  
  561. /*---------------------------------------------------------------------------*/
  562. BOOLEAN ismemr()        /* Test auf genuegend freien Speicher         */
  563.   {
  564.   if((nmbfre < 256) && (!userpo->sysflg))    /* Platz oder Sysop?         */
  565.    {
  566.     putmsg("Node busy");
  567.     return(FALSE);
  568.    }
  569.   cpyid(usrcal, calofs('U', userpo->cblk_u, userpo->typ_u));
  570.   return(TRUE);
  571.   }
  572.  
  573. /*---------------------------------------------------------------------------*/
  574. VOID setl2b()            /* User Kontrollblock aufbauen             */
  575.   {
  576.   userpo->cblk_p = lnkpoi;            /* Pointer auf L2-Block         */
  577.   userpo->typ_p = 2;                /* Partner ist L2         */
  578.   userpo->status = 2;                /* Status: connect laeuft    */
  579.   cpyid(lnkpoi->srcid, usrcal);            /* Call eintragen         */
  580.   }
  581.  
  582. /*---------------------------------------------------------------------------*/
  583. char *calofs(seite, link, user)    /* Offset Call-String im Kontrollblock         */
  584. unsigned user;            /* Usertyp: 0=Host, 2=L2-User, 4=Circuit     */
  585. ctyp     *link;            /* Linkkontrollblock                 */
  586. unsigned seite;            /* Seite der Verbindung: U=uplink, D=downlink*/
  587.   {
  588.   if (user == 4) {        /* Circuit?                     */
  589.     return ((seite == 'D') ?    /* welche Seite?                 */
  590.       link->l3blk.downca : link->l3blk.upcall);
  591.     }
  592.   if (user == 2)        /* L2-User?                     */
  593.     return(link->l2blk.dstid);
  594.   else return(myid);        /* muss Host sein                 */
  595.   }
  596.  
  597. /*---------------------------------------------------------------------------*/
  598. BOOLEAN getlin(mbhd)        /* Zeile im Messagebuffer verfuegbar?         */
  599. mhtyp    *mbhd;
  600.   {
  601. char     *nextch;        /* naechstes Zeichen                 */
  602. unsigned getcou;        /* verfuegbare Zeichen                 */
  603. BOOLEAN  found;            /* Flag: Ueberlauf                 */
  604. unsigned laenge;        /* Laenge der Zeile                 */
  605.  
  606.   nextch = mbhd->nxtchr;    /* Pointer auf naechstes Zeichen         */
  607.   getcou = mbhd->getcnt;    /* verfuegbare Zeichen                 */
  608.   found = FALSE;        /* default: Zeile nicht da             */
  609.   laenge = 0;            /* Laenge initialisieren             */
  610.   while (mbhd->getcnt < mbhd->putcnt) { /* so lange Vorrat reicht         */
  611.     if (((getchr(mbhd) & 0x7f) == 0x0d) /* Zeichen = Zeilenende?         */
  612.       || (++laenge == 81)){    /* Zeile zu lang?                 */
  613.       found = TRUE;        /* markieren                     */
  614.       break;
  615.      }
  616.     }
  617.   mbhd->nxtchr = nextch;    /* MBHD auf alte Werte zurueck             */
  618.   mbhd->getcnt = getcou;
  619.   return (found);
  620.   }
  621.  
  622. /*---------------------------------------------------------------------------*/
  623. invsid()            /* SSID umdrehen                 */
  624.   {
  625.   usrcal[6] = 0x7e - (usrcal[6] & 0x1e);
  626.   }
  627.  
  628. /*---------------------------------------------------------------------------*/
  629. BOOLEAN issyso()        /* Test auf Sysop Attribut             */
  630.   {
  631.   return (
  632.              (userpo->sysflg == TRUE)
  633.           && (skipsp(&clicnt, &clipoi) == TRUE) /* kein Sysop ohne Eingabe   */
  634.          );
  635.   }
  636.  
  637. /*---------------------------------------------------------------------------*/
  638. unsigned skipsp(laenge, string)    /* in String auf naechstes Zeichen != ' '    */
  639. unsigned *laenge;        /* Laenge des String, wird korrigiert         */
  640. char     *(*string);        /* die Adresse des Kandidaten             */
  641.   {
  642.   while ((*laenge != 0) && (*(*string) == ' ')) {
  643.     ++*string;
  644.     --*laenge;
  645.     }
  646.   return (*laenge != 0);
  647.   }
  648.  
  649. /*---------------------------------------------------------------------------*/
  650. VOID timer()            /* alle 10ms Uhrzeit erhoehen             */
  651.   {
  652.   ++tic10;
  653.   }
  654.  
  655. /*---------------------------------------------------------------------------*/
  656.