/***************************************************************************** Prototype : cmd_reg_newcmdelement Description : 注册命令元素 Input : int cmd_elem_id char *cmd_name char *cmd_help Output : None Return Value : Calls : Called By : History : 1.Date : 2013/10/4 Author : weizengke Modification : Created function *****************************************************************************/ int cmd_reg_newcmdelement(int cmd_elem_id, CMD_ELEM_TYPE_EM cmd_elem_type, const char *cmd_name, const char *cmd_help) { /* BEGIN: Added by weizengke, 2013/10/4 PN:后续需要校验合法性 , 命名规范与变量名相似 */ g_cmd_elem[cmd_elem_id].para = (char*)malloc(strlen(cmd_name) + 1); if (g_cmd_elem[cmd_elem_id].para == NULL) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "malloc memory for para fail in regNewCmdElement."); return 1; } g_cmd_elem[cmd_elem_id].desc = (char*)malloc(strlen(cmd_help) + 1); if (g_cmd_elem[cmd_elem_id].desc == NULL) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "malloc memory for desc fail in regNewCmdElement."); free(g_cmd_elem[cmd_elem_id].para); return 1; } g_cmd_elem[cmd_elem_id].elem_id = cmd_elem_id; g_cmd_elem[cmd_elem_id].elem_tpye = cmd_elem_type; strcpy(g_cmd_elem[cmd_elem_id].para, cmd_name); strcpy(g_cmd_elem[cmd_elem_id].desc, cmd_help); debug_print_ex(CMD_DEBUG_TYPE_MSG, "cmd_reg_newcmdelement(%d %d %s %s) ok.", cmd_elem_id, cmd_elem_type, g_cmd_elem[cmd_elem_id].para, g_cmd_elem[cmd_elem_id].desc); return 0; }
void cmd_resolve_insert(struct cmd_vty *vty) { int i, size; // no more to insert if (vty->used_len >= vty->buf_len) return; size = vty->used_len - vty->cur_pos; debug_print_ex(CMD_DEBUG_TYPE_INFO,"\r\nused_len=%d, pos=%d\r\n",vty->used_len, vty->cur_pos); CMD_DBGASSERT(size >= 0, "cmd_resolve_insert"); memcpy(&vty->buffer[vty->cur_pos + 1], &vty->buffer[vty->cur_pos], size); vty->buffer[vty->cur_pos] = vty->c; #if 0 /* BEGIN: del by weizengke, 2013/11/17 */ /* BEGIN: Added by weizengke, 2013/10/4 PN:bug for continue tab */ vty->buffer[vty->cur_pos + 1] = '\0'; /* END: Added by weizengke, 2013/10/4 PN:None */ /* END: del by weizengke, 2013/11/17 */ #endif // print left chars, then back size for (i = 0; i < size + 1; i++) cmd_put_one(vty->buffer[vty->cur_pos + i]); for (i = 0; i < size; i++) cmd_back_one(); vty->cur_pos++; vty->used_len++; }
cmd_vector_t *cmd_vector_init(int size) { cmd_vector_t *v = (cmd_vector_t *)calloc(1, sizeof(struct cmd_vector)); if (v == NULL) { return NULL; } if (size == 0) { size = 1; } v->data = (void**)calloc(1, sizeof(void *) * size); if (v->data == NULL) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "In cmd_vector_init, Not Enough Memory For data"); free(v); return NULL; } v->used_size = 0; v->size = size; return v; }
/* vector */ int cmd_vector_fetch(cmd_vector_t *v) { int fetch_idx; for (fetch_idx = 0; fetch_idx < v->used_size; fetch_idx++) { if (v->data[fetch_idx] == NULL) { break; } } while (v->size < fetch_idx + 1) { v->data = (void**)realloc(v->data, sizeof(void *) * v->size * 2); if (!v->data) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "In cmd_vector_fetch, Not Enough Memory For data"); return -1; } memset(&v->data[v->size], 0, sizeof(void *) * v->size); v->size *= 2; } return fetch_idx; }
void cmd_read(struct cmd_vty *vty) { int key_type; g_InputMachine_prev = CMD_KEY_CODE_NOTCARE; g_InputMachine_now = CMD_KEY_CODE_NOTCARE; while ((vty->c = cmd_getch()) != EOF) { /* step 1: get input key type */ key_type = cmd_resolve(vty->c); g_InputMachine_now = key_type; if (key_type <= CMD_KEY_CODE_NONE || key_type > CMD_KEY_CODE_NOTCARE) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "Unidentify Key Type, c = %c, key_type = %d\n", vty->c, key_type); continue; } /* step 2: take actions according to input key */ key_resolver[key_type].key_func(vty); g_InputMachine_prev = g_InputMachine_now; if (g_InputMachine_now != CMD_KEY_CODE_TAB) { memset(g_tabString,0,sizeof(g_tabString)); memset(g_tabbingString,0,sizeof(g_tabbingString)); g_tabStringLenth = 0; } } }
int cmd_get_elem_by_name(char *cmd_name, struct para_desc *cmd_elem) { int i = 0; if (cmd_name == NULL || cmd_elem == NULL) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "In cmd_get_elem_by_name, param is null"); return 1; } for (i = 0; i < CMD_ELEM_ID_MAX; i++) { if ( g_cmd_elem[i].para == NULL) { continue; } if (0 == strcmp(cmd_name, g_cmd_elem[i].para)) { *cmd_elem = g_cmd_elem[i]; return 0; } } return 1; }
void install_element(struct cmd_elem_st *elem) { if (cmd_vec == NULL) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "Command Vector Not Exist"); exit(1); } debug_print_ex(CMD_DEBUG_TYPE_FUNC, "install_element, string(%s), doc(%s).", elem->string, elem->doc); cmd_vector_insert(cmd_vec, elem); elem->para_vec = cmd2vec(elem->string, elem->doc); elem->para_num = cmd_vector_max(elem->para_vec); debug_print_ex(CMD_DEBUG_TYPE_FUNC, "install_element ok, string(%s), generate para_num(%d). ", elem->string, elem->para_num); }
int cmd_get_elem_by_id(int cmd_elem_id, struct para_desc *cmd_elem) { if (cmd_elem == NULL) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "In cmd_get_elem_by_id, param is null"); return 1; } if (cmd_elem_id <= CMD_ELEM_ID_NONE || cmd_elem_id >= CMD_ELEM_ID_MAX) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "In cmd_get_elem_by_id, cmd_elem_id is invalid"); return 1; } *cmd_elem = g_cmd_elem[cmd_elem_id]; return 0; }
/* 检查字符串是不是只包含数字 */ int cmd_string_isdigit(char *string) { int i = 0; if (string == NULL) { return CMD_ERR; } for (i = 0; i < (int)strlen(string); i++) { if (!isdigit(*(string + i))) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "cmd_string_isdigit return error."); return CMD_ERR; } } debug_print_ex(CMD_DEBUG_TYPE_INFO, "cmd_string_isdigit return ok."); return CMD_OK; }
/* vty */ struct cmd_vty *cmd_vty_init() { struct cmd_vty *vty; vty = (struct cmd_vty *)calloc(1, sizeof(struct cmd_vty)); if(vty == NULL) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "In cmd_vty_init, Not Enough Memory For vty%s", CMD_ENTER); return NULL; } memcpy(vty->prompt, CMD_PROMPT_DEFAULT, sizeof(CMD_PROMPT_DEFAULT)); vty->prompt[strlen(CMD_PROMPT_DEFAULT)] = '\0'; vty->buf_len = CMD_BUFFER_SIZE; vty->used_len = vty->cur_pos = 0; vty->hpos = vty->hindex = 0; return vty; }
int cmd_get_elemid_by_name(int *cmd_elem_id, char *cmd_name) { int i = 0; if (cmd_elem_id == NULL || cmd_name == NULL) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "In cmd_get_elemid_by_name, param is null"); return 1; } for (i = 0; i < CMD_ELEM_ID_MAX; i++) { if (0 == strcmp(cmd_name, g_cmd_elem[i].para)) { *cmd_elem_id = i; return 0; } } return 1; }
/***************************************************************************** 函 数 名 : cmd_resolve_tab 功能描述 : 适配TAB键,命令补全 输入参数 : struct cmd_vty *vty 输出参数 : 无 返 回 值 : void 调用函数 : 被调函数 : 修改历史 : 1.日 期 : 2013年11月17日 作 者 : weizengke 修改内容 : 新生成函数 *****************************************************************************/ void cmd_resolve_tab(struct cmd_vty *vty) { int i; cmd_vector_t *v; struct para_desc *match[CMD_MAX_MATCH_SIZE] = {0}; // matched string int match_size = 0; int match_type = CMD_NO_MATCH; int isNeedMatch = 1; /* 非TAB场景(无空格),不需要匹配 */ char lcd_str[1024] = {0}; // if part match, then use this char *last_word = NULL; /* 1: 取pos 之前的buf 2: 需要覆盖当前光标后的buf */ /* BEGIN: Added by weizengke, 2013/11/17 bug for left and tab*/ memset(&(vty->buffer[vty->cur_pos]), 0 ,strlen(vty->buffer) - vty->cur_pos); vty->used_len = strlen(vty->buffer); /* END: Added by weizengke, 2013/11/17 */ if (g_InputMachine_prev == CMD_KEY_CODE_TAB) { cmd_delete_word(vty); cmd_insert_word(vty, g_tabbingString); } else { memset(g_tabString,0,sizeof(g_tabString)); g_tabStringLenth = 0; } v = str2vec(vty->buffer); if (v == NULL) { /* v = cmd_vector_init(1); cmd_vector_insert(v, '\0'); */ isNeedMatch = 0; } if (isspace((int)vty->buffer[vty->used_len - 1])) { isNeedMatch = 0; } if (1 == isNeedMatch && NULL != v) { match_type = cmd_match_command(v, vty, match, &match_size, lcd_str); last_word = (char*)cmd_vector_slot(v, cmd_vector_max(v) - 1); if (g_InputMachine_prev != CMD_KEY_CODE_TAB) { strcpy(g_tabbingString, last_word); } cmd_vector_deinit(v, 1); } cmd_outstring("%s", CMD_ENTER); switch (match_type) { case CMD_NO_MATCH: cmd_outprompt(vty->prompt); cmd_outstring("%s", vty->buffer); break; case CMD_FULL_MATCH: cmd_delete_word(vty); if (NULL != match[0]) { cmd_insert_word(vty, match[0]->para); } /* BEGIN: Added by weizengke, 2013/10/14 for full match then next input*/ cmd_insert_word(vty, " "); /* END: Added by weizengke, 2013/10/14 */ cmd_outprompt(vty->prompt); cmd_outstring("%s", vty->buffer); /* BEGIN: Added by weizengke, 2013/10/27 PN: fix the bug of CMD_FULL_MATCH and then continue TAB*/ memset(g_tabString,0,sizeof(g_tabString)); memset(g_tabbingString,0,sizeof(g_tabbingString)); g_tabStringLenth = 0; /* END: Added by weizengke, 2013/10/27 */ break; case CMD_PART_MATCH: /* delete at 2013-10-05, CMD_PART_MATCH will never reach, CMD_LIST_MATCH instead. case like this: disable , display >di TAB >dis ==> CMD_PART_MATCH */ cmd_delete_word(vty); cmd_insert_word(vty, lcd_str); cmd_outprompt(vty->prompt); cmd_outstring("%s", vty->buffer); break; case CMD_LIST_MATCH: if (g_InputMachine_prev != CMD_KEY_CODE_TAB) { memset(g_tabString,0,sizeof(g_tabString)); strcpy(g_tabString, match[0]->para); g_tabStringLenth = strlen(g_tabString); /* cmd_outstring("%s", CMD_ENTER); */ } else { for (i = 0; i < match_size; i++) { if (0 == strcmp(g_tabString, match[i]->para)) { break; } } if (i == match_size) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "TAB for completing command. bug of tab continue. (g_tabString=%s)", g_tabString); } i++; if (i == match_size) { i = 0; } memset(g_tabString,0,sizeof(g_tabString)); strcpy(g_tabString, match[i]->para); g_tabStringLenth = strlen(g_tabString); } /*for (i = 0; i < match_size; i++) { if (ANOTHER_LINE(i)) cmd_outstring("%s", CMD_ENTER); cmd_outstring("%-25s", match[i]->para); } */ cmd_delete_word(vty); cmd_insert_word(vty, g_tabString); cmd_outprompt(vty->prompt); cmd_outstring("%s", vty->buffer); break; default: break; } }
cmd_vector_t *cmd2vec(char *string, char *doc) { char *sp=NULL, *d_sp=NULL; char *cp = string; char *d_cp = doc; char *token=NULL, *d_token=NULL; int len, d_len; cmd_vector_t *allvec=NULL; struct para_desc *desc = NULL; struct para_desc *desc_cr = NULL; if(cp == NULL) { return NULL; } allvec = cmd_vector_init(1); while (1) { while(isspace((int) *cp) && *cp != '\0') { cp++; } if(*cp == '\0') { break; } sp = cp; while(!(isspace ((int) *cp) || *cp == '\r' || *cp == '\n') && *cp != '\0') { cp++; } len = cp - sp; token = (char*)malloc(len + 1); if (NULL == token) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "In cmd2vec, There is no memory for param token."); return NULL; } memcpy(token, sp, len); *(token + len) = '\0'; while(isspace((int)*d_cp) && *d_cp != '\0') { d_cp++; } if (*d_cp == '\0') { d_token = NULL; } else { d_sp = d_cp; while(!(*d_cp == '\r' || *d_cp == '\n') && *d_cp != '\0') { d_cp++; } d_len = d_cp - d_sp; d_token = (char*)malloc(d_len + 1); if (NULL == d_token) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "In cmd2vec, There is no memory for param d_token."); free(token); return NULL; } memcpy(d_token, d_sp, d_len); *(d_token + d_len) = '\0'; } desc = (struct para_desc *)calloc(1, sizeof(struct para_desc)); if (desc == NULL) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "In cmd2Vec, calloc for desc fail. (token=%s)", token); free(token); free(d_token); return NULL; } /* BEGIN: Added by weizengke, 2013/10/4 PN:for regCmdElem */ if (0 != cmd_get_elem_by_name(token, desc)) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "In cmd2Vec, cmd_get_elem_by_name fail. (token=%s)", token); free(token); free(d_token); free(desc); return NULL; } /* END: Added by weizengke, 2013/10/4 PN:None */ cmd_vector_insert(allvec, (void *)desc); } /* add <CR> into command vector */ desc_cr = (struct para_desc *)calloc(1, sizeof(struct para_desc)); if (desc_cr == NULL) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "In cmd2Vec, calloc for desc_cr fail. (token=%s)", token); cmd_vector_deinit(allvec, 1); return NULL; } /* BEGIN: Added by weizengke, 2013/10/4 PN:for regCmdElem */ if (0 != cmd_get_elem_by_name((char*)CMD_END, desc_cr)) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "In cmd2Vec, cmd_get_elem_by_name fail. (token=%s)", token); free(desc_cr); cmd_vector_deinit(allvec, 1); return NULL; } /* END: Added by weizengke, 2013/10/4 PN:None */ cmd_vector_insert(allvec, (void *)desc_cr); /* { struct para_desc *desc_ = NULL; for (int i = 0; i < cmd_vector_max(allvec); i++) { desc_ = (struct para_desc *)cmd_vector_slot(allvec, i); printf("cmd2vec + %s\n",(char*)desc_->para); } } */ return allvec; }
cmd_vector_t *str2vec(char *string) { int str_len; char *cur, *start, *token; cmd_vector_t *vec; // empty string if (string == NULL) { return NULL; } cur = string; // skip white spaces while (isspace((int) *cur) && *cur != '\0') { cur++; } // only white spaces if (*cur == '\0') { return NULL; } // copy each command pieces into vector vec = cmd_vector_init(1); while (1) { start = cur; while (!(isspace((int) *cur) || *cur == '\r' || *cur == '\n') && *cur != '\0') { cur++; } str_len = cur - start; token = (char *)malloc(sizeof(char) * (str_len + 1)); if (NULL == token) { debug_print_ex(CMD_DEBUG_TYPE_ERROR, "In str2vec, There is no memory for param token."); return NULL; } memcpy(token, start, str_len); *(token + str_len) = '\0'; cmd_vector_insert(vec, (void *)token); while((isspace ((int) *cur) || *cur == '\n' || *cur == '\r') && *cur != '\0') { cur++; } if (*cur == '\0') { return vec; } } }
/* Note: Added by weizengke, 2014/3/23 delete the last word at current pos from input buffer*/ void cmd_delete_word_ctrl_W_ex(struct cmd_vty *vty) { /* 删除光标所在当前或之前elem */ int start_pos = 0; int end_pos = 0; int len = strlen(vty->buffer); int pos = vty->cur_pos; debug_print_ex(CMD_DEBUG_TYPE_INFO, "\r\nctrl_W:cur_poscur_pos = %d buffer_len = %d \r\n", pos, len); if (pos == 0) { return; } /* ignore suffix-space */ if (vty->buffer[pos] == ' ' || vty->buffer[pos] == '\0') { end_pos = pos; pos--; /* 往回找第一个非空字符 */ while (pos >= 0 && vty->buffer[pos] == ' ') { pos--; } if (pos == 0) { return; } /* 继续往回找第一个空格或命令头 */ while (pos >= 0 && vty->buffer[pos] != ' ') { pos--; } start_pos = pos + 1; } else { /* 分别往左右找空格 */ pos++; while (vty->buffer[pos] != ' ') { /* BEGIN: Added by weizengke, 2014/4/5 当光标位于命令行最后一个元素中间,再执行CTRL+W,出现异常显示 https://github.com/weizengke/jungle/issues/2 */ if (vty->buffer[pos] == '\0') break; /* END: Added by weizengke, 2014/4/5 */ pos++; } /* BEGIN: Modified by weizengke, 2014/4/5 https://github.com/weizengke/jungle/issues/2 */ end_pos = pos; /* END: Modified by weizengke, 2014/4/5 */ pos = vty->cur_pos; while (vty->buffer[pos] != ' ') { pos--; } start_pos = pos + 1; } int len_last = strlen(&vty->buffer[end_pos]); memcpy(&vty->buffer[start_pos], &vty->buffer[end_pos], strlen(&vty->buffer[end_pos])); memset(&vty->buffer[start_pos + len_last], 0, sizeof(vty->buffer)-(start_pos + len_last)); vty->cur_pos -= (vty->cur_pos - start_pos); vty->used_len -= (end_pos - start_pos); debug_print_ex(CMD_DEBUG_TYPE_INFO, "\r\nctrl+w end:start_pos=%d end_pos=%d len_last=%d cur_pos=%d used_len=%d\r\n", start_pos,end_pos,len_last,vty->cur_pos, vty->used_len); }