~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/mysqladmin.cc

  • Committer: Monty Taylor
  • Date: 2008-07-05 17:09:05 UTC
  • mto: This revision was merged to the branch mainline in revision 63.
  • Revision ID: monty@inaugust.com-20080705170905-itvcfiincapslw9w
Removed redundant declaration.

Show diffs side-by-side

added added

removed removed

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