⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cli_term.c

📁 命令行在嵌入式系统的实现
💻 C
📖 第 1 页 / 共 5 页
字号:
            if (G_SUCCESS != IO_GetString(szPassword, PASSWORD_LEN, EN_SHOWBACK_INVISIBLE))
            {
                #if CLI_TELNET_SUPPORT
                if( G_YES == g_ul_INCLUDE_SUB_MODULE_CLI_TELNET )
                {
                    if (pTermStruct->iSocket != SOCKET_FOR_SERIAL)
                    {
                        DBG_ASSERT( G_NULL != g_pfn_CFG_CLI_CloseSocket );

                        /*如果是telnet,手动注销并关闭该终端*/
                        g_pfn_CFG_CLI_CloseSocket(pTermStruct);
                        CLI_TaskDataInit(pTermStruct);
                        CLI_ResetEnviroment(pTermStruct->pWS);
                        CLI_SetTermStatus(pTermStruct, TERM_SLEEPING);
                        return ;
                    }
                }
                #endif

                IO_OutToTerm(pTermStruct, "\r\n  Timeout. \r\n  Press any key and input again.");
                while(IO_GetChar() ==G_NULL)
                    pTermStruct->ulTimeLeft = DEADLINE_SHORT;
                continue;
            }
        }

        if (CLI_CheckUserPassword(szUsername, szPassword) != G_SUCCESS)
        {
            CLI_DELAY(100);
            IO_OutToTerm(pTermStruct, "\r\n  Error username or password!");
            if (pTermStruct->iSocket != SOCKET_FOR_SERIAL)
            {
                /* 如果telnet的登录失败达到3次,注销该终端 */
                if (++ulFailCount >= MAX_FAILED_LOG_TIME)
                {
                    CLI_RECORD(CLI_STAT_TELNET_LOGIN);
                    CLI_TermLogout(pTermStruct);
                    return;
                }
            }
            continue;
        }

        pTermUser = CLI_GetUserByName(szUsername);

        /* 如果已经有终端试图重复登录,则不允许第三个终端重复登录 */
        if (pTermUser->ucInvadedFlag == EN_USER_INVADED)
        {
            IO_Print(CLI_USER_TOO_BUSY);
            continue;
        }

        /* 如果该用户对应的终端ID不为零,表示该用户在另一个终端已经登录 */
        if (pTermUser->ulTermId != 0)
        {
            pstOldLogTerm = m_TDTable[pTermUser->ulTermId - 1].pTermStruct;

            DBG_Out(PID_CLI, MT_DBGOUT_NOTE, G_STR_HEAD
                    "CLI_TermLogin(): user <%s> has log on from term <%d>!",
                     pTermUser->szUserName, pTermUser->ulTermId);

            pTermUser->ucInvadedFlag = EN_USER_INVADED;
            if (IO_GetConfirm(CLI_TERMINAL_COLLISION, INPUT_NO) == INPUT_YES)
            {
                /* 强制注销另一个命令行终端 */
                if( CLI_IS_TERMID_VALIDE(pTermUser->ulTermId) )
                {
                    /* 加此重复判断是为了防止在确认的过程中,对方的登录状况有变*/
                    if ((pTermUser->ulTermId != 0)
                      &&(0 == EOS_StriCmp(szUsername, pstOldLogTerm->szCurUserName)))
                    {
                        IO_PrintToTerm(pTermUser->ulTermId, CLI_TERMINAL_KICKED_OFF);
                        CLI_SetTermStatus(pstOldLogTerm, TERM_SLEEPING);
                    }

                    /* 等待该终端用户注销之后方才正式登录,如果一定时间内对方没有自动退出,*/
                    /* 则强行注销该终端(这是唯一的注销其它终端的地方,尽量限制使用) */
                    CLI_RECORD(CLI_STAT_KICKOFF_OTHER);
                    DBG_Out( PID_CLI, MT_DBGOUT_NOTE, G_STR_HEAD
                             "CLI_TermLogin(): Cli term %d is Forced Logout!", pTermUser->ulTermId );
                    CLI_TermLogout(pstOldLogTerm);
                }
                /* 强制注销另一个web终端 */
                #if ( CLI_WEB_SUPPORT == G_YES )
                else if( IS_WEB_TERMID( pTermUser->ulTermId ) )
                {
                    _U32    ulStratCentiSec, ulElapsCentiSec = 0;
                    _BOOL   bWebLogOutOk = G_FALSE;

                    DBG_Out( PID_CLI, MT_DBGOUT_NOTE, G_STR_HEAD
                             "CLI_TermLogin(): Web term %d is Forced Logout!", pTermUser->ulTermId );

                    (_VOID)EOS_GetCentiSecondFromStart( &ulStratCentiSec );

                    /* 通过消息包方式通知web网管踢用户, 异步方式 */
                    (_VOID)CLI_WebSendKickOffUserMsg( pTermUser->ulTermId );

                    /* 延迟让权, 保证web网管处理结束, 最多等1秒 */
                    while(  ulElapsCentiSec < ( 1 * 100 ) )
                    {
                        CLI_DELAY(1);

                        /* 确保web网管退出登录的处理结果正确 */
                        if(    ( TERM_SLEEPING == pstOldLogTerm->ucTermStatus )
                            && ( TERM_SLEEPING == pTermUser->ucUserStatus )
                            && ( 0 == pTermUser->ulTermId )
                          )
                        {
                            bWebLogOutOk = G_TRUE;
                            break;
                        }

                        (_VOID)EOS_GetCentiSecondFromStart( &ulElapsCentiSec );
                        ulElapsCentiSec = ulElapsCentiSec - ulStratCentiSec;
                    }

                    /* 确保web网管退出登录的处理结果正确 */
                    if( G_TRUE != bWebLogOutOk )
                    {
                        DBG_ErrLog( 0, EN_ERR_LEVEL_GENERAL, ulElapsCentiSec, pstOldLogTerm->ucTermStatus );
                        DBG_ErrLog( 0, EN_ERR_LEVEL_GENERAL, pTermUser->ucUserStatus, pTermUser->ulTermId );
                    }

                }
                #endif /* #if ( CLI_WEB_SUPPORT == G_YES ) */
                else
                {
                    MT_ERRLOG(0);
                }

            }
            else
            {
                pTermUser->ucInvadedFlag = EN_USER_NOT_INVADED;
                continue;
            }
        }

        /* 成功登录后的一些用户与终端数据初始化 */
        pTermUser->ulTermId       = pTermStruct->ulTermId;
        pTermUser->ucUserStatus   = TERM_LOGED;
        CLI_SetTermStatus(pTermStruct, TERM_LOGED);
        pTermStruct->ucUserLevel  = (_U8)pTermUser->ulLevel;
        pTermStruct->pWS->ulLevel = pTermUser->ulLevel;
        EOS_StrCpy(pTermStruct->szCurUserName, szUsername);
        pTermUser->ucInvadedFlag = EN_USER_NOT_INVADED;

        ML_SetLanguage(pTermStruct->ulTermId, pTermUser->ucLanguage);

        if (pTermStruct->iSocket == SOCKET_FOR_SERIAL)
            ulLogMode = LOG_MODE_SERIAL ;
        else if(pTermStruct->iSocket == SOCKET_FOR_MML)
            ulLogMode = LOG_MODE_MML;
        else
            ulLogMode = LOG_MODE_TELNET;
        CLI_SaveUserLog(pTermStruct->szCurUserName, ulLogMode, pTermStruct->ulClientIP, "logon[s]") ;

        if (EOS_GetTime(&sTime) == G_SUCCESS)
        {
            if ((pTermUser->ulPwdRenewTime + 100) < (_U32)USER_MAKE_DAY(sTime.ucYear, sTime.ucMonth, sTime.ucDay))
            {
                IO_Print(CLI_PASSWORD_NEED_RENEW);
                CLI_DELAY(50);
            }
        }

        IO_Print( CLI_LOGED_OEM_VENDOR_INFO, ROS_GetVendorNameStrId() );
        IO_Print( CLI_LOGED_INFO , ROS_GetDevSoftVer() );
        CI_DisplayPrompt(pTermStruct);

        return;
    }

}

