diff --git a/include/my_getopt.h b/include/my_getopt.h
index 3b4551b445e5837a295445d8dccdf1500203f0e5..213c8c3570ee2cf1d05a0195875e375ba10f4d0b 100644
--- a/include/my_getopt.h
+++ b/include/my_getopt.h
@@ -17,7 +17,12 @@
 C_MODE_START
 
 enum get_opt_var_type { GET_NO_ARG, GET_BOOL, GET_INT, GET_UINT, GET_LONG,
-			GET_ULONG, GET_LL, GET_ULL, GET_STR, GET_STR_ALLOC };
+			GET_ULONG, GET_LL, GET_ULL, GET_STR, GET_STR_ALLOC
+                      };
+
+#define GET_ASK_ADDR	128
+#define GET_TYPE_MASK	127
+
 enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG };
 
 struct my_option
@@ -48,6 +53,8 @@ extern int handle_options (int *argc, char ***argv,
 						     char *));
 extern void my_print_help(const struct my_option *options);
 extern void my_print_variables(const struct my_option *options);
+extern void my_getopt_register_get_addr(gptr* (*func_addr)(char *, uint,
+							   const struct my_option *));
 
 ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp);
 my_bool getopt_compare_strings(const char *s, const char *t, uint length);
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index 759c96462f6249249fd625115818ed8fa3d71594..07f4f306198ffebf3803a3c10ad49e2d11aa8e2a 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -34,6 +34,7 @@ static ulonglong getopt_ull(char *arg, const struct my_option *optp,
 static void init_variables(const struct my_option *options);
 static int setval(const struct my_option *opts, char *argument,
 		  my_bool set_maximum_value);
+static char *check_struct_option(char *cur_arg, char *key_name);
 
 /*
   The following three variables belong to same group and the number and
@@ -67,6 +68,14 @@ my_bool my_getopt_print_errors= 1;
   one. Call function 'get_one_option()' once for each option.
 */
 
+static gptr* (*getopt_get_addr)(char *, uint, const struct my_option *);
+
+void my_getopt_register_get_addr(gptr* (*func_addr)(char *, uint,
+						    const struct my_option *))
+{
+  getopt_get_addr= func_addr;
+}
+
 int handle_options(int *argc, char ***argv, 
 		   const struct my_option *longopts, 
 		   my_bool (*get_one_option)(int,
@@ -76,8 +85,10 @@ int handle_options(int *argc, char ***argv,
   uint opt_found, argvpos= 0, length, i;
   my_bool end_of_options= 0, must_be_var, set_maximum_value, special_used,
           option_is_loose;
-  char *progname= *(*argv), **pos, **pos_end, *optend, *prev_found;
+  char **pos, **pos_end, *optend, *prev_found,
+       *opt_str, key_name[FN_REFLEN];
   const struct my_option *optp;
+  gptr *value;
   int error;
 
   LINT_INIT(opt_found);
@@ -110,7 +121,7 @@ int handle_options(int *argc, char ***argv,
 	    {
 	      if (my_getopt_print_errors)
 		fprintf(stderr, "%s: Option '-O' requires an argument\n",
-			progname);
+			my_progname);
 	      return EXIT_ARGUMENT_REQUIRED;
 	    }
 	    cur_arg= *pos;
@@ -128,7 +139,7 @@ int handle_options(int *argc, char ***argv,
 	      if (my_getopt_print_errors)
 		fprintf(stderr,
 			"%s: Option '--set-variable' requires an argument\n",
-			progname);
+			my_progname);
 	      return EXIT_ARGUMENT_REQUIRED;
 	    }
 	  }
@@ -142,7 +153,7 @@ int handle_options(int *argc, char ***argv,
 	      if (my_getopt_print_errors)
 		fprintf(stderr,
 			"%s: Option '--set-variable' requires an argument\n",
-			progname);
+			my_progname);
 	      return EXIT_ARGUMENT_REQUIRED;
 	    }
 	    cur_arg= *pos;
@@ -159,19 +170,20 @@ int handle_options(int *argc, char ***argv,
 	    continue;
 	  }
 	}
-	optend= strcend(cur_arg, '=');
-	length= optend - cur_arg;
+	opt_str= check_struct_option(cur_arg, key_name);
+	optend= strcend(opt_str, '=');
+	length= optend - opt_str;
 	if (*optend == '=')
 	  optend++;
 	else
