static int execute_commands()

in client/mysqladmin.cc [663:1219]


static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
  const char *status;
  /*
    MySQL documentation relies on the fact that mysqladmin will
    execute commands in the order specified, e.g.
    mysqladmin -u root flush-privileges password "newpassword"
    to reset a lost root password.
    If this behaviour is ever changed, Docs should be notified.
  */

  struct rand_struct rand_st;

  for (; argc > 0 ; argv++,argc--)
  {
    int option;
    bool log_warnings= true;
    switch (option= find_type(argv[0], &command_typelib, FIND_TYPE_BASIC)) {
    case ADMIN_CREATE:
    {
      char buff[FN_REFLEN+20];
      if (argc < 2)
      {
	my_printf_error(0, "Too few arguments to create", error_flags);
	return 1;
      }
      sprintf(buff,"create database `%.*s`",FN_REFLEN,argv[1]);
      if (mysql_query(mysql,buff))
      {
	my_printf_error(0,"CREATE DATABASE failed; error: '%-.200s'",
			error_flags, mysql_error(mysql));
	return -1;
      }
      argc--; argv++;
      break;
    }
    case ADMIN_DROP:
    {
      if (argc < 2)
      {
	my_printf_error(0, "Too few arguments to drop", error_flags);
	return 1;
      }
      if (drop_db(mysql,argv[1]))
	return -1;
      argc--; argv++;
      break;
    }
    case ADMIN_SHUTDOWN:
    {
      char pidfile[FN_REFLEN];
      bool got_pidfile= 0;
      time_t last_modified= 0;
      struct stat pidfile_status;

      /*
	Only wait for pidfile on local connections
	If pidfile doesn't exist, continue without pid file checking
      */
      if (mysql->unix_socket && (got_pidfile= !get_pidfile(mysql, pidfile)) &&
	  !stat(pidfile, &pidfile_status))
	last_modified= pidfile_status.st_mtime;

      if(mysql_query(mysql, "shutdown"))
      {
        my_printf_error(0, "shutdown failed; error: '%s'", error_flags,
        mysql_error(mysql));
        return -1;
      }

      argc=1;                   /* force SHUTDOWN to be the last command    */
      if (got_pidfile)
      {
	if (opt_verbose)
	  printf("Shutdown signal sent to server;  Waiting for pid file to disappear\n");

	/* Wait until pid file is gone */
	if (wait_pidfile(pidfile, last_modified, &pidfile_status))
	  return -1;
      }
      /* Do not try to print warning as server has gone away */
      log_warnings= false;
      break;
    }
    case ADMIN_FLUSH_PRIVILEGES:
    case ADMIN_RELOAD:
      if (mysql_query(mysql,"flush privileges"))
      {
	my_printf_error(0, "reload failed; error: '%s'", error_flags,
			mysql_error(mysql));
	return -1;
      }
      break;
    case ADMIN_REFRESH:
      if (mysql_refresh(mysql,
			(uint) ~(REFRESH_GRANT | REFRESH_STATUS |
				 REFRESH_READ_LOCK | REFRESH_SLAVE |
				 REFRESH_MASTER)))
      {
	my_printf_error(0, "refresh failed; error: '%s'", error_flags,
			mysql_error(mysql));
	return -1;
      }
      break;
    case ADMIN_FLUSH_THREADS:
      if (mysql_refresh(mysql,(uint) REFRESH_THREADS))
      {
	my_printf_error(0, "refresh failed; error: '%s'", error_flags,
			mysql_error(mysql));
	return -1;
      }
      break;
    case ADMIN_VER:
      new_line=1;
      print_version();
      puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
      printf("Server version\t\t%s\n", mysql_get_server_info(mysql));
      printf("Protocol version\t%d\n", mysql_get_proto_info(mysql));
      printf("Connection\t\t%s\n",mysql_get_host_info(mysql));
      if (mysql->unix_socket)
	printf("UNIX socket\t\t%s\n", mysql->unix_socket);
      else
	printf("TCP port\t\t%d\n", mysql->port);
      status=mysql_stat(mysql);
      {
	char *pos,buff[40];
	ulong sec;
	pos= (char*) strchr(status,' ');
	*pos++=0;
	printf("%s\t\t\t",status);			/* print label */
	if ((status=str2int(pos,10,0,LONG_MAX,(long*) &sec)))
	{
	  nice_time(sec,buff);
	  puts(buff);				/* print nice time */
	  while (*status == ' ') status++;	/* to next info */
	}
      }
      putc('\n',stdout);
      if (status)
	puts(status);
      break;
    case ADMIN_PROCESSLIST:
    {
      MYSQL_RES *result;
      MYSQL_ROW row;

      if (mysql_query(mysql, (opt_verbose ? "show full processlist" :
			      "show processlist")) ||
	  !(result = mysql_store_result(mysql)))
      {
	my_printf_error(0, "process list failed; error: '%s'", error_flags,
			mysql_error(mysql));
	return -1;
      }
      print_header(result);
      while ((row=mysql_fetch_row(result)))
	print_row(result,row,0);
      print_top(result);
      mysql_free_result(result);
      new_line=1;
      break;
    }
    case ADMIN_STATUS:
      status=mysql_stat(mysql);
      if (status)
	puts(status);
      break;
    case ADMIN_KILL:
      {
	uint error=0;
	char *pos;
	if (argc < 2)
	{
	  my_printf_error(0, "Too few arguments to 'kill'", error_flags);
	  return 1;
	}
	pos=argv[1];
	for (;;)
	{
          /* We don't use mysql_kill(), since it only handles 32-bit IDs. */
          char buff[26], *out; /* "KILL " + max 20 digs + NUL */
          out= strxmov(buff, "KILL ", NullS);
          ullstr(my_strtoull(pos, NULL, 0), out);

          if (mysql_query(mysql, buff))
	  {
            /* out still points to just the number */
	    my_printf_error(0, "kill failed on %s; error: '%s'", error_flags,
			    out, mysql_error(mysql));
	    error=1;
	  }
	  if (!(pos=strchr(pos,',')))
	    break;
	  pos++;
	}
	argc--; argv++;
	if (error)
	  return -1;
	break;
      }
    case ADMIN_DEBUG:
      if (mysql_dump_debug_info(mysql))
      {
	my_printf_error(0, "debug failed; error: '%s'", error_flags,
			mysql_error(mysql));
	return -1;
      }
      break;
    case ADMIN_VARIABLES:
    {
      MYSQL_RES *res;
      MYSQL_ROW row;

      new_line=1;
      if (mysql_query(mysql,"show /*!40003 GLOBAL */ variables") ||
	  !(res=mysql_store_result(mysql)))
      {
	my_printf_error(0, "unable to show variables; error: '%s'", error_flags,
			mysql_error(mysql));
	return -1;
      }
      print_header(res);
      while ((row=mysql_fetch_row(res)))
	print_row(res,row,0);
      print_top(res);
      mysql_free_result(res);
      break;
    }
    case ADMIN_EXTENDED_STATUS:
    {
      MYSQL_RES *res;
      MYSQL_ROW row;
      uint rownr = 0;
      void (*func) (MYSQL_RES*, MYSQL_ROW, uint);

      new_line = 1;
      if (mysql_query(mysql, "show /*!50002 GLOBAL */ status") ||
	  !(res = mysql_store_result(mysql)))
      {
	my_printf_error(0, "unable to show status; error: '%s'", error_flags,
			mysql_error(mysql));
	return -1;
      }

      DBUG_ASSERT(mysql_num_rows(res) < MAX_MYSQL_VAR);

      if (!opt_vertical)
	print_header(res);
      else
      {
	if (!ex_status_printed)
	{
	  store_values(res);
	  truncate_names();   /* Does some printing also */
	}
	else
	{
	  print_relative_line();
	  print_relative_header();
	  print_relative_line();
	}
      }

      /*      void (*func) (MYSQL_RES*, MYSQL_ROW, uint); */
      if (opt_relative && !opt_vertical)
	func = print_relative_row;
      else if (opt_vertical)
	func = print_relative_row_vert;
      else
	func = print_row;

      while ((row = mysql_fetch_row(res)))
	(*func)(res, row, rownr++);
      if (opt_vertical)
      {
	if (ex_status_printed)
	{
	  putchar('\n');
	  print_relative_line();
	}
      }
      else
	print_top(res);

      ex_status_printed = 1; /* From now on the output will be relative */
      mysql_free_result(res);
      break;
    }
    case ADMIN_FLUSH_LOGS:
    {
      std::string command;
      if (argc > 1)
      {
        bool first_arg= true;
        for (command= "FLUSH "; argc > 1; argc--, argv++)
        {
          if (!first_arg)
            command+= ",";

          if (!my_strcasecmp(&my_charset_latin1, argv[1], "binary"))
            command+= " BINARY LOGS";
          else if (!my_strcasecmp(&my_charset_latin1, argv[1], "engine"))
            command+= " ENGINE LOGS";
          else if (!my_strcasecmp(&my_charset_latin1, argv[1], "error"))
            command+= " ERROR LOGS";
          else if (!my_strcasecmp(&my_charset_latin1, argv[1], "general"))
            command+= " GENERAL LOGS";
          else if (!my_strcasecmp(&my_charset_latin1, argv[1], "relay"))
            command+= " RELAY LOGS";
          else if (!my_strcasecmp(&my_charset_latin1, argv[1], "slow"))
            command+= " SLOW LOGS";
          else
          {
            /*
              Not a valid log type, assume it's the next command.
              Remove the trailing comma if any of the log types is specified
              or flush all if no specific log type is specified.
            */
            if (!first_arg)
              command.resize(command.size() - 1);
            else
              command= "FLUSH LOGS";
            break;
          }

          if (first_arg)
            first_arg= false;
        }
      }
      else
        command= "FLUSH LOGS";
      if (mysql_query(mysql, command.c_str()))
      {
	my_printf_error(0, "refresh failed; error: '%s'", error_flags,
			mysql_error(mysql));
	return -1;
      }
      break;
    }
    case ADMIN_FLUSH_HOSTS:
    {
      if (mysql_query(mysql,"flush hosts"))
      {
	my_printf_error(0, "refresh failed; error: '%s'", error_flags,
			mysql_error(mysql));
	return -1;
      }
      break;
    }
    case ADMIN_FLUSH_TABLES:
    {
      if (mysql_query(mysql,"flush tables"))
      {
	my_printf_error(0, "refresh failed; error: '%s'", error_flags,
			mysql_error(mysql));
	return -1;
      }
      break;
    }
    case ADMIN_FLUSH_STATUS:
    {
      if (mysql_query(mysql,"flush status"))
      {
	my_printf_error(0, "refresh failed; error: '%s'", error_flags,
			mysql_error(mysql));
	return -1;
      }
      break;
    }
    case ADMIN_PASSWORD:
    {
      char buff[128];
      time_t start_time;
      char *typed_password= NULL, *verified= NULL, *tmp= NULL;
      bool log_off= true, err= false;
      size_t password_len;

      /* Do initialization the same way as we do in mysqld */
      start_time=time((time_t*) 0);
      randominit(&rand_st,(ulong) start_time,(ulong) start_time/2);

      if (argc < 1)
      {
	my_printf_error(0, "Too few arguments to change password", error_flags);
	return 1;
      }
      else if (argc == 1)
      {
        /* prompt for password */
        typed_password= get_tty_password("New password: ");
        verified= get_tty_password("Confirm new password: ");
        if (strcmp(typed_password, verified) != 0)
        {
          my_printf_error(0,"Passwords don't match",MYF(ME_BELL));
          err= true;
          goto error;
        }
        /* escape quotes if password has any special characters */
        password_len= strlen(typed_password);
        tmp= (char*) my_malloc(PSI_NOT_INSTRUMENTED, password_len*2+1, MYF(MY_WME));
        mysql_real_escape_string(mysql, tmp, typed_password, (ulong)password_len);
        typed_password= tmp;
      }
      else
      {
        print_cmdline_password_warning();
        typed_password= argv[1];
      }

      if (typed_password[0])
      {
#ifdef _WIN32
        size_t pw_len= strlen(typed_password);
        if (pw_len > 1 && typed_password[0] == '\'' &&
            typed_password[pw_len-1] == '\'')
          printf("Warning: single quotes were not trimmed from the password by"
                 " your command\nline client, as you might have expected.\n");
#endif
        /* turn logging off if we can */
        if (mysql_query(mysql, "set sql_log_off=1"))
        {
          if (opt_verbose)
            fprintf(stderr, "Note: Can't turn off logging; '%s'", mysql_error(mysql));
          log_off= false;
        }

        /*
          In case the password_expired flag is set ('Y'), then there is no way
          to determine the password format. So, assume that setting the
          password using the server's default authentication format
          (mysql_native_password) will work.
          TODO: make sure this always uses SSL and then let the server
          calculate the scramble.
        */
      }

      /* Warn about password being set in non ssl connection */
#if defined(HAVE_OPENSSL)
      {
        uint ssl_mode= 0;
        if (!mysql_get_option(mysql, MYSQL_OPT_SSL_MODE, &ssl_mode) &&
            ssl_mode <= SSL_MODE_PREFERRED)
        {
          fprintf(stderr, "Warning: Since password will be sent to server in "
                  "plain text, use ssl connection to ensure password safety.\n");
        }
      }
#endif
      memset(buff, 0, sizeof(buff));
      sprintf(buff, "ALTER USER USER() IDENTIFIED BY '%s'", typed_password);

      if (mysql_query(mysql,buff))
      {
	if (mysql_errno(mysql)!=1290)
	{
	  my_printf_error(0,"unable to change password; error: '%s'",
			  error_flags, mysql_error(mysql));
          err= true;
          goto error;
	}
	else
	{
	  /*
	    We don't try to execute 'update mysql.user set..'
	    because we can't perfectly find out the host
	   */
	  my_printf_error(0,"\n"
			  "You cannot use 'password' command as mysqld runs\n"
			  " with grant tables disabled (was started with"
			  " --skip-grant-tables).\n"
			  "Use: \"mysqladmin flush-privileges password '*'\""
			  " instead", error_flags);
          err= true;
          goto error;
	}
      }
      /*
        We may call set sql_log_off after this so check for warnings here.
      */
      if (opt_show_warnings)
      {
        print_warnings(mysql);
        log_warnings= false;
      }
      if (log_off && mysql_query(mysql, "set sql_log_off=0"))
      {
        if (opt_verbose)
          fprintf(stderr, "Note: Can't turn on logging; '%s'", mysql_error(mysql));
      }
error:
      /* free up memory from prompted password */
      if (typed_password != argv[1]) 
      {
        my_free(typed_password);
        my_free(verified);
      }
      if (err)
        return -1;

      argc--; argv++;
      break;
    }

    case ADMIN_START_SLAVE:
      if (mysql_query(mysql, "START SLAVE"))
      {
	my_printf_error(0, "Error starting slave: %s", error_flags,
			mysql_error(mysql));
	return -1;
      }
      else
	puts("Slave started");
      break;
    case ADMIN_STOP_SLAVE:
      if (mysql_query(mysql, "STOP SLAVE"))
      {
	  my_printf_error(0, "Error stopping slave: %s", error_flags,
			  mysql_error(mysql));
	  return -1;
      }
      else
	puts("Slave stopped");
      break;

    case ADMIN_PING:
      mysql->reconnect=0;	/* We want to know of reconnects */
      if (!mysql_ping(mysql))
      {
	if (option_silent < 2)
	  puts("mysqld is alive");
      }
      else
      {
	if (mysql_errno(mysql) == CR_SERVER_GONE_ERROR)
	{
	  mysql->reconnect=1;
	  if (!mysql_ping(mysql))
	    puts("connection was down, but mysqld is now alive");
	}
	else
	{
	  my_printf_error(0,"mysqld doesn't answer to ping, error: '%s'",
			  error_flags, mysql_error(mysql));
	  return -1;
	}
      }
      mysql->reconnect=1;	/* Automatic reconnect is default */
      break;
    default:
      my_printf_error(0, "Unknown command: '%-.60s'", error_flags, argv[0]);
      return 1;
    }
    if (opt_show_warnings && log_warnings)
      print_warnings(mysql);
  }
  return 0;
}