~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/mysqladmin.cc

  • Committer: Monty Taylor
  • Date: 2008-07-02 14:35:48 UTC
  • mto: This revision was merged to the branch mainline in revision 51.
  • Revision ID: monty@inaugust.com-20080702143548-onj30ry0sugr01uw
Removed all references to THREAD.

Show diffs side-by-side

added added

removed removed

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