MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
my_getopt.cc
1 /* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
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 Foundation,
14  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
15 
16 #include <my_global.h>
17 #include <m_string.h>
18 #include <stdlib.h>
19 #include <mysys_err.h>
20 #include <my_getopt.h>
21 #include <errno.h>
22 #include <m_string.h>
23 #include "my_default.h"
24 
25 typedef void (*init_func_p)(const struct my_option *option, void *variable,
26  longlong value);
27 
28 static void default_reporter(enum loglevel level, const char *format, ...);
29 my_error_reporter my_getopt_error_reporter= &default_reporter;
30 
31 static int findopt(char *, uint, const struct my_option **, const char **);
32 my_bool getopt_compare_strings(const char *, const char *, uint);
33 static longlong getopt_ll(char *arg, const struct my_option *optp, int *err);
34 static ulonglong getopt_ull(char *, const struct my_option *, int *);
35 static double getopt_double(char *arg, const struct my_option *optp, int *err);
36 static void init_variables(const struct my_option *, init_func_p);
37 static void init_one_value(const struct my_option *, void *, longlong);
38 static void fini_one_value(const struct my_option *, void *, longlong);
39 static int setval(const struct my_option *, void *, char *, my_bool);
40 static char *check_struct_option(char *cur_arg, char *key_name);
41 static void print_cmdline_password_warning();
42 static my_bool get_bool_argument(const struct my_option *opts,
43  const char *argument,
44  bool *error);
45 
46 /*
47  The following three variables belong to same group and the number and
48  order of their arguments must correspond to each other.
49 */
50 static const char *special_opt_prefix[]=
51 {"skip", "disable", "enable", "maximum", "loose", 0};
52 static const uint special_opt_prefix_lengths[]=
53 { 4, 7, 6, 7, 5, 0};
54 enum enum_special_opt
55 { OPT_SKIP, OPT_DISABLE, OPT_ENABLE, OPT_MAXIMUM, OPT_LOOSE};
56 
57 char *disabled_my_option= (char*) "0";
58 char *enabled_my_option= (char*) "1";
59 
60 /*
61  This is a flag that can be set in client programs. 0 means that
62  my_getopt will not print error messages, but the client should do
63  it by itself
64 */
65 
66 my_bool my_getopt_print_errors= 1;
67 
68 /*
69  This is a flag that can be set in client programs. 1 means that
70  my_getopt will skip over options it does not know how to handle.
71 */
72 
73 my_bool my_getopt_skip_unknown= 0;
74 
75 static void default_reporter(enum loglevel level,
76  const char *format, ...)
77 {
78  va_list args;
79  va_start(args, format);
80  if (level == WARNING_LEVEL)
81  fprintf(stderr, "%s", "Warning: ");
82  else if (level == INFORMATION_LEVEL)
83  fprintf(stderr, "%s", "Info: ");
84  vfprintf(stderr, format, args);
85  va_end(args);
86  fputc('\n', stderr);
87  fflush(stderr);
88 }
89 
90 static my_getopt_value getopt_get_addr;
91 
92 void my_getopt_register_get_addr(my_getopt_value func_addr)
93 {
94  getopt_get_addr= func_addr;
95 }
96 
97 
110 int handle_options(int *argc, char ***argv,
111  const struct my_option *longopts,
112  my_get_one_option get_one_option)
113 {
114  return my_handle_options(argc, argv, longopts, get_one_option, NULL);
115 }
116 
117 union ull_dbl
118 {
119  ulonglong ull;
120  double dbl;
121 };
122 
127 ulonglong getopt_double2ulonglong(double v)
128 {
129  union ull_dbl u;
130  u.dbl= v;
131  compile_time_assert(sizeof(ulonglong) >= sizeof(double));
132  return u.ull;
133 }
134 
139 double getopt_ulonglong2double(ulonglong v)
140 {
141  union ull_dbl u;
142  u.ull= v;
143  return u.dbl;
144 }
145 
212 int my_handle_options(int *argc, char ***argv,
213  const struct my_option *longopts,
214  my_get_one_option get_one_option,
215  const char **command_list)
216 {
217  uint UNINIT_VAR(opt_found), argvpos= 0, length;
218  my_bool end_of_options= 0, must_be_var, set_maximum_value,
219  option_is_loose;
220  char **pos, **pos_end, *optend, *opt_str, key_name[FN_REFLEN];
221  const char *UNINIT_VAR(prev_found);
222  const struct my_option *optp;
223  void *value;
224  int error, i;
225  my_bool is_cmdline_arg= 1;
226 
227  /* handle_options() assumes arg0 (program name) always exists */
228  DBUG_ASSERT(argc && *argc >= 1);
229  DBUG_ASSERT(argv && *argv);
230  (*argc)--; /* Skip the program name */
231  (*argv)++; /* --- || ---- */
232  init_variables(longopts, init_one_value);
233 
234  /*
235  Search for args_separator, if found, then the first part of the
236  arguments are loaded from configs
237  */
238  for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++)
239  {
240  if (my_getopt_is_args_separator(*pos))
241  {
242  is_cmdline_arg= 0;
243  break;
244  }
245  }
246 
247  for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++)
248  {
249  char **first= pos;
250  char *cur_arg= *pos;
251  opt_found= 0;
252  if (!is_cmdline_arg && (my_getopt_is_args_separator(cur_arg)))
253  {
254  is_cmdline_arg= 1;
255 
256  /* save the separator too if skip unkown options */
257  if (my_getopt_skip_unknown)
258  (*argv)[argvpos++]= cur_arg;
259  else
260  (*argc)--;
261  continue;
262  }
263  if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */
264  {
265  char *argument= 0;
266  must_be_var= 0;
267  set_maximum_value= 0;
268  option_is_loose= 0;
269 
270  cur_arg++; /* skip '-' */
271  if (*cur_arg == '-') /* check for long option, */
272  {
273  if (!*++cur_arg) /* skip the double dash */
274  {
275  /* '--' means end of options, look no further */
276  end_of_options= 1;
277  (*argc)--;
278  continue;
279  }
280  opt_str= check_struct_option(cur_arg, key_name);
281  optend= strcend(opt_str, '=');
282  length= (uint) (optend - opt_str);
283  if (*optend == '=')
284  optend++;
285  else
286  optend= 0;
287 
288  /*
289  Find first the right option. Return error in case of an ambiguous,
290  or unknown option
291  */
292  optp= longopts;
293  if (!(opt_found= findopt(opt_str, length, &optp, &prev_found)))
294  {
295  /*
296  Didn't find any matching option. Let's see if someone called
297  option with a special option prefix
298  */
299  if (!must_be_var)
300  {
301  if (optend)
302  must_be_var= 1; /* option is followed by an argument */
303  for (i= 0; special_opt_prefix[i]; i++)
304  {
305  if (!getopt_compare_strings(special_opt_prefix[i], opt_str,
306  special_opt_prefix_lengths[i]) &&
307  (opt_str[special_opt_prefix_lengths[i]] == '-' ||
308  opt_str[special_opt_prefix_lengths[i]] == '_'))
309  {
310  /*
311  We were called with a special prefix, we can reuse opt_found
312  */
313  opt_str+= special_opt_prefix_lengths[i] + 1;
314  length-= special_opt_prefix_lengths[i] + 1;
315  if (i == OPT_LOOSE)
316  option_is_loose= 1;
317  if ((opt_found= findopt(opt_str, length, &optp, &prev_found)))
318  {
319  if (opt_found > 1)
320  {
321  if (my_getopt_print_errors)
322  my_getopt_error_reporter(ERROR_LEVEL,
323  "%s: ambiguous option '--%s-%s' (--%s-%s)",
324  my_progname, special_opt_prefix[i],
325  opt_str, special_opt_prefix[i],
326  prev_found);
327  return EXIT_AMBIGUOUS_OPTION;
328  }
329  switch (i) {
330  case OPT_SKIP:
331  case OPT_DISABLE: /* fall through */
332  /*
333  double negation is actually enable again,
334  for example: --skip-option=0 -> option = TRUE
335  */
336  optend= (optend && *optend == '0' && !(*(optend + 1))) ?
337  enabled_my_option : disabled_my_option;
338  break;
339  case OPT_ENABLE:
340  optend= (optend && *optend == '0' && !(*(optend + 1))) ?
341  disabled_my_option : enabled_my_option;
342  break;
343  case OPT_MAXIMUM:
344  set_maximum_value= 1;
345  must_be_var= 1;
346  break;
347  }
348  break; /* break from the inner loop, main loop continues */
349  }
350  i= -1; /* restart the loop */
351  }
352  }
353  }
354  if (!opt_found)
355  {
356  if (my_getopt_skip_unknown)
357  {
358  /* Preserve all the components of this unknown option. */
359  do {
360  (*argv)[argvpos++]= *first++;
361  } while (first <= pos);
362  continue;
363  }
364  if (must_be_var)
365  {
366  if (my_getopt_print_errors)
367  my_getopt_error_reporter(option_is_loose ?
368  WARNING_LEVEL : ERROR_LEVEL,
369  "%s: unknown variable '%s'",
370  my_progname, cur_arg);
371  if (!option_is_loose)
372  return EXIT_UNKNOWN_VARIABLE;
373  }
374  else
375  {
376  if (my_getopt_print_errors)
377  my_getopt_error_reporter(option_is_loose ?
378  WARNING_LEVEL : ERROR_LEVEL,
379  "%s: unknown option '--%s'",
380  my_progname, cur_arg);
381  if (!option_is_loose)
382  return EXIT_UNKNOWN_OPTION;
383  }
384  if (option_is_loose)
385  {
386  (*argc)--;
387  continue;
388  }
389  }
390  }
391  if (opt_found > 1)
392  {
393  if (must_be_var)
394  {
395  if (my_getopt_print_errors)
396  my_getopt_error_reporter(ERROR_LEVEL,
397  "%s: variable prefix '%s' is not unique",
398  my_progname, opt_str);
399  return EXIT_VAR_PREFIX_NOT_UNIQUE;
400  }
401  else
402  {
403  if (my_getopt_print_errors)
404  my_getopt_error_reporter(ERROR_LEVEL,
405  "%s: ambiguous option '--%s' (%s, %s)",
406  my_progname, opt_str, prev_found,
407  optp->name);
408  return EXIT_AMBIGUOUS_OPTION;
409  }
410  }
411  if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED)
412  {
413  if (my_getopt_print_errors)
414  fprintf(stderr,
415  "%s: %s: Option '%s' used, but is disabled\n", my_progname,
416  option_is_loose ? "WARNING" : "ERROR", opt_str);
417  if (option_is_loose)
418  {
419  (*argc)--;
420  continue;
421  }
422  return EXIT_OPTION_DISABLED;
423  }
424  error= 0;
425  value= optp->var_type & GET_ASK_ADDR ?
426  (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp, &error) :
427  optp->value;
428  if (error)
429  return error;
430 
431  if (optp->arg_type == NO_ARG)
432  {
433  /*
434  Due to historical reasons GET_BOOL var_types still accepts arguments
435  despite the NO_ARG arg_type attribute. This can seems a bit unintuitive
436  and care should be taken when refactoring this code.
437  */
438  if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL)
439  {
440  if (my_getopt_print_errors)
441  my_getopt_error_reporter(ERROR_LEVEL,
442  "%s: option '--%s' cannot take an argument",
443  my_progname, optp->name);
444  return EXIT_NO_ARGUMENT_ALLOWED;
445  }
446  if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL)
447  {
448  /*
449  Set bool to 1 if no argument or if the user has used
450  --enable-'option-name'.
451  *optend was set to '0' if one used --disable-option
452  */
453  (*argc)--;
454  if(!optend)
455  *((my_bool*) value)= (my_bool) 1;
456  else
457  {
458  my_bool ret= 0;
459  bool error= 0;
460  ret= get_bool_argument(optp, optend, &error);
461  if(error)
462  {
463  my_getopt_error_reporter(WARNING_LEVEL,
464  "%s: ignoring option '--%s' "
465  "due to invalid value '%s'",
466  my_progname, optp->name, optend);
467  continue;
468  }
469  else
470  *((my_bool*) value)= ret;
471  }
472  if (get_one_option && get_one_option(optp->id, optp,
473  *((my_bool*) value) ?
474  enabled_my_option : disabled_my_option))
475  return EXIT_ARGUMENT_INVALID;
476  continue;
477  }
478  argument= optend;
479  }
480  else if (optp->arg_type == REQUIRED_ARG && !optend)
481  {
482  /* Check if there are more arguments after this one,
483  Note: options loaded from config file that requires value
484  should always be in the form '--option=value'.
485  */
486  if (!is_cmdline_arg || !*++pos)
487  {
488  if (my_getopt_print_errors)
489  my_getopt_error_reporter(ERROR_LEVEL,
490  "%s: option '--%s' requires an argument",
491  my_progname, optp->name);
492  return EXIT_ARGUMENT_REQUIRED;
493  }
494  argument= *pos;
495  (*argc)--;
496  }
497  else
498  argument= optend;
499 
500  if (optp->var_type == GET_PASSWORD && is_cmdline_arg && argument)
501  print_cmdline_password_warning();
502  }
503  else /* must be short option */
504  {
505  for (optend= cur_arg; *optend; optend++)
506  {
507  opt_found= 0;
508  for (optp= longopts; optp->name; optp++)
509  {
510  if (optp->id && optp->id == (int) (uchar) *optend)
511  {
512  /* Option recognized. Find next what to do with it */
513  opt_found= 1;
514  if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED)
515  {
516  if (my_getopt_print_errors)
517  fprintf(stderr,
518  "%s: ERROR: Option '-%c' used, but is disabled\n",
519  my_progname, optp->id);
520  return EXIT_OPTION_DISABLED;
521  }
522  if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL &&
523  optp->arg_type == NO_ARG)
524  {
525  *((my_bool*) optp->value)= (my_bool) 1;
526  if (get_one_option && get_one_option(optp->id, optp, argument))
527  return EXIT_UNSPECIFIED_ERROR;
528  continue;
529  }
530  else if (optp->arg_type == REQUIRED_ARG ||
531  optp->arg_type == OPT_ARG)
532  {
533  if (*(optend + 1))
534  {
535  /* The rest of the option is option argument */
536  argument= optend + 1;
537  /* This is in effect a jump out of the outer loop */
538  optend= (char*) " ";
539  if (optp->var_type == GET_PASSWORD && is_cmdline_arg)
540  print_cmdline_password_warning();
541  }
542  else
543  {
544  if (optp->arg_type == OPT_ARG)
545  {
546  if (optp->var_type == GET_BOOL)
547  *((my_bool*) optp->value)= (my_bool) 1;
548  if (get_one_option && get_one_option(optp->id, optp, argument))
549  return EXIT_UNSPECIFIED_ERROR;
550  continue;
551  }
552  /* Check if there are more arguments after this one */
553  if (!pos[1])
554  {
555  if (my_getopt_print_errors)
556  my_getopt_error_reporter(ERROR_LEVEL,
557  "%s: option '-%c' requires an argument",
558  my_progname, optp->id);
559  return EXIT_ARGUMENT_REQUIRED;
560  }
561  argument= *++pos;
562  (*argc)--;
563  /* the other loop will break, because *optend + 1 == 0 */
564  }
565  }
566  if ((error= setval(optp, optp->value, argument,
567  set_maximum_value)))
568  return error;
569  if (get_one_option && get_one_option(optp->id, optp, argument))
570  return EXIT_UNSPECIFIED_ERROR;
571  break;
572  }
573  }
574  if (!opt_found)
575  {
576  if (my_getopt_skip_unknown)
577  {
578  /*
579  We are currently parsing a single argv[] argument
580  of the form "-XYZ".
581  One or the argument found (say Y) is not an option.
582  Hack the string "-XYZ" to make a "-YZ" substring in it,
583  and push that to the output as an unrecognized parameter.
584  */
585  DBUG_ASSERT(optend > *pos);
586  DBUG_ASSERT(optend >= cur_arg);
587  DBUG_ASSERT(optend <= *pos + strlen(*pos));
588  DBUG_ASSERT(*optend);
589  optend--;
590  optend[0]= '-'; /* replace 'X' or '-' by '-' */
591  (*argv)[argvpos++]= optend;
592  /*
593  Do not continue to parse at the current "-XYZ" argument,
594  skip to the next argv[] argument instead.
595  */
596  optend= (char*) " ";
597  }
598  else
599  {
600  if (my_getopt_print_errors)
601  my_getopt_error_reporter(ERROR_LEVEL,
602  "%s: unknown option '-%c'",
603  my_progname, *optend);
604  return EXIT_UNKNOWN_OPTION;
605  }
606  }
607  }
608  if (opt_found)
609  (*argc)--; /* option handled (short), decrease argument count */
610  continue;
611  }
612  if ((error= setval(optp, value, argument, set_maximum_value)))
613  return error;
614  if (get_one_option && get_one_option(optp->id, optp, argument))
615  return EXIT_UNSPECIFIED_ERROR;
616 
617  (*argc)--; /* option handled (long), decrease argument count */
618  }
619  else /* non-option found */
620  {
621  if (command_list)
622  {
623  while (* command_list)
624  {
625  if (!strcmp(*command_list, cur_arg))
626  {
627  /* Match found. */
628  (*argv)[argvpos ++]= cur_arg;
629 
630  /* Copy rest of the un-parsed elements & return. */
631  while ((++ pos) != pos_end)
632  (*argv)[argvpos ++]= *pos;
633  goto done;
634  }
635  command_list ++;
636  }
637  }
638  (*argv)[argvpos ++]= cur_arg;
639  }
640  }
641 
642 done:
643  /*
644  Destroy the first, already handled option, so that programs that look
645  for arguments in 'argv', without checking 'argc', know when to stop.
646  Items in argv, before the destroyed one, are all non-option -arguments
647  to the program, yet to be (possibly) handled.
648  */
649  (*argv)[argvpos]= 0;
650  return 0;
651 }
652 
653 
659 static void print_cmdline_password_warning()
660 {
661  static my_bool password_warning_announced= FALSE;
662 
663  if (!password_warning_announced)
664  {
665  fprintf(stderr, "Warning: Using a password on the command line "
666  "interface can be insecure.\n");
667  (void) fflush(stderr);
668  password_warning_announced= TRUE;
669  }
670 }
671 
672 
673 /*
674  function: check_struct_option
675 
676  Arguments: Current argument under processing from argv and a variable
677  where to store the possible key name.
678 
679  Return value: In case option is a struct option, returns a pointer to
680  the current argument at the position where the struct option (key_name)
681  ends, the next character after the dot. In case argument is not a struct
682  option, returns a pointer to the argument.
683 
684  key_name will hold the name of the key, or 0 if not found.
685 */
686 
687 static char *check_struct_option(char *cur_arg, char *key_name)
688 {
689  char *ptr, *end;
690 
691  ptr= strcend(cur_arg + 1, '.'); /* Skip the first character */
692  end= strcend(cur_arg, '=');
693 
694  /*
695  If the first dot is after an equal sign, then it is part
696  of a variable value and the option is not a struct option.
697  Also, if the last character in the string before the ending
698  NULL, or the character right before equal sign is the first
699  dot found, the option is not a struct option.
700  */
701  if (end - ptr > 1)
702  {
703  uint len= (uint) (ptr - cur_arg);
704  set_if_smaller(len, FN_REFLEN-1);
705  strmake(key_name, cur_arg, len);
706  return ++ptr;
707  }
708  else
709  {
710  key_name[0]= 0;
711  return cur_arg;
712  }
713 }
714 
715 
725 static my_bool get_bool_argument(const struct my_option *opts,
726  const char *argument,
727  bool *error)
728 {
729  if (!my_strcasecmp(&my_charset_latin1, argument, "true") ||
730  !my_strcasecmp(&my_charset_latin1, argument, "on") ||
731  !my_strcasecmp(&my_charset_latin1, argument, "1"))
732  return 1;
733  else if (!my_strcasecmp(&my_charset_latin1, argument, "false") ||
734  !my_strcasecmp(&my_charset_latin1, argument, "off") ||
735  !my_strcasecmp(&my_charset_latin1, argument, "0"))
736  return 0;
737  else
738  *error= 1;
739  return 0;
740 }
741 
742 /*
743  function: setval
744 
745  Arguments: opts, argument
746  Will set the option value to given value
747 */
748 
749 static int setval(const struct my_option *opts, void *value, char *argument,
750  my_bool set_maximum_value)
751 {
752  int err= 0, res= 0;
753  bool error= 0;
754 
755  if (!argument)
756  argument= enabled_my_option;
757 
758  if (value)
759  {
760  if (set_maximum_value && !(value= opts->u_max_value))
761  {
762  my_getopt_error_reporter(ERROR_LEVEL,
763  "%s: Maximum value of '%s' cannot be set",
764  my_progname, opts->name);
765  return EXIT_NO_PTR_TO_VARIABLE;
766  }
767 
768  switch ((opts->var_type & GET_TYPE_MASK)) {
769  case GET_BOOL: /* If argument differs from 0, enable option, else disable */
770  *((my_bool*) value)= get_bool_argument(opts, argument, &error);
771  if(error)
772  my_getopt_error_reporter(WARNING_LEVEL,
773  "option '%s': boolean value '%s' wasn't recognized. Set to OFF.",
774  opts->name, argument);
775  break;
776  case GET_INT:
777  *((int*) value)= (int) getopt_ll(argument, opts, &err);
778  break;
779  case GET_UINT:
780  *((uint*) value)= (uint) getopt_ull(argument, opts, &err);
781  break;
782  case GET_LONG:
783  *((long*) value)= (long) getopt_ll(argument, opts, &err);
784  break;
785  case GET_ULONG:
786  *((long*) value)= (long) getopt_ull(argument, opts, &err);
787  break;
788  case GET_LL:
789  *((longlong*) value)= getopt_ll(argument, opts, &err);
790  break;
791  case GET_ULL:
792  *((ulonglong*) value)= getopt_ull(argument, opts, &err);
793  break;
794  case GET_DOUBLE:
795  *((double*) value)= getopt_double(argument, opts, &err);
796  break;
797  case GET_STR:
798  case GET_PASSWORD:
799  if (argument == enabled_my_option)
800  break; /* string options don't use this default of "1" */
801  *((char**) value)= argument;
802  break;
803  case GET_STR_ALLOC:
804  if (argument == enabled_my_option)
805  break; /* string options don't use this default of "1" */
806  my_free(*((char**) value));
807  if (!(*((char**) value)= my_strdup(argument, MYF(MY_WME))))
808  {
809  res= EXIT_OUT_OF_MEMORY;
810  goto ret;
811  };
812  break;
813  case GET_ENUM:
814  {
815  int type= find_type(argument, opts->typelib, FIND_TYPE_BASIC);
816  if (type == 0)
817  {
818  /*
819  Accept an integer representation of the enumerated item.
820  */
821  char *endptr;
822  ulong arg= strtoul(argument, &endptr, 10);
823  if (*endptr || arg >= opts->typelib->count)
824  {
825  res= EXIT_ARGUMENT_INVALID;
826  goto ret;
827  }
828  *(ulong*)value= arg;
829  }
830  else if (type < 0)
831  {
832  res= EXIT_AMBIGUOUS_OPTION;
833  goto ret;
834  }
835  else
836  *(ulong*)value= type - 1;
837  }
838  break;
839  case GET_SET:
840  *((ulonglong*)value)= find_typeset(argument, opts->typelib, &err);
841  if (err)
842  {
843  /* Accept an integer representation of the set */
844  char *endptr;
845  ulonglong arg= (ulonglong) strtol(argument, &endptr, 10);
846  if (*endptr || (arg >> 1) >= (1ULL << (opts->typelib->count-1)))
847  {
848  res= EXIT_ARGUMENT_INVALID;
849  goto ret;
850  };
851  *(ulonglong*)value= arg;
852  err= 0;
853  }
854  break;
855  case GET_FLAGSET:
856  {
857  char *error;
858  uint error_len;
859 
860  *((ulonglong*)value)=
861  find_set_from_flags(opts->typelib, opts->typelib->count,
862  *(ulonglong *)value, opts->def_value,
863  argument, strlen(argument),
864  &error, &error_len);
865  if (error)
866  {
867  res= EXIT_ARGUMENT_INVALID;
868  goto ret;
869  };
870  }
871  break;
872  case GET_NO_ARG: /* get_one_option has taken care of the value already */
873  default: /* dummy default to avoid compiler warnings */
874  break;
875  }
876  if (err)
877  {
878  res= EXIT_UNKNOWN_SUFFIX;
879  goto ret;
880  };
881  }
882  return 0;
883 
884 ret:
885  my_getopt_error_reporter(ERROR_LEVEL,
886  "%s: Error while setting value '%s' to '%s'",
887  my_progname, argument, opts->name);
888  return res;
889 }
890 
891 
892 /*
893  Find option
894 
895  SYNOPSIS
896  findopt()
897  optpat Prefix of option to find (with - or _)
898  length Length of optpat
899  opt_res Options
900  ffname Place for pointer to first found name
901 
902  IMPLEMENTATION
903  Go through all options in the my_option struct. Return number
904  of options found that match the pattern and in the argument
905  list the option found, if any. In case of ambiguous option, store
906  the name in ffname argument
907 
908  RETURN
909  0 No matching options
910  # Number of matching options
911  ffname points to first matching option
912 */
913 
914 static int findopt(char *optpat, uint length,
915  const struct my_option **opt_res,
916  const char **ffname)
917 {
918  uint count;
919  const struct my_option *opt= *opt_res;
920  my_bool is_prefix= FALSE;
921 
922  for (count= 0; opt->name; opt++)
923  {
924  if (!getopt_compare_strings(opt->name, optpat, length)) /* match found */
925  {
926  (*opt_res)= opt;
927  if (!opt->name[length]) /* Exact match */
928  return 1;
929 
930  if (!count)
931  {
932  /* We only need to know one prev */
933  count= 1;
934  *ffname= opt->name;
935  if (opt->name[length])
936  is_prefix= TRUE;
937  }
938  else if (strcmp(*ffname, opt->name))
939  {
940  /*
941  The above test is to not count same option twice
942  (see mysql.cc, option "help")
943  */
944  count++;
945  }
946  }
947  }
948  if (is_prefix && count == 1)
949  my_getopt_error_reporter(WARNING_LEVEL,
950  "Using unique option prefix %.*s instead of %s "
951  "is deprecated and will be removed in a future "
952  "release. Please use the full name instead.",
953  length, optpat, *ffname);
954  return count;
955 }
956 
957 
958 /*
959  function: compare_strings
960 
961  Works like strncmp, other than 1.) considers '-' and '_' the same.
962  2.) Returns -1 if strings differ, 0 if they are equal
963 */
964 
965 my_bool getopt_compare_strings(register const char *s, register const char *t,
966  uint length)
967 {
968  char const *end= s + length;
969  for (;s != end ; s++, t++)
970  {
971  if ((*s != '-' ? *s : '_') != (*t != '-' ? *t : '_'))
972  return 1;
973  }
974  return 0;
975 }
976 
977 /*
978  function: eval_num_suffix
979 
980  Transforms a number with a suffix to real number. Suffix can
981  be k|K for kilo, m|M for mega or g|G for giga.
982 */
983 
984 static longlong eval_num_suffix(char *argument, int *error, char *option_name)
985 {
986  char *endchar;
987  longlong num;
988 
989  *error= 0;
990  errno= 0;
991  num= strtoll(argument, &endchar, 10);
992  if (errno == ERANGE)
993  {
994  my_getopt_error_reporter(ERROR_LEVEL,
995  "Incorrect integer value: '%s'", argument);
996  *error= 1;
997  return 0;
998  }
999  if (*endchar == 'k' || *endchar == 'K')
1000  num*= 1024L;
1001  else if (*endchar == 'm' || *endchar == 'M')
1002  num*= 1024L * 1024L;
1003  else if (*endchar == 'g' || *endchar == 'G')
1004  num*= 1024L * 1024L * 1024L;
1005  else if (*endchar)
1006  {
1007  fprintf(stderr,
1008  "Unknown suffix '%c' used for variable '%s' (value '%s')\n",
1009  *endchar, option_name, argument);
1010  *error= 1;
1011  return 0;
1012  }
1013  return num;
1014 }
1015 
1016 /*
1017  function: getopt_ll
1018 
1019  Evaluates and returns the value that user gave as an argument
1020  to a variable. Recognizes (case insensitive) K as KILO, M as MEGA
1021  and G as GIGA bytes. Some values must be in certain blocks, as
1022  defined in the given my_option struct, this function will check
1023  that those values are honored.
1024  In case of an error, set error value in *err.
1025 */
1026 
1027 static longlong getopt_ll(char *arg, const struct my_option *optp, int *err)
1028 {
1029  longlong num=eval_num_suffix(arg, err, (char*) optp->name);
1030  return getopt_ll_limit_value(num, optp, NULL);
1031 }
1032 
1033 
1039 ulonglong max_of_int_range(int var_type)
1040 {
1041  switch (var_type)
1042  {
1043  case GET_INT:
1044  return INT_MAX;
1045  case GET_LONG:
1046  return LONG_MAX;
1047  case GET_LL:
1048  return LONGLONG_MAX;
1049  case GET_UINT:
1050  return UINT_MAX;
1051  case GET_ULONG:
1052  return ULONG_MAX;
1053  case GET_ULL:
1054  return ULONGLONG_MAX;
1055  default:
1056  DBUG_ASSERT(0);
1057  return 0;
1058  }
1059 }
1060 
1061 
1062 /*
1063  function: getopt_ll_limit_value
1064 
1065  Applies min/max/block_size to a numeric value of an option.
1066  Returns "fixed" value.
1067 */
1068 
1069 longlong getopt_ll_limit_value(longlong num, const struct my_option *optp,
1070  my_bool *fix)
1071 {
1072  longlong old= num;
1073  my_bool adjusted= FALSE;
1074  char buf1[255], buf2[255];
1075  ulonglong block_size= (optp->block_size ? (ulonglong) optp->block_size : 1L);
1076  const longlong max_of_type=
1077  (longlong)max_of_int_range(optp->var_type & GET_TYPE_MASK);
1078 
1079  if (num > 0 && ((ulonglong) num > (ulonglong) optp->max_value) &&
1080  optp->max_value) /* if max value is not set -> no upper limit */
1081  {
1082  num= (ulonglong) optp->max_value;
1083  adjusted= TRUE;
1084  }
1085 
1086  if (num > max_of_type)
1087  {
1088  num= max_of_type;
1089  adjusted= TRUE;
1090  }
1091 
1092  num= (num / block_size);
1093  num= (longlong) (num * block_size);
1094 
1095  if (num < optp->min_value)
1096  {
1097  num= optp->min_value;
1098  if (old < optp->min_value)
1099  adjusted= TRUE;
1100  }
1101 
1102  if (fix)
1103  *fix= old != num;
1104  else if (adjusted)
1105  my_getopt_error_reporter(WARNING_LEVEL,
1106  "option '%s': signed value %s adjusted to %s",
1107  optp->name, llstr(old, buf1), llstr(num, buf2));
1108  return num;
1109 }
1110 
1111 /*
1112  function: getopt_ull
1113 
1114  This is the same as getopt_ll, but is meant for unsigned long long
1115  values.
1116 */
1117 
1118 static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err)
1119 {
1120  ulonglong num= eval_num_suffix(arg, err, (char*) optp->name);
1121  return getopt_ull_limit_value(num, optp, NULL);
1122 }
1123 
1124 
1125 ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp,
1126  my_bool *fix)
1127 {
1128  my_bool adjusted= FALSE;
1129  ulonglong old= num;
1130  char buf1[255], buf2[255];
1131  const ulonglong max_of_type=
1132  max_of_int_range(optp->var_type & GET_TYPE_MASK);
1133 
1134  if ((ulonglong) num > (ulonglong) optp->max_value &&
1135  optp->max_value) /* if max value is not set -> no upper limit */
1136  {
1137  num= (ulonglong) optp->max_value;
1138  adjusted= TRUE;
1139  }
1140 
1141  if (num > max_of_type)
1142  {
1143  num= max_of_type;
1144  adjusted= TRUE;
1145  }
1146 
1147  if (optp->block_size > 1)
1148  {
1149  num/= (ulonglong) optp->block_size;
1150  num*= (ulonglong) optp->block_size;
1151  }
1152 
1153  if (num < (ulonglong) optp->min_value)
1154  {
1155  num= (ulonglong) optp->min_value;
1156  if (old < (ulonglong) optp->min_value)
1157  adjusted= TRUE;
1158  }
1159 
1160  if (fix)
1161  *fix= old != num;
1162  else if (adjusted)
1163  my_getopt_error_reporter(WARNING_LEVEL,
1164  "option '%s': unsigned value %s adjusted to %s",
1165  optp->name, ullstr(old, buf1), ullstr(num, buf2));
1166 
1167  return num;
1168 }
1169 
1170 double getopt_double_limit_value(double num, const struct my_option *optp,
1171  my_bool *fix)
1172 {
1173  my_bool adjusted= FALSE;
1174  double old= num;
1175  double min, max;
1176 
1177  max= getopt_ulonglong2double(optp->max_value);
1178  min= getopt_ulonglong2double(optp->min_value);
1179  if (max && num > max)
1180  {
1181  num= max;
1182  adjusted= TRUE;
1183  }
1184  if (num < min)
1185  {
1186  num= min;
1187  adjusted= TRUE;
1188  }
1189  if (fix)
1190  *fix= adjusted;
1191  else if (adjusted)
1192  my_getopt_error_reporter(WARNING_LEVEL,
1193  "option '%s': value %g adjusted to %g",
1194  optp->name, old, num);
1195  return num;
1196 }
1197 
1198 /*
1199  Get double value withing ranges
1200 
1201  Evaluates and returns the value that user gave as an argument to a variable.
1202 
1203  RETURN
1204  decimal value of arg
1205 
1206  In case of an error, prints an error message and sets *err to
1207  EXIT_ARGUMENT_INVALID. Otherwise err is not touched
1208 */
1209 
1210 static double getopt_double(char *arg, const struct my_option *optp, int *err)
1211 {
1212  double num;
1213  int error;
1214  char *end= arg + 1000; /* Big enough as *arg is \0 terminated */
1215  num= my_strtod(arg, &end, &error);
1216  if (end[0] != 0 || error)
1217  {
1218  my_getopt_error_reporter(ERROR_LEVEL,
1219  "Invalid decimal value for option '%s'\n", optp->name);
1220  *err= EXIT_ARGUMENT_INVALID;
1221  return 0.0;
1222  }
1223  return getopt_double_limit_value(num, optp, NULL);
1224 }
1225 
1226 /*
1227  Init one value to it's default values
1228 
1229  SYNOPSIS
1230  init_one_value()
1231  option Option to initialize
1232  value Pointer to variable
1233 */
1234 
1235 static void init_one_value(const struct my_option *option, void *variable,
1236  longlong value)
1237 {
1238  DBUG_ENTER("init_one_value");
1239  switch ((option->var_type & GET_TYPE_MASK)) {
1240  case GET_BOOL:
1241  *((my_bool*) variable)= (my_bool) value;
1242  break;
1243  case GET_INT:
1244  *((int*) variable)= (int) getopt_ll_limit_value((int) value, option, NULL);
1245  break;
1246  case GET_ENUM:
1247  *((ulong*) variable)= (ulong) value;
1248  break;
1249  case GET_UINT:
1250  *((uint*) variable)= (uint) getopt_ull_limit_value((uint) value, option, NULL);
1251  break;
1252  case GET_LONG:
1253  *((long*) variable)= (long) getopt_ll_limit_value((long) value, option, NULL);
1254  break;
1255  case GET_ULONG:
1256  *((ulong*) variable)= (ulong) getopt_ull_limit_value((ulong) value, option, NULL);
1257  break;
1258  case GET_LL:
1259  *((longlong*) variable)= (longlong) getopt_ll_limit_value((longlong) value, option, NULL);
1260  break;
1261  case GET_ULL:
1262  *((ulonglong*) variable)= (ulonglong) getopt_ull_limit_value((ulonglong) value, option, NULL);
1263  break;
1264  case GET_SET:
1265  case GET_FLAGSET:
1266  *((ulonglong*) variable)= (ulonglong) value;
1267  break;
1268  case GET_DOUBLE:
1269  *((double*) variable)= getopt_ulonglong2double(value);
1270  break;
1271  case GET_STR:
1272  case GET_PASSWORD:
1273  /*
1274  Do not clear variable value if it has no default value.
1275  The default value may already be set.
1276  NOTE: To avoid compiler warnings, we first cast longlong to intptr,
1277  so that the value has the same size as a pointer.
1278  */
1279  if ((char*) (intptr) value)
1280  *((char**) variable)= (char*) (intptr) value;
1281  break;
1282  case GET_STR_ALLOC:
1283  /*
1284  Do not clear variable value if it has no default value.
1285  The default value may already be set.
1286  NOTE: To avoid compiler warnings, we first cast longlong to intptr,
1287  so that the value has the same size as a pointer.
1288  */
1289  if ((char*) (intptr) value)
1290  {
1291  char **pstr= (char **) variable;
1292  my_free(*pstr);
1293  *pstr= my_strdup((char*) (intptr) value, MYF(MY_WME));
1294  }
1295  break;
1296  default: /* dummy default to avoid compiler warnings */
1297  break;
1298  }
1299  DBUG_VOID_RETURN;
1300 }
1301 
1302 
1303 /*
1304  Init one value to it's default values
1305 
1306  SYNOPSIS
1307  init_one_value()
1308  option Option to initialize
1309  value Pointer to variable
1310 */
1311 
1312 static void fini_one_value(const struct my_option *option, void *variable,
1313  longlong value __attribute__ ((unused)))
1314 {
1315  DBUG_ENTER("fini_one_value");
1316  switch ((option->var_type & GET_TYPE_MASK)) {
1317  case GET_STR_ALLOC:
1318  my_free(*((char**) variable));
1319  *((char**) variable)= NULL;
1320  break;
1321  default: /* dummy default to avoid compiler warnings */
1322  break;
1323  }
1324  DBUG_VOID_RETURN;
1325 }
1326 
1327 
1328 void my_cleanup_options(const struct my_option *options)
1329 {
1330  init_variables(options, fini_one_value);
1331 }
1332 
1333 
1334 /*
1335  initialize all variables to their default values
1336 
1337  SYNOPSIS
1338  init_variables()
1339  options Array of options
1340 
1341  NOTES
1342  We will initialize the value that is pointed to by options->value.
1343  If the value is of type GET_ASK_ADDR, we will ask for the address
1344  for a value and initialize.
1345 */
1346 
1347 static void init_variables(const struct my_option *options,
1348  init_func_p init_one_value)
1349 {
1350  DBUG_ENTER("init_variables");
1351  for (; options->name; options++)
1352  {
1353  void *value;
1354  DBUG_PRINT("options", ("name: '%s'", options->name));
1355  /*
1356  We must set u_max_value first as for some variables
1357  options->u_max_value == options->value and in this case we want to
1358  set the value to default value.
1359  */
1360  if (options->u_max_value)
1361  init_one_value(options, options->u_max_value, options->max_value);
1362  value= (options->var_type & GET_ASK_ADDR ?
1363  (*getopt_get_addr)("", 0, options, 0) : options->value);
1364  if (value)
1365  init_one_value(options, value, options->def_value);
1366  }
1367  DBUG_VOID_RETURN;
1368 }
1369 
1371 static uint print_name(const struct my_option *optp)
1372 {
1373  const char *s= optp->name;
1374  for (;*s;s++)
1375  putchar(*s == '_' ? '-' : *s);
1376  return s - optp->name;
1377 }
1378 
1379 /*
1380  function: my_print_options
1381 
1382  Print help for all options and variables.
1383 */
1384 
1385 void my_print_help(const struct my_option *options)
1386 {
1387  uint col, name_space= 22, comment_space= 57;
1388  const char *line_end;
1389  const struct my_option *optp;
1390 
1391  for (optp= options; optp->name; optp++)
1392  {
1393  if (optp->id && optp->id < 256)
1394  {
1395  printf(" -%c%s", optp->id, strlen(optp->name) ? ", " : " ");
1396  col= 6;
1397  }
1398  else
1399  {
1400  printf(" ");
1401  col= 2;
1402  }
1403  if (strlen(optp->name))
1404  {
1405  printf("--");
1406  col+= 2 + print_name(optp);
1407  if (optp->arg_type == NO_ARG ||
1408  (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
1409  {
1410  putchar(' ');
1411  col++;
1412  }
1413  else if ((optp->var_type & GET_TYPE_MASK) == GET_STR ||
1414  (optp->var_type & GET_TYPE_MASK) == GET_PASSWORD ||
1415  (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC ||
1416  (optp->var_type & GET_TYPE_MASK) == GET_ENUM ||
1417  (optp->var_type & GET_TYPE_MASK) == GET_SET ||
1418  (optp->var_type & GET_TYPE_MASK) == GET_FLAGSET )
1419  {
1420  printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "",
1421  optp->arg_type == OPT_ARG ? "]" : "");
1422  col+= (optp->arg_type == OPT_ARG) ? 8 : 6;
1423  }
1424  else
1425  {
1426  printf("%s=#%s ", optp->arg_type == OPT_ARG ? "[" : "",
1427  optp->arg_type == OPT_ARG ? "]" : "");
1428  col+= (optp->arg_type == OPT_ARG) ? 5 : 3;
1429  }
1430  if (col > name_space && optp->comment && *optp->comment)
1431  {
1432  putchar('\n');
1433  col= 0;
1434  }
1435  }
1436  for (; col < name_space; col++)
1437  putchar(' ');
1438  if (optp->comment && *optp->comment)
1439  {
1440  const char *comment= optp->comment, *end= strend(comment);
1441 
1442  while ((uint) (end - comment) > comment_space)
1443  {
1444  for (line_end= comment + comment_space; *line_end != ' '; line_end--)
1445  {}
1446  for (; comment != line_end; comment++)
1447  putchar(*comment);
1448  comment++; /* skip the space, as a newline will take it's place now */
1449  putchar('\n');
1450  for (col= 0; col < name_space; col++)
1451  putchar(' ');
1452  }
1453  printf("%s", comment);
1454  }
1455  putchar('\n');
1456  if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL)
1457  {
1458  if (optp->def_value != 0)
1459  {
1460  printf("%*s(Defaults to on; use --skip-", name_space, "");
1461  print_name(optp);
1462  printf(" to disable.)\n");
1463  }
1464  }
1465  }
1466 }
1467 
1468 
1469 /*
1470  function: my_print_options
1471 
1472  Print variables.
1473 */
1474 
1475 void my_print_variables(const struct my_option *options)
1476 {
1477  uint name_space= 34, length, nr;
1478  ulonglong llvalue;
1479  char buff[255];
1480  const struct my_option *optp;
1481 
1482  for (optp= options; optp->name; optp++)
1483  {
1484  length= strlen(optp->name)+1;
1485  if (length > name_space)
1486  name_space= length;
1487  }
1488 
1489  printf("\nVariables (--variable-name=value)\n");
1490  printf("%-*s%s", name_space, "and boolean options {FALSE|TRUE}",
1491  "Value (after reading options)\n");
1492  for (length=1; length < 75; length++)
1493  putchar(length == name_space ? ' ' : '-');
1494  putchar('\n');
1495 
1496  for (optp= options; optp->name; optp++)
1497  {
1498  void *value= (optp->var_type & GET_ASK_ADDR ?
1499  (*getopt_get_addr)("", 0, optp, 0) : optp->value);
1500  if (value)
1501  {
1502  length= print_name(optp);
1503  for (; length < name_space; length++)
1504  putchar(' ');
1505  switch ((optp->var_type & GET_TYPE_MASK)) {
1506  case GET_SET:
1507  if (!(llvalue= *(ulonglong*) value))
1508  printf("%s\n", "");
1509  else
1510  for (nr= 0; llvalue && nr < optp->typelib->count; nr++, llvalue >>=1)
1511  {
1512  if (llvalue & 1)
1513  printf( llvalue > 1 ? "%s," : "%s\n", get_type(optp->typelib, nr));
1514  }
1515  break;
1516  case GET_FLAGSET:
1517  llvalue= *(ulonglong*) value;
1518  for (nr= 0; llvalue && nr < optp->typelib->count; nr++, llvalue >>=1)
1519  {
1520  printf("%s%s=", (nr ? "," : ""), get_type(optp->typelib, nr));
1521  printf(llvalue & 1 ? "on" : "off");
1522  }
1523  printf("\n");
1524  break;
1525  case GET_ENUM:
1526  printf("%s\n", get_type(optp->typelib, *(ulong*) value));
1527  break;
1528  case GET_STR:
1529  case GET_PASSWORD:
1530  case GET_STR_ALLOC: /* fall through */
1531  printf("%s\n", *((char**) value) ? *((char**) value) :
1532  "(No default value)");
1533  break;
1534  case GET_BOOL:
1535  printf("%s\n", *((my_bool*) value) ? "TRUE" : "FALSE");
1536  break;
1537  case GET_INT:
1538  printf("%d\n", *((int*) value));
1539  break;
1540  case GET_UINT:
1541  printf("%d\n", *((uint*) value));
1542  break;
1543  case GET_LONG:
1544  printf("%ld\n", *((long*) value));
1545  break;
1546  case GET_ULONG:
1547  printf("%lu\n", *((ulong*) value));
1548  break;
1549  case GET_LL:
1550  printf("%s\n", llstr(*((longlong*) value), buff));
1551  break;
1552  case GET_ULL:
1553  longlong2str(*((ulonglong*) value), buff, 10);
1554  printf("%s\n", buff);
1555  break;
1556  case GET_DOUBLE:
1557  printf("%g\n", *(double*) value);
1558  break;
1559  case GET_NO_ARG:
1560  printf("(No default value)\n");
1561  break;
1562  default:
1563  printf("(Disabled)\n");
1564  break;
1565  }
1566  }
1567  }
1568 }