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

  1. // TermCap.cpp : This file contains the
  2. // Created: Dec '97
  3. // Author : a-rakeba
  4. // History:
  5. // Copyright (C) 1997 Microsoft Corporation
  6. // All rights reserved.
  7. // Microsoft Confidential
  8. #include <StdLib.h>
  9. #include <Debug.h>
  10. #include <DbgLvl.h>
  11. #include <TermCap.h>
  12. #include <w4warn.h>
  13. #include <TelnetD.h>
  14. #include <TlntUtils.h>
  15. using namespace _Utils;
  16. using CDebugLevel::TRACE_DEBUGGING;
  17. using CDebugLevel::TRACE_HANDLE;
  18. using CDebugLevel::TRACE_SOCKET;
  19. CTermCap* CTermCap::m_pInstance = 0;
  20. int CTermCap::m_iRefCount = 0;
  21. PCHAR CTermCap::m_pszFileName = 0;
  22. extern HANDLE g_hSyncCloseHandle;
  23. // makes sure that there is only one instance of CTermCap created
  24. CTermCap* CTermCap::Instance()
  25. {
  26. if( 0 == m_pInstance )
  27. {
  28. m_pInstance = new CTermCap;
  29. m_iRefCount ++;
  30. }
  31. return m_pInstance;
  32. }
  33. CTermCap::CTermCap()
  34. {
  35. m_lpBuffer = new CHAR[BUFF_SIZE3];
  36. }
  37. CTermCap::~CTermCap()
  38. {
  39. delete [] m_pszFileName;
  40. delete [] m_lpBuffer;
  41. if(0 == (m_iRefCount --))
  42. {
  43. delete [] m_pInstance;
  44. }
  45. }
  46. //
  47. // This function sits on top of FindEntry so that we have the
  48. // flexibility (in future) to look for the TERMCAP entry in
  49. // areas other than the "termcap" file
  50. //
  51. bool CTermCap::LoadEntry( LPSTR lpszTermName )
  52. {
  53. bool bReturn = false;
  54. if( 0 == lpszTermName )
  55. return ( false );
  56. #if 0
  57. // try to move m_hFile's file pointer to the beginning
  58. LONG lDistance = 0;
  59. DWORD dwPointer = SetFilePointer( m_hFile, lDistance, NULL, FILE_BEGIN );
  60. // if we failed ...
  61. if( dwPointer == 0xFFFFFFFF )
  62. {
  63. // obtain the error code
  64. DWORD dwError = GetLastError() ;
  65. // deal with that failure
  66. _TRACE( TRACE_DEBUGGING, "SetFilePointer() failed %d" , dwError );
  67. }
  68. #endif
  69. m_hFile = CreateFileA( m_pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
  70. OPEN_EXISTING,
  71. FILE_ATTRIBUTE_NORMAL,
  72. NULL);
  73. if ( m_hFile == INVALID_HANDLE_VALUE )
  74. return false ;
  75. //Fix for HANDLE LEAK : close the handle in the caller function.
  76. bReturn = FindEntry( lpszTermName);
  77. TELNET_CLOSE_HANDLE(m_hFile);
  78. return bReturn;
  79. }
  80. //
  81. // This function reads blocks of data from the termcap file.
  82. // Then it looks at each character. If it is a new line
  83. // preceded by a '\' then it continues reading the characters.
  84. // Else, it knows that it has successfully read a complete
  85. // termcap "entry" ( which is stored in m_lpBuffer).
  86. // Then it calls LookForTermName(). If LookForTermName()
  87. // is successful, then the job is done and we have the correct
  88. // "entry" in the m_lpBuffer. Else, ie. if LookForTermName()
  89. // fails, then we repeat the whole process again by reading
  90. // the next block of data in the termcap file.
  91. //
  92. bool CTermCap::FindEntry(LPSTR lpszTermName)
  93. {
  94. if(0 == lpszTermName)
  95. {
  96. return ( false );
  97. }
  98. _chASSERT( m_lpBuffer != 0 );
  99. PCHAR lpBuf;
  100. WORD c;
  101. WORD i = 0;
  102. DWORD dwBytesRead = 0;
  103. PCHAR lpInBuffer = new CHAR[BUFF_SIZE3];
  104. BOOL fResult;
  105. bool ret=false;
  106. if( !lpInBuffer )
  107. {
  108. return false;
  109. }
  110. SfuZeroMemory(lpInBuffer,BUFF_SIZE3);
  111. for(;;)
  112. {
  113. lpBuf = m_lpBuffer;
  114. for(;;)
  115. {
  116. if( i >= dwBytesRead )
  117. {
  118. fResult = ReadFile( m_hFile, lpInBuffer, BUFF_SIZE3,
  119. &dwBytesRead,
  120. NULL );
  121. if( fResult && dwBytesRead == 0 )
  122. {
  123. ret = false;
  124. goto _cleanup;
  125. }
  126. i = 0;
  127. }
  128. c = lpInBuffer[i++];
  129. if( '\r' == c )
  130. c = lpInBuffer[i++];
  131. if( '\n' == c )
  132. {
  133. if( lpBuf > m_lpBuffer && lpBuf[-1] == '\\' )
  134. {
  135. lpBuf--;
  136. continue;
  137. }
  138. break;
  139. }
  140. //if( lpBuf >= m_lpBuffer + BUFF_SIZE3 )
  141. if( (lpBuf - m_lpBuffer) >= BUFF_SIZE3 )
  142. {
  143. _TRACE(CDebugLevel::TRACE_DEBUGGING, "error: TERMCAP entry is way too big");
  144. dwBytesRead =0;
  145. i = 0;
  146. break;
  147. }
  148. else
  149. *lpBuf++ = (CHAR)c;
  150. }
  151. *lpBuf = 0;
  152. if( LookForTermName( lpszTermName ))
  153. {
  154. ret = true;
  155. goto _cleanup;
  156. }
  157. }
  158. _cleanup:
  159. delete [] lpInBuffer;
  160. return ( ret );
  161. }
  162. bool CTermCap::LookForTermName( LPSTR lpszTermName )
  163. {
  164. if( 0 == lpszTermName )
  165. return ( false );
  166. _chASSERT( m_lpBuffer != 0 );
  167. PCHAR lpName;
  168. PCHAR lpBuf = m_lpBuffer;
  169. if('#' == *lpBuf)
  170. return ( false );
  171. for(;;)
  172. {
  173. for( lpName = lpszTermName;
  174. *lpName && toupper( *lpBuf ) == toupper( *lpName );
  175. lpBuf++, lpName++ )
  176. {
  177. continue;
  178. }
  179. if(*lpName == 0 && (*lpBuf == '|' || *lpBuf == ':' || *lpBuf == 0))
  180. {
  181. return ( true );
  182. }
  183. while(*lpBuf && *lpBuf != ':' && *lpBuf != '|')
  184. {
  185. lpBuf++;
  186. }
  187. if(*lpBuf == 0 || *lpBuf == ':')
  188. {
  189. return ( false );
  190. }
  191. lpBuf++;
  192. }
  193. }
  194. #if 0
  195. WORD CTermCap::GetNumber( LPCSTR lpszCapabilityName )
  196. {
  197. if( 0 == lpszCapabilityName )
  198. return ( ( WORD ) -1 );
  199. _chASSERT( m_lpBuffer != 0 );
  200. PCHAR lpBuf = m_lpBuffer;
  201. for(;;)
  202. {
  203. lpBuf = SkipToNextField( lpBuf );
  204. if( NULL == lpBuf )
  205. return ( ( WORD ) -1 );
  206. if( *lpBuf++ != lpszCapabilityName[0] || *lpBuf == 0 ||
  207. *lpBuf++ != lpszCapabilityName[1])
  208. {
  209. continue;
  210. }
  211. if( *lpBuf != '#' )
  212. return ( ( WORD ) -1 );
  213. lpBuf++;
  214. WORD i = 0;
  215. while( isdigit( *lpBuf ))
  216. {
  217. i = i*10 + *lpBuf - '0';
  218. lpBuf++;
  219. }
  220. return ( i );
  221. }
  222. }
  223. #endif
  224. bool CTermCap::CheckFlag(LPCSTR lpszCapabilityName)
  225. {
  226. if( NULL == lpszCapabilityName )
  227. return ( false );
  228. // _chASSERT( m_lpBuffer != 0 );
  229. PCHAR lpBuf = m_lpBuffer;
  230. for(;lpBuf;)
  231. {
  232. lpBuf = SkipToNextField( lpBuf );
  233. if( !*lpBuf )
  234. {
  235. break;
  236. }
  237. if( *lpBuf++ == lpszCapabilityName[0] && *lpBuf != 0 &&
  238. *lpBuf++ == lpszCapabilityName[1] )
  239. {
  240. if(!*lpBuf || *lpBuf == ':')
  241. {
  242. return ( true );
  243. }
  244. else
  245. {
  246. break;
  247. }
  248. }
  249. }
  250. return false;
  251. }
  252. PCHAR CTermCap::SkipToNextField( PCHAR lpBuf )
  253. {
  254. if( NULL == lpBuf )
  255. return ( NULL );
  256. while( *lpBuf && *lpBuf != ':' )
  257. lpBuf++;
  258. if( *lpBuf == ':' )
  259. lpBuf++;
  260. return ( lpBuf );
  261. }
  262. LPSTR CTermCap::GetString( LPCSTR lpszCapabilityName )
  263. {
  264. if( NULL == lpszCapabilityName )
  265. return ( NULL );
  266. // _chASSERT( m_lpBuffer != 0 );
  267. PCHAR pBuf = m_lpBuffer;
  268. for(;pBuf;)
  269. {
  270. pBuf = SkipToNextField( pBuf );
  271. if( !*pBuf )
  272. return ( NULL );
  273. if( *pBuf++ != lpszCapabilityName[0] || *pBuf == 0 ||
  274. *pBuf++ != lpszCapabilityName[1] )
  275. {
  276. continue;
  277. }
  278. if( *pBuf != '=' )
  279. return ( NULL );
  280. pBuf++;
  281. return ( ParseString( pBuf ));
  282. }
  283. return ( NULL );
  284. }
  285. LPSTR CTermCap::ParseString( PCHAR pBuf )
  286. {
  287. if( NULL == pBuf )
  288. return ( NULL );
  289. LPSTR lpszStr = new CHAR[25];
  290. PCHAR p = lpszStr;
  291. WORD c;
  292. if( !lpszStr )
  293. {
  294. return ( NULL );
  295. }
  296. if( *pBuf != '^' )
  297. {
  298. for( c = *pBuf++; ( c && c != ':' ); c = *pBuf++)
  299. {
  300. *p++ = (CHAR)c;
  301. }
  302. }
  303. else
  304. {
  305. //Single control character.
  306. pBuf++;
  307. *p++ = *pBuf - '@' ;
  308. }
  309. *p++ = 0;
  310. return ( lpszStr );
  311. }
  312. // Notes: take care of other options, escapes, codes.
  313. //
  314. LPSTR CTermCap::CursorMove( LPSTR lpszCursMotionStr, WORD wHorPos,
  315. WORD wVertPos )
  316. {
  317. if( NULL == lpszCursMotionStr )
  318. return ( NULL );
  319. PCHAR pCms = lpszCursMotionStr;
  320. LPSTR lpszCmsResult = new CHAR[BUFF_SIZE1];
  321. PCHAR pCmsResult = lpszCmsResult;
  322. WORD c, wNum = 0;
  323. bool fIsColumn = false;
  324. WORD wPos = wHorPos;
  325. if( !lpszCmsResult )
  326. {
  327. return NULL;
  328. }
  329. for( c = *pCms++; c ; c = *pCms++ )
  330. {
  331. if( c != '%' )
  332. {
  333. *pCmsResult++ = (CHAR)c;
  334. continue;
  335. }
  336. switch( c = *pCms++ ) {
  337. case 'd':
  338. _itoa( wPos, pCmsResult, 10 );
  339. while( *pCmsResult != '\0' )
  340. {
  341. pCmsResult++;
  342. }
  343. fIsColumn = !fIsColumn;
  344. wPos = fIsColumn ? wVertPos : wHorPos;
  345. continue;
  346. break;
  347. case '+':
  348. /* %. output value as in printf %c
  349. * %+x add x to value, then do %. */
  350. wNum = ( wPos - 1 ) + *pCms++;
  351. sprintf( pCmsResult, "%c", wNum ); // NO BO here - BaskarK
  352. pCmsResult += strlen( pCmsResult );
  353. wPos = wVertPos;
  354. break;
  355. case 'i':
  356. //wHorPos++;
  357. //wVertPos++;
  358. continue;
  359. default:
  360. delete [] lpszCmsResult;
  361. return NULL;
  362. }
  363. }
  364. *pCmsResult = 0;
  365. return ( lpszCmsResult );
  366. }
  367. //this funtion is sort a of a kludge
  368. //if and when we decide to support
  369. //padding then we need to revisit this
  370. //piece of code.
  371. //we assume that the string sent in
  372. //conatins a padding number followed
  373. //by \E
  374. //it basically strips the padding
  375. //number in the string.
  376. //It also substitutes \033 for \E
  377. void CTermCap::ProcessString( LPSTR* lplpszStr )
  378. {
  379. LPSTR lpszStr = *lplpszStr;
  380. if(lpszStr == NULL)
  381. {
  382. return;
  383. }
  384. PCHAR pStr = new char[ strlen( lpszStr ) + 2 ];
  385. if( !pStr )
  386. {
  387. return;
  388. }
  389. strcpy( pStr, "\033" ); // NO BO - Baskar
  390. PCHAR pChar = lpszStr;
  391. //strip padding
  392. while( (*pChar != '\0') && isdigit( *pChar ) )
  393. {
  394. pChar++;
  395. }
  396. //strip \E
  397. if(*pChar != '\0' )
  398. {
  399. pChar++;
  400. if (*pChar != '\0' )
  401. pChar++;
  402. }
  403. strcat( pStr, pChar );
  404. delete [] lpszStr;
  405. *lplpszStr = pStr;
  406. }