~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2006 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
/* maintaince of mysql databases */
17
18
#include "client_priv.h"
19
#include <signal.h>
20
#ifdef THREAD
21
#include <my_pthread.h>				/* because of signal()	*/
22
#endif
23
#include <sys/stat.h>
24
#include <mysql.h>
25
26
#ifdef LATER_HAVE_NDBCLUSTER_DB
27
#include "../ndb/src/mgmclient/ndb_mgmclient.h"
28
#endif
29
30
#define ADMIN_VERSION "8.42"
31
#define MAX_MYSQL_VAR 256
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= NULL;
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 ulong opt_connect_timeout, opt_shutdown_timeout;
48
static char * unix_port=0;
49
#ifdef LATER_HAVE_NDBCLUSTER_DB
50
static my_bool opt_ndbcluster=0;
51
static char *opt_ndb_connectstring=0;
52
#endif
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
static void print_version(void);
71
static void usage(void);
72
extern "C" my_bool get_one_option(int optid, const struct my_option *opt,
73
                                  char *argument);
74
static my_bool sql_connect(MYSQL *mysql, uint wait);
75
static int execute_commands(MYSQL *mysql,int argc, char **argv);
76
static int drop_db(MYSQL *mysql,const char *db);
77
extern "C" sig_handler endprog(int signal_number);
78
static void nice_time(ulong sec,char *buff);
79
static void print_header(MYSQL_RES *result);
80
static void print_top(MYSQL_RES *result);
81
static void print_row(MYSQL_RES *result,MYSQL_ROW cur, uint row);
82
static void print_relative_row(MYSQL_RES *result, MYSQL_ROW cur, uint row);
83
static void print_relative_row_vert(MYSQL_RES *result, MYSQL_ROW cur, uint row);
84
static void print_relative_header();
85
static void print_relative_line();
86
static void truncate_names();
87
static my_bool get_pidfile(MYSQL *mysql, char *pidfile);
88
static my_bool wait_pidfile(char *pidfile, time_t last_modified,
89
			    struct stat *pidfile_status);
