in client/mysqladmin.cc [642:1234]
static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
const char *status;
/*
MySQL documentation relies on the fact that mysqladmin will
execute commands in the order specified, e.g.
mysqladmin -u root flush-privileges password "newpassword"
to reset a lost root password.
If this behaviour is ever changed, Docs should be notified.
*/
struct rand_struct rand_st;
for (; argc > 0 ; argv++,argc--)
{
int option;
switch (option= find_type(argv[0], &command_typelib, FIND_TYPE_BASIC)) {
case ADMIN_CREATE:
{
char buff[FN_REFLEN+20];
if (argc < 2)
{
my_printf_error(0, "Too few arguments to create", error_flags);
return 1;
}
sprintf(buff,"create database `%.*s`",FN_REFLEN,argv[1]);
if (mysql_query(mysql,buff))
{
my_printf_error(0,"CREATE DATABASE failed; error: '%-.200s'",
error_flags, mysql_error(mysql));
return -1;
}
argc--; argv++;
break;
}
case ADMIN_DROP:
{
if (argc < 2)
{
my_printf_error(0, "Too few arguments to drop", error_flags);
return 1;
}
if (drop_db(mysql,argv[1]))
return -1;
argc--; argv++;
break;
}
case ADMIN_SHUTDOWN:
{
char pidfile[FN_REFLEN];
my_bool got_pidfile= 0;
time_t last_modified= 0;
struct stat pidfile_status;
/*
Only wait for pidfile on local connections
If pidfile doesn't exist, continue without pid file checking
*/
if (mysql->unix_socket && (got_pidfile= !get_pidfile(mysql, pidfile)) &&
!stat(pidfile, &pidfile_status))
last_modified= pidfile_status.st_mtime;
if (mysql_shutdown(mysql, SHUTDOWN_DEFAULT))
{
my_printf_error(0, "shutdown failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
argc=1; /* force SHUTDOWN to be the last command */
if (got_pidfile)
{
if (opt_verbose)
printf("Shutdown signal sent to server; Waiting for pid file to disappear\n");
/* Wait until pid file is gone */
if (wait_pidfile(pidfile, last_modified, &pidfile_status))
return -1;
}
break;
}
case ADMIN_FLUSH_PRIVILEGES:
case ADMIN_RELOAD:
if (mysql_query(mysql,"flush privileges"))
{
my_printf_error(0, "reload failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
break;
case ADMIN_REFRESH:
if (mysql_refresh(mysql,
(uint) ~(REFRESH_GRANT | REFRESH_STATUS |
REFRESH_READ_LOCK | REFRESH_SLAVE |
REFRESH_MASTER)))
{
my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
break;
case ADMIN_FLUSH_THREADS:
if (mysql_refresh(mysql,(uint) REFRESH_THREADS))
{
my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
break;
case ADMIN_VER:
new_line=1;
print_version();
puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
printf("Server version\t\t%s\n", mysql_get_server_info(mysql));
printf("Protocol version\t%d\n", mysql_get_proto_info(mysql));
printf("Connection\t\t%s\n",mysql_get_host_info(mysql));
if (mysql->unix_socket)
printf("UNIX socket\t\t%s\n", mysql->unix_socket);
else
printf("TCP port\t\t%d\n", mysql->port);
status=mysql_stat(mysql);
{
char *pos,buff[40];
ulong sec;
pos= (char*) strchr(status,' ');
*pos++=0;
printf("%s\t\t\t",status); /* print label */
if ((status=str2int(pos,10,0,LONG_MAX,(long*) &sec)))
{
nice_time(sec,buff);
puts(buff); /* print nice time */
while (*status == ' ') status++; /* to next info */
}
}
putc('\n',stdout);
if (status)
puts(status);
break;
case ADMIN_PROCESSLIST:
{
MYSQL_RES *result;
MYSQL_ROW row;
if (mysql_query(mysql, (opt_verbose ? "show full processlist" :
"show processlist")) ||
!(result = mysql_store_result(mysql)))
{
my_printf_error(0, "process list failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
print_header(result);
while ((row=mysql_fetch_row(result)))
print_row(result,row,0);
print_top(result);
mysql_free_result(result);
new_line=1;
break;
}
case ADMIN_STATUS:
status=mysql_stat(mysql);
if (status)
puts(status);
break;
case ADMIN_KILL:
{
uint error=0;
char *pos;
if (argc < 2)
{
my_printf_error(0, "Too few arguments to 'kill'", error_flags);
return 1;
}
pos=argv[1];
for (;;)
{
/* We don't use mysql_kill(), since it only handles 32-bit IDs. */
char buff[26], *out; /* "KILL " + max 20 digs + NUL */
out= strxmov(buff, "KILL ", NullS);
ullstr(strtoull(pos, NULL, 0), out);
if (mysql_query(mysql, buff))
{
/* out still points to just the number */
my_printf_error(0, "kill failed on %s; error: '%s'", error_flags,
out, mysql_error(mysql));
error=1;
}
if (!(pos=strchr(pos,',')))
break;
pos++;
}
argc--; argv++;
if (error)
return -1;
break;
}
case ADMIN_DEBUG:
if (mysql_dump_debug_info(mysql))
{
my_printf_error(0, "debug failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
break;
case ADMIN_VARIABLES:
{
MYSQL_RES *res;
MYSQL_ROW row;
new_line=1;
if (mysql_query(mysql,"show /*!40003 GLOBAL */ variables") ||
!(res=mysql_store_result(mysql)))
{
my_printf_error(0, "unable to show variables; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
print_header(res);
while ((row=mysql_fetch_row(res)))
print_row(res,row,0);
print_top(res);
mysql_free_result(res);
break;
}
case ADMIN_EXTENDED_STATUS:
{
MYSQL_RES *res;
MYSQL_ROW row;
uint rownr = 0;
void (*func) (MYSQL_RES*, MYSQL_ROW, uint);
new_line = 1;
if (mysql_query(mysql, "show /*!50002 GLOBAL */ status") ||
!(res = mysql_store_result(mysql)))
{
my_printf_error(0, "unable to show status; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
if (mysql_num_rows(res) >= MAX_MYSQL_VAR) {
my_printf_error(0, "Too many rows returned: '%llu'. "
"Expecting no more than '%d' rows", error_flags,
mysql_num_rows(res), MAX_MYSQL_VAR);
return -1;
}
if (!opt_vertical)
print_header(res);
else
{
if (!ex_status_printed)
{
store_values(res);
truncate_names(); /* Does some printing also */
}
else
{
print_relative_line();
print_relative_header();
print_relative_line();
}
}
/* void (*func) (MYSQL_RES*, MYSQL_ROW, uint); */
if (opt_relative && !opt_vertical)
func = print_relative_row;
else if (opt_vertical)
func = print_relative_row_vert;
else
func = print_row;
while ((row = mysql_fetch_row(res)))
(*func)(res, row, rownr++);
if (opt_vertical)
{
if (ex_status_printed)
{
putchar('\n');
print_relative_line();
}
}
else
print_top(res);
ex_status_printed = 1; /* From now on the output will be relative */
mysql_free_result(res);
break;
}
case ADMIN_FLUSH_LOGS:
{
if (mysql_refresh(mysql,REFRESH_LOG))
{
my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
break;
}
case ADMIN_FLUSH_HOSTS:
{
if (mysql_query(mysql,"flush hosts"))
{
my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
break;
}
case ADMIN_FLUSH_TABLES:
{
if (mysql_query(mysql,"flush tables"))
{
my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
break;
}
case ADMIN_FLUSH_STATUS:
{
if (mysql_query(mysql,"flush status"))
{
my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
break;
}
case ADMIN_OLD_PASSWORD:
case ADMIN_PASSWORD:
{
char crypted_pw[64];
time_t start_time;
char *buffer= NULL, *typed_password= NULL, *verified= NULL;
bool log_off= true, err= false;
int retry_count= 0; /* Attempts to SET PASSWORD */
unsigned long version= 0;
bool old= (option == ADMIN_OLD_PASSWORD);
/* Do initialization the same way as we do in mysqld */
start_time=time((time_t*) 0);
randominit(&rand_st,(ulong) start_time,(ulong) start_time/2);
version = mysql_get_server_version(mysql);
if (argc < 1)
{
my_printf_error(0, "Too few arguments to change password", error_flags);
return 1;
}
else if (version >= 50700 && old)
{
my_printf_error(0, "old-password command is not supported by the "
"server version 5.7 and above", error_flags);
return 1;
}
else if (argc == 1)
{
/* prompt for password */
typed_password= get_tty_password("New password: ");
verified= get_tty_password("Confirm new password: ");
if (strcmp(typed_password, verified) != 0)
{
my_printf_error(0,"Passwords don't match",MYF(ME_BELL));
err= true;
goto error;
}
}
else
{
typed_password= argv[1];
}
/* Allocate a buffer containing a query and a password (char * 2). */
buffer= (char *)my_malloc(strlen(typed_password) * 2 + 64, MYF(MY_WME));
if (!buffer)
{
err= true;
goto error;
}
/* Default set password query if no password is provided. */
sprintf(buffer, "set password=''");
if (typed_password[0])
{
#ifdef __WIN__
size_t pw_len= strlen(typed_password);
if (pw_len > 1 && typed_password[0] == '\'' &&
typed_password[pw_len-1] == '\'')
printf("Warning: single quotes were not trimmed from the password by"
" your command\nline client, as you might have expected.\n");
#endif
/*
If we don't already know to use an old-style password, see
(if possible) what the server is using.
*/
if (!old)
{
if (mysql_query(mysql, "SHOW VARIABLES LIKE 'old_passwords'"))
{
bool fatal= (mysql_errno(mysql) != ER_MUST_CHANGE_PASSWORD);
if (fatal || opt_verbose)
my_printf_error(0, "Could not determine old_passwords setting "
"from server; error: '%s'.", error_flags,
mysql_error(mysql));
if (fatal)
{
err= true;
goto error;
}
}
else
{
MYSQL_RES *res= mysql_store_result(mysql);
if (!res)
{
my_printf_error(0,
"Could not get old_passwords setting from "
"server; error: '%s'.",
error_flags, mysql_error(mysql));
err= true;
goto error;
}
if (!mysql_num_rows(res))
old= 1;
else
{
MYSQL_ROW row= mysql_fetch_row(res);
old= (!strncmp(row[1], "ON", 2) || !strncmp(row[1], "1", 1));
}
mysql_free_result(res);
}
}
/* turn logging off if we can */
if (mysql_query(mysql,"set sql_log_off=1"))
{
if (opt_verbose)
fprintf(stderr, "Note: Can't turn off logging; '%s'", mysql_error(mysql));
log_off= false;
}
retry:
/*
In case the password_expired flag is set ('Y'), then there is no way
to determine the password format. So, we first try to set the
password using native format. If it fails with ER_PASSWORD_LENGTH,
we will give one more try with old format.
*/
if (old)
{
make_scrambled_password_323(crypted_pw, typed_password);
sprintf(buffer, "set password='%s'", crypted_pw);
}
else if (version < 50700)
{
make_scrambled_password(crypted_pw, typed_password);
sprintf(buffer, "set password='%s'", crypted_pw);
}
else
{
printf("Warning: Server version is 5.7 or greater. "
"The password will be sent to server in plain text. "
"Upgrade the mysqladmin to a version "
"that matches the server's version.\n");
int offset= sprintf(buffer, "ALTER USER USER() IDENTIFIED BY '");
int length= (int)mysql_real_escape_string(mysql, buffer + offset,
typed_password, (ulong)
strlen(typed_password));
if (length == -1)
{
/* Should never fail. Buffer should be long enough.*/
err= true;
goto error;
}
sprintf(buffer + offset + length, "'");
}
}
if (mysql_query(mysql,buffer))
{
if ((mysql_errno(mysql) == ER_PASSWD_LENGTH) &&
!(option == ADMIN_OLD_PASSWORD) && !retry_count)
{
/* Try to set the password using old format. */
memset(crypted_pw, 0, 64);
old= 0;
retry_count ++;
goto retry;
}
if (mysql_errno(mysql)!=1290)
{
my_printf_error(0,"unable to change password; error: '%s'",
error_flags, mysql_error(mysql));
err= true;
goto error;
}
else
{
/*
We don't try to execute 'update mysql.user set..'
because we can't perfectly find out the host
*/
my_printf_error(0,"\n"
"You cannot use 'password' command as mysqld runs\n"
" with grant tables disabled (was started with"
" --skip-grant-tables).\n"
"Use: \"mysqladmin flush-privileges password '*'\""
" instead", error_flags);
err= true;
goto error;
}
}
if (log_off && mysql_query(mysql, "set sql_log_off=0"))
{
if (opt_verbose)
fprintf(stderr, "Note: Can't turn on logging; '%s'", mysql_error(mysql));
}
error:
my_free(buffer);
/* free up memory from prompted password */
if (typed_password != argv[1])
{
my_free(typed_password);
my_free(verified);
}
if (err)
return -1;
argc--; argv++;
break;
}
case ADMIN_START_SLAVE:
if (mysql_query(mysql, "START SLAVE"))
{
my_printf_error(0, "Error starting slave: %s", error_flags,
mysql_error(mysql));
return -1;
}
else
puts("Slave started");
break;
case ADMIN_STOP_SLAVE:
if (mysql_query(mysql, "STOP SLAVE"))
{
my_printf_error(0, "Error stopping slave: %s", error_flags,
mysql_error(mysql));
return -1;
}
else
puts("Slave stopped");
break;
case ADMIN_PING:
mysql->reconnect=0; /* We want to know of reconnects */
if (!mysql_ping(mysql))
{
if (option_silent < 2)
puts("mysqld is alive");
}
else
{
if (mysql_errno(mysql) == CR_SERVER_GONE_ERROR)
{
mysql->reconnect=1;
if (!mysql_ping(mysql))
puts("connection was down, but mysqld is now alive");
}
else
{
my_printf_error(0,"mysqld doesn't answer to ping, error: '%s'",
error_flags, mysql_error(mysql));
return -1;
}
}
mysql->reconnect=1; /* Automatic reconnect is default */
break;
default:
my_printf_error(0, "Unknown command: '%-.60s'", error_flags, argv[0]);
return 1;
}
}
return 0;
}