diff options
Diffstat (limited to 'lib/vty_io.h')
-rw-r--r-- | lib/vty_io.h | 257 |
1 files changed, 180 insertions, 77 deletions
diff --git a/lib/vty_io.h b/lib/vty_io.h index 5db12ca2..24790526 100644 --- a/lib/vty_io.h +++ b/lib/vty_io.h @@ -36,6 +36,7 @@ #include "thread.h" #include "command_execute.h" #include "qstring.h" +#include "list_util.h" /*============================================================================== * Structures and other definitions for the top level VTY I/O. @@ -92,9 +93,9 @@ enum vio_out_type /* Command output */ VOUT_VTYSH, /* a vty_shell output pipe */ VOUT_FILE, /* ordinary file */ - VOUT_PIPE, /* pipe (to child process) */ + VOUT_PIPE, /* pipe (to child process, and back again) */ - VOUT_CONFIG, /* config file ?? */ + VOUT_CONFIG, /* config file */ /* The VOUT types >= VOUT_SPECIALS do not have an associated fd. * @@ -105,32 +106,73 @@ enum vio_out_type /* Command output */ VOUT_DEV_NULL = VOUT_SPECIALS, /* black hole output */ + VOUT_SHELL_ONLY, /* pipe (but only back from child process */ + VOUT_STDOUT, /* stdout */ VOUT_STDERR, /* stderr */ }; typedef enum vio_out_type vio_out_type_t ; /*------------------------------------------------------------------------------ - * State of a vf or of the entire vio. - * - * For a vf: I/O is possible iff vf_open -- has separate state for vin/vout. - * - * For a vio: used to manage the closing process. + * State of a vf -- has separate state for vin/vout. */ enum vf_state { - vf_closed = 0, /* not active -- may be discarded */ + vf_closed = 0, /* the vf has not been opened, or has been + * completely closed -- there will be no vfd. */ + + vf_open, /* the vf has been opened, and any required vfd + * is open and I/O is possible. */ + + vf_eof, /* for a vin: end of file has been reached or + * input has been terminated. The vfd may have + * been closed -- but in any case no further + * I/O should be attempted, and any buffered + * input will be discarded. */ - vf_open = 1, /* open for business */ + vf_closing, /* for a vout: open, but in process of closing. + * May still output stuff. */ - vf_eof = 2, /* open, but at eof */ - vf_error = 3, /* open, but error reported */ + vf_error, /* an I/O error has been reported. + * The vfd may or may not have been closed and + * I/O may or may not be possible TODO */ - vf_closing = 4, /* open, but in process of closing */ + vf_timed_out, /* a timout has been reported. + * The vfd may or may not have been closed and + * I/O may or may not be possible TODO */ } ; typedef enum vf_state vf_state_t ; /*------------------------------------------------------------------------------ + * vio_child structure. + * + * Lives on the vio_childer_list until collected or "curtains". + * + */ +typedef enum vio_child_await vio_child_await_t ; + +struct vio_vf ; /* Forward reference */ +typedef struct vio_vf* vio_vf ; + +typedef struct vio_child* vio_child ; + +struct vio_child +{ + struct dl_list_pair(vio_child) list ; /* in the list of children */ + + vio_vf parent ; + + pid_t pid ; + bool collected ; /* waitpid() done */ + int report ; /* from waitpid() */ + + bool overdue ; /* patience exhausted */ + + bool awaited ; /* if child is awaited -- !vf->blocking */ + vio_timer timer ; /* limit the waiting time */ +} ; + +/*------------------------------------------------------------------------------ * vty_vf -- "vty file" structure * * A vio_vf may be a read, write or read/write object. @@ -148,8 +190,6 @@ typedef enum vf_state vf_state_t ; struct vty_io ; /* Forward reference */ typedef struct vty_io* vty_io ; -typedef struct vio_vf* vio_vf ; - struct vio_vf { vty_io vio ; /* parent */ @@ -162,28 +202,28 @@ struct vio_vf vf_state_t vin_state ; vio_vf vin_next ; /* list of inputs */ + cmd_context context ; /* pushed exec->context. */ struct vty_cli* cli ; /* NULL if not a VTY_TERMINAL ! */ vio_fifo ibuf ; /* input fifo (if required) */ - qstring_t cl ; /* command line buffer */ + qstring cl ; /* command line buffer */ bool line_complete ; /* false => line in construction */ uint line_number ; /* number of first line in cl */ uint line_step ; /* number of real lines in cl */ - cmd_parse_type_t parse_type ; /* iff vin_type != VIN_NONE */ - bool reflect_enabled ; /* false if vin_type == VIN_NONE */ - /* Output side. */ vio_out_type_t vout_type ; vf_state_t vout_state ; vio_vf vout_next ; /* list of outputs */ + vio_vf pr_master ; /* receiving return stuff from there */ + vio_fifo obuf ; /* output fifo (if required) */ - bool out_enabled ; /* false if vout_type == VOUT_NONE */ + uint depth_mark ; /* depth of this vout */ /* I/O */ @@ -193,12 +233,19 @@ struct vio_vf int error_seen ; /* non-zero => failed */ - on_off_b read_on ; - on_off_b write_on ; - vty_timer_time read_timeout ; vty_timer_time write_timeout ; + /* Pipe extras */ + + vio_child child ; /* state of child */ + + vf_state_t pr_state ; /* iff pipe */ + vio_vfd pr_vfd ; /* if pr_state == vf_open */ + + vio_vf pr_slave ; /* sending return stuff to there */ + + bool pr_only ; /* no vfd */ } ; enum vty_readiness /* bit significant */ @@ -206,11 +253,36 @@ enum vty_readiness /* bit significant */ not_ready = 0, read_ready = BIT(0), write_ready = BIT(1), /* may take precedence */ - now_ready = BIT(2) } ; typedef enum vty_readiness vty_readiness_t ; /*------------------------------------------------------------------------------ + * State of a vty command loop. + */ +enum vc_state +{ + vc_null = 0, /* the command loop has not yet been entered. */ + + vc_running, /* the command loop is running, and the vty is + * in its hands. */ + + vc_io_error_trap, /* the command loop is running, but an I/O + * error has been posted. */ + + vc_close_trap, /* the command loop is running, but the vty is + * reset and must be closed */ + + vc_waiting, /* the command loop is waiting for I/O. */ + + vc_stopped, /* the command loop has stopped, the vty is due + to be closed (loop cannot run again) */ + + vc_closed, /* the command loop has finished and the vty + * has been closed. */ +} ; +typedef enum vc_state vc_state_t ; + +/*------------------------------------------------------------------------------ * The vty_io structure * * The main elements of the vty_io object are the vin and vout stacks. @@ -223,7 +295,7 @@ typedef enum vty_readiness vty_readiness_t ; * * * - * "cmd_running" means that the VTY is in hands of (or has been passed to) + * "cmd_running" means that the VTY is in hands of (or has been passed to) TODO * a command loop -- the VTY cannot be fully closed until that is no * longer the case. * @@ -237,7 +309,7 @@ typedef enum vty_readiness vty_readiness_t ; * * - any further attempts to read will give "eof" * - * - there may be a command in execution -- see "cmd_running". + * - there may be a command in execution -- see "cmd_running". TODO * * - further writing will be honoured. * @@ -265,62 +337,82 @@ struct vty_io /* typedef appears above */ vio_vf vin_base ; uint vin_depth ; + uint real_depth ; /* less than vin_depth when closing */ + vio_vf vout ; /* vout stack */ vio_vf vout_base ; uint vout_depth ; - vio_vf vout_closing ; /* vout closing list */ + uint depth_mark ; /* vin_depth before pipes opened */ + + /* Error handling */ + bool err_hard ; /* eg I/O error */ + vio_fifo ebuf ; /* buffer for error message */ /* List of all vty_io objects */ struct dl_list_pair(vty_io) vio_list ; - /* List of all vty_io that are in monitor state */ - struct dl_list_pair(vty_io) mon_list ; - - /* VTY state + /* State * * "blocking" is set for configuration reading VTY, so that everything is * done with blocking I/O. * - * "half_closed" means that the vty has been closed (!), but a command - * and or output may still be active: - * - * - if is a socket, will have shut_down the read side (half-closed) - * - * - any further attempts to read will give "eof" - * - * - there may be a command in execution -- see "cmd_running". - * - * - further writing will be honoured. - * - * - the write side may still be active, attempting to empty out any - * pending output. - * - * "cmd_running" means that the VTY is in hands of (or has been passed to) - * a command loop -- the VTY cannot be fully closed until that is no - * longer the case. - * - * "closed" means the vty has been fully and finally closed. - * - * - any further attempts to write will be ignored, but return instant - * success. + * "state" as described above. + */ + bool blocking ; /* => all I/O is blocking. */ + + vc_state_t state ; + + char* close_reason ; /* MTYPE_TMP (if any) */ + + /* For ease of output, pointer to current vout->obuf * - * - the file/socket has been fully closed. + * Even when the vty is almost closed, there will remain a valid obuf, + * though anything sent to it under those conditions will be discarded. + */ + vio_fifo obuf ; + + /* The following is for "vty monitor". * - * - the VTY and all attached structures can be reaped by the death_watch. + * With the exception of the "monitor" flag, need the LOG_MUTEX in order + * to change any of this. */ - bool blocking ; /* => all I/O is blocking. */ + bool monitor ; /* is in monitor state */ - bool cmd_running ; /* => cannot be fully closed */ + bool mon_kick ; /* vty needs a kick */ + int maxlvl ; /* message level wish to see */ - vf_state_t state ; + vio_fifo mbuf ; /* monitor output pending */ - qstring close_reason ; /* message to be sent, once all other - output has completed, giving reason - for closing the VTY. */ + /* List of all vty_io that are in monitor state */ + struct dl_list_pair(vty_io) mon_list ; +} ; - /* For ease of output, pointer to current vout->obuf */ - vio_fifo obuf ; /* NULL => no vout ! */ +/*============================================================================== + * Assertions for suitable state to close things ! + */ +Inline void +VTY_ASSERT_CAN_CLOSE(vty vty) +{ + if (vty_debug) + { + VTY_ASSERT_LOCKED() ; + + if (!vty->vio->blocking && !vty_is_cli_thread()) + VTY_ASSERT_FAILED() ; + } ; +} ; + +Inline void +VTY_ASSERT_CAN_CLOSE_VF(vio_vf vf) +{ + if (vty_debug) + { + VTY_ASSERT_LOCKED() ; + + if (!vf->blocking && !vty_is_cli_thread()) + VTY_ASSERT_FAILED() ; + } ; } ; /*============================================================================== @@ -334,35 +426,46 @@ Inline void uty_out_clear(vty_io vio) ; Inline void uty_out_accept(vty_io vio) ; Inline void uty_out_reject(vty_io vio) ; -extern vty uty_new (vty_type_t type) ; -extern bool uty_close(vty_io vio, bool final, qstring reason) ; - -extern void uty_vin_close(vty_io vio) ; -extern void uty_vout_close(vty_io vio, bool final) ; -extern void uty_vin_close_stack(vty_io vio) ; -extern void uty_vout_close_stack(vty_io vio, bool final) ; +extern vty uty_new (vty_type_t type, node_type_t node) ; +extern void uty_close(vty_io vio, const char* reason, bool curtains) ; extern void uty_set_timeout(vty_io vio, vty_timer_time timeout) ; -extern void uty_vin_open(vty_io vio, vio_vf vf, vio_in_type_t type, +extern void uty_vin_new_context(vty_io vio, cmd_context context, + qpath file_here) ; +extern void uty_vin_push(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) ; -extern void uty_vout_open(vty_io vio, vio_vf vf, vio_out_type_t type, +extern void uty_vout_push(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) ; +extern cmd_return_code_t uty_vin_pop(vty_io vio, bool final, + cmd_context context) ; +extern cmd_return_code_t uty_vout_pop(vty_io vio, bool final) ; + extern vio_vf uty_vf_new(vty_io vio, const char* name, int fd, vfd_type_t type, vfd_io_type_t io_type) ; -extern on_off_b uty_vf_set_read(vio_vf vf, on_off_b on) ; -extern on_off_b uty_vf_set_read_timeout(vio_vf vf, - vty_timer_time read_timeout) ; -extern on_off_b uty_vf_set_write(vio_vf vf, on_off_b on) ; -extern on_off_b uty_vf_set_write_timeout(vio_vf vf, - vty_timer_time write_timeout) ; +extern void uty_vf_set_read(vio_vf vf, on_off_b on) ; +extern void uty_vf_set_read_timeout(vio_vf vf, vty_timer_time read_timeout) ; +extern void uty_vf_set_write(vio_vf vf, on_off_b on) ; +extern void uty_vf_set_write_timeout(vio_vf vf, vty_timer_time write_timeout) ; extern int uty_vf_error(vio_vf vf, const char* what, int err) ; +extern vio_child uty_child_register(pid_t pid, vio_vf parent) ; +extern void vty_child_close_register(void) ; +extern void uty_child_awaited(vio_child child, vty_timer_time timeout) ; +extern bool uty_child_collect(vio_child child, vty_timer_time timeout, + bool final) ; +extern vio_child uty_child_dismiss(vio_child child, bool final) ; +extern void uty_sigchld(void) ; + +extern void uty_child_signal_nexus_set(vty_io vio) ; +extern void vty_child_signal_nexus_signal(void) ; +extern void uty_child_signal_nexus_clear(vty_io vio) ; + extern void uty_open_listeners(const char *addr, unsigned short port, const char *path) ; |