90
static void store_values(MYSQL_RES *result);
91
92
/*
93
  The order of commands must be the same as command_names,
94
  except ADMIN_ERROR
95
*/
96
enum commands {
97
  ADMIN_ERROR,
98
  ADMIN_CREATE,           ADMIN_DROP,            ADMIN_SHUTDOWN,
99
  ADMIN_RELOAD,           ADMIN_REFRESH,         ADMIN_VER,
100
  ADMIN_PROCESSLIST,      ADMIN_STATUS,          ADMIN_KILL,
101
  ADMIN_DEBUG,            ADMIN_VARIABLES,       ADMIN_FLUSH_LOGS,
102
  ADMIN_FLUSH_HOSTS,      ADMIN_FLUSH_TABLES,    ADMIN_PASSWORD,
103
  ADMIN_PING,             ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS,
104
  ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE,     ADMIN_STOP_SLAVE,
105
  ADMIN_FLUSH_THREADS,    ADMIN_OLD_PASSWORD
106
#ifdef LATER_HAVE_NDBCLUSTER_DB
107
  ,ADMIN_NDB_MGM
108
#endif
109
};
110
static const char *command_names[]= {
111
  "create",               "drop",                "shutdown",
112
  "reload",               "refresh",             "version",
113
  "processlist",          "status",              "kill",
114
  "debug",                "variables",           "flush-logs",
115
  "flush-hosts",          "flush-tables",        "password",
116
  "ping",                 "extended-status",     "flush-status",
117
  "flush-privileges",     "start-slave",         "stop-slave",
118
  "flush-threads","old-password",
119
#ifdef LATER_HAVE_NDBCLUSTER_DB
120
  "ndb-mgm",
121
#endif
122
  NullS
123
};
124
125
static TYPELIB command_typelib=
126
{ array_elements(command_names)-1,"commands", command_names, NULL};
127
128
static struct my_option my_long_options[] =
129
{
130
  {"count", 'c',
131
   "Number of iterations to make. This works with -i (--sleep) only.",
132
   (uchar**) &nr_iterations, (uchar**) &nr_iterations, 0, GET_UINT,
133
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
134
#ifndef DBUG_OFF
135
  {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
136
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
137
#endif
138
  {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit .",
139
   (uchar**) &debug_check_flag, (uchar**) &debug_check_flag, 0,
140
   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
141
  {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
142
   (uchar**) &debug_info_flag, (uchar**) &debug_info_flag,
143
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
144
  {"force", 'f',
145
   "Don't ask for confirmation on drop database; with multiple commands, continue even if an error occurs.",
146
   (uchar**) &option_force, (uchar**) &option_force, 0, GET_BOOL, NO_ARG, 0, 0,
147
   0, 0, 0, 0},
148
  {"compress", 'C', "Use compression in server/client protocol.",
149
   (uchar**) &opt_compress, (uchar**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
150
   0, 0, 0},
151
  {"character-sets-dir", OPT_CHARSETS_DIR,
152
   "Directory where character sets are.", (uchar**) &charsets_dir,
153
   (uchar**) &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.", (uchar**) &default_charset,
156
   (uchar**) &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.", (uchar**) &host, (uchar**) &host, 0, GET_STR,
160
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
161
  {"no-beep", 'b', "Turn off beep on error.", (uchar**) &opt_nobeep,
162
   (uchar**) &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_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
166
  {"port", 'P', "Port number to use for connection or 0 for default to, in "
167
   "order of preference, my.cnf, $MYSQL_TCP_PORT, "
168
#if MYSQL_PORT_DEFAULT == 0
169
   "/etc/services, "
170
#endif
171
   "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
172
   (uchar**) &tcp_port,
173
   (uchar**) &tcp_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
174
  {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).",
175
    0, 0, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
176
  {"relative", 'r',
177
   "Show difference between current and previous values when used with -i. Currently works only with extended-status.",
178
   (uchar**) &opt_relative, (uchar**) &opt_relative, 0, GET_BOOL, NO_ARG, 0, 0, 0,
179
  0, 0, 0},
180
  {"set-variable", 'O',
181
   "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
182
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
183
#ifdef HAVE_SMEM
184
  {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
185
   "Base name of shared memory.", (uchar**) &shared_memory_base_name, (uchar**) &shared_memory_base_name,
186
   0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
187
#endif
188
  {"silent", 's', "Silently exit if one can't connect to server.",
189
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
190
  {"socket", 'S', "Socket file to use for connection.",
191
   (uchar**) &unix_port, (uchar**) &unix_port, 0, GET_STR, REQUIRED_ARG, 0, 0, 0,
192
   0, 0, 0},
193
  {"sleep", 'i', "Execute commands again and again with a sleep between.",
194
   (uchar**) &interval, (uchar**) &interval, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0,
195
   0, 0},
196
#ifndef DONT_ALLOW_USER_CHANGE
197
  {"user", 'u', "User for login if not current user.", (uchar**) &user,
198
   (uchar**) &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
199
#endif
200
  {"verbose", 'v', "Write more information.", (uchar**) &opt_verbose,
201
   (uchar**) &opt_verbose, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
202
  {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
203
   NO_ARG, 0, 0, 0, 0, 0, 0},
204
  {"vertical", 'E',
205
   "Print output vertically. Is similar to --relative, but prints output vertically.",
206
   (uchar**) &opt_vertical, (uchar**) &opt_vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0,
207
   0, 0, 0},
208
  {"wait", 'w', "Wait and retry if connection is down.", 0, 0, 0, GET_UINT,
209
   OPT_ARG, 0, 0, 0, 0, 0, 0},
210
  {"connect_timeout", OPT_CONNECT_TIMEOUT, "", (uchar**) &opt_connect_timeout,
211
   (uchar**) &opt_connect_timeout, 0, GET_ULONG, REQUIRED_ARG, 3600*12, 0,
212
   3600*12, 0, 1, 0},
213
  {"shutdown_timeout", OPT_SHUTDOWN_TIMEOUT, "", (uchar**) &opt_shutdown_timeout,
214
   (uchar**) &opt_shutdown_timeout, 0, GET_ULONG, REQUIRED_ARG,
215
   SHUTDOWN_DEF_TIMEOUT, 0, 3600*12, 0, 1, 0},
216
#ifdef LATER_HAVE_NDBCLUSTER_DB
217
  {"ndbcluster", OPT_NDBCLUSTER, ""
218
   "", (uchar**) &opt_ndbcluster,
219
   (uchar**) &opt_ndbcluster, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
220
  {"ndb-connectstring", OPT_NDB_CONNECTSTRING, ""
221
   "", (uchar**) &opt_ndb_connectstring,
222
   (uchar**) &opt_ndb_connectstring, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
223
#endif
224
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
225
};
226
227
228
static const char *load_default_groups[]= { "mysqladmin","client",0 };
229
230
my_bool
231
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
232
	       char *argument)
233
{
234
  int error = 0;
235
236
  switch(optid) {
237
  case 'c':
238
    opt_count_iterations= 1;
239
    break;
240
  case 'p':
241
    if (argument)
242
    {
243
      char *start=argument;
244
      my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
245
      opt_password=my_strdup(argument,MYF(MY_FAE));
246
      while (*argument) *argument++= 'x';		/* Destroy argument */
247
      if (*start)
248
	start[1]=0;				/* Cut length of argument */
249
      tty_password= 0;
250
    }
251
    else
252
      tty_password=1;
253
    break;
254
  case 's':
255
    option_silent++;
256
    break;
257
  case '#':
258
    DBUG_PUSH(argument ? argument : "d:t:o,/tmp/mysqladmin.trace");
259
    break;
260
  case 'V':
261
    print_version();
262
    exit(0);
263
    break;
264
  case 'w':
265
    if (argument)
266
    {
267
      if ((option_wait=atoi(argument)) <= 0)
268
	option_wait=1;
269
    }
270
    else
271
      option_wait= ~(uint)0;
272
    break;
273
  case '?':
274
  case 'I':					/* Info */
275
    error++;
276
    break;
277
  case OPT_CHARSETS_DIR:
278
#if MYSQL_VERSION_ID > 32300
279
    charsets_dir = argument;
280
#endif
281
    break;
282
  case OPT_MYSQL_PROTOCOL:
283
    opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
284
                                    opt->name);
285
    break;
286
  }
287
  if (error)
288
  {
289
    usage();
290
    exit(1);
291
  }
292
  return 0;
293
}
294
295
296
int main(int argc,char *argv[])
297
{
298
  int error= 0, ho_error;
299
  MYSQL mysql;
300
  char **commands, **save_argv;
301
302
  MY_INIT(argv[0]);
303
  mysql_init(&mysql);
304
  load_defaults("my",load_default_groups,&argc,&argv);
305
  save_argv = argv;				/* Save for free_defaults */
306
  if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
307
  {
308
    free_defaults(save_argv);
309
    exit(ho_error);
310
  }
311
  if (debug_info_flag)
312
    my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
313
  if (debug_check_flag)
314
    my_end_arg= MY_CHECK_ERROR;
315
316
  if (argc == 0)
317
  {
318
    usage();
319
    exit(1);
320
  }
321
  commands = argv;
322
  if (tty_password)
323
    opt_password = get_tty_password(NullS);
324
325
  VOID(signal(SIGINT,endprog));			/* Here if abort */
326
  VOID(signal(SIGTERM,endprog));		/* Here if abort */
327
328
  if (opt_compress)
329
    mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
330
  if (opt_connect_timeout)
331
  {
332
    uint tmp=opt_connect_timeout;
333
    mysql_options(&mysql,MYSQL_OPT_CONNECT_TIMEOUT, (char*) &tmp);
334
  }
335
#ifdef HAVE_OPENSSL
336
  if (opt_use_ssl)
337
    mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
338
		  opt_ssl_capath, opt_ssl_cipher);
339
  mysql_options(&mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
340
                (char*)&opt_ssl_verify_server_cert);
341
#endif
342
  if (opt_protocol)
343
    mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
344
#ifdef HAVE_SMEM
345
  if (shared_memory_base_name)
346
    mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
347
#endif
348
  if (default_charset)
349
    mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
350
  error_flags= (myf)(opt_nobeep ? 0 : ME_BELL);
351
352
  if (sql_connect(&mysql, option_wait))
353
  {
354
    unsigned int err= mysql_errno(&mysql);
355
    if (err >= CR_MIN_ERROR && err <= CR_MAX_ERROR)
356
      error= 1;
357
    else
358
    {
359
      /* Return 0 if all commands are PING */
360
      for (; argc > 0; argv++, argc--)
361
      {
362
        if (find_type(argv[0], &command_typelib, 2) != ADMIN_PING)
363
        {
364
          error= 1;
365
          break;
366
        }
367
      }
368
    }
369
  }
370
  else
371
  {
372
    while (!interrupted && (!opt_count_iterations || nr_iterations))
373
    {
374
      new_line = 0;
375
      if ((error=execute_commands(&mysql,argc,commands)))
376
      {
377
	if (error > 0)
378
	  break;				/* Wrong command error */
379
	if (!option_force)
380
	{
381
	  if (option_wait && !interrupted)
382
	  {
383
	    mysql_close(&mysql);
384
	    if (!sql_connect(&mysql, option_wait))
385
	    {
386
	      sleep(1);				/* Don't retry too rapidly */
387
	      continue;				/* Retry */
388
	    }
389
	  }
390
	  error=1;
391
	  break;
392
	}
393
      }
394
      if (interval)
395
      {
396
	sleep(interval);
397
	if (new_line)
398
	  puts("");
399
	if (opt_count_iterations)
400
	  nr_iterations--;
401
      }
402
      else
403
	break;
404
    }
405
    mysql_close(&mysql);
406
  }
407
  my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
408
  my_free(user,MYF(MY_ALLOW_ZERO_PTR));
409
#ifdef HAVE_SMEM
410
  my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
411
#endif
412
  free_defaults(save_argv);
413
  my_end(my_end_arg);
414
  exit(error ? 1 : 0);
415
  return 0;
416
}
417
418
419
sig_handler endprog(int signal_number __attribute__((unused)))
420
{
421
  interrupted=1;
422
}
423
424
425
static my_bool sql_connect(MYSQL *mysql, uint wait)
426
{
427
  my_bool info=0;
428
429
  for (;;)
430
  {
431
    if (mysql_real_connect(mysql,host,user,opt_password,NullS,tcp_port,
432
			   unix_port, 0))
433
    {
434
      mysql->reconnect= 1;
435
      if (info)
436
      {
437
	fputs("\n",stderr);
438
	(void) fflush(stderr);
439
      }
440
      return 0;
441
    }
442
443
    if (!wait)
444
    {
445
      if (!option_silent)
446
      {
447
	if (!host)
448
	  host= (char*) LOCAL_HOST;
449
	my_printf_error(0,"connect to server at '%s' failed\nerror: '%s'",
450
			error_flags, host, mysql_error(mysql));
451
	if (mysql_errno(mysql) == CR_CONNECTION_ERROR)
452
	{
453
	  fprintf(stderr,
454
		  "Check that mysqld is running and that the socket: '%s' exists!\n",
455
		  unix_port ? unix_port : mysql_unix_port);
456
	}
457
	else if (mysql_errno(mysql) == CR_CONN_HOST_ERROR ||
458
		 mysql_errno(mysql) == CR_UNKNOWN_HOST)
459
	{
460
	  fprintf(stderr,"Check that mysqld is running on %s",host);
461
	  fprintf(stderr," and that the port is %d.\n",
462
		  tcp_port ? tcp_port: mysql_port);
463
	  fprintf(stderr,"You can check this by doing 'telnet %s %d'\n",
464
		  host, tcp_port ? tcp_port: mysql_port);
465
	}
466
      }
467
      return 1;
468
    }
469
    if (wait != (uint) ~0)
470
      wait--;				/* One less retry */
471
    if ((mysql_errno(mysql) != CR_CONN_HOST_ERROR) &&
472
	(mysql_errno(mysql) != CR_CONNECTION_ERROR))
473
    {
474
      fprintf(stderr,"Got error: %s\n", mysql_error(mysql));
475
      if (!option_force)
476
	return 1;
477
    }
478
    else if (!option_silent)
479
    {
480
      if (!info)
481
      {
482
	info=1;
483
	fputs("Waiting for MySQL server to answer",stderr);
484
	(void) fflush(stderr);
485
      }
486
      else
487
      {
488
	putc('.',stderr);
489
	(void) fflush(stderr);
490
      }
491
    }
492
    sleep(5);
493
  }
494
}
495
496
497
/*
498
  Execute a command.
499
  Return 0 on ok
500
	 -1 on retryable error
501
	 1 on fatal error
502
*/
503
504
static int execute_commands(MYSQL *mysql,int argc, char **argv)
505
{
506
  const char *status;
507
  /*
508
    MySQL documentation relies on the fact that mysqladmin will
509
    execute commands in the order specified, e.g.
510
    mysqladmin -u root flush-privileges password "newpassword"
511
    to reset a lost root password.
512
    If this behaviour is ever changed, Docs should be notified.
513
  */
514
515
  struct rand_struct rand_st;
516
517
  for (; argc > 0 ; argv++,argc--)
518
  {
519
    switch (find_type(argv[0],&command_typelib,2)) {
520
    case ADMIN_CREATE:
521
    {
522
      char buff[FN_REFLEN+20];
523
      if (argc < 2)
524
      {
525
	my_printf_error(0, "Too few arguments to create", error_flags);
526
	return 1;
527
      }
528
      sprintf(buff,"create database `%.*s`",FN_REFLEN,argv[1]);
529
      if (mysql_query(mysql,buff))
530
      {
531
	my_printf_error(0,"CREATE DATABASE failed; error: '%-.200s'",
532
			error_flags, mysql_error(mysql));
533
	return -1;
534
      }
535
      argc--; argv++;
536
      break;
537
    }
538
    case ADMIN_DROP:
539
    {
540
      if (argc < 2)
541
      {
542
	my_printf_error(0, "Too few arguments to drop", error_flags);
543
	return 1;
544
      }
545
      if (drop_db(mysql,argv[1]))
546
	return -1;
547
      argc--; argv++;
548
      break;
549
    }
550
    case ADMIN_SHUTDOWN:
551
    {
552
      char pidfile[FN_REFLEN];
553
      my_bool got_pidfile= 0;
554
      time_t last_modified= 0;
555
      struct stat pidfile_status;
556
557
      /*
558
	Only wait for pidfile on local connections
559
	If pidfile doesn't exist, continue without pid file checking
560
      */
561
      if (mysql->unix_socket && (got_pidfile= !get_pidfile(mysql, pidfile)) &&
562
	  !stat(pidfile, &pidfile_status))
563
	last_modified= pidfile_status.st_mtime;
564
565
      if (mysql_shutdown(mysql, SHUTDOWN_DEFAULT))
566
      {
567
	my_printf_error(0, "shutdown failed; error: '%s'", error_flags,
568
			mysql_error(mysql));
569
	return -1;
570
      }
571
      mysql_close(mysql);	/* Close connection to avoid error messages */
572
      argc=1;                   /* force SHUTDOWN to be the last command    */
573
      if (got_pidfile)
574
      {
575
	if (opt_verbose)
576
	  printf("Shutdown signal sent to server;  Waiting for pid file to disappear\n");
577
578
	/* Wait until pid file is gone */
579
	if (wait_pidfile(pidfile, last_modified, &pidfile_status))
580
	  return -1;
581
      }
582
      break;
583
    }
584
    case ADMIN_FLUSH_PRIVILEGES:
585
    case ADMIN_RELOAD:
586
      if (mysql_query(mysql,"flush privileges"))
587
      {
588
	my_printf_error(0, "reload failed; error: '%s'", error_flags,
589
			mysql_error(mysql));
590
	return -1;
591
      }
592
      break;
593
    case ADMIN_REFRESH:
594
      if (mysql_refresh(mysql,
595
			(uint) ~(REFRESH_GRANT | REFRESH_STATUS |
596
				 REFRESH_READ_LOCK | REFRESH_SLAVE |
597
				 REFRESH_MASTER)))
598
      {
599
	my_printf_error(0, "refresh failed; error: '%s'", error_flags,
600
			mysql_error(mysql));
601
	return -1;
602
      }
603
      break;
604
    case ADMIN_FLUSH_THREADS:
605
      if (mysql_refresh(mysql,(uint) REFRESH_THREADS))
606
      {
607
	my_printf_error(0, "refresh failed; error: '%s'", error_flags,
608
			mysql_error(mysql));
609
	return -1;
610
      }
611
      break;
612
    case ADMIN_VER:
613
      new_line=1;
614
      print_version();
615
      puts("Copyright (C) 2000-2006 MySQL AB");
616
      puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
617
      printf("Server version\t\t%s\n", mysql_get_server_info(mysql));
618
      printf("Protocol version\t%d\n", mysql_get_proto_info(mysql));
619
      printf("Connection\t\t%s\n",mysql_get_host_info(mysql));
620
      if (mysql->unix_socket)
621
	printf("UNIX socket\t\t%s\n", mysql->unix_socket);
622
      else
623
	printf("TCP port\t\t%d\n", mysql->port);
624
      status=mysql_stat(mysql);
625
      {
626
	char *pos,buff[40];
627
	ulong sec;
628
	pos= (char*) strchr(status,' ');
629
	*pos++=0;
630
	printf("%s\t\t\t",status);			/* print label */
631
	if ((status=str2int(pos,10,0,LONG_MAX,(long*) &sec)))
632
	{
633
	  nice_time(sec,buff);
634
	  puts(buff);				/* print nice time */
635
	  while (*status == ' ') status++;	/* to next info */
636
	}
637
      }
638
      putc('\n',stdout);
639
      if (status)
640
	puts(status);
641
      break;
642
    case ADMIN_PROCESSLIST:
643
    {
644
      MYSQL_RES *result;
645
      MYSQL_ROW row;
646
647
      if (mysql_query(mysql, (opt_verbose ? "show full processlist" :
648
			      "show processlist")) ||
649
	  !(result = mysql_store_result(mysql)))
650
      {
651
	my_printf_error(0, "process list failed; error: '%s'", error_flags,
652
			mysql_error(mysql));
653
	return -1;
654
      }
655
      print_header(result);
656
      while ((row=mysql_fetch_row(result)))
657
	print_row(result,row,0);
658
      print_top(result);
659
      mysql_free_result(result);
660
      new_line=1;
661
      break;
662
    }
663
    case ADMIN_STATUS:
664
      status=mysql_stat(mysql);
665
      if (status)
666
	puts(status);
667
      break;
668
    case ADMIN_KILL:
669
      {
670
	uint error=0;
671
	char *pos;
672
	if (argc < 2)
673
	{
674
	  my_printf_error(0, "Too few arguments to 'kill'", error_flags);
675
	  return 1;
676
	}
677
	pos=argv[1];
678
	for (;;)
679
	{
680
	  if (mysql_kill(mysql,(ulong) atol(pos)))
681
	  {
682
	    my_printf_error(0, "kill failed on %ld; error: '%s'", error_flags,
683
			    atol(pos), mysql_error(mysql));
684
	    error=1;
685
	  }
686
	  if (!(pos=strchr(pos,',')))
687
	    break;
688
	  pos++;
689
	}
690
	argc--; argv++;
691
	if (error)
692
	  return -1;
693
	break;
694
      }
695
    case ADMIN_DEBUG:
696
      if (mysql_dump_debug_info(mysql))
697
      {
698
	my_printf_error(0, "debug failed; error: '%s'", error_flags,
699
			mysql_error(mysql));
700
	return -1;
701
      }
702
      break;
703
    case ADMIN_VARIABLES:
704
    {
705
      MYSQL_RES *res;
706
      MYSQL_ROW row;
707
708
      new_line=1;
709
      if (mysql_query(mysql,"show /*!40003 GLOBAL */ variables") ||
710
	  !(res=mysql_store_result(mysql)))
711
      {
712
	my_printf_error(0, "unable to show variables; error: '%s'", error_flags,
713
			mysql_error(mysql));
714
	return -1;
715
      }
716
      print_header(res);
717
      while ((row=mysql_fetch_row(res)))
718
	print_row(res,row,0);
719
      print_top(res);
720
      mysql_free_result(res);
721
      break;
722
    }
723
    case ADMIN_EXTENDED_STATUS:
724
    {
725
      MYSQL_RES *res;
726
      MYSQL_ROW row;
727
      uint rownr = 0;
728
      void (*func) (MYSQL_RES*, MYSQL_ROW, uint);
729
730
      new_line = 1;
731
      if (mysql_query(mysql, "show /*!50002 GLOBAL */ status") ||
732
	  !(res = mysql_store_result(mysql)))
733
      {
734
	my_printf_error(0, "unable to show status; error: '%s'", error_flags,
735
			mysql_error(mysql));
736
	return -1;
737
      }
738
      if (!opt_vertical)
739
	print_header(res);
740
      else
741
      {
742
	if (!ex_status_printed)
743
	{
744
	  store_values(res);
745
	  truncate_names();   /* Does some printing also */
746
	}
747
	else
748
	{
749
	  print_relative_line();
750
	  print_relative_header();
751
	  print_relative_line();
752
	}
753
      }
754
755
      /*      void (*func) (MYSQL_RES*, MYSQL_ROW, uint); */
756
      if (opt_relative && !opt_vertical)
757
	func = print_relative_row;
758
      else if (opt_vertical)
759
	func = print_relative_row_vert;
760
      else
761
	func = print_row;
762
763
      while ((row = mysql_fetch_row(res)))
764
	(*func)(res, row, rownr++);
765
      if (opt_vertical)
766
      {
767
	if (ex_status_printed)
768
	{
769
	  putchar('\n');
770
	  print_relative_line();
771
	}
772
      }
773
      else
774
	print_top(res);
775
776
      ex_status_printed = 1; /* From now on the output will be relative */
777
      mysql_free_result(res);
778
      break;
779
    }
780
    case ADMIN_FLUSH_LOGS:
781
    {
782
      if (mysql_refresh(mysql,REFRESH_LOG))
783
      {
784
	my_printf_error(0, "refresh failed; error: '%s'", error_flags,
785
			mysql_error(mysql));
786
	return -1;
787
      }
788
      break;
789
    }
790
    case ADMIN_FLUSH_HOSTS:
791
    {
792
      if (mysql_query(mysql,"flush hosts"))
793
      {
794
	my_printf_error(0, "refresh failed; error: '%s'", error_flags,
795
			mysql_error(mysql));
796
	return -1;
797
      }
798
      break;
799
    }
800
    case ADMIN_FLUSH_TABLES:
801
    {
802
      if (mysql_query(mysql,"flush tables"))
803
      {
804
	my_printf_error(0, "refresh failed; error: '%s'", error_flags,
805
			mysql_error(mysql));
806
	return -1;
807
      }
808
      break;
809
    }
810
    case ADMIN_FLUSH_STATUS:
811
    {
812
      if (mysql_query(mysql,"flush status"))
813
      {
814
	my_printf_error(0, "refresh failed; error: '%s'", error_flags,
815
			mysql_error(mysql));
816
	return -1;
817
      }
818
      break;
819
    }
820
    case ADMIN_OLD_PASSWORD:
821
    case ADMIN_PASSWORD:
822
    {
823
      char buff[128],crypted_pw[64];
824
      time_t start_time;
825
      /* Do initialization the same way as we do in mysqld */
826
      start_time=time((time_t*) 0);
827
      randominit(&rand_st,(ulong) start_time,(ulong) start_time/2);
828
829
      if (argc < 2)
830
      {
831
	my_printf_error(0, "Too few arguments to change password", error_flags);
832
	return 1;
833
      }
834
      if (argv[1][0])
835
      {
836
        char *pw= argv[1];
837
        bool old= (find_type(argv[0], &command_typelib, 2) ==
838
                   ADMIN_OLD_PASSWORD);
839
        /*
840
           If we don't already know to use an old-style password, see what
841
           the server is using
842
        */
843
        if (!old)
844
        {
845
          if (mysql_query(mysql, "SHOW VARIABLES LIKE 'old_passwords'"))
846
          {
847
            my_printf_error(0, "Could not determine old_passwords setting from server; error: '%s'",
848
                	    error_flags, mysql_error(mysql));
849
            return -1;
850
          }
851
          else
852
          {
853
            MYSQL_RES *res= mysql_store_result(mysql);
854
            if (!res)
855
            {
856
              my_printf_error(0,
857
                              "Could not get old_passwords setting from "
858
                              "server; error: '%s'",
859
        		      error_flags, mysql_error(mysql));
860
              return -1;
861
            }
862
            if (!mysql_num_rows(res))
863
              old= 1;
864
            else
865
            {
866
              MYSQL_ROW row= mysql_fetch_row(res);
867
              old= !strncmp(row[1], "ON", 2);
868
            }
869
            mysql_free_result(res);
870
          }
871
        }
872
        if (old)
873
          make_scrambled_password_323(crypted_pw, pw);
874
        else
875
          make_scrambled_password(crypted_pw, pw);
876
      }
877
      else
878
	crypted_pw[0]=0;			/* No password */
879
      sprintf(buff,"set password='%s',sql_log_off=0",crypted_pw);
880
881
      if (mysql_query(mysql,"set sql_log_off=1"))
882
      {
883
	my_printf_error(0, "Can't turn off logging; error: '%s'",
884
			error_flags, mysql_error(mysql));
885
	return -1;
886
      }
887
      if (mysql_query(mysql,buff))
888
      {
889
	if (mysql_errno(mysql)!=1290)
890
	{
891
	  my_printf_error(0,"unable to change password; error: '%s'",
892
			  error_flags, mysql_error(mysql));
893
	  return -1;
894
	}
895
	else
896
	{
897
	  /*
898
	    We don't try to execute 'update mysql.user set..'
899
	    because we can't perfectly find out the host
900
	   */
901
	  my_printf_error(0,"\n"
902
			  "You cannot use 'password' command as mysqld runs\n"
903
			  " with grant tables disabled (was started with"
904
			  " --skip-grant-tables).\n"
905
			  "Use: \"mysqladmin flush-privileges password '*'\""
906
			  " instead", error_flags);
907
	  return -1;
908
	}
909
      }
910
      argc--; argv++;
911
      break;
912
    }
913
914
    case ADMIN_START_SLAVE:
915
      if (mysql_query(mysql, "START SLAVE"))
916
      {
917
	my_printf_error(0, "Error starting slave: %s", error_flags,
918
			mysql_error(mysql));
919
	return -1;
920
      }
921
      else
922
	puts("Slave started");
923
      break;
924
    case ADMIN_STOP_SLAVE:
925
      if (mysql_query(mysql, "STOP SLAVE"))
926
      {
927
	  my_printf_error(0, "Error stopping slave: %s", error_flags,
928
			  mysql_error(mysql));
929
	  return -1;
930
      }
931
      else
932
	puts("Slave stopped");
933
      break;
934
935
    case ADMIN_PING:
936
      mysql->reconnect=0;	/* We want to know of reconnects */
937
      if (!mysql_ping(mysql))
938
      {
939
	if (option_silent < 2)
940
	  puts("mysqld is alive");
941
      }
942
      else
943
      {
944
	if (mysql_errno(mysql) == CR_SERVER_GONE_ERROR)
945
	{
946
	  mysql->reconnect=1;
947
	  if (!mysql_ping(mysql))
948
	    puts("connection was down, but mysqld is now alive");
949
	}
950
	else
951
	{
952
	  my_printf_error(0,"mysqld doesn't answer to ping, error: '%s'",
953
			  error_flags, mysql_error(mysql));
954
	  return -1;
955
	}
956
      }
957
      mysql->reconnect=1;	/* Automatic reconnect is default */
958
      break;
959
#ifdef LATER_HAVE_NDBCLUSTER_DB
960
    case ADMIN_NDB_MGM:
961
    {
962
      if (argc < 2)
963
      {
964
	my_printf_error(0, "Too few arguments to ndb-mgm", error_flags);
965
	return 1;
966
      }
967
      {
968
        Ndb_mgmclient_handle cmd=
969
	  ndb_mgmclient_handle_create(opt_ndb_connectstring);
970
        ndb_mgmclient_execute(cmd, --argc, ++argv);
971
	ndb_mgmclient_handle_destroy(cmd);
972
      }
973
      argc= 0;
974
    }
975
    break;
976
#endif
977
    default:
978
      my_printf_error(0, "Unknown command: '%-.60s'", error_flags, argv[0]);
979
      return 1;
980
    }
981
  }
982
  return 0;
983
}
984
985
#include <help_start.h>
986
987
static void print_version(void)
988
{
989
  printf("%s  Ver %s Distrib %s, for %s on %s\n",my_progname,ADMIN_VERSION,
990
	 MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
991
}
992
993
994
static void usage(void)
995
{
996
  print_version();
997
  puts("Copyright (C) 2000-2006 MySQL AB");
998
  puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
999
  puts("Administration program for the mysqld daemon.");
1000
  printf("Usage: %s [OPTIONS] command command....\n", my_progname);
1001
  my_print_help(my_long_options);
1002
  my_print_variables(my_long_options);
1003
  print_defaults("my",load_default_groups);
1004
  puts("\nWhere command is a one or more of: (Commands may be shortened)\n\
1005
  create databasename	Create a new database\n\
1006
  debug			Instruct server to write debug information to log\n\
1007
  drop databasename	Delete a database and all its tables\n\
1008
  extended-status       Gives an extended status message from the server\n\
1009
  flush-hosts           Flush all cached hosts\n\
1010
  flush-logs            Flush all logs\n\
1011
  flush-status		Clear status variables\n\
1012
  flush-tables          Flush all tables\n\
1013
  flush-threads         Flush the thread cache\n\
1014
  flush-privileges      Reload grant tables (same as reload)\n\
1015
  kill id,id,...	Kill mysql threads");
1016
#if MYSQL_VERSION_ID >= 32200
1017
  puts("\
1018
  password new-password Change old password to new-password, MySQL 4.1 hashing.\n\
1019
  old-password new-password Change old password to new-password in old format.\n");
1020
#endif
1021
  puts("\
1022
  ping			Check if mysqld is alive\n\
1023
  processlist		Show list of active threads in server\n\
1024
  reload		Reload grant tables\n\
1025
  refresh		Flush all tables and close and open logfiles\n\
1026
  shutdown		Take server down\n\
1027
  status		Gives a short status message from the server\n\
1028
  start-slave		Start slave\n\
1029
  stop-slave		Stop slave\n\
1030
  variables             Prints variables available\n\
1031
  version		Get version info from server");
1032
}
1033
1034
#include <help_end.h>
1035
1036
static int drop_db(MYSQL *mysql, const char *db)
1037
{
1038
  char name_buff[FN_REFLEN+20], buf[10];
1039
  if (!option_force)
1040
  {
1041
    puts("Dropping the database is potentially a very bad thing to do.");
1042
    puts("Any data stored in the database will be destroyed.\n");
1043
    printf("Do you really want to drop the '%s' database [y/N] ",db);
1044
    fflush(stdout);
1045
    VOID(fgets(buf,sizeof(buf)-1,stdin));
1046
    if ((*buf != 'y') && (*buf != 'Y'))
1047
    {
1048
      puts("\nOK, aborting database drop!");
1049
      return -1;
1050
    }
1051
  }
1052
  sprintf(name_buff,"drop database `%.*s`",FN_REFLEN,db);
1053
  if (mysql_query(mysql,name_buff))
1054
  {
1055
    my_printf_error(0, "DROP DATABASE %s failed;\nerror: '%s'", error_flags,
1056
		    db,mysql_error(mysql));
1057
    return 1;
1058
  }
1059
  printf("Database \"%s\" dropped\n",db);
1060
  return 0;
1061
}
1062
1063
1064
static void nice_time(ulong sec,char *buff)
1065
{
1066
  ulong tmp;
1067
1068
  if (sec >= 3600L*24)
1069
  {
1070
    tmp=sec/(3600L*24);
1071
    sec-=3600L*24*tmp;
1072
    buff=int10_to_str(tmp, buff, 10);
1073
    buff=strmov(buff,tmp > 1 ? " days " : " day ");
1074
  }
1075
  if (sec >= 3600L)
1076
  {
1077
    tmp=sec/3600L;
1078
    sec-=3600L*tmp;
1079
    buff=int10_to_str(tmp, buff, 10);
1080
    buff=strmov(buff,tmp > 1 ? " hours " : " hour ");
1081
  }
1082
  if (sec >= 60)
1083
  {
1084
    tmp=sec/60;
1085
    sec-=60*tmp;
1086
    buff=int10_to_str(tmp, buff, 10);
1087
    buff=strmov(buff," min ");
1088
  }
1089
  strmov(int10_to_str(sec, buff, 10)," sec");
1090
}
1091
1092
1093
static void print_header(MYSQL_RES *result)
1094
{
1095
  MYSQL_FIELD *field;
1096
1097
  print_top(result);
1098
  mysql_field_seek(result,0);
1099
  putchar('|');
1100
  while ((field = mysql_fetch_field(result)))
1101
  {
1102
    printf(" %-*s|",(int) field->max_length+1,field->name);
1103
  }
1104
  putchar('\n');
1105
  print_top(result);
1106
}
1107
1108
1109
static void print_top(MYSQL_RES *result)
1110
{
1111
  uint i,length;
1112
  MYSQL_FIELD *field;
1113
1114
  putchar('+');
1115
  mysql_field_seek(result,0);
1116
  while((field = mysql_fetch_field(result)))
1117
  {
1118
    if ((length=(uint) strlen(field->name)) > field->max_length)
1119
      field->max_length=length;
1120
    else
1121
      length=field->max_length;
1122
    for (i=length+2 ; i--> 0 ; )
1123
      putchar('-');
1124
    putchar('+');
1125
  }
1126
  putchar('\n');
1127
}
1128
1129
1130
/* 3.rd argument, uint row, is not in use. Don't remove! */
1131
static void print_row(MYSQL_RES *result, MYSQL_ROW cur,
1132
		      uint row __attribute__((unused)))
1133
{
1134
  uint i,length;
1135
  MYSQL_FIELD *field;
1136
1137
  putchar('|');
1138
  mysql_field_seek(result,0);
1139
  for (i=0 ; i < mysql_num_fields(result); i++)
1140
  {
1141
    field = mysql_fetch_field(result);
1142
    length=field->max_length;
1143
    printf(" %-*s|",length+1,cur[i] ? (char*) cur[i] : "");
1144
  }
1145
  putchar('\n');
1146
}
1147
1148
1149
static void print_relative_row(MYSQL_RES *result, MYSQL_ROW cur, uint row)
1150
{
1151
  ulonglong tmp;
1152
  char buff[22];
1153
  MYSQL_FIELD *field;
1154
1155
  mysql_field_seek(result, 0);
1156
  field = mysql_fetch_field(result);
1157
  printf("| %-*s|", (int) field->max_length + 1, cur[0]);
1158
1159
  field = mysql_fetch_field(result);
1160
  tmp = cur[1] ? strtoull(cur[1], NULL, 10) : (ulonglong) 0;
1161
  printf(" %-*s|\n", (int) field->max_length + 1,
1162
	 llstr((tmp - last_values[row]), buff));
1163
  last_values[row] = tmp;
1164
}
1165
1166
1167
static void print_relative_row_vert(MYSQL_RES *result __attribute__((unused)),
1168
				    MYSQL_ROW cur,
1169
				    uint row __attribute__((unused)))
1170
{
1171
  uint length;
1172
  ulonglong tmp;
1173
  char buff[22];
1174
1175
  if (!row)
1176
    putchar('|');
1177
1178
  tmp = cur[1] ? strtoull(cur[1], NULL, 10) : (ulonglong) 0;
1179
  printf(" %-*s|", ex_val_max_len[row] + 1,
1180
	 llstr((tmp - last_values[row]), buff));
1181
1182
  /* Find the minimum row length needed to output the relative value */
1183
  if ((length=(uint) strlen(buff) > ex_val_max_len[row]) && ex_status_printed)
1184
    ex_val_max_len[row] = length;
1185
  last_values[row] = tmp;
1186
}
1187
1188
1189
static void store_values(MYSQL_RES *result)
1190
{
1191
  uint i;
1192
  MYSQL_ROW row;
1193
  MYSQL_FIELD *field;
1194
1195
  field = mysql_fetch_field(result);
1196
  max_var_length = field->max_length;
1197
  field = mysql_fetch_field(result);
1198
  max_val_length = field->max_length;
1199
1200
  for (i = 0; (row = mysql_fetch_row(result)); i++)
1201
  {
1202
    strmov(ex_var_names[i], row[0]);
1203
    last_values[i]=strtoull(row[1],NULL,10);
1204
    ex_val_max_len[i]=2;		/* Default print width for values */
1205
  }
1206
  ex_var_count = i;
1207
  return;
1208
}
1209
1210
1211
static void print_relative_header()
1212
{
1213
  uint i;
1214
1215
  putchar('|');
1216
  for (i = 0; i < ex_var_count; i++)
1217
    printf(" %-*s|", ex_val_max_len[i] + 1, truncated_var_names[i]);
1218
  putchar('\n');
1219
}
1220
1221
1222
static void print_relative_line()
1223
{
1224
  uint i;
1225
1226
  putchar('+');
1227
  for (i = 0; i < ex_var_count; i++)
1228
  {
1229
    uint j;
1230
    for (j = 0; j < ex_val_max_len[i] + 2; j++)
1231
      putchar('-');
1232
    putchar('+');
1233
  }
1234
  putchar('\n');
1235
}
1236
1237
1238
static void truncate_names()
1239
{
1240
  uint i;
1241
  char *ptr,top_line[MAX_TRUNC_LENGTH+4+NAME_LEN+22+1],buff[22];
1242
1243
  ptr=top_line;
1244
  *ptr++='+';
1245
  ptr=strfill(ptr,max_var_length+2,'-');
1246
  *ptr++='+';
1247
  ptr=strfill(ptr,MAX_TRUNC_LENGTH+2,'-');
1248
  *ptr++='+';
1249
  ptr=strfill(ptr,max_val_length+2,'-');
1250
  *ptr++='+';
1251
  *ptr=0;
1252
  puts(top_line);
1253
1254
  for (i = 0 ; i < ex_var_count; i++)
1255
  {
1256
    uint sfx=1,j;
1257
    printf("| %-*s|", max_var_length + 1, ex_var_names[i]);
1258
    ptr = ex_var_names[i];
1259
    /* Make sure no two same truncated names will become */
1260
    for (j = 0; j < i; j++)
1261
      if (*truncated_var_names[j] == *ptr)
1262
	sfx++;
1263
1264
    truncated_var_names[i][0]= *ptr;		/* Copy first var char */
1265
    int10_to_str(sfx, truncated_var_names[i]+1,10);
1266
    printf(" %-*s|", MAX_TRUNC_LENGTH + 1, truncated_var_names[i]);
1267
    printf(" %-*s|\n", max_val_length + 1, llstr(last_values[i],buff));
1268
  }
1269
  puts(top_line);
1270
  return;
1271
}
1272
1273
1274
static my_bool get_pidfile(MYSQL *mysql, char *pidfile)
1275
{
1276
  MYSQL_RES* result;
1277
1278
  if (mysql_query(mysql, "SHOW VARIABLES LIKE 'pid_file'"))
1279
  {
1280
    my_printf_error(0, "query failed; error: '%s'", error_flags,
1281
		    mysql_error(mysql));
1282
  }
1283
  result = mysql_store_result(mysql);
1284
  if (result)
1285
  {
1286
    MYSQL_ROW row=mysql_fetch_row(result);
1287
    if (row)
1288
      strmov(pidfile, row[1]);
1289
    mysql_free_result(result);
1290
    return row == 0;				/* Error if row = 0 */
1291
  }
1292
  return 1;					/* Error */
1293
}
1294
1295
/*
1296
  Return 1 if pid file didn't disappear or change
1297
*/
1298
1299
static my_bool wait_pidfile(char *pidfile, time_t last_modified,
1300
			    struct stat *pidfile_status)
1301
{
1302
  char buff[FN_REFLEN];
1303
  int error= 1;
1304
  uint count= 0;
1305
  DBUG_ENTER("wait_pidfile");
1306
1307
  system_filename(buff, pidfile);
1308
  do
1309
  {
1310
    int fd;
1311
    if ((fd= my_open(buff, O_RDONLY, MYF(0))) < 0)
1312
    {
1313
      error= 0;
1314
      break;
1315
    }
1316
    (void) my_close(fd,MYF(0));
1317
    if (last_modified && !stat(pidfile, pidfile_status))
1318
    {
1319
      if (last_modified != pidfile_status->st_mtime)
1320
      {
1321
	/* File changed;  Let's assume that mysqld did restart */
1322
	if (opt_verbose)
1323
	  printf("pid file '%s' changed while waiting for it to disappear!\nmysqld did probably restart\n",
1324
		 buff);
1325
	error= 0;
1326
	break;
1327
      }
1328
    }
1329
    if (count++ == opt_shutdown_timeout)
1330
      break;
1331
    sleep(1);
1332
  } while (!interrupted);
1333
1334
  if (error)
1335
  {
1336
    DBUG_PRINT("warning",("Pid file didn't disappear"));
1337
    fprintf(stderr,
1338
	    "Warning;  Aborted waiting on pid file: '%s' after %d seconds\n",
1339
	    buff, count-1);
1340
  }
1341
  DBUG_RETURN(error);
1342
}