summaryrefslogtreecommitdiffstats
path: root/lib/vty_io.h
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vty_io.h')
-rw-r--r--lib/vty_io.h257
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) ;