tw_cli.c
上传用户:hujq123
上传日期:2016-04-10
资源大小:153k
文件大小:47k
源码类别:

Telnet服务器

开发平台:

Unix_Linux

  1. /* 
  2.  * Copyright (C) 2002 Koninklijke Philips Electronics N.V., 
  3.  * All Rights Reserved. 
  4.  *
  5.  * This source code and any compilation or derivative thereof is the 
  6.  * proprietary information of Koninklijke Philips Electronics N.V. 
  7.  * and is confidential in nature. 
  8.  * Under no circumstances is this software to be exposed to or placed 
  9.  * under an Open Source License of any type without the expressed 
  10.  * written permission of Koninklijke Philips Electronics N.V. 
  11.  * 
  12.  *###########################################################
  13.  */ 
  14. /*! 
  15.  *   file    tw_cli.c 
  16.  * 
  17.  *   brief   - 
  18.  * 
  19.  */ 
  20. /*-----------------------------------------------------------*
  21.  * 
  22.  *   %version:    6 % 
  23.  *   instance:    DS_6 
  24.  *   %date_created:  Fri Feb 21 08:04:49 2003 % 
  25.  *
  26.  *###########################################################
  27.  */ 
  28. /****************************************************************************
  29. *
  30. *
  31. * This module is writen to support 2 or more sessions.  Everything that is
  32. * specific to a session is stored in a Cli_cmdSession_t object.  There are two
  33. * such objects in sockSession[] array right now.
  34. *
  35. * To truely support multisession, the caller of these routines must provide
  36. * either 2 threads or some kind of nselect() services.
  37. *
  38. *
  39. *
  40. * CLI Style Guide
  41. * ---------------
  42. * All commands and options are all in lower case.
  43. *
  44. * In the help string, if there are optional parameters accompanying the
  45. * command, put the optional parameters within a braces "{}".  All lowercase
  46. * word means that user can type the exact same form.  Multiple
  47. * selections within the same field are seperated by "|".  All uppercase
  48. * word means that user needs to type an appropriate value for the field.
  49. *
  50. * Even though the CLI parser support multiple hierachy, try not to have more
  51. * than 3 levels deep.
  52. *
  53. * Philips history
  54. * who   When Why
  55. * KBL   6/14/99  And God set them in the firmament of the heavens to give 
  56. *    light upon the earth,  
  57. *
  58. *****************************************************************************/
  59. #include <stdio.h>
  60. #include <stdlib.h>
  61. #include <unistd.h>
  62. #include <stdarg.h>
  63. #include <string.h>
  64. #include <ctype.h>
  65. #include <inttypes.h>
  66. #include <tw_cli.h>
  67. /* All command structure objects adhere to following naming convention :
  68.  *
  69.  * If the object is at root, meaning that it's a command and not a option,
  70.  * start with "CliRco", otherwise start with "CliCo".
  71.  * Next comes the actual command+option in concatenated form, e.g. "show abc"
  72.  * will be "showAbc".
  73.  *
  74.  * All handler must start with "CliXXXProc_" (handler with no argument) or 
  75.  * "CliXXXVoproc" (handler with arguments - variations and options).  Help 
  76.  * function must start with "CliXXXHelp".  XXX is either Rco or Co, depends
  77.  * if the handler is attached to a root command or sub command.
  78.  *
  79.  * All root command objects must be included in the "Cli_AllRootCmdObjList"
  80.  * list in this file.  Definition of this object, as well as its child
  81.  * command objects and handlers must be placed in its own file.
  82.  */
  83. /* Root commands are application specific. */
  84. extern Cli_CmdStruct_t  *Cli_AllRootCmdObjList[];
  85. /*** STOP !  There is no need to venture below this line if ***
  86.  ***  all you need is to add a root command object.  ***/
  87. //#define   NUM_ALL_CMD_OBJ  (sizeof(Cli_AllRootCmdObjList) / sizeof(Cli_CmdStruct_t *))
  88. /* Foundation for support for multiple CLI session is here.  The following functions;
  89.  * Cli_Sock2sess(), Cli_NewSess(), and Cli_FreeSess() are initially implemented as
  90.  * macros and will only work for 2 sessions.
  91.  */
  92. #define    NUM_OF_CLI_ACCESS_SESSION  3
  93. static Cli_CmdStruct_t  Cli_WorkingRootCmdObj = 
  94. "@root",
  95. 0,
  96. Cli_AllRootCmdObjList,
  97. "--",
  98. NULL,
  99. NULL,
  100. NULL
  101. };
  102. static Cli_cmdSession_t  sockSession[NUM_OF_CLI_ACCESS_SESSION];
  103. /* Convert from socket and pointer to a Session, return pSess if successful,
  104.  * otherwise NULL.  Writen for 2 sessions only.
  105.  */
  106. #define  Cli_Sock2Sess(so)  ( (so) == sockSession[0].pSessFuns ?  
  107.   &(sockSession[0]) :   
  108.   ((so) == sockSession[1].pSessFuns ? &(sockSession[1]) : NULL) )
  109. /* Common size text string to be reused.
  110.  */
  111. char *badPasswordStr  = "nInvalid Password.n";
  112. char *endSessionStr   = "nCLI session terminated.n";
  113. char *noHelpStr   = "nNo help available.n";
  114. char *missingCmdStr   = "nMissing command options.n";
  115. char *invalidCmdStr   = "nInvalid command or options.n";
  116. char *cmdOptionsAreStr   = "nAvailable command options:n";
  117. char *noSuchHistoryStr   = "nNo such history.n";
  118. char *badParamStr = "Bad param.n";
  119. char *operationFailedStr = "Operation failed.n";
  120. char *waitForAKeyStr  = "<Pause>n";
  121. char *Cli_FailedStr   = "Failed!n";
  122. static const char init_msg[] = "nPress [ENTER] key to active this console...";
  123. static const char banner1[] =
  124. "n"
  125. "+---------------------------------------+n"
  126. "| Net camera configuration console v1.2 |n"
  127. "|         GuangZhou Seeland Inc. 2005.5 |n"
  128. "+---------------------------------------+n";
  129. /* Telnet session state to track user login progress
  130.  */
  131. enum 
  132. {
  133. CLI_ACCESS_CMD_NULL,
  134. CLI_ACCESS_CMD_INIT,
  135. CLI_ACCESS_CMD_PROMPT_USER,
  136. CLI_ACCESS_CMD_PROMPT_PASS,
  137. CLI_ACCESS_CMD_OPEN
  138. };
  139. /* Command mode occupies 3 characters near the start of prompt
  140.  */
  141. static char *modePrompt[] = { "   ", "USR", "OPR", "ENG", "BLO" };
  142. #define   MODE_PROMPT_SIZE 3
  143. /* Available hardcoded usernames.
  144.  */
  145. #define   CLI_LOGIN_USER "user"
  146. #define   CLI_USER_PASSWORD  "eureka"  
  147. #define   CLI_LOGIN_OPERATOR   "super"
  148. #define   CLI_OPERATOR_PASSWORD "slxj530"
  149. #define   CLI_LOGIN_ENG  "eng"
  150. #define   CLI_LOGIN_ENG2 "engineer"
  151. #define   CLI_ENG_PASSWORD   "sierra"
  152. #define   CLI_LOGIN_BLO  "blo"
  153. #define   CLI_BLO_PASSWORD   "whatsup1226"
  154. #define   Is_space(c)  ((c) == ' ')
  155. /* Forward declaration of local static functions
  156.  */
  157. static Cli_CmdStruct_t *Cli_SeekOptionMatch(Cli_CmdStruct_t *baseCmdObj, 
  158. char *thisCmd, 
  159. int thisCmdLen);
  160. static void Cli_UpdateCmdHistory(Cli_cmdSession_t *pSess, char *cmdBuf, int len);
  161. static int Cli_Cmdprocessing(Cli_cmdSession_t *pSess, 
  162.  Cli_CmdStruct_t *baseCmdObj, 
  163.  char *cmdStr, 
  164.  int cmdPtr, 
  165.  int recurLevel);
  166. static int Cli_BuildCmdObj(Cli_CmdStruct_t **rootList, 
  167.    Cli_CmdStruct_t **workingList, 
  168.    unsigned int flags);
  169. static int Cli_SetAccessMode(Cli_cmdSession_t *pSess, int mode);
  170. static int Cli_VerifyPassword(Cli_cmdSession_t *pSess, char *cmdBuf, int len);
  171. static int Cli_ParseCmd(Cli_cmdSession_t *pSess, char *cmdBuf, int len);
  172. int Cli_PrepareOpenSession (Cli_cmdSession_t *pSess);
  173. #ifdef SC_PSOS
  174. #include <tmlib/AppSem.h>
  175. static struct _AppSem_Semaphore cli_mutex  = _AppSem_INITIALISED_SEM; 
  176. #define LOCKSESSION() AppSem_P( &cli_mutex );
  177. #define UNLOCKSESSION() AppSem_V( &cli_mutex);
  178. #else
  179. #include <pthread.h>
  180. static pthread_mutex_t cli_mutex = PTHREAD_MUTEX_INITIALIZER;
  181. #define LOCKSESSION() pthread_mutex_lock( &cli_mutex );
  182. #define UNLOCKSESSION() pthread_mutex_unlock( &cli_mutex);
  183. #endif
  184. /***************************************************************************** 
  185. * int Cli_WriteBuf(Cli_cmdSession_t *pSess, char *str, int len)
  186. *
  187. * Description :
  188. *   This function print a text string "str" of length "len".  The text string
  189. *   is not necessary to be NULL terminated.  It is important to get the length
  190. *   right.
  191. *
  192. *   This is the basic function that does ALL the CLI text output.  Modify this
  193. *   function to support multiple session type.
  194. * Arguments :
  195. *   pSess - a pointer to a command session
  196. *   str - a character string
  197. *   len - length of the character string.
  198. *
  199. * Returns :
  200. *   0 - OK
  201. *   -1 - Failed
  202. *
  203. * History
  204. *   who   when why
  205. *   KBL   9/7/99   created
  206. *
  207. *****************************************************************************/
  208. static int Cli_WriteBuf(Cli_cmdSession_t *pSess, char *str, int len)
  209. {
  210. char cr_buf[] = "rn";
  211. int idx, PrintLen;   
  212. char  *pStrStart;
  213. if (pSess->skipPrinting)
  214. return 0;
  215. pStrStart = NULL;
  216. for (idx = 0 ; idx < len; idx++) {
  217. int cr;
  218. if (pStrStart == NULL)
  219. pStrStart = &(str[idx]);
  220. /* If it's carriage return, perform end-of-line conversion. */
  221. cr = (str[idx] == 'n');
  222. if (cr || (idx == (len - 1))) {
  223. PrintLen = &(str[idx]) - pStrStart + 1;
  224. PrintLen -= cr;
  225. pSess->pSessFuns->write(pStrStart, PrintLen);
  226. if (cr)
  227. pSess->pSessFuns->write(cr_buf, 2);
  228. pStrStart = NULL; 
  229. pSess->pSessFuns->yield();
  230. }
  231. }
  232. return 0;
  233. }
  234. /***************************************************************************** 
  235. * void Cli_InitDataSet()
  236. *
  237. * Description :
  238. * This function must be called once during system initialization for proper
  239. * operation of the command line mechanism.
  240. * Arguments :
  241. * None
  242. *
  243. * Returns :
  244. * None
  245. *
  246. * History
  247. * who   when why
  248. * KBL   7/7/99   created
  249. *
  250. *****************************************************************************/
  251. static void Cli_InitDataSet()
  252. {
  253. int i;
  254. for (i = 0; i < NUM_OF_CLI_ACCESS_SESSION; i++) 
  255. sockSession[i].pSessFuns = NULL;
  256. return;
  257. }
  258. static Cli_cmdSession_t *
  259. Cli_NewSess () {
  260. int i;
  261. Cli_cmdSession_t *p = NULL;
  262. LOCKSESSION()
  263. for (i = 0; i < NUM_OF_CLI_ACCESS_SESSION; i++) {
  264. if (!sockSession[i].pSessFuns) {
  265. sockSession[i].pSessFuns = (Cli_SessionFuns_t*) 1;
  266. p = &sockSession[i];
  267. break;
  268. }
  269. }
  270. UNLOCKSESSION()
  271. return p;
  272. }
  273. static int Cli_FreeSess (Cli_cmdSession_t *pSess) {
  274. if (pSess->pSessFuns->cleanup)
  275. pSess->pSessFuns->cleanup(pSess);
  276. return 0;
  277. }
  278. /***************************************************************************** 
  279. * int Cli_CloseCmdSession(Cli_cmdSession_t *pSess)
  280. *
  281. * Description :
  282. * This function must be called when a command session is terminated so that
  283. * the session object associated with the obsolete session is freed.
  284. * Arguments :
  285. * the pointer to the command session
  286. *
  287. * Returns :
  288. * 0 if OK, -1 if failed.
  289. *
  290. * History
  291. * who   when why
  292. * KBL   7/7/99   created
  293. *
  294. *****************************************************************************/
  295. static int Cli_CloseCmdSession(Cli_cmdSession_t *pSess)
  296. {
  297. LOCKSESSION()
  298. Cli_FreeSess(pSess);
  299. /* set pSessFuns to NULL to "free" it */
  300. pSess->pSessFuns = NULL;
  301. UNLOCKSESSION()
  302. return 0;
  303. }
  304. /***************************************************************************** 
  305. * Cli_cmdSession_t Cli_InitCmdSession(int nsock)
  306. *
  307. * Description :
  308. * This function must be called before a specific telnet command session can
  309. * be used.  It is typical called after a successful accept operation.
  310. * Arguments :
  311. *   nsock - socket number returned by accept() or other equipvalent procedure.
  312. *
  313. * Returns :
  314. *   NULL if failed
  315. *   pointer to a command session if OK
  316. *
  317. * History
  318. * who   when why
  319. * KBL   7/7/99   created
  320. *
  321. *****************************************************************************/
  322. static Cli_cmdSession_t *
  323. Cli_InitCmdSession(Cli_SessionFuns_t *pSessFuns)
  324. {
  325. // int  i;
  326. Cli_cmdSession_t  *pSess;
  327. if ((pSess = Cli_NewSess()) == NULL)
  328. /* No more session space.  This should not happen */
  329. return NULL;
  330. if (pSessFuns->init)
  331. pSessFuns->init();
  332. bzero(pSess, sizeof(Cli_cmdSession_t));
  333. pSess->pSessFuns = pSessFuns;
  334. pSess->cmdSessionType = pSessFuns->sessionType;
  335. pSess->cmdState = CLI_ACCESS_CMD_NULL;
  336. pSess->historyNextNumber = 1;
  337. pSess->currentCmdMode = CLI_ACCESS_NO_MODE;
  338. pSess->myProductType = CLI_ACCESS_PRODUCT_1;
  339. pSess->pageLength = CLI_DEFAULT_PAGE_LENGTH;
  340. Cli_WriteBuf(pSess, (char*) init_msg, strlen(init_msg));
  341. return pSess;
  342. }
  343. /*****************************************************************************
  344. * Jcon_CLI_Task - 
  345. *    
  346. *    Jcon DP buffer dump and command line monitor task.
  347. *   
  348. * Description:   
  349. *    Upon starting, console input is read and checked against command list.
  350. *    Most important command functionality is DP buffer dump which 
  351. *    is specified in terms of number of lines before the end of the buffer.
  352. *    'quit' command closes all psos tasks and exits. This is strictly a debug
  353. *    workaround until both tmdbg.exe and Philips telnet Cli work reliably.
  354. *   
  355. * History:
  356. *   10/12/99 BM  Added header and Jim's code.
  357. *
  358. *****************************************************************************/
  359. static void*
  360. Jcon_CLI_Task(void *arg)
  361. {
  362. char   myChar;
  363. int ret; 
  364. Cli_SessionFuns_t *pSessFuns = (Cli_SessionFuns_t*)arg;
  365. /* Go straight into CLI now */
  366. while (1) {
  367. /* Initialize this command session.  Any nsock number will do
  368.  * for JTAG connection.
  369.  */
  370. Cli_cmdSession_t *pCli_Session = NULL;
  371. pCli_Session =  Cli_InitCmdSession(pSessFuns);
  372. if (pCli_Session == NULL)  {
  373. pSessFuns->log("****Can't initialize CLI****.n");
  374. break;
  375. }
  376. do {
  377. ret = pCli_Session->pSessFuns->read_char();
  378. if ( ret < 0) {
  379. break;
  380. }
  381. if ( !ret )
  382. pSessFuns->yield();
  383. myChar = ret;
  384. /* If session is closed, open another one. */
  385. } while (Cli_ProcessCmd(&myChar, 1, pCli_Session) != -1);
  386. Cli_CloseCmdSession(pCli_Session);
  387. }
  388. return NULL;
  389. }
  390. /************************************************************************
  391. *
  392. * Cli_Initialize - Initialize CLI for a JCON session.
  393. *
  394. * Returns:
  395. *   int - 0 if no error, nonzero otherwise.
  396. *
  397. * Description:
  398. *   Send an echo request to a host. Each TCP/IP stack seems to have 
  399. *   their own favorite API for this so we combine them here.
  400. *
  401. * Notes:
  402. *   None
  403. *
  404. * History:
  405. *   10/25/01 FD  Created.
  406. *
  407. ************************************************************************/
  408. int Cli_Initialize(Cli_SessionFuns_t *pSessFuns)
  409. {
  410. static char bInit = 1;
  411. unsigned long RetVal;
  412. /* Initialize CLI data set */
  413. if( bInit ) {
  414. bInit = 0;
  415. Cli_InitDataSet ();
  416. }
  417. /* Start JCON task now so we have CLI even if boot count suspends root */
  418. RetVal = pSessFuns->create_task("jcli", Jcon_CLI_Task, 0, 8192, (void*)pSessFuns);
  419. if (RetVal != 0)
  420. pSessFuns->log("ERROR: Jcon_CLI_Task(jcli) failed! status = %dn", RetVal);
  421. return (int) RetVal;
  422. }
  423. /***************************************************************************** 
  424. * void Cli_IncrementRowCounter(Cli_cmdSession_t *pSess)
  425. * void Cli_ResetRowCounter(Cli_cmdSession_t *pSess)
  426. * void Cli_DisableScrollPause(Cli_cmdSession_t *pSess)
  427. * void Cli_EnableScrollPause(Cli_cmdSession_t *pSess)
  428. * int Cli_SetPageLength(Cli_cmdSession_t *pSess, int NewPageLen)
  429. * int Cli_GetScrollPauseStatus(Cli_cmdSession_t *pSess, int *PageLen)
  430. *
  431. * Description :
  432. *   These functions control the pausing of scrolling.  
  433. * Arguments :
  434. *   pSess - the pointer to the command session
  435. *
  436. * Returns :
  437. *   0 if OK, -1 if failed.
  438. *
  439. * History
  440. *   who   when why
  441. *   KBL   7/7/99   created
  442. *
  443. *****************************************************************************/
  444. static void Cli_IncrementRowCounter(Cli_cmdSession_t *pSess)
  445. {
  446. pSess->currentRow++;
  447. }
  448. static void Cli_ResetRowCounter(Cli_cmdSession_t *pSess)
  449. {
  450. pSess->currentRow = 0;
  451. }
  452. void Cli_DisableScrollPause(Cli_cmdSession_t *pSess)
  453. {
  454. pSess->scrollPause = 0;
  455. }
  456. void Cli_EnableScrollPause(Cli_cmdSession_t *pSess)
  457. {
  458. pSess->scrollPause = 1;
  459. }
  460. int Cli_SetPageLength(Cli_cmdSession_t *pSess, int NewPageLen)
  461. {
  462. int OldLen;
  463. /* Keep a lower bound for page length. */
  464. if (NewPageLen < CLI_MINIMAL_PAGE_LENGTH) 
  465. {
  466. NewPageLen = CLI_MINIMAL_PAGE_LENGTH;
  467. }
  468. OldLen = pSess->pageLength;
  469. pSess->pageLength = NewPageLen;
  470. return 0;
  471. }
  472. int Cli_GetScrollPauseStatus(Cli_cmdSession_t *pSess, int *PageLen)
  473. {
  474. if (PageLen) 
  475. {
  476. *PageLen = pSess->pageLength;
  477. }
  478. return (pSess->scrollPause);
  479. }
  480. /***************************************************************************** 
  481. * int Cli_Prompt(Cli_cmdSession_t *pSess, int PromptStrOffset)
  482. *
  483. * Description :
  484. * This function prints the prompt with the proper history number embedded.
  485. * Arguments :
  486. * the pointer to the command session, and offset into the text string 
  487. * "prompt".  The offset thing is a cheap way to print either one or two
  488. * newlines.  The offset should never be larger than 2.
  489. *
  490. * Returns :
  491. * 0 if OK, -1 if failed.
  492. *
  493. * History
  494. * who   when why
  495. * KBL   7/7/99   created
  496. *
  497. *****************************************************************************/
  498. int Cli_Prompt(Cli_cmdSession_t *pSess, int PromptStrOffset)
  499. {
  500. /* Scrolling control can never span commands.  Therefore everytime we
  501.  * need to print the prompt, we reset row counter.
  502.  */
  503. Cli_ResetRowCounter(pSess);
  504. pSess->skipPrinting = 0;
  505. if (PromptStrOffset != 0)
  506. {
  507. Cli_Printf(pSess, "n") ;
  508. }
  509. return (Cli_Printf(pSess, "%s%d>", pSess->prompt, pSess->historyNextNumber));
  510. }
  511. /***************************************************************************** 
  512. * int Cli_ProcessCmd(char *msgbuf, int len, Cli_cmdSession_t *pSess)
  513. *
  514. * Description :
  515. * This function is called to pass in a message buffer from user input.  It
  516. * performs all the functionalities for proper command line interface including
  517. * user login, password validation, CR detection and subsequent command
  518. * processing, '?' character detectin and subsequent help processing and so
  519. * forth.
  520. *
  521. * Special notice : a char string containing the command is ALWAYS NULL
  522. *   terminated.  The length field is also passed in for
  523. *   convineance.
  524. * Arguments :
  525. * pointer to message buffer (msgbuf), its length (len) and pointer to session.
  526. *
  527. * Returns :
  528. * 0 if OK, -1 if bad.  A return of -1 must trigger a shutdown of this
  529. * socket.
  530. *
  531. * History
  532. * who   when why
  533. * KBL   7/7/99   created
  534. *
  535. *****************************************************************************/
  536. int Cli_ProcessCmd(char *msgbuf, int len, Cli_cmdSession_t *pSess)
  537. {
  538. int i, j, promptStrOffset;
  539. for (i = 0; i < len; i++) 
  540. {
  541. if (msgbuf[i] == 0x0A) 
  542. {
  543. /* ignore line feed (0x0A), Return (0x0D) is what we are looking for.  We
  544.  * will regenerate the combo LF/CR later.
  545.  */
  546. continue;
  547. }
  548. if (msgbuf[i] == 0x0D)
  549. {
  550. /* We can now process the CR/LF */
  551. switch (pSess->cmdState) 
  552. {
  553. case CLI_ACCESS_CMD_NULL:
  554. /* Add any special pre-loggin processing code here.  Otherwise
  555.  * it just go straight to getting user login.
  556.  */
  557. if (pSess->cmdSessionType == CLI_SERIAL_SESSION)
  558. {
  559. memcpy(pSess->myUserName, CLI_LOGIN_OPERATOR, strlen(CLI_LOGIN_OPERATOR));
  560. Cli_VerifyPassword(pSess, CLI_OPERATOR_PASSWORD, strlen(CLI_OPERATOR_PASSWORD));
  561. Cli_PrepareOpenSession(pSess);
  562. pSess->cmdState = CLI_ACCESS_CMD_OPEN;
  563. }
  564. else
  565. {
  566. pSess->cmdState = CLI_ACCESS_CMD_INIT;
  567. }
  568. break;
  569. case CLI_ACCESS_CMD_INIT:
  570. if (pSess->cmdBufIdx == 0) {
  571. /* user keep hitting Return */
  572. if (Cli_Printf((Cli_cmdSession_t*)pSess, "nusername:"))
  573. {
  574. return -1;
  575. }
  576. pSess->cmdState = CLI_ACCESS_CMD_PROMPT_USER;
  577. }
  578. break;
  579. case CLI_ACCESS_CMD_PROMPT_USER:
  580. /* Make sure the string is NULL terminated */
  581. pSess->cmdBuf[pSess->cmdBufIdx] = 0;
  582. if ( (pSess->cmdBufIdx == 0) || (pSess->cmdBufIdx > MAX_USERPASS_LEN) )
  583. {
  584. /* Damn user hit Return again */
  585. if (Cli_Printf((Cli_cmdSession_t*)pSess, "nusername:"))
  586. {
  587. return -1;
  588. }
  589. }
  590. else
  591. {  
  592. /* got username */
  593. memcpy(pSess->myUserName, pSess->cmdBuf, pSess->cmdBufIdx);
  594. Cli_SendCrLf(pSess);
  595. pSess->myUserName[pSess->cmdBufIdx] = 0;
  596. if (Cli_Printf((Cli_cmdSession_t *)pSess, "password:"))
  597. {
  598. return -1;
  599. }
  600. pSess->cmdState = CLI_ACCESS_CMD_PROMPT_PASS;
  601. }
  602. break;
  603. case CLI_ACCESS_CMD_PROMPT_PASS:
  604. /* Make sure the string is NULL terminated */
  605. pSess->cmdBuf[pSess->cmdBufIdx] = 0;
  606. Cli_SendCrLf(pSess);
  607. if ((pSess->cmdBufIdx > MAX_USERPASS_LEN) || 
  608. Cli_VerifyPassword(pSess, pSess->cmdBuf, pSess->cmdBufIdx) == -1)
  609. {
  610. if (Cli_Printf(pSess, badPasswordStr) < 0)
  611. {
  612. return -1;
  613. }
  614. pSess->cmdState = CLI_ACCESS_CMD_INIT;
  615. pSess->loginFailedCount++;
  616. /* Kick this user off if he/she keeps failing */
  617. if (pSess->loginFailedCount > MAX_LOGIN_FAILURE) 
  618. {
  619. return -1;
  620. }
  621. }
  622. else
  623. {
  624. pSess->cmdState = CLI_ACCESS_CMD_OPEN;
  625. if (Cli_PrepareOpenSession(pSess) != 0)
  626. {
  627. return -1;
  628. }
  629. }
  630. break;
  631. case CLI_ACCESS_CMD_OPEN:
  632. /* Make sure the string is NULL terminated */
  633. pSess->cmdBuf[pSess->cmdBufIdx] = 0;
  634. /* If user just hit CR then cmdBufIdx is 0.  In this case we don't
  635.  * print 2 LF.  Otherwise 2 LF is used.
  636.  */
  637. if(pSess->cmdBufIdx == 0)
  638. promptStrOffset = 1 ;
  639. else
  640. promptStrOffset = 0;
  641. /* copy the last command into history buffer as well; note that even
  642.  * bogus commands are copied.  Anything ended with a CR is a command.
  643.  */
  644. Cli_UpdateCmdHistory(pSess, pSess->cmdBuf, pSess->cmdBufIdx);
  645. if (Cli_ParseCmd(pSess, pSess->cmdBuf, pSess->cmdBufIdx) == -1)
  646. {
  647. Cli_Printf(pSess, endSessionStr);
  648. return -1;
  649. }
  650. if (Cli_Prompt(pSess, promptStrOffset) < 0)
  651. {
  652. return -1;
  653. }
  654. break;
  655. }
  656. /* Done processing last command, reset index */
  657. pSess->cmdBufIdx = 0;
  658. }
  659.    
  660. else if ((msgbuf[i] == 't') &&
  661.  (pSess->cmdState == CLI_ACCESS_CMD_OPEN))
  662. {
  663. pSess->cmdBuf[pSess->cmdBufIdx] = 't';
  664. pSess->cmdBufIdx++;
  665. pSess->cmdBuf[pSess->cmdBufIdx] = 0;
  666. if (Cli_Printf(pSess, "?") < 0) 
  667. {
  668. return -1;
  669. }
  670. Cli_UpdateCmdHistory(pSess, pSess->cmdBuf, pSess->cmdBufIdx);
  671. if ((j = Cli_ParseCmd(pSess, pSess->cmdBuf, pSess->cmdBufIdx)) == -1)
  672. {
  673. Cli_Printf(pSess, endSessionStr);
  674. return -1;
  675. }
  676. if (Cli_Prompt(pSess, 0) < 0)
  677. {
  678. return -1;
  679. }
  680. if (j != -2) 
  681. {
  682. /* now back out the '?' and print what user type */
  683. pSess->cmdBufIdx--;
  684. pSess->cmdBuf[pSess->cmdBufIdx] = 0;
  685. if (Cli_Printf(pSess, pSess->cmdBuf) < 0) 
  686. {
  687. return -1;
  688. }
  689. }
  690. else
  691. {
  692. /* try to get help on bogus command, reset command buffer */
  693. pSess->cmdBufIdx = 0;
  694. }
  695. }
  696. else
  697. {
  698. if (msgbuf[i] == 'b') 
  699. {
  700. /* If it's backspace, back cmdBufIdx up */
  701. if (pSess->cmdBufIdx > 0)
  702. {
  703. pSess->cmdBufIdx--;
  704. if (Cli_Printf(pSess, "b ") < 0)
  705. {
  706. return -1;
  707. }
  708. }
  709. else
  710. continue;
  711. }
  712. else
  713. {
  714. if ( pSess->cmdBufIdx >= (CLI_ACCESS_CMDSTR_SIZE - 2) ) 
  715. {
  716. if (pSess->cmdState == CLI_ACCESS_CMD_NULL)
  717. {
  718. pSess->cmdBufIdx = 0;
  719. }
  720. else
  721. {
  722. /* User has typed too much without hitting return or ?. 
  723.  * Don't copy into command buffer and don't echo it back.
  724.  */
  725. continue;
  726. }
  727. pSess->cmdBuf[pSess->cmdBufIdx] = msgbuf[i];
  728. pSess->cmdBufIdx++;
  729. }
  730. if ((pSess->cmdState != CLI_ACCESS_CMD_INIT) &&
  731. (pSess->cmdState != CLI_ACCESS_CMD_PROMPT_PASS))
  732. {
  733. if (Cli_PutChar(pSess, (msgbuf[i])) < 0)
  734. {
  735. return -1;
  736. }
  737. }
  738. }
  739. }
  740. return 0;
  741. }
  742. /*****************************************************************************
  743. * Cli_PrepareOpenSession - Displays session banner and initializes mode
  744. *
  745. * Returns:
  746. *   int - 0 on success, -1 on failure.
  747. *
  748. * Description:
  749. *   Called to prepare for entering session Open state after authenticating the
  750. *   user.
  751. *
  752. * History:
  753. *   12/19/99 MA  Original version
  754. *
  755. *****************************************************************************/
  756. int Cli_PrepareOpenSession (Cli_cmdSession_t *pSess)
  757. {
  758. int j;
  759. /* Print Philips logo */
  760. if (Cli_Printf(pSess,(char*) banner1) < 0)
  761. return -1;
  762. /* By default turn on scroll control. */
  763. Cli_EnableScrollPause(pSess);
  764. Cli_Printf(pSess, "Screen length is set to %d by default"
  765.   ", paging is enabled.n",
  766.    pSess->pageLength);
  767. if (Cli_Prompt(pSess, 0) < 0)
  768. {
  769. return -1;
  770. }
  771. return 0;
  772. }
  773. /***************************************************************************** 
  774. * static Cli_CmdStruct_t *Cli_SeekOptionMatch(Cli_CmdStruct_t *baseCmdObj, 
  775. *  char *thisCmd, 
  776. *  int thisCmdLen)
  777. *
  778. * Description :
  779. * This function scans the optionList of the supplied Cli_CmdStruct_t object to
  780. * find a match for the currently processed command/option.
  781. * Arguments :
  782. * pointer to the base Cli_CmdStruct_t object (baseCmdObj), currently processed 
  783. * command (thisCmd) and its length (thisCmdLen).
  784. *
  785. * Returns :
  786. * If a Cli_CmdStruct_t object is in optionList[] matches, it's pointer is
  787. * returned.  If no match, NULL is return.
  788. *
  789. * History
  790. * who   when why
  791. * KBL   7/7/99   created
  792. *
  793. *****************************************************************************/
  794. static Cli_CmdStruct_t *Cli_SeekOptionMatch(Cli_CmdStruct_t *baseCmdObj, 
  795. char *thisCmd, 
  796. int thisCmdLen)
  797. {
  798. int i;
  799. if (baseCmdObj->optionList == NULL) 
  800. {
  801. return NULL;
  802. }
  803. i = 0;
  804. while (baseCmdObj->optionList[i] != NULL)
  805. {
  806. if ( (strlen(baseCmdObj->optionList[i]->name) == (unsigned int) thisCmdLen) &&
  807.  !memcmp(baseCmdObj->optionList[i]->name, thisCmd, thisCmdLen)) 
  808. {
  809. return baseCmdObj->optionList[i];
  810. }
  811. i++;
  812. }
  813. return NULL;
  814. }
  815. /***************************************************************************** 
  816. * static int Cli_Cmdprocessing(Cli_cmdSession_t *pSess, 
  817. *   Cli_CmdStruct_t *baseCmdObj, 
  818. *   char *cmdStr, 
  819. *   int cmdPtr, 
  820. *   int recurLevel)
  821. *
  822. * Description :
  823. * This RECURSIVE function performs all help and command processing function.
  824. * To safeguard deep recursion, a maximum depth of 4 calls is enforced.
  825. * Arguments :
  826. * see it for yourself.
  827. *
  828. * Returns :
  829. * 0 if OK, -1 if failed.
  830. *
  831. * History
  832. * who   when why
  833. * KBL   7/7/99   created
  834. *
  835. *****************************************************************************/
  836. static int Cli_Cmdprocessing(Cli_cmdSession_t *pSess, 
  837.  Cli_CmdStruct_t *baseCmdObj, 
  838.  char *cmdStr, 
  839.  int cmdPtr, 
  840.  int recurLevel)
  841. {
  842. char  *thisCmd;
  843. int   i, thisCmdLen, oldCmdPtr;
  844. Cli_CmdStruct_t  *thisCmdObj;
  845. unsigned int  myAccessFlags;
  846. myAccessFlags = TO_ACCESS_FLAG(pSess->currentCmdMode) | 
  847. TO_ACCESS_FLAG(pSess->myProductType);
  848. if (recurLevel > 4) 
  849. {
  850. return 0;
  851. }
  852. recurLevel++;
  853. oldCmdPtr = cmdPtr;
  854. /* Find out the current command option and size */
  855. thisCmd = cmdStr + cmdPtr;
  856. thisCmdLen = 0;
  857. for (i = cmdPtr; i < CLI_ACCESS_CMDSTR_SIZE; i++) 
  858. {
  859. if (Is_space(cmdStr[i]) || cmdStr[i] == 0)
  860. {
  861. thisCmdLen = i - cmdPtr;
  862. break;
  863. }
  864. }
  865. if (thisCmdLen <= 0)
  866. {
  867. /* no command or option at all, return */
  868. return 0;
  869. }
  870. /* Have cmdPtr indexes the start of next options, or end of string */
  871. for (i = cmdPtr + thisCmdLen; i < CLI_ACCESS_CMDSTR_SIZE; i++)
  872. {
  873. if (!Is_space(cmdStr[i]) || cmdStr[i] == 0) 
  874. {
  875. cmdPtr = i;
  876. break;
  877. }
  878. }
  879. /* Perform Help processing */
  880. if (thisCmd[0] == 't') 
  881. {
  882. i = 0;
  883. if (baseCmdObj->optionList == NULL) {
  884. /* Without a optionList pointer, this is a leaf node.  There isn't
  885.  * any other subcommands after this.
  886.  */
  887. if (baseCmdObj->helpStr != NULL) 
  888. {
  889. Cli_SendCrLf(pSess);
  890. if (Cli_Printf(pSess, baseCmdObj->helpStr) < 0)
  891. {
  892. return -1;
  893. }
  894. Cli_SendCrLf(pSess);
  895. }
  896. else if (Cli_Printf(pSess, noHelpStr) < 0)
  897. {
  898. return -1;
  899. }
  900. } else {
  901. int PrintVerbage = 1;
  902. /* print out all available root level commands */
  903. while (baseCmdObj->optionList[i] != NULL) 
  904. {
  905. if ((baseCmdObj->optionList[i]->accessFlag & myAccessFlags) == myAccessFlags)
  906. {
  907. if (PrintVerbage)
  908. {
  909. if (Cli_Printf(pSess, cmdOptionsAreStr) < 0)
  910. {
  911. return -1;
  912. }
  913. PrintVerbage = 0;
  914. }
  915.  
  916. if (Cli_Printf(pSess, "   %-16s ", baseCmdObj->optionList[i]->name) < 0) 
  917. {
  918. return -1;
  919. }
  920. if (Cli_Printf(pSess, "%sn", baseCmdObj->optionList[i]->helpStr) < 0) 
  921. {
  922. return -1;
  923. }
  924. }
  925. i++;
  926. }
  927. }
  928. /* call additional help function if available */
  929. if (baseCmdObj->helpFunc != NULL) 
  930. return baseCmdObj->helpFunc(pSess, cmdStr, cmdPtr);
  931. }
  932. /* Perform command processing */
  933. else
  934. {
  935. /* Look for the Cli_CmdStruct_t object which represents the command
  936.  * option currently under processing.
  937.  */
  938. thisCmdObj = Cli_SeekOptionMatch(baseCmdObj, thisCmd, thisCmdLen);
  939. if (thisCmdObj != NULL)
  940. {
  941. if ((cmdStr[cmdPtr] == 0) )
  942. {
  943. /* no more command options, or no optionList[], 
  944.  * must execute handler.
  945.  */
  946. if ((thisCmdObj->procFunc != NULL) &&
  947. ((thisCmdObj->accessFlag & myAccessFlags) == myAccessFlags))
  948. {
  949. if (Cli_Printf(pSess, "n") < 0)
  950. {
  951. return -1 ;
  952. }
  953. return thisCmdObj->procFunc(pSess, cmdStr, cmdPtr);
  954. }
  955. else
  956. {
  957. if (Cli_Printf(pSess, invalidCmdStr) < 0)
  958. {
  959. return -1;
  960. }
  961. return 0;
  962. }
  963. }
  964. else
  965. {
  966. /* user has typed in some option, run Cli_Cmdprocessing() again.
  967.  */
  968. return Cli_Cmdprocessing(pSess, thisCmdObj, cmdStr, cmdPtr, recurLevel);
  969. }
  970. }
  971. else
  972. {
  973. /* No match in optionList[].  There can be 2 reasons.
  974.  * 1) user type in a bogus option.
  975.  * 2) user type in a variable option.
  976.  *
  977.  * It is assumed that next higher (caller) cmdObj that supports
  978.  * variable option will have a varOptFunc().  If no such handler
  979.  * is defined, caller will determine that option is bogus.
  980.  */
  981. if ((baseCmdObj->varOptFunc != NULL) &&
  982. ((baseCmdObj->accessFlag & myAccessFlags) == myAccessFlags))
  983. {
  984. if (Cli_Printf(pSess, "n") < 0)
  985. {
  986. return -1 ;
  987. }
  988. return baseCmdObj->varOptFunc(pSess, cmdStr, oldCmdPtr); //zouyx add
  989. }
  990. else
  991. {
  992. if (Cli_Printf(pSess, invalidCmdStr) < 0)
  993. {
  994. return -1;
  995. }
  996. }
  997. return 0;
  998. }
  999. }
  1000. return 0;
  1001. }
  1002. /***************************************************************************** 
  1003. * static int Cli_BuildCmdObj(Cli_CmdStruct_t **rootList, 
  1004. * Cli_CmdStruct_t **workingList, 
  1005. * unsigned int accessflags)
  1006. *
  1007. * Description :
  1008. * This function is called to construct a working root command list based on
  1009. * the supplied accessFlags.
  1010. * Arguments :
  1011. * the root list (typical a list of all command), working list and the
  1012. * access flags.
  1013. *
  1014. * Returns :
  1015. * Always returns 0.
  1016. *
  1017. * History
  1018. * who   when why
  1019. * KBL   7/7/99   created
  1020. *
  1021. *****************************************************************************/
  1022. static int Cli_BuildCmdObj(Cli_CmdStruct_t **rootList, 
  1023.    Cli_CmdStruct_t **workingList, 
  1024.    unsigned int accessflags)
  1025. {
  1026. int i, j;
  1027. i = j = 0;
  1028. while(rootList[i] != NULL)
  1029. {
  1030. if (rootList[i]->accessFlag & accessflags)
  1031. {
  1032. workingList[j]=rootList[i];
  1033. j++;
  1034. }
  1035. i++;
  1036. }
  1037. return 0;
  1038. }
  1039. /***************************************************************************** 
  1040. * static int Cli_SetAccessMode(Cli_cmdSession_t *pSess, int mode)
  1041. *
  1042. * Description :
  1043. * This function must be called when user first login and enter/exit to
  1044. * different access level (e.g. go from operator to admin).  Based on
  1045. * current access mode, user access right and product type, a working list
  1046. * of commands is constructed.
  1047. * Arguments :
  1048. * pointer to a session, plus access mode.
  1049. *
  1050. * Returns :
  1051. * Always returns 0.
  1052. *
  1053. * History
  1054. * who   when why
  1055. * KBL   7/7/99   created
  1056. *
  1057. *****************************************************************************/
  1058. static int Cli_SetAccessMode(Cli_cmdSession_t *pSess, int accessLevel)
  1059. {
  1060. // unsigned flags;
  1061. pSess->currentCmdMode = accessLevel;
  1062. sprintf(pSess->prompt, "[%s]", modePrompt[accessLevel]);
  1063. return 0;
  1064. }
  1065. /***************************************************************************** 
  1066. * static int Cli_VerifyPassword(Cli_cmdSession_t *pSess, char *password, int len)
  1067. *
  1068. * Description :
  1069. * This function verifies password against the current user of this session.
  1070. * More sophisticated method of verification should be used in the future.
  1071. * Arguments :
  1072. * password string plus it's length.
  1073. *
  1074. * Returns :
  1075. * 0 if verified OK, -1 if failed.
  1076. *
  1077. * History
  1078. * who   when why
  1079. * KBL   7/7/99   created
  1080. *
  1081. *****************************************************************************/
  1082. static int Cli_VerifyPassword(Cli_cmdSession_t *pSess, char *password, int len)
  1083. {
  1084. /* These are the four level of access to CLI.  To make thing easy, it maps
  1085.  * to 4 unique username.  For example, if you log in as "Eng", you 
  1086.  * automatically have ENG level of access.
  1087.  */
  1088. char UserPassword[] = CLI_USER_PASSWORD;
  1089. char OperPassword[] = CLI_OPERATOR_PASSWORD;
  1090. char EngPassword[]  = CLI_ENG_PASSWORD;
  1091. char BloPassword[]  = CLI_BLO_PASSWORD;
  1092. int  AccessLevel;
  1093. char *DiffPassword;
  1094. if (!memcmp(pSess->myUserName, CLI_LOGIN_USER, strlen(CLI_LOGIN_USER)))
  1095. {
  1096. AccessLevel = CLI_ACCESS_USER_MODE;
  1097. DiffPassword = UserPassword;
  1098. }
  1099. else if (!memcmp(pSess->myUserName, CLI_LOGIN_OPERATOR, strlen(CLI_LOGIN_OPERATOR)))
  1100. {
  1101. AccessLevel = CLI_ACCESS_TECH_MODE;   /* operator = technican in my book */
  1102. DiffPassword = OperPassword;
  1103. }
  1104. else if ( (!memcmp(pSess->myUserName, CLI_LOGIN_ENG, strlen(CLI_LOGIN_ENG))) ||
  1105.   (!memcmp(pSess->myUserName, CLI_LOGIN_ENG2, strlen(CLI_LOGIN_ENG2))) )
  1106. {
  1107. AccessLevel = CLI_ACCESS_ENG_MODE;
  1108. DiffPassword = EngPassword;
  1109. }
  1110. else if (!memcmp(pSess->myUserName, CLI_LOGIN_BLO, strlen(CLI_LOGIN_BLO)))
  1111. {
  1112. AccessLevel = CLI_ACCESS_BLO_MODE;
  1113. DiffPassword = BloPassword;
  1114. }
  1115. else
  1116. {
  1117. /* Unknown user ! */
  1118. return -1;
  1119. }
  1120. if ( (( unsigned int) len == (strlen(DiffPassword))) && 
  1121.  (!memcmp(password, DiffPassword, strlen(DiffPassword))) )
  1122. {
  1123. Cli_SetAccessMode(pSess, AccessLevel);
  1124. return 0;
  1125. }
  1126. return -1;
  1127. }
  1128. /***************************************************************************** 
  1129. * static int Cli_ParseCmd(Cli_cmdSession_t *pSess, char *cmdBuf, int len)
  1130. *
  1131. * Description :
  1132. * This function is called when the session is in OPEN state (user successfully
  1133. * logged in) and a command has been entered (CR has been hit).  History (!...)
  1134. * processing is also performed here.
  1135. * Arguments :
  1136. * Go take a look.
  1137. *
  1138. * Returns :
  1139. * 0 if OK, -1 if bad thing happened and the socket and session must be 
  1140. * terminated.
  1141. *
  1142. * History
  1143. * who   when why
  1144. * KBL   7/7/99   created
  1145. *
  1146. *****************************************************************************/
  1147. static int Cli_ParseCmd(Cli_cmdSession_t *pSess, char *cmdBuf, int len)
  1148. {
  1149. int hptr;
  1150. if (len)
  1151. {
  1152. if (cmdBuf[0] == '!') 
  1153. {
  1154. /* History processing */
  1155. Cli_SendCrLf(pSess);
  1156. if ((len == 2) && cmdBuf[1] == '!') 
  1157. {
  1158. hptr = (pSess->historyPtr + CLI_ACCESS_HISTORY_DEPTH - 1 )% CLI_ACCESS_HISTORY_DEPTH;
  1159. if (Cli_Printf(pSess, pSess->historyBuf[hptr]) < 0)
  1160. {
  1161. return -1;
  1162. }
  1163. }
  1164. else
  1165. {
  1166. int histNum;
  1167. /* Handle case of !XYZ where XYZ is the command history number */
  1168. if (sscanf(cmdBuf+1, "%d", &histNum) == 0)
  1169. {
  1170. if (Cli_Printf(pSess, invalidCmdStr) < 0)
  1171. {
  1172. return -1;
  1173. }
  1174. return 0;
  1175. }
  1176. else
  1177. {
  1178. for (hptr = 0; hptr < CLI_ACCESS_HISTORY_DEPTH; hptr++) 
  1179. {
  1180. if(pSess->historyNum[hptr] == histNum)
  1181. break;
  1182. }
  1183. /* Return if no such history is found */
  1184. if (hptr >= CLI_ACCESS_HISTORY_DEPTH) 
  1185. {
  1186. if (Cli_Printf(pSess, noSuchHistoryStr) < 0)
  1187. {
  1188. return -1;
  1189. }
  1190. return 0;
  1191. }
  1192. /* Print out the historical command */
  1193. if (Cli_Printf(pSess, pSess->historyBuf[hptr]) < 0)
  1194. {
  1195. return -1;
  1196. }
  1197. }
  1198. }
  1199. /* Record history and process the command as if user just type in the
  1200.  * same command rather than !XYZ
  1201.  */
  1202. Cli_UpdateCmdHistory(pSess, pSess->historyBuf[hptr], strlen(pSess->historyBuf[hptr]));
  1203. return Cli_Cmdprocessing(pSess, &Cli_WorkingRootCmdObj, pSess->historyBuf[hptr], 0, 0);
  1204. }
  1205. else
  1206. {
  1207. /* Command processing */
  1208. return Cli_Cmdprocessing(pSess, &Cli_WorkingRootCmdObj, cmdBuf, 0, 0);
  1209. }
  1210. }
  1211. return 0;
  1212. }
  1213. /***************************************************************************** 
  1214. * static void Cli_UpdateCmdHistory(Cli_cmdSession_t *pSess, 
  1215. *   char *cmdBuf, int len)
  1216. *
  1217. * Description :
  1218. * This function updates the last command into our ring buffer type command
  1219. * history buffer.
  1220. * Arguments :
  1221. * the session, the command string and its length.
  1222. *
  1223. * Returns :
  1224. * None.
  1225. *
  1226. * History
  1227. * who   when why
  1228. * KBL   7/7/99   created
  1229. *
  1230. *****************************************************************************/
  1231. static void Cli_UpdateCmdHistory(Cli_cmdSession_t *pSess, char *cmdBuf, int len)
  1232. {
  1233. if (cmdBuf[0] == '!')
  1234. {
  1235. /* We don't record history commands */
  1236. return;
  1237. }
  1238. /* Copy the command into an entry in historyBuf[] and null terminated it */
  1239. memcpy(pSess->historyBuf[pSess->historyPtr], cmdBuf, len);
  1240. pSess->historyBuf[pSess->historyPtr][len] = 0;
  1241. pSess->historyNum[pSess->historyPtr] = pSess->historyNextNumber;
  1242. pSess->historyPtr = (pSess->historyPtr + 1) % CLI_ACCESS_HISTORY_DEPTH;
  1243. pSess->historyNextNumber++;
  1244. return;
  1245. }
  1246. /***************************************************************************** 
  1247. * int Cli_GetChar(Cli_cmdSession_t *pSess)
  1248. *
  1249. * Description :
  1250. *   This function blocks until a character is received unless the connection
  1251. *   is discontinued.
  1252. *
  1253. *   This is the basic function that does ALL the in-context CLI text input.
  1254. *   An in-context CLI text input is used when during processing of a command,
  1255. *   additional text input is needed.  Normally, text input to a CLI session is
  1256. *   via command processing handler.
  1257. *
  1258. *   Modify this function to support multiple session type.
  1259. * Arguments :
  1260. *   pSess - a pointer to a command session
  1261. *
  1262. * Returns :
  1263. *   >= 0 - the character returned
  1264. *   -1 - Failed
  1265. *
  1266. * History
  1267. *   who   when why
  1268. *   KBL   11/17/99 created
  1269. *
  1270. *****************************************************************************/
  1271. int Cli_GetChar(Cli_cmdSession_t *pSess)
  1272. {
  1273. char MyChar;
  1274. while ((MyChar = pSess->pSessFuns->read_char()) == 0)
  1275. pSess->pSessFuns->yield();
  1276. return MyChar;
  1277. }
  1278. /*
  1279.  * CLI utility functions - based on Cli_PutStr()
  1280.  */
  1281. int Cli_PutStr(Cli_cmdSession_t *pSess, char *str, int len)
  1282. {
  1283. int  StrIdx, PrintLen;
  1284. char KeyPressed, *pStrStart;
  1285. pStrStart = NULL;
  1286. for (StrIdx = 0; StrIdx < len; StrIdx++) 
  1287. {
  1288. if (pStrStart == NULL)
  1289. {
  1290. pStrStart = &(str[StrIdx]);
  1291. }
  1292. if ((str[StrIdx] == 'n') || (StrIdx == (len - 1)))
  1293. {
  1294. PrintLen = &(str[StrIdx]) - pStrStart + 1;
  1295. Cli_WriteBuf(pSess, pStrStart, PrintLen);
  1296. pStrStart = NULL;
  1297. if ((str[StrIdx] == 'n') && pSess->scrollPause) 
  1298. {
  1299. pSess->currentRow++;
  1300. if (pSess->currentRow >= (pSess->pageLength - 1)) 
  1301. {
  1302. Cli_WriteBuf(pSess, waitForAKeyStr, strlen(waitForAKeyStr));
  1303. KeyPressed = Cli_GetChar(pSess);
  1304. /* Clear out the "Press XYZ..." string. */
  1305. /* Cli_Printf(pSess, " r"); */
  1306. /* Check for ESC */
  1307. if (KeyPressed == 0x1b)
  1308. {
  1309. pSess->skipPrinting = 1;
  1310. break;
  1311. }
  1312. /* Check for -1 */
  1313. if (KeyPressed == -1)
  1314. {
  1315. return -1;
  1316. }
  1317. /* Don't forget to reset the row counter ! */
  1318. Cli_ResetRowCounter(pSess);
  1319. }
  1320. }
  1321. }   
  1322. }
  1323. return 0;
  1324. }
  1325. /***************************************************************************** 
  1326. * int Cli_Printf(Cli_cmdSession_t *pSess, char *fmt, ...)
  1327. *
  1328. * Description :
  1329. * This is the printf function for CLI.
  1330. * Arguments :
  1331. * pCmdSession - opaque pointer to a command session
  1332. * the rest of the parameters are the same as for printf().
  1333. *
  1334. * Returns :
  1335. *   0 - OK
  1336. *   
  1337. *
  1338. * History
  1339. * who   when why
  1340. * KBL   7/7/99   created
  1341. *
  1342. *****************************************************************************/
  1343. int Cli_Printf(Cli_cmdSession_t *pSess, char *fmt, ...)
  1344. {
  1345. va_list  ap;
  1346. va_start(ap, fmt);
  1347. vsprintf(pSess->scratchBuf, fmt, ap);
  1348. va_end(ap);
  1349. /* Make sure it's NULL terminated at the very least */
  1350. pSess->scratchBuf[SCRATCH_BUF_SIZE-2] = 0;
  1351. return Cli_PutStr(pSess, pSess->scratchBuf, strlen(pSess->scratchBuf)); 
  1352. }
  1353. /***************************************************************************** 
  1354. * int Cli_PutChar(Cli_cmdSession_t *pSess, char ch)
  1355. *
  1356. * Description :
  1357. * This function print a character.
  1358. * Arguments :
  1359. * pCmdSession - opaque pointer to a command session
  1360. * ch - the character.
  1361. *
  1362. * Returns :
  1363. *   0 - OK
  1364. *  -1 - Failed
  1365. *
  1366. * History
  1367. * who   when why
  1368. * KBL   9/7/99   created
  1369. *
  1370. *****************************************************************************/
  1371. int Cli_PutChar(Cli_cmdSession_t *pSess, char ch)
  1372. {
  1373. return Cli_PutStr(pSess, &ch, 1);
  1374. }
  1375. /***************************************************************************** 
  1376. * int Cli_SendCrLf(Cli_cmdSession_t *pSess)
  1377. *
  1378. * Description :
  1379. * send a CR/LF pair to advance a line.
  1380. * Arguments :
  1381. *   pSess - pointer to the session.
  1382. *
  1383. * Returns :
  1384. *   0 if OK
  1385. *   -1 if Failed, likely cause is a bad socket.
  1386. *
  1387. * History
  1388. * who   when why
  1389. * KBL   7/7/99   created
  1390. *
  1391. *****************************************************************************/
  1392. int Cli_SendCrLf(Cli_cmdSession_t *pSess)
  1393. {
  1394. return ( Cli_Printf(pSess, "n") );
  1395. }
  1396. /***************************************************************************** 
  1397. * int Cli_PrintLine(Cli_cmdSession_t *pSess, 
  1398. *    int  NumChar,
  1399. *    char Character,
  1400. *    int  NumFrontCR, 
  1401. *    int  NumBackCR)
  1402. *
  1403. * Description :
  1404. *   This function draws a line made up of "Character" of "NumChar" width.
  1405. *   If "NumFrontCR" is 1, a CR is placed before the line.  Likewise if
  1406. *   "NumBackCR" is 1, a CR is placed after the line.
  1407. * Arguments :
  1408. *   pSess - pointer to the session.
  1409. *   see above for explantion for the other parameters.
  1410. *
  1411. * Returns :
  1412. *   0 if OK
  1413. *   -1 if Failed, likely cause is a bad socket.
  1414. *
  1415. * History
  1416. * who   when why
  1417. * KBL   7/7/99   created
  1418. *
  1419. *****************************************************************************/
  1420. int Cli_PrintLine(Cli_cmdSession_t *pSess, 
  1421.  int  NumChar,
  1422.  char Character,
  1423.  int  NumFrontCR, 
  1424.  int  NumBackCR)
  1425. {
  1426. int Cnt;
  1427. for (Cnt = 0; Cnt < NumFrontCR; Cnt++) 
  1428. {
  1429. if (Cli_SendCrLf(pSess) == -1) return -1;
  1430. }
  1431. for (Cnt = 0; Cnt < NumChar; Cnt++) 
  1432. {
  1433. if (Cli_Printf(pSess, "%c", Character) == -1) return -1;
  1434. }
  1435. for (Cnt = 0; Cnt < NumBackCR; Cnt++) 
  1436. {
  1437. if (Cli_SendCrLf(pSess) == -1) return -1;
  1438. }
  1439. return 0;
  1440. }
  1441. /***************************************************************************** 
  1442. * int Cli_PrintFileContent(Cli_cmdSession_t *pSess, char *FileName)
  1443. *
  1444. * Description :
  1445. *   This function prints out the content of a file.  The file must better be
  1446. *   a text file, otherwise weird thing may happen.
  1447. * Arguments :
  1448. *   pSess - pointer to the session.
  1449. *   FileName - pointer to a filename string.
  1450. *
  1451. * Returns :
  1452. *   0 if OK
  1453. *   -1 if Failed, likely cause is a bad socket.
  1454. *
  1455. * History
  1456. *   who   when why
  1457. *   KBL   11/24/99 created
  1458. *
  1459. *****************************************************************************/
  1460. int Cli_PrintFileContent(Cli_cmdSession_t *pSess, char *FileName)
  1461. {
  1462. FILE *fp;
  1463. char ScratchPadStr[100];
  1464. if ((fp = fopen(FileName, "rt")) == NULL) 
  1465. {
  1466. Cli_Printf(pSess, "Could not open file %sn", FileName);
  1467. return 0;
  1468. }
  1469. Cli_SendCrLf(pSess);
  1470. Cli_SendCrLf(pSess);
  1471. Cli_Printf(pSess, "%s :n", FileName);
  1472. while (fgets(ScratchPadStr, (sizeof(ScratchPadStr) - 1), fp) != NULL ) 
  1473. {
  1474. if (Cli_Printf(pSess, "%s", ScratchPadStr) != 0)
  1475. {
  1476. fclose(fp);
  1477. return -1;
  1478. }
  1479. }
  1480. fclose(fp);
  1481. return 0;
  1482. }
  1483. /*+***************************************************************************
  1484. * Cli_PrintData - Utility function for dumping memory
  1485. *
  1486. * Returns:
  1487. *   void- 
  1488. *
  1489. * Description:
  1490. *   Formats for display the contents of a memory buffer. The eFormat option
  1491. *   indicates the data width and representation (dec, hex). The bUseRelativeAddr
  1492. *   parameter determines whether a zero-based index is displayed or the absolute
  1493. *   address of the data at the start of each line.
  1494. *
  1495. * History:
  1496. *   1/13/00  MA  Original version
  1497. *
  1498. **-**************************************************************************/ 
  1499. void Cli_PrintData(Cli_cmdSession_t *pSess, void *pvBuffer, int nBytes, 
  1500.    Cli_PrintFormat_e eFormat, int bUseRelativeAddr)
  1501. {
  1502. int i, j;
  1503. int LineLen;
  1504. char Char;
  1505. int iChar;
  1506. if (eFormat == CLI_PRINT_DATA_FORMAT_HEX8)
  1507. {
  1508. LineLen = 16;
  1509. }
  1510. else if (eFormat <= CLI_PRINT_DATA_FORMAT_HEX32)
  1511. {
  1512. LineLen = 4;
  1513. }
  1514. else
  1515. {
  1516. LineLen = 8;
  1517. }
  1518. for (i = 0; i < nBytes;)
  1519. {
  1520. if (bUseRelativeAddr)
  1521. Cli_Printf(pSess, "0x%04x: ", i);
  1522. else
  1523. Cli_Printf(pSess, "0x%08x: ", (u_int32_t)pvBuffer + i);
  1524. /* Save start offset of line */
  1525. iChar = i;
  1526. for (j = 0; j < LineLen && i < nBytes; j++)
  1527. {
  1528. switch (eFormat)
  1529. {
  1530. case CLI_PRINT_DATA_FORMAT_INT32:
  1531. Cli_Printf(pSess, "%11d ", *((int *)((u_int32_t)pvBuffer + i)));
  1532. i += sizeof(int);
  1533. break;
  1534. case CLI_PRINT_DATA_FORMAT_UINT32:
  1535. Cli_Printf(pSess, "%10lu ", *((unsigned int *)((u_int32_t)pvBuffer + i)));
  1536. i += sizeof(int);
  1537. break;
  1538. case CLI_PRINT_DATA_FORMAT_INT16:
  1539. Cli_Printf(pSess, "%6d ", (int) *((int16_t *)((u_int32_t)pvBuffer + i)));
  1540. i += sizeof(int16_t);
  1541. break;
  1542. case CLI_PRINT_DATA_FORMAT_UINT16:
  1543. Cli_Printf(pSess, "%5lu ", (unsigned int) *((u_int16_t *)((u_int32_t)pvBuffer + i)));
  1544. i += sizeof(int16_t);
  1545. break;
  1546. case CLI_PRINT_DATA_FORMAT_INT8:
  1547. Cli_Printf(pSess, "%4d ", (int) *((int8_t *)((u_int32_t)pvBuffer + i)));
  1548. i += sizeof(int8_t);
  1549. break;
  1550. case CLI_PRINT_DATA_FORMAT_UINT8:
  1551. Cli_Printf(pSess, "%3d ", (unsigned int) *((u_int8_t *)((u_int32_t)pvBuffer + i)));
  1552. i += sizeof(int8_t);
  1553. break;
  1554. case CLI_PRINT_DATA_FORMAT_HEX32:
  1555. Cli_Printf(pSess, "%08x ", *((u_int32_t *)((u_int32_t)pvBuffer + i)));
  1556. i += sizeof(u_int32_t);
  1557. break;
  1558. case CLI_PRINT_DATA_FORMAT_HEX16:
  1559. Cli_Printf(pSess, "%04x ", (u_int32_t) *((u_int16_t *)((u_int32_t)pvBuffer + i)));
  1560. i += sizeof(u_int16_t);
  1561. break;
  1562. default:
  1563. case CLI_PRINT_DATA_FORMAT_HEX8:
  1564. Cli_Printf(pSess, "%02x ", (u_int32_t) *((u_int8_t *)((u_int32_t)pvBuffer + i)));
  1565. i += sizeof(u_int8_t);
  1566. break;
  1567. }
  1568. }
  1569. if (eFormat == CLI_PRINT_DATA_FORMAT_HEX8)
  1570. {
  1571. /* Align to start of text column */
  1572. for (;j < LineLen + 1; j++)
  1573. {
  1574. Cli_Printf(pSess, "   ");
  1575. }
  1576. /* Now print ASCII representation of this line */
  1577. for (j = 0; j < LineLen && iChar < nBytes; j++, iChar++)
  1578. {
  1579. Char = *(char *)((u_int32_t)pvBuffer + iChar);
  1580. if (!isprint(Char))
  1581. Char = '.';
  1582. Cli_Printf(pSess, "%c", Char);
  1583. }
  1584. }
  1585. Cli_Printf(pSess, "n");
  1586. }
  1587. }
  1588. /***************************************************************************** 
  1589. * int Cli_IpAndMask2int()
  1590. *
  1591. * Description :
  1592. * convert from a string like "A.B.C.D/P.Q.R.S" to its IP address and mask
  1593. * in unsigned int.
  1594. * Arguments :
  1595. * str is where the string start, the values are returned via addr and mask.
  1596. *
  1597. * Returns :
  1598. * 0 if OK, -1 if convertion error.  Both addr & mask are returned in network
  1599. * byte order.
  1600. *
  1601. * History
  1602. * who   when why
  1603. * KBL   7/15/99  created
  1604. *
  1605. *****************************************************************************/
  1606. int Cli_IpAndMask2int(char *str, unsigned int *addr, unsigned int *mask)
  1607. {
  1608. int    iByte, value;
  1609. unsigned int  ipaddress = 0;
  1610. unsigned int  ipmask = 0;
  1611. char   *pb, *pb2;
  1612. pb = str;
  1613. pb2 = strchr(pb, '/') + 1;  /* knows where the mask is before messing up */
  1614. /* Parse dotted IP address */
  1615. for (iByte = 0; iByte < 4; iByte++)
  1616. {
  1617. value = atoi(pb);
  1618. if (value > 255)
  1619. {
  1620. return -1;
  1621. }
  1622. ipaddress |= (value << 24);
  1623. if (iByte < 3) 
  1624. {
  1625. ipaddress >>= 8;
  1626. pb = strchr (pb, '.');
  1627. if (pb == NULL)
  1628. {
  1629. return -1;
  1630. }
  1631. pb++;  /* move to the number field */
  1632. }
  1633. }
  1634. /* If the caller only need IP address, mask is NULL, we return here. */
  1635. if (mask == NULL) 
  1636. {
  1637. *addr = ipaddress;
  1638. return 0;
  1639. }
  1640. /* make sure the next "." is after "/" */
  1641. pb = strchr(pb, '.');
  1642. if ((pb == NULL) || (pb < pb2))
  1643. {
  1644. return -1;
  1645. }
  1646. /* Parse dotted IP mask */
  1647. for (iByte = 0; iByte < 4; iByte++)
  1648. {
  1649. value = atoi(pb2);
  1650. if (value > 255)
  1651. {
  1652. return -1;
  1653. }
  1654. ipmask |= (value << 24);
  1655. if (iByte < 3)
  1656. {
  1657. ipmask >>= 8;
  1658. pb2 = strchr (pb2, '.');
  1659. if (pb2 == NULL)
  1660. {
  1661. return -1;
  1662. }
  1663. pb2++;
  1664. }
  1665. }
  1666. /* make sure there is no more "." */
  1667. pb2 = strchr(pb2, '.');
  1668. if (pb2 != NULL) 
  1669. {
  1670. return -1;
  1671. }
  1672. *addr = ipaddress;
  1673. *mask = ipmask;
  1674. return 0;
  1675. }