📄 vty.c
字号:
vty_backward_char (vty); vty_delete_char (vty);}/* Kill rest of line from current point. */static voidvty_kill_line (struct vty *vty){ int i; int size; size = vty->length - vty->cp; if (size == 0) return; for (i = 0; i < size; i++) vty_write (vty, &telnet_space_char, 1); for (i = 0; i < size; i++) vty_write (vty, &telnet_backward_char, 1); memset (&vty->buf[vty->cp], 0, size); vty->length = vty->cp;}/* Kill line from the beginning. */static voidvty_kill_line_from_beginning (struct vty *vty){ vty_beginning_of_line (vty); vty_kill_line (vty);}/* Delete a word before the point. */static voidvty_forward_kill_word (struct vty *vty){ while (vty->cp != vty->length && vty->buf[vty->cp] == ' ') vty_delete_char (vty); while (vty->cp != vty->length && vty->buf[vty->cp] != ' ') vty_delete_char (vty);}/* Delete a word before the point. */static voidvty_backward_kill_word (struct vty *vty){ while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ') vty_delete_backward_char (vty); while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ') vty_delete_backward_char (vty);}/* Transpose chars before or at the point. */static voidvty_transpose_chars (struct vty *vty){ char c1, c2; /* If length is short or point is near by the beginning of line then return. */ if (vty->length < 2 || vty->cp < 1) return; /* In case of point is located at the end of the line. */ if (vty->cp == vty->length) { c1 = vty->buf[vty->cp - 1]; c2 = vty->buf[vty->cp - 2]; vty_backward_char (vty); vty_backward_char (vty); vty_self_insert_overwrite (vty, c1); vty_self_insert_overwrite (vty, c2); } else { c1 = vty->buf[vty->cp]; c2 = vty->buf[vty->cp - 1]; vty_backward_char (vty); vty_self_insert_overwrite (vty, c1); vty_self_insert_overwrite (vty, c2); }}/* Do completion at vty interface. */static voidvty_complete_command (struct vty *vty){ int i; int ret; char **matched = NULL; vector vline; if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE) return; vline = cmd_make_strvec (vty->buf); if (vline == NULL) return; /* In case of 'help \t'. */ if (isspace ((int) vty->buf[vty->length - 1])) vector_set (vline, '\0'); matched = cmd_complete_command (vline, vty, &ret); cmd_free_strvec (vline); vty_out (vty, "%s", VTY_NEWLINE); switch (ret) { case CMD_ERR_AMBIGUOUS: vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE); vty_prompt (vty); vty_redraw_line (vty); break; case CMD_ERR_NO_MATCH: /* vty_out (vty, "%% There is no matched command.%s", VTY_NEWLINE); */ vty_prompt (vty); vty_redraw_line (vty); break; case CMD_COMPLETE_FULL_MATCH: vty_prompt (vty); vty_redraw_line (vty); vty_backward_pure_word (vty); vty_insert_word_overwrite (vty, matched[0]); vty_self_insert (vty, ' '); XFREE (MTYPE_TMP, matched[0]); break; case CMD_COMPLETE_MATCH: vty_prompt (vty); vty_redraw_line (vty); vty_backward_pure_word (vty); vty_insert_word_overwrite (vty, matched[0]); XFREE (MTYPE_TMP, matched[0]); vector_only_index_free (matched); return; break; case CMD_COMPLETE_LIST_MATCH: for (i = 0; matched[i] != NULL; i++) { if (i != 0 && ((i % 6) == 0)) vty_out (vty, "%s", VTY_NEWLINE); vty_out (vty, "%-10s ", matched[i]); XFREE (MTYPE_TMP, matched[i]); } vty_out (vty, "%s", VTY_NEWLINE); vty_prompt (vty); vty_redraw_line (vty); break; case CMD_ERR_NOTHING_TODO: vty_prompt (vty); vty_redraw_line (vty); break; default: break; } if (matched) vector_only_index_free (matched);}voidvty_describe_fold (struct vty *vty, int cmd_width, int desc_width, struct desc *desc){ char *buf, *cmd, *p; int pos; cmd = desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd; if (desc_width <= 0) { vty_out (vty, " %-*s %s%s", cmd_width, cmd, desc->str, VTY_NEWLINE); return; } buf = XCALLOC (MTYPE_TMP, strlen (desc->str) + 1); for (p = desc->str; strlen (p) > desc_width; p += pos + 1) { for (pos = desc_width; pos > 0; pos--) if (*(p + pos) == ' ') break; if (pos == 0) break; strncpy (buf, p, pos); buf[pos] = '\0'; vty_out (vty, " %-*s %s%s", cmd_width, cmd, buf, VTY_NEWLINE); cmd = ""; } vty_out (vty, " %-*s %s%s", cmd_width, cmd, p, VTY_NEWLINE); XFREE (MTYPE_TMP, buf);}/* Describe matched command function. */static voidvty_describe_command (struct vty *vty){ int ret; vector vline; vector describe; int i, width, desc_width; struct desc *desc, *desc_cr = NULL; vline = cmd_make_strvec (vty->buf); /* In case of '> ?'. */ if (vline == NULL) { vline = vector_init (1); vector_set (vline, '\0'); } else if (isspace ((int) vty->buf[vty->length - 1])) vector_set (vline, '\0'); describe = cmd_describe_command (vline, vty, &ret); vty_out (vty, "%s", VTY_NEWLINE); /* Ambiguous error. */ switch (ret) { case CMD_ERR_AMBIGUOUS: cmd_free_strvec (vline); vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE); vty_prompt (vty); vty_redraw_line (vty); return; break; case CMD_ERR_NO_MATCH: cmd_free_strvec (vline); vty_out (vty, "%% There is no matched command.%s", VTY_NEWLINE); vty_prompt (vty); vty_redraw_line (vty); return; break; } /* Get width of command string. */ width = 0; for (i = 0; i < vector_max (describe); i++) if ((desc = vector_slot (describe, i)) != NULL) { int len; if (desc->cmd[0] == '\0') continue; len = strlen (desc->cmd); if (desc->cmd[0] == '.') len--; if (width < len) width = len; } /* Get width of description string. */ desc_width = vty->width - (width + 6); /* Print out description. */ for (i = 0; i < vector_max (describe); i++) if ((desc = vector_slot (describe, i)) != NULL) { if (desc->cmd[0] == '\0') continue; if (strcmp (desc->cmd, "<cr>") == 0) { desc_cr = desc; continue; } if (!desc->str) vty_out (vty, " %-s%s", desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd, VTY_NEWLINE); else if (desc_width >= strlen (desc->str)) vty_out (vty, " %-*s %s%s", width, desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd, desc->str, VTY_NEWLINE); else vty_describe_fold (vty, width, desc_width, desc);#if 0 vty_out (vty, " %-*s %s%s", width desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd, desc->str ? desc->str : "", VTY_NEWLINE);#endif /* 0 */ } if ((desc = desc_cr)) { if (!desc->str) vty_out (vty, " %-s%s", desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd, VTY_NEWLINE); else if (desc_width >= strlen (desc->str)) vty_out (vty, " %-*s %s%s", width, desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd, desc->str, VTY_NEWLINE); else vty_describe_fold (vty, width, desc_width, desc); } cmd_free_strvec (vline); vector_free (describe); vty_prompt (vty); vty_redraw_line (vty);}voidvty_clear_buf (struct vty *vty){ memset (vty->buf, 0, vty->max);}/* ^C stop current input and do not add command line to the history. */static voidvty_stop_input (struct vty *vty){ vty->cp = vty->length = 0; vty_clear_buf (vty); vty_out (vty, "%s", VTY_NEWLINE); switch (vty->node) { case VIEW_NODE: case ENABLE_NODE: /* Nothing to do. */ break; case CONFIG_NODE: case INTERFACE_NODE: case ZEBRA_NODE: case RIP_NODE: case RIPNG_NODE: case BGP_NODE: case RMAP_NODE: case OSPF_NODE: case OSPF6_NODE: case KEYCHAIN_NODE: case KEYCHAIN_KEY_NODE: case MASC_NODE: case VTY_NODE: vty_config_unlock (vty); vty->node = ENABLE_NODE; break; default: /* Unknown node, we have to ignore it. */ break; } vty_prompt (vty); /* Set history pointer to the latest one. */ vty->hp = vty->hindex;}/* Add current command line to the history buffer. */static voidvty_hist_add (struct vty *vty){ int index; if (vty->length == 0) return; index = vty->hindex ? vty->hindex - 1 : VTY_MAXHIST - 1; /* Ignore the same string as previous one. */ if (vty->hist[index]) if (strcmp (vty->buf, vty->hist[index]) == 0) { vty->hp = vty->hindex; return; } /* Insert history entry. */ if (vty->hist[vty->hindex]) XFREE (MTYPE_VTY_HIST, vty->hist[vty->hindex]); vty->hist[vty->hindex] = XSTRDUP (MTYPE_VTY_HIST, vty->buf); /* History index rotation. */ vty->hindex++; if (vty->hindex == VTY_MAXHIST) vty->hindex = 0; vty->hp = vty->hindex;}/* #define TELNET_OPTION_DEBUG *//* Get telnet window size. */static intvty_telnet_option (struct vty *vty, unsigned char *buf, int nbytes){#ifdef TELNET_OPTION_DEBUG int i; for (i = 0; i < nbytes; i++) { switch (buf[i]) { case IAC: vty_out (vty, "IAC "); break; case WILL: vty_out (vty, "WILL "); break; case WONT: vty_out (vty, "WONT "); break; case DO: vty_out (vty, "DO "); break; case DONT: vty_out (vty, "DONT "); break; case SB: vty_out (vty, "SB "); break; case SE: vty_out (vty, "SE "); break; case TELOPT_ECHO: vty_out (vty, "TELOPT_ECHO %s", VTY_NEWLINE); break; case TELOPT_SGA: vty_out (vty, "TELOPT_SGA %s", VTY_NEWLINE); break; case TELOPT_NAWS: vty_out (vty, "TELOPT_NAWS %s", VTY_NEWLINE); break; default: vty_out (vty, "%x ", buf[i]); break; } } vty_out (vty, "%s", VTY_NEWLINE);#endif /* TELNET_OPTION_DEBUG */ switch (buf[0]) { case SB: buffer_reset(vty->sb_buffer); vty->iac_sb_in_progress = 1; return 0; break; case SE: { char *buffer; int length; if (!vty->iac_sb_in_progress) return 0; buffer = (char *)vty->sb_buffer->head->data; length = vty->sb_buffer->length; if (buffer == NULL) return 0; if (buffer[0] == '\0') { vty->iac_sb_in_progress = 0; return 0; } switch (buffer[0]) { case TELOPT_NAWS: if (length < 5) break; vty->width = buffer[2]; vty->height = vty->lines >= 0 ? vty->lines : buffer[4]; break; } vty->iac_sb_in_progress = 0; return 0; break; } default: break; } return 1;}/* Execute current command line. */static intvty_execute (struct vty *vty){ int ret; ret = CMD_SUCCESS; switch (vty->node) { case AUTH_NODE: case AUTH_ENABLE_NODE: vty_auth (vty, vty->buf); break; default: ret = vty_command (vty, vty->buf); if (vty->type == VTY_TERM) vty_hist_add (vty); break; } /* Clear command line buffer. */ vty->cp = vty->length = 0; vty_clear_buf (vty); if (vty->status != VTY_CLOSE && vty->status != VTY_START && vty->status != VTY_CONTINUE) vty_prompt (vty); return ret;}#define CONTROL(X) ((X) - '@')#define VTY_NORMAL 0#define VTY_PRE_ESCAPE 1#define VTY_ESCAPE 2/* Escape character command map. */static voidvty_escape_map (unsigned char c, struct vty *vty){ switch (c) { case ('A'): vty_previous_line (vty); break; case ('B'): vty_next_line (vty); break; case ('C'): vty_forward_char (vty); break; case ('D'): vty_backward_char (vty); break; default: break; } /* Go back to normal mode. */ vty->escape = VTY_NORMAL;}/* Quit print out to the buffer. */static voidvty_buffer_reset (struct vty *vty){ buffer_reset (vty->obuf); vty_prompt (vty); vty_redraw_line (vty);}/* Read data via vty socket. */static intvty_read (struct thread *thread){ int i; int ret; int nbytes; unsigned char buf[VTY_READ_BUFSIZ]; int vty_sock = THREAD_FD (thread); struct vty *vty = THREAD_ARG (thread); vty->t_read = NULL; /* Read raw data from socket */ nbytes = read (vty->fd, buf, VTY_READ_BUFSIZ); if (nbytes <= 0) vty->status = VTY_CLOSE; for (i = 0; i < nbytes; i++) { if (buf[i] == IAC) { if (!vty->iac) { vty->iac = 1; continue; } else { vty->iac = 0; } } if (vty->iac_sb_in_progress && !vty->iac) { buffer_putc(vty->sb_buffer, buf[i]); continue; } if (vty->iac) { /* In case of telnet command */ ret = vty_telnet_option (vty, buf + i, nbytes - i); vty->iac = 0; i += ret; continue; } if (vty->status == VTY_MORE) { switch (buf[i]) { case CONTROL('C'): case 'q': case 'Q': if (vty->output_func) (*vty->output_func) (vty, 1); vty_buffer_reset (vty); break;#if 0 /* More line does not work for "show ip bgp". */ case '\n': case '\r': vty->status = VTY_MORELINE; break;#endif default: if (vty->output_func) (*vty->output_func) (vty, 0); break; } continue; } /* Escape character. */ if (vty->escape == VTY_ESCAPE) { vty_escape_map (buf[i], vty); continue; } /* Pre-escape status. */ if (vty->escape == VTY_PRE_ESCAPE) { switch (buf[i]) { case '[': vty->escape = VTY_ESCAPE; break; case 'b': vty_backward_word (vty); vty->escape = VTY_NORMAL; break; case 'f': vty_forward_word (vty); vty->escape = VTY_NORMAL; break; case 'd': vty_forward_kill_word (vty); vty->escape = VTY_NORMAL; break; case CONTROL('H'): case 0x7f: vty_backward_kill_word (vty); vty->escape = VTY_NORMAL; break; default: vty->escape = VTY_NORMAL; break; } continue; } switch (buf[i]) { case CONTROL('A'): vty_beginning_of_line (vty); break; case CONTROL('B'): vty_backward_char (vty); break; case CONTROL('C'): vty_stop_input (vty); break; case CONTROL('D'): vty_delete_char (vty); break; case CONTROL('E'): vty_end_of_line (vty); break; case CONTROL('F'): vty_forward_char (vty); break; case CONTROL('H'): case 0x7f: vty_delete_backward_char (vty);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -