@ -268,6 +268,7 @@ enum enum_commands {
Q_WRITE_FILE , Q_COPY_FILE , Q_PERL , Q_DIE , Q_EXIT , Q_SKIP ,
Q_CHMOD_FILE , Q_APPEND_FILE , Q_CAT_FILE , Q_DIFF_FILES ,
Q_SEND_QUIT , Q_CHANGE_USER , Q_MKDIR , Q_RMDIR ,
Q_SHUTDOWN , Q_KILL_SERVER ,
Q_UNKNOWN , /* Unknown command. */
Q_COMMENT , /* Comments, ignored. */
@ -359,6 +360,8 @@ const char *command_names[]=
" change_user " ,
" mkdir " ,
" rmdir " ,
" shutdown " ,
" kill_server " ,
0
} ;
@ -3806,6 +3809,120 @@ void do_set_charset(struct st_command *command)
}
/*
Run query and return one field in the result set from the
first row and < column >
*/
int query_get_string ( MYSQL * mysql , const char * query ,
int column , DYNAMIC_STRING * ds )
{
MYSQL_RES * res ;
MYSQL_ROW row ;
if ( mysql_query ( mysql , query ) | | ! ( res = mysql_store_result ( mysql ) ) )
die ( " '%s' failed: %d %s " , query ,
mysql_errno ( mysql ) , mysql_error ( mysql ) ) ;
if ( ! ( row = mysql_fetch_row ( res ) ) | | ! row [ column ] )
{
mysql_free_result ( res ) ;
ds = 0 ;
return 1 ;
}
init_dynamic_string ( ds , row [ 1 ] , strlen ( row [ column ] ) , 32 ) ;
mysql_free_result ( res ) ;
return 0 ;
}
/*
Shutdown the server of current connection and
make sure it goes away within < timeout > seconds
NOTE ! Currently only works with local server
SYNOPSIS
do_kill_server ( )
command called command
DESCRIPTION
kill_server [ < timeout > ]
*/
void do_kill_server ( struct st_command * command )
{
int timeout = 60 , pid ;
DYNAMIC_STRING * ds_pidfile_name ;
MYSQL * mysql = & cur_con - > mysql ;
static DYNAMIC_STRING ds_timeout ;
const struct command_arg kill_args [ ] = {
" timeout " , ARG_STRING , FALSE , & ds_timeout , " Timeout before killing server "
} ;
DBUG_ENTER ( " do_kill_server " ) ;
check_command_args ( command , command - > first_argument ,
kill_args , sizeof ( kill_args ) / sizeof ( struct command_arg ) ,
' ' ) ;
if ( ds_timeout . length )
{
timeout = atoi ( ds_timeout . str ) ;
if ( timeout = = 0 )
die ( " Illegal argument for timeout: '%s' " , ds_timeout . str ) ;
}
/* Get the servers pid_file name and use it to read pid */
if ( query_get_string ( mysql , " SHOW VARIABLES LIKE 'pid_file' " , 1 ,
ds_pidfile_name ) )
die ( " Failed to get pid_file from server " ) ;
/* Read the pid from the file */
{
int fd ;
char buff [ 32 ] ;
if ( ( fd = my_open ( ds_pidfile_name - > str , O_RDONLY , MYF ( 0 ) ) ) < 0 )
die ( " Failed to open file '%s' " , ds_pidfile_name - > str ) ;
if ( my_read ( fd , ( uchar * ) & buff ,
sizeof ( buff ) , MYF ( 0 ) ) < = 0 ) {
my_close ( fd , MYF ( 0 ) ) ;
die ( " pid file was empty " ) ;
}
pid = atoi ( buff ) ;
if ( pid = = 0 ) {
my_close ( fd , MYF ( 0 ) ) ;
die ( " pid file was empty " ) ;
}
DBUG_PRINT ( " info " , ( " Read pid %d from '%s' " , pid , ds_pidfile_name - > str ) ) ;
my_close ( fd , MYF ( 0 ) ) ;
}
DBUG_PRINT ( " info " , ( " Got pid %d " , pid ) ) ;
/* Tell server to shutdown */
if ( mysql_shutdown ( & cur_con - > mysql , SHUTDOWN_DEFAULT ) )
die ( " mysql_shutdown failed " ) ;
/* Check that server dies */
while ( timeout - - ) {
if ( kill ( 0 , pid ) < 0 ) {
DBUG_PRINT ( " info " , ( " Sleeping, timeout: %d " , timeout ) ) ;
break ;
}
DBUG_PRINT ( " info " , ( " Sleeping, timeout: %d " , timeout ) ) ;
my_sleep ( 1 ) ;
}
/* Kill the server */
DBUG_PRINT ( " info " , ( " Killing server, pid: %d " , pid ) ) ;
( void ) kill ( 9 , pid ) ;
DBUG_VOID_RETURN ;
}
# if MYSQL_VERSION_ID >= 50000
/* List of error names to error codes, available from 5.0 */
typedef struct
@ -7192,8 +7309,16 @@ int main(int argc, char **argv)
command - > last_argument = command - > end ;
break ;
case Q_PING :
( void ) mysql_ping ( & cur_con - > mysql ) ;
break ;
handle_command_error ( command , mysql_ping ( & cur_con - > mysql ) ) ;
break ;
case Q_SHUTDOWN :
handle_command_error ( command ,
mysql_shutdown ( & cur_con - > mysql ,
SHUTDOWN_DEFAULT ) ) ;
break ;
case Q_KILL_SERVER :
do_kill_server ( command ) ;
break ;
case Q_EXEC :
do_exec ( command ) ;
command_executed + + ;