MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mysqladmin.cc
1 /*
2  Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 /* maintaince of mysql databases */
19 
20 #include "client_priv.h"
21 #include "my_default.h"
22 #include <signal.h>
23 #include <my_pthread.h> /* because of signal() */
24 #include <sys/stat.h>
25 #include <mysql.h>
26 #include <sql_common.h>
27 #include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
28 #include <mysqld_error.h> /* to check server error codes */
29 
30 #define ADMIN_VERSION "8.42"
31 #define MAX_MYSQL_VAR 512
32 #define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */
33 #define MAX_TRUNC_LENGTH 3
34 
35 char *host= NULL, *user= 0, *opt_password= 0,
36  *default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME;
37 char truncated_var_names[MAX_MYSQL_VAR][MAX_TRUNC_LENGTH];
38 char ex_var_names[MAX_MYSQL_VAR][FN_REFLEN];
39 ulonglong last_values[MAX_MYSQL_VAR];
40 static int interval=0;
41 static my_bool option_force=0,interrupted=0,new_line=0,
42  opt_compress=0, opt_relative=0, opt_verbose=0, opt_vertical=0,
43  tty_password= 0, opt_nobeep;
44 static my_bool debug_info_flag= 0, debug_check_flag= 0;
45 static uint tcp_port = 0, option_wait = 0, option_silent=0, nr_iterations;
46 static uint opt_count_iterations= 0, my_end_arg;
47 static char *opt_bind_addr = NULL;
48 static ulong opt_connect_timeout, opt_shutdown_timeout;
49 static char * unix_port=0;
50 static char *opt_plugin_dir= 0, *opt_default_auth= 0;
51 static uint opt_enable_cleartext_plugin= 0;
52 static my_bool using_opt_enable_cleartext_plugin= 0;
53 
54 #ifdef HAVE_SMEM
55 static char *shared_memory_base_name=0;
56 #endif
57 static uint opt_protocol=0;
58 static myf error_flags; /* flags to pass to my_printf_error, like ME_BELL */
59 
60 /*
61  When using extended-status relatively, ex_val_max_len is the estimated
62  maximum length for any relative value printed by extended-status. The
63  idea is to try to keep the length of output as short as possible.
64 */
65 
66 static uint ex_val_max_len[MAX_MYSQL_VAR];
67 static my_bool ex_status_printed = 0; /* First output is not relative. */
68 static uint ex_var_count, max_var_length, max_val_length;
69 
70 #include <sslopt-vars.h>
71 
72 static void print_version(void);
73 static void usage(void);
74 extern "C" my_bool get_one_option(int optid, const struct my_option *opt,
75  char *argument);
76 static my_bool sql_connect(MYSQL *mysql, uint wait);
77 static int execute_commands(MYSQL *mysql,int argc, char **argv);
78 static int drop_db(MYSQL *mysql,const char *db);
79 extern "C" sig_handler endprog(int signal_number);
80 static void nice_time(ulong sec,char *buff);
81 static void print_header(MYSQL_RES *result);
82 static void print_top(MYSQL_RES *result);
83 static void print_row(MYSQL_RES *result,MYSQL_ROW cur, uint row);
84 static void print_relative_row(MYSQL_RES *result, MYSQL_ROW cur, uint row);
85 static void print_relative_row_vert(MYSQL_RES *result, MYSQL_ROW cur, uint row);
86 static void print_relative_header();
87 static void print_relative_line();
88 static void truncate_names();
89 static my_bool get_pidfile(MYSQL *mysql, char *pidfile);
90 static my_bool wait_pidfile(char *pidfile, time_t last_modified,
91  struct stat *pidfile_status);
92 static void store_values(MYSQL_RES *result);
93 
94 /*
95  The order of commands must be the same as command_names,
96  except ADMIN_ERROR
97 */
98 enum commands {
99  ADMIN_ERROR,
100  ADMIN_CREATE, ADMIN_DROP, ADMIN_SHUTDOWN,
101  ADMIN_RELOAD, ADMIN_REFRESH, ADMIN_VER,
102  ADMIN_PROCESSLIST, ADMIN_STATUS, ADMIN_KILL,
103  ADMIN_DEBUG, ADMIN_VARIABLES, ADMIN_FLUSH_LOGS,
104  ADMIN_FLUSH_HOSTS, ADMIN_FLUSH_TABLES, ADMIN_PASSWORD,
105  ADMIN_PING, ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS,
106  ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE, ADMIN_STOP_SLAVE,
107  ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD
108 };
109 static const char *command_names[]= {
110  "create", "drop", "shutdown",
111  "reload", "refresh", "version",
112  "processlist", "status", "kill",
113  "debug", "variables", "flush-logs",
114  "flush-hosts", "flush-tables", "password",
115  "ping", "extended-status", "flush-status",
116  "flush-privileges", "start-slave", "stop-slave",
117  "flush-threads","old-password",
118  NullS
119 };
120 
121 static TYPELIB command_typelib=
122 { array_elements(command_names)-1,"commands", command_names, NULL};
123 
124 static struct my_option my_long_options[] =
125 {
126  {"bind-address", 0, "IP address to bind to.",
127  (uchar**) &opt_bind_addr, (uchar**) &opt_bind_addr, 0, GET_STR,
128  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
129  {"count", 'c',
130  "Number of iterations to make. This works with -i (--sleep) only.",
131  &nr_iterations, &nr_iterations, 0, GET_UINT,
132  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
133 #ifndef DBUG_OFF
134  {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
135  0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
136 #endif
137  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
138  &debug_check_flag, &debug_check_flag, 0,
139  GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
140  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
141  &debug_info_flag, &debug_info_flag,
142  0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
143  {"force", 'f',
144  "Don't ask for confirmation on drop database; with multiple commands, "
145  "continue even if an error occurs.",
146  &option_force, &option_force, 0, GET_BOOL, NO_ARG, 0, 0,
147  0, 0, 0, 0},
148  {"compress", 'C', "Use compression in server/client protocol.",
149  &opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
150  0, 0, 0},
151  {"character-sets-dir", OPT_CHARSETS_DIR,
152  "Directory for character set files.", &charsets_dir,
153  &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
154  {"default-character-set", OPT_DEFAULT_CHARSET,
155  "Set the default character set.", &default_charset,
156  &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
157  {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG,
158  NO_ARG, 0, 0, 0, 0, 0, 0},
159  {"host", 'h', "Connect to host.", &host, &host, 0, GET_STR,
160  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
161  {"no-beep", 'b', "Turn off beep on error.", &opt_nobeep,
162  &opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
163  {"password", 'p',
164  "Password to use when connecting to server. If password is not given it's asked from the tty.",
165  0, 0, 0, GET_PASSWORD, OPT_ARG, 0, 0, 0, 0, 0, 0},
166 #ifdef __WIN__
167  {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
168  NO_ARG, 0, 0, 0, 0, 0, 0},
169 #endif
170  {"port", 'P', "Port number to use for connection or 0 for default to, in "
171  "order of preference, my.cnf, $MYSQL_TCP_PORT, "
172 #if MYSQL_PORT_DEFAULT == 0
173  "/etc/services, "
174 #endif
175  "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
176  &tcp_port, &tcp_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
177  {"protocol", OPT_MYSQL_PROTOCOL, "The protocol to use for connection (tcp, socket, pipe, memory).",
178  0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
179  {"relative", 'r',
180  "Show difference between current and previous values when used with -i. "
181  "Currently only works with extended-status.",
182  &opt_relative, &opt_relative, 0, GET_BOOL, NO_ARG, 0, 0, 0,
183  0, 0, 0},
184 #ifdef HAVE_SMEM
185  {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
186  "Base name of shared memory.", &shared_memory_base_name, &shared_memory_base_name,
187  0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
188 #endif
189  {"silent", 's', "Silently exit if one can't connect to server.",
190  0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
191  {"socket", 'S', "The socket file to use for connection.",
192  &unix_port, &unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
193  0, 0, 0},
194  {"sleep", 'i', "Execute commands repeatedly with a sleep between.",
195  &interval, &interval, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0,
196  0, 0},
197 #include <sslopt-longopts.h>
198 #ifndef DONT_ALLOW_USER_CHANGE
199  {"user", 'u', "User for login if not current user.", &user,
200  &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
201 #endif
202  {"verbose", 'v', "Write more information.", &opt_verbose,
203  &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
204  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
205  NO_ARG, 0, 0, 0, 0, 0, 0},
206  {"vertical", 'E',
207  "Print output vertically. Is similar to --relative, but prints output vertically.",
208  &opt_vertical, &opt_vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0,
209  0, 0, 0},
210  {"wait", 'w', "Wait and retry if connection is down.", 0, 0, 0, GET_UINT,
211  OPT_ARG, 0, 0, 0, 0, 0, 0},
212  {"connect_timeout", OPT_CONNECT_TIMEOUT, "", &opt_connect_timeout,
213  &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 3600*12, 0,
214  3600*12, 0, 1, 0},
215  {"shutdown_timeout", OPT_SHUTDOWN_TIMEOUT, "", &opt_shutdown_timeout,
216  &opt_shutdown_timeout, 0, GET_ULONG, REQUIRED_ARG,
217  SHUTDOWN_DEF_TIMEOUT, 0, 3600*12, 0, 1, 0},
218  {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
219  &opt_plugin_dir, &opt_plugin_dir, 0,
220  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
221  {"default_auth", OPT_DEFAULT_AUTH,
222  "Default authentication client-side plugin to use.",
223  &opt_default_auth, &opt_default_auth, 0,
224  GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
225  {"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN,
226  "Enable/disable the clear text authentication plugin.",
227  &opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin,
228  0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
229  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
230 };
231 
232 
233 static const char *load_default_groups[]= { "mysqladmin","client",0 };
234 
235 my_bool
236 get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
237  char *argument)
238 {
239  int error = 0;
240 
241  switch(optid) {
242  case 'c':
243  opt_count_iterations= 1;
244  break;
245  case 'p':
246  if (argument == disabled_my_option)
247  argument= (char*) ""; // Don't require password
248  if (argument)
249  {
250  char *start=argument;
251  my_free(opt_password);
252  opt_password=my_strdup(argument,MYF(MY_FAE));
253  while (*argument) *argument++= 'x'; /* Destroy argument */
254  if (*start)
255  start[1]=0; /* Cut length of argument */
256  tty_password= 0;
257  }
258  else
259  tty_password=1;
260  break;
261  case 's':
262  option_silent++;
263  break;
264  case 'W':
265 #ifdef __WIN__
266  opt_protocol = MYSQL_PROTOCOL_PIPE;
267 #endif
268  break;
269  case '#':
270  DBUG_PUSH(argument ? argument : "d:t:o,/tmp/mysqladmin.trace");
271  break;
272 #include <sslopt-case.h>
273  case 'V':
274  print_version();
275  exit(0);
276  break;
277  case 'w':
278  if (argument)
279  {
280  if ((option_wait=atoi(argument)) <= 0)
281  option_wait=1;
282  }
283  else
284  option_wait= ~(uint)0;
285  break;
286  case '?':
287  case 'I': /* Info */
288  error++;
289  break;
290  case OPT_CHARSETS_DIR:
291 #if MYSQL_VERSION_ID > 32300
292  charsets_dir = argument;
293 #endif
294  break;
295  case OPT_MYSQL_PROTOCOL:
296  opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
297  opt->name);
298  break;
299  case OPT_ENABLE_CLEARTEXT_PLUGIN:
300  using_opt_enable_cleartext_plugin= TRUE;
301  break;
302  }
303  if (error)
304  {
305  usage();
306  exit(1);
307  }
308  return 0;
309 }
310 
311 
312 int main(int argc,char *argv[])
313 {
314  int error= 0, ho_error;
315  int first_command;
316  my_bool can_handle_passwords;
317  MYSQL mysql;
318  char **commands, **save_argv;
319 
320  MY_INIT(argv[0]);
321  mysql_init(&mysql);
322  my_getopt_use_args_separator= TRUE;
323  if (load_defaults("my",load_default_groups,&argc,&argv))
324  exit(1);
325  my_getopt_use_args_separator= FALSE;
326 
327  save_argv = argv; /* Save for free_defaults */
328  if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
329  {
330  free_defaults(save_argv);
331  exit(ho_error);
332  }
333  if (debug_info_flag)
334  my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
335  if (debug_check_flag)
336  my_end_arg= MY_CHECK_ERROR;
337 
338  if (argc == 0)
339  {
340  usage();
341  exit(1);
342  }
343  commands = argv;
344  if (tty_password)
345  opt_password = get_tty_password(NullS);
346 
347  (void) signal(SIGINT,endprog); /* Here if abort */
348  (void) signal(SIGTERM,endprog); /* Here if abort */
349 
350  if (opt_bind_addr)
351  mysql_options(&mysql,MYSQL_OPT_BIND,opt_bind_addr);
352  if (opt_compress)
353  mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
354  if (opt_connect_timeout)
355  {
356  uint tmp=opt_connect_timeout;
357  mysql_options(&mysql,MYSQL_OPT_CONNECT_TIMEOUT, (char*) &tmp);
358  }
359 #ifdef HAVE_OPENSSL
360  if (opt_use_ssl)
361  {
362  mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
363  opt_ssl_capath, opt_ssl_cipher);
364  mysql_options(&mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
365  mysql_options(&mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
366  }
367  mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
368  (char*)&opt_ssl_verify_server_cert);
369 #endif
370  if (opt_protocol)
371  mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
372 #ifdef HAVE_SMEM
373  if (shared_memory_base_name)
374  mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
375 #endif
376  mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
377  error_flags= (myf)(opt_nobeep ? 0 : ME_BELL);
378 
379  if (opt_plugin_dir && *opt_plugin_dir)
380  mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
381 
382  if (opt_default_auth && *opt_default_auth)
383  mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
384 
385  mysql_options(&mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
386  mysql_options4(&mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
387  "program_name", "mysqladmin");
388  if (using_opt_enable_cleartext_plugin)
389  mysql_options(&mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN,
390  (char*) &opt_enable_cleartext_plugin);
391 
392  first_command= find_type(argv[0], &command_typelib, FIND_TYPE_BASIC);
393  can_handle_passwords=
394  (first_command == ADMIN_PASSWORD || first_command == ADMIN_OLD_PASSWORD) ?
395  TRUE : FALSE;
396  mysql_options(&mysql, MYSQL_OPT_CAN_HANDLE_EXPIRED_PASSWORDS,
397  &can_handle_passwords);
398 
399  if (sql_connect(&mysql, option_wait))
400  {
401  /*
402  We couldn't get an initial connection and will definitely exit.
403  The following just determines the exit-code we'll give.
404  */
405 
406  unsigned int err= mysql_errno(&mysql);
407  if (err >= CR_MIN_ERROR && err <= CR_MAX_ERROR)
408  error= 1;
409  else
410  {
411  /* Return 0 if all commands are PING */
412  for (; argc > 0; argv++, argc--)
413  {
414  if (find_type(argv[0], &command_typelib, FIND_TYPE_BASIC) !=
415  ADMIN_PING)
416  {
417  error= 1;
418  break;
419  }
420  }
421  }
422  }
423  else
424  {
425  /*
426  --count=0 aborts right here. Otherwise iff --sleep=t ("interval")
427  is given a t!=0, we get an endless loop, or n iterations if --count=n
428  was given an n!=0. If --sleep wasn't given, we get one iteration.
429 
430  To wit, --wait loops the connection-attempts, while --sleep loops
431  the command execution (endlessly if no --count is given).
432  */
433 
434  while (!interrupted && (!opt_count_iterations || nr_iterations))
435  {
436  new_line = 0;
437 
438  if ((error= execute_commands(&mysql,argc,commands)))
439  {
440  /*
441  Unknown/malformed command always aborts and can't be --forced.
442  If the user got confused about the syntax, proceeding would be
443  dangerous ...
444  */
445  if (error > 0)
446  break;
447 
448  /*
449  Command was well-formed, but failed on the server. Might succeed
450  on retry (if conditions on server change etc.), but needs --force
451  to retry.
452  */
453  if (!option_force)
454  break;
455  } /* if((error= ... */
456 
457  if (interval) /* --sleep=interval given */
458  {
459  if (opt_count_iterations && --nr_iterations == 0)
460  break;
461 
462  /*
463  If connection was dropped (unintentionally, or due to SHUTDOWN),
464  re-establish it if --wait ("retry-connect") was given and user
465  didn't signal for us to die. Otherwise, signal failure.
466  */
467 
468  if (mysql.net.vio == 0)
469  {
470  if (option_wait && !interrupted)
471  {
472  sleep(1);
473  sql_connect(&mysql, option_wait);
474  /*
475  continue normally and decrease counters so that
476  "mysqladmin --count=1 --wait=1 shutdown"
477  cannot loop endlessly.
478  */
479  }
480  else
481  {
482  /*
483  connexion broke, and we have no order to re-establish it. fail.
484  */
485  if (!option_force)
486  error= 1;
487  break;
488  }
489  } /* lost connection */
490 
491  sleep(interval);
492  if (new_line)
493  puts("");
494  }
495  else
496  break; /* no --sleep, done looping */
497  } /* command-loop */
498  } /* got connection */
499 
500  mysql_close(&mysql);
501  my_free(opt_password);
502  my_free(user);
503 #ifdef HAVE_SMEM
504  my_free(shared_memory_base_name);
505 #endif
506  free_defaults(save_argv);
507  my_end(my_end_arg);
508  exit(error ? 1 : 0);
509  return 0;
510 }
511 
512 
513 sig_handler endprog(int signal_number __attribute__((unused)))
514 {
515  interrupted=1;
516 }
517 
530 static my_bool sql_connect(MYSQL *mysql, uint wait)
531 {
532  my_bool info=0;
533 
534  for (;;)
535  {
536  if (mysql_real_connect(mysql,host,user,opt_password,NullS,tcp_port,
537  unix_port, CLIENT_REMEMBER_OPTIONS))
538  {
539  mysql->reconnect= 1;
540  if (info)
541  {
542  fputs("\n",stderr);
543  (void) fflush(stderr);
544  }
545  return 0;
546  }
547 
548  if (!wait) // was or reached 0, fail
549  {
550  if (!option_silent) // print diagnostics
551  {
552  if (!host)
553  host= (char*) LOCAL_HOST;
554  my_printf_error(0,"connect to server at '%s' failed\nerror: '%s'",
555  error_flags, host, mysql_error(mysql));
556  if (mysql_errno(mysql) == CR_CONNECTION_ERROR)
557  {
558  fprintf(stderr,
559  "Check that mysqld is running and that the socket: '%s' exists!\n",
560  unix_port ? unix_port : mysql_unix_port);
561  }
562  else if (mysql_errno(mysql) == CR_CONN_HOST_ERROR ||
563  mysql_errno(mysql) == CR_UNKNOWN_HOST)
564  {
565  fprintf(stderr,"Check that mysqld is running on %s",host);
566  fprintf(stderr," and that the port is %d.\n",
567  tcp_port ? tcp_port: mysql_port);
568  fprintf(stderr,"You can check this by doing 'telnet %s %d'\n",
569  host, tcp_port ? tcp_port: mysql_port);
570  }
571  }
572  return 1;
573  }
574 
575  if (wait != (uint) ~0)
576  wait--; /* count down, one less retry */
577 
578  if ((mysql_errno(mysql) != CR_CONN_HOST_ERROR) &&
579  (mysql_errno(mysql) != CR_CONNECTION_ERROR))
580  {
581  /*
582  Error is worse than "server doesn't answer (yet?)";
583  fail even if we still have "wait-coins" unless --force
584  was also given.
585  */
586  fprintf(stderr,"Got error: %s\n", mysql_error(mysql));
587  if (!option_force)
588  return 1;
589  }
590  else if (!option_silent)
591  {
592  if (!info)
593  {
594  info=1;
595  fputs("Waiting for MySQL server to answer",stderr);
596  (void) fflush(stderr);
597  }
598  else
599  {
600  putc('.',stderr);
601  (void) fflush(stderr);
602  }
603  }
604  sleep(5);
605  }
606 }
607 
608 
623 static int execute_commands(MYSQL *mysql,int argc, char **argv)
624 {
625  const char *status;
626  /*
627  MySQL documentation relies on the fact that mysqladmin will
628  execute commands in the order specified, e.g.
629  mysqladmin -u root flush-privileges password "newpassword"
630  to reset a lost root password.
631  If this behaviour is ever changed, Docs should be notified.
632  */
633 
634  struct rand_struct rand_st;
635 
636  for (; argc > 0 ; argv++,argc--)
637  {
638  int option;
639  switch (option= find_type(argv[0], &command_typelib, FIND_TYPE_BASIC)) {
640  case ADMIN_CREATE:
641  {
642  char buff[FN_REFLEN+20];
643  if (argc < 2)
644  {
645  my_printf_error(0, "Too few arguments to create", error_flags);
646  return 1;
647  }
648  sprintf(buff,"create database `%.*s`",FN_REFLEN,argv[1]);
649  if (mysql_query(mysql,buff))
650  {
651  my_printf_error(0,"CREATE DATABASE failed; error: '%-.200s'",
652  error_flags, mysql_error(mysql));
653  return -1;
654  }
655  argc--; argv++;
656  break;
657  }
658  case ADMIN_DROP:
659  {
660  if (argc < 2)
661  {
662  my_printf_error(0, "Too few arguments to drop", error_flags);
663  return 1;
664  }
665  if (drop_db(mysql,argv[1]))
666  return -1;
667  argc--; argv++;
668  break;
669  }
670  case ADMIN_SHUTDOWN:
671  {
672  char pidfile[FN_REFLEN];
673  my_bool got_pidfile= 0;
674  time_t last_modified= 0;
675  struct stat pidfile_status;
676 
677  /*
678  Only wait for pidfile on local connections
679  If pidfile doesn't exist, continue without pid file checking
680  */
681  if (mysql->unix_socket && (got_pidfile= !get_pidfile(mysql, pidfile)) &&
682  !stat(pidfile, &pidfile_status))
683  last_modified= pidfile_status.st_mtime;
684 
685  if (mysql_shutdown(mysql, SHUTDOWN_DEFAULT))
686  {
687  my_printf_error(0, "shutdown failed; error: '%s'", error_flags,
688  mysql_error(mysql));
689  return -1;
690  }
691  argc=1; /* force SHUTDOWN to be the last command */
692  if (got_pidfile)
693  {
694  if (opt_verbose)
695  printf("Shutdown signal sent to server; Waiting for pid file to disappear\n");
696 
697  /* Wait until pid file is gone */
698  if (wait_pidfile(pidfile, last_modified, &pidfile_status))
699  return -1;
700  }
701  break;
702  }
703  case ADMIN_FLUSH_PRIVILEGES:
704  case ADMIN_RELOAD:
705  if (mysql_query(mysql,"flush privileges"))
706  {
707  my_printf_error(0, "reload failed; error: '%s'", error_flags,
708  mysql_error(mysql));
709  return -1;
710  }
711  break;
712  case ADMIN_REFRESH:
713  if (mysql_refresh(mysql,
714  (uint) ~(REFRESH_GRANT | REFRESH_STATUS |
715  REFRESH_READ_LOCK | REFRESH_SLAVE |
716  REFRESH_MASTER)))
717  {
718  my_printf_error(0, "refresh failed; error: '%s'", error_flags,
719  mysql_error(mysql));
720  return -1;
721  }
722  break;
723  case ADMIN_FLUSH_THREADS:
724  if (mysql_refresh(mysql,(uint) REFRESH_THREADS))
725  {
726  my_printf_error(0, "refresh failed; error: '%s'", error_flags,
727  mysql_error(mysql));
728  return -1;
729  }
730  break;
731  case ADMIN_VER:
732  new_line=1;
733  print_version();
734  puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
735  printf("Server version\t\t%s\n", mysql_get_server_info(mysql));
736  printf("Protocol version\t%d\n", mysql_get_proto_info(mysql));
737  printf("Connection\t\t%s\n",mysql_get_host_info(mysql));
738  if (mysql->unix_socket)
739  printf("UNIX socket\t\t%s\n", mysql->unix_socket);
740  else
741  printf("TCP port\t\t%d\n", mysql->port);
742  status=mysql_stat(mysql);
743  {
744  char *pos,buff[40];
745  ulong sec;
746  pos= (char*) strchr(status,' ');
747  *pos++=0;
748  printf("%s\t\t\t",status); /* print label */
749  if ((status=str2int(pos,10,0,LONG_MAX,(long*) &sec)))
750  {
751  nice_time(sec,buff);
752  puts(buff); /* print nice time */
753  while (*status == ' ') status++; /* to next info */
754  }
755  }
756  putc('\n',stdout);
757  if (status)
758  puts(status);
759  break;
760  case ADMIN_PROCESSLIST:
761  {
762  MYSQL_RES *result;
763  MYSQL_ROW row;
764 
765  if (mysql_query(mysql, (opt_verbose ? "show full processlist" :
766  "show processlist")) ||
767  !(result = mysql_store_result(mysql)))
768  {
769  my_printf_error(0, "process list failed; error: '%s'", error_flags,
770  mysql_error(mysql));
771  return -1;
772  }
773  print_header(result);
774  while ((row=mysql_fetch_row(result)))
775  print_row(result,row,0);
776  print_top(result);
777  mysql_free_result(result);
778  new_line=1;
779  break;
780  }
781  case ADMIN_STATUS:
782  status=mysql_stat(mysql);
783  if (status)
784  puts(status);
785  break;
786  case ADMIN_KILL:
787  {
788  uint error=0;
789  char *pos;
790  if (argc < 2)
791  {
792  my_printf_error(0, "Too few arguments to 'kill'", error_flags);
793  return 1;
794  }
795  pos=argv[1];
796  for (;;)
797  {
798  /* We don't use mysql_kill(), since it only handles 32-bit IDs. */
799  char buff[26], *out; /* "KILL " + max 20 digs + NUL */
800  out= strxmov(buff, "KILL ", NullS);
801  ullstr(strtoull(pos, NULL, 0), out);
802 
803  if (mysql_query(mysql, buff))
804  {
805  /* out still points to just the number */
806  my_printf_error(0, "kill failed on %s; error: '%s'", error_flags,
807  out, mysql_error(mysql));
808  error=1;
809  }
810  if (!(pos=strchr(pos,',')))
811  break;
812  pos++;
813  }
814  argc--; argv++;
815  if (error)
816  return -1;
817  break;
818  }
819  case ADMIN_DEBUG:
820  if (mysql_dump_debug_info(mysql))
821  {
822  my_printf_error(0, "debug failed; error: '%s'", error_flags,
823  mysql_error(mysql));
824  return -1;
825  }
826  break;
827  case ADMIN_VARIABLES:
828  {
829  MYSQL_RES *res;
830  MYSQL_ROW row;
831 
832  new_line=1;
833  if (mysql_query(mysql,"show /*!40003 GLOBAL */ variables") ||
834  !(res=mysql_store_result(mysql)))
835  {
836  my_printf_error(0, "unable to show variables; error: '%s'", error_flags,
837  mysql_error(mysql));
838  return -1;
839  }
840  print_header(res);
841  while ((row=mysql_fetch_row(res)))
842  print_row(res,row,0);
843  print_top(res);
844  mysql_free_result(res);
845  break;
846  }
847  case ADMIN_EXTENDED_STATUS:
848  {
849  MYSQL_RES *res;
850  MYSQL_ROW row;
851  uint rownr = 0;
852  void (*func) (MYSQL_RES*, MYSQL_ROW, uint);
853 
854  new_line = 1;
855  if (mysql_query(mysql, "show /*!50002 GLOBAL */ status") ||
856  !(res = mysql_store_result(mysql)))
857  {
858  my_printf_error(0, "unable to show status; error: '%s'", error_flags,
859  mysql_error(mysql));
860  return -1;
861  }
862 
863  DBUG_ASSERT(mysql_num_rows(res) < MAX_MYSQL_VAR);
864 
865  if (!opt_vertical)
866  print_header(res);
867  else
868  {
869  if (!ex_status_printed)
870  {
871  store_values(res);
872  truncate_names(); /* Does some printing also */
873  }
874  else
875  {
876  print_relative_line();
877  print_relative_header();
878  print_relative_line();
879  }
880  }
881 
882  /* void (*func) (MYSQL_RES*, MYSQL_ROW, uint); */
883  if (opt_relative && !opt_vertical)
884  func = print_relative_row;
885  else if (opt_vertical)
886  func = print_relative_row_vert;
887  else
888  func = print_row;
889 
890  while ((row = mysql_fetch_row(res)))
891  (*func)(res, row, rownr++);
892  if (opt_vertical)
893  {
894  if (ex_status_printed)
895  {
896  putchar('\n');
897  print_relative_line();
898  }
899  }
900  else
901  print_top(res);
902 
903  ex_status_printed = 1; /* From now on the output will be relative */
904  mysql_free_result(res);
905  break;
906  }
907  case ADMIN_FLUSH_LOGS:
908  {
909  if (mysql_refresh(mysql,REFRESH_LOG))
910  {
911  my_printf_error(0, "refresh failed; error: '%s'", error_flags,
912  mysql_error(mysql));
913  return -1;
914  }
915  break;
916  }
917  case ADMIN_FLUSH_HOSTS:
918  {
919  if (mysql_query(mysql,"flush hosts"))
920  {
921  my_printf_error(0, "refresh failed; error: '%s'", error_flags,
922  mysql_error(mysql));
923  return -1;
924  }
925  break;
926  }
927  case ADMIN_FLUSH_TABLES:
928  {
929  if (mysql_query(mysql,"flush tables"))
930  {
931  my_printf_error(0, "refresh failed; error: '%s'", error_flags,
932  mysql_error(mysql));
933  return -1;
934  }
935  break;
936  }
937  case ADMIN_FLUSH_STATUS:
938  {
939  if (mysql_query(mysql,"flush status"))
940  {
941  my_printf_error(0, "refresh failed; error: '%s'", error_flags,
942  mysql_error(mysql));
943  return -1;
944  }
945  break;
946  }
947  case ADMIN_OLD_PASSWORD:
948  case ADMIN_PASSWORD:
949  {
950  char buff[128],crypted_pw[64];
951  time_t start_time;
952  char *typed_password= NULL, *verified= NULL;
953  bool log_off= true, err= false;
954  int retry_count= 0; /* Attempts to SET PASSWORD */
955 
956  bool old= (option == ADMIN_OLD_PASSWORD);
957 
958  /* Do initialization the same way as we do in mysqld */
959  start_time=time((time_t*) 0);
960  randominit(&rand_st,(ulong) start_time,(ulong) start_time/2);
961 
962  if (argc < 1)
963  {
964  my_printf_error(0, "Too few arguments to change password", error_flags);
965  return 1;
966  }
967  else if (argc == 1)
968  {
969  /* prompt for password */
970  typed_password= get_tty_password("New password: ");
971  verified= get_tty_password("Confirm new password: ");
972  if (strcmp(typed_password, verified) != 0)
973  {
974  my_printf_error(0,"Passwords don't match",MYF(ME_BELL));
975  err= true;
976  goto error;
977  }
978  }
979  else
980  typed_password= argv[1];
981 
982  if (typed_password[0])
983  {
984 #ifdef __WIN__
985  size_t pw_len= strlen(typed_password);
986  if (pw_len > 1 && typed_password[0] == '\'' &&
987  typed_password[pw_len-1] == '\'')
988  printf("Warning: single quotes were not trimmed from the password by"
989  " your command\nline client, as you might have expected.\n");
990 #endif
991  /*
992  If we don't already know to use an old-style password, see
993  (if possible) what the server is using.
994  */
995  if (!old)
996  {
997  if (mysql_query(mysql, "SHOW VARIABLES LIKE 'old_passwords'"))
998  {
999  bool fatal= (mysql_errno(mysql) != ER_MUST_CHANGE_PASSWORD);
1000  if (fatal || opt_verbose)
1001  my_printf_error(0, "Could not determine old_passwords setting "
1002  "from server; error: '%s'.", error_flags,
1003  mysql_error(mysql));
1004  if (fatal)
1005  {
1006  err= true;
1007  goto error;
1008  }
1009  }
1010  else
1011  {
1012  MYSQL_RES *res= mysql_store_result(mysql);
1013  if (!res)
1014  {
1015  my_printf_error(0,
1016  "Could not get old_passwords setting from "
1017  "server; error: '%s'.",
1018  error_flags, mysql_error(mysql));
1019  err= true;
1020  goto error;
1021  }
1022  if (!mysql_num_rows(res))
1023  old= 1;
1024  else
1025  {
1026  MYSQL_ROW row= mysql_fetch_row(res);
1027  old= (!strncmp(row[1], "ON", 2) || !strncmp(row[1], "1", 1));
1028  }
1029  mysql_free_result(res);
1030  }
1031  }
1032  /* turn logging off if we can */
1033  if (mysql_query(mysql,"set sql_log_off=1"))
1034  {
1035  if (opt_verbose)
1036  fprintf(stderr, "Note: Can't turn off logging; '%s'", mysql_error(mysql));
1037  log_off= false;
1038  }
1039 
1040 retry:
1041  /*
1042  In case the password_expired flag is set ('Y'), then there is no way
1043  to determine the password format. So, we first try to set the
1044  password using native format. If it fails with ER_PASSWORD_LENGTH,
1045  we will give one more try with old format.
1046  */
1047  if (old)
1048  make_scrambled_password_323(crypted_pw, typed_password);
1049  else
1050  make_scrambled_password(crypted_pw, typed_password);
1051  }
1052  else
1053  crypted_pw[0]=0; /* No password */
1054 
1055  sprintf(buff, "set password='%s'", crypted_pw);
1056 
1057  if (mysql_query(mysql,buff))
1058  {
1059  if ((mysql_errno(mysql) == ER_PASSWD_LENGTH) &&
1060  !(option == ADMIN_OLD_PASSWORD) && !retry_count)
1061  {
1062  /* Try to set the password using old format. */
1063  memset(crypted_pw, 0, 64);
1064  old= 0;
1065  retry_count ++;
1066  goto retry;
1067  }
1068 
1069  if (mysql_errno(mysql)!=1290)
1070  {
1071  my_printf_error(0,"unable to change password; error: '%s'",
1072  error_flags, mysql_error(mysql));
1073  err= true;
1074  goto error;
1075  }
1076  else
1077  {
1078  /*
1079  We don't try to execute 'update mysql.user set..'
1080  because we can't perfectly find out the host
1081  */
1082  my_printf_error(0,"\n"
1083  "You cannot use 'password' command as mysqld runs\n"
1084  " with grant tables disabled (was started with"
1085  " --skip-grant-tables).\n"
1086  "Use: \"mysqladmin flush-privileges password '*'\""
1087  " instead", error_flags);
1088  err= true;
1089  goto error;
1090  }
1091  }
1092  if (log_off && mysql_query(mysql, "set sql_log_off=0"))
1093  {
1094  if (opt_verbose)
1095  fprintf(stderr, "Note: Can't turn on logging; '%s'", mysql_error(mysql));
1096  }
1097 error:
1098  /* free up memory from prompted password */
1099  if (typed_password != argv[1])
1100  {
1101  my_free(typed_password);
1102  my_free(verified);
1103  }
1104  if (err)
1105  return -1;
1106 
1107  argc--; argv++;
1108  break;
1109  }
1110 
1111  case ADMIN_START_SLAVE:
1112  if (mysql_query(mysql, "START SLAVE"))
1113  {
1114  my_printf_error(0, "Error starting slave: %s", error_flags,
1115  mysql_error(mysql));
1116  return -1;
1117  }
1118  else
1119  puts("Slave started");
1120  break;
1121  case ADMIN_STOP_SLAVE:
1122  if (mysql_query(mysql, "STOP SLAVE"))
1123  {
1124  my_printf_error(0, "Error stopping slave: %s", error_flags,
1125  mysql_error(mysql));
1126  return -1;
1127  }
1128  else
1129  puts("Slave stopped");
1130  break;
1131 
1132  case ADMIN_PING:
1133  mysql->reconnect=0; /* We want to know of reconnects */
1134  if (!mysql_ping(mysql))
1135  {
1136  if (option_silent < 2)
1137  puts("mysqld is alive");
1138  }
1139  else
1140  {
1141  if (mysql_errno(mysql) == CR_SERVER_GONE_ERROR)
1142  {
1143  mysql->reconnect=1;
1144  if (!mysql_ping(mysql))
1145  puts("connection was down, but mysqld is now alive");
1146  }
1147  else
1148  {
1149  my_printf_error(0,"mysqld doesn't answer to ping, error: '%s'",
1150  error_flags, mysql_error(mysql));
1151  return -1;
1152  }
1153  }
1154  mysql->reconnect=1; /* Automatic reconnect is default */
1155  break;
1156  default:
1157  my_printf_error(0, "Unknown command: '%-.60s'", error_flags, argv[0]);
1158  return 1;
1159  }
1160  }
1161  return 0;
1162 }
1163 
1164 
1165 static void print_version(void)
1166 {
1167  printf("%s Ver %s Distrib %s, for %s on %s\n",my_progname,ADMIN_VERSION,
1168  MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
1169 }
1170 
1171 
1172 static void usage(void)
1173 {
1174  print_version();
1175  puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
1176  puts("Administration program for the mysqld daemon.");
1177  printf("Usage: %s [OPTIONS] command command....\n", my_progname);
1178  my_print_help(my_long_options);
1179  my_print_variables(my_long_options);
1180  print_defaults("my",load_default_groups);
1181  puts("\nWhere command is a one or more of: (Commands may be shortened)\n\
1182  create databasename Create a new database\n\
1183  debug Instruct server to write debug information to log\n\
1184  drop databasename Delete a database and all its tables\n\
1185  extended-status Gives an extended status message from the server\n\
1186  flush-hosts Flush all cached hosts\n\
1187  flush-logs Flush all logs\n\
1188  flush-status Clear status variables\n\
1189  flush-tables Flush all tables\n\
1190  flush-threads Flush the thread cache\n\
1191  flush-privileges Reload grant tables (same as reload)\n\
1192  kill id,id,... Kill mysql threads");
1193 #if MYSQL_VERSION_ID >= 32200
1194  puts("\
1195  password [new-password] Change old password to new-password in current format\n\
1196  old-password [new-password] Change old password to new-password in old format");
1197 #endif
1198  puts("\
1199  ping Check if mysqld is alive\n\
1200  processlist Show list of active threads in server\n\
1201  reload Reload grant tables\n\
1202  refresh Flush all tables and close and open logfiles\n\
1203  shutdown Take server down\n\
1204  status Gives a short status message from the server\n\
1205  start-slave Start slave\n\
1206  stop-slave Stop slave\n\
1207  variables Prints variables available\n\
1208  version Get version info from server");
1209 }
1210 
1211 
1212 static int drop_db(MYSQL *mysql, const char *db)
1213 {
1214  char name_buff[FN_REFLEN+20], buf[10];
1215  char *input;
1216 
1217  if (!option_force)
1218  {
1219  puts("Dropping the database is potentially a very bad thing to do.");
1220  puts("Any data stored in the database will be destroyed.\n");
1221  printf("Do you really want to drop the '%s' database [y/N] ",db);
1222  fflush(stdout);
1223  input= fgets(buf, sizeof(buf)-1, stdin);
1224  if (!input || ((*input != 'y') && (*input != 'Y')))
1225  {
1226  puts("\nOK, aborting database drop!");
1227  return -1;
1228  }
1229  }
1230  sprintf(name_buff,"drop database `%.*s`",FN_REFLEN,db);
1231  if (mysql_query(mysql,name_buff))
1232  {
1233  my_printf_error(0, "DROP DATABASE %s failed;\nerror: '%s'", error_flags,
1234  db,mysql_error(mysql));
1235  return 1;
1236  }
1237  printf("Database \"%s\" dropped\n",db);
1238  return 0;
1239 }
1240 
1241 
1242 static void nice_time(ulong sec,char *buff)
1243 {
1244  ulong tmp;
1245 
1246  if (sec >= 3600L*24)
1247  {
1248  tmp=sec/(3600L*24);
1249  sec-=3600L*24*tmp;
1250  buff=int10_to_str(tmp, buff, 10);
1251  buff=strmov(buff,tmp > 1 ? " days " : " day ");
1252  }
1253  if (sec >= 3600L)
1254  {
1255  tmp=sec/3600L;
1256  sec-=3600L*tmp;
1257  buff=int10_to_str(tmp, buff, 10);
1258  buff=strmov(buff,tmp > 1 ? " hours " : " hour ");
1259  }
1260  if (sec >= 60)
1261  {
1262  tmp=sec/60;
1263  sec-=60*tmp;
1264  buff=int10_to_str(tmp, buff, 10);
1265  buff=strmov(buff," min ");
1266  }
1267  strmov(int10_to_str(sec, buff, 10)," sec");
1268 }
1269 
1270 
1271 static void print_header(MYSQL_RES *result)
1272 {
1273  MYSQL_FIELD *field;
1274 
1275  print_top(result);
1276  mysql_field_seek(result,0);
1277  putchar('|');
1278  while ((field = mysql_fetch_field(result)))
1279  {
1280  printf(" %-*s|",(int) field->max_length+1,field->name);
1281  }
1282  putchar('\n');
1283  print_top(result);
1284 }
1285 
1286 
1287 static void print_top(MYSQL_RES *result)
1288 {
1289  uint i,length;
1290  MYSQL_FIELD *field;
1291 
1292  putchar('+');
1293  mysql_field_seek(result,0);
1294  while((field = mysql_fetch_field(result)))
1295  {
1296  if ((length=(uint) strlen(field->name)) > field->max_length)
1297  field->max_length=length;
1298  else
1299  length=field->max_length;
1300  for (i=length+2 ; i--> 0 ; )
1301  putchar('-');
1302  putchar('+');
1303  }
1304  putchar('\n');
1305 }
1306 
1307 
1308 /* 3.rd argument, uint row, is not in use. Don't remove! */
1309 static void print_row(MYSQL_RES *result, MYSQL_ROW cur,
1310  uint row __attribute__((unused)))
1311 {
1312  uint i,length;
1313  MYSQL_FIELD *field;
1314 
1315  putchar('|');
1316  mysql_field_seek(result,0);
1317  for (i=0 ; i < mysql_num_fields(result); i++)
1318  {
1319  field = mysql_fetch_field(result);
1320  length=field->max_length;
1321  printf(" %-*s|",length+1,cur[i] ? (char*) cur[i] : "");
1322  }
1323  putchar('\n');
1324 }
1325 
1326 
1327 static void print_relative_row(MYSQL_RES *result, MYSQL_ROW cur, uint row)
1328 {
1329  ulonglong tmp;
1330  char buff[22];
1331  MYSQL_FIELD *field;
1332 
1333  mysql_field_seek(result, 0);
1334  field = mysql_fetch_field(result);
1335  printf("| %-*s|", (int) field->max_length + 1, cur[0]);
1336 
1337  field = mysql_fetch_field(result);
1338  tmp = cur[1] ? strtoull(cur[1], NULL, 10) : (ulonglong) 0;
1339  printf(" %-*s|\n", (int) field->max_length + 1,
1340  llstr((tmp - last_values[row]), buff));
1341  last_values[row] = tmp;
1342 }
1343 
1344 
1345 static void print_relative_row_vert(MYSQL_RES *result __attribute__((unused)),
1346  MYSQL_ROW cur,
1347  uint row __attribute__((unused)))
1348 {
1349  uint length;
1350  ulonglong tmp;
1351  char buff[22];
1352 
1353  if (!row)
1354  putchar('|');
1355 
1356  tmp = cur[1] ? strtoull(cur[1], NULL, 10) : (ulonglong) 0;
1357  printf(" %-*s|", ex_val_max_len[row] + 1,
1358  llstr((tmp - last_values[row]), buff));
1359 
1360  /* Find the minimum row length needed to output the relative value */
1361  if ((length=(uint) strlen(buff) > ex_val_max_len[row]) && ex_status_printed)
1362  ex_val_max_len[row] = length;
1363  last_values[row] = tmp;
1364 }
1365 
1366 
1367 static void store_values(MYSQL_RES *result)
1368 {
1369  uint i;
1370  MYSQL_ROW row;
1371  MYSQL_FIELD *field;
1372 
1373  field = mysql_fetch_field(result);
1374  max_var_length = field->max_length;
1375  field = mysql_fetch_field(result);
1376  max_val_length = field->max_length;
1377 
1378  for (i = 0; (row = mysql_fetch_row(result)); i++)
1379  {
1380  strmov(ex_var_names[i], row[0]);
1381  last_values[i]=strtoull(row[1],NULL,10);
1382  ex_val_max_len[i]=2; /* Default print width for values */
1383  }
1384  ex_var_count = i;
1385  return;
1386 }
1387 
1388 
1389 static void print_relative_header()
1390 {
1391  uint i;
1392 
1393  putchar('|');
1394  for (i = 0; i < ex_var_count; i++)
1395  printf(" %-*s|", ex_val_max_len[i] + 1, truncated_var_names[i]);
1396  putchar('\n');
1397 }
1398 
1399 
1400 static void print_relative_line()
1401 {
1402  uint i;
1403 
1404  putchar('+');
1405  for (i = 0; i < ex_var_count; i++)
1406  {
1407  uint j;
1408  for (j = 0; j < ex_val_max_len[i] + 2; j++)
1409  putchar('-');
1410  putchar('+');
1411  }
1412  putchar('\n');
1413 }
1414 
1415 
1416 static void truncate_names()
1417 {
1418  uint i;
1419  char *ptr,top_line[MAX_TRUNC_LENGTH+4+NAME_LEN+22+1],buff[22];
1420 
1421  ptr=top_line;
1422  *ptr++='+';
1423  ptr=strfill(ptr,max_var_length+2,'-');
1424  *ptr++='+';
1425  ptr=strfill(ptr,MAX_TRUNC_LENGTH+2,'-');
1426  *ptr++='+';
1427  ptr=strfill(ptr,max_val_length+2,'-');
1428  *ptr++='+';
1429  *ptr=0;
1430  puts(top_line);
1431 
1432  for (i = 0 ; i < ex_var_count; i++)
1433  {
1434  uint sfx=1,j;
1435  printf("| %-*s|", max_var_length + 1, ex_var_names[i]);
1436  ptr = ex_var_names[i];
1437  /* Make sure no two same truncated names will become */
1438  for (j = 0; j < i; j++)
1439  if (*truncated_var_names[j] == *ptr)
1440  sfx++;
1441 
1442  truncated_var_names[i][0]= *ptr; /* Copy first var char */
1443  int10_to_str(sfx, truncated_var_names[i]+1,10);
1444  printf(" %-*s|", MAX_TRUNC_LENGTH + 1, truncated_var_names[i]);
1445  printf(" %-*s|\n", max_val_length + 1, llstr(last_values[i],buff));
1446  }
1447  puts(top_line);
1448  return;
1449 }
1450 
1451 
1452 static my_bool get_pidfile(MYSQL *mysql, char *pidfile)
1453 {
1454  MYSQL_RES* result;
1455 
1456  if (mysql_query(mysql, "SHOW VARIABLES LIKE 'pid_file'"))
1457  {
1458  my_printf_error(0, "query failed; error: '%s'", error_flags,
1459  mysql_error(mysql));
1460  }
1461  result = mysql_store_result(mysql);
1462  if (result)
1463  {
1464  MYSQL_ROW row=mysql_fetch_row(result);
1465  if (row)
1466  strmov(pidfile, row[1]);
1467  mysql_free_result(result);
1468  return row == 0; /* Error if row = 0 */
1469  }
1470  return 1; /* Error */
1471 }
1472 
1473 /*
1474  Return 1 if pid file didn't disappear or change
1475 */
1476 
1477 static my_bool wait_pidfile(char *pidfile, time_t last_modified,
1478  struct stat *pidfile_status)
1479 {
1480  char buff[FN_REFLEN];
1481  int error= 1;
1482  uint count= 0;
1483  DBUG_ENTER("wait_pidfile");
1484 
1485  system_filename(buff, pidfile);
1486  do
1487  {
1488  int fd;
1489  if ((fd= my_open(buff, O_RDONLY, MYF(0))) < 0)
1490  {
1491  error= 0;
1492  break;
1493  }
1494  (void) my_close(fd,MYF(0));
1495  if (last_modified && !stat(pidfile, pidfile_status))
1496  {
1497  if (last_modified != pidfile_status->st_mtime)
1498  {
1499  /* File changed; Let's assume that mysqld did restart */
1500  if (opt_verbose)
1501  printf("pid file '%s' changed while waiting for it to disappear!\nmysqld did probably restart\n",
1502  buff);
1503  error= 0;
1504  break;
1505  }
1506  }
1507  if (count++ == opt_shutdown_timeout)
1508  break;
1509  sleep(1);
1510  } while (!interrupted);
1511 
1512  if (error)
1513  {
1514  DBUG_PRINT("warning",("Pid file didn't disappear"));
1515  fprintf(stderr,
1516  "Warning; Aborted waiting on pid file: '%s' after %d seconds\n",
1517  buff, count-1);
1518  }
1519  DBUG_RETURN(error);
1520 }