File: cli_client.hh

package info (click to toggle)
xorp 1.8.5-4
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 28,560 kB
  • ctags: 54,995
  • sloc: cpp: 397,204; sh: 17,490; ansic: 17,029; python: 7,643; lex: 1,632; yacc: 1,474; awk: 956; makefile: 251; perl: 217; sed: 33
file content (619 lines) | stat: -rw-r--r-- 19,131 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
// -*- c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t -*-

// Copyright (c) 2001-2011 XORP, Inc and Others
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, Version 2, June
// 1991 as published by the Free Software Foundation. Redistribution
// and/or modification of this program under the terms of any other
// version of the GNU General Public License is not permitted.
// 
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details,
// see the GNU General Public License, Version 2, a copy of which can be
// found in the XORP LICENSE.gpl file.
// 
// XORP Inc, 2953 Bunker Hill Lane, Suite 204, Santa Clara, CA 95054, USA;
// http://xorp.net

// $XORP: xorp/cli/cli_client.hh,v 1.38 2008/10/02 21:56:29 bms Exp $


#ifndef __CLI_CLI_CLIENT_HH__
#define __CLI_CLI_CLIENT_HH__

//
// CLI client definition.
//

#include "libxorp/xorp.h"
#include "libxorp/buffer.hh"
#include "libxorp/ipvx.hh"
#include "libxorp/xorpfd.hh"
#include "libxorp/eventloop.hh"
#include "libxorp/timer.hh"
#include "cli_node.hh"




//
// Constants definitions
//

//
// Structures/classes, typedefs and macros
//

class CliNode;
class CliCommand;

/**
 * @short The class for the CLI client.
 * 
 * There is one CLI client per CLI user (e.g., telnet connection).
 */
class CliClient {
public:
    /**
     * Constructor for a given CLI node and file descriptor.
     * 
     * @param init_cli_node the @ref CliNode CLI node this client belongs to.
     * @param input_fd the file descriptor for the CLI client to read
     * data from.
     * @param output_fd the file descriptor for the CLI client to write
     * data to.
     * @param startup_cli_prompt the startup CLI prompt.
     */
    CliClient(CliNode& init_cli_node, XorpFd input_fd, XorpFd output_fd,
	      const string& startup_cli_prompt);

    /**
     * Destructor
     */
    virtual ~CliClient();

    /**
     * Test if the processing of any pending commands or pending data has
     * complated.
     * 
     * @return true if processing of any pending commands or pending data
     * has completed, otherwise false.
     */
    bool done() const;

    /**
     * Start the connection.
     * 
     * @param error_msg the error message (if error).
     * @return XORP_OK on success, otherwise XORP_ERROR.
     */
    int		start_connection(string& error_msg);

    /**
     * Stop the connection.
     * 
     * @param error_msg the error message (if error).
     * @return XORP_OK on success, otherwise XORP_ERROR.
     */
    int		stop_connection(string& error_msg);
    
    /**
     * Print a message to the CLI user.
     * 
     * @param msg C++ string with the message to display.
     * @return the number of characters printed (not including
     * the trailing '\0').
     */
    int		cli_print(const string& msg);
    
    /**
     * Flush the CLI output.
     * 
     * @return XORP_OK on success, otherwise XORP_ERROR.
     */
    int		cli_flush();
    
    /**
     * Add/remove this client for displaying log messages.
     * 
     * @param v if true, add this client for displaying messages, otherwise
     * remove it.
     * @return XORP_OK on success, otherwise XORP_ERROR.
     */
    int		set_log_output(bool v);
    
    /**
     * Test if this client has been added for displaying log messages.
     * 
     * @return true if this client has been added for displaying log messages,
     * otherwise false.
     */
    bool	is_log_output() const { return (_is_log_output); }
    
    /**
     * Get the file descriptor for reading the input from the user.
     * 
     * @return the file descriptor for reading the input from the user.
     */
    XorpFd	input_fd() { return (_input_fd); }

