346 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			346 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
#include <stdio.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <kwrap/type.h>
 | 
						|
#include <kwrap/cmdsys.h>
 | 
						|
#include <kwrap/task.h>
 | 
						|
#include <kwrap/debug.h>
 | 
						|
 | 
						|
#if !defined(__FREERTOS) && !defined(MODULE)
 | 
						|
#define LINUX_USERSPACE
 | 
						|
#endif
 | 
						|
 | 
						|
#if defined(LINUX_USERSPACE)
 | 
						|
#include <sys/ipc.h>
 | 
						|
#include <sys/msg.h>
 | 
						|
static key_t m_key= MAKEFOURCC('U','V','O','S'); //user space VOS
 | 
						|
#endif
 | 
						|
 | 
						|
#define MAX_ARGS 32
 | 
						|
 | 
						|
typedef struct _NVT_CMDSYS_DOMAIN {
 | 
						|
    char ch; ///< domain character
 | 
						|
    NVT_CMDSYS_CB cb; ///< domain running body
 | 
						|
} NVT_CMDSYS_DOMAIN;
 | 
						|
 | 
						|
static NVT_CMDSYS_DOMAIN m_domain[8] = {
 | 
						|
	{'>', nvt_cmdsys_runcmd},
 | 
						|
	{'\0', NULL},
 | 
						|
	{'\0', NULL},
 | 
						|
	{'\0', NULL},
 | 
						|
	{'\0', NULL},
 | 
						|
	{'\0', NULL},
 | 
						|
	{'\0', NULL},
 | 
						|
	{'\0', NULL},
 | 
						|
};
 | 
						|
 | 
						|
static NVT_CMDSYS_DOMAIN *mp_curr = &m_domain[0];
 | 
						|
 | 
						|
extern const char __MAINFUNCTAB_BEGIN__[] __attribute__((weak));
 | 
						|
extern const char __MAINFUNCTAB_END__[] __attribute__((weak));
 | 
						|
 | 
						|
static THREAD_HANDLE m_cmdsys_thread;
 | 
						|
 | 
						|
static int list_all_cmd(void)
 | 
						|
{
 | 
						|
    NVT_CMDSYS_ENTRY *t;
 | 
						|
    int cnt = 0;
 | 
						|
 | 
						|
    //printf("list command set: 0x%x-0x%x\n",(unsigned int)__MAINFUNCTAB_BEGIN__,(unsigned int)__MAINFUNCTAB_END__);
 | 
						|
 | 
						|
    for (t = (NVT_CMDSYS_ENTRY *)__MAINFUNCTAB_BEGIN__; t != (NVT_CMDSYS_ENTRY *)__MAINFUNCTAB_END__; t++)
 | 
						|
    {
 | 
						|
        //printf("%s: 0x%x\n", t->name, (unsigned int)t->p_main);
 | 
						|
        printf("%s\n", t->name);
 | 
						|
        cnt++;
 | 
						|
    }
 | 
						|
 | 
						|
    return cnt;
 | 
						|
}
 | 
						|
 | 
						|
