xorp

cli_client.hh

00001 // -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-
00002 
00003 // Copyright (c) 2001-2011 XORP, Inc and Others
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License, Version 2, June
00007 // 1991 as published by the Free Software Foundation. Redistribution
00008 // and/or modification of this program under the terms of any other
00009 // version of the GNU General Public License is not permitted.
00010 // 
00011 // This program is distributed in the hope that it will be useful, but
00012 // WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
00014 // see the GNU General Public License, Version 2, a copy of which can be
00015 // found in the XORP LICENSE.gpl file.
00016 // 
00017 // XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
00018 // http://xorp.net
00019 
00020 // $XORP: xorp/cli/cli_client.hh,v 1.38 2008/10/02 21:56:29 bms Exp $
00021 
00022 
00023 #ifndef __CLI_CLI_CLIENT_HH__
00024 #define __CLI_CLI_CLIENT_HH__
00025 
00026 //
00027 // CLI client definition.
00028 //
00029 
00030 #include "libxorp/xorp.h"
00031 #include "libxorp/buffer.hh"
00032 #include "libxorp/ipvx.hh"
00033 #include "libxorp/xorpfd.hh"
00034 #include "libxorp/eventloop.hh"
00035 #include "libxorp/timer.hh"
00036 #include "cli_node.hh"
00037 
00038 
00039 
00040 
00041 //
00042 // Constants definitions
00043 //
00044 
00045 //
00046 // Structures/classes, typedefs and macros
00047 //
00048 
00049 class CliNode;
00050 class CliCommand;
00051 
00057 class CliClient {
00058 public:
00069     CliClient(CliNode& init_cli_node, XorpFd input_fd, XorpFd output_fd,
00070           const string& startup_cli_prompt);
00071 
00075     virtual ~CliClient();
00076 
00084     bool done() const;
00085 
00092     int     start_connection(string& error_msg);
00093 
00100     int     stop_connection(string& error_msg);
00101     
00109     int     cli_print(const string& msg);
00110     
00116     int     cli_flush();
00117     
00125     int     set_log_output(bool v);
00126     
00133     bool    is_log_output() const { return (_is_log_output); }
00134     
00140     XorpFd  input_fd() { return (_input_fd); }
00141 
00147     XorpFd  output_fd() { return (_output_fd); }
00148     
00155     bool    is_input_tty() const;
00156 
00163     bool    is_output_tty() const;
00164 
00171     bool    is_network() const;
00172 
00178     void    set_network_client(bool v);
00179 
00186     bool    is_telnet() const;
00187 
00194     bool    is_interactive() const;
00195 
00196     //
00197     // Session info
00198     //
00204     const string& cli_session_user_name() const {
00205     return (_cli_session_user_name);
00206     }
00207     
00213     const string& cli_session_term_name() const {
00214     return (_cli_session_term_name);
00215     }
00216 
00217     /*
00218      * Get the user network address.
00219      * 
00220      * @return the user network address.
00221      */
00222     const IPvX& cli_session_from_address() const {
00223     return (_cli_session_from_address);
00224     }
00225 
00232     const TimeVal& cli_session_start_time() const {
00233     return (_cli_session_start_time);
00234     }
00235 
00242     const TimeVal& cli_session_stop_time() const {
00243     return (_cli_session_stop_time);
00244     }
00245     
00252     bool    is_cli_session_active() const {
00253     return (_is_cli_session_active);
00254     }
00255     
00261     uint32_t    cli_session_session_id() const {
00262     return (_cli_session_session_id);
00263     }
00264     
00270     void    set_cli_session_user_name(const string& v) {
00271     _cli_session_user_name = v;
00272     }
00273     
00279     void    set_cli_session_term_name(const string& v) {
00280     _cli_session_term_name = v;
00281     }
00282     
00288     void    set_cli_session_from_address(const IPvX& v) {
00289     _cli_session_from_address = v;
00290     }
00291     
00297     void    set_cli_session_start_time(const TimeVal& v) {
00298     _cli_session_start_time = v;
00299     }
00300     
00306     void    set_cli_session_stop_time(const TimeVal& v) {
00307     _cli_session_stop_time = v;
00308     }
00309     
00316     void    set_is_cli_session_active(bool v) {
00317     _is_cli_session_active = v;
00318     }
00319     
00325     void    set_cli_session_session_id(uint32_t v) {
00326     _cli_session_session_id = v;
00327     }
00328     
00332     void post_process_command();
00333 
00337     void flush_process_command_output();
00338     
00339     //
00340     // Server communication state
00341     //
00348     bool is_waiting_for_data() const { return (_is_waiting_for_data); }
00349     
00356     void set_is_waiting_for_data(bool v);
00357     
00363     const string& current_cli_prompt() const { return (_current_cli_prompt); }
00364     
00370     void    set_current_cli_prompt(const string& cli_prompt);
00371 
00375     void    terminal_resized();
00376     
00377 private:
00378     friend class CliPipe;
00379     
00380     CliNode&    cli_node() { return (_cli_node); }
00381     
00382     GetLine *gl() { return (_gl); }
00383 
00393     int     process_telnet_option(int val, bool& is_telnet_option);
00394     
00395     bool    telnet_iac() { return (_telnet_iac); }
00396     void    set_telnet_iac(bool v) { _telnet_iac = v; }
00397     bool    telnet_sb() { return (_telnet_sb); }
00398     void    set_telnet_sb(bool v) {_telnet_sb = v; }
00399     bool    telnet_dont() { return (_telnet_dont); }
00400     void    set_telnet_dont(bool v) { _telnet_dont = v; }
00401     bool    telnet_do() { return (_telnet_do); }
00402     void    set_telnet_do(bool v) { _telnet_do = v; }
00403     bool    telnet_wont() { return (_telnet_wont); }
00404     void    set_telnet_wont(bool v) { _telnet_wont = v; }
00405     bool    telnet_will() { return (_telnet_will); }
00406     void    set_telnet_will(bool v) { _telnet_will = v; }
00407     bool    telnet_binary() { return (_telnet_binary); }
00408     void    set_telnet_binary(bool v) { _telnet_binary = v; }
00409 
00410     void    update_terminal_size();
00411 
00412     size_t  window_width() { return ((size_t)_window_width); }
00413     void    set_window_width(uint16_t v) { _window_width = v; }
00414     size_t  window_height() { return ((size_t)_window_height); }
00415     void    set_window_height(uint16_t v) { _window_height = v; }
00416     
00417     Buffer& command_buffer() { return (_command_buffer); }
00418     Buffer& telnet_sb_buffer() { return (_telnet_sb_buffer); }
00419     
00420     
00421     CliCommand  *cli_command_root() { return (cli_node().cli_command_root());}
00422     int     buff_curpos() { return (_buff_curpos); }
00423     void    set_buff_curpos(int v) { _buff_curpos = v; }
00424     
00425     CliCommand  *current_cli_command() { return (_current_cli_command); }
00426     void    set_current_cli_command(CliCommand *v);
00427     
00428     int     process_command(const string& command_line);
00429     void    interrupt_command();
00430     
00431     CliPipe *add_pipe(const string& pipe_name);
00432     CliPipe *add_pipe(const string& pipe_name,
00433               const list<string>& args_list);
00434     void    delete_pipe_all();
00435     bool    is_pipe_mode() { return (_is_pipe_mode); }
00436     void    set_pipe_mode(bool v) { _is_pipe_mode = v; }
00437     
00438     int     block_connection(bool is_blocked);
00439     void    client_read(XorpFd fd, IoEventType type);
00440     void    process_input_data();
00441     void    schedule_process_input_data();
00442     
00443     static  CPL_MATCH_FN(command_completion_func);
00444     int     process_char(const string& line, uint8_t val,
00445                  bool& stop_processing);
00446     int     process_char_page_mode(uint8_t val);
00447     int     preprocess_char(uint8_t val, bool& stop_processing);
00448     void    command_line_help(const string& line, int word_end,
00449                   bool remove_last_input_char);
00450     bool    is_multi_command_prefix(const string& command_line);
00451     
00452     void    process_line_through_pipes(string& pipe_line);
00453     // Output paging related functions
00454     bool    is_page_mode() { return (_is_page_mode); }
00455     void    set_page_mode(bool v);
00456     bool    is_page_buffer_mode() { return (*_is_page_buffer_mode); }
00457     void    set_page_buffer_mode(bool v) { *_is_page_buffer_mode = v; }
00458     vector<string>& page_buffer() { return (*_page_buffer); }
00459     const string& page_buffer_line(size_t line_n) const;
00460     void    reset_page_buffer() { page_buffer().clear(); set_page_buffer_last_line_n(0); }
00461     size_t  page_buffer_lines_n() { return (page_buffer().size()); }
00462     void    append_page_buffer_line(const string& buffer_line);
00463     void    concat_page_buffer_line(const string& buffer_line, size_t pos);
00464     size_t  page_buffer_last_line_n() { return (*_page_buffer_last_line_n); }
00465     void    set_page_buffer_last_line_n(size_t v) { *_page_buffer_last_line_n = v; }
00466     void    incr_page_buffer_last_line_n() { (*_page_buffer_last_line_n)++; }
00467     void    decr_page_buffer_last_line_n() { (*_page_buffer_last_line_n)--; }
00468     size_t  page_buffer_window_lines_n();
00469     size_t  page_buffer_last_window_line_n();
00470     size_t  page_buffer2window_line_n(size_t buffer_line_n);
00471     size_t  window_lines_n(size_t buffer_line_n);
00472     size_t  calculate_first_page_buffer_line_by_window_size(
00473     size_t last_buffer_line_n,
00474     size_t max_window_size);
00475 
00476     bool    is_help_mode() { return (_is_help_mode); }
00477     void    set_help_mode(bool v) { _is_help_mode = v; }
00478     bool    is_nomore_mode() { return (_is_nomore_mode); }
00479     void    set_nomore_mode(bool v) { _is_nomore_mode = v; }
00480     bool    is_hold_mode() { return (_is_hold_mode); }
00481     void    set_hold_mode(bool v) { _is_hold_mode = v; }
00482     bool    is_prompt_flushed() const { return _is_prompt_flushed; }
00483     void    set_prompt_flushed(bool v) { _is_prompt_flushed = v; }
00484 
00485     CliNode&    _cli_node;      // The CLI node I belong to
00486     XorpFd  _input_fd;      // File descriptor to read the input
00487     XorpFd  _output_fd;     // File descriptor to write the output
00488     FILE    *_input_fd_file;    // The FILE version of _input_fd
00489     FILE    *_output_fd_file;   // The FILE version of _output_fd
00490     
00491     enum ClientType{
00492     CLIENT_MIN      = 0,
00493     CLIENT_TERMINAL     = 0,
00494     CLIENT_FILE     = 1,
00495     CLIENT_MAX
00496     };
00497     ClientType  _client_type;       // Type of the client: term, file, etc.
00498     GetLine *_gl;           // The GetLine for libtecla
00499     
00500     bool    _telnet_iac;        // True if the last octet was IAC
00501     bool    _telnet_sb;     // True if subnegotiation has began
00502     bool    _telnet_dont;       // True if the last octet was DONT
00503     bool    _telnet_do;     // True if the last octet was DO
00504     bool    _telnet_wont;       // True if the last octet was WONT
00505     bool    _telnet_will;       // True if the last octet was WILL
00506     bool    _telnet_binary;     // True if the client "do" binary mode
00507     
00508     uint16_t    _window_width;      // The CLI client window width
00509     uint16_t    _window_height;     // The CLI client window height
00510     Buffer  _command_buffer;
00511     Buffer  _telnet_sb_buffer;
00512     
00513     // The modified terminal flags
00514     bool    _is_modified_stdio_termios_icanon;
00515     bool    _is_modified_stdio_termios_echo;
00516     bool    _is_modified_stdio_termios_isig;
00517     //
00518     // The original VMIN and VTIME members of the termios.c_cc[] array.
00519     // TODO: those should have type cc_t, but we are using 'int' instead
00520     // to avoid complicated conditional declarations.
00521     //
00522     int     _saved_stdio_termios_vmin;
00523     int     _saved_stdio_termios_vtime;
00524 
00525     // The command we are currently executing and its arguments
00526     CliCommand  *_executed_cli_command; // The command currently executed
00527     vector<string> _executed_cli_command_name;  // The command name
00528     vector<string> _executed_cli_command_args;  // The arguments
00529     
00530     CliCommand  *_current_cli_command;  // The command we have "cd" to
00531     string  _current_cli_prompt;    // The CLI prompt
00532     int     _buff_curpos;       // The cursor position in the buffer
00533     
00534     string  _buffer_line;       // To buffer data when pipe-processing
00535     list<CliPipe *> _pipe_list;     // A list with the CLI pipe commands
00536     bool    _is_pipe_mode;      // True if pipe processing enabled
00537     bool    _is_nomore_mode;    // True if disabled "more" mode
00538     bool    _is_hold_mode;      // True if enabled "hold" mode
00539     
00540     // Output paging related stuff
00541     bool    _is_page_mode;      // True if the output is paged
00542     
00543     bool    *_is_page_buffer_mode;  // True if enabled page_buffer_mode
00544     vector<string> *_page_buffer;
00545     size_t  *_page_buffer_last_line_n;
00546     
00547     bool    _is_output_buffer_mode; // True if enabled output_buffer_mode
00548     vector<string> _output_buffer;  // The output buffer: line per element
00549     size_t  _output_buffer_last_line_n; // The current last (visable) line
00550     
00551     bool    _is_help_buffer_mode;   // True if enabled help_buffer_mode
00552     vector<string> _help_buffer;    // The help buffer: line per element
00553     size_t  _help_buffer_last_line_n; // The current last (visable) line
00554     bool    _is_help_mode;      // True if enabled help mode
00555     
00556     bool    _is_prompt_flushed; // True if we have flushed the prompt
00557     
00558     // The strings to save the action names that some keys were bind to
00559     string  _action_name_up_arrow;
00560     string  _action_name_down_arrow;
00561     string  _action_name_tab;
00562     string  _action_name_newline_n;
00563     string  _action_name_newline_r;
00564     string  _action_name_spacebar;
00565     string  _action_name_ctrl_a;
00566     string  _action_name_ctrl_b;
00567     string  _action_name_ctrl_c;
00568     string  _action_name_ctrl_d;
00569     string  _action_name_ctrl_e;
00570     string  _action_name_ctrl_f;
00571     string  _action_name_ctrl_h;
00572     string  _action_name_ctrl_k;
00573     string  _action_name_ctrl_l;
00574     string  _action_name_ctrl_m;
00575     string  _action_name_ctrl_n;
00576     string  _action_name_ctrl_p;
00577     string  _action_name_ctrl_u;
00578     string  _action_name_ctrl_x;
00579     
00580     //
00581     // Session info state
00582     //
00583     string  _cli_session_user_name;
00584     string  _cli_session_term_name;
00585     IPvX    _cli_session_from_address;
00586     TimeVal _cli_session_start_time;
00587     TimeVal _cli_session_stop_time;
00588     bool    _is_cli_session_active;
00589     uint32_t    _cli_session_session_id;    // The unique session ID.
00590     bool    _is_network;
00591     
00592     //
00593     // Log-related state
00594     //
00595     bool    _is_log_output;
00596     
00597     //
00598     // Server communication state
00599     //
00600     bool _is_waiting_for_data;      // True if waiting for external data
00601 
00602     //
00603     // Misc state
00604     //
00605     vector<uint8_t> _pending_input_data;
00606     XorpTimer       _process_pending_input_data_timer;
00607 };
00608 
00609 
00610 //
00611 // Global variables
00612 //
00613 
00614 
00615 //
00616 // Global functions prototypes
00617 //
00618 
00619 #endif // __CLI_CLI_CLIENT_HH__
 All Classes Namespaces Functions Variables Typedefs Enumerations