    /**
     * Get the file descriptor for writing the output to the user.
     * 
     * @return the file descriptor for writing the output to the user.
     */
    XorpFd	output_fd() { return (_output_fd); }
    
    /**
     * Test if this client is associated with a terminal type input device.
     * 
     * @return true if this client is associated with a terminal type input
     * device, otherwise false.
     */
    bool	is_input_tty() const;

    /**
     * Test if this client is associated with a terminal type output device.
     * 
     * @return true if this client is associated with a terminal type output
     * device, otherwise false.
     */
    bool	is_output_tty() const;

    /**
     * Test if this client is associated with a network connection.
     * 
     * @return true if this client is associated with a network connection,
     * otherwise false.
     */
    bool	is_network() const;

    /**
     * Set the flag that associates the client with a network connection.
     * 
     * @param v true if this client is associated with a network connection.
     */
    void	set_network_client(bool v);

    /**
     * Test if this client is associated with a telnet connection.
     * 
     * @return true if this client is associated with a telnet connection,
     * otherwise false.
     */
    bool	is_telnet() const;

    /**
     * Test if this client is running in interactive mode.
     * 
     * @return true if this client is running in interactive mode,
     * otherwise false.
     */
    bool	is_interactive() const;

    //
    // Session info
    //
    /**
     * Get the user name.
     * 
     * @return the user name.
     */
    const string& cli_session_user_name() const {
	return (_cli_session_user_name);
    }
    
    /**
     * Get the terminal name.
     * 
     * @return the terminal name.
     */
    const string& cli_session_term_name() const {
	return (_cli_session_term_name);
    }

    /*
     * Get the user network address.
     * 
     * @return the user network address.
     */
    const IPvX&	cli_session_from_address() const {
	return (_cli_session_from_address);
    }

    /**
     * Get the start time for this connection.
     * 
     * @return a reference to @ref TimeVal with the starting time for
     * this connection.
     */
    const TimeVal& cli_session_start_time() const {
	return (_cli_session_start_time);
    }

    /**
     * Get the stop time for this connection.
     * 
     * @return a reference to @ref TimeVal with the end time for
     * this connection.
     */
    const TimeVal& cli_session_stop_time() const {
	return (_cli_session_stop_time);
    }
    
    /**
     * Test if the CLI session is active (i.e., it has been setup and ready
     * to use).
     * 
     * @return true if the CLI session is active, otherwise false.
     */
    bool	is_cli_session_active() const {
	return (_is_cli_session_active);
    }
    
    /**
     * Get the session ID.
     * 
     * @return the session ID for this client.
     */
    uint32_t	cli_session_session_id() const {
	return (_cli_session_session_id);
    }
    
    /**
     * Set the user name.
     * 
     * @param v the user name to set.
     */
    void	set_cli_session_user_name(const string& v) {
	_cli_session_user_name = v;
    }
    
    /**
     * Set the terminal name.
     * 
     * @param v the terminal name to set.
     */
    void	set_cli_session_term_name(const string& v) {
	_cli_session_term_name = v;
    }
    
    /**
     * Set the user network address.
     * 
     * @param v the user network address to set.
     */
    void	set_cli_session_from_address(const IPvX& v) {
	_cli_session_from_address = v;
    }
    
    /**
     * Set the start time for this connection.
     * 
     * @param v the start time for this connection.
     */
    void	set_cli_session_start_time(const TimeVal& v) {
	_cli_session_start_time = v;
    }
    
    /**
     * Set the stop time for this connection.
     * 
     * @param v the stop time for this connection.
     */
    void	set_cli_session_stop_time(const TimeVal& v) {
	_cli_session_stop_time = v;
    }
    
    /**
     * Set if this session is active.
     * 
     * @param v if true, the session is set as active, otherwise is
     * set as non-active.
     */
    void	set_is_cli_session_active(bool v) {
	_is_cli_session_active = v;
    }
    
