home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
kermit.columbia.edu
/
kermit.columbia.edu.tar
/
kermit.columbia.edu
/
archives
/
ckc190.zip
/
ckonet.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-09
|
41KB
|
1,501 lines
char *ckonetv = "OS/2 Network support, 5A(040) 4 Oct 94";
/* C K O N E T -- OS/2-specific network support */
/*
COPYRIGHT NOTICE:
Copyright (C) 1985, 1994, Trustees of Columbia University in the City of New
York. The C-Kermit software may not be, in whole or in part, licensed or
sold for profit as a software product itself, nor may it be included in or
distributed with commercial products or otherwise distributed by commercial
concerns to their clients or customers without written permission of the
Office of Kermit Development and Distribution, Columbia University. This
copyright notice must not be removed, altered, or obscured.
*/
/*
Currently supported network services:
- DECnet (PATHWORKS) LAT (support resides in this module)
- TCP/IP Telnet (for which this module acts as a front end to ckcnet.c)
- Named pipes [Jeffrey Altman <p00118@psilink.com>]
- NETBIOS [Jeffrey Altman <p00118@psilink.com>]
*/
#include "ckcdeb.h"
#include "ckcker.h"
#include "ckuusr.h"
#include "ckcasc.h"
#define EXTERN
#include "ckcnet.h" /* include ckonet.h and this includes ckotcp.h */
#include <io.h>
#include <fcntl.h>
#include <string.h>
extern int ttnproto, tt_type;
extern char *tn_term;
char tcpname[512]; /* For SHOW NET */
#ifndef NETCONN
/*
Network support not defined.
Dummy functions here in case #ifdef's forgotten elsewhere.
*/
int /* Open network connection */
os2_netopen(name, lcl, nett) char *name; int *lcl, nett; {
return(-1);
}
int /* Close network connection */
os2_netclos() {
return(-1);
}
int /* Check network input buffer */
os2_nettchk() {
return(-1);
}
int /* Flush network input buffer */
os2_netflui() {
return(-1);
}
int /* Send network BREAK */
os2_netbreak() {
return(-1);
}
int /* Input character from network */
os2_netinc(timo) int timo; {
}
int /* Output character to network */
os2_nettoc(c) int c; {
return(-1);
}
int
os2_nettol(s,n) char *s; int n; {
return(-1);
}
#else /* NETCONN is defined (rest of this module...) */
#ifndef __32BIT__
#define far _far
#define near _near
#define pascal _pascal
#endif
#ifdef NPIPE
#include <time.h>
#define INCL_DOSNMPIPES
extern char pipename[PIPENAML+1];
#endif /* NPIPE */
#define INCL_NOPM
#define INCL_DOSPROCESS
#define INCL_DOSMODULEMGR
#define INCL_DOSSEMAPHORES
#define INCL_ERRORS
#include <os2.h>
#undef COMMENT
int tcp_avail = 0;
int dnet_avail = 0;
USHORT netbiosAvail = 0;
#ifdef DECNET
#ifdef __32BIT__
#pragma seg16(lcb)
#pragma seg16(latinfo)
#pragma seg16(inbuf)
#else /* __32BIT__ */
#define _Seg16
#define APIENTRY16 APIENTRY
#define APIRET16 USHORT
#endif /* __32BIT__ */
#include "ckolat.h"
static APIRET16 (* APIENTRY16 LATENTRY)(struct lat_cb * _Seg16) = NULL;
static struct lat_cb lcb;
static struct lat_info latinfo;
#endif /* DECNET */
/* N E T I N C - Input Buffer */
static unsigned long size = 0, pos = 0;
static unsigned char inbuf[MAXRP+1] ;
extern int duplex, debses, seslog, ttyfd, quiet; /* External variables */
extern int nettype;
extern char ttname[] ;
extern char myhost[] ;
#ifdef NPIPE
HPIPE hPipe = 0 ;
UCHAR PipeName[PIPENAML+1]; /* Pipe name */
#endif /* NPIPE */
#ifdef CK_NETBIOS
#include "ckonbi.h"
extern PNCB pWorkNCB ;
extern PNCB pListenNCB ;
extern PNCB pRecvNCB ;
extern PNCB pSendNCB[MAXWS] ;
extern BYTE NetBiosLSN ;
extern HEV hevNetBiosLSN ;
extern UCHAR NetBiosRemote[NETBIOS_NAME_LEN+1] ;
extern UCHAR NetBiosName[NETBIOS_NAME_LEN+1] ;
extern UCHAR NetBiosAdapter ;
extern TID ListenThreadID ;
extern BYTE NetBiosRecvBuf[MAXRP] ;
extern BYTE * NetBiosSendBuf[MAXWS] ;
extern USHORT MaxCmds,MaxSess,MaxNames ;
void NetbiosListenThread(void * pArgList);
#endif /* CK_NETBIOS */
/* N E T O P E N -- Open a network connection. */
/* Returns 0 on success, -1 on failure. */
/*
Calling conventions same as ttopen(), except third argument is network
type rather than modem type. Designed to be called from within ttopen.
*/
int
os2_netopen(name, lcl, nett) char *name; int *lcl, nett; {
#ifdef NPIPE
ULONG OpenMode;
ULONG PipeMode;
ULONG OutBufSize;
ULONG InBufSize;
ULONG TimeOut;
ULONG ActionTaken ;
ULONG OpenFlag ;
ULONG BytesRead ;
AVAILDATA AvailData ;
ULONG PipeState ;
#endif /* NPIPE */
int rc = -1;
#ifdef CK_NETBIOS
if ( nettype == NET_BIOS ) {
ULONG PostCount ;
UCHAR RemoteName[NETBIOS_NAME_LEN+1] = " \0" ;
if ( !netbiosAvail )
return -1 ;
strncpy( RemoteName, name, strlen(name) ) ;
/* strcpy( name, RemoteName ) ; */ /* name will now be 16 characters */
if ( NetBiosLSN > 0 /* Make sure a handle doesn't exist */
|| ttyfd > -1 )
return 0 ;
DosResetEventSem( hevNetBiosLSN, &PostCount ) ;
if ( !strcmp( "* ", RemoteName ) ) { /* Server Mode */
if ( pListenNCB->basic_ncb.bncb.ncb_retcode == NB_COMMAND_IN_PROCESS)
return 0 ;
printf("Listening for a NetBios connection\n") ;
rc = NCBListen( NetbeuiAPI,
pListenNCB, NetBiosAdapter, NetBiosName, RemoteName,
NB_RECV_TIMEOUT, NB_SEND_TIMEOUT, FALSE ) ;
if ( rc )
return -1 ;
ttyfd = NetBiosLSN = 0 ;
ListenThreadID = _beginthread( &NetbiosListenThread, 0, 16384, 0 );
if ( ListenThreadID == -1 ) {
Dos16SemWait( pListenNCB->basic_ncb.ncb_semaphore,
SEM_INDEFINITE_WAIT ) ;
switch (pListenNCB->basic_ncb.bncb.ncb_retcode) {
case NB_COMMAND_SUCCESSFUL:
ttyfd = NetBiosLSN = pListenNCB->basic_ncb.bncb.ncb_lsn ;
return 0 ;
break;
default:
return -1 ;
}
}
return 0 ;
} else { /* Remote Mode */
int oldalarm = alarm(0) ;
printf("Calling \"%s\" via NetBios\n", RemoteName ) ;
rc = NCBCall( NetbeuiAPI, pWorkNCB, NetBiosAdapter, NetBiosName,
RemoteName, NB_RECV_TIMEOUT, NB_SEND_TIMEOUT, FALSE ) ;
rc = Dos16SemWait( pWorkNCB->basic_ncb.ncb_semaphore,
SEM_INDEFINITE_WAIT ) ;
if (rc)
return -1 ;
switch ( pWorkNCB->basic_ncb.bncb.ncb_retcode ) {
case NB_COMMAND_SUCCESSFUL:
strncpy( NetBiosRemote, pWorkNCB->basic_ncb.bncb.ncb_callname,
NETBIOS_NAME_LEN ) ;
ttyfd = NetBiosLSN = pWorkNCB->basic_ncb.bncb.ncb_lsn ;
NCBReceive( NetbeuiAPI, pRecvNCB, NetBiosAdapter, NetBiosLSN,
NetBiosRecvBuf, sizeof(NetBiosRecvBuf), FALSE ) ;
Dos16SemClear(pListenNCB->basic_ncb.ncb_semaphore ) ;
DosPostEventSem( hevNetBiosLSN ) ;
rc = 0 ;
break;
case ERROR_FILE_NOT_FOUND:
case ERROR_ACCESS_DENIED:
case ERROR_INVALID_PARAMETER:
default:
rc = -1 ;
}
alarm(oldalarm) ;
return rc ;
}
}
#endif /* CK_NETBIOS */
#ifdef NPIPE
if ( nettype == NET_PIPE ) {
if ( hPipe ) { /* Make sure a pipe isn't open */
char buffer[64];
rc = DosPeekNPipe(hPipe, buffer, sizeof(buffer),
&BytesRead, &AvailData, &PipeState);
switch ( rc ) {
case NO_ERROR:
return 0 ;
case ERROR_BAD_PIPE:
case ERROR_PIPE_NOT_CONNECTED:
ttclos(0);
break;
default:
break;
}
}
if ( *name == '\0' ) {
strcpy( PipeName, "\\PIPE\\C-Kermit for OS2" ) ;
} else {
strcpy( PipeName, name ) ;
}
if ( PipeName[0] == '\\' && PipeName[1] == '\\' ) {
/* Client Mode */
OpenFlag = OPEN_ACTION_OPEN_IF_EXISTS ;
OpenMode = OPEN_FLAGS_WRITE_THROUGH |
OPEN_FLAGS_FAIL_ON_ERROR |
OPEN_FLAGS_RANDOM |
OPEN_SHARE_DENYNONE |
OPEN_ACCESS_READWRITE ;
if (PipeName[2] == '.' && PipeName[3] == '\\') { /* Internal use. */
int i, n = strlen(PipeName);
for (i = 3; i <= n; i++)
PipeName[i-3] = PipeName[i];
}
rc = DosOpen( PipeName, &hPipe, &ActionTaken, 0, 0,
OpenFlag, OpenMode, 0 ) ;
switch (rc) {
case NO_ERROR:
ttyfd = hPipe ;
DosSetNPHState( hPipe, NP_NOWAIT | NP_READMODE_BYTE ) ;
printf(
"\nNamed Pipe %s open.\nConnection to server complete.\n",
PipeName
);
break;
case ERROR_BAD_NETPATH:
printf("\nInvalid Server specified in Pipe Name: %s\n",
PipeName ) ;
break;
case ERROR_PATH_NOT_FOUND:
case ERROR_FILE_NOT_FOUND:
printf("\nNonexistent Named Pipe: %s\n", PipeName ) ;
break;
case ERROR_PIPE_BUSY:
printf("\nNamed Pipe Already in Use: %s\n", PipeName ) ;
break;
default:
debug( F101, "DosOpen error: return code","",rc) ;
printf( "\nDosOpen error: return code = %ld\n",rc ) ;
}
} else { /* Server Mode */
OpenMode = NP_ACCESS_DUPLEX | NP_INHERIT | NP_NOWRITEBEHIND |
NP_TYPE_BYTE | NP_READMODE_BYTE ;
PipeMode = NP_NOWAIT | 0x01;
OutBufSize = MAXSP + 4 ;
InBufSize = MAXRP + 4 ;
TimeOut = 10000;
rc = DosCreateNPipe( PipeName, &hPipe, OpenMode,
PipeMode, OutBufSize, InBufSize, TimeOut);
switch (rc) {
case NO_ERROR:
ttyfd = hPipe ;
rc = DosConnectNPipe( hPipe ) ;
if (rc == NO_ERROR || rc == ERROR_PIPE_NOT_CONNECTED) {
printf("\nNamed Pipe %s created.\nWaiting for client connection ...\n\n",
PipeName ) ;
rc = 0 ;
} else {
debug( F101,"DosConnectNPipe error: return code","",rc) ;
printf("\nDosConnectNPipe error: return code = %ld\n", rc);
}
break;
case ERROR_PATH_NOT_FOUND:
printf("\nInvalid Pipe Name: %s\n", PipeName ) ;
break;
case ERROR_PIPE_BUSY:
printf("\nNamed Pipe Already in Use: %s\n", PipeName ) ;
break;
default:
debug( F101,"DosCreateNPipe error: return code","",rc) ;
printf("\nDosCreateNPipe error: return code = %ld\n", rc);
}
}
return ( rc ? -1 : 0 ) ;
}
#endif /* NPIPE */
#ifdef TCPSOCKET
if ( nettype == NET_TCPB ) {
if (!tcp_avail)
return -1 ;
rc = netopen(name, lcl, nett);
#ifdef COMMENT
if ( rc > -1) rc = tn_ini();
#endif /* COMMENT */
return(rc);
}
#endif /* TCPSOCKET */
#ifdef DECNET
if ( nettype == NET_DEC ) {
if ( LATENTRY == NULL )
return -1;
ttnproto = NP_LAT;
printf("Trying %s ... ", name);
memset( &lcb, 0, sizeof(struct lat_cb) ) ;
lcb.LatFunction = START_SESSION;
lcb.BufferSize = strlen(name);
lcb.BufferPtr = (void * _Seg16) name;
LATENTRY(&lcb);
ttyfd = lcb.SessionHandle;
printf(lcb.LatStatus ? "failed.\n" : "OK.\n");
rc = (lcb.LatStatus == 0) ? 0 : -1;
}
#endif /* DECNET */
return rc;
}
/* N E T C L O S -- Close current network connection. */
int
os2_netclos() {
int rc = 0;
if (ttyfd < 0) /* Was open? */
return(rc); /* Wasn't. */
#ifdef CK_NETBIOS
if ( nettype == NET_BIOS ) {
ULONG PostCount ;
if ( NetBiosLSN >= 0 ) {
NCB CleanupNCB ;
int i ;
if ( pWorkNCB->basic_ncb.bncb.ncb_retcode == NB_COMMAND_IN_PROCESS )
NCBCancel( NetbeuiAPI, &CleanupNCB, NetBiosAdapter, pWorkNCB ) ;
if ( pListenNCB->basic_ncb.bncb.ncb_retcode == NB_COMMAND_IN_PROCESS )
{
NCBCancel( NetbeuiAPI, &CleanupNCB, NetBiosAdapter, pListenNCB ) ;
DosWaitEventSem( hevNetBiosLSN, SEM_INDEFINITE_WAIT ) ;
}
if ( pRecvNCB->basic_ncb.bncb.ncb_retcode == NB_COMMAND_IN_PROCESS )
NCBCancel( NetbeuiAPI, &CleanupNCB, NetBiosAdapter, pRecvNCB ) ;
for ( i=0 ; i<MAXWS ; i++ ) {
if ( pSendNCB[i]->basic_ncb.bncb.ncb_retcode == NB_COMMAND_IN_PROCESS )
NCBCancel( NetbeuiAPI, &CleanupNCB, NetBiosAdapter, pSendNCB[i] ) ;
}
NCBHangup( NetbeuiAPI, pWorkNCB, NetBiosAdapter, NetBiosLSN ) ;
}
NetBiosLSN = 0 ;
strncpy( NetBiosRemote, " ", NETBIOS_NAME_LEN ) ;
DosResetEventSem( hevNetBiosLSN, &PostCount ) ;
ttyfd = -1 ;
Dos16SemSet( pListenNCB->basic_ncb.ncb_semaphore ) ;
}
#endif /* CK_NETBIOS */
#ifdef NPIPE
if ( nettype == NET_PIPE ) {
if ( hPipe ) {
rc = DosClose( hPipe ) ;
hPipe = 0 ;
ttyfd = -1 ;
}
return rc ;
}
#endif /* NPIPE */
#ifdef TCPSOCKET
if ( nettype == NET_TCPB )
{
if (!tcp_avail)
return -1 ;
return netclos();
}
#endif /* TCPSOCKET */
#ifdef DECNET
if ( nettype == NET_DEC ) {
if (ttyfd > -1) {
memset( &lcb, 0, sizeof(struct lat_cb) ) ;
lcb.LatFunction = STOP_SESSION;
lcb.SessionHandle = ttyfd;
LATENTRY(&lcb);
rc = (lcb.LatStatus == 0) ? 0 : -1;
}
}
#endif /* DECNET */
ttyfd = -1; /* Mark it as closed. */
return(rc);
}
/* N E T T C H K -- Check if network up, and how many bytes can be read */
/*
Returns number of bytes waiting, or -1 if connection has been dropped.
*/
int /* Check how many bytes are ready */
os2_nettchk() { /* for reading from network */
#ifdef NPIPE
int rc = 0 ;
ULONG bytesread ;
AVAILDATA availdata ;
ULONG PipeState ;
#endif /* NPIPE */
#ifdef CK_NETBIOS
if ( nettype == NET_BIOS ) {
if ( NetBiosLSN > 0 )
{
SESSIONINFO statusinfo ;
if ( pos < size )
return size - pos ;
#ifndef NONBTCHK
/* This is for testing on a machine with LAN Distance installed
when we want to run two CKs on the same machine without connecting
to a remote network. NCBSessionStatus fails to return under
these conditions.
*/
NCBSessionStatus( NetbeuiAPI, pWorkNCB, NetBiosAdapter, NetBiosName,
&statusinfo, sizeof(SESSIONINFO), TRUE ) ;
if ( pWorkNCB->basic_ncb.bncb.ncb_retcode == NB_COMMAND_SUCCESSFUL &&
statusinfo.session_state > NB_SESSION_STATE_SESSION_ACTIVE )
#endif /* NONBTCHK */
return 0 ;
}
return -1 ;
}
#endif /* CK_NETBIOS */
#ifdef NPIPE
if ( nettype == NET_PIPE ) {
char buffer[64];
if ( pos < size )
return size - pos ;
if ( !(rc = DosPeekNPipe(hPipe, buffer, sizeof(buffer),
&bytesread, &availdata, &PipeState)) ) {
switch ( PipeState ) {
case NP_STATE_DISCONNECTED:
case NP_STATE_CLOSING:
if ( PipeName[0] != PipeName[1] ) {
/* Server Mode */
DosDisConnectNPipe( hPipe ) ;
DosConnectNPipe( hPipe ) ;
} else {
/* Client Mode */
ttclos(0) ;
}
return -2 ;
break;
case NP_STATE_LISTENING:
return 0 ;
break;
case NP_STATE_CONNECTED:
return availdata.cbpipe ;
break;
default:
return -1 ;
} /* switch */
} else
return (rc > 0 ? -rc : rc) ;
}
#endif /* NPIPE */
#ifdef TCPSOCKET
if ( nettype == NET_TCPB )
{
if (!tcp_avail)
return -1 ;
return nettchk();
}
#endif /* TCPSOCKET */
#ifdef DECNET
if ( nettype == NET_DEC ) {
if ( pos < size ) {
return size - pos ;
} else {
memset( &lcb, 0, sizeof(struct lat_cb) ) ;
lcb.LatFunction = GET_STATUS ;
lcb.SessionHandle = ttyfd;
LATENTRY(&lcb);
debug(F101,"os2_nettchk (DECNET) lcb.SessionStatus",
"",lcb.SessionStatus) ;
debug(F101,"os2_nettchk (DECNET) lcb.LatStatus","",lcb.LatStatus) ;
return ( lcb.LatStatus & LS_RxData ) ? 1 : 0 ;
}
}
#endif /* DECNET */
return(0);
}
/* N E T T I N C -- Input character from network */
int
os2_netinc(timo) int timo; {
int chr = -1;
int rc = 0 ;
time_t timer, timenow ;
#ifdef CK_NETBIOS
if ( nettype == NET_BIOS ) {
if ( NetBiosLSN == -1 )
return -1 ;
else if ( NetBiosLSN == 0 )
{
if ( pListenNCB->basic_ncb.bncb.ncb_retcode != NB_COMMAND_IN_PROCESS )
{
return -1 ;
}
else {
rc = DosWaitEventSem( hevNetBiosLSN,
timo > 0 ? timo * 1000 :
timo < -1 ? 1000 : SEM_INDEFINITE_WAIT ) ;
if (rc) return -1 ;
}
}
if ( pos < size ) {
chr = inbuf[pos++];
}
else {
rc = 0 ;
if ( ( pRecvNCB->basic_ncb.bncb.ncb_retcode) == NB_COMMAND_IN_PROCESS)
{
rc = Dos16SemWait( pRecvNCB->basic_ncb.ncb_semaphore,
timo > 0 ? timo * 1000 :
timo < -1 ? 1000 : SEM_INDEFINITE_WAIT ) ;
}
if ( rc )
{
return -1 ;
}
switch ( pRecvNCB->basic_ncb.bncb.ncb_retcode ) {
case NB_COMMAND_SUCCESSFUL:
if ( (size = pRecvNCB->basic_ncb.bncb.ncb_length) == 0 )
return -1 ;
memcpy( inbuf, NetBiosRecvBuf, size ) ;
rc = NCBReceive( NetbeuiAPI, pRecvNCB, NetBiosAdapter,
NetBiosLSN, NetBiosRecvBuf, sizeof(NetBiosRecvBuf), FALSE );
break;
case NB_SESSION_CLOSED:
case NB_SESSION_ENDED_ABNORMALLY:
ttclos(0) ;
if ( ttname[0] == '*' )
{
os2_netopen( "*",0,0 ) ;
return -1 ;
}
else
return -3 ;
break;
case NB_OS_ERROR_DETECTED:
ttclos(0) ;
return -3 ;
break;
case NB_COMMAND_IN_PROCESS:
case NB_COMMAND_TIME_OUT:
case NB_COMMAND_CANCELLED:
default:
return -1 ;
}
pos = 0 ;
chr = inbuf[pos++] ;
}
return chr ;
}
#endif /* CK_NETBIOS */
#ifdef NPIPE
if ( nettype == NET_PIPE ) {
if ( timo < -1 )
timo = 1 ; /* Can't set timeout less than 1 sec */
if ( pos < size ) {
chr = inbuf[pos++];
} else {
if ( !timo ) {
while ( !os2_nettchk() )
DosSleep(100) ;
} else {
timer = 0 ;
while (1) {
if ( os2_nettchk() )
break;
if ( timo > 0 ) {
if ( !timer )
timer = time(0) ;
timenow = time(0) ;
if ( timenow - timer > timo )
return -1 ;
}
DosSleep(100) ;
}
}
rc = DosRead( hPipe, &inbuf, sizeof(inbuf), &size ) ;
switch ( rc ) {
case NO_ERROR:
if ( !size )
return -1 ;
break;
case ERROR_BROKEN_PIPE:
if ( PipeName[0] != PipeName[1] ) {
/* Server Mode */
DosDisConnectNPipe( hPipe ) ;
DosConnectNPipe( hPipe ) ;
} else {
/* Client Mode */
ttclos(0) ;
}
return -2 ;
break;
default:
return -1 ;
}
pos = 0 ;
chr = inbuf[pos++] ;
}
return chr ;
}
#endif /* NPIPE */
#ifdef TCPSOCKET
if ( nettype == NET_TCPB ) {
if (!tcp_avail)
return -1 ;
if ( (chr = netinc(timo)) != -1 )
return chr;
else
return (nettchk() == -1) ? -2 : -1;
}
#endif /* TCPSOCKET */
#ifdef DECNET
if ( nettype == NET_DEC ) {
if ( pos < size )
return inbuf[pos++];
memset( &lcb, 0, sizeof(struct lat_cb) ) ;
memset( inbuf, 0, sizeof(inbuf) ) ;
lcb.LatFunction = GET_CHAR_BLK;
lcb.SessionHandle = ttyfd;
lcb.BufferSize = sizeof(inbuf);
lcb.BufferPtr = (void * _Seg16) inbuf;
if ( timo < -1 )
lcb.WaitTime = 10L * -timo ;
else if ( timo > 0 )
lcb.WaitTime = 1000L * timo ;
else
lcb.WaitTime = LAT_INDEFINITE_WAIT ;
LATENTRY(&lcb);
debug(F101,"os2_netinc (DECNET) lcb.SessionStatus","",
lcb.SessionStatus) ;
debug(F101,"os2_netinc (DECNET) lcb.LatStatus","",lcb.LatStatus) ;
if ( (lcb.SessionStatus & 0xFF) == SS_Stopped )
return -2;
if ( lcb.LatStatus ) {
if ( lcb.LatStatus & LS_InvalidSize )
debug(F101,"os2_netinc (DECNET) LS_InvalidSize","",
lcb.BufferSize) ;
return -1 ;
}
pos = 0;
size = lcb.BufferSize;
debug(F111,"os2_netinc (DECNET) lcb.BufferSize",inbuf,lcb.BufferSize) ;
chr = inbuf[pos++];
}
#endif /* DECNET */
return chr;
}
#ifdef CK_NETBIOS
static int NextSendNCB = 0 ;
#endif /* CK_NETBIOS */
/* N E T T O C -- Output character to network */
/*
Call with character to be transmitted.
Returns 0 if transmission was successful, or
-1 upon i/o error, or -2 if called improperly.
*/
int
os2_nettoc(c) int c; {
#ifdef DECNET
int i;
#endif /* DECNET */
int rc = -1;
ULONG bytesWritten ;
#ifdef CK_NETBIOS
if ( nettype == NET_BIOS ) {
int i = 0 ;
int SendNCB ;
UCHAR chr = c ;
if ( NetBiosLSN == -1 )
return -1 ;
else if ( NetBiosLSN == 0 ) {
#ifdef COMMENT
/*
This code enables us to issue a blocking send prior to the
establishment of a connection. The problem with this is that
when a connection terminates and we are in Kermit Server mode,
the Kermit Server will send a NAK in response to the timeout it
received when the connection was lost. This NAK will be the
first packet received by the next Client to complete a connection,
and all packets in the exchange will be out of sequence.
Therefore, we don't allow packets to be issued prior to the
establishment of a real connection.
*/
if ( pListenNCB->basic_ncb.bncb.ncb_retcode !=
NB_COMMAND_IN_PROCESS ) {
return -1 ;
} else {
rc = DosWaitEventSem( hevNetBiosLSN,
SEM_INDEFINITE_WAIT ) ;
if (rc) return -1 ;
}
#else
if ( pListenNCB->basic_ncb.bncb.ncb_retcode !=
NB_COMMAND_SUCCESSFUL )
return -1 ;
#endif /* COMMENT */
}
for ( SendNCB = 0 ; SendNCB < MaxCmds ; SendNCB++ ) {
if (pSendNCB[SendNCB]->basic_ncb.bncb.ncb_retcode
!= NB_COMMAND_IN_PROCESS )
break;
}
if ( SendNCB == MaxCmds )
return -1 ;
if (pSendNCB[SendNCB]->basic_ncb.bncb.ncb_retcode
== NB_COMMAND_IN_PROCESS) {
NCB CancelNCB ;
rc = NCBCancel( NetbeuiAPI, &CancelNCB, NetBiosAdapter,
pSendNCB[SendNCB] ) ;
Dos16SemWait( pSendNCB[SendNCB]->basic_ncb.ncb_semaphore,
SEM_INDEFINITE_WAIT ) ;
}
memcpy( NetBiosSendBuf[SendNCB], &chr, sizeof(chr) ) ;
rc = NCBSend( NetbeuiAPI, pSendNCB[SendNCB], NetBiosAdapter,
NetBiosLSN, NetBiosSendBuf[SendNCB], sizeof(chr), FALSE );
#ifdef COMMENT
/* Let's try a nonblocking Send */
Dos16SemWait( pSendNCB[SendNCB]->basic_ncb.ncb_semaphore,
SEM_INDEFINITE_WAIT ) ;
#endif /* COMMENT */
switch ( pSendNCB[SendNCB]->basic_ncb.bncb.ncb_retcode ) {
case NB_COMMAND_SUCCESSFUL:
case NB_COMMAND_IN_PROCESS:
return 0 ;
break;
case NB_SESSION_CLOSED:
case NB_SESSION_ENDED_ABNORMALLY:
ttclos(0) ;
if ( ttname[0] == '*' ) {
os2_netopen( "*",0,0 ) ;
return -1 ;
} else
return -2 ;
break;
case NB_OS_ERROR_DETECTED:
ttclos(0) ;
return -3 ;
break;
case NB_COMMAND_TIME_OUT:
case NB_COMMAND_CANCELLED:
default:
return -1 ;
}
}
#endif /* CK_NETBIOS */
#ifdef NPIPE
if ( nettype == NET_PIPE ) {
UCHAR chr = c ;
rc = DosWrite( hPipe, &chr, sizeof(chr), &bytesWritten ) ;
if ( rc )
return -1 ;
else
return 0 ;
}
#endif /* NPIPE */
#ifdef TCPSOCKET
if ( nettype == NET_TCPB ) {
if (!tcp_avail)
return -1 ;
return nettoc((char) c);
}
#endif /* TCPSOCKET */
#ifdef DECNET
if ( nettype == NET_DEC ) {
debug(F100,"os2_nettoc (DECNET) begin send char","",0);
pos = size ;
/* Send the character */
memset( &lcb, 0, sizeof(struct lat_cb) ) ;
lcb.LatFunction = SEND_CHAR;
lcb.SessionHandle = ttyfd;
lcb.CharByte = c;
LATENTRY(&lcb);
debug(F101,"os2_nettoc (DECNET) lcb.SessionStatus","",
lcb.SessionStatus) ;
debug(F101,"os2_nettoc (DECNET) lcb.LatStatus","",lcb.LatStatus) ;
for (i = 0; i < 10000 && ( lcb.LatStatus & LS_CharNotSent ); i++) {
DosSleep(1); /* give up rest of current timeslice */
LATENTRY(&lcb) ;
debug(F100,"os2_nettoc (DECNET) repeat char send","",0);
debug(F101,"os2_nettoc (DECNET) lcb.SessionStatus",
"",lcb.SessionStatus) ;
debug(F101,"os2_nettoc (DECNET) lcb.LatStatus","",lcb.LatStatus) ;
}
debug(F100,"os2_nettoc (DECNET) end send char","",0);
rc = (lcb.LatStatus == LS_NoError) ? 0 : -1;
}
#endif /* DECNET */
return rc;
}
/* N E T T O L -- Output a string of bytes to the network */
/*
Call with s = pointer to string, n = length.
Returns number of bytes actuall written on success, or
-1 on i/o error, -2 if called improperly.
*/
int
os2_nettol(s,n) char *s; int n; {
int rc;
#ifdef NPIPE
ULONG bytesWritten ;
#endif /* NPIPE */
#ifdef CK_NETBIOS
int SendNCB ;
if ( nettype == NET_BIOS ) {
if ( NetBiosLSN == -1 )
return -3 ;
else if ( NetBiosLSN == 0 ) {
#ifdef COMMENT
/*
This code enables us to issue a blocking send prior to the
establishment of a connection. The problem with this is that
when a connection terminates and we are in Kermit Server mode,
the Kermit Server will send a NAK in response to the timeout it
received when the connection was lost. This NAK will be the
first packet received by the next Client to complete a connection,
and all packets in the exchange will be out of sequence.
Therefore, we don't allow packets to be issued prior to the
establishment of a real connection.
*/
if ( pListenNCB->basic_ncb.bncb.ncb_retcode !=
NB_COMMAND_IN_PROCESS ) {
return -1 ;
} else {
rc = DosWaitEventSem( hevNetBiosLSN,
SEM_INDEFINITE_WAIT ) ;
if (rc) return -1 ;
}
#else
if ( pListenNCB->basic_ncb.bncb.ncb_retcode !=
NB_COMMAND_SUCCESSFUL )
return -1 ;
#endif /* COMMENT */
}
for ( SendNCB = 0 ; SendNCB < MaxCmds ; SendNCB++ ) {
if (pSendNCB[SendNCB]->basic_ncb.bncb.ncb_retcode
!= NB_COMMAND_IN_PROCESS )
break;
}
if ( SendNCB == MaxCmds )
return -1 ;
if (pSendNCB[SendNCB]->basic_ncb.bncb.ncb_retcode
== NB_COMMAND_IN_PROCESS) {
NCB CancelNCB ;
rc = NCBCancel( NetbeuiAPI, &CancelNCB, NetBiosAdapter,
pSendNCB[SendNCB] );
Dos16SemWait( pSendNCB[SendNCB]->basic_ncb.ncb_semaphore,
SEM_INDEFINITE_WAIT ) ;
}
memcpy( NetBiosSendBuf[SendNCB], s, n ) ;
rc = NCBSend( NetbeuiAPI, pSendNCB[SendNCB], NetBiosAdapter,
NetBiosLSN, NetBiosSendBuf[SendNCB], n, FALSE ) ;
#ifdef COMMENT
/* Lets try a non blocking Send */
Dos16SemWait( pSendNCB[SendNCB]->basic_ncb.ncb_semaphore,
SEM_INDEFINITE_WAIT ) ;
#endif /* COMMENT */
debug(F101,"NETTOL: SendNCB","",SendNCB ) ;
debug(F101,"NETTOL: NCB_retcode","",
pSendNCB[SendNCB]->basic_ncb.bncb.ncb_retcode ) ;
switch ( pSendNCB[SendNCB]->basic_ncb.bncb.ncb_retcode ) {
case NB_COMMAND_SUCCESSFUL:
case NB_COMMAND_IN_PROCESS:
return pSendNCB[SendNCB]->basic_ncb.bncb.ncb_length ;
break;
case NB_SESSION_CLOSED:
case NB_SESSION_ENDED_ABNORMALLY:
ttclos(0) ;
if ( ttname[0] == '*' ) {
os2_netopen( "*",0,0 ) ;
return -1 ;
} else
return -2 ;
break;
case NB_OS_ERROR_DETECTED:
ttclos(0) ;
return -3 ;
break;
case NB_MAX_CMNDS_EXCEEDED:
case NB_COMMAND_TIME_OUT:
case NB_COMMAND_CANCELLED:
default:
return -1 ;
}
}
#endif /* CK_NETBIOS */
#ifdef NPIPE
if ( nettype == NET_PIPE ) {
rc = DosWrite( hPipe, s, n, &bytesWritten ) ;
return ( rc ? -1 : bytesWritten ) ;
}
#endif /* NPIPE */
#ifdef TCPSOCKET
if ( nettype == NET_TCPB ) {
if (!tcp_avail)
return -1 ;
return nettol(s, n);
}
#endif /* TCPSOCKET */
#ifdef DECNET
if ( nettype == NET_DEC ) {
for ( rc = 0; rc < n; rc++, s++ )
if ( os2_nettoc(*s) )
break;
}
#endif /* DECNET */
return(rc);
}
/* N E T F L U I -- Flush network input buffer */
int
os2_netflui() {
#ifdef CK_NETBIOS
if ( nettype == NET_BIOS ) {
pos = size ;
return 0 ;
}
#endif /* CK_NETBIOS */
#ifdef NPIPE
if ( nettype == NET_PIPE )
pos = size ;
return 0 ;
#endif /* NPIPE */
#ifdef TCPSOCKET
if ( nettype == NET_TCPB )
{
if (!tcp_avail)
return 0 ;
return netflui();
}
#endif /* TCPSOCKET */
#ifdef DECNET
if ( nettype == NET_DEC ) {
pos = size ;
return (0) ;
}
#endif /* DECNET */
return(0);
}
/* Send network BREAK */
/*
Returns -1 on error, 0 if nothing happens, 1 if BREAK sent successfully.
*/
int
os2_netbreak() {
int rc = -1;
#ifdef CK_NETBIOS
if ( nettype == NET_BIOS ) {
return 0 ;
}
#endif /* CK_NETBIOS */
#ifdef NPIPE
if ( nettype == NET_PIPE )
return 0 ;
#endif /* NPIPE */
#ifdef TCPSOCKET
if ( nettype == NET_TCPB ) {
if (!tcp_avail)
return -1 ;
return netbreak();
}
#endif /* TCPSOCKET */
#ifdef DECNET
if ( nettype == NET_DEC ) {
memset( &lcb, 0, sizeof(struct lat_cb) ) ;
lcb.LatFunction = SEND_BREAK;
lcb.SessionHandle = ttyfd;
LATENTRY(&lcb);
rc = (lcb.LatStatus == 0) ? 0 : -1;
}
#endif /* DECNET */
return rc;
}
/*
* what follows is all dynamic link stuff to let the same executable
* run on machines with and without networking software
*/
#ifdef __32BIT__
#define GetProc(h, n, e) DosQueryProcAddr(h, 0, n, (PFN *) e)
#define PREFIX
#else
#define GetProc(h, n, e) DosGetProcAddr(h, n, (PFN *) e)
#define PREFIX "_"
#endif
#ifdef TCPSOCKET
int
os2_tcpipinit() {
char dll[_MAX_PATH], fail[_MAX_PATH];
HMODULE library;
extern char startupdir[];
int rc=1 ;
char * CKTCPIPDLL ;
char *p, *q;
p = q = strdup(startupdir);
if (p) {
while (*p) {
if (*p == '/') *p = '\\';
if (islower(*p)) *p = toupper(*p);
p++;
}
p = q;
} else p = startupdir;
tcp_avail = 0 ;
if (deblog) {
printf( " TCP/IP support..." ) ;
debug(F100,"TCP/IP support...","",0);
}
tcpname[0] = NUL;
/* User can override DLL search order with an environment variable */
CKTCPIPDLL = getenv( "CKTCPIPDLL" ) ;
if ( CKTCPIPDLL ) {
strcpy(dll, p);
strcat(dll, CKTCPIPDLL );
rc = DosLoadModule(fail, sizeof(fail), dll, &library) ;
if (!rc) {
if (deblog) printf( "CKTCPIPDLL=%s loaded...",CKTCPIPDLL) ;
sprintf(tcpname,"CKTCPIPDLL=%s",CKTCPIPDLL) ;
debug(F111,"CKTCPIPDLL var loaded",CKTCPIPDLL,rc);
} else
debug(F111,"CKTCPIPDLL file not found",CKTCPIPDLL,rc);
} else
debug(F100,"CKTCPIPDLL not defined","",0);
#ifdef __32BIT__
/*
Attempt to load in the following order:
1. CKTCPIPDLL environment variable
2. IBM 2.0
3. FTP 1.3
4. IBM 1.2
*/
if (rc != 0) {
strcpy(dll, p);
strcat(dll, "CKO32I20.DLL");
rc = DosLoadModule(fail, sizeof(fail), dll, &library) ;
if (!rc) {
if (deblog) printf( "32bit IBM 2.0 TCP/IP loaded...") ;
sprintf(tcpname,"%s = 32-bit IBM TCP/IP 2.0", dll);
debug(F111,"32bit IBM TCP/IP 2.0 loaded",dll,rc);
} else
debug(F111,"32bit IBM TCP/IP 2.0 load failed",dll,rc);
}
if (rc != 0) {
strcpy(dll, p);
strcat(dll, "CKO32F13.DLL");
rc = DosLoadModule(fail, sizeof(fail), dll, &library) ;
if (!rc) {
if (deblog) printf( "32bit FTP PC/TCP 1.3 loaded...") ;
sprintf(tcpname,"%s = 32-bit FTP PC/TCP 1.3", dll);
debug(F111,"32bit FTP PC/TCP 1.3 loaded",dll,rc);
} else
debug(F111,"32bit FTP PC/TCP 1.3 load failed",dll,rc);
}
if (rc != 0) {
strcpy(dll, p);
strcat(dll, "CKO32I12.DLL");
rc = DosLoadModule(fail, sizeof(fail), dll, &library) ;
if (!rc)
{
HMODULE tcpiplib ;
PFN pfn ;
rc = DosLoadModule(fail, sizeof(fail), "TCPIPDLL", &tcpiplib) ;
rc = GetProc(tcpiplib,"_bsdselect", &pfn);
}
if (!rc) {
if (deblog)
printf( "32bit IBM TCP/IP 1.2 (or compatible) loaded...") ;
sprintf(tcpname,"%s = 32-bit IBM TCP/IP 1.2 (or compatible)", dll);
debug(F111,"32bit IBM TCP/IP 1.2 (or compatible) loaded",dll,rc);
} else
debug(F111,
"32bit IBM TCP/IP 1.2 (or compatible) load failed",dll,rc);
}
#else
/*
Attempt to load in the following order:
1. CKTCPIPDLL environment variable
2. FTP 1.3
3. IBM 1.2
*/
if (rc != 0) {
strcpy(dll, p);
strcat(dll, "CKO16F13.DLL");
rc = DosLoadModule(fail, sizeof(fail), dll, &library) ;
if (!rc) {
if (deblog) printf( "16bit FTP PC/TCP 1.3 loaded...") ;
sprintf(tcpname,"%s = 16-bit FTP PC/TCP 1.3", dll);
debug(F111,"16bit FTP PC/TCP 1.3 loaded",dll,rc);
} else
debug(F111,"16bit FTP PC/TCP 1.3 load failed",dll,rc);
}
if (rc != 0) {
strcpy(dll, p);
strcat(dll, "CKO16I12.DLL");
rc = DosLoadModule(fail, sizeof(fail), dll, &library) ;
if (!rc)
{
HMODULE tcpiplib ;
PFN pfn ;
rc = DosLoadModule(fail, sizeof(fail), "TCPIPDLL", &tcpiplib) ;
rc = GetProc(tcpiplib,"_bsdselect", &pfn);
}
if (!rc) {
if (deblog)
printf( "16bit IBM TCP/IP 1.2 (or compatible) loaded...") ;
sprintf(tcpname,"%s = 16-bit IBM TCP/IP 1.2", dll);
debug(F111,"16bit IBM TCP/IP 1.2 (or compatible) loaded",dll,rc);
} else
debug(F111,
"16bit IBM TCP/IP 1.2 (or compatible) load failed",dll,rc);
}
#endif /* __32BIT__ */
if (rc != 0) {
if (deblog) {
printf( "Not installed\n") ;
debug(F101,"TCP/IP not installed - rc","",rc);
}
sprintf(tcpname,"(no TCP/IP DLL found)");
return -1;
}
if (GetProc(library, PREFIX "ck_sockinit", &sockinit) ||
GetProc(library, PREFIX "ck_connect", &connect) ||
GetProc(library, PREFIX "ck_ioctl", &ioctl) ||
GetProc(library, PREFIX "ck_recv", &recv) ||
GetProc(library, PREFIX "ck_select", &select) ||
GetProc(library, PREFIX "ck_send", &send) ||
GetProc(library, PREFIX "ck_setsockopt", &setsockopt) ||
GetProc(library, PREFIX "ck_socket", &socket) ||
GetProc(library, PREFIX "ck_soclose", &soclose) ||
GetProc(library, PREFIX "ck_gethostbyname", &gethostbyname) ||
GetProc(library, PREFIX "ck_getservbyname", &getservbyname) ||
GetProc(library, PREFIX "ck_inet_addr", &inet_addr) ||
GetProc(library, PREFIX "ck_inet_ntoa", &inet_ntoa)) {
if (deblog) {
printf( "Not installed\n") ;
debug(F100,"TCP/IP not installed","",0);
}
strcat(tcpname," - ERROR: Missing Entry Points");
return -1;
}
if (rc = sockinit()) {
tcp_avail = 0 ;
if (deblog) {
printf( "init failed\n" ) ;
strcat(tcpname," - ERROR: Initialization Failed");
debug(F101,"TCP/IP sockinit() failed","",rc);
}
} else {
tcp_avail = 1;
if (deblog) {
printf( "initialized\n" ) ;
debug(F101,"TCP/IP sockinit() successful","",rc);
}
}
return rc;
}
#endif /* TCPSOCKET */
void
netinit() {
extern int nettype;
char fail[256];
HMODULE library;
if (deblog)
{
printf( "Initializing Network Support:\n" ) ;
debug(F100,"Initializing Network Support:","",0) ;
}
#ifdef CK_NETBIOS
os2_netbiosinit() ;
#endif /* CK_NETBIOS */
#ifdef DECNET
if (deblog) {
printf(" DECNet support..." ) ;
debug(F100,"DECNet support...","",0);
}
if ( !DosLoadModule(fail, sizeof(fail), "LATCALLS", &library) ) {
if ( !GetProc(library, "LATENTRY", &LATENTRY) ) {
dnet_avail = 1;
if (deblog) {
printf("OK\n") ;
debug(F100,"DECNet OK","",0);
memset( &lcb, 0, sizeof(struct lat_cb) ) ;
lcb.LatFunction = READ_LATINFO;
lcb.BufferSize = sizeof(latinfo);
lcb.BufferPtr = (void * _Seg16) &latinfo;
LATENTRY(&lcb);
debug(F101,"DECNet LatStatus","",lcb.LatStatus) ;
if (!lcb.LatStatus) {
debug(F101,"DECNet Major Version","",latinfo.vermjr) ;
debug(F101,"DECNet Minor Version","",latinfo.vermir) ;
debug(F101,"DECNet Max Sessions","",latinfo.NSessions) ;
debug(F101,"DECNet Max Buffers per Session","",
latinfo.NBuffers) ;
debug(F101,"DECNet Max Services","",latinfo.NServices) ;
}
}
} else {
dnet_avail = 0 ;
if (deblog) {
printf("Not installed\n" ) ;
debug(F100,"DECNet not installed","",0) ;
}
}
} else {
dnet_avail = 0 ;
if (deblog) {
printf("Not installed\n" ) ;
debug(F100,"DECNet not installed","",0) ;
}
}
#endif /* DECNET */
#ifdef TCPSOCKET
os2_tcpipinit() ;
#ifdef COMMENT
/* this code should never have been added to this module */
/* it results in there being an override variable even when */
/* one has never been assigned by the user */
if (tn_term == NULL) {
switch (tt_type) {
case TT_VT52: tn_term = strdup("vt52"); break;
case TT_VT100: tn_term = strdup("vt100"); break;
case TT_VT102: tn_term = strdup("vt102"); break;
case TT_VT220: tn_term = strdup("vt220"); break;
case TT_ANSI: tn_term = strdup("ansi"); break;
}
}
#endif /* COMMENT */
#endif /* TCPSOCKET */
if (tcp_avail) /* Set the default network type */
nettype = NET_TCPB; /* TCP/IP first */
else if (dnet_avail) /* Then DECnet */
nettype = NET_DEC;
#ifdef COMMENT
/*
NetBios cannot be set as a default network type even though
we would like to because it requires that a NetBiosName be
specified. If the default is already in use, then we will
not know what name to use. Not providing a name will leave
Kermit in an unknown state (network type NetBios without any
means for addressing this session.) Better never to allow
it to be set as a default.
All the code to implement it is shown below though just in case.
*/
else if (netbiosAvail) { /* Then NETBIOS */
NCB ncb ;
APIRET rc ;
int x,y ;
nettype = NET_BIOS;
strncpy(NetBiosName, (*myhost?myhost:"kermit"),NETBIOS_NAME_LEN);
for (x = y; x < NETBIOS_NAME_LEN; x++)
NetBiosName[x] = SP;
NetBiosName[NETBIOS_NAME_LEN] = NUL;
printf("Verifying \"%s\" is a unique NetBIOS node name ...\n",
NetBiosName) ;
rc = NCBAddName( NetbeuiAPI, &ncb, 0, NetBiosName ) ;
if ( rc ) {
printf(
"?Sorry, \"%s\" is already in use by another NetBIOS node.\n",
NetBiosName);
for ( x=0; x < NETBIOS_NAME_LEN; x++)
NetBiosName[x] = SP ;
}
}
#endif /* COMMENT */
#ifdef NPIPE
else { /* Otherwise Named Pipes, */
nettype = NET_PIPE; /* which is always there. */
strncpy(pipename,"kermit",PIPENAML); /* better set the pipename */
}
#else
else nettype = NET_NONE;
#endif /* NPIPE */
}
int
netcleanup() {
#ifdef CK_NETBIOS
os2_netbioscleanup() ;
#endif /* CK_NETBIOS */
}
#ifdef CK_NETBIOS
void
NetbiosListenThread(void * pArgList) {
APIRET rc = 0 ;
rc = Dos16SemWait( pListenNCB->basic_ncb.ncb_semaphore,
SEM_INDEFINITE_WAIT ) ;
if ( rc ||
pListenNCB->basic_ncb.bncb.ncb_retcode != NB_COMMAND_SUCCESSFUL ) {
os2_netclos() ;
} else {
ttyfd = NetBiosLSN = pListenNCB->basic_ncb.bncb.ncb_lsn ;
strncpy( NetBiosRemote,
pListenNCB->basic_ncb.bncb.ncb_callname,
NETBIOS_NAME_LEN ) ;
#ifdef COMMENT
if ( pRecvNCB->basic_ncb.bncb.ncb_retcode == NB_COMMAND_IN_PROCESS ) {
NCB CleanupNCB ;
NCBCancel( NetbeuiAPI, &CleanupNCB, NetBiosAdapter, pRecvNCB ) ;
Dos16SemWait( pRecvNCB->basic_ncb.ncb_semaphore,
SEM_INDEFINITE_WAIT ) ;
}
#endif /* COMMENT */
NCBReceive( NetbeuiAPI, pRecvNCB, NetBiosAdapter, NetBiosLSN,
NetBiosRecvBuf, sizeof(NetBiosRecvBuf), FALSE ) ;
}
DosPostEventSem( hevNetBiosLSN ) ;
ListenThreadID = -1 ;
}
#endif /* CK_NETBIOS */
#endif /* NETCONN */