~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to client/drizzle.cc

MergedĀ inĀ remove-internal-from-drizzle-cc

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
 *
34
34
 **/
35
35
 
36
 
#include "client_priv.h"
 
36
#include "config.h"
 
37
#include <libdrizzle/drizzle_client.h>
 
38
 
 
39
#include "client/get_password.h"
 
40
 
 
41
#if TIME_WITH_SYS_TIME
 
42
# include <sys/time.h>
 
43
# include <time.h>
 
44
#else
 
45
# if HAVE_SYS_TIME_H
 
46
#  include <sys/time.h>
 
47
# else
 
48
#  include <time.h>
 
49
# endif
 
50
#endif
 
51
 
 
52
#include <cerrno>
37
53
#include <string>
38
54
#include <drizzled/gettext.h>
39
55
#include <iostream>
 
56
#include <fstream>
40
57
#include <map>
41
58
#include <algorithm>
42
59
#include <limits.h>
43
60
#include <cassert>
44
 
#include "drizzled/charset_info.h"
45
61
#include <stdarg.h>
46
62
#include <math.h>
47
63
#include "client/linebuffer.h"
48
64
#include <signal.h>
49
65
#include <sys/ioctl.h>
50
66
#include <drizzled/configmake.h>
51
 
#include "drizzled/charset.h"
 
67
#include "drizzled/utf8/utf8.h"
52
68
 
53
69
#if defined(HAVE_CURSES_H) && defined(HAVE_TERM_H)
54
70
#include <curses.h>
139
155
#undef vidattr
140
156
#define vidattr(A) {}      // Can't get this to work
141
157
#endif
 
158
#include <boost/program_options.hpp>
142
159
 
143
 
using namespace drizzled;
144
160
using namespace std;
 
161
namespace po=boost::program_options;
145
162
 
146
163
const string VER("14.14");
147
164
/* Don't try to make a nice table if the data is too big */
149
166
 
150
167
/* Buffer to hold 'version' and 'version_comment' */
151
168
const int MAX_SERVER_VERSION_LENGTH= 128;
 
169
const string PASSWORD_SENTINEL("\0\0\0\0\0", 5);
152
170
 
153
171
#define PROMPT_CHAR '\\'
154
 
#define DEFAULT_DELIMITER ";"
155
172
 
