TheNetNode-CB/src/l7host.c

1399 lines
49 KiB
C
Executable File

/************************************************************************/
/* */
/* ***** ***** */
/* ***** ***** */
/* ***** ***** */
/* ***** ***** */
/* *************** *************** */
/* ***************** ***************** */
/* *************** *************** */
/* ***** ***** TheNetNode */
/* ***** ***** Portable */
/* ***** ***** Network */
/* ***** ***** Software */
/* */
/* File src/l7host.c (maintained by: DF6LN) */
/* */
/* This file is part of "TheNetNode" - Software Package */
/* */
/* Copyright (C) 1998 - 2008 NORD><LINK e.V. Braunschweig */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the NORD><LINK ALAS (Allgemeine Lizenz fuer */
/* Amateurfunk Software) as published by Hans Georg Giese (DF2AU) */
/* on 13/Oct/1992; either version 1, or (at your option) any later */
/* version. */
/* */
/* This program is distributed WITHOUT ANY WARRANTY only for further */
/* development and learning purposes. See the ALAS (Allgemeine Lizenz */
/* fuer Amateurfunk Software). */
/* */
/* You should have received a copy of the NORD><LINK ALAS (Allgemeine */
/* Lizenz fuer Amateurfunk Software) along with this program; if not, */
/* write to NORD><LINK e.V., Hinter dem Berge 5, D-38108 Braunschweig */
/* */
/* Dieses Programm ist PUBLIC DOMAIN, mit den Einschraenkungen durch */
/* die ALAS (Allgemeine Lizenz fuer Amateurfunk Software), entweder */
/* Version 1, veroeffentlicht von Hans Georg Giese (DF2AU), */
/* am 13.Oct.1992, oder (wenn gewuenscht) jede spaetere Version. */
/* */
/* Dieses Programm wird unter Haftungsausschluss vertrieben, aus- */
/* schliesslich fuer Weiterentwicklungs- und Lehrzwecke. Naeheres */
/* koennen Sie der ALAS (Allgemeine Lizenz fuer Amateurfunk Software) */
/* entnehmen. */
/* */
/* Sollte dieser Software keine ALAS (Allgemeine Lizenz fuer Amateur- */
/* funk Software) beigelegen haben, wenden Sie sich bitte an */
/* NORD><LINK e.V., Hinter dem Berge 5, D-38108 Braunschweig */
/* */
/************************************************************************/
#include "tnn.h"
WORD startup_running = FALSE; /* laeuft Start-Batch? */
int console_login_status = 0; /* Host-Console eingeloggt */
WORD last_hour; /* letzte Stunde (fuer Batch-Verarbeitung) */
WORD last_min; /* letzte Minute merken */
FILE *tnnb_file; /* aktives Batch-File */
FILE *pro_file = NULL; /* Protokoll_File */
BOOLEAN ishmod = FALSE; /* HOSTMODE aktiv? */
int numhsts = 0; /* Aktive Host-Connects */
int Ypar = 0; /* Maximalzahl der zulaessigen Host-Verb. */
int Ypar2 = MAXHST - 1; /* Max. Zahl verwendbarer Hostkanaele */
LHEAD smonfl; /* Liste der Monitor-Daten (Header,Info) */
LHEAD statml; /* Liste der Statusmeldungen (Monitor) */
int monlin; /* Zahl gespeicherte Monitor-Daten */
int stalin; /* Zahl gespeicherte Meldungen (Monitor) */
MBHEAD *mifmbp = NULL; /* angefangener Monitor-Buffer (Hostmode) */
WORD actch; /* momentan bearbeiteter Host-Channel */
BOOLEAN tnb_ch; /* TRUE = TNB-Kanal, FALSE sonst */
char hinbuf[256]; /* Zeile vom Hostinterface */
BOOLEAN hlixfl; /* X-on / X-off Flag fuer Hostinterface */
int incnt; /* Eingabezaehler */
char *inbufp; /* Pointer fuer die Eingabezeile */
char *blipoi; /* Pointer */
WORD blicnt; /* zaehlt Zeichen */
HOSTUS *hstubl; /* Kontrollblock fuer Host-User */
HOSTUS *hstusr; /* Pointer auf aktuellen Host User */
LHEAD hstatl;
MBHEAD *hstmbp;
/* Zielcall, Digi-Liste und Port fuer UI-Frames Hostmode Kanal 0 (z.B. */
/* fuer MAIL-Beacons einer Mailbox) */
char hmdest[L2IDLEN] = {' ', ' ', ' ', ' ', ' ', ' ', '\140'};
char hmdigil[L2VLEN+1] = "";
WORD hmport = 0;
static const char *tmp_tnb = "TNB.$$$";
extern char *hm_err[];
void cputmb(MBHEAD *);
static void hstol7(WORD, void *);
static void trpmbb(MBHEAD *);
static BOOLEAN termle(unsigned);
static void tohost(void);
static void srvbch(void);
static void srvhch(void);
static void sttoch(unsigned);
/************************************************************************/
/* */
/* TheNetNode Hostinterface */
/* */
/*----------------------------------------------------------------------*/
/* */
/* Die vorliegende Version des Hostinterface beinhaltet grundlegende */
/* Veraenderungen am urspruenglichen Host-Konzept, um eine bessere */
/* Ausnutzung insbesondere fuer die Singelboard-Loesungen (TNC3 und */
/* TNC4) zu ermoeglichen. Dabei wird der Host-Kanal 0 gemeinsam */
/* verwendet fuer den Monitor an der Konsole und fuer die Ausfuehrung */
/* von Batch-Files. Die Konsole kann daher nicht mehr auf dem Kanal 0 */
/* verwendet werden. An sonsten ist das Interface vom Verhalten im */
/* Terminal-Mode kompatibel zu TheFirmware, abgesehen von den verfueg- */
/* baren Befehlen. */
/* */
/* - Meldungen (Status) werden pro Kanal gepuffert */
/* - die wichtigen Konsolen-Befehle werden unterstuetzt: */
/* C, D, I, K, L, M, S, V, Y, @B */
/* - zusaetzliche Befehle an der Konsole: */
/* B = anzeigen Rounds/s */
/* @E = Protokoll_File ein/aus */
/* LOGOUT = Konsole ausloggen */
/* QUIT = Programmende */
/* T = Tokenring-Baudrate */
/* @Y = max. verwendete Konsolenkanaele */
/* @C = Port, Ziel-Call + Digiliste fuer UI-Frames setzen */
/* */
/* Weiterhin wird der Hostmode unterstuetzt. Dafuer wird die Konsole */
/* bei der DOS/GO32-Version auf eine serielle Schnittstelle umgeleitet, */
/* bei Linux wird ueber eine Socket-Schnittstelle gearbeitet. Der Host- */
/* mode unterstuetzt die Befehle C, D, G, I, K, L, M, V, Y, @B, @C, @S, */
/* @Y. Der Befehl E wird ignoriert (fuehrt also nicht zu einer Fehler- */
/* meldung). Der Monitor ist voll funktionsfaehig. */
/* */
/* Alle Konsolenbefehle schreiben die Ausgaben in einen Buffer */
/* (hstmbp). Je nach Aufruf von der Konsole, vom Hostmode oder ueber */
/* einen Batch wird der Buffer-Inhalt weitergeleitet. Damit sind die */
/* Konsole bzw. Hostmode und Batches voneinander unabhaengig. Die */
/* Ausgaben von Batchbefehlen koennen in einem File protokolliert */
/* werden. */
/* */
/************************************************************************/
/************************************************************************/
/* */
/* Initialisieren der Host-Variablen */
/* */
/************************************************************************/
void
init_host(void)
{
char startup[20];
WORD i;
tnb_ch = FALSE;
actch = 1;
init_console();
inithd(&smonfl);
inithd(&statml);
inithd(&hstatl);
for (i = 0, hstusr = hstubl; i < MAXHST; ++i, ++hstusr)
{
#ifdef __WIN32__
hstusr->conflg = 0;
hstusr->disflg = 0;
hstusr->inlin = 0;
hstusr->outlin = 0;
hstusr->outsta = 0;
#else
hstusr->conflg =
hstusr->disflg =
hstusr->inlin =
hstusr->outlin =
hstusr->outsta =
#endif /* WIN32 */
hstusr->direction = 0;
inithd(&hstusr->inbuf);
inithd(&hstusr->outbuf);
cpyid(hstusr->call, hostid);
}
hlixfl = FALSE;
incnt = 0;
monlin = stalin = 0;
tnnb_aktiv = FALSE;
last_hour = 30;
last_min = 70;
xremove(tmp_tnb); /* temporaer-File loeschen */
strcpy(startup, cfgfile);
strcat(startup, ".TNB");
if ((startup_running = runbatch(startup)) == TRUE)
{
#ifndef MC68302
pro_file = xfopen("STARTUP.LOG", "wt+");
#else
pro_file = NULL; /* Platz sparen und Zeit */
#endif
#ifdef ST
setvbuf(pro_file, NULL, _IOFBF, 4096L); /* speedup */
#endif
}
else
xprintf("*** WARNING: %s not found!\r", startup);
}
/************************************************************************/
/* */
/* */
/* */
/************************************************************************/
void
exit_host(void)
{
exit_console();
}
/************************************************************************/
/* */
/* "host to level 7" */
/* */
/* Hier begegnet uns mal wieder das Problem mit dem globalen userpo */
/* usw., wir duerfen hier nicht l2tol7 aufrufen, weil wir selber aus */
/* l7tx() aufgerufen wurden und eventuell die Userliste oder userpo */
/* geaendert werden. Das Prinzip Bottom-Up (Meldungen nur von unten */
/* nach oben) muss gewahrt bleiben, also melden wir spaeter. */
/* */
/************************************************************************/
static void
hstol7(WORD status, void *link)
{
MBHEAD *mbhd;
(mbhd = (MBHEAD *)allocb(ALLOC_MBHEAD))->type = status;
mbhd->l2link = link;
relink((LEHEAD *)mbhd, (LEHEAD *)hstatl.tail);
}
/************************************************************************/
/* */
/* "terminal mode response message buffer bell" */
/* */
/************************************************************************/
static void
trpmbb(MBHEAD *mbp)
{
hputs("\r* ");
rwndmb(mbp);
hputmb(mbp);
if (stamp)
{
hputs(" - ");
hputbt(&mbp->btime);
}
hputs(" *\007\r");
}
/************************************************************************/
/* */
/* "terminal mode line editor" */
/* */
/************************************************************************/
static BOOLEAN
termle(unsigned ch)
{
if (incnt == 0)
inbufp = hinbuf; /* leere Zeile: Pointer = Start */
switch (ch) /* ueber Eingabe verzweigen */
{
case CR:
hputc(CR); /* abspeichern */
if (hinbuf[0] != ESC) /* Textzeilen mit CR */
{
*inbufp++ = CR;
incnt++;
}
*inbufp = NUL; /* Ende markieren */
blipoi = hinbuf; /* blipoi auf Eingabezeile */
blicnt = incnt; /* Laenge merken */
inbufp = hinbuf; /* wieder auf Start */
incnt = 0; /* neue Zeile beginnt */
if (console_login_status) /* ist Console eingeloggt ? */
return (TRUE); /* eine Zeile ist fertig */
else
{
if (strnicmp((char *)blipoi, "\x1BJHOST", 6) == 0)
{
blipoi += 2; /* ESC uebergehen */
blicnt -= 2;
Jcmd(); /* Umschaltung ermoeglichen */
break;
}
if (strstr((char *)blipoi, pass) == (char *)blipoi)
{
console_login_status = 1; /* die Console einloggen */
#ifdef SPEECH
hprintf(speech_message(242), signon);
#else
hprintf("Welcome to %s", signon);
#endif
hputid(myid);
hputs(")\r");
}
else
hputs("password: ");
}
break;
case BS: /* BS und DEL werden gleich */
case DEL: /* behandelt und loeschen */
if (incnt) /* destruktiv. Sie werden aber */
bliloe(); /* ignoriert. */
break;
case 0x15: /* ctl-U und */
case 0x18: /* ctl-X loeschen Eingabezeile */
while (incnt)
bliloe();
break;
case XON: /* XON loescht Flag */
hlixfl = FALSE;
break;
case XOFF: /* XOFF setzt Flag */
hlixfl = TRUE;
break;
default:
if ((incnt < 255)
&& ((ch >= ' ') || (ch == ESC) || (ch == 26)))
{
blieco(ch);
*inbufp++ = ch;
++incnt;
}
else
hputc(BELL); /* Zeile voll: meckern */
}
return (FALSE);
}
/************************************************************************/
/* */
/* "to host" */
/* */
/************************************************************************/
static void
tohost(void)
{
MBHEAD *mbp;
if (nmbfre < 14) /* kein Speicher */
{
if (!ishmod)
hprintf("* %s *\007\n", hm_err[HMELIG]);
else
{
#ifdef __WIN32__
hputc((char)actch);
#else
hputc(actch);
#endif /* WIN32 */
hputs(hm_err[HMELIG]);
}
return;
}
if (!hstusr->conflg) /* nicht connected? */
{
if (!ishmod)
{
#ifdef SPEECH
hprintf(speech_message(243));
#else
hprintf("* CHANNEL NOT CONNECTED *\007\n");
#endif
return;
}
}
else
{
if (!(hstusr->disflg & 0x80)) /* schon DISCed */
{
mbp = (MBHEAD *)allocb(ALLOC_MBHEAD);
while (blicnt--)
putchr(*blipoi++, mbp);
rwndmb(mbp);
relink((LEHEAD *)mbp, (LEHEAD *)hstusr->inbuf.tail);
++hstusr->inlin;
hstsen(FALSE); /* Info an Rest des Programms */
}
}
if (ishmod && !tnb_ch)
{
#ifdef __WIN32__
hputc((char)actch);
#else
hputc(actch);
#endif /* WIN32 */
hputc(0);
}
}
/************************************************************************/
/* */
/* "service batch channel" */
/* */
/************************************************************************/
static void
srvbch(void)
{
MBHEAD *mbp;
char bline[256]; /* nicht die Host-Buffer! */
USRBLK *user;
hstusr = hstubl; /* auf den System-Kanal */
/* eingelaufene Infos ausgeben, Statusmeldungen ignorieren */
while ((LHEAD *)hstusr->outbuf.head != &hstusr->outbuf)
{
mbp = (MBHEAD *)ulink((LEHEAD *)hstusr->outbuf.head);
if (mbp->type == L2MNIX) /* Info-Frame */
{
--hstusr->outlin; /* ein Frame weniger */
cputmb(mbp); /* Frame ausgeben */
}
else /* Meldung */
--hstusr->outsta; /* eine Meldung weniger */
dealmb(mbp); /* Buffer dann auf den Muell */
}
/* abarbeiten von Batch-Files */
if (tnnb_aktiv)
{
/* ggf. erstmal zum Knoten connecten */
if (!hstusr->conflg)
{
hstcon(1);
return;
}
/* der Befehl muss erst komplett ausgefuehrt sein, bevor der naechste */
/* gestartet wird, d.h. saemtliche Ausgaben muessen beendet sein. */
user = (ptctab + g_uid(hstusr, HOST_USER))->ublk;
if (hstusr->outlin
|| hstusr->outsta
|| (user->status > US_CCP)
|| (user->fp != NULL))
return;
/* Naechsten Befehl holen und in Protokollfile schreiben (wenn */
/* verwendet). Befehle werden mit CR terminiert. */
if (fgets(bline, 255, tnnb_file))
{
bline[255] = NUL; /* auf jeden Fall terminieren */
if ((blipoi = strchr(bline, '\n')) != NULL)
{
if (pro_file != NULL) /* ggf. Befehl in ein Protokollfile */
fputs(bline, pro_file);
*blipoi = CR; /* '\n' durch CR ersetzen */
}
blipoi = bline;
blicnt = strlen((char *)blipoi); /* Laenge ermitteln */
tohost(); /* Info an den L7 */
}
else
{
if (hstusr->inlin || hstusr->outlin)/* noch Reste zu verarbeiten? */
return;
fclose(tnnb_file); /* File wieder schliessen */
xremove(tmp_tnb); /* temporaer-File loeschen */
tnnb_aktiv = FALSE;
if ((hstusr->conflg)
&& (user->auditlevel == 0)
&& (user->monitor == NULL))
hstdis(); /* Kanal rauswerfen */
}
}
else
{
if (startup_running)
{
if (pro_file != NULL)
{
fclose(pro_file);
pro_file = NULL;
}
startup_running = FALSE;
}
}
}
/************************************************************************/
/* */
/* "service host channel" */
/* */
/************************************************************************/
static void
srvhch(void)
{
MBHEAD *mbp;
unsigned ch;
static int hmstat = 0; /* Hostmode Status */
static int hmch; /* Hostmode Kanal */
static int hmcmd; /* Hostmode Befehl */
static int hmlen; /* Hostmode Datenbytes */
/* Kanaele disconnecten, wenn disco gefordert und alle Info abgeholt */
for (hstusr = &hstubl[1]; hstusr < &hstubl[MAXHST]; hstusr++)
if (((hstusr->disflg & 0x80) != 0)
&& (hstusr->outlin == 0)
&& (hstusr->outsta == 0))
hstdis();
hstusr = &hstubl[actch]; /* auf aktuellen Kanal */
if (!ishmod) /* kein Hostmode? */
{
if (!ishput()) /* keine Reste auszugeben */
if (!incnt && !hlixfl) /* wenn am Zeilenanfang und */
{ /* kein XOFF Status */
while (stalin) /* solange noch Meldungen */
{
mbp = (MBHEAD *)ulink((LEHEAD *)statml.head);
trpmbb(mbp);
dealmb(mbp);
stalin--;
}
while (monlin) /* solange Frames fuer Monitor */
{
mbp = (MBHEAD *)ulink((LEHEAD *)smonfl.head);
rwndmb(mbp);
hputmb(mbp);
hputc('\r');
dealmb(mbp);
monlin--;
}
/* eingelaufene Infos ausgeben */
while ((LHEAD *)hstusr->outbuf.head != &hstusr->outbuf)
{
mbp = (MBHEAD *)ulink((LEHEAD *)hstusr->outbuf.head);
if (mbp->type == L2MNIX) /* Info-Frame */
{
--hstusr->outlin; /* ein Frame weniger */
hputmb(mbp); /* Frame ausgeben */
if (mbp->l4type != HMRINFO)
hputs(" *\r");
}
else /* Meldung */
{
--hstusr->outsta; /* eine Meldung weniger */
trpmbb(mbp); /* Meldung ausgeben */
}
dealmb(mbp); /* Buffer dann auf den Muell */
}
}
if (monlin > 50) /* damit der Knoten nicht voll- */
{ /* laeuft */
dealml((LEHEAD *)&smonfl);
monlin = 0; /* Monitor leeren */
}
if (ishget()) /* nun Eingaben bearbeiten: */
{
ch = hgetc(); /* Zeichen holen, wenn vorhanden */
if (termle(ch)) /* Zeile fertig? */
{
if (*blipoi == ESC) /* Befehl eingegeben? */
{
*blipoi++ = 0x00;
--blicnt;
skipsp(&blicnt, &blipoi);
hstcmd((MBHEAD *)NULL); /* Befehl ausfuehren */
}
else /* Info fuer Kanal */
tohost();
}
}
}
else /* Hostmode */
{
while (ishget())
{
ch = hgetc(); /* ein Zeichen lesen */
switch (hmstat)
{
case 0: /* CHANNEL */
hmch = ch;
++hmstat;
break;
case 1: /* COMMAND */
hmcmd = ch;
++hmstat;
break;
case 2: /* LENGTH */
hmlen = ch;
++hmstat;
inbufp = hinbuf;
incnt = 0;
break;
case 3:
*inbufp++ = ch;
++incnt;
if (hmlen != 0)
--hmlen;
else /* Hostmode-Packet komplett da */
{
hmstat = 0;
actch = hmch;
if ((actch < MAXHST)
|| ((actch == 0xFF)
&& (hmcmd == TRUE)
&& (toupper(*hinbuf) == 'G')))
{
if ((actch != 0)
&& (actch != 0xFF))
hstusr = &hstubl[actch];
blipoi = hinbuf;
blicnt = incnt;
if (hmcmd) /* Befehl? */
{
skipsp(&blicnt, &blipoi);
hstcmd((MBHEAD *)NULL); /* Konsolen-Befehl ausfuehren */
}
else /* Info */
if (actch)
tohost(); /* an den L7 senden */
else
{
if (hmdest[0] != ' ')
{
(mbp = (MBHEAD *)allocb(ALLOC_MBHEAD))->l2fflg = L2CPID;
inbufp = hinbuf;
while (incnt--)
putchr(*inbufp++, mbp);
rwndmb(mbp);
#ifdef __WIN32__
sdui(hmdigil, hmdest, hostid, (char)hmport, mbp);
#else
sdui(hmdigil, hmdest, hostid, hmport, mbp);
#endif /* WIN32 */
dealmb(mbp);
}
#ifdef __WIN32__
hputc((char)actch); /* Info an Monitor-Kanal */
#else
hputc(actch); /* Info an Monitor-Kanal */
#endif /* WIN32 */
hputc(0); /* ignorieren */
}
}
else /* Fehler */
{
hmputr(HMRFMSG);
hputs("INVALID CHANNEL NUMBER");
hputc(0);
}
actch = 1; /* Schutzmassnahme XAO 050100 */
}
break;
}
}
}
hstsen(FALSE); /* Info an Rest des Programms */
}
/************************************************************************/
/* */
/* Host_Service */
/* */
/* Statusmeldungen an L7 weiterleiten, Batches ausfuehren, Konsole */
/* bedienen. */
/* */
/************************************************************************/
void
hostsv(void)
{
MBHEAD *mbhd;
while ((LHEAD *)hstatl.head != &hstatl)
{
mbhd = (MBHEAD *)ulink((LEHEAD *)hstatl.head);
l2tol7(mbhd->type, mbhd->l2link, HOST_USER);
dealoc(mbhd);
}
tnb_ch = TRUE;
srvbch(); /* Batch-Kanal behandeln */
tnb_ch = FALSE;
srvhch(); /* Host-Kanaele auch */
}
/************************************************************************/
/* */
/* Batches ausfuehren. */
/* */
/************************************************************************/
BOOLEAN
runbatch(char *batchname)
{
FILE *batch_file;
char line[256];
char *lp;
LONG oldpos = 0L;
strcpy(line, batchname);
if (strchr(line, '.') == NULL)
strcat(line, ".TNB");
batch_file = xfopen(line, "rt");
if (!batch_file)
return (FALSE); /* nicht gefunden! */
if (tnnb_aktiv) /* laeuft schon ein Batch? */
{
oldpos = ftell(tnnb_file); /* Position merken */
fclose(tnnb_file); /* ... das ist zum lesen! */
}
tnnb_file = xfopen(tmp_tnb, "at");
if (!tnnb_file) /* Temp-File geht nicht auf? */
{
fclose(batch_file);
tnnb_aktiv = FALSE;
return (FALSE); /* Fehler! */
}
#ifdef ST
setvbuf(tnnb_file, NULL, _IOFBF, 4096L); /* speedup */
#endif
/* Eine Zeile aus Batchfile einlesen, Zeile beim ersten ";" oder "\n" */
/* beenden. Tabs entfernen, sonst kommt der CPP durcheinander. Leer- */
/* zeichen am Zeilenende werden ebenfalls entfernt. */
while (fgets(line, 255, batch_file) != NULL)
{
line[strcspn(line, ";\n\r")] = NUL;
while ((lp = strchr(line, 9)) != NULL)
*lp = 32;
lp = strchr(line, 0) - 1; /* Zeilenende */
while ((lp > line) && (*lp == 32))
*lp-- = NUL;
/* Zeilen mit "#" am Zeilenanfang als ESC-Befehl in Temporaer-File, */
/* andere Zeilen unveraendert ins Temporaer-File. Leerzeilen ignorieren */
if (line[0])
{
if (line[0] == '#')
fprintf(tnnb_file, "ESC %s\n", &line[1]);
else
fprintf(tnnb_file, "%s\n", line);
}
}
fclose(tnnb_file); /* File wieder schliessen */
fclose(batch_file); /* auch Batch File */
tnnb_file = xfopen(tmp_tnb, "rt"); /* ... und zum Lesen oeffnen */
if (tnnb_file)
{
fseek(tnnb_file, oldpos, SEEK_SET);
tnnb_aktiv = TRUE; /* Markieren -> Batch laeuft */
}
return (tnnb_aktiv);
}
/************************************************************************/
/* */
/* Host-Timer */
/* */
/* Noactivity-Timer fuer Konsolen-Kanaele reduzieren und ggf. Kanal */
/* disconnecten. Zur vollen Stunde Batches starten. */
/* */
/************************************************************************/
void
hostim(void)
{
WORD i;
char tnnb_d_name[15];
char tnnb_w_name[15];
WORD fertig;
struct ffblk tnnb_f;
if (!tnnb_aktiv)
for (i = 1, hstusr = hstubl + 1; i < MAXHST; i++, hstusr++)
{
if (hstusr->conflg)
{
if ((hstusr->noacti != 0) && (--hstusr->noacti == 0))
hstdis();
}
}
hstusr = &hstubl[actch]; /* auf aktuellen Kanal */
if (sys_localtime->tm_min != last_min)
{
last_min = sys_localtime->tm_min; /* aktuelle Minute merken */
if (xaccess("NOW.TNB", 0) == 0)
{
runbatch("NOW.TNB");
xremove("NOW.TNB");
}
}
if (sys_localtime->tm_hour != last_hour)
{
/* Stuendlich kontrollieren, ob ein passendes TNB-File existiert. Dazu */
/* die gesuchten Filenamen fuer taeglichen und woechentlichen Job */
/* aus aktuellem Datum und aktueller Zeit generieren. */
last_hour = sys_localtime->tm_hour; /* aktuelle Stunde merken */
sprintf(tnnb_d_name, "%02d%02d%02d%02d.TNB",
sys_localtime->tm_year % 100, sys_localtime->tm_mon + 1,
sys_localtime->tm_mday, sys_localtime->tm_hour);
sprintf(tnnb_w_name, "%02d%02dW%1.1d%02d.TNB",
sys_localtime->tm_year % 100, sys_localtime->tm_mon + 1,
sys_localtime->tm_wday, sys_localtime->tm_hour);
/* Nun nach allen passenden Files suchen, Wildcards beachten. */
fertig = xfindfirst("*.TNB", &tnnb_f, 0);
while (!fertig)
{
for (i = 0; i < 8; i += 2) /* Beide Buffer testen */
{
if (tnnb_f.ff_name[i] == '#')
continue;
if (strnicmp(&tnnb_f.ff_name[i], &tnnb_d_name[i], 2)
&& strnicmp(&tnnb_f.ff_name[i], &tnnb_w_name[i], 2))
break; /* Abbruch beim ersten nicht passenden Zeichen */
}
if (i == 8) /* Name stimmt? */
runbatch(tnnb_f.ff_name); /* Batch ausfuehren */
fertig = xfindnext(&tnnb_f); /* nichts gefunden, weitersuchen */
}
}
}
/************************************************************************/
/* */
/* Connect-Wunsch zum Host bearbeiten */
/* */
/************************************************************************/
BOOLEAN
hstreq(void)
{
MBHEAD *mbp;
if (numhsts < Ypar)
{
hstcon(0);
}
else
{
#ifdef SPEECH
putstr(speech_message(246), mbp = (MBHEAD *)allocb(ALLOC_MBHEAD));
#else
putstr("CONNECT REQUEST fm ", mbp = (MBHEAD *)allocb(ALLOC_MBHEAD));
#endif
putid(hstusr->call, mbp);
mbp->btime = sys_time;
mbp->type = L2MBUSYT;
relink((LEHEAD *)mbp, (LEHEAD *)statml.tail);
stalin++;
hstol7(L2MBUSYF, hstusr);
cpyid(hstusr->call, hostid);
return (FALSE);
}
return (TRUE);
}
/************************************************************************/
/* */
/* Host-User wurde vom CCP disconnected. */
/* */
/************************************************************************/
void
hstout(void)
{
dealml((LEHEAD *)&hstusr->inbuf);
hstusr->inlin = 0;
hstusr->disflg |= 0x80;
}
/************************************************************************/
/* */
/* Info vom L7 an Host */
/* */
/************************************************************************/
BOOLEAN
itohst(BOOLEAN conflg, MBHEAD *ublk)
{
HOSTUS *hostp;
hostp = (HOSTUS *)ublk->l2link;
if (hostp == hstubl) /* im Batch-Modus keine */
conflg = TRUE; /* Erstickungskontrolle. */
if ((conflg == TRUE)
|| (hostp->outlin < conctl))
{
if ((ublk->mbpc - ublk->mbgc) == 0) /* Frames ohne Info ignorieren */
{
dealmb((MBHEAD *)ulink((LEHEAD *)ublk));
return (TRUE);
}
relink(ulink((LEHEAD *)ublk), (LEHEAD *)hostp->outbuf.tail);
ublk->type = L2MNIX; /* Info-Frame (keine Meldung) */
ublk->l4type = HMRINFO;
++hostp->outlin;
hostp->noacti = ininat;
return (TRUE);
}
return (FALSE);
}
/************************************************************************/
/* */
/* Echo fuer Konsole */
/* */
/************************************************************************/
void
blieco(int zeichen)
{
if (console_login_status)
{
if (incnt == 0 && zeichen == ESC)
hputs("* ");
else
#ifdef __WIN32__
hputcc((char)zeichen);
#else
hputcc(zeichen);
#endif /* WIN32 */
}
else /* Password als ***** anzeigen */
hputc('*');
}
/************************************************************************/
/* */
/* 1 eingegebenes Zeichen im Buffer und in der Anzeige loeschen */
/* */
/************************************************************************/
void
bliloe(void)
{
char ch;
if ((ch = *(--inbufp)) != BELL)
{
bputbs();
if (ch < ' ')
bputbs();
}
else
hputc(ch);
--incnt;
}
/************************************************************************/
/* */
/* 1 Zeichen in der Anzeige loeschen */
/* */
/************************************************************************/
void
bputbs(void)
{
hputs("\010 \010");
}
/************************************************************************/
/* */
/* Konsolenbefehle bearbeiten, auch ESC-Befehl im CCP */
/* */
/************************************************************************/
void
hstcmd(MBHEAD *mbpoi)
{
HOSTCMD *cmdpoi;
if (skipsp(&blicnt, &blipoi))
{
/* Befehl in Befehlsliste suchen */
for (cmdpoi = hostcmdtab; cmdpoi->cmdfun != NULL; ++cmdpoi)
{
if (toupper(*blipoi) == *cmdpoi->cmdstr)
{
++blipoi;
--blicnt;
break;
}
}
if (cmdpoi->cmdfun != NULL) /* Befehl gefunden */
{
hstmbp = mbpoi;
if (hstmbp == NULL) /* Aufruf von Terminal / Hostmode */
hstmbp = (MBHEAD *)allocb(ALLOC_MBHEAD);
else
tnb_ch = TRUE; /* Aufruf vom CCP */
hstmbp->type = L2MNIX;
hstmbp->l4type = HMRINFO;
(*cmdpoi->cmdfun) (); /* Befehl ausfuehren */
if (mbpoi == NULL) /* Aufruf von Terminal / Hostmode */
{
hstusr->noacti = ininat; /* Timeout zuruecksetzen */
rwndmb(hstmbp);
if (!ishmod) /* Terminalmode */
{
if (hstmbp->mbpc != 0) /* Antwort vorhanden */
{
hputmb(hstmbp);
if (hstmbp->l4type != HMRINFO)
hputs(" *\n");
if (hstmbp->l4type == HMRFMSG)
hputc('\007');
}
}
else /* Hostmode */
{
while (hstmbp->mbpc > hstmbp->mbgc)
hputc(getchr(hstmbp));
if (hstmbp->l4type < HMRMONI) /* Meldung mit '\0' beenden */
hputc(0);
}
dealmb(hstmbp);
}
else /* Aufruf vom CCP */
if (hstmbp->mbpc > hstmbp->mbgc) /* wenn Antwort im Buffer */
putchr('\r', hstmbp); /* <CR> hinterher */
return;
}
if (mbpoi != NULL)
#ifdef SPEECH
putstr(speech_message(247), hstmbp);
#else
putstr("INVALID COMMAND\r", hstmbp);
#endif
else
{
hmputr(HMRFMSG);
if (!ishmod)
hputs("* ");
hputs("INVALID COMMAND: ");
hputcc(*blipoi);
if (!ishmod)
hputs(" *\007\r");
else
hputc(0);
}
return;
}
if (ishmod)
hmputr(0);
}
/************************************************************************/
/* */
/* "status to channel" */
/* */
/************************************************************************/
static void
sttoch(unsigned msg)
{
MBHEAD *mbp;
CIRBLK *cp;
UID uid;
const char *vp;
if (tnb_ch) /* keine Meldung fuer TNBs */
return;
putprintf(mbp = (MBHEAD *)allocb(ALLOC_MBHEAD),
"(%u) ", (unsigned)(hstusr - hstubl));
#ifdef SPEECH
putstr(msg == L2MCONNT ? speech_message(244) : speech_message(245), mbp);
#else
putstr(msg == L2MCONNT ? "CONNECTED to " : "DISCONNECTED fm ", mbp);
#endif
if (hstusr->direction)
putid(myid, mbp);
else
{
putid(hstusr->call, mbp);
if (msg == L2MCONNT)
{
uid = userpo->uid;
switch (g_utyp(uid))
{
case L2_USER:
putdil(((LNKBLK *)g_ulink(uid))->viaidl, mbp);
break;
case L4_USER:
cp = g_ulink(uid);
if ((!cmpid(cp->upnod, cp->downca))
|| (*(cp->upnodv) != NUL))
{
putstr(" via ", mbp);
putid(cp->upnod, mbp);
vp = cp->upnodv;
while (*vp != NUL)
{
putchr(' ', mbp);
putid(vp, mbp);
vp += L2IDLEN;
}
}
break;
}
}
}
mbp->btime = sys_time;
mbp->type = msg;
if (!ishmod)
{
relink((LEHEAD *)mbp, (LEHEAD *)statml.tail);
stalin++;
}
else
{
relink((LEHEAD *)mbp, (LEHEAD *)hstusr->outbuf.tail);
hstusr->outsta++;
}
}
/************************************************************************/
/* */
/* Hostmode-Kanal Connecten */
/* */
/************************************************************************/
void
hstcon(char direction)
{
hstusr->direction = direction;
sttoch(L2MCONNT);
hstol7(L2MCONNT, hstusr);
hstusr->conflg = 1;
hstusr->noacti = ininat;
#ifdef HOSTMYCALL
cpyid(hstusr->call, hostuserid);
#endif /* HOSTMYCAL */
resptc(g_uid(hstusr, HOST_USER));
numhsts++;
}
/************************************************************************/
/* */
/* Host-Kanal disconnecten */
/* */
/************************************************************************/
void
hstdis(void)
{
dealml((LEHEAD *)&hstusr->inbuf);
dealml((LEHEAD *)&hstusr->outbuf);
hstusr->inlin =
hstusr->outlin =
hstusr->outsta = 0;
sttoch(L2MDISCF);
hstol7(L2MDISCF, hstusr);
resptc(g_uid(hstusr, HOST_USER));
hstusr->conflg =
hstusr->disflg = 0;
cpyid(hstusr->call, hostid);
numhsts--;
}
/************************************************************************/
/* */
/* Informationstransfer von Host nach Layer X */
/* ------------------------------------------ */
/* */
/* Solange noch empfangene Pakete vorhanden sind, werden diese */
/* an andere Layer durch Aufruf von fmlink() uebertragen. Bei ge- */
/* setztem Ueberfuellungskontroll-Flag (conctl == TRUE) wird die */
/* Uebertragung abgebrochen, wenn der andere Layer keine weiteren */
/* Daten mehr aufnehmen kann. */
/* */
/* Nach erfolgter Uebertragung wird der No-Activity-Timer neu */
/* gesetzt. */
/* */
/************************************************************************/
void
hstsen(BOOLEAN conctl)
{
MBHEAD *mbp;
if ((hstusr - hstubl) >= MAXHST)
return;
while (hstusr->inlin != 0)
{
mbp = (MBHEAD *)hstusr->inbuf.head;
mbp->l2link = (LNKBLK *)hstusr;
mbp->type = HOST_USER;
mbp->l2fflg = L2CPID;
if (!fmlink(conctl, mbp))
break;
hstusr->noacti = ininat;
--hstusr->inlin;
}
}
/************************************************************************/
/* */
/* Rufzeichen mit SSID an der Konsole anzeigen. */
/* */
/************************************************************************/
void
hputid(char *id)
{
WORD ssid;
WORD i;
char ch;
for (i = 0; i < L2CALEN; ++i)
if ((ch = *id++ & 0xFF) != ' ')
hputcc(ch);
if ((ssid = (*id >> 1) & 0x0F) != 0)
hprintf("-%d", ssid);
}
/************************************************************************/
/* */
/* Zeichen an der Konsole anzeigen, Steuerzeichen mit "^" vorweg. */
/* */
/************************************************************************/
void
hputcc(char c)
{
if (c >= ' ')
hputc(c);
else
{
hputc('^');
#ifdef __WIN32__
hputc((char)(c + '@'));
#else
hputc(c + '@');
#endif /* WIN32 */
}
}
/************************************************************************/
/* */
/* Uhrzeit aus Buffer an der Konsole anzeigen. */
/* */
/************************************************************************/
void
hputbt(time_t * t)
{
struct tm *p;
p = localtime(t);
hprintf("%02u.%02u.%02u %02u:%02u:%02u",
p->tm_mday, p->tm_mon + 1, p->tm_year % 100,
p->tm_hour, p->tm_min, p->tm_sec);
}
/************************************************************************/
/* */
/* String an der Konsole formatiert anzeigen. */
/* */
/************************************************************************/
void
hprintf(const char *format,...)
{
va_list arg_ptr;
char str[256];
va_start(arg_ptr, format);
vsprintf(str, format, arg_ptr);
va_end(arg_ptr);
hputs(str);
}
/************************************************************************/
/* */
/* Text auf die Console ausgeben, nicht unbedingt an das Host-Interface.*/
/* xprintf() wird fuer Status-Ausgaben genutzt, die den Hostmode durch- */
/* einander bringen koennten. */
/* Der TNC3 muss xprintf() im Hostmode unterdruecken! */
/* */
/************************************************************************/
void
xprintf(const char *format,...)
{
va_list arg_ptr;
if (consfile == NULL)
return;
va_start(arg_ptr, format);
vfprintf(consfile, format, arg_ptr);
va_end(arg_ptr);
}
/************************************************************************/
/* */
/* String an der Konsole anzeigen. */
/* */
/************************************************************************/
void
hputs(const char *str)
{
while (*str)
hputc(*str++);
}
/************************************************************************/
/* */
/* Inhalt eines Buffers an der Konsole anzeigen, Steuerzeichen mit "^" */
/* vorweg. */
/* */
/************************************************************************/
void
hputmb(MBHEAD *mbp)
{
UBYTE c;
if (tnb_ch)
{
cputmb(mbp);
return;
}
while (mbp->mbgc < mbp->mbpc)
{
c = getchr(mbp);
if (c >= ' ' || c == BELL || c == TAB || c == LF || c == CR)
hputc(c);
else
hputcc(c);
}
}
/************************************************************************/
/* */
/* Inhalt eines Buffers in das Protokollfile fuer Batches schreiben, */
/* Steuerzeichen mit "^" vorweg. */
/* */
/************************************************************************/
void
cputmb(MBHEAD *mbp)
{
UBYTE c;
if (pro_file == NULL)
return;
while (mbp->mbgc < mbp->mbpc)
{
c = getchr(mbp);
if (c >= ' ')
fputc(c, pro_file);
else
{
if (c == CR)
fputs("\n", pro_file);
else if (c != LF)
{
fputc('^', pro_file);
fputc(c + '@', pro_file);
}
}
}
}
/* End of src/l7host.c */