-	  optend=0;
+	  optend= 0;
 
 	/*
 	  Find first the right option. Return error in case of an ambiguous,
 	  or unknown option
 	*/
 	optp= longopts;
-	if (!(opt_found= findopt(cur_arg, length, &optp, &prev_found)))
+	if (!(opt_found= findopt(opt_str, length, &optp, &prev_found)))
 	{
 	  /*
 	    Didn't find any matching option. Let's see if someone called
@@ -183,18 +195,18 @@ int handle_options(int *argc, char ***argv,
 	      must_be_var= 1; /* option is followed by an argument */
 	    for (i= 0; special_opt_prefix[i]; i++)
 	    {
-	      if (!getopt_compare_strings(special_opt_prefix[i], cur_arg,
+	      if (!getopt_compare_strings(special_opt_prefix[i], opt_str,
 					  special_opt_prefix_lengths[i]) &&
-		  cur_arg[special_opt_prefix_lengths[i]] == '-')
+		  opt_str[special_opt_prefix_lengths[i]] == '-')
 	      {
 		/*
 		  We were called with a special prefix, we can reuse opt_found
 		*/
 		special_used= 1;
-		cur_arg+= (special_opt_prefix_lengths[i] + 1);
+		opt_str+= (special_opt_prefix_lengths[i] + 1);
 		if (i == OPT_LOOSE)
 		  option_is_loose= 1;
-		if ((opt_found= findopt(cur_arg, length -
+		if ((opt_found= findopt(opt_str, length -
 					(special_opt_prefix_lengths[i] + 1),
 					&optp, &prev_found)))
 		{
@@ -203,7 +215,7 @@ int handle_options(int *argc, char ***argv,
 		    if (my_getopt_print_errors)
 		      fprintf(stderr,
 			      "%s: ambiguous option '--%s-%s' (--%s-%s)\n",
-			      progname, special_opt_prefix[i], cur_arg,
+			      my_progname, special_opt_prefix[i], opt_str,
 			      special_opt_prefix[i], prev_found);
 		    return EXIT_AMBIGUOUS_OPTION;
 		  }
@@ -237,8 +249,8 @@ int handle_options(int *argc, char ***argv,
 	    {
 	      if (my_getopt_print_errors)
 		fprintf(stderr,
-			"%s: %s: unknown variable '%s'\n", progname,
-			option_is_loose ? "WARNING" : "ERROR", cur_arg);
+			"%s: %s: unknown variable '%s'\n", my_progname,
+			option_is_loose ? "WARNING" : "ERROR", opt_str);
 	      if (!option_is_loose)
 		return EXIT_UNKNOWN_VARIABLE;
 	    }
@@ -246,8 +258,8 @@ int handle_options(int *argc, char ***argv,
 	    {
 	      if (my_getopt_print_errors)
 		fprintf(stderr,
-			"%s: %s: unknown option '--%s'\n", progname,
-			option_is_loose ? "WARNING" : "ERROR", cur_arg);
+			"%s: %s: unknown option '--%s'\n", my_progname,
+			option_is_loose ? "WARNING" : "ERROR", opt_str);
 	      if (!option_is_loose)
 		return EXIT_UNKNOWN_OPTION;
 	    }
@@ -264,57 +276,61 @@ int handle_options(int *argc, char ***argv,
 	  {
 	    if (my_getopt_print_errors)
 	      fprintf(stderr, "%s: variable prefix '%s' is not unique\n",
-		      progname, cur_arg);
+		      my_progname, opt_str);
 	    return EXIT_VAR_PREFIX_NOT_UNIQUE;
 	  }
 	  else
 	  {
 	    if (my_getopt_print_errors)
 	      fprintf(stderr, "%s: ambiguous option '--%s' (%s, %s)\n",
-		      progname, cur_arg, prev_found, optp->name);
+		      my_progname, opt_str, prev_found, optp->name);
 	    return EXIT_AMBIGUOUS_OPTION;
 	  }
 	}
-	if (must_be_var && optp->var_type == GET_NO_ARG)
+	if (must_be_var && (optp->var_type & GET_TYPE_MASK) == GET_NO_ARG)
 	{
 	  if (my_getopt_print_errors)
 	    fprintf(stderr, "%s: option '%s' cannot take an argument\n",
-		    progname, optp->name);
+		    my_progname, optp->name);
 	  return EXIT_NO_ARGUMENT_ALLOWED;
 	}
+	value= optp->var_type & GET_ASK_ADDR ?
+	  (*getopt_get_addr)(key_name, strlen(key_name), optp) : optp->value;
+  
 	if (optp->arg_type == NO_ARG)
 	{
-	  if (optend && optp->var_type != GET_BOOL)
+	  if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL)
 	  {
 	    if (my_getopt_print_errors)
 	      fprintf(stderr, "%s: option '--%s' cannot take an argument\n",
-		      progname, optp->name);
+		      my_progname, optp->name);
 	    return EXIT_NO_ARGUMENT_ALLOWED;
 	  }
-	  if (optp->var_type == GET_BOOL)
+	  if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL)
 	  {
 	    /*
 	      Set bool to 1 if no argument or if the user has used
 	      --enable-'option-name'.
 	      *optend was set to '0' if one used --disable-option
 	      */
-	    *((my_bool*) optp->value)= 	(my_bool) (!optend || *optend == '1');
+	    *((my_bool*) value)= (my_bool) (!optend || *optend == '1');
 	    (*argc)--;	    
 	    get_one_option(optp->id, optp, argument);
 	    continue;
 	  }
 	  argument= optend;
 	}
-	else if (optp->arg_type == OPT_ARG && optp->var_type == GET_BOOL)
+	else if (optp->arg_type == OPT_ARG &&
+		 (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
 	{
 	  if (optend == disabled_my_option)
-	    *((my_bool*) optp->value)= (my_bool) 0;
+	    *((my_bool*) value)= (my_bool) 0;
 	  else
 	  {
 	    if (!optend) /* No argument -> enable option */
-	      *((my_bool*) optp->value)= (my_bool) 1;
+	      *((my_bool*) value)= (my_bool) 1;
 	    else /* If argument differs from 0, enable option, else disable */
-	      *((my_bool*) optp->value)= (my_bool) atoi(optend) != 0;
+	      *((my_bool*) value)= (my_bool) atoi(optend) != 0;
 	  }
 	  (*argc)--;	    
 	  continue;
@@ -326,7 +342,7 @@ int handle_options(int *argc, char ***argv,
 	  {
 	    if (my_getopt_print_errors)
 	      fprintf(stderr, "%s: option '--%s' requires an argument\n",
-		      progname, optp->name);
+		      my_progname, optp->name);
 	    return EXIT_ARGUMENT_REQUIRED;
 	  }
 	  argument= *pos;
@@ -346,7 +362,8 @@ int handle_options(int *argc, char ***argv,
 	    {
 	      /* Option recognized. Find next what to do with it */
 	      opt_found= 1;
-	      if (optp->var_type == GET_BOOL && optp->arg_type == NO_ARG)
+	      if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL &&
+		  optp->arg_type == NO_ARG)
 	      {
 		*((my_bool*) optp->value)= (my_bool) 1;
 		get_one_option(optp->id, optp, argument);
@@ -370,7 +387,7 @@ int handle_options(int *argc, char ***argv,
 		    if (my_getopt_print_errors)
 		      fprintf(stderr,
 			      "%s: option '-%c' requires an argument\n",
-			      progname, optp->id);
+			      my_progname, optp->id);
 		    return EXIT_ARGUMENT_REQUIRED;
 		  }
 		  argument= *pos;
@@ -382,7 +399,7 @@ int handle_options(int *argc, char ***argv,
 	      {
 		fprintf(stderr,
 			"%s: Error while setting value '%s' to '%s'\n",
-			progname, argument, optp->name);
+			my_progname, argument, optp->name);
 		return error;
 	      }
 	      get_one_option(optp->id, optp, argument);
@@ -393,7 +410,7 @@ int handle_options(int *argc, char ***argv,
 	  {
 	    if (my_getopt_print_errors)
 	      fprintf(stderr,
-		      "%s: unknown option '-%c'\n", progname, *optend);
+		      "%s: unknown option '-%c'\n", my_progname, *optend);
 	    return EXIT_UNKNOWN_OPTION;
 	  }
 	}
@@ -404,7 +421,7 @@ int handle_options(int *argc, char ***argv,
       {
 	fprintf(stderr,
 		"%s: Error while setting value '%s' to '%s'\n",
-		progname, argument, optp->name);
+		my_progname, argument, optp->name);
 	return error;
       }
       get_one_option(optp->id, optp, argument);
@@ -424,6 +441,47 @@ int handle_options(int *argc, char ***argv,
   return 0;
 }
 
+
+/*
+  function: check_struct_option
+
+  Arguments: Current argument under processing from argv and a variable
+  where to store the possible key name.
+
+  Return value: In case option is a struct option, returns a pointer to
+  the current argument at the position where the struct option (key_name)
+  ends, the next character after the dot. In case argument is not a struct
+  option, returns a pointer to the argument.
+
+  key_name will hold the name of the key, or 0 if not found.
+*/
+
+static char *check_struct_option(char *cur_arg, char *key_name)
+{
+  char *ptr, *ptr2;
+
+  ptr= strcend(cur_arg, '.');
+  ptr2= strcend(cur_arg, '=');
+
+  /* 
+     Minimum length for a struct option is 3 (--a.b)
+     If the (first) dot is after an equal sign, then it is part
+     of a variable value and the option is not a struct option.
+  */
+  if (strlen(ptr) >= 3 && ptr2 - ptr > 0)
+  {
+    uint len= ptr - cur_arg;
+    strnmov(key_name, cur_arg, len);
+    key_name[len]= '\0';
+    return ++ptr;
+  }
+  else
+  {
+    key_name= 0;
+    return cur_arg;
+  }
+}
+
 /*
   function: setval
 
@@ -444,7 +502,7 @@ static int setval(const struct my_option *opts, char *argument,
     if (!result_pos)
       return EXIT_NO_PTR_TO_VARIABLE;
 
-    switch (opts->var_type) {
+    switch ((opts->var_type & GET_TYPE_MASK)) {
     case GET_INT:
     case GET_UINT:           /* fall through */
       *((int*) result_pos)= (int) getopt_ll(argument, opts, &err);
@@ -634,7 +692,7 @@ static void init_variables(const struct my_option *options)
   {
     if (options->value)
     {
-      switch (options->var_type) {
+      switch ((options->var_type & GET_TYPE_MASK)) {
       case GET_BOOL:
 	if (options->u_max_value)
 	  *((my_bool*) options->u_max_value)= (my_bool) options->max_value;
@@ -706,13 +764,15 @@ void my_print_help(const struct my_option *options)
     {
       printf("--%s", optp->name);
       col+= 2 + strlen(optp->name);
-      if (optp->var_type == GET_STR || optp->var_type == GET_STR_ALLOC)
+      if ((optp->var_type & GET_TYPE_MASK) == GET_STR ||
+	  (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC)
       {
 	printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "",
 	       optp->arg_type == OPT_ARG ? "]" : "");
 	col+= (optp->arg_type == OPT_ARG) ? 8 : 6;
       }
-      else if (optp->var_type == GET_NO_ARG || optp->var_type == GET_BOOL)
+      else if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG ||
+	       (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
       {
 	putchar(' ');
 	col++;
@@ -775,7 +835,7 @@ void my_print_variables(const struct my_option *options)
       length= strlen(optp->name);
       for (; length < name_space; length++)
 	putchar(' ');
-      switch (optp->var_type) {
+      switch ((optp->var_type & GET_TYPE_MASK)) {
       case GET_STR:
       case GET_STR_ALLOC:                    /* fall through */
 	printf("%s\n", *((char**) optp->value) ? *((char**) optp->value) :
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 68fa0cca2d56af2838a37f08fa390db417d69b56..72ee3e30c639e43a19f242d58a6f932f7fca8c33 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -4092,7 +4092,8 @@ replicating a LOAD DATA INFILE command.",
    IO_SIZE, 0},
   {"key_buffer_size", OPT_KEY_BUFFER_SIZE,
    "The size of the buffer used for index blocks. Increase this to get better index handling (for all reads and multiple writes) to as much as you can afford; 64M on a 256M machine that mainly runs MySQL is quite common.",
-   (gptr*) &keybuff_size, (gptr*) &keybuff_size, 0, GET_ULL,
+   (gptr*) &keybuff_size, (gptr*) &keybuff_size, 0,
+   (enum get_opt_var_type) (GET_ULL | GET_ASK_ADDR),
    REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD,
    IO_SIZE, 0},
   {"long_query_time", OPT_LONG_QUERY_TIME,
@@ -5298,10 +5299,19 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
 }
 	/* Initiates DEBUG - but no debugging here ! */
 
+
+extern "C" gptr *
+mysql_getopt_value(char *keyname, uint key_length,
+		   const struct my_option *option)
+{
+  return option->value;
+}
+
 static void get_options(int argc,char **argv)
 {
   int ho_error;
 
+  my_getopt_register_get_addr(mysql_getopt_value);
   if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
     exit(ho_error);
   if (argc > 0)