156
173
class Status
157
174
{
260
277
static map<string, string> completion_map;
261
278
static string completion_string;
262
279
 
263
 
static char **defaults_argv;
264
280
 
265
281
enum enum_info_type { INFO_INFO,INFO_ERROR,INFO_RESULT};
266
282
typedef enum enum_info_type INFO_TYPE;
275
291
  vertical= false, line_numbers= true, column_names= true,
276
292
  opt_nopager= true, opt_outfile= false, named_cmds= false,
277
293
  tty_password= false, opt_nobeep= false, opt_reconnect= true,
278
 
  default_charset_used= false, opt_secure_auth= false,
 
294
  opt_secure_auth= false,
279
295
  default_pager_set= false, opt_sigint_ignore= false,
280
296
  auto_vertical_output= false,
281
297
  show_warnings= false, executing_query= false, interrupted_query= false,
282
 
  opt_mysql= false;
283
 
static uint32_t  show_progress_size= 0;
 
298
  opt_mysql= false, opt_local_infile;
 
299
static uint32_t show_progress_size= 0;
284
300
static bool column_types_flag;
285
301
static bool preserve_comments= false;
286
 
static uint32_t opt_max_input_line, opt_drizzle_port= 0;
287
 
static int verbose= 0, opt_silent= 0, opt_local_infile= 0;
 
302
static uint32_t opt_max_input_line;
 
303
static uint32_t opt_drizzle_port= 0;
 
304
static int  opt_silent, verbose= 0;
288
305
static drizzle_capabilities_t connect_flag= DRIZZLE_CAPABILITIES_NONE;
289
 
static char *current_host, *current_db, *current_user= NULL,
290
 
  *opt_password= NULL, *delimiter_str= NULL, *current_prompt= NULL;
291
306
static char *histfile;
292
307
static char *histfile_tmp;
293
308
static string *glob_buffer;
298
313
static uint32_t select_limit;
299
314
static uint32_t max_join_size;
300
315
static uint32_t opt_connect_timeout= 0;
 
316
std::string current_db,
 
317
  delimiter_str,  
 
318
  current_host,
 
319
  current_prompt,
 
320
  current_user,
 
321
  opt_verbose,
 
322
  current_password,
 
323
  opt_password;
301
324
// TODO: Need to i18n these
302
325
static const char *day_names[]= {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
303
326
static const char *month_names[]= {"Jan","Feb","Mar","Apr","May","Jun","Jul",
304
327
                                  "Aug","Sep","Oct","Nov","Dec"};
305
 
static char default_pager[FN_REFLEN];
306
 
static char pager[FN_REFLEN], outfile[FN_REFLEN];
 
328
/* @TODO: Remove this */
 
329
#define FN_REFLEN 512
 
330
 
 
331
static string default_pager("");
 
332
static string pager("");
 
333
static string outfile("");
307
334
static FILE *PAGER, *OUTFILE;
308
335
static uint32_t prompt_counter;
309
 
static char delimiter[16]= DEFAULT_DELIMITER;
 
336
static char *delimiter= NULL;
310
337
static uint32_t delimiter_length= 1;
311
338
unsigned short terminal_width= 80;
312
339
 
313
 
static const CHARSET_INFO *charset_info= &my_charset_utf8_general_ci;
314
 
 
315
340
int drizzleclient_real_query_for_lazy(const char *buf, int length,
316
341
                                      drizzle_result_st *result,
317
342
                                      uint32_t *error_code);
324
349
void tee_putc(int c, FILE *file);
325
350
static void tee_print_sized_data(const char *, unsigned int, unsigned int, bool);
326
351
/* The names of functions that actually do the manipulation. */
327
 
static int get_options(int argc,char **argv);
 
352
static int process_options(void);
328
353
static int com_quit(string *str,const char*),
329
354
  com_go(string *str,const char*), com_ego(string *str,const char*),
330
355
  com_print(string *str,const char*),
338
363
  com_nopager(string *str, const char*), com_pager(string *str, const char*);
339
364
 
340
365
static int read_and_execute(bool interactive);
341
 
static int sql_connect(char *host,char *database,char *user,char *password,
 
366
static int sql_connect(const string &host, const string &database, const string &user, const string &password,
342
367
                       uint32_t silent);
343
368
static const char *server_version_string(drizzle_con_st *con);
344
369
static int put_info(const char *str,INFO_TYPE info,uint32_t error,
1157
1182
  Commands((char *)NULL,       0, 0, 0, "")
1158
1183
};
1159
1184
 
1160
 
static const char *load_default_groups[]= { "drizzle","client",0 };
1161
1185
 
1162
1186
int history_length;
1163
1187
static int not_in_history(const char *line);
1300
1324
  return executed;
1301
1325
}
1302
1326
 
 
1327
static void check_timeout_value(uint32_t in_connect_timeout)
 
1328
{
 
1329
  opt_connect_timeout= 0;
 
1330
  if (in_connect_timeout > 3600*12)
 
1331
  {
 
1332
    cout<<N_("Error: Invalid Value for connect_timeout"); 
 
1333
    exit(-1);
 
1334
  }
 
1335
  opt_connect_timeout= in_connect_timeout;
 
1336
}
 
1337
 
 
1338
static void check_max_input_line(uint32_t in_max_input_line)
 
1339
{
 
1340
  opt_max_input_line= 0;
 
1341
  if (in_max_input_line<4096 || in_max_input_line>(int64_t)2*1024L*1024L*1024L)
 
1342
  {
 
1343
    cout<<N_("Error: Invalid Value for max_input_line");
 
1344
    exit(-1);
 
1345
  }
 
1346
  opt_max_input_line= in_max_input_line/1024;
 
1347
  opt_max_input_line*=1024;
 
1348
}
 
1349
 
 
1350
static pair<string, string> parse_password_arg(std::string s)
 
1351
{
 
1352
  if (s.find("--password") == 0)
 
1353
  {
 
1354
    if (s == "--password")
 
1355
    {
 
1356
      tty_password= true;
 
1357
      //check if no argument is passed.
 
1358
      return make_pair("password", PASSWORD_SENTINEL);
 
1359
    }
 
1360
 
 
1361
    if (s.substr(10,3) == "=\"\"" || s.substr(10,3) == "=''")
 
1362
    {
 
1363
      // Check if --password="" or --password=''
 
1364
      return make_pair("password", PASSWORD_SENTINEL);
 
1365
    }
 
1366
    
 
1367
    if(s.substr(10) == "=" && s.length() == 11)
 
1368
    {
 
1369
      // check if --password= and return a default value
 
1370
      return make_pair("password", PASSWORD_SENTINEL);
 
1371
    }
 
1372
 
 
1373
    if(s.length()>12 && (s[10] == '"' || s[10] == '\''))
 
1374
    {
 
1375
      // check if --password has quotes, remove quotes and return the value
 
1376
      return make_pair("password", s.substr(11,s.length()-1));
 
1377
    }
 
1378
 
 
1379
    // if all above are false, it implies that --password=value, return value.
 
1380
    return make_pair("password", s.substr(11));
 
1381
  }
 
1382
 
 
1383
  else
 
1384
  {
 
1385
    return make_pair(string(""), string(""));
 
1386
  } 
 
1387
}
 
1388
 
1303
1389
int main(int argc,char *argv[])
1304
1390
{
 
1391
try
 
1392
{
1305
1393
#if defined(ENABLE_NLS)
1306
1394
# if defined(HAVE_LOCALE_H)
1307
1395
  setlocale(LC_ALL, "");
1310
1398
  textdomain("drizzle");
1311
1399
#endif
1312
1400
 
1313
 
  MY_INIT(argv[0]);
1314
 
  delimiter_str= delimiter;
 
1401
  po::options_description commandline_options("Options used only in command line");
 
1402
  commandline_options.add_options()
 
1403
  ("help,?",N_("Displays this help and exit."))
 
1404
  ("batch,B",N_("Don't use history file. Disable interactive behavior. (Enables --silent)"))
 
1405
  ("column-type-info", po::value<bool>(&column_types_flag)->default_value(false)->zero_tokens(),
 
1406
  N_("Display column type information."))
 
1407
  ("comments,c", po::value<bool>(&preserve_comments)->default_value(false)->zero_tokens(),
 
1408
  N_("Preserve comments. Send comments to the server. The default is --skip-comments (discard comments), enable with --comments"))
 
1409
  ("compress,C", po::value<bool>(&opt_compress)->default_value(false)->zero_tokens(),
 
1410
  N_("Use compression in server/client protocol."))  
 
1411
  ("vertical,E", po::value<bool>(&vertical)->default_value(false)->zero_tokens(),
 
1412
  N_("Print the output of a query (rows) vertically."))
 
1413
  ("force,f", po::value<bool>(&ignore_errors)->default_value(false)->zero_tokens(),
 
1414
  N_("Continue even if we get an sql error."))
 
1415
  ("named-commands,G", po::value<bool>(&named_cmds)->default_value(false)->zero_tokens(),
 
1416
  N_("Enable named commands. Named commands mean this program's internal commands; see drizzle> help . When enabled, the named commands can be used from any line of the query, otherwise only from the first line, before an enter. Disable with --disable-named-commands. This option is disabled by default."))
 
1417
  ("no-named-commands,g",
 
1418
  N_("Named commands are disabled. Use \\* form only, or use named commands only in the beginning of a line ending with a semicolon (;) Since version 10.9 the client now starts with this option ENABLED by default! Disable with '-G'. Long format commands still work from the first line. WARNING: option deprecated; use --disable-named-commands instead."))
 
1419
  ("ignore-spaces,i", N_("Ignore space after function names."))
 
1420
  ("no-beep,b", po::value<bool>(&opt_nobeep)->default_value(false)->zero_tokens(),
 
1421
  N_("Turn off beep on error."))
 
1422
  ("line-numbers", po::value<bool>(&line_numbers)->default_value(true)->zero_tokens(),
 
1423
  N_("Write line numbers for errors."))
 
1424
  ("skip-line-numbers,L", 
 
1425
  N_("Don't write line number for errors. WARNING: -L is deprecated, use long version of this option instead."))
 
1426
  ("column-name", po::value<bool>(&column_names)->default_value(true)->zero_tokens(),
 
1427
  N_("Write column names in results."))
 
1428
  ("skip-column-names,N", 
 
1429
  N_("Don't write column names in results. WARNING: -N is deprecated, use long version of this options instead."))
 
1430
  ("set-variable,O", po::value<string>(),
 
1431
  N_("Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value."))
 
1432
  ("table,t", po::value<bool>(&output_tables)->default_value(false)->zero_tokens(),
 
1433
  N_("Output in table format.")) 
 
1434
  ("safe-updates,U", po::value<bool>(&safe_updates)->default_value(0)->zero_tokens(),
 
1435
  N_("Only allow UPDATE and DELETE that uses keys."))
 
1436
  ("i-am-a-dummy,U", po::value<bool>(&safe_updates)->default_value(0)->zero_tokens(),
 
1437
  N_("Synonym for option --safe-updates, -U."))
 
1438
  ("verbose,v", po::value<string>(&opt_verbose)->default_value(""),
 
1439
  N_("-v vvv implies that verbose= 3, Used to specify verbose"))
 
1440
  ("version,V", N_("Output version information and exit."))
 
1441
  ("secure-auth", po::value<bool>(&opt_secure_auth)->default_value(false)->zero_tokens(),
 
1442
  N_("Refuse client connecting to server if it uses old (pre-4.1.1) protocol"))
 
1443
  ("show-warnings", po::value<bool>(&show_warnings)->default_value(false)->zero_tokens(),
 
1444
  N_("Show warnings after every statement."))
 
1445
  ("show-progress-size", po::value<uint32_t>(&show_progress_size)->default_value(0),
 
1446
  N_("Number of lines before each import progress report."))
 
1447
  ("ping", po::value<bool>(&opt_ping)->default_value(false)->zero_tokens(),
 
1448
  N_("Ping the server to check if it's alive."))
 
1449
  ("no-defaults", po::value<bool>()->default_value(false)->zero_tokens(),
 
1450
  N_("Configuration file defaults are not used if no-defaults is set"))
 
1451
  ;
 
1452
 
 
1453
  po::options_description drizzle_options("Options specific to the drizzle client");
 
1454
  drizzle_options.add_options()
 
1455
  ("auto-rehash", po::value<bool>(&opt_rehash)->default_value(true)->zero_tokens(),
 
1456
  N_("Enable automatic rehashing. One doesn't need to use 'rehash' to get table and field completion, but startup and reconnecting may take a longer time. Disable with --disable-auto-rehash."))
 
1457
  ("no-auto-rehash,A",N_("No automatic rehashing. One has to use 'rehash' to get table and field completion. This gives a quicker start of drizzle_st and disables rehashing on reconnect. WARNING: options deprecated; use --disable-auto-rehash instead."))
 
1458
  ("auto-vertical-output", po::value<bool>(&auto_vertical_output)->default_value(false)->zero_tokens(),
 
1459
  N_("Automatically switch to vertical output mode if the result is wider than the terminal width."))
 
1460
  ("database,D", po::value<string>(&current_db)->default_value(""),
 
1461
  N_("Database to use."))
 
1462
  ("default-character-set",po::value<string>(),
 
1463
  N_("(not used)"))
 
1464
  ("delimiter", po::value<string>(&delimiter_str)->default_value(";"),
 
1465
  N_("Delimiter to be used."))
 
1466
  ("execute,e", po::value<string>(),
 
1467
  N_("Execute command and quit. (Disables --force and history file)"))
 
1468
  ("local-infile", po::value<bool>(&opt_local_infile)->default_value(false)->zero_tokens(),
 
1469
  N_("Enable/disable LOAD DATA LOCAL INFILE."))
 
1470
  ("unbuffered,n", po::value<bool>(&unbuffered)->default_value(false)->zero_tokens(),
 
1471
  N_("Flush buffer after each query."))
 
1472
  ("sigint-ignore", po::value<bool>(&opt_sigint_ignore)->default_value(false)->zero_tokens(),
 
1473
  N_("Ignore SIGINT (CTRL-C)"))
 
1474
  ("one-database,o", po::value<bool>(&one_database)->default_value(false)->zero_tokens(),
 
1475
  N_("Only update the default database. This is useful for skipping updates to other database in the update log."))
 
1476
  ("pager", po::value<string>(),
 
1477
  N_("Pager to use to display results. If you don't supply an option the default pager is taken from your ENV variable PAGER. Valid pagers are less, more, cat [> filename], etc. See interactive help (\\h) also. This option does not work in batch mode. Disable with --disable-pager. This option is disabled by default."))
 
1478
  ("disable-pager", po::value<bool>(&opt_nopager)->default_value(false)->zero_tokens(),
 
1479
  N_("Disable pager and print to stdout. See interactive help (\\h) also."))
 
1480
  ("prompt", po::value<string>(&current_prompt)->default_value(""),  
 
1481
  N_("Set the drizzle prompt to this value."))
 
1482
  ("quick,q", po::value<bool>(&quick)->default_value(false)->zero_tokens(),
 
1483
  N_("Don't cache result, print it row by row. This may slow down the server if the output is suspended. Doesn't use history file."))
 
1484
  ("raw,r", po::value<bool>(&opt_raw_data)->default_value(false)->zero_tokens(),
 
1485
  N_("Write fields without conversion. Used with --batch.")) 
 
1486
  ("reconnect", po::value<bool>(&opt_reconnect)->default_value(true)->zero_tokens(),
 
1487
  N_("Reconnect if the connection is lost. Disable with --disable-reconnect. This option is enabled by default."))
 
1488
  ("shutdown", po::value<bool>(&opt_shutdown)->default_value(false)->zero_tokens(),
 
1489
  N_("Shutdown the server"))
 
1490
  ("silent,s", N_("Be more silent. Print results with a tab as separator, each row on new line."))
 
1491
  ("tee", po::value<string>(),
 
1492
  N_("Append everything into outfile. See interactive help (\\h) also. Does not work in batch mode. Disable with --disable-tee. This option is disabled by default."))
 
1493
  ("disable-tee", po::value<bool>()->default_value(false)->zero_tokens(), 
 
1494
  N_("Disable outfile. See interactive help (\\h) also."))
 
1495
  ("wait,w", N_("Wait and retry if connection is down."))
 
1496
  ("connect_timeout", po::value<uint32_t>(&opt_connect_timeout)->default_value(0)->notifier(&check_timeout_value),
 
1497
  N_("Number of seconds before connection timeout."))
 
1498
  ("max_input_line", po::value<uint32_t>(&opt_max_input_line)->default_value(16*1024L*1024L)->notifier(&check_max_input_line),
 
1499
  N_("Max length of input line"))
 
1500
  ("select_limit", po::value<uint32_t>(&select_limit)->default_value(1000L),
 
1501
  N_("Automatic limit for SELECT when using --safe-updates"))
 
1502
  ("max_join_size", po::value<uint32_t>(&max_join_size)->default_value(1000000L),
 
1503
  N_("Automatic limit for rows in a join when using --safe-updates"))
 
1504
  ;
 
1505
 
 
1506
  po::options_description client_options("Options specific to the client");
 
1507
  client_options.add_options()
 
1508
  ("mysql,m", po::value<bool>(&opt_mysql)->default_value(true)->zero_tokens(),
 
1509
  N_("Use MySQL Protocol."))
 
1510
  ("host,h", po::value<string>(&current_host)->default_value("localhost"),
 
1511
  N_("Connect to host"))
 
1512
  ("password,P", po::value<string>(&current_password)->default_value(PASSWORD_SENTINEL),
 
1513
  N_("Password to use when connecting to server. If password is not given it's asked from the tty."))
 
1514
  ("port,p", po::value<uint32_t>()->default_value(0),
 
1515
  N_("Port number to use for connection or 0 for default to, in order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, built-in default"))
 
1516
  ("user,u", po::value<string>(&current_user)->default_value(""),
 
1517
  N_("User for login if not current user."))
 
1518
  ("protocol",po::value<string>(),
 
1519
  N_("The protocol of connection (tcp,socket,pipe,memory)."))
 
1520
  ;
 
1521
 
 
1522
  po::options_description long_options("Allowed Options");
 
1523
  long_options.add(commandline_options).add(drizzle_options).add(client_options);
 
1524
 
 
1525
  std::string system_config_dir_drizzle(SYSCONFDIR); 
 
1526
  system_config_dir_drizzle.append("/drizzle/drizzle.cnf");
 
1527
 
 
1528
  std::string system_config_dir_client(SYSCONFDIR); 
 
1529
  system_config_dir_client.append("/drizzle/client.cnf");
 
1530
 
 
1531
  po::variables_map vm;
 
1532
 
 
1533
  po::positional_options_description p;
 
1534
  p.add("database", -1);
 
1535
 
 
1536
  po::store(po::command_line_parser(argc, argv).options(long_options).
 
1537
            positional(p).extra_parser(parse_password_arg).run(), vm);
 
1538
 
 
1539
  if (! vm["no-defaults"].as<bool>())
 
1540
  {
 
1541
    ifstream user_drizzle_ifs("~/.drizzle/drizzle.cnf");
 
1542
    po::store(parse_config_file(user_drizzle_ifs, drizzle_options), vm);
 
1543
 
 
1544
    ifstream system_drizzle_ifs(system_config_dir_drizzle.c_str());
 
1545
    store(parse_config_file(system_drizzle_ifs, drizzle_options), vm);
 
1546
 
 
1547
    ifstream user_client_ifs("~/.drizzle/client.cnf");
 
1548
    po::store(parse_config_file(user_client_ifs, client_options), vm);
 
1549
 
 
1550
    ifstream system_client_ifs(system_config_dir_client.c_str());
 
1551
    po::store(parse_config_file(system_client_ifs, client_options), vm);
 
1552
  }
 
1553
 
 
1554
  po::notify(vm);
 
1555
 
1315
1556
  default_prompt= strdup(getenv("DRIZZLE_PS1") ?
1316
1557
                         getenv("DRIZZLE_PS1") :
1317
1558
                         "drizzle> ");
1318
 
  
1319
1559
  if (default_prompt == NULL)
1320
1560
  {
1321
1561
    fprintf(stderr, _("Memory allocation error while constructing initial "
1323
1563
    exit(ENOMEM);
1324
1564
  }
1325
1565
  current_prompt= strdup(default_prompt);
1326
 
  if (current_prompt == NULL)
 
1566
  if (current_prompt.empty())
1327
1567
  {
1328
1568
    fprintf(stderr, _("Memory allocation error while constructing initial "
1329
1569
                      "prompt. Aborting.\n"));
1334
1574
 
1335
1575
  prompt_counter=0;
1336
1576
 
1337
 
  outfile[0]=0;      // no (default) outfile
1338
 
  strcpy(pager, "stdout");  // the default, if --pager wasn't given
 
1577
  outfile.clear();      // no (default) outfile
 
1578
  pager.assign("stdout");  // the default, if --pager wasn't given
1339
1579
  {
1340
 
    char *tmp=getenv("PAGER");
 
1580
    const char *tmp= getenv("PAGER");
1341
1581
    if (tmp && strlen(tmp))
1342
1582
    {
1343
1583
      default_pager_set= 1;
1344
 
      strcpy(default_pager, tmp);
 
1584
      default_pager.assign(tmp);
1345
1585
    }
1346
1586
  }
1347
 
  if (!isatty(0) || !isatty(1))
 
1587
  if (! isatty(0) || ! isatty(1))
1348
1588
  {
1349
1589
    status.setBatch(1); opt_silent=1;
1350
1590
    ignore_errors=0;
1367
1607
      close(stdout_fileno_copy);             /* Clean up dup(). */
1368
1608
  }
1369
1609
 
1370
 
  internal::load_defaults("drizzle",load_default_groups,&argc,&argv);
1371
 
  defaults_argv=argv;
1372
 
  if (get_options(argc, (char **) argv))
1373
 
  {
1374
 
    internal::free_defaults(defaults_argv);
1375
 
    internal::my_end();
 
1610
  if (vm.count("delimiter"))
 
1611
  {
 
1612
    /* Check that delimiter does not contain a backslash */
 
1613
    if (! strstr(delimiter_str.c_str(), "\\"))
 
1614
    {
 
1615
      delimiter= (char *)delimiter_str.c_str();  
 
1616
    }
 
1617
    else
 
1618
    {
 
1619
      put_info(_("DELIMITER cannot contain a backslash character"),
 
1620
      INFO_ERROR,0,0);
 
1621
      exit(-1);
 
1622
    }
 
1623
   
 
1624
    delimiter_length= (uint32_t)strlen(delimiter);
 
1625
  }
 
1626
  if (vm.count("tee"))
 
1627
  { 
 
1628
    if (vm["tee"].as<string>().empty())
 
1629
    {
 
1630
      if (opt_outfile)
 
1631
        end_tee();
 
1632
    }
 
1633
    else
 
1634
      init_tee(vm["tee"].as<string>().c_str());
 
1635
  }
 
1636
  if (vm["disable-tee"].as<bool>() == true)
 
1637
  {
 
1638
    if (opt_outfile)
 
1639
      end_tee();
 
1640
  }
 
1641
  if (vm.count("pager"))
 
1642
  {
 
1643
    if (vm["pager"].as<string>().empty())
 
1644
      opt_nopager= 1;
 
1645
    else
 
1646
    {
 
1647
      opt_nopager= 0;
 
1648
      if (vm[pager].as<string>().length())
 
1649
      {
 
1650
        default_pager_set= 1;
 
1651
        pager.assign(vm["pager"].as<string>());
 
1652
        default_pager.assign(pager);
 
1653
      }
 
1654
      else if (default_pager_set)
 
1655
        pager.assign(default_pager);
 
1656
      else
 
1657
        opt_nopager= 1;
 
1658
    }
 
1659
  }
 
1660
  if (vm.count("disable-pager"))
 
1661
  {
 
1662
    opt_nopager= 1;
 
1663
  }
 
1664
 
 
1665
  if (vm.count("no-auto-rehash"))
 
1666
    opt_rehash= 0;
 
1667
 
 
1668
  if (vm.count("skip-column-names"))
 
1669
    column_names= 0;
 
1670
    
 
1671
  if (vm.count("execute"))
 
1672
  {  
 
1673
    status.setBatch(1);
 
1674
    status.setAddToHistory(1);
 
1675
    if (status.getLineBuff() == NULL)
 
1676
      status.setLineBuff(opt_max_input_line,NULL);
 
1677
    if (status.getLineBuff() == NULL)
 
1678
    {
 
1679
      exit(1);
 
1680
    }
 
1681
    status.getLineBuff()->addString(vm["execute"].as<string>().c_str());
 
1682
  }
 
1683
 
 
1684
  if (one_database)
 
1685
    skip_updates= true;
 
1686
  
 
1687
  if (vm.count("port"))
 
1688
  {
 
1689
    opt_drizzle_port= vm["port"].as<uint32_t>();
 
1690
 
 
1691
    /* If the port number is > 65535 it is not a valid port
 
1692
       This also helps with potential data loss casting unsigned long to a
 
1693
       uint32_t. */
 
1694
    if (opt_drizzle_port > 65535)
 
1695
    {
 
1696
      printf(_("Error: Value of %" PRIu32 " supplied for port is not valid.\n"), opt_drizzle_port);
 
1697
      exit(-1);
 
1698
    }
 
1699
  }
 
1700
 
 
1701
  if (vm.count("password"))
 
1702
  {
 
1703
    if (!opt_password.empty())
 
1704
      opt_password.erase();
 
1705
    if (current_password == PASSWORD_SENTINEL)
 
1706
    {
 
1707
      opt_password= "";
 
1708
    }
 
1709
    else
 
1710
    {
 
1711
      opt_password= current_password;
 
1712
      tty_password= false;
 
1713
    }
 
1714
    char *start= (char *)current_password.c_str();
 
1715
    char *temp_pass= (char *)current_password.c_str();
 
1716
    while (*temp_pass)
 
1717
    {
 
1718
        /* Overwriting password with 'x' */
 
1719
        *temp_pass++= 'x';
 
1720
    }
 
1721
    if (*start)
 
1722
    {
 
1723
      start[1]= 0;
 
1724
    }
 
1725
  }
 
1726
  else
 
1727
  {
 
1728
      tty_password= true;
 
1729
  }
 
1730
  
 
1731
 
 
1732
  if (!opt_verbose.empty())
 
1733
  {
 
1734
    verbose= opt_verbose.length();
 
1735
  }
 
1736
 
 
1737
  if (vm.count("batch"))
 
1738
  {
 
1739
    status.setBatch(1);
 
1740
    status.setAddToHistory(0);
 
1741
    if (opt_silent < 1)
 
1742
    {
 
1743
      opt_silent= 1;
 
1744
    }
 
1745
  }
 
1746
  if (vm.count("silent"))
 
1747
  {
 
1748
    opt_silent++;
 
1749
  }
 
1750
  if (vm.count("version"))
 
1751
  {
 
1752
    printf(_("drizzle  Ver %s Distrib %s, for %s-%s (%s) using readline %s\n"),
 
1753
           VER.c_str(), drizzle_version(),
 
1754
           HOST_VENDOR, HOST_OS, HOST_CPU,
 
1755
           rl_library_version);
 
1756
 
 
1757
    exit(0);
 
1758
  }
 
1759
  
 
1760
  if (vm.count("help"))
 
1761
  {
 
1762
    printf(_("drizzle  Ver %s Distrib %s, for %s-%s (%s) using readline %s\n"),
 
1763
           VER.c_str(), drizzle_version(),
 
1764
           HOST_VENDOR, HOST_OS, HOST_CPU,
 
1765
           rl_library_version);
 
1766
    printf(_("Copyright (C) 2008 Sun Microsystems\n"
 
1767
           "This software comes with ABSOLUTELY NO WARRANTY. "
 
1768
           "This is free software,\n"
 
1769
           "and you are welcome to modify and redistribute it "
 
1770
           "under the GPL license\n"));
 
1771
    printf(_("Usage: drizzle [OPTIONS] [database]\n"));
 
1772
    cout<<long_options;
 
1773
    exit(0);
 
1774
  }
 
1775
 
 
1776
 
 
1777
  if (process_options())
 
1778
  {
1376
1779
    exit(1);
1377
1780
  }
1378
1781
 
 
1782
  if (argc == 1)
 
1783
  {
 
1784
    skip_updates= 0;
 
1785
    current_db.erase();
 
1786
    current_db= strdup(*argv);
 
1787
  }
1379
1788
  memset(&drizzle, 0, sizeof(drizzle));
1380
 
  if (sql_connect(current_host,current_db,current_user,opt_password,
1381
 
                  opt_silent))
 
1789
  if (sql_connect(current_host, current_db, current_user, opt_password,opt_silent))
1382
1790
  {
1383
1791
    quick= 1;          // Avoid history
1384
1792
    status.setExitStatus(1);
1389
1797
  if (execute_commands(&command_error) != false)
1390
1798
  {
1391
1799
    /* we've executed a command so exit before we go into readline mode */
1392
 
    internal::free_defaults(defaults_argv);
1393
 
    internal::my_end();
1394
1800
    exit(command_error);
1395
1801
  }
1396
1802
 
1399
1805
    status.setLineBuff(opt_max_input_line, stdin);
1400
1806
    if (status.getLineBuff() == NULL)
1401
1807
    {
1402
 
      internal::free_defaults(defaults_argv);
1403
 
      internal::my_end();
1404
1808
      exit(1);
1405
1809
    }
1406
1810
  }
1436
1840
          server_version_string(&con));
1437
1841
  put_info(output_buff, INFO_INFO, 0, 0);
1438
1842
 
1439
 
  initialize_readline(current_prompt);
 
1843
  initialize_readline((char *)current_prompt.c_str());
1440
1844
  if (!status.getBatch() && !quick)
1441
1845
  {
1442
1846
    /* read-history from file, default ~/.drizzle_history*/
1480
1884
  if (opt_outfile)
1481
1885
    end_tee();
1482
1886
  drizzle_end(0);
 
1887
}
1483
1888
 
 
1889
  catch(exception &err)
 
1890
  {
 
1891
  cerr<<"Error:"<<err.what()<<endl;
 
1892
  }
1484
1893
  return(0);        // Keep compiler happy
1485
1894
}
1486
1895
 
1494
1903
    if (verbose)
1495
1904
      tee_fprintf(stdout, _("Writing history-file %s\n"),histfile);
1496
1905
    if (!write_history(histfile_tmp))
1497
 
      internal::my_rename(histfile_tmp, histfile, MYF(MY_WME));
 
1906
      rename(histfile_tmp, histfile);
1498
1907
  }
1499
1908
  delete status.getLineBuff();
1500
1909
  status.setLineBuff(0);
1505
1914
    delete glob_buffer;
1506
1915
  if (processed_prompt)
1507
1916
    delete processed_prompt;
1508
 
  free(opt_password);
 
1917
  opt_password.erase();
1509
1918
  free(histfile);
1510
1919
  free(histfile_tmp);
1511
 
  free(current_db);
1512
 
  free(current_host);
1513
 
  free(current_user);
 
1920
  current_db.erase();
 
1921
  current_host.erase();
 
1922
  current_user.erase();
1514
1923
  free(full_username);
1515
1924
  free(part_username);
1516
1925
  free(default_prompt);
1517
 
  free(current_prompt);
1518
 
  internal::free_defaults(defaults_argv);
1519
 
  internal::my_end();
 
1926
  current_prompt.erase();
1520
1927
  exit(status.getExitStatus());
1521
1928
}
1522
1929
 
1539
1946
    goto err;
1540
1947
  }
1541
1948
 
1542
 
  if (drizzle_con_add_tcp(&drizzle, &kill_drizzle, current_host,
1543
 
                          opt_drizzle_port, current_user, opt_password, NULL,
 
1949
  if (drizzle_con_add_tcp(&drizzle, &kill_drizzle, current_host.c_str(),
 
1950
                          opt_drizzle_port, current_user.c_str(), opt_password.c_str(), NULL,
1544
1951
                          opt_mysql ? DRIZZLE_CON_MYSQL : DRIZZLE_CON_NONE) == NULL)
1545
1952
  {
1546
1953
    goto err;
1575
1982
}
1576
1983
#endif
1577
1984
 
1578
 
static struct option my_long_options[] =
1579
 
{
1580
 
  {"help", '?', N_("Display this help and exit."), 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
1581
 
   0, 0, 0, 0, 0},
1582
 
  {"help", 'I', N_("Synonym for -?"), 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
1583
 
   0, 0, 0, 0, 0},
1584
 
  {"auto-rehash", OPT_AUTO_REHASH,
1585
 
   N_("Enable automatic rehashing. One doesn't need to use 'rehash' to get table and field completion, but startup and reconnecting may take a longer time. Disable with --disable-auto-rehash."),
1586
 
   (char**) &opt_rehash, (char**) &opt_rehash, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
1587
 
   0, 0},
1588
 
  {"no-auto-rehash", 'A',
1589
 
   N_("No automatic rehashing. One has to use 'rehash' to get table and field completion. This gives a quicker start of drizzle_st and disables rehashing on reconnect. WARNING: options deprecated; use --disable-auto-rehash instead."),
1590
 
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1591
 
  {"auto-vertical-output", OPT_AUTO_VERTICAL_OUTPUT,
1592
 
   N_("Automatically switch to vertical output mode if the result is wider than the terminal width."),
1593
 
   (char**) &auto_vertical_output, (char**) &auto_vertical_output, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1594
 
  {"batch", 'B',
1595
 
   N_("Don't use history file. Disable interactive behavior. (Enables --silent)"), 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1596
 
  {"column-type-info", OPT_COLUMN_TYPES, N_("Display column type information."),
1597
 
   (char**) &column_types_flag, (char**) &column_types_flag,
1598
 
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1599
 
  {"comments", 'c', N_("Preserve comments. Send comments to the server. The default is --skip-comments (discard comments), enable with --comments"),
1600
 
   (char**) &preserve_comments, (char**) &preserve_comments,
1601
 
   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1602
 
  {"compress", 'C', N_("Use compression in server/client protocol."),
1603
 
   (char**) &opt_compress, (char**) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
1604
 
   0, 0, 0},
1605
 
  {"database", 'D', N_("Database to use."), (char**) &current_db,
1606
 
   (char**) &current_db, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1607
 
  {"default-character-set", OPT_DEFAULT_CHARSET,
1608
 
   N_("(not used)"), 0,
1609
 
   0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1610
 
  {"delimiter", OPT_DELIMITER, N_("Delimiter to be used."), (char**) &delimiter_str,
1611
 
   (char**) &delimiter_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1612
 
  {"execute", 'e', N_("Execute command and quit. (Disables --force and history file)"), 0,
1613
 
   0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1614
 
  {"vertical", 'E', N_("Print the output of a query (rows) vertically."),
1615
 
   (char**) &vertical, (char**) &vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
1616
 
   0},
1617
 
  {"force", 'f', N_("Continue even if we get an sql error."),
1618
 
   (char**) &ignore_errors, (char**) &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
1619
 
   0, 0, 0, 0},
1620
 
  {"named-commands", 'G',
1621
 
   N_("Enable named commands. Named commands mean this program's internal commands; see drizzle> help . When enabled, the named commands can be used from any line of the query, otherwise only from the first line, before an enter. Disable with --disable-named-commands. This option is disabled by default."),
1622
 
   (char**) &named_cmds, (char**) &named_cmds, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1623
 
   0, 0},
1624
 
  {"no-named-commands", 'g',
1625
 
   N_("Named commands are disabled. Use \\* form only, or use named commands only in the beginning of a line ending with a semicolon (;) Since version 10.9 the client now starts with this option ENABLED by default! Disable with '-G'. Long format commands still work from the first line. WARNING: option deprecated; use --disable-named-commands instead."),
1626
 
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1627
 
  {"ignore-spaces", 'i', N_("Ignore space after function names."), 0, 0, 0,
1628
 
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1629
 
  {"local-infile", OPT_LOCAL_INFILE, N_("Enable/disable LOAD DATA LOCAL INFILE."),
1630
 
   (char**) &opt_local_infile,
1631
 
   (char**) &opt_local_infile, 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
1632
 
  {"no-beep", 'b', N_("Turn off beep on error."), (char**) &opt_nobeep,
1633
 
   (char**) &opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1634
 
  {"host", 'h', N_("Connect to host."), (char**) &current_host,
1635
 
   (char**) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1636
 
  {"line-numbers", OPT_LINE_NUMBERS, N_("Write line numbers for errors."),
1637
 
   (char**) &line_numbers, (char**) &line_numbers, 0, GET_BOOL,
1638
 
   NO_ARG, 1, 0, 0, 0, 0, 0},
1639
 
  {"skip-line-numbers", 'L', N_("Don't write line number for errors. WARNING: -L is deprecated, use long version of this option instead."), 0, 0, 0, GET_NO_ARG,
1640
 
   NO_ARG, 0, 0, 0, 0, 0, 0},
1641
 
  {"unbuffered", 'n', N_("Flush buffer after each query."), (char**) &unbuffered,
1642
 
   (char**) &unbuffered, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1643
 
  {"column-names", OPT_COLUMN_NAMES, N_("Write column names in results."),
1644
 
   (char**) &column_names, (char**) &column_names, 0, GET_BOOL,
1645
 
   NO_ARG, 1, 0, 0, 0, 0, 0},
1646
 
  {"skip-column-names", 'N',
1647
 
   N_("Don't write column names in results. WARNING: -N is deprecated, use long version of this options instead."),
1648
 
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1649
 
  {"set-variable", 'O',
1650
 
   N_("Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value."),
1651
 
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1652
 
  {"sigint-ignore", OPT_SIGINT_IGNORE, N_("Ignore SIGINT (CTRL-C)"),
1653
 
   (char**) &opt_sigint_ignore,  (char**) &opt_sigint_ignore, 0, GET_BOOL,
1654
 
   NO_ARG, 0, 0, 0, 0, 0, 0},
1655
 
  {"one-database", 'o',
1656
 
   N_("Only update the default database. This is useful for skipping updates to other database in the update log."),
1657
 
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1658
 
  {"pager", OPT_PAGER,
1659
 
   N_("Pager to use to display results. If you don't supply an option the default pager is taken from your ENV variable PAGER. Valid pagers are less, more, cat [> filename], etc. See interactive help (\\h) also. This option does not work in batch mode. Disable with --disable-pager. This option is disabled by default."),
1660
 
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1661
 
  {"no-pager", OPT_NOPAGER,
1662
 
   N_("Disable pager and print to stdout. See interactive help (\\h) also. WARNING: option deprecated; use --disable-pager instead."),
1663
 
   0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1664
 
  {"password", 'P',
1665
 
   N_("Password to use when connecting to server. If password is not given it's asked from the tty."),
1666
 
   0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1667
 
  {"port", 'p', N_("Port number to use for connection or 0 for default to, in order of preference, drizzle.cnf, $DRIZZLE_TCP_PORT, ")
1668
 
   N_("built-in default") " (" STRINGIFY_ARG(DRIZZLE_PORT) ").",
1669
 
   0, 0, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1670
 
  {"prompt", OPT_PROMPT, N_("Set the drizzle prompt to this value."),
1671
 
   (char**) &current_prompt, (char**) &current_prompt, 0, GET_STR_ALLOC,
1672
 
   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1673
 
  {"quick", 'q',
1674
 
   N_("Don't cache result, print it row by row. This may slow down the server if the output is suspended. Doesn't use history file."),
1675
 
   (char**) &quick, (char**) &quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1676
 
  {"raw", 'r', N_("Write fields without conversion. Used with --batch."),
1677
 
   (char**) &opt_raw_data, (char**) &opt_raw_data, 0, GET_BOOL, NO_ARG, 0, 0, 0,
1678
 
   0, 0, 0},
1679
 
  {"reconnect", OPT_RECONNECT, N_("Reconnect if the connection is lost. Disable with --disable-reconnect. This option is enabled by default."),
1680
 
   (char**) &opt_reconnect, (char**) &opt_reconnect, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
1681
 
  {"shutdown", OPT_SHUTDOWN, N_("Shutdown the server."),
1682
 
   (char**) &opt_shutdown, (char**) &opt_shutdown, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1683
 
  {"silent", 's', N_("Be more silent. Print results with a tab as separator, each row on new line."), 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0,
1684
 
   0, 0},
1685
 
  {"table", 't', N_("Output in table format."), (char**) &output_tables,
1686
 
   (char**) &output_tables, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1687
 
  {"tee", OPT_TEE,
1688
 
   N_("Append everything into outfile. See interactive help (\\h) also. Does not work in batch mode. Disable with --disable-tee. This option is disabled by default."),
1689
 
   0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1690
 
  {"no-tee", OPT_NOTEE, N_("Disable outfile. See interactive help (\\h) also. WARNING: option deprecated; use --disable-tee instead"), 0, 0, 0, GET_NO_ARG,
1691
 
   NO_ARG, 0, 0, 0, 0, 0, 0},
1692
 
  {"user", 'u', N_("User for login if not current user."), (char**) &current_user,
1693
 
   (char**) &current_user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1694
 
  {"safe-updates", 'U', N_("Only allow UPDATE and DELETE that uses keys."),
1695
 
   (char**) &safe_updates, (char**) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0,
1696
 
   0, 0, 0, 0},
1697
 
  {"i-am-a-dummy", 'U', N_("Synonym for option --safe-updates, -U."),
1698
 
   (char**) &safe_updates, (char**) &safe_updates, 0, GET_BOOL, NO_ARG, 0, 0,
1699
 
   0, 0, 0, 0},
1700
 
  {"verbose", 'v', N_("Write more. (-v -v -v gives the table output format)."), 0,
1701
 
   0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1702
 
  {"version", 'V', N_("Output version information and exit."), 0, 0, 0,
1703
 
   GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1704
 
  {"wait", 'w', N_("Wait and retry if connection is down."), 0, 0, 0, GET_NO_ARG,
1705
 
   NO_ARG, 0, 0, 0, 0, 0, 0},
1706
 
  {"connect_timeout", OPT_CONNECT_TIMEOUT,
1707
 
   N_("Number of seconds before connection timeout."),
1708
 
   (char**) &opt_connect_timeout,
1709
 
   (char**) &opt_connect_timeout, 0, GET_UINT32, REQUIRED_ARG, 0, 0, 3600*12, 0,
1710
 
   0, 0},
1711
 
  {"max_input_line", OPT_MAX_INPUT_LINE,
1712
 
   N_("Max length of input line"),
1713
 
   (char**) &opt_max_input_line, (char**) &opt_max_input_line, 0,
1714
 
   GET_UINT32, REQUIRED_ARG, 16 *1024L*1024L, 4096,
1715
 
   (int64_t) 2*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
1716
 
  {"select_limit", OPT_SELECT_LIMIT,
1717
 
   N_("Automatic limit for SELECT when using --safe-updates"),
1718
 
   (char**) &select_limit,
1719
 
   (char**) &select_limit, 0, GET_UINT32, REQUIRED_ARG, 1000L, 1, ULONG_MAX,
1720
 
   0, 1, 0},
1721
 
  {"max_join_size", OPT_MAX_JOIN_SIZE,
1722
 
   N_("Automatic limit for rows in a join when using --safe-updates"),
1723
 
   (char**) &max_join_size,
1724
 
   (char**) &max_join_size, 0, GET_UINT32, REQUIRED_ARG, 1000000L, 1, ULONG_MAX,
1725
 
   0, 1, 0},
1726
 
  {"secure-auth", OPT_SECURE_AUTH, N_("Refuse client connecting to server if it uses old (pre-4.1.1) protocol"), (char**) &opt_secure_auth,
1727
 
   (char**) &opt_secure_auth, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1728
 
  {"show-warnings", OPT_SHOW_WARNINGS, N_("Show warnings after every statement."),
1729
 
   (char**) &show_warnings, (char**) &show_warnings, 0, GET_BOOL, NO_ARG,
1730
 
   0, 0, 0, 0, 0, 0},
1731
 
  {"show-progress-size", OPT_SHOW_PROGRESS_SIZE, N_("Number of lines before each import progress report."),
1732
 
   (char**) &show_progress_size, (char**) &show_progress_size, 0, GET_UINT32, REQUIRED_ARG,
1733
 
   0, 0, 0, 0, 0, 0},
1734
 
  {"ping", OPT_PING, N_("Ping the server to check if it's alive."),
1735
 
   (char**) &opt_ping, (char**) &opt_ping, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1736
 
  {"mysql", 'm', N_("Use MySQL Protocol."),
1737
 
   (char**) &opt_mysql, (char**) &opt_mysql, 0, GET_BOOL, NO_ARG, 1, 0, 0,
1738
 
   0, 0, 0},
1739
 
  { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1740
 
};
1741
 
 
1742
 
 
1743
 
static void usage(int version)
1744
 
{
1745
 
  const char* readline= "readline";
1746
 
 
1747
 
  printf(_("%s  Ver %s Distrib %s, for %s-%s (%s) using %s %s\n"),
1748
 
         internal::my_progname, VER.c_str(), drizzle_version(),
1749
 
         HOST_VENDOR, HOST_OS, HOST_CPU,
1750
 
         readline, rl_library_version);
1751
 
 
1752
 
  if (version)
1753
 
    return;
1754
 
  printf(_("Copyright (C) 2008 Sun Microsystems\n"
1755
 
           "This software comes with ABSOLUTELY NO WARRANTY. "
1756
 
           "This is free software,\n"
1757
 
           "and you are welcome to modify and redistribute it "
1758
 
           "under the GPL license\n"));
1759
 
  printf(_("Usage: %s [OPTIONS] [database]\n"), internal::my_progname);
1760
 
  my_print_help(my_long_options);
1761
 
  internal::print_defaults("drizzle", load_default_groups);
1762
 
  my_print_variables(my_long_options);
1763
 
}
1764
 
 
1765
 
 
1766
 
static int get_one_option(int optid, const struct option *, char *argument)
1767
 
{
1768
 
  char *endchar= NULL;
1769
 
  uint64_t temp_drizzle_port= 0;
1770
 
 
1771
 
  switch(optid) {
1772
 
  case  OPT_DEFAULT_CHARSET:
1773
 
    default_charset_used= 1;
1774
 
    break;
1775
 
  case OPT_DELIMITER:
1776
 
    if (argument == disabled_my_option)
1777
 
    {
1778
 
      strcpy(delimiter, DEFAULT_DELIMITER);
1779
 
    }
1780
 
    else
1781
 
    {
1782
 
      /* Check that delimiter does not contain a backslash */
1783
 
      if (!strstr(argument, "\\"))
1784
 
      {
1785
 
        strncpy(delimiter, argument, sizeof(delimiter) - 1);
1786
 
      }
1787
 
      else
1788
 
      {
1789
 
        put_info(_("DELIMITER cannot contain a backslash character"),
1790
 
                 INFO_ERROR,0,0);
1791
 
        return false;
1792
 
      }
1793
 
    }
1794
 
    delimiter_length= (uint32_t)strlen(delimiter);
1795
 
    delimiter_str= delimiter;
1796
 
    break;
1797
 
  case OPT_TEE:
1798
 
    if (argument == disabled_my_option)
1799
 
    {
1800
 
      if (opt_outfile)
1801
 
        end_tee();
1802
 
    }
1803
 
    else
1804
 
      init_tee(argument);
1805
 
    break;
1806
 
  case OPT_NOTEE:
1807
 
    printf(_("WARNING: option deprecated; use --disable-tee instead.\n"));
1808
 
    if (opt_outfile)
1809
 
      end_tee();
1810
 
    break;
1811
 
  case OPT_PAGER:
1812
 
    if (argument == disabled_my_option)
1813
 
      opt_nopager= 1;
1814
 
    else
1815
 
    {
1816
 
      opt_nopager= 0;
1817
 
      if (argument && strlen(argument))
1818
 
      {
1819
 
        default_pager_set= 1;
1820
 
        strncpy(pager, argument, sizeof(pager) - 1);
1821
 
        strcpy(default_pager, pager);
1822
 
      }
1823
 
      else if (default_pager_set)
1824
 
        strcpy(pager, default_pager);
1825
 
      else
1826
 
        opt_nopager= 1;
1827
 
    }
1828
 
    break;
1829
 
  case OPT_NOPAGER:
1830
 
    printf(_("WARNING: option deprecated; use --disable-pager instead.\n"));
1831
 
    opt_nopager= 1;
1832
 
    break;
1833
 
  case OPT_SERVER_ARG:
1834
 
    printf(_("WARNING: --server-arg option not supported in this configuration.\n"));
1835
 
    break;
1836
 
  case 'A':
1837
 
    opt_rehash= 0;
1838
 
    break;
1839
 
  case 'N':
1840
 
    column_names= 0;
1841
 
    break;
1842
 
  case 'e':
1843
 
    status.setBatch(1);
1844
 
    status.setAddToHistory(1);
1845
 
    if (status.getLineBuff() == NULL)
1846
 
      status.setLineBuff(opt_max_input_line,NULL);
1847
 
    if (status.getLineBuff() == NULL)
1848
 
    {
1849
 
      internal::my_end();
1850
 
      exit(1);
1851
 
    }
1852
 
    status.getLineBuff()->addString(argument);
1853
 
    break;
1854
 
  case 'o':
1855
 
    if (argument == disabled_my_option)
1856
 
      one_database= 0;
1857
 
    else
1858
 
      one_database= skip_updates= 1;
1859
 
    break;
1860
 
  case 'p':
1861
 
    temp_drizzle_port= (uint64_t) strtoul(argument, &endchar, 10);
1862
 
    /* if there is an alpha character this is not a valid port */
1863
 
    if (strlen(endchar) != 0)
1864
 
    {
1865
 
      put_info(_("Non-integer value supplied for port.  If you are trying to enter a password please use --password instead."), INFO_ERROR, 0, 0);
1866
 
      return false;
1867
 
    }
1868
 
    /* If the port number is > 65535 it is not a valid port
1869
 
       This also helps with potential data loss casting unsigned long to a
1870
 
       uint32_t. */
1871
 
    if ((temp_drizzle_port == 0) || (temp_drizzle_port > 65535))
1872
 
    {
1873
 
      put_info(_("Value supplied for port is not valid."), INFO_ERROR, 0, 0);
1874
 
      return false;
1875
 
    }
1876
 
    else
1877
 
    {
1878
 
      opt_drizzle_port= (uint32_t) temp_drizzle_port;
1879
 
    }
1880
 
    break;
1881
 
  case 'P':
1882
 
    /* Don't require password */
1883
 
    if (argument == disabled_my_option)
1884
 
    {
1885
 
      argument= (char*) "";
1886
 
    }
1887
 
    if (argument)
1888
 
    {
1889
 
      char *start= argument;
1890
 
      free(opt_password);
1891
 
      opt_password= strdup(argument);
1892
 
      while (*argument)
1893
 
      {
1894
 
        /* Overwriting password with 'x' */
1895
 
        *argument++= 'x';
1896
 
      }
1897
 
      if (*start)
1898
 
      {
1899
 
        start[1]= 0;
1900
 
      }
1901
 
      tty_password= 0;
1902
 
    }
1903
 
    else
1904
 
    {
1905
 
      tty_password= 1;
1906
 
    }
1907
 
    break;
1908
 
  case 's':
1909
 
    if (argument == disabled_my_option)
1910
 
      opt_silent= 0;
1911
 
    else
1912
 
      opt_silent++;
1913
 
    break;
1914
 
  case 'v':
1915
 
    if (argument == disabled_my_option)
1916
 
      verbose= 0;
1917
 
    else
1918
 
      verbose++;
1919
 
    break;
1920
 
  case 'B':
1921
 
    status.setBatch(1);
1922
 
    status.setAddToHistory(0);
1923
 
    set_if_bigger(opt_silent,1);                         // more silent
1924
 
    break;
1925
 
  case 'V':
1926
 
    usage(1);
1927
 
    exit(0);
1928
 
  case 'I':
1929
 
  case '?':
1930
 
    usage(0);
1931
 
    exit(0);
1932
 
  }
1933
 
  return 0;
1934
 
}
1935
 
 
1936
 
 
1937
 
static int get_options(int argc, char **argv)
 
1985
 
 
1986
 
 
1987
static int process_options(void)
1938
1988
{
1939
1989
  char *tmp, *pagpoint;
1940
 
  int ho_error;
 
1990
  
1941
1991
 
1942
1992
  tmp= (char *) getenv("DRIZZLE_HOST");
1943
1993
  if (tmp)
1946
1996
  pagpoint= getenv("PAGER");
1947
1997
  if (!((char*) (pagpoint)))
1948
1998
  {
1949
 
    strcpy(pager, "stdout");
 
1999
    pager.assign("stdout");
1950
2000
    opt_nopager= 1;
1951
2001
  }
1952
2002
  else
1953
 
    strcpy(pager, pagpoint);
1954
 
  strcpy(default_pager, pager);
 
2003
  {
 
2004
    pager.assign(pagpoint);
 
2005
  }
 
2006
  default_pager.assign(pager);
1955
2007
 
1956
 
  if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
1957
 
    exit(ho_error);
 
2008
  //
1958
2009
 
1959
2010
  if (status.getBatch()) /* disable pager and outfile in this case */
1960
2011
  {
1961
 
    strcpy(default_pager, "stdout");
1962
 
    strcpy(pager, "stdout");
 
2012
    default_pager.assign("stdout");
 
2013
    pager.assign("stdout");
1963
2014
    opt_nopager= 1;
1964
2015
    default_pager_set= 0;
1965
2016
    opt_outfile= 0;
1967
2018
    connect_flag= DRIZZLE_CAPABILITIES_NONE; /* Not in interactive mode */
1968
2019
  }
1969
2020
 
1970
 
  if (argc > 1)
1971
 
  {
1972
 
    usage(0);
1973
 
    exit(1);
1974
 
  }
1975
 
  if (argc == 1)
1976
 
  {
1977
 
    skip_updates= 0;
1978
 
    free(current_db);
1979
 
    current_db= strdup(*argv);
1980
 
  }
1981
2021
  if (tty_password)
1982
2022
    opt_password= client_get_tty_password(NULL);
1983
 
 
1984
2023
  return(0);
1985
2024
}
1986
2025
 
2013
2052
    }
2014
2053
    else
2015
2054
    {
2016
 
      const char *prompt= (const char*) (ml_comment ? "   /*> " :
2017
 
                                         (glob_buffer->empty())
2018
 
                                         ?  construct_prompt()
2019
 
                                         : !in_string ? "    -> " :
2020
 
                                         in_string == '\'' ?
2021
 
                                         "    '> " : (in_string == '`' ?
2022
 
                                                      "    `> " :
2023
 
                                                      "    \"> "));
 
2055
      string prompt(ml_comment
 
2056
                      ? "   /*> " 
 
2057
                      : glob_buffer->empty()
 
2058
                        ? construct_prompt()
 
2059
                        : not in_string
 
2060
                          ? "    -> "
 
2061
                          : in_string == '\''
 
2062
                            ? "    '> "
 
2063
                            : in_string == '`'
 
2064
                              ? "    `> "
 
2065
                              : "    \"> ");
2024
2066
      if (opt_outfile && glob_buffer->empty())
2025
2067
        fflush(OUTFILE);
2026
2068
 
2027
2069
      if (opt_outfile)
2028
 
        fputs(prompt, OUTFILE);
2029
 
      line= readline(prompt);
 
2070
        fputs(prompt.c_str(), OUTFILE);
 
2071
      line= readline(prompt.c_str());
2030
2072
      /*
2031
2073
        When Ctrl+d or Ctrl+z is pressed, the line may be NULL on some OS
2032
2074
        which may cause coredump.
2089
2131
  }
2090
2132
  else
2091
2133
  {
2092
 
    while (my_isspace(charset_info,*name))
 
2134
    while (isspace(*name))
2093
2135
      name++;
2094
2136
    /*
2095
2137
      If there is an \\g in the row or if the row has a delimiter but
2098
2140
    */
2099
2141
    if (strstr(name, "\\g") || (strstr(name, delimiter) &&
2100
2142
                                !(strlen(name) >= 9 &&
2101
 
                                  !my_strnncoll(charset_info,
2102
 
                                                (unsigned char*) name, 9,
2103
 
                                                (const unsigned char*) "delimiter",
2104
 
                                                9))))
 
2143
                                  !strcmp(name, "delimiter"))))
2105
2144
      return(NULL);
2106
2145
    if ((end=strcont(name," \t")))
2107
2146
    {
2108
2147
      len=(uint32_t) (end - name);
2109
 
      while (my_isspace(charset_info,*end))
 
2148
      while (isspace(*end))
2110
2149
        end++;
2111
2150
      if (!*end)
2112
2151
        end=0;          // no arguments to function
2118
2157
  for (uint32_t i= 0; commands[i].getName(); i++)
2119
2158
  {
2120
2159
    if (commands[i].func &&
2121
 
        ((name && !my_strnncoll(charset_info,(const unsigned char*)name,len, (const unsigned char*)commands[i].getName(),len) && !commands[i].getName()[len] && (!end || (end && commands[i].getTakesParams()))) || (!name && commands[i].getCmdChar() == cmd_char)))
 
2160
        ((name && !strncmp(name, commands[i].getName(), len)
 
2161
          && !commands[i].getName()[len] && (!end || (end && commands[i].getTakesParams()))) || (!name && commands[i].getCmdChar() == cmd_char)))
2122
2162
    {
2123
2163
      return(&commands[i]);
2124
2164
    }
2148
2188
    if (!preserve_comments)
2149
2189
    {
2150
2190
      // Skip spaces at the beggining of a statement
2151
 
      if (my_isspace(charset_info,inchar) && (out == line) &&
 
2191
      if (isspace(inchar) && (out == line) &&
2152
2192
          (buffer->empty()))
2153
2193
        continue;
2154
2194
    }
2155
2195
 
2156
2196
    // Accept multi-byte characters as-is
2157
 
    int length;
2158
 
    if (use_mb(charset_info) &&
2159
 
        (length= my_ismbchar(charset_info, pos, end_of_line)))
 
2197
    if (not drizzled::utf8::is_single(*pos))
2160
2198
    {
2161
 
      if (!*ml_comment || preserve_comments)
 
2199
      int length;
 
2200
      if ((length= drizzled::utf8::sequence_length(*pos)))
2162
2201
      {
2163
 
        while (length--)
2164
 
          *out++ = *pos++;
2165
 
        pos--;
 
2202
        if (!*ml_comment || preserve_comments)
 
2203
        {
 
2204
          while (length--)
 
2205
            *out++ = *pos++;
 
2206
          pos--;
 
2207
        }
 
2208
        else
 
2209
          pos+= length - 1;
 
2210
        continue;
2166
2211
      }
2167
 
      else
2168
 
        pos+= length - 1;
2169
 
      continue;
2170
2212
    }
2171
2213
    if (!*ml_comment && inchar == '\\' &&
2172
2214
        !(*in_string && (drizzle_con_status(&con) & DRIZZLE_CON_STATUS_NO_BACKSLASH_ESCAPES)))
2235
2277
    }
2236
2278
    else if (!*ml_comment && !*in_string &&
2237
2279
             (end_of_line - pos) >= 10 &&
2238
 
             !my_strnncoll(charset_info, (unsigned char*) pos, 10,
2239
 
                           (const unsigned char*) "delimiter ", 10))
 
2280
             !strncmp(pos, "delimiter ", 10))
2240
2281
    {
2241
2282
      // Flush previously accepted characters
2242
2283
      if (out != line)
2273
2314
 
2274
2315
      if (preserve_comments)
2275
2316
      {
2276
 
        while (my_isspace(charset_info, *pos))
 
2317
        while (isspace(*pos))
2277
2318
          *out++= *pos++;
2278
2319
      }
2279
2320
      // Flush previously accepted characters
2286
2327
      if (preserve_comments && ((*pos == '#') ||
2287
2328
                                ((*pos == '-') &&
2288
2329
                                 (pos[1] == '-') &&
2289
 
                                 my_isspace(charset_info, pos[2]))))
 
2330
                                 isspace(pos[2]))))
2290
2331
      {
2291
2332
        // Add trailing single line comments to this statement
2292
2333
        buffer->append(pos);
2313
2354
                 && (inchar == '#'
2314
2355
                     || (inchar == '-'
2315
2356
                         && pos[1] == '-'
2316
 
                         && my_isspace(charset_info,pos[2])))))
 
2357
                         && isspace(pos[2])))))
2317
2358
    {
2318
2359
      // Flush previously accepted characters
2319
2360
      if (out != line)
2379
2420
        *in_string= (char) inchar;
2380
2421
      if (!*ml_comment || preserve_comments)
2381
2422
      {
2382
 
        if (need_space && !my_isspace(charset_info, (char)inchar))
 
2423
        if (need_space && !isspace((char)inchar))
2383
2424
          *out++= ' ';
2384
2425
        need_space= 0;
2385
2426
        *out++= (char) inchar;
2582
2623
  drizzle_column_st *sql_field;
2583
2624
  string tmp_str, tmp_str_lower;
2584
2625
 
2585
 
  if (status.getBatch() || quick || !current_db)
 
2626
  if (status.getBatch() || quick || current_db.empty())
2586
2627
    return;      // We don't need completion in batches
2587
2628
  if (!rehash)
2588
2629
    return;
2717
2758
  drizzle_return_t ret;
2718
2759
  drizzle_result_st res;
2719
2760
 
2720
 
  free(current_db);
2721
 
  current_db= NULL;
 
2761
  current_db.erase();
 
2762
  current_db= "";
2722
2763
  /* In case of error below current_db will be NULL */
2723
2764
  if (drizzle_query_str(&con, &res, "SELECT DATABASE()", &ret) != NULL)
2724
2765
  {
3002
3043
{
3003
3044
  if (!opt_nopager)
3004
3045
  {
3005
 
    if (!(PAGER= popen(pager, "w")))
 
3046
    if (!(PAGER= popen(pager.c_str(), "w")))
3006
3047
    {
3007
3048
      tee_fprintf(stdout, "popen() failed! defaulting PAGER to stdout!\n");
3008
3049
      PAGER= stdout;
3030
3071
    return;
3031
3072
  }
3032
3073
  OUTFILE = new_outfile;
3033
 
  strncpy(outfile, file_name, FN_REFLEN-1);
 
3074
  outfile.assign(file_name);
3034
3075
  tee_fprintf(stdout, "Logging to file '%s'\n", file_name);
3035
3076
  opt_outfile= 1;
3036
3077
 
3120
3161
                "Database:   `%s`\n"
3121
3162
                "Table:      `%s`\n"
3122
3163
                "Org_table:  `%s`\n"
3123
 
                "Type:       %s\n"
 
3164
                "Type:       UTF-8\n"
3124
3165
                "Collation:  %s (%u)\n"
3125
3166
                "Length:     %lu\n"
3126
3167
                "Max_length: %lu\n"
3131
3172
                drizzle_column_db(field), drizzle_column_table(field),
3132
3173
                drizzle_column_orig_table(field),
3133
3174
                fieldtype2str(drizzle_column_type(field)),
3134
 
                get_charset_name(drizzle_column_charset(field)),
3135
3175
                drizzle_column_charset(field), drizzle_column_size(field),
3136
3176
                drizzle_column_max_size(field), drizzle_column_decimals(field),
3137
3177
                fieldflags2str(drizzle_column_flags(field)));
3139
3179
  tee_puts("", PAGER);
3140
3180
}
3141
3181
 
3142
 
 
3143
3182
static void
3144
3183
print_table_data(drizzle_result_st *result)
3145
3184
{
3171
3210
      /* Check if the max_byte value is really the maximum in terms
3172
3211
         of visual length since multibyte characters can affect the
3173
3212
         length of the separator. */
3174
 
      length= charset_info->cset->numcells(charset_info,
3175
 
                                           drizzle_column_name(field),
3176
 
                                           drizzle_column_name(field) +
3177
 
                                           name_length);
 
3213
      length= drizzled::utf8::char_length(drizzle_column_name(field));
3178
3214
 
3179
3215
      if (name_length == drizzle_column_max_size(field))
3180
3216
      {
3212
3248
    for (uint32_t off=0; (field = drizzle_column_next(result)) ; off++)
3213
3249
    {
3214
3250
      uint32_t name_length= (uint32_t) strlen(drizzle_column_name(field));
3215
 
      uint32_t numcells= charset_info->cset->numcells(charset_info,
3216
 
                                                  drizzle_column_name(field),
3217
 
                                                  drizzle_column_name(field) +
3218
 
                                                  name_length);
 
3251
      uint32_t numcells= drizzled::utf8::char_length(drizzle_column_name(field));
3219
3252
      uint32_t display_length= drizzle_column_max_size(field) + name_length -
3220
3253
                               numcells;
3221
3254
      tee_fprintf(PAGER, " %-*s |",(int) min(display_length,
3278
3311
        We need to find how much screen real-estate we will occupy to know how
3279
3312
        many extra padding-characters we should send with the printing function.
3280
3313
      */
3281
 
      visible_length= charset_info->cset->numcells(charset_info, buffer, buffer + data_length);
 
3314
      visible_length= drizzled::utf8::char_length(buffer);
3282
3315
      extra_padding= data_length - visible_length;
3283
3316
 
3284
3317
      if (field_max_length > MAX_COLUMN_LENGTH)
3506
3539
    else for (const char *end=pos+length ; pos != end ; pos++)
3507
3540
    {
3508
3541
      int l;
3509
 
      if (use_mb(charset_info) &&
3510
 
          (l = my_ismbchar(charset_info, pos, end)))
 
3542
      if ((l = drizzled::utf8::sequence_length(*pos)))
3511
3543
      {
3512
3544
        while (l--)
3513
3545
          tee_putc(*pos++, PAGER);
3586
3618
 
3587
3619
  if (status.getBatch())
3588
3620
    return 0;
3589
 
  while (my_isspace(charset_info,*line))
 
3621
  while (isspace(*line))
3590
3622
    line++;
3591
 
  if (!(param = strchr(line, ' '))) // if outfile wasn't given, use the default
 
3623
  if (!(param =strchr(line, ' '))) // if outfile wasn't given, use the default
3592
3624
  {
3593
 
    if (!strlen(outfile))
 
3625
    if (outfile.empty())
3594
3626
    {
3595
3627
      printf("No previous outfile available, you must give a filename!\n");
3596
3628
      return 0;
3597
3629
    }
3598
3630
    else if (opt_outfile)
3599
3631
    {
3600
 
      tee_fprintf(stdout, "Currently logging to file '%s'\n", outfile);
 
3632
      tee_fprintf(stdout, "Currently logging to file '%s'\n", outfile.c_str());
3601
3633
      return 0;
3602
3634
    }
3603
3635
    else
3604
 
      param = outfile;      //resume using the old outfile
 
3636
      param= outfile.c_str();      //resume using the old outfile
3605
3637
  }
3606
3638
 
 
3639
  /* @TODO: Replace this with string methods */
3607
3640
  /* eliminate the spaces before the parameters */
3608
 
  while (my_isspace(charset_info,*param))
 
3641
  while (isspace(*param))
3609
3642
    param++;
3610
3643
  strncpy(file_name, param, sizeof(file_name) - 1);
3611
3644
  end= file_name + strlen(file_name);
3612
3645
  /* remove end space from command line */
3613
 
  while (end > file_name && (my_isspace(charset_info,end[-1]) ||
3614
 
                             my_iscntrl(charset_info,end[-1])))
 
3646
  while (end > file_name && (isspace(end[-1]) ||
 
3647
                             iscntrl(end[-1])))
3615
3648
    end--;
3616
3649
  end[0]= 0;
3617
3650
  if (end == file_name)
3640
3673
static int
3641
3674
com_pager(string *, const char *line)
3642
3675
{
3643
 
  char pager_name[FN_REFLEN], *end;
3644
3676
  const char *param;
3645
3677
 
3646
3678
  if (status.getBatch())
3647
3679
    return 0;
3648
3680
  /* Skip spaces in front of the pager command */
3649
 
  while (my_isspace(charset_info, *line))
 
3681
  while (isspace(*line))
3650
3682
    line++;
3651
3683
  /* Skip the pager command */
3652
3684
  param= strchr(line, ' ');
3653
3685
  /* Skip the spaces between the command and the argument */
3654
 
  while (param && my_isspace(charset_info, *param))
 
3686
  while (param && isspace(*param))
3655
3687
    param++;
3656
3688
  if (!param || !strlen(param)) // if pager was not given, use the default
3657
3689
  {
3659
3691
    {
3660
3692
      tee_fprintf(stdout, "Default pager wasn't set, using stdout.\n");
3661
3693
      opt_nopager=1;
3662
 
      strcpy(pager, "stdout");
 
3694
      pager.assign("stdout");
3663
3695
      PAGER= stdout;
3664
3696
      return 0;
3665
3697
    }
3666
 
    strcpy(pager, default_pager);
 
3698
    pager.assign(default_pager);
3667
3699
  }
3668
3700
  else
3669
3701
  {
3670
 
    end= strncpy(pager_name, param, sizeof(pager_name)-1);
3671
 
    end+= strlen(pager_name);
3672
 
    while (end > pager_name && (my_isspace(charset_info,end[-1]) ||
3673
 
                                my_iscntrl(charset_info,end[-1])))
3674
 
      end--;
3675
 
    end[0]=0;
3676
 
    strcpy(pager, pager_name);
3677
 
    strcpy(default_pager, pager_name);
 
3702
    string pager_name(param);
 
3703
    string::iterator end= pager_name.end();
 
3704
    while (end > pager_name.begin() &&
 
3705
           (isspace(*(end-1)) || iscntrl(*(end-1))))
 
3706
      --end;
 
3707
    pager_name.erase(end, pager_name.end());
 
3708
    pager.assign(pager_name);
 
3709
    default_pager.assign(pager_name);
3678
3710
  }
3679
3711
  opt_nopager=0;
3680
 
  tee_fprintf(stdout, "PAGER set to '%s'\n", pager);
 
3712
  tee_fprintf(stdout, "PAGER set to '%s'\n", pager.c_str());
3681
3713
  return 0;
3682
3714
}
3683
3715
 
3685
3717
static int
3686
3718
com_nopager(string *, const char *)
3687
3719
{
3688
 
  strcpy(pager, "stdout");
 
3720
  pager.assign("stdout");
3689
3721
  opt_nopager=1;
3690
3722
  PAGER= stdout;
3691
3723
  tee_fprintf(stdout, "PAGER set to stdout\n");
3746
3778
    tmp= get_arg(buff, 0);
3747
3779
    if (tmp && *tmp)
3748
3780
    {
3749
 
      free(current_db);
 
3781
      current_db.erase();
3750
3782
      current_db= strdup(tmp);
3751
3783
      tmp= get_arg(buff, 1);
3752
3784
      if (tmp)
3753
3785
      {
3754
 
        free(current_host);
 
3786
        current_host.erase();
3755
3787
        current_host=strdup(tmp);
3756
3788
      }
3757
3789
    }
3766
3798
  }
3767
3799
  else
3768
3800
    opt_rehash= 0;
3769
 
  error=sql_connect(current_host,current_db,current_user,opt_password,0);
 
3801
  error=sql_connect(current_host, current_db, current_user, opt_password,0);
3770
3802
  opt_rehash= save_rehash;
3771
3803
 
3772
3804
  if (connected)
3774
3806
    sprintf(buff,"Connection id:    %u",drizzle_con_thread_id(&con));
3775
3807
    put_info(buff,INFO_INFO,0,0);
3776
3808
    sprintf(buff,"Current database: %.128s\n",
3777
 
            current_db ? current_db : "*** NONE ***");
 
3809
            !current_db.empty() ? current_db.c_str() : "*** NONE ***");
3778
3810
    put_info(buff,INFO_INFO,0,0);
3779
3811
  }
3780
3812
  return error;
3791
3823
  FILE *sql_file;
3792
3824
 
3793
3825
  /* Skip space from file name */
3794
 
  while (my_isspace(charset_info,*line))
 
3826
  while (isspace(*line))
3795
3827
    line++;
3796
3828
  if (!(param = strchr(line, ' ')))    // Skip command name
3797
3829
    return put_info("Usage: \\. <filename> | source <filename>",
3798
3830
                    INFO_ERROR, 0,0);
3799
 
  while (my_isspace(charset_info,*param))
 
3831
  while (isspace(*param))
3800
3832
    param++;
3801
3833
  end= strncpy(source_name,param,sizeof(source_name)-1);
3802
3834
  end+= strlen(source_name);
3803
 
  while (end > source_name && (my_isspace(charset_info,end[-1]) ||
3804
 
                               my_iscntrl(charset_info,end[-1])))
 
3835
  while (end > source_name && (isspace(end[-1]) ||
 
3836
                               iscntrl(end[-1])))
3805
3837
    end--;
3806
3838
  end[0]=0;
3807
 
  internal::unpack_filename(source_name,source_name);
 
3839
 
3808
3840
  /* open file name */
3809
3841
  if (!(sql_file = fopen(source_name, "r")))
3810
3842
  {
3896
3928
  */
3897
3929
  get_current_db();
3898
3930
 
3899
 
  if (!current_db || strcmp(current_db,tmp))
 
3931
  if (current_db.empty() || strcmp(current_db.c_str(),tmp))
3900
3932
  {
3901
3933
    if (one_database)
3902
3934
    {
3948
3980
      else
3949
3981
        drizzle_result_free(&result);
3950
3982
    }
3951
 
    free(current_db);
 
3983
    current_db.erase();
3952
3984
    current_db= strdup(tmp);
3953
3985
    if (select_db > 1)
3954
3986
      build_completion_hash(opt_rehash, 1);
4000
4032
  else
4001
4033
  {
4002
4034
    /* skip leading white spaces */
4003
 
    while (my_isspace(charset_info, *ptr))
 
4035
    while (isspace(*ptr))
4004
4036
      ptr++;
4005
4037
    if (*ptr == '\\') // short command was used
4006
4038
      ptr+= 2;
4007
4039
    else
4008
 
      while (*ptr &&!my_isspace(charset_info, *ptr)) // skip command
 
4040
      while (*ptr &&!isspace(*ptr)) // skip command
4009
4041
        ptr++;
4010
4042
  }
4011
4043
  if (!*ptr)
4012
4044
    return NULL;
4013
 
  while (my_isspace(charset_info, *ptr))
 
4045
  while (isspace(*ptr))
4014
4046
    ptr++;
4015
4047
  if (*ptr == '\'' || *ptr == '\"' || *ptr == '`')
4016
4048
  {
4037
4069
 
4038
4070
 
4039
4071
static int
4040
 
sql_connect(char *host,char *database,char *user,char *password,
 
4072
sql_connect(const string &host, const string &database, const string &user, const string &password,
4041
4073
                 uint32_t silent)
4042
4074
{
4043
4075
  drizzle_return_t ret;
4044
 
 
4045
4076
  if (connected)
4046
4077
  {
4047
4078
    connected= 0;
4049
4080
    drizzle_free(&drizzle);
4050
4081
  }
4051
4082
  drizzle_create(&drizzle);
4052
 
  if (drizzle_con_add_tcp(&drizzle, &con, host, opt_drizzle_port, user,
4053
 
                          password, database, opt_mysql ? DRIZZLE_CON_MYSQL : DRIZZLE_CON_NONE) == NULL)
 
4083
  if (drizzle_con_add_tcp(&drizzle, &con, (char *)host.c_str(), opt_drizzle_port, (char *)user.c_str(),
 
4084
                          (char *)password.c_str(), (char *)database.c_str(), opt_mysql ? DRIZZLE_CON_MYSQL : DRIZZLE_CON_NONE) == NULL)
4054
4085
  {
4055
4086
    (void) put_error(&con, NULL);
4056
4087
    (void) fflush(stdout);
4106
4137
  drizzle_return_t ret;
4107
4138
 
4108
4139
  tee_puts("--------------", stdout);
4109
 
  usage(1);          /* Print version */
 
4140
  printf(_("drizzle  Ver %s Distrib %s, for %s-%s (%s) using readline %s\n"),
 
4141
  VER.c_str(), drizzle_version(),
 
4142
  HOST_VENDOR, HOST_OS, HOST_CPU,
 
4143
  rl_library_version);          /* Print version */
 
4144
 
 
4145
 
4110
4146
  if (connected)
4111
4147
  {
4112
4148
    tee_fprintf(stdout, "\nConnection id:\t\t%lu\n",drizzle_con_thread_id(&con));
4143
4179
    tee_fprintf(stdout, "\nAll updates ignored to this database\n");
4144
4180
    vidattr(A_NORMAL);
4145
4181
  }
4146
 
  tee_fprintf(stdout, "Current pager:\t\t%s\n", pager);
4147
 
  tee_fprintf(stdout, "Using outfile:\t\t'%s'\n", opt_outfile ? outfile : "");
 
4182
  tee_fprintf(stdout, "Current pager:\t\t%s\n", pager.c_str());
 
4183
  tee_fprintf(stdout, "Using outfile:\t\t'%s'\n", opt_outfile ? outfile.c_str() : "");
4148
4184
  tee_fprintf(stdout, "Using delimiter:\t%s\n", delimiter);
4149
4185
  tee_fprintf(stdout, "Server version:\t\t%s\n", server_version_string(&con));
4150
4186
  tee_fprintf(stdout, "Protocol version:\t%d\n", drizzle_con_protocol_version(&con));
4313
4349
{
4314
4350
  const char *start=  buffer->c_str();
4315
4351
  const char *end= start + (buffer->length());
4316
 
  while (start < end && !my_isgraph(charset_info,end[-1]))
 
4352
  while (start < end && !isgraph(end[-1]))
4317
4353
    end--;
4318
4354
  uint32_t pos_to_truncate= (end-start);
4319
4355
  if (buffer->length() > pos_to_truncate)
4452
4488
  struct tm *t = localtime(&lclock);
4453
4489
 
4454
4490
  /* parse thru the settings for the prompt */
4455
 
  for (char *c= current_prompt; *c; (void)*c++)
 
4491
  string::iterator c= current_prompt.begin();
 
4492
  while (c != current_prompt.end())
4456
4493
  {
4457
4494
    if (*c != PROMPT_CHAR)
4458
4495
    {
4459
 
      processed_prompt->append(c, 1);
 
4496
      processed_prompt->push_back(*c);
4460
4497
    }
4461
4498
    else
4462
4499
    {
4467
4504
      switch (*++c) {
4468
4505
      case '\0':
4469
4506
        // stop it from going beyond if ends with %
4470
 
        c--;
 
4507
        --c;
4471
4508
        break;
4472
4509
      case 'c':
4473
4510
        add_int_to_prompt(++prompt_counter);
4479
4516
          processed_prompt->append("not_connected");
4480
4517
        break;
4481
4518
      case 'd':
4482
 
        processed_prompt->append(current_db ? current_db : "(none)");
 
4519
        processed_prompt->append(not current_db.empty() ? current_db : "(none)");
4483
4520
        break;
4484
4521
      case 'h':
4485
4522
      {
4486
 
        const char *prompt;
4487
 
        prompt= connected ? drizzle_con_host(&con) : "not_connected";
 
4523
        const char *prompt= connected ? drizzle_con_host(&con) : "not_connected";
4488
4524
        if (strstr(prompt, "Localhost"))
4489
4525
          processed_prompt->append("localhost");
4490
4526
        else
4516
4552
        if (!full_username)
4517
4553
          init_username();
4518
4554
        processed_prompt->append(full_username ? full_username :
4519
 
                                 (current_user ?  current_user : "(unknown)"));
 
4555
                                 (!current_user.empty() ?  current_user : "(unknown)"));
4520
4556
        break;
4521
4557
      case 'u':
4522
4558
        if (!full_username)
4523
4559
          init_username();
4524
4560
        processed_prompt->append(part_username ? part_username :
4525
 
                                 (current_user ?  current_user : "(unknown)"));
 
4561
                                 (!current_user.empty() ?  current_user : "(unknown)"));
4526
4562
        break;
4527
4563
      case PROMPT_CHAR:
4528
4564
        {
4604
4640
        processed_prompt->append(delimiter_str);
4605
4641
        break;
4606
4642
      default:
4607
 
        processed_prompt->append(c, 1);
 
4643
        processed_prompt->push_back(*c);
4608
4644
      }
4609
4645
    }
 
4646
    ++c;
4610
4647
  }
4611
4648
  return processed_prompt->c_str();
4612
4649
}
4649
4686
    tee_fprintf(stdout, "Memory allocation error. Not changing prompt\n");
4650
4687
  else
4651
4688
  {
4652
 
    free(current_prompt);
 
4689
    current_prompt.erase();
4653
4690
    current_prompt= tmpptr;
4654
 
    tee_fprintf(stdout, "PROMPT set to '%s'\n", current_prompt);
 
4691
    tee_fprintf(stdout, "PROMPT set to '%s'\n", current_prompt.c_str());
4655
4692
  }
4656
4693
  return 0;
4657
4694
}