/*********************************************************************/
/* 函数名称 : CLI_TermLogout()                                       */
/* 函数功能 : 终端注销函数入口                                       */
/* 输入参数 : 终端任务数据                                           */
/* 输出参数 : 终端任务数据                                           */
/* 返回     : 无                                                     */
/* 上层函数 : 终端任务执行主函数体                                   */
/* 创建者   :                                                        */
/* 修改记录 :                                                        */
/*********************************************************************/
_VOID CLI_TermLogout(PTerm_Data_S pTermStruct)
{
    PTermUserItem pTermUser;
    PTerm_Data_S  pCurTerm;
    _U32 ulTermID;
    _U32 ulLogMode;
    _U32 ulCallPc;

    if (pTermStruct == G_NULL)
    {
        MT_ERRLOG(0);
        return;
    }

    pCurTerm = CLI_GetCurrentTaskData();

    EOS_GetCallersPC( &ulCallPc, 1 );
    DBG_Out(PID_CLI, MT_DBGOUT_NOTE, "\r\n CLI_Logout::Addr 0x%x call logout func", ulCallPc);

    ulTermID  = pTermStruct->ulTermId;

    if (pTermStruct->iSocket == SOCKET_NOT_INITIAL || pTermStruct->iSocket == SOCKET_FOR_MML)
    {
        DBG_Out(PID_CLI, MT_DBGOUT_NOTE, "\r\n CLI_Logout::试图注销一个未登录的终端!");
        return ;
    }
    /* 分两种情况考虑: 1、未成功登录的注销; 2、登录后的注销  */
    /* 两种情况由用户名是否为初始化的用户名来判定            */
    if (!EOS_StriCmp(pTermStruct->szCurUserName, UNLOGON_USER_NAME))
    {
        if (pTermStruct->iSocket == SOCKET_FOR_SERIAL)
            return ;
    }
    else
    {
        /* 以下情况表示该终端已经注销过,不能重复注销                */
        /* 注意: 判断是否已经注销不能通过终端状态是否为TERM_SLEEPING */
        /*       来决定,因为该状态本身就是用于告诉任务终端在等待注销 */
        pTermUser = CLI_GetUserByName(pTermStruct->szCurUserName);
        if (pTermUser == G_NULL || pTermUser->ulTermId == 0)
        {
            pTermStruct->ucTermStatus = TERM_SLEEPING;
            CLI_RECORD(CLI_STAT_LOGOUT_MANY_TIMES);
            return ;
        }
        /* 作此判断是考虑到可能在该终端注销前另一个终端已经使用同名用户登录 */
        if (pTermUser->ulTermId == ulTermID)
        {
            pTermUser->ulTermId = 0;
            pTermUser->ucUserStatus = TERM_SLEEPING;
        }
    }

    /* 将该终端任务返回到根模式 */
    CLI_ReturnRootMode(pTermStruct);

    IO_PrintToTerm (pTermStruct->ulTermId, CLI_LOGOUT_NOTE);
    CLI_DELAY(100);

    #if CLI_TELNET_SUPPORT
    if( G_YES == g_ul_INCLUDE_SUB_MODULE_CLI_TELNET )
    {
        if (pTermStruct->iSocket != SOCKET_FOR_SERIAL)
        {
            DBG_ASSERT( G_NULL != g_pfn_CFG_CLI_CloseSocket );
            g_pfn_CFG_CLI_CloseSocket(pTermStruct);
        }
    }
    #endif

    if (pTermStruct->iSocket == SOCKET_FOR_SERIAL)
        ulLogMode = LOG_MODE_SERIAL;
    else if(pTermStruct->iSocket == SOCKET_FOR_MML)
        ulLogMode = LOG_MODE_MML;
    else
        ulLogMode = LOG_MODE_TELNET;
    CLI_SaveUserLog(pTermStruct->szCurUserName, ulLogMode, pTermStruct->ulClientIP, "logout[s]") ;

    // 如果注销的是串口而且是自身注销,则需要任意键进入下次登录
    if (pTermStruct->iSocket == SOCKET_FOR_SERIAL && pCurTerm == pTermStruct)
    {
        CLI_SetTermStatus(pCurTerm, TERM_ACTIVE);
        IO_PrintToTerm (pTermStruct->ulTermId, CLI_ANYKEY_CONTINUE);
        while(IO_GetChar() ==G_NULL)
        {
            if (pCurTerm->ulTimeLeft == 0 || pCurTerm->ucTermStatus == TERM_SLEEPING)
            {
                break;
            }
            pTermStruct->ulTimeLeft = DEADLINE_SHORT;
        }
    }
    CLI_TaskDataInit(pTermStruct);
    CLI_ResetEnviroment(pTermStruct->pWS);
    CLI_SetTermStatus(pTermStruct, TERM_SLEEPING);

    return;
}