    /**
     * Set the session ID.
     * 
     * @param v the session ID value to set.
     */
    void	set_cli_session_session_id(uint32_t v) {
	_cli_session_session_id = v;
    }
    
    /**
     * Perform final processing of a command.
     */
    void post_process_command();

    /**
     * Flush the output of a command while it is still running
     */
    void flush_process_command_output();
    
    //
    // Server communication state
    //
    /**
     * Test if waiting for data from command processor.
     * 
     * @return true if waiting for data from command processor, otherwise
     * false.
     */
    bool is_waiting_for_data() const { return (_is_waiting_for_data); }
    
    /**
     * Set a flag whether is waiting for data from command processor.
     * 
     * @param v if true, the session is set as waiting for data, otherwise
     * is set as non-waiting.
     */
    void set_is_waiting_for_data(bool v);
    
    /**
     * Get the current CLI prompt.
     * 
     * @return the current CLI prompt.
     */
    const string& current_cli_prompt() const { return (_current_cli_prompt); }
    
    /**
     * Set the current CLI prompt.
     * 
     * @param cli_prompt the current CLI prompt to set.
     */
    void	set_current_cli_prompt(const string& cli_prompt);

    /**
     * Update the terminal-related information after it has been resized.
     */
    void	terminal_resized();
    
private:
    friend class CliPipe;
    
    CliNode&	cli_node() { return (_cli_node); }
    
    GetLine	*gl() { return (_gl); }

    /**
     * Process octet that may be part of a telnet option.
     *
     * @param val the value of the next octet.
     * @param is_telnet_option return-by-reference result: if true,
     * then @ref val is part of a telnet option and it was processed.
     * If it is false, then @ref value should be processed as input data.
     * @return XORP_OK on success, otherwise XORP_ERROR.
     */
    int		process_telnet_option(int val, bool& is_telnet_option);
    
    bool	telnet_iac() { return (_telnet_iac); }
    void	set_telnet_iac(bool v) { _telnet_iac = v; }
    bool	telnet_sb() { return (_telnet_sb); }
    void	set_telnet_sb(bool v) {_telnet_sb = v; }
    bool	telnet_dont() { return (_telnet_dont); }
    void	set_telnet_dont(bool v) { _telnet_dont = v; }
    bool	telnet_do() { return (_telnet_do); }
    void	set_telnet_do(bool v) { _telnet_do = v; }
    bool	telnet_wont() { return (_telnet_wont); }
    void	set_telnet_wont(bool v) { _telnet_wont = v; }
    bool	telnet_will() { return (_telnet_will); }
    void	set_telnet_will(bool v) { _telnet_will = v; }
    bool	telnet_binary() { return (_telnet_binary); }
    void	set_telnet_binary(bool v) { _telnet_binary = v; }

    void	update_terminal_size();

    size_t	window_width() { return ((size_t)_window_width); }
    void	set_window_width(uint16_t v) { _window_width = v; }
    size_t	window_height() { return ((size_t)_window_height); }
    void	set_window_height(uint16_t v) { _window_height = v; }
    
    Buffer&	command_buffer() { return (_command_buffer); }
    Buffer&	telnet_sb_buffer() { return (_telnet_sb_buffer); }
    
    
    CliCommand	*cli_command_root() { return (cli_node().cli_command_root());}
    int		buff_curpos() { return (_buff_curpos); }
    void	set_buff_curpos(int v) { _buff_curpos = v; }
    
    CliCommand	*current_cli_command() { return (_current_cli_command); }
    void	set_current_cli_command(CliCommand *v);
    
    int		process_command(const string& command_line);
    void	interrupt_command();
    
    CliPipe	*add_pipe(const string& pipe_name);
    CliPipe	*add_pipe(const string& pipe_name,
			  const list<string>& args_list);
    void	delete_pipe_all();
    bool	is_pipe_mode() { return (_is_pipe_mode); }
    void	set_pipe_mode(bool v) { _is_pipe_mode = v; }
    
