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
|