--- embedaddon/quagga/lib/vty.c 2013/07/21 23:54:39 1.1.1.3 +++ embedaddon/quagga/lib/vty.c 2016/11/02 10:09:10 1.1.1.4 @@ -38,6 +38,7 @@ #include "network.h" #include +#include /* Vty events */ enum event @@ -57,7 +58,7 @@ static void vty_event (enum event, int, struct vty *); /* Extern host structure from command.c */ extern struct host host; - + /* Vector which store each vty structure. */ static vector vtyvec; @@ -71,7 +72,7 @@ static char *vty_accesslist_name = NULL; static char *vty_ipv6_accesslist_name = NULL; /* VTY server thread. */ -vector Vvty_serv_thread; +static vector Vvty_serv_thread; /* Current directory. */ char *vty_cwd = NULL; @@ -89,7 +90,7 @@ static u_char restricted_mode = 0; /* Integrated configuration file path */ char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG; - + /* VTY standard output function. */ int vty_out (struct vty *vty, const char *format, ...) @@ -110,7 +111,7 @@ vty_out (struct vty *vty, const char *format, ...) { /* Try to write to initial buffer. */ va_start (args, format); - len = vsnprintf (buf, sizeof buf, format, args); + len = vsnprintf (buf, sizeof(buf), format, args); va_end (args); /* Initial buffer is not enough. */ @@ -184,7 +185,7 @@ vty_log_out (struct vty *vty, const char *level, const buf[len++] = '\r'; buf[len++] = '\n'; - if (write(vty->fd, buf, len) < 0) + if (write(vty->wfd, buf, len) < 0) { if (ERRNO_IO_RETRY(errno)) /* Kernel buffer is full, probably too much debugging output, so just @@ -400,7 +401,41 @@ vty_command (struct vty *vty, char *buf) int ret; vector vline; const char *protocolname; + char *cp; + /* + * Log non empty command lines + */ + cp = buf; + if (cp != NULL) + { + /* Skip white spaces. */ + while (isspace ((int) *cp) && *cp != '\0') + cp++; + } + if (cp != NULL && *cp != '\0') + { + unsigned i; + char vty_str[VTY_BUFSIZ]; + char prompt_str[VTY_BUFSIZ]; + + /* format the base vty info */ + snprintf(vty_str, sizeof(vty_str), "vty[??]@%s", vty->address); + if (vty) + for (i = 0; i < vector_active (vtyvec); i++) + if ((vty == vector_slot (vtyvec, i))) + { + snprintf(vty_str, sizeof(vty_str), "vty[%d]@%s", + i, vty->address); + break; + } + + /* format the prompt */ + snprintf(prompt_str, sizeof(prompt_str), cmd_prompt (vty->node), vty_str); + + /* now log the command */ + zlog(NULL, LOG_NOTICE, "%s%s", prompt_str, buf); + } /* Split readline string up into the vector */ vline = cmd_make_strvec (buf); @@ -455,7 +490,7 @@ vty_command (struct vty *vty, char *buf) return ret; } - + static const char telnet_backward_char = 0x08; static const char telnet_space_char = ' '; @@ -702,6 +737,9 @@ vty_end_config (struct vty *vty) case BABEL_NODE: case BGP_NODE: case BGP_VPNV4_NODE: + case BGP_VPNV6_NODE: + case BGP_ENCAP_NODE: + case BGP_ENCAPV6_NODE: case BGP_IPV4_NODE: case BGP_IPV4M_NODE: case BGP_IPV6_NODE: @@ -713,6 +751,7 @@ vty_end_config (struct vty *vty) case KEYCHAIN_NODE: case KEYCHAIN_KEY_NODE: case MASC_NODE: + case PIM_NODE: case VTY_NODE: vty_config_unlock (vty); vty->node = ENABLE_NODE; @@ -869,9 +908,9 @@ vty_complete_command (struct vty *vty) /* In case of 'help \t'. */ if (isspace ((int) vty->buf[vty->length - 1])) - vector_set (vline, '\0'); + vector_set (vline, NULL); - matched = cmd_complete_command (vline, vty, &ret); + matched = cmd_complete_command_lib (vline, vty, &ret, 1); cmd_free_strvec (vline); @@ -931,23 +970,23 @@ vty_complete_command (struct vty *vty) static void vty_describe_fold (struct vty *vty, int cmd_width, - unsigned int desc_width, struct desc *desc) + unsigned int desc_width, struct cmd_token *token) { char *buf; const char *cmd, *p; int pos; - cmd = desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd; + cmd = token->cmd[0] == '.' ? token->cmd + 1 : token->cmd; if (desc_width <= 0) { - vty_out (vty, " %-*s %s%s", cmd_width, cmd, desc->str, VTY_NEWLINE); + vty_out (vty, " %-*s %s%s", cmd_width, cmd, token->desc, VTY_NEWLINE); return; } - buf = XCALLOC (MTYPE_TMP, strlen (desc->str) + 1); + buf = XCALLOC (MTYPE_TMP, strlen (token->desc) + 1); - for (p = desc->str; strlen (p) > desc_width; p += pos + 1) + for (p = token->desc; strlen (p) > desc_width; p += pos + 1) { for (pos = desc_width; pos > 0; pos--) if (*(p + pos) == ' ') @@ -976,7 +1015,7 @@ vty_describe_command (struct vty *vty) vector vline; vector describe; unsigned int i, width, desc_width; - struct desc *desc, *desc_cr = NULL; + struct cmd_token *token, *token_cr = NULL; vline = cmd_make_strvec (vty->buf); @@ -984,11 +1023,11 @@ vty_describe_command (struct vty *vty) if (vline == NULL) { vline = vector_init (1); - vector_set (vline, '\0'); + vector_set (vline, NULL); } else if (isspace ((int) vty->buf[vty->length - 1])) - vector_set (vline, '\0'); + vector_set (vline, NULL); describe = cmd_describe_command (vline, vty, &ret); @@ -1010,15 +1049,15 @@ vty_describe_command (struct vty *vty) /* Get width of command string. */ width = 0; for (i = 0; i < vector_active (describe); i++) - if ((desc = vector_slot (describe, i)) != NULL) + if ((token = vector_slot (describe, i)) != NULL) { unsigned int len; - if (desc->cmd[0] == '\0') + if (token->cmd[0] == '\0') continue; - len = strlen (desc->cmd); - if (desc->cmd[0] == '.') + len = strlen (token->cmd); + if (token->cmd[0] == '.') len--; if (width < len) @@ -1030,27 +1069,27 @@ vty_describe_command (struct vty *vty) /* Print out description. */ for (i = 0; i < vector_active (describe); i++) - if ((desc = vector_slot (describe, i)) != NULL) + if ((token = vector_slot (describe, i)) != NULL) { - if (desc->cmd[0] == '\0') + if (token->cmd[0] == '\0') continue; - if (strcmp (desc->cmd, command_cr) == 0) + if (strcmp (token->cmd, command_cr) == 0) { - desc_cr = desc; + token_cr = token; continue; } - if (!desc->str) + if (!token->desc) vty_out (vty, " %-s%s", - desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd, + token->cmd[0] == '.' ? token->cmd + 1 : token->cmd, VTY_NEWLINE); - else if (desc_width >= strlen (desc->str)) + else if (desc_width >= strlen (token->desc)) vty_out (vty, " %-*s %s%s", width, - desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd, - desc->str, VTY_NEWLINE); + token->cmd[0] == '.' ? token->cmd + 1 : token->cmd, + token->desc, VTY_NEWLINE); else - vty_describe_fold (vty, width, desc_width, desc); + vty_describe_fold (vty, width, desc_width, token); #if 0 vty_out (vty, " %-*s %s%s", width @@ -1059,18 +1098,18 @@ vty_describe_command (struct vty *vty) #endif /* 0 */ } - if ((desc = desc_cr)) + if ((token = token_cr)) { - if (!desc->str) + if (!token->desc) vty_out (vty, " %-s%s", - desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd, + token->cmd[0] == '.' ? token->cmd + 1 : token->cmd, VTY_NEWLINE); - else if (desc_width >= strlen (desc->str)) + else if (desc_width >= strlen (token->desc)) vty_out (vty, " %-*s %s%s", width, - desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd, - desc->str, VTY_NEWLINE); + token->cmd[0] == '.' ? token->cmd + 1 : token->cmd, + token->desc, VTY_NEWLINE); else - vty_describe_fold (vty, width, desc_width, desc); + vty_describe_fold (vty, width, desc_width, token); } out: @@ -1117,6 +1156,7 @@ vty_stop_input (struct vty *vty) case KEYCHAIN_NODE: case KEYCHAIN_KEY_NODE: case MASC_NODE: + case PIM_NODE: case VTY_NODE: vty_config_unlock (vty); vty->node = ENABLE_NODE; @@ -1361,8 +1401,8 @@ vty_read (struct thread *thread) vty->monitor = 0; /* disable monitoring to avoid infinite recursion */ zlog_warn("%s: read error on vty client fd %d, closing: %s", __func__, vty->fd, safe_strerror(errno)); + buffer_reset(vty->obuf); } - buffer_reset(vty->obuf); vty->status = VTY_CLOSE; } @@ -1540,7 +1580,7 @@ vty_read (struct thread *thread) vty_close (vty); else { - vty_event (VTY_WRITE, vty_sock, vty); + vty_event (VTY_WRITE, vty->wfd, vty); vty_event (VTY_READ, vty_sock, vty); } return 0; @@ -1568,13 +1608,13 @@ vty_flush (struct thread *thread) erase = ((vty->status == VTY_MORE || vty->status == VTY_MORELINE)); /* N.B. if width is 0, that means we don't know the window size. */ - if ((vty->lines == 0) || (vty->width == 0)) - flushrc = buffer_flush_available(vty->obuf, vty->fd); + if ((vty->lines == 0) || (vty->width == 0) || (vty->height == 0)) + flushrc = buffer_flush_available(vty->obuf, vty_sock); else if (vty->status == VTY_MORELINE) - flushrc = buffer_flush_window(vty->obuf, vty->fd, vty->width, + flushrc = buffer_flush_window(vty->obuf, vty_sock, vty->width, 1, erase, 0); else - flushrc = buffer_flush_window(vty->obuf, vty->fd, vty->width, + flushrc = buffer_flush_window(vty->obuf, vty_sock, vty->width, vty->lines >= 0 ? vty->lines : vty->height, erase, 0); @@ -1608,6 +1648,34 @@ vty_flush (struct thread *thread) return 0; } +/* allocate and initialise vty */ +static struct vty * +vty_new_init (int vty_sock) +{ + struct vty *vty; + + vty = vty_new (); + vty->fd = vty_sock; + vty->wfd = vty_sock; + vty->type = VTY_TERM; + vty->node = AUTH_NODE; + vty->fail = 0; + vty->cp = 0; + vty_clear_buf (vty); + vty->length = 0; + memset (vty->hist, 0, sizeof (vty->hist)); + vty->hp = 0; + vty->hindex = 0; + vector_set_index (vtyvec, vty_sock, vty); + vty->status = VTY_NORMAL; + vty->lines = -1; + vty->iac = 0; + vty->iac_sb_in_progress = 0; + vty->sb_len = 0; + + return vty; +} + /* Create new vty structure. */ static struct vty * vty_create (int vty_sock, union sockunion *su) @@ -1618,9 +1686,10 @@ vty_create (int vty_sock, union sockunion *su) sockunion2str(su, buf, SU_ADDRSTRLEN); /* Allocate new vty structure and set up default values. */ - vty = vty_new (); - vty->fd = vty_sock; - vty->type = VTY_TERM; + vty = vty_new_init (vty_sock); + + /* configurable parameters not part of basic init */ + vty->v_timeout = vty_timeout_val; strcpy (vty->address, buf); if (no_password_check) { @@ -1631,25 +1700,8 @@ vty_create (int vty_sock, union sockunion *su) else vty->node = VIEW_NODE; } - else - vty->node = AUTH_NODE; - vty->fail = 0; - vty->cp = 0; - vty_clear_buf (vty); - vty->length = 0; - memset (vty->hist, 0, sizeof (vty->hist)); - vty->hp = 0; - vty->hindex = 0; - vector_set_index (vtyvec, vty_sock, vty); - vty->status = VTY_NORMAL; - vty->v_timeout = vty_timeout_val; if (host.lines >= 0) vty->lines = host.lines; - else - vty->lines = -1; - vty->iac = 0; - vty->iac_sb_in_progress = 0; - vty->sb_len = 0; if (! no_password_check) { @@ -1685,6 +1737,66 @@ vty_create (int vty_sock, union sockunion *su) return vty; } +/* create vty for stdio */ +static struct termios stdio_orig_termios; +static struct vty *stdio_vty = NULL; +static void (*stdio_vty_atclose)(void); + +static void +vty_stdio_reset (void) +{ + if (stdio_vty) + { + tcsetattr (0, TCSANOW, &stdio_orig_termios); + stdio_vty = NULL; + + if (stdio_vty_atclose) + stdio_vty_atclose (); + stdio_vty_atclose = NULL; + } +} + +struct vty * +vty_stdio (void (*atclose)()) +{ + struct vty *vty; + struct termios termios; + + /* refuse creating two vtys on stdio */ + if (stdio_vty) + return NULL; + + vty = stdio_vty = vty_new_init (0); + stdio_vty_atclose = atclose; + vty->wfd = 1; + + /* always have stdio vty in a known _unchangeable_ state, don't want config + * to have any effect here to make sure scripting this works as intended */ + vty->node = ENABLE_NODE; + vty->v_timeout = 0; + strcpy (vty->address, "console"); + + if (!tcgetattr (0, &stdio_orig_termios)) + { + termios = stdio_orig_termios; + termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP + | INLCR | IGNCR | ICRNL | IXON); + termios.c_oflag &= ~OPOST; + termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); + termios.c_cflag &= ~(CSIZE | PARENB); + termios.c_cflag |= CS8; + tcsetattr (0, TCSANOW, &termios); + } + + vty_prompt (vty); + + /* Add read/write thread. */ + vty_event (VTY_WRITE, 1, vty); + vty_event (VTY_READ, 0, vty); + + return vty; +} + /* Accept connection from the network. */ static int vty_accept (struct thread *thread) @@ -1694,7 +1806,7 @@ vty_accept (struct thread *thread) int ret; unsigned int on; int accept_sock; - struct prefix *p = NULL; + struct prefix p; struct access_list *acl = NULL; char buf[SU_ADDRSTRLEN]; @@ -1714,13 +1826,13 @@ vty_accept (struct thread *thread) } set_nonblocking(vty_sock); - p = sockunion2hostprefix (&su); + sockunion2hostprefix (&su, &p); /* VTY's accesslist apply. */ - if (p->family == AF_INET && vty_accesslist_name) + if (p.family == AF_INET && vty_accesslist_name) { if ((acl = access_list_lookup (AFI_IP, vty_accesslist_name)) && - (access_list_apply (acl, p) == FILTER_DENY)) + (access_list_apply (acl, &p) == FILTER_DENY)) { zlog (NULL, LOG_INFO, "Vty connection refused from %s", sockunion2str (&su, buf, SU_ADDRSTRLEN)); @@ -1729,18 +1841,16 @@ vty_accept (struct thread *thread) /* continue accepting connections */ vty_event (VTY_SERV, accept_sock, NULL); - prefix_free (p); - return 0; } } #ifdef HAVE_IPV6 /* VTY's ipv6 accesslist apply. */ - if (p->family == AF_INET6 && vty_ipv6_accesslist_name) + if (p.family == AF_INET6 && vty_ipv6_accesslist_name) { if ((acl = access_list_lookup (AFI_IP6, vty_ipv6_accesslist_name)) && - (access_list_apply (acl, p) == FILTER_DENY)) + (access_list_apply (acl, &p) == FILTER_DENY)) { zlog (NULL, LOG_INFO, "Vty connection refused from %s", sockunion2str (&su, buf, SU_ADDRSTRLEN)); @@ -1749,15 +1859,11 @@ vty_accept (struct thread *thread) /* continue accepting connections */ vty_event (VTY_SERV, accept_sock, NULL); - prefix_free (p); - return 0; } } #endif /* HAVE_IPV6 */ - prefix_free (p); - on = 1; ret = setsockopt (vty_sock, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof (on)); @@ -1773,7 +1879,7 @@ vty_accept (struct thread *thread) return 0; } -#if defined(HAVE_IPV6) && !defined(NRL) +#ifdef HAVE_IPV6 static void vty_serv_sock_addrinfo (const char *hostname, unsigned short port) { @@ -1838,7 +1944,7 @@ vty_serv_sock_addrinfo (const char *hostname, unsigned freeaddrinfo (ainfo_save); } -#else /* HAVE_IPV6 && ! NRL */ +#else /* HAVE_IPV6 */ /* Make vty server socket. */ static void @@ -1856,9 +1962,11 @@ vty_serv_sock_family (const char* addr, unsigned short { case AF_INET: naddr=&su.sin.sin_addr; + break; #ifdef HAVE_IPV6 case AF_INET6: naddr=&su.sin6.sin6_addr; + break; #endif } @@ -1904,7 +2012,7 @@ vty_serv_sock_family (const char* addr, unsigned short /* Add vty server event. */ vty_event (VTY_SERV, accept_sock, NULL); } -#endif /* HAVE_IPV6 && ! NRL */ +#endif /* HAVE_IPV6 */ #ifdef VTYSH /* For sockaddr_un. */ @@ -2018,6 +2126,7 @@ vtysh_accept (struct thread *thread) vty = vty_new (); vty->fd = sock; + vty->wfd = sock; vty->type = VTY_SHELL_SERV; vty->node = VIEW_NODE; @@ -2029,10 +2138,10 @@ vtysh_accept (struct thread *thread) static int vtysh_flush(struct vty *vty) { - switch (buffer_flush_available(vty->obuf, vty->fd)) + switch (buffer_flush_available(vty->obuf, vty->wfd)) { case BUFFER_PENDING: - vty_event(VTYSH_WRITE, vty->fd, vty); + vty_event(VTYSH_WRITE, vty->wfd, vty); break; case BUFFER_ERROR: vty->monitor = 0; /* disable monitoring to avoid infinite recursion */ @@ -2139,12 +2248,7 @@ vty_serv_sock (const char *addr, unsigned short port, { #ifdef HAVE_IPV6 -#ifdef NRL - vty_serv_sock_family (addr, port, AF_INET); - vty_serv_sock_family (addr, port, AF_INET6); -#else /* ! NRL */ vty_serv_sock_addrinfo (addr, port); -#endif /* NRL*/ #else /* ! HAVE_IPV6 */ vty_serv_sock_family (addr,port, AF_INET); #endif /* HAVE_IPV6 */ @@ -2173,7 +2277,7 @@ vty_close (struct vty *vty) thread_cancel (vty->t_timeout); /* Flush buffer. */ - buffer_flush_all (vty->obuf, vty->fd); + buffer_flush_all (vty->obuf, vty->wfd); /* Free input buffer. */ buffer_free (vty->obuf); @@ -2189,6 +2293,8 @@ vty_close (struct vty *vty) /* Close socket. */ if (vty->fd > 0) close (vty->fd); + else + vty_stdio_reset (); if (vty->buf) XFREE (MTYPE_VTY, vty->buf); @@ -2227,28 +2333,38 @@ vty_read_file (FILE *confp) { int ret; struct vty *vty; + unsigned int line_num = 0; vty = vty_new (); - vty->fd = 0; /* stdout */ - vty->type = VTY_TERM; + vty->wfd = dup(STDERR_FILENO); /* vty_close() will close this */ + if (vty->wfd < 0) + { + /* Fine, we couldn't make a new fd. vty_close doesn't close stdout. */ + vty->wfd = STDOUT_FILENO; + } + vty->fd = STDIN_FILENO; + vty->type = VTY_FILE; vty->node = CONFIG_NODE; /* Execute configuration file */ - ret = config_from_file (vty, confp); + ret = config_from_file (vty, confp, &line_num); + /* Flush any previous errors before printing messages below */ + buffer_flush_all (vty->obuf, vty->fd); + if ( !((ret == CMD_SUCCESS) || (ret == CMD_ERR_NOTHING_TODO)) ) { switch (ret) { case CMD_ERR_AMBIGUOUS: - fprintf (stderr, "Ambiguous command.\n"); + fprintf (stderr, "*** Error reading config: Ambiguous command.\n"); break; case CMD_ERR_NO_MATCH: - fprintf (stderr, "There is no such command.\n"); + fprintf (stderr, "*** Error reading config: There is no such command.\n"); break; } - fprintf (stderr, "Error occured during reading below line.\n%s\n", - vty->buf); + fprintf (stderr, "*** Error occured processing line %u, below:\n%s\n", + line_num, vty->buf); vty_close (vty); exit (1); } @@ -2447,7 +2563,7 @@ vty_log (const char *level, const char *proto_str, /* Async-signal-safe version of vty_log for fixed strings. */ void -vty_log_fixed (const char *buf, size_t len) +vty_log_fixed (char *buf, size_t len) { unsigned int i; struct iovec iov[2]; @@ -2456,7 +2572,7 @@ vty_log_fixed (const char *buf, size_t len) if (!vtyvec) return; - iov[0].iov_base = (void *)buf; + iov[0].iov_base = buf; iov[0].iov_len = len; iov[1].iov_base = (void *)"\r\n"; iov[1].iov_len = 2; @@ -2467,7 +2583,7 @@ vty_log_fixed (const char *buf, size_t len) if (((vty = vector_slot (vtyvec, i)) != NULL) && vty->monitor) /* N.B. We don't care about the return code, since process is most likely just about to die anyway. */ - writev(vty->fd, iov, 2); + writev(vty->wfd, iov, 2); } } @@ -2492,9 +2608,9 @@ vty_config_unlock (struct vty *vty) } return vty->config; } - + /* Master of the threads. */ -static struct thread_master *master; +static struct thread_master *vty_master; static void vty_event (enum event event, int sock, struct vty *vty) @@ -2504,22 +2620,23 @@ vty_event (enum event event, int sock, struct vty *vty switch (event) { case VTY_SERV: - vty_serv_thread = thread_add_read (master, vty_accept, vty, sock); + vty_serv_thread = thread_add_read (vty_master, vty_accept, vty, sock); vector_set_index (Vvty_serv_thread, sock, vty_serv_thread); break; #ifdef VTYSH case VTYSH_SERV: - thread_add_read (master, vtysh_accept, vty, sock); + vty_serv_thread = thread_add_read (vty_master, vtysh_accept, vty, sock); + vector_set_index (Vvty_serv_thread, sock, vty_serv_thread); break; case VTYSH_READ: - vty->t_read = thread_add_read (master, vtysh_read, vty, sock); + vty->t_read = thread_add_read (vty_master, vtysh_read, vty, sock); break; case VTYSH_WRITE: - vty->t_write = thread_add_write (master, vtysh_write, vty, sock); + vty->t_write = thread_add_write (vty_master, vtysh_write, vty, sock); break; #endif /* VTYSH */ case VTY_READ: - vty->t_read = thread_add_read (master, vty_read, vty, sock); + vty->t_read = thread_add_read (vty_master, vty_read, vty, sock); /* Time out treatment. */ if (vty->v_timeout) @@ -2527,12 +2644,12 @@ vty_event (enum event event, int sock, struct vty *vty if (vty->t_timeout) thread_cancel (vty->t_timeout); vty->t_timeout = - thread_add_timer (master, vty_timeout, vty, vty->v_timeout); + thread_add_timer (vty_master, vty_timeout, vty, vty->v_timeout); } break; case VTY_WRITE: if (! vty->t_write) - vty->t_write = thread_add_write (master, vty_flush, vty, sock); + vty->t_write = thread_add_write (vty_master, vty_flush, vty, sock); break; case VTY_TIMEOUT_RESET: if (vty->t_timeout) @@ -2543,12 +2660,12 @@ vty_event (enum event event, int sock, struct vty *vty if (vty->v_timeout) { vty->t_timeout = - thread_add_timer (master, vty_timeout, vty, vty->v_timeout); + thread_add_timer (vty_master, vty_timeout, vty, vty->v_timeout); } break; } } - + DEFUN (config_who, config_who_cmd, "who", @@ -2955,7 +3072,9 @@ vty_init (struct thread_master *master_thread) vtyvec = vector_init (VECTOR_MIN_SIZE); - master = master_thread; + vty_master = master_thread; + + atexit (vty_stdio_reset); /* Initilize server thread vector. */ Vvty_serv_thread = vector_init (VECTOR_MIN_SIZE);