static int parsecmd(char *cmdline, char **cmdname, char **cmdarg)
 | 
						|
{
 | 
						|
    char *pstr, *cmd, *pstrend;
 | 
						|
    char *arg;
 | 
						|
 | 
						|
    pstr = cmdline;
 | 
						|
    pstrend = cmdline + strlen(cmdline);
 | 
						|
    while (*pstr==' ' || *pstr=='\t' || *pstr=='\r' || *pstr=='\n') pstr++;
 | 
						|
    arg = strchr(pstr, ' ');
 | 
						|
    if (arg)
 | 
						|
    {
 | 
						|
        while (*arg==' ' || *arg=='\t' || *arg=='\r' || *arg=='\n') arg++;
 | 
						|
        *cmdarg = arg;
 | 
						|
    }
 | 
						|
    else
 | 
						|
        *cmdarg = pstrend;
 | 
						|
 | 
						|
    cmd = strtok (pstr," \t\n");
 | 
						|
 | 
						|
    if (!cmd)
 | 
						|
        return FALSE;
 | 
						|
    *cmdname = cmd;
 | 
						|
 | 
						|
    //printf("parsecmd: cmd=\"%s\", arg=\"%s\"\n", *cmdname, *cmdarg);
 | 
						|
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
static int run_func(char *name, NVT_CMDSYS_MAIN prun_func, char *args)
 | 
						|
{
 | 
						|
    int ret;
 | 
						|
    char *cmdLine;
 | 
						|
    int _argc = 0;
 | 
						|
    char *_argv[MAX_ARGS];
 | 
						|
    char *param;
 | 
						|
 | 
						|
    cmdLine = strdup(args);
 | 
						|
 | 
						|
	if (cmdLine == NULL) {
 | 
						|
		printf("cmdsys failed to strdup.\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
    param = strtok(cmdLine, " \t\n");
 | 
						|
    _argv[_argc++] = name;
 | 
						|
    while (param && _argc < MAX_ARGS) {
 | 
						|
        _argv[_argc++] = param;
 | 
						|
        param = strtok(NULL, " \t\n");
 | 
						|
    }
 | 
						|
 | 
						|
	if (_argc < MAX_ARGS) {
 | 
						|
	    _argv[_argc] = NULL;
 | 
						|
	}
 | 
						|
 | 
						|
    ret = prun_func(_argc, _argv);
 | 
						|
 | 
						|
    free(cmdLine);
 | 
						|
 | 
						|
    return ret;
 | 
						|
}
 | 
						|
 | 
						|
static int find_and_runcmd(char *cmdname, char *cmdarg)
 | 
						|
{
 | 
						|
    NVT_CMDSYS_ENTRY *t;
 | 
						|
 | 
						|
    for (t = (NVT_CMDSYS_ENTRY *)__MAINFUNCTAB_BEGIN__; t != (NVT_CMDSYS_ENTRY *)__MAINFUNCTAB_END__; t++)
 | 
						|
    {
 | 
						|
        if (strcmp(cmdname, t->name) == 0)
 | 
						|
        {
 | 
						|
            run_func(cmdname, t->p_main, cmdarg);
 | 
						|
            return TRUE;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
int nvt_cmdsys_runcmd(char *str)
 | 
						|
{
 | 
						|
    int err = -1;
 | 
						|
    char *cmdstr, *cmdname, *cmdarg;
 | 
						|
 | 
						|
    if (str[0] == '?' || strncmp(str, "ls", 3) == 0) {
 | 
						|
        list_all_cmd();
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    cmdstr = strdup(str);
 | 
						|
	if (cmdstr == NULL) {
 | 
						|
		printf("cmdsys failed to strdup.\n");
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
    if (parsecmd(cmdstr,&cmdname, &cmdarg))
 | 
						|
    {
 | 
						|
        if (find_and_runcmd(cmdname, cmdarg))
 | 
						|
        {
 | 
						|
              err = 1;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            printf("parsecmd: cmd=\"%s\", arg=\"%s\"\n", cmdname, cmdarg);
 | 
						|
            printf("command not found!\n");
 | 
						|
              err = 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    free(cmdstr);
 | 
						|
    return err;
 | 
						|
}
 | 
						|
 | 
						|
static NVT_CMDSYS_DOMAIN *nvt_cmdys_switch(char ch)
 | 
						|
{
 | 
						|
	size_t i;
 | 
						|
	for (i = 0; i < sizeof(m_domain)/sizeof(m_domain[0]); i++) {
 | 
						|
		if (m_domain[i].ch == 0) {
 | 
						|
			break;
 | 
						|
		} else if (m_domain[i].ch == ch) {
 | 
						|
			return &m_domain[i];
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return NULL;
 | 
						|
}
 | 
						|
 | 
						|
static char gbuf[512] = {0};
 | 
						|
static THREAD_DECLARE(nvt_cmdsys_tsk, p_param)
 | 
						|
{
 | 
						|
#if defined(LINUX_USERSPACE)
 | 
						|
    int msqid;
 | 
						|
    char *buf = &gbuf[sizeof(long)];
 | 
						|
 | 
						|
    if ((msqid = msgget(m_key, IPC_CREAT | 0666)) < 0) {
 | 
						|
		fprintf(stderr, "nvt_cmdys: msgget failed\n");
 | 
						|
        THREAD_RETURN(-1);
 | 
						|
	}
 | 
						|
#else
 | 
						|
    char *buf = &gbuf[0];
 | 
						|
#endif
 | 
						|
 | 
						|
	//coverity[no_escape]
 | 
						|
	while (1) {
 | 
						|
        size_t i;
 | 
						|
#if defined(LINUX_USERSPACE)
 | 
						|
        //mtype is long, but we keep 8 bytes alive for coverity
 | 
						|
        if (msgrcv(msqid, gbuf, sizeof(gbuf)-8, 1, 0) < 0) {
 | 
						|
			printf("nvt_cmdys: msgrcv failed.\r\n");
 | 
						|
			THREAD_RETURN(-1);
 | 
						|
		}
 | 
						|
#else
 | 
						|
        printf("%c ", mp_curr->ch);
 | 
						|
	    fgets(gbuf, sizeof(gbuf), stdin);
 | 
						|
#endif
 | 
						|
        char *p_proc = &buf[0];
 | 
						|
        // removing \r\n and processing backspace
 | 
						|
        for(i = 0; i < strlen(buf) ; i++) {
 | 
						|
            if (buf[i] == '\r' || buf[i] == '\n') {
 | 
						|
                *p_proc = '\0';
 | 
						|
                break;
 | 
						|
            }
 | 
						|
            if (buf[i] == '\b') {
 | 
						|
                if(p_proc > &buf[0]) {
 | 
						|
                    p_proc--;
 | 
						|
                }
 | 
						|
            } else {
 | 
						|
                *p_proc++ = buf[i];
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
		//check domain change
 | 
						|
		if (strlen(buf) == 1) {
 | 
						|
			NVT_CMDSYS_DOMAIN *p_new = nvt_cmdys_switch(buf[0]);
 | 
						|
			if (p_new) {
 | 
						|
				mp_curr = p_new;
 | 
						|
				printf("switch to '%c'\n", mp_curr->ch);
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
        if (strlen(buf) > 0) {
 | 
						|
	        printf("run: %s\n", buf);
 | 
						|
            mp_curr->cb(buf);
 | 
						|
        }
 | 
						|
	}
 | 
						|
 | 
						|
    THREAD_RETURN(-1);
 | 
						|
}
 | 
						|
 | 
						|
int nvt_cmdsys_init(void)
 | 
						|
{
 | 
						|
    m_cmdsys_thread = vos_task_create(nvt_cmdsys_tsk, NULL, "nvt_cmdsys_tsk", 2, 16*1024);
 | 
						|
    vos_task_resume(m_cmdsys_thread);
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
int nvt_cmdsys_regsys(char domain, NVT_CMDSYS_CB cb)
 | 
						|
{
 | 
						|
	size_t i;
 | 
						|
 | 
						|
	for (i = 0; i < sizeof(m_domain)/sizeof(m_domain[0]); i++) {
 | 
						|
		if (m_domain[i].ch == 0) {
 | 
						|
			m_domain[i].ch = domain;
 | 
						|
			m_domain[i].cb = cb;
 | 
						|
			return 0;
 | 
						|
		} else if (m_domain[i].ch == domain) {
 | 
						|
			m_domain[i].cb = cb;
 | 
						|
			return 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	printf("nvt_cmdsys_regsys is full.\n");
 | 
						|
	return -1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#if !defined(__FREERTOS) && !defined(MODULE)
 | 
						|
 | 
						|
static int nvt_cmdsys_calc_flat_cmd(char *p_flat, int flat_len, int argc, char **argv)
 | 
						|
{
 | 
						|
    int i;
 | 
						|
    int sum = 0;
 | 
						|
 | 
						|
    for(i = 1; i < argc; i++) {
 | 
						|
        sum += strlen(argv[i]) + 1; // +1 is for space or eof
 | 
						|
    }
 | 
						|
 | 
						|
    if (p_flat == NULL) {
 | 
						|
        return sum; // just calc size
 | 
						|
    }
 | 
						|
 | 
						|
    memset(p_flat, 0, flat_len);
 | 
						|
    for(i = 1; i < argc; i++) {
 | 
						|
        strncat(p_flat, argv[i], flat_len);
 | 
						|
        flat_len -= strlen(argv[i]);
 | 
						|
        if (flat_len <= 0) {
 | 
						|
            fprintf(stderr, "nvt_cmdsys: flat_len is too small.\n");
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
        if (i < argc-1) {
 | 
						|
            strncat(p_flat, " ", flat_len);
 | 
						|
            flat_len -= 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    return sum;
 | 
						|
}
 | 
						|
 | 
						|
int nvt_cmdsys_ipc_cmd(int argc, char **argv)
 | 
						|
{
 | 
						|
    int msqid = msgget(m_key, 0666);
 | 
						|
	if (msqid < 0) {
 | 
						|
		//fprintf(stderr, "program may not start.\n");
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
    int flat_cmd_len = nvt_cmdsys_calc_flat_cmd(NULL, 0, argc, argv);
 | 
						|
    if (flat_cmd_len <= 0) {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    //mtype is long, but we keep 8 bytes alive for coverity
 | 
						|
    int alloc_size = flat_cmd_len+8;
 | 
						|
    char *p_cmd = (char *)malloc(alloc_size);
 | 
						|
 | 
						|
    if (p_cmd == NULL) {
 | 
						|
        fprintf(stderr, "nvt_cmdsys: no mem.\n");
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    *(long *)p_cmd = 1; //mtype = 1
 | 
						|
    if (nvt_cmdsys_calc_flat_cmd(p_cmd+sizeof(long), flat_cmd_len, argc, argv) <= 0) {
 | 
						|
        free(p_cmd);
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
 | 
						|
    //the size is string len exclude mtype
 | 
						|
    int er = msgsnd(msqid, p_cmd, flat_cmd_len, 0);
 | 
						|
	if (er < 0) {
 | 
						|
		fprintf(stderr, "nvt_cmdsys: failed to send command, er=%d.\n", er);
 | 
						|
        free(p_cmd);
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
    free(p_cmd);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |