Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

496 lines
11 KiB

// TermCap.cpp : This file contains the
// Created: Dec '97
// Author : a-rakeba
// History:
// Copyright (C) 1997 Microsoft Corporation
// All rights reserved.
// Microsoft Confidential
#include <StdLib.h>
#include <Debug.h>
#include <DbgLvl.h>
#include <TermCap.h>
#include <w4warn.h>
#include <TelnetD.h>
#include <TlntUtils.h>
using namespace _Utils;
using CDebugLevel::TRACE_DEBUGGING;
using CDebugLevel::TRACE_HANDLE;
using CDebugLevel::TRACE_SOCKET;
CTermCap* CTermCap::m_pInstance = 0;
int CTermCap::m_iRefCount = 0;
PCHAR CTermCap::m_pszFileName = 0;
extern HANDLE g_hSyncCloseHandle;
// makes sure that there is only one instance of CTermCap created
CTermCap* CTermCap::Instance()
{
if( 0 == m_pInstance )
{
m_pInstance = new CTermCap;
m_iRefCount ++;
}
return m_pInstance;
}
CTermCap::CTermCap()
{
m_lpBuffer = new CHAR[BUFF_SIZE3];
}
CTermCap::~CTermCap()
{
delete [] m_pszFileName;
delete [] m_lpBuffer;
if(0 == (m_iRefCount --))
{
delete [] m_pInstance;
}
}
//
// This function sits on top of FindEntry so that we have the
// flexibility (in future) to look for the TERMCAP entry in
// areas other than the "termcap" file
//
bool CTermCap::LoadEntry( LPSTR lpszTermName )
{
bool bReturn = false;
if( 0 == lpszTermName )
return ( false );
#if 0
// try to move m_hFile's file pointer to the beginning
LONG lDistance = 0;
DWORD dwPointer = SetFilePointer( m_hFile, lDistance, NULL, FILE_BEGIN );
// if we failed ...
if( dwPointer == 0xFFFFFFFF )
{
// obtain the error code
DWORD dwError = GetLastError() ;
// deal with that failure
_TRACE( TRACE_DEBUGGING, "SetFilePointer() failed %d" , dwError );
}
#endif
m_hFile = CreateFileA( m_pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if ( m_hFile == INVALID_HANDLE_VALUE )
return false ;
//Fix for HANDLE LEAK : close the handle in the caller function.
bReturn = FindEntry( lpszTermName);
TELNET_CLOSE_HANDLE(m_hFile);
return bReturn;
}
//
// This function reads blocks of data from the termcap file.
// Then it looks at each character. If it is a new line
// preceded by a '\' then it continues reading the characters.
// Else, it knows that it has successfully read a complete
// termcap "entry" ( which is stored in m_lpBuffer).
// Then it calls LookForTermName(). If LookForTermName()
// is successful, then the job is done and we have the correct
// "entry" in the m_lpBuffer. Else, ie. if LookForTermName()
// fails, then we repeat the whole process again by reading
// the next block of data in the termcap file.
//
bool CTermCap::FindEntry(LPSTR lpszTermName)
{
if(0 == lpszTermName)
{
return ( false );
}
_chASSERT( m_lpBuffer != 0 );
PCHAR lpBuf;
WORD c;
WORD i = 0;
DWORD dwBytesRead = 0;
PCHAR lpInBuffer = new CHAR[BUFF_SIZE3];
BOOL fResult;
bool ret=false;
if( !lpInBuffer )
{
return false;
}
SfuZeroMemory(lpInBuffer,BUFF_SIZE3);
for(;;)
{
lpBuf = m_lpBuffer;
for(;;)
{
if( i >= dwBytesRead )
{
fResult = ReadFile( m_hFile, lpInBuffer, BUFF_SIZE3,
&dwBytesRead,
NULL );
if( fResult && dwBytesRead == 0 )
{
ret = false;
goto _cleanup;
}
i = 0;
}
c = lpInBuffer[i++];
if( '\r' == c )
c = lpInBuffer[i++];
if( '\n' == c )
{
if( lpBuf > m_lpBuffer && lpBuf[-1] == '\\' )
{
lpBuf--;
continue;
}
break;
}
//if( lpBuf >= m_lpBuffer + BUFF_SIZE3 )
if( (lpBuf - m_lpBuffer) >= BUFF_SIZE3 )
{
_TRACE(CDebugLevel::TRACE_DEBUGGING, "error: TERMCAP entry is way too big");
dwBytesRead =0;
i = 0;
break;
}
else
*lpBuf++ = (CHAR)c;
}
*lpBuf = 0;
if( LookForTermName( lpszTermName ))
{
ret = true;
goto _cleanup;
}
}
_cleanup:
delete [] lpInBuffer;
return ( ret );
}
bool CTermCap::LookForTermName( LPSTR lpszTermName )
{
if( 0 == lpszTermName )
return ( false );
_chASSERT( m_lpBuffer != 0 );
PCHAR lpName;
PCHAR lpBuf = m_lpBuffer;
if('#' == *lpBuf)
return ( false );
for(;;)
{
for( lpName = lpszTermName;
*lpName && toupper( *lpBuf ) == toupper( *lpName );
lpBuf++, lpName++ )
{
continue;
}
if(*lpName == 0 && (*lpBuf == '|' || *lpBuf == ':' || *lpBuf == 0))
{
return ( true );
}
while(*lpBuf && *lpBuf != ':' && *lpBuf != '|')
{
lpBuf++;
}
if(*lpBuf == 0 || *lpBuf == ':')
{
return ( false );
}
lpBuf++;
}
}
#if 0
WORD CTermCap::GetNumber( LPCSTR lpszCapabilityName )
{
if( 0 == lpszCapabilityName )
return ( ( WORD ) -1 );
_chASSERT( m_lpBuffer != 0 );
PCHAR lpBuf = m_lpBuffer;
for(;;)
{
lpBuf = SkipToNextField( lpBuf );
if( NULL == lpBuf )
return ( ( WORD ) -1 );
if( *lpBuf++ != lpszCapabilityName[0] || *lpBuf == 0 ||
*lpBuf++ != lpszCapabilityName[1])
{
continue;
}
if( *lpBuf != '#' )
return ( ( WORD ) -1 );
lpBuf++;
WORD i = 0;
while( isdigit( *lpBuf ))
{
i = i*10 + *lpBuf - '0';
lpBuf++;
}
return ( i );
}
}
#endif
bool CTermCap::CheckFlag(LPCSTR lpszCapabilityName)
{
if( NULL == lpszCapabilityName )
return ( false );
// _chASSERT( m_lpBuffer != 0 );
PCHAR lpBuf = m_lpBuffer;
for(;lpBuf;)
{
lpBuf = SkipToNextField( lpBuf );
if( !*lpBuf )
{
break;
}
if( *lpBuf++ == lpszCapabilityName[0] && *lpBuf != 0 &&
*lpBuf++ == lpszCapabilityName[1] )
{
if(!*lpBuf || *lpBuf == ':')
{
return ( true );
}
else
{
break;
}
}
}
return false;
}
PCHAR CTermCap::SkipToNextField( PCHAR lpBuf )
{
if( NULL == lpBuf )
return ( NULL );
while( *lpBuf && *lpBuf != ':' )
lpBuf++;
if( *lpBuf == ':' )
lpBuf++;
return ( lpBuf );
}
LPSTR CTermCap::GetString( LPCSTR lpszCapabilityName )
{
if( NULL == lpszCapabilityName )
return ( NULL );
// _chASSERT( m_lpBuffer != 0 );
PCHAR pBuf = m_lpBuffer;
for(;pBuf;)
{
pBuf = SkipToNextField( pBuf );
if( !*pBuf )
return ( NULL );
if( *pBuf++ != lpszCapabilityName[0] || *pBuf == 0 ||
*pBuf++ != lpszCapabilityName[1] )
{
continue;
}
if( *pBuf != '=' )
return ( NULL );
pBuf++;
return ( ParseString( pBuf ));
}
return ( NULL );
}
LPSTR CTermCap::ParseString( PCHAR pBuf )
{
if( NULL == pBuf )
return ( NULL );
LPSTR lpszStr = new CHAR[25];
PCHAR p = lpszStr;
WORD c;
if( !lpszStr )
{
return ( NULL );
}
if( *pBuf != '^' )
{
for( c = *pBuf++; ( c && c != ':' ); c = *pBuf++)
{
*p++ = (CHAR)c;
}
}
else
{
//Single control character.
pBuf++;
*p++ = *pBuf - '@' ;
}
*p++ = 0;
return ( lpszStr );
}
// Notes: take care of other options, escapes, codes.
//
LPSTR CTermCap::CursorMove( LPSTR lpszCursMotionStr, WORD wHorPos,
WORD wVertPos )
{
if( NULL == lpszCursMotionStr )
return ( NULL );
PCHAR pCms = lpszCursMotionStr;
LPSTR lpszCmsResult = new CHAR[BUFF_SIZE1];
PCHAR pCmsResult = lpszCmsResult;
WORD c, wNum = 0;
bool fIsColumn = false;
WORD wPos = wHorPos;
if( !lpszCmsResult )
{
return NULL;
}
for( c = *pCms++; c ; c = *pCms++ )
{
if( c != '%' )
{
*pCmsResult++ = (CHAR)c;
continue;
}
switch( c = *pCms++ ) {
case 'd':
_itoa( wPos, pCmsResult, 10 );
while( *pCmsResult != '\0' )
{
pCmsResult++;
}
fIsColumn = !fIsColumn;
wPos = fIsColumn ? wVertPos : wHorPos;
continue;
break;
case '+':
/* %. output value as in printf %c
* %+x add x to value, then do %. */
wNum = ( wPos - 1 ) + *pCms++;
sprintf( pCmsResult, "%c", wNum ); // NO BO here - BaskarK
pCmsResult += strlen( pCmsResult );
wPos = wVertPos;
break;
case 'i':
//wHorPos++;
//wVertPos++;
continue;
default:
delete [] lpszCmsResult;
return NULL;
}
}
*pCmsResult = 0;
return ( lpszCmsResult );
}
//this funtion is sort a of a kludge
//if and when we decide to support
//padding then we need to revisit this
//piece of code.
//we assume that the string sent in
//conatins a padding number followed
//by \E
//it basically strips the padding
//number in the string.
//It also substitutes \033 for \E
void CTermCap::ProcessString( LPSTR* lplpszStr )
{
LPSTR lpszStr = *lplpszStr;
if(lpszStr == NULL)
{
return;
}
PCHAR pStr = new char[ strlen( lpszStr ) + 2 ];
if( !pStr )
{
return;
}
strcpy( pStr, "\033" ); // NO BO - Baskar
PCHAR pChar = lpszStr;
//strip padding
while( (*pChar != '\0') && isdigit( *pChar ) )
{
pChar++;
}
//strip \E
if(*pChar != '\0' )
{
pChar++;
if (*pChar != '\0' )
pChar++;
}
strcat( pStr, pChar );
delete [] lpszStr;
*lplpszStr = pStr;
}