Skip to content

File wsh_shell_cmd_def.c

File List > src > wsh_shell_cmd_def.c

Go to the documentation of this file

#include "wsh_shell_cmd_def.h"
#include "wsh_shell.h"

#if WSH_SHELL_DEF_COMMAND

    #define X_ENTRY(name, value) value,
static const WSH_SHELL_CMD_GROUP_t WshShell_CmdGroups[] = {WSH_SHELL_CMD_GROUP_LIST};
    #undef X_ENTRY

    #define WSH_SHELL_CMD_GROUP_COUNT (WSH_SHELL_ARR_LEN(WshShell_CmdGroups))

/* clang-format off */
#define WSH_SHELL_CMD_DEF_OPT_TABLE() \
    X_CMD_ENTRY(WSH_SHELL_DEF_OPT_DEF, WSH_SHELL_OPT_NO(WSH_SHELL_OPT_ACCESS_ANY, "Print basic info about shell instance")) \
    X_CMD_ENTRY(WSH_SHELL_DEF_OPT_HELP, WSH_SHELL_OPT_HELP()) \
    X_CMD_ENTRY(WSH_SHELL_DEF_OPT_INTERACT, WSH_SHELL_OPT_INTERACT(WSH_SHELL_OPT_ACCESS_ANY)) \
    X_CMD_ENTRY(WSH_SHELL_DEF_OPT_EXEC, WSH_SHELL_OPT_WO_PARAM(WSH_SHELL_OPT_ACCESS_READ, "-x", "--exec", "Get info about accessible commands")) \
    X_CMD_ENTRY(WSH_SHELL_DEF_OPT_USER, WSH_SHELL_OPT_WO_PARAM(WSH_SHELL_OPT_ACCESS_READ, "-u", "--user", "Get info about users")) \
    X_CMD_ENTRY(WSH_SHELL_DEF_OPT_CLS, WSH_SHELL_OPT_WO_PARAM(WSH_SHELL_OPT_ACCESS_EXECUTE, "-c", "--cls", "Clear screen")) \
    X_CMD_ENTRY(WSH_SHELL_DEF_OPT_HIST_CLEAR, WSH_SHELL_OPT_WO_PARAM(WSH_SHELL_OPT_ACCESS_WRITE, "-r", "--histrst", "Reset history storage")) \
    X_CMD_ENTRY(WSH_SHELL_DEF_OPT_HIST_PRINT, WSH_SHELL_OPT_WO_PARAM(WSH_SHELL_OPT_ACCESS_READ, "-p", "--histprint", "Print history storage")) \
    X_CMD_ENTRY(WSH_SHELL_DEF_OPT_DEAUTH, WSH_SHELL_OPT_WO_PARAM(WSH_SHELL_OPT_ACCESS_ANY, "-d", "--deauth", "DeAuth and destroy history")) \
    X_CMD_ENTRY(WSH_SHELL_DEF_OPT_STR, WSH_SHELL_OPT_STR(WSH_SHELL_OPT_ACCESS_EXECUTE, "-s", "--str", "Set string")) \
    X_CMD_ENTRY(WSH_SHELL_DEF_OPT_INT, WSH_SHELL_OPT_INT(WSH_SHELL_OPT_ACCESS_EXECUTE, "-n", "--int", "Set int")) \
    X_CMD_ENTRY(WSH_SHELL_DEF_OPT_FLT, WSH_SHELL_OPT_FLOAT(WSH_SHELL_OPT_ACCESS_ADMIN, "-f", "--flt", "Set float")) \
    X_CMD_ENTRY(WSH_SHELL_DEF_OPT_END, WSH_SHELL_OPT_END())
/* clang-format on */

typedef enum {
    #define X_CMD_ENTRY(en, m) en,
    WSH_SHELL_CMD_DEF_OPT_TABLE() WSH_SHELL_CMD_DEF_OPT_ENUM_SIZE
    #undef X_CMD_ENTRY
} WSH_SHELL_DEF_OPT_t;

    #define X_CMD_ENTRY(enum, opt) {enum, opt},
static const WshShellOption_t WshShell_OptArr[] = {WSH_SHELL_CMD_DEF_OPT_TABLE()};
    #undef X_CMD_ENTRY

static void WshShell_CmdDefInteractive(WshShellIO_CommandLine_t* pInter) {
    WshShellInteract_AppendLineBreak(pInter);

    WSH_SHELL_PRINT("Just echo of interactive command: %s", pInter->Buff);
}