/*********************************************************************/
/* 函数名称 : CLI_ReturnRootMode()                                   */
/* 函数功能 : 将当前终端任务返回到根模式                             */
/* 输入参数 : pTermStruct: 终端任务数据                              */
/* 输出参数 : pTermStruct: 终端任务数据                              */
/* 返回     : 成功、失败                                             */
/* 上层函数 :                                                        */
/* 创建者   :                                                        */
/* 修改记录 :                                                        */
/*********************************************************************/
_U32 CLI_ReturnRootMode(PTerm_Data_S pTermStruct)
{
    CLI_ASSURE_OR_FAIL( G_NULL != pTermStruct );

    CI_SetWSStatus(pTermStruct->pWS, (_U32)STAT_ENV_RUNCFG) ;

    if (pTermStruct->pWS->ulCurrentMode != CTM_GENL)
    {
        EOS_StrCpy(pTermStruct->szCommandBuf, CMD_CM "root") ;
        CI_CmdExecute(pTermStruct) ;
    }
    CI_SetWSStatus(pTermStruct->pWS, 0) ;
    return G_SUCCESS;
}

/*==================================================================*/
/*      函数名      :CLI_SetTermStatus                              */
/*      函数功能    :设置终端状态                                   */
/*      输入参数    :PTerm_Data_S pTermStruct  任务数据指针         */
/*                   ucTermStatus 设置的状态                        */
/*      输出参数    :PTerm_Data_S pTermStruct  任务数据指针         */
/*      返回值      :无                                             */
/*      被调函数    :                                               */
/*==================================================================*/
_VOID CLI_SetTermStatus(PTerm_Data_S pTermStruct, _U8 ucTermStatus)
{
    _S8 szInfo[TELNET_MAX_STATUS][15] =
            {"SLEEPING","ACTIVE","LOGED","EXEC-CMD","WAIT-RESPONSE"};

    DBG_Out(PID_CLI, CLI_DBGOUT_NOTE,
        "\r\n CLI: Term %d status terned from [%s] to [%s]",
        pTermStruct->ulTermId, szInfo[pTermStruct->ucTermStatus], szInfo[ucTermStatus]);

    if (pTermStruct->ucTermStatus == TERM_WAIT_RESPONSE && ucTermStatus == TERM_LOGED)
    {
        pTermStruct->ucTermStatus = ucTermStatus;
        CI_DisplayPrompt(pTermStruct);
        return;
    }

    pTermStruct->ucTermStatus = ucTermStatus;
    return ;
}


/* 字符串编辑部分 */

/*==================================================================*/
/*      函数名      :CLI_EditString                                 */
/*      函数功能    :扫描接收缓冲区,并编辑字符串编辑缓冲区          */
/*      输入参数    :PTerm_Data_S pTermStruct  任务数据指针         */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -