diff options
author | Chris Hall <chris.hall@highwayman.com> | 2011-02-13 23:11:45 +0000 |
---|---|---|
committer | Chris Hall <chris.hall@highwayman.com> | 2011-02-13 23:11:45 +0000 |
commit | 5cae7eea451f2b7d65b5892e2c1dafc70f8b836e (patch) | |
tree | 0fbd9679e9ae28e7d061b5bdda08756077415ecb /lib/vty_io.c | |
parent | 64be6d766a65dc0749d17f5023d714678e9c96a6 (diff) | |
download | quagga-5cae7eea451f2b7d65b5892e2c1dafc70f8b836e.tar.bz2 quagga-5cae7eea451f2b7d65b5892e2c1dafc70f8b836e.tar.xz |
Second tranche of updates for pipework branch.
modified: bgpd/bgp_connection.c
modified: bgpd/bgp_debug.c
modified: bgpd/bgp_engine.h
modified: bgpd/bgp_main.c
modified: bgpd/bgp_packet.c
modified: bgpd/bgp_peer.c
modified: bgpd/bgp_route.c
modified: bgpd/bgp_routemap.c
modified: bgpd/bgp_session.c
modified: bgpd/bgp_vty.c
modified: bgpd/bgpd.c
modified: bgpd/bgpd.h
modified: configure.ac
modified: isisd/dict.h
modified: isisd/isis_misc.c
modified: isisd/isis_routemap.c
modified: isisd/isis_spf.c
modified: lib/Makefile.am
modified: lib/command.c
modified: lib/command.h
modified: lib/command_execute.h
modified: lib/command_parse.c
modified: lib/command_parse.h
modified: lib/command_queue.c
modified: lib/command_queue.h
modified: lib/elstring.h
modified: lib/heap.c
modified: lib/if.c
modified: lib/if.h
modified: lib/keychain.c
modified: lib/keystroke.c
modified: lib/keystroke.h
modified: lib/list_util.c
modified: lib/list_util.h
modified: lib/log.c
modified: lib/log.h
modified: lib/memory.c
modified: lib/memory.h
modified: lib/memtypes.c
modified: lib/misc.h
modified: lib/mqueue.c
modified: lib/mqueue.h
deleted: lib/node_type.h
modified: lib/pthread_safe.c
modified: lib/qfstring.c
modified: lib/qiovec.c
modified: lib/qiovec.h
modified: lib/qpath.c
modified: lib/qpnexus.c
modified: lib/qpnexus.h
modified: lib/qpselect.c
modified: lib/qpthreads.h
modified: lib/qstring.c
modified: lib/qstring.h
modified: lib/qtime.c
modified: lib/qtime.h
modified: lib/qtimers.c
modified: lib/qtimers.h
modified: lib/routemap.c
modified: lib/symtab.h
modified: lib/thread.h
deleted: lib/uty.h
modified: lib/vector.c
modified: lib/vector.h
modified: lib/version.h.in
modified: lib/vio_fifo.c
modified: lib/vio_fifo.h
modified: lib/vio_lines.c
modified: lib/vio_lines.h
modified: lib/vty.c
modified: lib/vty.h
modified: lib/vty_cli.c
modified: lib/vty_cli.h
modified: lib/vty_io.c
modified: lib/vty_io.h
modified: lib/vty_io_basic.c
modified: lib/vty_io_basic.h
modified: lib/vty_io_file.c
modified: lib/vty_io_file.h
modified: lib/vty_io_shell.c
modified: lib/vty_io_term.c
modified: lib/vty_io_term.h
modified: lib/vty_local.h
modified: lib/vty_pipe.c
modified: lib/workqueue.h
modified: lib/zebra.h
modified: ospf6d/ospf6_lsa.c
modified: ripngd/ripngd.c
modified: tests/test-list_util.c
modified: tests/test-vector.c
modified: vtysh/vtysh.c
modified: vtysh/vtysh_config.c
Diffstat (limited to 'lib/vty_io.c')
-rw-r--r-- | lib/vty_io.c | 1196 |
1 files changed, 640 insertions, 556 deletions
diff --git a/lib/vty_io.c b/lib/vty_io.c index c116e6b9..4b50c526 100644 --- a/lib/vty_io.c +++ b/lib/vty_io.c @@ -24,10 +24,14 @@ #include "vty.h" #include "vty_io.h" #include "vty_io_term.h" +#include "vty_io_file.h" #include "vty_cli.h" +#include "vty_command.h" #include "qstring.h" #include "keystroke.h" #include "list_util.h" +#include "command_parse.h" +#include "command_execute.h" #include "memory.h" @@ -45,20 +49,18 @@ /*============================================================================== * Basic output to VTY. - * - * */ /*------------------------------------------------------------------------------ - * UTY output function -- cf fprintf + * VTY output -- cf fprintf ! Same as vty_out, less the VTY_LOCK(). * - * NB: this is NOT suppressed by ! vty->output_enabled + * This is for command output, which may later be suppressed * * Returns: >= 0 => OK * < 0 => failed (see errno) */ extern int -uty_output(struct vty *vty, const char *format, ...) +uty_out(vty_io vio, const char *format, ...) { int ret ; va_list args ; @@ -66,122 +68,10 @@ uty_output(struct vty *vty, const char *format, ...) VTY_ASSERT_LOCKED() ; va_start (args, format) ; - ret = uty_vprintf(vty, format, args) ; + ret = uty_vprintf(vio, format, args) ; va_end (args) ; return ret ; -} - -/*------------------------------------------------------------------------------ - * UTY reflect command line, if not already reflected - * - * NB: this is NOT suppressed by ! vty->output_enabled - * - * Returns: >= 0 => OK - * < 0 => failed (see errno) - */ -extern int -uty_reflect(struct vty *vty) -{ - int ret ; - - if (!vty->reflected) - ret = uty_output(vty, "%s\n", vty->buf) ; - else - ret = 0 ; - - vty->reflected = true ; - - return ret ; -} ; - -/*------------------------------------------------------------------------------ - * VTY output function -- cf vfprintf - * - * Returns: >= 0 => OK - * < 0 => failed (see errno) - * - * NB: for VTY_TERM and for VTY_SHELL_SERV -- this is command output: - * - * * MAY NOT do any command output if !cmd_enabled - * - * * first, the life of a vty is not guaranteed unless cmd_in_progress, - * so should not attempt to use a vty anywhere other than command - * execution. - * - * * second, cmd_out_enabled is false most of the time, and is only - * set true when a command completes, and it is time to write away - * the results. - * - * * all output is placed in the vio->cmd_obuf. When the command completes, - * the contents of the cmd_obuf will be written away -- subject to line - * control. - * - * * output is discarded if the vty is no longer write_open - */ -extern int -uty_vprintf(struct vty *vty, const char *format, va_list args) -{ - vio_vf vf ; - int ret ; - - VTY_ASSERT_LOCKED() ; - - vf = vty->vio->vout ; - - switch (vf->vout_type) - { - case VOUT_NONE: - ret = 0 ; - break ; - - case VOUT_TERM: - ret = uty_term_vprintf(vf, format, args) ; - break ; - - case VOUT_SHELL: - ret = uty_shell_vprintf(vf, format, args) ; - break ; - - case VOUT_FILE: - ret = uty_file_vprintf(vf, format, args) ; - break ; - - case VOUT_PIPE: - ret = uty_pipe_vprintf(vf, format, args) ; - break ; - - case VOUT_STDOUT: - ret = uty_stdout_vprintf(vf, format, args) ; - break ; - - case VOUT_STDERR: - ret = uty_stderr_vprintf(vf, format, args) ; - break ; - - default: - zabort("impossible VTY Output type") ; - } ; - - return ret ; -} ; - -/*------------------------------------------------------------------------------ - * Clear the contents of the command output FIFO etc. - * - * NB: does not change any of the cli_blocked/cmd_in_progress/cli_wait_more/etc - * flags -- competent parties must deal with those - */ -extern void -uty_out_clear(vty_io vio) -{ - VTY_ASSERT_LOCKED() ; - - if (vio->vout != NULL) - { - vio_fifo_clear(vio->vout->obuf) ; - vio_lc_clear(vio->vout->olc) ; - } ; } ; /*============================================================================== @@ -238,7 +128,7 @@ uty_watch_dog_stop(void) static vty_timer_time uty_watch_dog_bark(vio_timer_t* timer, void* info) { - uty_check_host_name() ; /* check for host name change */ + cmd_host_name(true) ; /* check for host name change */ uty_death_watch_scan(false) ; /* scan the death-watch list */ @@ -248,11 +138,12 @@ uty_watch_dog_bark(vio_timer_t* timer, void* info) /*------------------------------------------------------------------------------ * Scan the death watch list. * - * A vty may finally be freed if it is closed and there is no command in - * progress. + * A vty can finally be freed if it is closed and there is no command running. + * + * At curtains the command running state is forced off. */ static bool -uty_death_watch_scan(bool final) +uty_death_watch_scan(bool curtains) { vty_io vio ; vty_io next ; @@ -263,21 +154,19 @@ uty_death_watch_scan(bool final) vio = next ; next = sdl_next(vio, vio_list) ; - if (final && !vio->closed) - - - if (vio->closed) + /* If this is curtains, override cmd_running ! */ + if (curtains) + vio->cmd_running = false ; - - if (vio->closed && !vio->cmd_in_progress) + if (uty_close(vio, curtains, NULL)) { - uty_close(vio) ; /* closes again to ensure that all buffers - are released. */ + vty vty = vio->vty ; sdl_del(vio_death_watch, vio, vio_list) ; - XFREE(MTYPE_VTY, vio->vty) ; - XFREE(MTYPE_VTY, vio) ; + cmd_exec_free(vty->exec) ; + XFREE(MTYPE_VTY, vty->vio) ; + XFREE(MTYPE_VTY, vty) ; } ; } ; @@ -288,189 +177,128 @@ uty_death_watch_scan(bool final) * Prototypes. */ -static void uty_vf_half_close(vio_vf vf) ; -static void uty_vf_close(vio_vf vf) ; +static void uty_vf_read_close(vio_vf vf) ; +static bool uty_vf_write_close(vio_vf vf, bool final) ; +static vio_vf uty_vf_free(vio_vf vf) ; /*============================================================================== * Creation and destruction of VTY objects */ /*------------------------------------------------------------------------------ - * Allocate new vty struct - * - * VTY_TERMINAL a telnet terminal server - * - * Must be in cli thread. - * - * Requires fd = socket for telnet terminal. - * - * VTY_SHELL_SERVER a vty_shell server - * - * Must be in cli thread. + * Allocate new vty structure, including empty vty_io and empty execution + * structures. * - * Requires fd = socket for talking to the VTY_SHELL_CLIENT + * Caller must complete the initialisation of the vty_io, which means: * - * VTY_SHELL_CLIENT a vty_shell client + * * constructing a suitable vio_vf and doing uty_vin_open() to set the + * vin_base. * - * VTY_CONFIG_READ configuration file reader + * All vty_io MUST have a vin_base, even if it is /dev/null. * - * Requires fd = file descriptor for reading config file + * * constructing a suitable vio_vf and doing uty_vout_open() to set the + * vout_base. * - * VTY_STDOUT stdout - * VTY_STDERR stderr + * All vty_io MUST have a vout_base, even if it is /dev/null. * + * * setting the vio->obuf to the vout_base obuf... TODO ??? * + * * setting vio->cli, if required. * - * - * - * - * - * - * Allocates and initialises basic vty and vty_io structures, setting the - * given type. - * - * Note that where is not setting up a vty_file, this *may* be called from - * any thread. - * - * Returns: new vty + * Caller must also set the initial vty->node, if any. */ -extern struct vty * -uty_new(enum vty_type type, int fd) +extern vty +uty_new(vty_type_t type) { vty vty ; vty_io vio ; + bool execution ; + VTY_ASSERT_LOCKED() ; /* Basic allocation */ - vty = XCALLOC (MTYPE_VTY, sizeof (struct vty)) ; - vio = XCALLOC (MTYPE_VTY, sizeof (struct vty_io)) ; - - vty->vio = vio ; - vio->vty = vty ; - - /* Zeroising the vty_io structure has set: - * - * name = NULL -- no name, yet - * - * vio_list both pointers NULL - * mon_list both pointers NULL - * - * half_closed = 0 -- NOT half closed (important !) - * closed = 0 -- NOT closed (important !) - * close_reason = NULL -- no reason, yet + vty = XCALLOC(MTYPE_VTY, sizeof(struct vty)) ; + /* Zeroising the vty structure has set: * - * real_type = 0 -- not material - * file_fd = 0 -- not material - * file_error = 0 -- not material + * type = X -- set to actual type, below * - * key_stream = NULL -- no key stream (always empty, at EOF) + * node = NULL_NODE -- set to something sensible elsewhere * - * cli_drawn = 0 -- not drawn - * cli_dirty = 0 -- not dirty - * cli_prompt_len = 0 ) - * cli_extra_len = 0 ) not material - * cli_echo_suppress = 0 ) + * index = NULL -- nothing, yet + * index_sub = NULL -- nothing, yet * - * cli_prompt_node = 0 -- not material - * cli_prompt_set = 0 -- so prompt needs to be constructed + * config = false -- not in configure mode * - * cli_blocked = 0 -- not blocked - * cmd_in_progress = 0 -- no command in progress - * cmd_out_enabled = 0 -- command output is disabled - * cli_wait_more = 0 -- not waiting for response to "--more--" + * execution = X -- set below + * vio = X -- set below + */ + confirm(NULL_NODE == 0) ; + confirm(QSTRING_INIT_ALL_ZEROS) ; + + vty->type = type ; + + vio = XCALLOC(MTYPE_VTY, sizeof(struct vty_io)) ; + + /* Zeroising the vty_io structure has set: * - * cli_more_enabled = 0 -- not enabled for "--more--" + * vty = X -- set to point to parent vty, below * - * cmd_out_done = 0 -- not material + * name = NULL -- no name, yet TODO ??? * - * cli_do = 0 == cli_do_nothing + * vin = NULL -- empty input stack + * vin_base = NULL -- empty input stack + * vin_depth = 0 -- no stacked vin's, yet * - * cmd_lc = NULL -- no line control + * vout = NULL -- empty output stack + * vout_base = NULL -- empty output stack + * vout_depth = 0 -- no stacked vout's, yet * - * fail = 0 -- no login failures yet + * vout_closing = NULL -- nothing closing yet * - * hist = empty vector - * hp = 0 -- at the beginning - * hindex = 0 -- the beginning + * vio_list = NULLs -- not on the vio_list, yet + * mon_list = NULLs -- not on the monitors list * - * width = 0 -- unknown console width - * height = 0 -- unknown console height + * blocking = X -- set below: false unless VTY_CONFIG_READ + * cmd_running = false -- no commands running, yet * - * lines = 0 -- no limit - * lines_set = 0 -- no explicit setting + * state = X -- set vf_open, below. * - * monitor = 0 -- not a monitor - * monitor_busy = 0 -- not a busy monitor + * close_reason = NULL -- not closed, yet * - * config = 0 -- not holder of "config" mode + * obuf = NULL -- no output buffer, yet */ - confirm(cli_do_nothing == 0) ; - confirm(AUTH_NODE == 0) ; /* default node type */ - - vty->type = type ; - + vty->vio = vio ; + vio->vty = vty ; + vio->blocking = (type == VTY_CONFIG_READ) ; + vio->state = vf_open ; + /* Create and initialise the command execution environment (if any) */ + execution = true ; - /* Zeroising the vty structure has set: - * - * node = 0 TODO: something better for node value ???? - * buf = NULL -- no command line, yet - * parsed = NULL -- no parsed command, yet - * lineno = 0 -- nothing read, yet - * index = NULL -- nothing, yet - * index_sub = NULL -- nothing, yet - */ - - /* If this is a VTY_TERM or a VTY_SHELL, place */ - switch (type) + switch(type) { - case VTY_TERMINAL: /* Require fd -- Telnet session */ - VTY_ASSERT_CLI_THREAD() ; - assert(fd >= 0) ; - - uty_term_new(vio, fd) ; - break ; - - case VTY_SHELL_SERVER: /* Require fd -- Unix socket */ - VTY_ASSERT_CLI_THREAD() ; - assert(fd >= 0) ; - - - break ; - - case VTY_CONFIG_READ: /* Require fd -- file to read */ - assert(fd >= 0) ; + case VTY_TERMINAL: + case VTY_SHELL_SERVER: + case VTY_SHELL_CLIENT: + case VTY_CONFIG_READ: + execution = true ; break ; case VTY_STDOUT: case VTY_STDERR: - case VTY_SHELL_CLIENT: - fd = -1 ; /* No fd -- output to stdout/stderr */ + execution = false ; break ; default: - zabort("unknown VTY type") ; + zabort("unknown vty type") ; } ; - - - - /* Make sure all buffers etc. are initialised clean and empty. - * - * Note that no buffers are actually allocated at this stage. - */ - qs_init_new(&vio->cli_prompt_for_node, 0) ; - - qs_init_new(&vio->cl, 0) ; - qs_init_new(&vio->clx, 0) ; - - vio_fifo_init_new(&vio->cli_obuf, 2 * 1024) ; /* allocate in 2K lumps */ - - vio_fifo_init_new(&vio->cmd_obuf, 8 * 1024) ; + if (execution) + vty->exec = cmd_exec_new(vty) ; /* Place on list of known vio/vty */ sdl_push(vio_list_base, vio, vio_list) ; @@ -483,73 +311,127 @@ uty_new(enum vty_type type, int fd) * * Sets the vf->vin_type and set vf->read_open. * - * Sets the read ready action and the read timer timeout action. + * Initialises an input buffer if required, and sets line_complete and + * line_step so that first attempt to fetch a line will give line 1. * - * NB: may add a VIN_NONE *only* as the first vin item. + * Sets the read ready action and the read timer timeout action. * - * Can have a write only VTY_XXX object, which requires a vin entry so that - * do not have to everywhere deal with NULL vio_vf pointers. + * NB: a uty_cmd_prepare() is required before command processing can continue. * - * But for subsequent write only vio_vf objects, must not add to the vin - * stack. + * That is not done here because the vin state may not be complete (in + * particular the vin->parse_type and vin->reflect_enabled !). */ extern void -uty_vin_add(vty_io vio, vio_vf vf, vio_in_type_t type, - vio_fd_action* read_action, vio_timer_action* read_timer_action) +uty_vin_open(vty_io vio, vio_vf vf, vio_in_type_t type, + vio_vfd_action* read_action, + vio_timer_action* read_timer_action, + usize ibuf_size) { vf->vin_type = type ; - vf->read_open = true ; + vf->vin_state = vf_open ; - vio_fd_set_read_action(vf->vfd, read_action) ; - vio_fd_set_read_timeout_action(vf->vfd, read_timer_action) ; + if (type < VIN_SPECIALS) + { + vio_vfd_set_read_action(vf->vfd, read_action) ; + vio_vfd_set_read_timeout_action(vf->vfd, read_timer_action) ; + } ; ssl_push(vio->vin, vf, vin_next) ; if (vio->vin_base == NULL) - vio->vin_base = vf ; + { + assert(vio->vin_depth == 0) ; + vio->vin_base = vf ; + } else - assert(type != VIN_NONE) ; + { + assert(type != VIN_NONE) ; + ++vio->vin_depth ; + } ; + + if (ibuf_size != 0) + { + vf->ibuf = vio_fifo_init_new(NULL, ibuf_size) ; + + vf->line_complete = true ; + vf->line_step = 1 ; + } ; } ; /*------------------------------------------------------------------------------ - * Add a new vf to the vio->vout stack, and set write stuff. + * Push a new vf to the vio->vout stack, and set write stuff. * * Sets the vf->vout_type and set vf->write_open. * * Sets the write ready action and the write timer timeout action. * - * NB: may add a VOUT_NONE *only* as the first vout item. + * Initialises an output buffer and sets an end_mark. + * + * NB: VOUT_DEV_NULL, VOUT_STDOUT and VOUT_STDERR are special. + * + * The write_action and the write_timer_action are ignored. * - * Can have a read only VTY_XXX object, which requires a vout entry so that - * do not have to everywhere deal with NULL vio_vf pointers. + * All actual I/O to these outputs is direct, blocking and via standard + * I/O -- except VOUT_DEV_NULL where all I/O is discarded. * - * But for subsequent read only vio_vf objects, must not add to the vout - * stack. + * NB: all outputs are set up with an obuf, so all output is collected, even + * if it is later to be discarded. + * + * NB: a uty_cmd_prepare() is required before command processing can continue. + * + * That is not done here because the vout state may not be complete (in + * particular the vout->out_enabled !). */ extern void -uty_vout_add(vty_io vio, vio_vf vf, vio_out_type_t type, - vio_fd_action* write_action, vio_timer_action* write_timer_action) +uty_vout_open(vty_io vio, vio_vf vf, vio_out_type_t type, + vio_vfd_action* write_action, + vio_timer_action* write_timer_action, + usize obuf_size) { vf->vout_type = type ; - vf->write_open = true ; + vf->vout_state = vf_open ; - vio_fd_set_write_action(vf->vfd, write_action) ; - vio_fd_set_write_timeout_action(vf->vfd, write_timer_action) ; + if (type < VOUT_SPECIALS) + { + vio_vfd_set_write_action(vf->vfd, write_action) ; + vio_vfd_set_write_timeout_action(vf->vfd, write_timer_action) ; + } ; ssl_push(vio->vout, vf, vout_next) ; if (vio->vout_base == NULL) - vio->vout_base = vf ; + { + assert(vio->vout_depth == 0) ; + vio->vout_base = vf ; + } else - assert(type != VOUT_NONE) ; -} ; - - - + { + assert(type != VOUT_NONE) ; + ++vio->vout_depth ; + } ; + vf->obuf = vio_fifo_init_new(NULL, obuf_size) ; + vio_fifo_set_end_mark(vf->obuf) ; + vio->obuf = vio->vout->obuf ; +} ; +/*------------------------------------------------------------------------------ + * Set timeout value. + * + * This is only ever called when a command (eg exec-timeout) sets a new + * time out value -- which applies only to VIN_TERM and VTY_VTYSH. + */ +extern void +uty_set_timeout(vty_io vio, vty_timer_time timeout) +{ + vio_in_type_t vt ; + VTY_ASSERT_LOCKED() ; + vt = vio->vin_base->vin_type ; + if ((vt == VIN_TERM) || (vt == VIN_VTYSH)) + uty_vf_set_read_timeout(vio->vin_base, timeout) ; +} ; /*------------------------------------------------------------------------------ * Set/Clear "monitor" state: @@ -561,10 +443,10 @@ extern void uty_set_monitor(vty_io vio, bool on) { VTY_ASSERT_LOCKED() ; - +#if 0 if (on && !vio->monitor) { - if ((vio->vty->type == VTY_TERMINAL) && !vio->half_closed) + if ((vio->vty->type == VTY_TERMINAL) && !vio->closing) { vio->monitor = 1 ; sdl_push(vio_monitors_base, vio, mon_list) ; @@ -575,267 +457,278 @@ uty_set_monitor(vty_io vio, bool on) vio->monitor = 0 ; sdl_del(vio_monitors_base, vio, mon_list) ; } +#endif } ; /*------------------------------------------------------------------------------ - * Return "name" of VTY + * Return "name" of VTY. * - * For VTY_TERM this is the IP address of the far end of the telnet connection. + * The name of the base vin, or (failing that) the base vout. */ extern const char* uty_get_name(vty_io vio) { - return (vio->name != NULL) ? vio->name : "?" ; + const char* name ; + + name = vio->vin_base->name ; + if (name == NULL) + name = vio->vout_base->name ; + + return (name != NULL) ? name : "?" ; } ; /*------------------------------------------------------------------------------ - * Close all the readers. + * Close all vin excluding the vin_base. * - * Half-close everything on the vin stack. Empties the vin stack down to the - * base entry. Discards any read-only vio_vf (except for last vin entry). + * This is done on close and when there is a command error. + */ +extern void +uty_vin_close_stack(vty_io vio) +{ + while (vio->vin != vio->vin_base) + uty_vin_close(vio) ; +} ; + +/*------------------------------------------------------------------------------ + * Close all vout except for the vout_base. * - * VIO is placed on death watch, and will stay there until: + * This is done on close and when there is a command error. * - * * outstanding commands complete. + * Should only be "final" on a call from the watch-dog ! + */ +extern void +uty_vout_close_stack(vty_io vio, bool final) +{ + while (vio->vout != vio->vout_base) + uty_vout_close(vio, final) ; +} ; + +/*------------------------------------------------------------------------------ + * Close VTY -- may be called any number of times ! * - * * outstanding output completes, or times out, or program terminates. + * If no reason for the close has already been set, sets the given reason. + * The close reason is reported at the end of the output to the vout_base. * - * For VTY_TERMINAL (must be in CLI thread): + * Once a VTY has been closed, it will provide no further input. However, until + * "final" close, it will continue to output anything which is pending at the + * time of the close, which includes: (a) anything in the output buffer, + * (b) any further output from a then running command and (c) anything that an + * out_pipe may be in the process of returning. * - * * shut the socket for reading - * * discard all buffered input, setting it to "EOF" - * * turns off any monitor status ! - * * drop down to RESTRICTED_NODE + * The main complication is that in a multi-threaded world there may be a + * vio->cmd_running. The close shuts down everything on the input stack, so + * any active command loop will come to a halt as soon as the current command + * does complete. The output stack is preserved, but will be closed on + * completion of the command. * - * For VTY_SHELL_SERVER (must be in CLI thread): + * Closing a VTY places it on the death-watch list. Once any pending output + * has been dealt with and any cmd_running has completed, then the death-watch + * will apply the coup de grace. * - * * shut the socket for reading - * * discard all buffered input - * * drop down to RESTRICTED_NODE + * Getting the death-watch to finally close the VTY also allows the vty to be + * closed from somewhere deep (e.g. when there is an I/O error) without + * destroying the VTY and upsetting code that might not realise the VTY has + * vanished. * - * If no reason for the close has already been set, sets the given reason. + * The close sequence is: + * + * 1. if a close reason has not already been set, set any given one. + * + * 2. if not already closing -- ie this is the first call of uty_close() + * + * a. transfer to death-watch list & set closing. + * + * b. turn off any monitor state + * + * c. close down the input/read side completely. + * + * Empties the vin stack down to vin_base, closing all input. + * + * Close the vin_base. The vin_base is left !read_open. + * + * All read-only vio_vf (except the vin_base) are freed. + * + * Note that everything is read closed before anything is write + * closed. + * + * A vio_vf is read closed once and only once. + * + * The vin_base is closed only by this function. Until the final + * uty_close, there is always at least the vin_base, even if it is + * read_closed. + * + * 3. try to close everything on the vout_closing list. + * + * even if cmd_running * - * If already half-closed, does nothing else. * - * Returns true <=> first half close. */ -static bool -uty_do_half_close(vty_io vio, const char* reason) +extern bool +uty_close(vty_io vio, bool final, qstring reason) { - vio_vf vf ; + vio_vf vf_next ; VTY_ASSERT_LOCKED() ; - if ((vio->close_reason == NULL) && (reason != NULL)) - vio->close_reason = XSTRDUP(MTYPE_TMP, reason) ; + /* quit if already closed */ + if (vio->state == vf_closed) + return true ; - if (vio->half_closed) - return false ; + /* Set the close reason, if not already set. */ + if (reason != NULL) + { + if (vio->close_reason == NULL) + vio->close_reason = reason ; + else + qs_reset(reason, free_it) ; + } ; - /* Half close everything on the vin stack. - * - * Leave stack with just the base entry (closed for read). + /* If not already closing, set closing and transfer to the death watch + * list -- turn off any "monitor" status immediately. */ - while (1) + if (vio->state == vf_open) { - vf = vio->vin ; /* Current first on list */ + vio->state = vf_closing ; - uty_vf_half_close(vf) ; /* fd level half close etc. */ + /* Transfer to the death-watch */ + sdl_del(vio_list_base, vio, vio_list) ; + sdl_push(vio_death_watch, vio, vio_list) ; - switch(vf->vin_type) /* tidy up each type */ - { - case VIN_NONE: - break ; + /* TODO turn off any "monitor" IMMEDIATELY. */ - case VIN_TERM: - uty_term_half_close(vf) ; - uty_cli_close(vio) ; /* tell the CLI to stop */ - break ; + /* Flush the vin stack. + * + * Where possible this will revoke commands bring command processing to + * as sudden a halt as possible -- though may still be processing + * commands. + */ + uty_vin_close_stack(vio) ; + assert(vio->vin == vio->vin_base) ; + uty_vf_read_close(vio->vin) ; + } ; + + /* If there is anything on the vout_closing list, give it a shove in case + * that manages to close anything -- which it will do if "final". + */ + vf_next = vio->vout_closing ; + while (vf_next != NULL) + { + vio_vf vf = vf_next ; + vf_next = ssl_next(vf, vout_next) ; - case VIN_SHELL: - break ; + uty_vf_write_close(vf, final) ; /* removes from vout_closing if + is now completely closed. */ + } ; - case VIN_FILE: - break ; + /* If is vio->cmd_running, this is as far as we can go this time. */ + if (vio->cmd_running) + return false ; - case VIN_PIPE: - break ; + /* Make sure no longer holding the config symbol of power */ + uty_config_unlock(vio->vty, NULL_NODE) ; - case VIN_CONFIG: - break ; + /* Flush the vout stack. + * + * If cannot completely close a vf, places it on the vout_closing list, + * except for the vout_base. + */ + uty_vout_close_stack(vio, final) ; + assert(vio->vout == vio->vout_base) ; + uty_vf_write_close(vio->vout, final) ; - default: - zabort("unknown VIN type") ; - } ; + /* See if have now successfully closed everything. */ + if ((vio->vout_closing != NULL) || (vio->vout_base->vout_state != vf_closed)) + return false ; /* something is still open */ - /* Finished if half closed the last on the list */ - if (vf == vio->vin_base) - break ; + /* Empty everything out of the vio and return the good news. + * + * NB: retains vio->vty & the vio->vio_list for death-watch. + */ + assert((vio->vin == vio->vin_base) && (vio->vin_depth == 0)) ; - /* Hack off head of list. If it is read-only, close & free. */ - ssl_del_head(vio->vin, vin_next) ; + if (vio->vin != vio->vout) + vio->vin = uty_vf_free(vio->vin) ; + else + vio->vin = NULL ; + vio->vin_base = NULL ; - if (vf->vout_type == VOUT_NONE) - uty_vf_close(vf) ; - } ; + assert((vio->vout == vio->vout_base) && (vio->vout_depth == 0)) ; - /* Make sure no longer holding the config symbol of power */ - uty_config_unlock(vio->vty, RESTRICTED_NODE) ; + vio->vout = uty_vf_free(vio->vout) ; - /* Move to the death watch list */ - sdl_del(vio_list_base, vio, vio_list) ; - sdl_push(vio_death_watch, vio, vio_list) ; + vio->close_reason = qs_reset(vio->close_reason, free_it) ; - vio->half_closed = true ; + vio->obuf = NULL ; + vio->state = vf_closed ; return true ; } ; /*------------------------------------------------------------------------------ - * Close VTY. - * + * Pop and close the top of the vin stack -- MUST NOT be vin_base. * + * Read closes the vio_vfd -- if the vio_vfd was read-only, this will fully + * close it, and the vio_vfd will have been freed. * - * If no reason for the close has already been set, sets the given reason. - * - * If not already half-closed, close all readers as described above, and then - * kick everything on the vout stack and apply VTY_HALF_CLOSE_TIMEOUT. + * If this is read-only will free the vio_vf and all its contents. * + * NB: a uty_cmd_prepare() is required before command processing can continue. * + * That is not done here because this may be called from outside the + * command loop -- in particular by uty_close(). */ extern void -uty_close (vty_io vio, const char* reason) +uty_vin_close(vty_io vio) { - if (uty_do_half_close(vio, reason)) - { - vio_vf vf ; + vio_vf vf ; - /* Run down the vout stack, and write-ready enable everything with - * the half close timeout set. - * - * This will have the effect of kicking all output. - */ - vf = vio->vout ; - while (vf != NULL) - { - vf->write_timeout = 0 ; - uty_vf_set_write(vf, on) ; + vf = vio->vin ; - vf = ssl_next(vf, vout_next) ; - } ; - } ; + assert(vf != vio->vin_base) ; + assert(vio->vin_depth > 0) ; + + ssl_del_head(vio->vin, vin_next) ; + --vio->vin_depth ; + + uty_vf_read_close(vf) ; } ; /*------------------------------------------------------------------------------ - * Closing down VTY. - * - * Shuts down everything and discards all buffers etc. etc. + * Pop and close the top of the vout stack -- MUST NOT be vout_base. * - * If cmd_in_progress, cannot complete the process -- but sets the closed - * flag. + * Moves the vio_vf to the vout_closing list. * - * Can call vty_close() any number of times. + * Before closing, push any outstanding output. * - * The vty structure is placed on death watch, which will finally free the - * structure once no longer cmd_in_progress. + * Unless "final", the close is soft, that is, if there is any output still + * outstanding does not actually close the vout. * + * If there is no outstanding output (or if final) will completely close the + * vf and free it. * - * If no reason for the close has already been set, sets the given reason. + * NB: a uty_cmd_prepare() is required before command processing can continue. * + * That is not done here because this may be called from outside the + * command loop -- in particular by uty_close(). */ extern void -uty_close_final(vty_io vio, const char* reason) +uty_vout_close(vty_io vio, bool final) { - VTY_ASSERT_LOCKED() ; - - /* If not already closed, close. */ - uty_do_half_close(vio, reason) ; /* set reason if required, and - make sure is half closed. */ - if (!vio->closed) - { - vio_vf vf ; - - /* Empty the vin stack */ - assert(vio->vin != NULL) ; - assert(vio->vin == vio->vin_base) ; - if (vio->vin != vio->vout_base) - uty_vf_close(vio->vin) ; - vio->vin_base = vio->vin = NULL ; - - /* Now kick everything in the vout stack, in case can get stuff - * written away. And then close. - */ - while (ssl_pop(&vf, vio->vout, vout_next) != NULL) - { - uty_vf_set_write(vf, off) ; /* stop any write ready... */ - vf->closing = true ; /* ...permanently. */ - - switch(vf->vout_type) /* tidy up each type */ - { - case VOUT_NONE: - break ; - - case VOUT_TERM: - break ; - - case VOUT_SHELL: - break ; - - case VOUT_FILE: - break ; - - case VOUT_PIPE: - break ; - - case VOUT_STDOUT: - break ; - - case VOUT_STDERR: - break ; - - default: - zabort("unknown VOUT type") ; - } ; - - uty_vf_close(vf) ; /* close and free */ - } ; + vio_vf vf ; - vio->vout_base = NULL ; /* stack is empty */ - vio->closed = true ; /* now closed */ - } ; + vf = vio->vout ; - /* Nothing more should happen, so can now release almost everything, - * the exceptions being the things that are related to a cmd_in_progress. - * - * All writing to buffers is suppressed, and as the sock has been closed, - * there will be no more read_ready or write_ready events. - */ - if (vio->name != NULL) - XFREE(MTYPE_VTY_NAME, vio->name) ; + assert(vf != vio->vout_base) ; + assert(vio->vout_depth > 0) ; - vio->key_stream = keystroke_stream_free(vio->key_stream) ; + ssl_del_head(vio->vout, vout_next) ; + --vio->vout_depth ; - qs_reset(&vio->cli_prompt_for_node, keep_it) ; - qs_reset(&vio->cl, keep_it) ; + ssl_push(vio->vout_closing, vf, vout_next) ; - { - qstring line ; - while ((line = vector_ream(vio->hist, keep_it)) != NULL) - qs_reset_free(line) ; - } ; + vio->obuf = vio->vout->obuf ; - /* The final stage cannot be completed if cmd_in_progress. - * - * The clx is pointed at by vty->buf -- containing the current command. - * - * Once everything is released, can take the vty off death watch, and - * release the vio and the vty. - */ - if (!vio->cmd_in_progress) - { - qs_reset(&vio->clx, keep_it) ; - vio->vty->buf = NULL ; - } ; + uty_vf_write_close(vf, final) ; } ; /*============================================================================== @@ -847,96 +740,294 @@ uty_close_final(vty_io vio, const char* reason) * * There are no errors, yet. * - * This leaves most things unset/NULL/false. Caller will want to set: + * This leaves most things unset/NULL/false. Caller will need to: + * + * - uty_vin_open() and/or uty_vout_open() + * + * - once those are done, the following optional items remain to be set + * if they are required: + * + * read_timeout -- default = 0 => no timeout + * write_timeout -- default = 0 => no timeout + * + * parse_type -- default = cmd_parse_standard + * reflect_enabled -- default = false + * out_enabled -- default = true iff vfd_io_write + * + * If vio->blocking, adds vfd_io_blocking to the io_type. * + * NB: if there is no fd for this vio_vf, it should be set to -1, and the + * type (recommend vfd_none) and io_type are ignored -- except for + * vfd_io_write and the out_enabled state. * + * A VTY_STDOUT or a VTY_STDERR (output only, to the standard I/O) can + * be set up without an fd, and with/without out_enabled. * - * Sets timeout to no timeout at all -- timeout is optional. + * A VTY_CONFIG_READ can be set up with the fd of the input file, but + * MUST be type = vfd_file and io_type = vfd_io_read -- because the fd + * is for input only. This will set out_enabled false (as required). + * The required VOUT_STDERR will be set by uty_vout_open(). */ extern vio_vf -uty_vf_new(vty_io vio, int fd, vfd_type_t type, vfd_io_type_t io_type) +uty_vf_new(vty_io vio, const char* name, int fd, vfd_type_t type, + vfd_io_type_t io_type) { vio_vf vf ; VTY_ASSERT_LOCKED() ; + if (vio->blocking) + io_type |= vfd_io_blocking ; + vf = XCALLOC (MTYPE_VTY, sizeof(struct vio_vf)) ; /* Zeroising the structure has set: * - * vin_type = 0 -- VIN_NONE - * vin_next = NULL -- not on a vin list, yet + * vio = X -- set below + * name = X -- set below + * + * vin_type = VIN_NONE -- see uty_vin_open() + * vin_state = vf_closed -- see uty_vin_open() + * vin_next = NULL -- see uty_vin_open() + * + * cli = NULL -- no CLI, yet + * + * ibuf = NULL -- none, yet -- see uty_vin_open() + * + * cl = zeros -- empty qstring (embedded) + * line_complete = false -- see uty_vout_open() + * line_number = 0 -- nothing yet + * line_step = 0 -- see uty_vout_open() + * + * parse_type = cmd_parse_standard + * reflect_enabled = false * - * vout_type = NULL -- VOUT_NONE - * vout_next = NULL -- not on a vout list, yet + * vout_type = VOUT_NONE -- see uty_vout_open() + * vout_state = vf_closed -- see uty_vout_open() + * vout_next = NULL -- see uty_vout_open() * - * obuf = NULL -- none, yet - * olc = NULL -- none, yet + * obuf = NULL -- none, yet -- see uty_vout_open() * - * blocking = false - * closing = false + * out_enabled = X -- set below: true iff vfd_io_write * - * read_open = false - * write_open = false - * error_seen = 0 -- no error seen, yet + * vfd = NULL -- no vfd, yet * - * read_timeout = 0 -- none - * write_timeout = 0 -- none + * blocking = false -- default is non-blocking I/O + * closing = false -- definitely not + * + * error_seen = 0 -- no error seen, yet + * + * read_on = false + * write_on = false + * + * read_timeout = 0 -- none + * write_timeout = 0 -- none */ confirm((VIN_NONE == 0) && (VOUT_NONE == 0)) ; + confirm(vf_closed == 0) ; + confirm(QSTRING_INIT_ALL_ZEROS) ; + confirm(cmd_parse_standard == 0) ; vf->vio = vio ; - vf->vfd = vio_fd_new(fd, type, io_type, vf) ; + + if (name != NULL) + vf->name = XSTRDUP(MTYPE_VTY_NAME, name) ; + + if (fd >= 0) + vf->vfd = vio_vfd_new(fd, type, io_type, vf) ; + + vf->out_enabled = ((io_type & vfd_io_write) != 0) ; return vf ; } ; /*------------------------------------------------------------------------------ - * Half close a vio_vf. + * Close the read side of the given vio_vf. + * + * Read closes the vio_vfd -- if the vio_vfd was read-only, this will fully + * close it, and the vio_vfd will have been freed. + * + * If this is read-only (ie vout_type == VOUT_NONE) will free the vio_vf as + * well as the vio_vfd -- unless this is the vin_base. * - * Half closes the vio_fd and shuts down all reading. If the vio_fd was - * read-only, the half-close will fully close it, and the vio_fd will have - * been freed. + * Note that read_close is effective immediately, there is no delay as there is + * with write_close -- so no need for a "final" option. */ static void -uty_vf_half_close(vio_vf vf) +uty_vf_read_close(vio_vf vf) { - /* the vfd level half close will close completely if is read only. */ - vf->vfd = vio_fd_half_close(vf->vfd) ; + assert(vf->vin_state != vf_closed) ; + + /* Do the vfd level read close and mark the vf no longer read_open */ + if (vf->vin_type < VIN_SPECIALS) + vf->vfd = vio_vfd_read_close(vf->vfd) ; + + vf->vin_state = vf_closed ; + vf->read_on = off ; + + /* Now the vin_type specific clean up. */ + switch(vf->vin_type) + { + case VIN_NONE: + zabort("invalid VIN_NONE") ; + break ; + + case VIN_TERM: + uty_term_read_close(vf) ; + break ; - vf->read_open = false ; /* no more read operations */ - vf->read_on = off ; /* of course */ + case VIN_VTYSH: + break ; - if (vf->vfd == NULL) /* check really was read-only */ - assert(!vf->write_open && !vf->read_on) ; + case VIN_FILE: + uty_file_read_close(vf) ; + break ; + + case VIN_PIPE: + break ; + + case VIN_CONFIG: + break ; + + case VIN_DEV_NULL: + break ; + + default: + zabort("unknown VIN type") ; + } ; + + if ((vf->vout_type == VOUT_NONE) && (vf != vf->vio->vin_base)) + uty_vf_free(vf) ; } ; /*------------------------------------------------------------------------------ - * Close given vio_vf and free the vio_vf structure and all its contents. + * Close the write side of the given vio_vf, if can. + * + * Pushes any outstanding output -- non-blocking if not a blocking vty. * - * Assumes has been removed from vio->vin and vio->vout ! + * The vio_vf MUST either be on the vout_closing list or be vout_base. + * The vio_vf MUST be write_open and MUST NOT be read_open. + * + * If output is empty, or if final, close the vf, then if it is on the + * vout_closing list, remove and free it. + * + * Returns whether output was empty or not. */ -static void -uty_vf_close(vio_vf vf) +static bool +uty_vf_write_close(vio_vf vf, bool final) +{ + bool empty ; + + assert((vf->vout_state != vf_closed) && (vf->vin_state == vf_closed)) ; + + /* Worry about remaining return input from vout pipe TODO */ + + /* Worry about appending the close reason to the vout_base TODO */ + + /* Now the vout_type specific clean up. */ + empty = false ; + + switch(vf->vout_type) + { + case VOUT_NONE: + zabort("invalid VOUT_NONE") ; + break ; + + case VOUT_TERM: + empty = uty_term_write_close(vf, final) ; + break ; + + case VOUT_VTYSH: + break ; + + case VOUT_FILE: + empty = uty_file_write_close(vf, final) ; + break ; + + case VOUT_PIPE: + break ; + + case VOUT_CONFIG: + break ; + + case VOUT_DEV_NULL: + case VOUT_STDOUT: + case VOUT_STDERR: + empty = true ; + break ; + + default: + zabort("unknown VOUT type") ; + } ; + + if (empty || final) + { + /* Do the vfd level close and mark the vf no longer write_open */ + if (vf->vout_type < VOUT_SPECIALS) + vf->vfd = vio_vfd_close(vf->vfd) ; + else + assert(vf->vfd == NULL) ; + + vf->vout_state = vf_closed ; + vf->write_on = off ; + + if (ssl_del(vf->vio->vout_closing, vf, vout_next)) + uty_vf_free(vf) ; + else + assert(vf == vf->vio->vout_base) ; + } ; + + return empty ; +} ; + +/*------------------------------------------------------------------------------ + * Free the given vio_vf structure and all its contents. + * + * Expects the vfd to already have been closed, but will close it if not. + * + * Expects any cli to be closed, but will close it if not. + * + * Assumes has been removed from any and all lists ! + */ +static vio_vf +uty_vf_free(vio_vf vf) { - vf->vfd = vio_fd_close(vf->vfd) ; + XFREE(MTYPE_VTY_NAME, vf->name) ; + + vf->ibuf = vio_fifo_reset(vf->ibuf, free_it) ; + vf->obuf = vio_fifo_reset(vf->obuf, free_it) ; + + qs_reset(vf->cl, keep_it) ; - vf->obuf = vio_fifo_reset_free(vf->obuf) ; - vf->olc = vio_lc_reset_free(vf->olc) ; + vf->cli = uty_cli_close(vf->cli, true) ; + vf->vfd = vio_vfd_close(vf->vfd) ; /* for completeness */ XFREE(MTYPE_VTY, vf) ; + + return NULL ; } ; /*------------------------------------------------------------------------------ + * + * + */ + + + + + +/*------------------------------------------------------------------------------ * Dealing with an I/O error on VTY socket * * If this is the first error for this VTY, produce suitable log message. * * If is a "monitor", turn that off, *before* issuing log message. */ -static int -uty_vf_error(vty_io vio, const char* what) +extern int +uty_vf_error(vio_vf vf, const char* what, int err) { + vty_io vio = vf->vio ; + VTY_ASSERT_LOCKED() ; VTY_ASSERT_CLI_THREAD() ; @@ -944,24 +1035,14 @@ uty_vf_error(vty_io vio, const char* what) uty_set_monitor(vio, 0) ; /* if this is the first error, log it */ - if (vio->sock.error_seen == 0) + if (vf->error_seen == 0) { - const char* type ; - switch (vio->vty_type) - { - case VTY_TERM: - type = "VTY Terminal" ; - break ; - case VTY_SHELL: - type = "VTY Shell Server" ; - break ; - default: - zabort("unknown VTY type for uty_file_error()") ; - } ; - - vio->sock.error_seen = errno ; + const char* type = "?" ; /* TODO */ + + + vf->error_seen = err ; uzlog(NULL, LOG_WARNING, "%s: %s failed on fd %d: %s", - type, what, vio->sock.fd, errtoa(vio->sock.error_seen, 0).str) ; + type, what, vio_vfd_fd(vf->vfd), errtoa(err, 0).str) ; } ; return -1 ; @@ -970,33 +1051,34 @@ uty_vf_error(vty_io vio, const char* what) /*------------------------------------------------------------------------------ * Set required read ready state. Applies the current read timeout. * - * Forces off if: vf->closing + * Forces off if: vf->vin_state != vf_open * - * Does nothing if: !vf->read_open + * Does nothing if: vf->vin_state == vf_closed * or: vf->vfd == NULL + * + * Returns new state of vf->read_on */ -extern on_off_t -uty_vf_set_read(vio_vf vf, on_off_t how) +extern on_off_b +uty_vf_set_read(vio_vf vf, on_off_b how) { - if (vf->closing) + if (vf->vin_state != vf_open) how = off ; - return vf->read_on = vf->read_open - ? vio_fd_set_read(vf->vfd, how, vf->read_timeout) + + return vf->read_on = (vf->vin_state != vf_closed) + ? vio_vfd_set_read(vf->vfd, how, vf->read_timeout) : off ; } ; /*------------------------------------------------------------------------------ * Set required read ready timeout -- if already read_on, restart it. * - * Forces read ready off if: vf->closing - * - * Does nothing if: !vf->read_open - * or: vf->vfd == NULL + * Returns new state of vf->read_on */ -extern on_off_t +extern on_off_b uty_vf_set_read_timeout(vio_vf vf, vty_timer_time read_timeout) { vf->read_timeout = read_timeout ; + return vf->read_on ? uty_vf_set_read(vf, on) : off ; } ; @@ -1004,34 +1086,34 @@ uty_vf_set_read_timeout(vio_vf vf, vty_timer_time read_timeout) /*------------------------------------------------------------------------------ * Set required write ready state. Applies the current write timeout. * - * Forces off if: vf->closing + * Forces off if: vf->vout_state != vf_open * - * Does nothing if: !vf->write_open + * Does nothing if: vf->vout_state == vf_closed * or: vf->vfd == NULL + * + * Returns new state of vf->write_on */ -extern on_off_t -uty_vf_set_write(vio_vf vf, on_off_t how) +extern on_off_b +uty_vf_set_write(vio_vf vf, on_off_b how) { - if (vf->closing) + if (vf->vout_state != vf_open) how = off ; - return vf->write_on = vf->write_open - ? vio_fd_set_write(vf->vfd, how, vf->write_timeout) + return vf->write_on = (vf->vout_state != vf_closed) + ? vio_vfd_set_write(vf->vfd, how, vf->write_timeout) : off ; } ; /*------------------------------------------------------------------------------ * Set required write ready timeout -- if already write_on, restart it. * - * Forces write ready off if: vf->closing - * - * Does nothing if: !vf->write_open - * or: vf->vfd == NULL + * Returns new state of vf->write_on */ -extern on_off_t +extern on_off_b uty_vf_set_write_timeout(vio_vf vf, vty_timer_time write_timeout) { vf->write_timeout = write_timeout ; + return vf->write_on ? uty_vf_set_write(vf, on) : off ; } ; @@ -1061,9 +1143,11 @@ uty_open_listeners(const char *addr, unsigned short port, const char *path) if (port) uty_term_open_listeners(addr, port) ; +#if 0 /* If want to listen for vtysh, set up listener now */ if (VTYSH_ENABLED && (path != NULL)) uty_serv_vtysh(path) ; +#endif } ; /*------------------------------------------------------------------------------ @@ -1072,7 +1156,7 @@ uty_open_listeners(const char *addr, unsigned short port, const char *path) * Adds to list of listeners for close down. */ extern void -uty_add_listener(int fd, vio_fd_accept* accept_action) +uty_add_listener(int fd, vio_vfd_accept* accept_action) { vio_listener vl ; |