static WSH_SHELL_RET_STATE_t WshShellCmdDef(const WshShellCmd_t* pcCmd, WshShell_Size_t argc,
                                            const WshShell_Char_t* pArgv[], void* pShellCtx) {
    if ((argc > 0 && !pArgv) || !pcCmd)
        return WSH_SHELL_RET_STATE_ERROR;

    WshShell_t* pParentShell       = (WshShell_t*)pShellCtx;
    WSH_SHELL_RET_STATE_t retState = WSH_SHELL_RET_STATE_SUCCESS;

    for (WshShell_Size_t tokenPos = 0; tokenPos < argc;) {
        WshShellOption_Ctx_t optCtx =
            WshShellCmd_ParseOpt(pcCmd, argc, pArgv, pParentShell->CurrUser->Rights, &tokenPos);
        if (!optCtx.Option)
            return WSH_SHELL_RET_STATE_ERR_EMPTY;

        switch (optCtx.Option->ID) {
            case WSH_SHELL_DEF_OPT_DEF: {
                WSH_SHELL_PRINT("Ver: %s\r\n", pParentShell->Version);
                WSH_SHELL_PRINT("Device name: %s\r\n", pParentShell->DeviceName);
                WSH_SHELL_PRINT("User: %s\r\n", pParentShell->CurrUser->Login);
            } break;

            case WSH_SHELL_DEF_OPT_HELP: {
                WshShellCmd_PrintOptionsOverview(pcCmd);
            } break;

            case WSH_SHELL_DEF_OPT_INTERACT: {
                WshShellInteract_Attach(&(pParentShell->Interact), pcCmd->Name,
                                        WshShell_CmdDefInteractive);
            } break;

            case WSH_SHELL_DEF_OPT_EXEC: {
                WSH_SHELL_PRINT("Availible commans:\r\n");

                const WshShell_Size_t cmdMaxLen   = WSH_SHELL_CMD_NAME_LEN;
                const WshShell_Size_t optMaxLen   = 5;
                const WshShell_Size_t groupMaxLen = WSH_SHELL_CMD_GROUP_COUNT + 3;

                WshShell_Char_t headTemplate[64];
                WSH_SHELL_SNPRINTF(headTemplate, sizeof(headTemplate),
                                   WSH_SHELL_COLOR_SYS
                                   "  %%-%ds %%-%ds %%-%ds %%s\r\n" WSH_SHELL_ESC_RESET_STYLE,
                                   cmdMaxLen, optMaxLen, groupMaxLen);

                WSH_SHELL_PRINT(headTemplate, "Command", "Opts", "Groups", "Descr");

                WshShell_Char_t rowTemplate[64];
                WSH_SHELL_SNPRINTF(rowTemplate, sizeof(rowTemplate),
                                   "  %%-%ds %%-%dd %%-%ds %%s\r\n", cmdMaxLen, optMaxLen,
                                   groupMaxLen);

                const WshShellCmd_t* pcDefCmd = WshShellDefCmd_GetPtr();
                if (pcDefCmd != NULL) {
                    WshShell_Char_t groupRow[WSH_SHELL_CMD_GROUP_COUNT + 1];
                    WshShellStr_GroupBitsToStr(pcDefCmd->Groups, WSH_SHELL_CMD_GROUP_COUNT,
                                               groupRow);
                    WSH_SHELL_PRINT(rowTemplate, pcDefCmd->Name, pcDefCmd->OptNum - 1, groupRow,
                                    pcDefCmd->Descr);
                }

                WshShell_Size_t commandsNum = WshShellCmd_GetCmdNum(&(pParentShell->Commands));
                for (WshShell_Size_t cmd = 0; cmd < commandsNum; cmd++) {
                    const WshShellCmd_t* pcTargetCmd =
                        WshShellCmd_GetCmdByIndex(&(pParentShell->Commands), cmd);

                    if (pcTargetCmd == NULL)
                        continue;

                    WshShell_Char_t groupRow[WSH_SHELL_CMD_GROUP_COUNT + 1];
                    WshShellStr_GroupBitsToStr(pcTargetCmd->Groups, WSH_SHELL_CMD_GROUP_COUNT,
                                               groupRow);

                    WSH_SHELL_PRINT(rowTemplate, pcTargetCmd->Name, pcTargetCmd->OptNum - 1,
                                    groupRow, pcTargetCmd->Descr);
                }
            } break;

            case WSH_SHELL_DEF_OPT_USER: {
                WSH_SHELL_PRINT("Availible users:\r\n");

                const WshShell_Size_t loginMaxLen  = WSH_SHELL_LOGIN_LEN;
                const WshShell_Size_t groupMaxLen  = WSH_SHELL_CMD_GROUP_COUNT + 3;
                const WshShell_Size_t rightsMaxLen = 6;

                WshShell_Char_t headTemplate[64];
                WSH_SHELL_SNPRINTF(headTemplate, sizeof(headTemplate),
                                   WSH_SHELL_COLOR_SYS
                                   "  %%-%ds %%-%ds %%-%ds\r\n" WSH_SHELL_ESC_RESET_STYLE,
                                   loginMaxLen, groupMaxLen, rightsMaxLen);

                WSH_SHELL_PRINT(headTemplate, "Login", "Groups", "Rights");

                WshShell_Char_t rowTemplate[64];
                WSH_SHELL_SNPRINTF(rowTemplate, sizeof(rowTemplate), "  %%-%ds %%-%ds %%-%ds\r\n",
                                   loginMaxLen, groupMaxLen, rightsMaxLen);

                const WshShell_Size_t usersNum = WshShellUser_GetUsersNum(&(pParentShell->Users));
                for (WshShell_Size_t user = 0; user < usersNum; user++) {
                    const WshShellUser_t* pcTargetUser =
                        WshShellUser_GetUserByIndex(&(pParentShell->Users), user);

                    if (pcTargetUser == NULL)
                        continue;

                    WshShell_Char_t groupRow[WSH_SHELL_CMD_GROUP_COUNT + 1];
                    WshShellStr_GroupBitsToStr(pcTargetUser->Groups, WSH_SHELL_CMD_GROUP_COUNT,
                                               groupRow);

                    WshShell_Char_t rightsRow[5];
                    WshShellStr_AccessBitsToStr(pcTargetUser->Rights, rightsRow);

                    WSH_SHELL_PRINT(rowTemplate, pcTargetUser->Login, groupRow, rightsRow);
                }
            } break;

            case WSH_SHELL_DEF_OPT_CLS: {
                WSH_SHELL_PRINT(WSH_SHELL_ECS_CLR_SCREEN);
            } break;

            case WSH_SHELL_DEF_OPT_HIST_CLEAR: {
                WshShellHistory_Flush(&(pParentShell->HistoryIO));
            } break;

            case WSH_SHELL_DEF_OPT_HIST_PRINT: {
                WshShell_Char_t cmdBuff[WSH_SHELL_INTR_BUFF_LEN];
                WshShell_Size_t cmdNum = WshShellHistory_GetTokenNum(&(pParentShell->HistoryIO));

                WSH_SHELL_PRINT("History len: %d\r\n", cmdNum);
                for (WshShell_Size_t cmdIdx = cmdNum; cmdIdx > 0; cmdIdx--) {
                    if (WshShellHistory_GetTokenByIndex(&(pParentShell->HistoryIO), cmdBuff,
                                                        sizeof(cmdBuff), cmdIdx - 1)) {
                        WSH_SHELL_PRINT("  hist[%2d]: %s\r\n", cmdNum - cmdIdx + 1, cmdBuff);
                    }
                }
            } break;

            case WSH_SHELL_DEF_OPT_DEAUTH: {
                WshShell_DeAuth(pParentShell, "command");
            } break;

            case WSH_SHELL_DEF_OPT_STR: {
                WshShell_Char_t optStr[WSH_SHELL_INTR_BUFF_LEN];
                WshShellCmd_GetOptValue(&optCtx, argc, pArgv, sizeof(optStr),
                                        (WshShell_Size_t*)optStr);
                WSH_SHELL_PRINT("Option (str): %s\r\n", optStr);
                break;
            }

            case WSH_SHELL_DEF_OPT_INT: {
                WshShell_Size_t optInt = 0;
                WshShellCmd_GetOptValue(&optCtx, argc, pArgv, sizeof(optInt),
                                        (WshShell_Size_t*)&optInt);
                WSH_SHELL_PRINT("Option (int): %d\r\n", optInt);
                break;
            }

            case WSH_SHELL_DEF_OPT_FLT: {
                WshShell_Float_t optFlt = 0.0f;
                WshShellCmd_GetOptValue(&optCtx, argc, pArgv, sizeof(optFlt),
                                        (WshShell_Size_t*)&optFlt);
                WSH_SHELL_PRINT("Option (float): %f\r\n", optFlt);
                break;
            }

            default: {
                retState = WSH_SHELL_RET_STATE_ERROR;
            } break;
        }
    }

    return retState;
}

static const WshShellCmd_t WshShellDefCmd = {
    .Groups  = WSH_SHELL_CMD_GROUP_ALL,
    .Name    = "def",
    .Descr   = "Default command for configuring and querying the shell interface",
    .Options = WshShell_OptArr,
    .OptNum  = WSH_SHELL_ARR_LEN(WshShell_OptArr),
    .Handler = WshShellCmdDef,
};

#else /* WSH_SHELL_DEF_COMMAND */

WSH_SHELL_RET_STATE_t WshShellCmdDef_Dummy(const WshShellCmd_t* pcCmd, WshShell_Size_t argc,
                                           const WshShell_Char_t* pArgv[], void* pShellCtx) {
    return WSH_SHELL_RET_STATE_ERR_EMPTY;
}

static const WshShellCmd_t WshShellDefCmd = {
    .Groups  = WSH_SHELL_CMD_GROUP_ALL,
    .Name    = "def",
    .Descr   = "",
    .Options = NULL,
    .OptNum  = 0,
    .Handler = WshShellCmdDef_Dummy,
};

#endif /* WSH_SHELL_DEF_COMMAND */

const WshShellCmd_t* WshShellDefCmd_GetPtr(void) {
    return &WshShellDefCmd;
}