2001-09-25 16:49:28 +04:00
/*
2008-01-30 17:00:02 +03:00
* Copyright ( C ) 2001 - 2004 Sistina Software , Inc . All rights reserved .
2007-08-21 00:55:30 +04:00
* Copyright ( C ) 2004 - 2007 Red Hat , Inc . All rights reserved .
2001-09-25 16:49:28 +04:00
*
2004-03-30 23:35:44 +04:00
* This file is part of LVM2 .
*
* This copyrighted material is made available to anyone wishing to use ,
* modify , copy , or redistribute it subject to the terms and conditions
* of the GNU General Public License v .2 .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software Foundation ,
* Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
2001-09-25 16:49:28 +04:00
*/
2007-02-14 19:51:48 +03:00
# include "tools.h"
2004-03-26 15:00:24 +03:00
# include "lvm2cmdline.h"
2002-11-18 17:04:08 +03:00
int main ( int argc , char * * argv )
{
2008-12-18 08:27:17 +03:00
return lvm2_main ( argc , argv ) ;
2002-11-18 17:04:08 +03:00
}
2007-02-14 19:51:48 +03:00
# ifdef READLINE_SUPPORT
# include <readline / readline.h>
# include <readline / history.h>
# ifndef HAVE_RL_COMPLETION_MATCHES
# define rl_completion_matches(a, b) completion_matches((char *)a, b)
# endif
static struct cmdline_context * _cmdline ;
/* List matching commands */
static char * _list_cmds ( const char * text , int state )
{
static int i = 0 ;
static size_t len = 0 ;
/* Initialise if this is a new completion attempt */
if ( ! state ) {
i = 0 ;
len = strlen ( text ) ;
}
while ( i < _cmdline - > num_commands )
if ( ! strncmp ( text , _cmdline - > commands [ i + + ] . name , len ) )
return strdup ( _cmdline - > commands [ i - 1 ] . name ) ;
return NULL ;
}
/* List matching arguments */
static char * _list_args ( const char * text , int state )
{
static int match_no = 0 ;
static size_t len = 0 ;
static struct command * com ;
/* Initialise if this is a new completion attempt */
if ( ! state ) {
char * s = rl_line_buffer ;
2012-02-08 15:36:18 +04:00
int j ;
2007-02-14 19:51:48 +03:00
match_no = 0 ;
com = NULL ;
len = strlen ( text ) ;
/* Find start of first word in line buffer */
while ( isspace ( * s ) )
s + + ;
/* Look for word in list of commands */
for ( j = 0 ; j < _cmdline - > num_commands ; j + + ) {
const char * p ;
char * q = s ;
p = _cmdline - > commands [ j ] . name ;
while ( * p = = * q ) {
p + + ;
q + + ;
}
if ( ( ! * p ) & & * q = = ' ' ) {
com = _cmdline - > commands + j ;
break ;
}
}
}
2010-10-25 16:57:00 +04:00
if ( ! com )
return NULL ;
2007-02-14 19:51:48 +03:00
/* Short form arguments */
2013-04-13 05:26:37 +04:00
if ( len < 3 ) {
while ( match_no < com - > num_args ) {
char s [ 3 ] ;
char c ;
if ( ! ( c = ( _cmdline - > arg_props +
com - > valid_args [ match_no + + ] ) - > short_arg ) )
continue ;
sprintf ( s , " -%c " , c ) ;
if ( ! strncmp ( text , s , len ) )
return strdup ( s ) ;
}
2007-02-14 19:51:48 +03:00
}
/* Long form arguments */
if ( match_no < com - > num_args )
match_no = com - > num_args ;
while ( match_no - com - > num_args < com - > num_args ) {
const char * l ;
2010-11-11 20:29:05 +03:00
l = ( _cmdline - > arg_props +
2007-02-14 19:51:48 +03:00
com - > valid_args [ match_no + + - com - > num_args ] ) - > long_arg ;
if ( * ( l + 2 ) & & ! strncmp ( text , l , len ) )
return strdup ( l ) ;
}
return NULL ;
}
/* Custom completion function */
2008-01-31 15:19:36 +03:00
static char * * _completion ( const char * text , int start_pos ,
2010-07-09 19:34:40 +04:00
int end_pos __attribute__ ( ( unused ) ) )
2007-02-14 19:51:48 +03:00
{
char * * match_list = NULL ;
int p = 0 ;
while ( isspace ( ( int ) * ( rl_line_buffer + p ) ) )
p + + ;
/* First word should be one of our commands */
if ( start_pos = = p )
match_list = rl_completion_matches ( text , _list_cmds ) ;
else if ( * text = = ' - ' )
match_list = rl_completion_matches ( text , _list_args ) ;
/* else other args */
/* No further completion */
rl_attempted_completion_over = 1 ;
return match_list ;
}
static int _hist_file ( char * buffer , size_t size )
{
char * e = getenv ( " HOME " ) ;
if ( dm_snprintf ( buffer , size , " %s/.lvm_history " , e ) < 0 ) {
log_error ( " $HOME/.lvm_history: path too long " ) ;
return 0 ;
}
return 1 ;
}
static void _read_history ( struct cmd_context * cmd )
{
char hist_file [ PATH_MAX ] ;
if ( ! _hist_file ( hist_file , sizeof ( hist_file ) ) )
return ;
if ( read_history ( hist_file ) )
log_very_verbose ( " Couldn't read history from %s. " , hist_file ) ;
2013-06-25 14:30:34 +04:00
stifle_history ( find_config_tree_int ( cmd , shell_history_size_CFG , NULL ) ) ;
2007-02-14 19:51:48 +03:00
}
static void _write_history ( void )
{
char hist_file [ PATH_MAX ] ;
if ( ! _hist_file ( hist_file , sizeof ( hist_file ) ) )
return ;
if ( write_history ( hist_file ) )
log_very_verbose ( " Couldn't write history to %s. " , hist_file ) ;
}
int lvm_shell ( struct cmd_context * cmd , struct cmdline_context * cmdline )
{
int argc , ret ;
char * input = NULL , * args [ MAX_ARGS ] , * * argv ;
rl_readline_name = " lvm " ;
rl_attempted_completion_function = ( CPPFunction * ) _completion ;
_read_history ( cmd ) ;
_cmdline = cmdline ;
_cmdline - > interactive = 1 ;
while ( 1 ) {
free ( input ) ;
input = readline ( " lvm> " ) ;
/* EOF */
if ( ! input ) {
config: add silent mode
Accept -q as the short form of --quiet.
Suppress non-essential standard output if -q is given twice.
Treat log/silent in lvm.conf as equivalent to -qq.
Review all log_print messages and change some to
log_print_unless_silent.
When silent, the following commands still produce output:
dumpconfig, lvdisplay, lvmdiskscan, lvs, pvck, pvdisplay,
pvs, version, vgcfgrestore -l, vgdisplay, vgs.
[Needs checking.]
Non-essential messages are shifted from log level 4 to log level 5
for syslog and lvm2_log_fn purposes.
2012-08-25 23:35:48 +04:00
/* readline sends prompt to stdout */
2007-02-14 19:51:48 +03:00
printf ( " \n " ) ;
break ;
}
/* empty line */
if ( ! * input )
continue ;
add_history ( input ) ;
argv = args ;
if ( lvm_split ( input , & argc , argv , MAX_ARGS ) = = MAX_ARGS ) {
log_error ( " Too many arguments, sorry. " ) ;
continue ;
}
2010-07-01 15:04:58 +04:00
if ( ! argc )
continue ;
2007-02-14 19:51:48 +03:00
if ( ! strcmp ( argv [ 0 ] , " lvm " ) ) {
argv + + ;
argc - - ;
}
if ( ! argc )
continue ;
if ( ! strcmp ( argv [ 0 ] , " quit " ) | | ! strcmp ( argv [ 0 ] , " exit " ) ) {
remove_history ( history_length - 1 ) ;
log_error ( " Exiting. " ) ;
break ;
}
ret = lvm_run_command ( cmd , argc , argv ) ;
if ( ret = = ENO_SUCH_CMD )
log_error ( " No such command '%s'. Try 'help'. " ,
argv [ 0 ] ) ;
2008-06-06 23:28:35 +04:00
if ( ( ret ! = ECMD_PROCESSED ) & & ! error_message_produced ( ) ) {
2009-12-16 22:22:11 +03:00
log_debug ( INTERNAL_ERROR " Failed command did not use log_error " ) ;
2008-06-06 23:28:35 +04:00
log_error ( " Command failed with status code %d. " , ret ) ;
}
2007-02-14 19:51:48 +03:00
_write_history ( ) ;
}
free ( input ) ;
return 0 ;
}
# endif /* READLINE_SUPPORT */