    int		block_connection(bool is_blocked);
    void	client_read(XorpFd fd, IoEventType type);
    void	process_input_data();
    void	schedule_process_input_data();
    
    static	CPL_MATCH_FN(command_completion_func);
    int		process_char(const string& line, uint8_t val,
			     bool& stop_processing);
    int		process_char_page_mode(uint8_t val);
    int		preprocess_char(uint8_t val, bool& stop_processing);
    void	command_line_help(const string& line, int word_end,
				  bool remove_last_input_char);
    bool	is_multi_command_prefix(const string& command_line);
    
    void	process_line_through_pipes(string& pipe_line);
    // Output paging related functions
    bool	is_page_mode() { return (_is_page_mode); }
    void	set_page_mode(bool v);
    bool	is_page_buffer_mode() { return (*_is_page_buffer_mode); }
    void	set_page_buffer_mode(bool v) { *_is_page_buffer_mode = v; }
    vector<string>& page_buffer() { return (*_page_buffer); }
    const string& page_buffer_line(size_t line_n) const;
    void	reset_page_buffer() { page_buffer().clear(); set_page_buffer_last_line_n(0); }
    size_t	page_buffer_lines_n() { return (page_buffer().size()); }
    void	append_page_buffer_line(const string& buffer_line);
    void	concat_page_buffer_line(const string& buffer_line, size_t pos);
    size_t	page_buffer_last_line_n() { return (*_page_buffer_last_line_n); }
    void	set_page_buffer_last_line_n(size_t v) { *_page_buffer_last_line_n = v; }
    void	incr_page_buffer_last_line_n() { (*_page_buffer_last_line_n)++; }
    void	decr_page_buffer_last_line_n() { (*_page_buffer_last_line_n)--; }
    size_t	page_buffer_window_lines_n();
    size_t	page_buffer_last_window_line_n();
    size_t	page_buffer2window_line_n(size_t buffer_line_n);
    size_t	window_lines_n(size_t buffer_line_n);
    size_t	calculate_first_page_buffer_line_by_window_size(
	size_t last_buffer_line_n,
	size_t max_window_size);

    bool	is_help_mode() { return (_is_help_mode); }
    void	set_help_mode(bool v) { _is_help_mode = v; }
    bool	is_nomore_mode() { return (_is_nomore_mode); }
    void	set_nomore_mode(bool v) { _is_nomore_mode = v; }
    bool	is_hold_mode() { return (_is_hold_mode); }
    void	set_hold_mode(bool v) { _is_hold_mode = v; }
    bool	is_prompt_flushed() const { return _is_prompt_flushed; }
    void	set_prompt_flushed(bool v) { _is_prompt_flushed = v; }

    CliNode&	_cli_node;		// The CLI node I belong to
    XorpFd	_input_fd;		// File descriptor to read the input
    XorpFd	_output_fd;		// File descriptor to write the output
    FILE	*_input_fd_file;	// The FILE version of _input_fd
    FILE	*_output_fd_file;	// The FILE version of _output_fd
    
    enum ClientType{
	CLIENT_MIN		= 0,
	CLIENT_TERMINAL		= 0,
	CLIENT_FILE		= 1,
	CLIENT_MAX
    };
    ClientType	_client_type;		// Type of the client: term, file, etc.
    GetLine	*_gl;			// The GetLine for libtecla
    
    bool	_telnet_iac;		// True if the last octet was IAC
    bool	_telnet_sb;		// True if subnegotiation has began
    bool	_telnet_dont;		// True if the last octet was DONT
    bool	_telnet_do;		// True if the last octet was DO
    bool	_telnet_wont;		// True if the last octet was WONT
    bool	_telnet_will;		// True if the last octet was WILL
    bool	_telnet_binary;		// True if the client "do" binary mode
    
