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