    uint16_t	_window_width;		// The CLI client window width
    uint16_t	_window_height;		// The CLI client window height
    Buffer	_command_buffer;
    Buffer	_telnet_sb_buffer;
    
    // The modified terminal flags
    bool	_is_modified_stdio_termios_icanon;
    bool	_is_modified_stdio_termios_echo;
    bool	_is_modified_stdio_termios_isig;
    //
    // The original VMIN and VTIME members of the termios.c_cc[] array.
    // TODO: those should have type cc_t, but we are using 'int' instead
    // to avoid complicated conditional declarations.
    //
    int		_saved_stdio_termios_vmin;
    int		_saved_stdio_termios_vtime;

    // The command we are currently executing and its arguments
    CliCommand	*_executed_cli_command;	// The command currently executed
    vector<string> _executed_cli_command_name;	// The command name
    vector<string> _executed_cli_command_args;	// The arguments
    
    CliCommand	*_current_cli_command;	// The command we have "cd" to
    string	_current_cli_prompt;	// The CLI prompt
    int		_buff_curpos;		// The cursor position in the buffer
    
    string	_buffer_line;		// To buffer data when pipe-processing
    list<CliPipe *> _pipe_list;		// A list with the CLI pipe commands
    bool	_is_pipe_mode;		// True if pipe processing enabled
    bool	_is_nomore_mode;	// True if disabled "more" mode
    bool	_is_hold_mode;		// True if enabled "hold" mode
    
    // Output paging related stuff
    bool	_is_page_mode;		// True if the output is paged
    
    bool	*_is_page_buffer_mode;	// True if enabled page_buffer_mode
    vector<string> *_page_buffer;
    size_t	*_page_buffer_last_line_n;
    
    bool	_is_output_buffer_mode;	// True if enabled output_buffer_mode
    vector<string> _output_buffer;	// The output buffer: line per element
    size_t	_output_buffer_last_line_n; // The current last (visable) line
    
    bool	_is_help_buffer_mode;	// True if enabled help_buffer_mode
    vector<string> _help_buffer;	// The help buffer: line per element
    size_t	_help_buffer_last_line_n; // The current last (visable) line
    bool	_is_help_mode;		// True if enabled help mode
    
    bool	_is_prompt_flushed;	// True if we have flushed the prompt
    
    // The strings to save the action names that some keys were bind to
    string	_action_name_up_arrow;
    string	_action_name_down_arrow;
    string	_action_name_tab;
    string	_action_name_newline_n;
    string	_action_name_newline_r;
    string	_action_name_spacebar;
    string	_action_name_ctrl_a;
    string	_action_name_ctrl_b;
    string	_action_name_ctrl_c;
    string	_action_name_ctrl_d;
    string	_action_name_ctrl_e;
    string	_action_name_ctrl_f;
    string	_action_name_ctrl_h;
    string	_action_name_ctrl_k;
    string	_action_name_ctrl_l;
    string	_action_name_ctrl_m;
    string	_action_name_ctrl_n;
    string	_action_name_ctrl_p;
    string	_action_name_ctrl_u;
    string	_action_name_ctrl_x;
    
    //
    // Session info state
    //
    string	_cli_session_user_name;
    string	_cli_session_term_name;
    IPvX	_cli_session_from_address;
    TimeVal	_cli_session_start_time;
    TimeVal	_cli_session_stop_time;
    bool	_is_cli_session_active;
    uint32_t	_cli_session_session_id;	// The unique session ID.
    bool	_is_network;
    
    //
    // Log-related state
    //
    bool	_is_log_output;
    
    //
    // Server communication state
    //
    bool _is_waiting_for_data;		// True if waiting for external data

    //
    // Misc state
    //
    vector<uint8_t>	_pending_input_data;
    XorpTimer		_process_pending_input_data_timer;
};


//
// Global variables
//


//
// Global functions prototypes
//

#endif // __CLI_CLI_CLIENT_HH__