/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include "mysql_priv.h"
#include <mysql.h>
#include <m_ctype.h>
#include <my_dir.h>
#include "sql_acl.h"
#include "slave.h"
#include "sql_repl.h"
#include "stacktrace.h"
#ifdef HAVE_BERKELEY_DB
#include "ha_berkeley.h"
#endif
#ifdef HAVE_INNOBASE_DB
#include "ha_innobase.h"
#endif
#ifdef HAVE_GEMINI_DB
#include "ha_gemini.h"
#endif
#include "ha_myisam.h"
#include <nisam.h>
#include <thr_alarm.h>
#include <ft_global.h>

#ifndef DBUG_OFF
#define ONE_THREAD
#endif

#if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ)
#define HAVE_CLOSE_SERVER_SOCK 1
void close_server_sock();
#endif

extern "C" {					// Because of SCO 3.2V4.2
#include <errno.h>
#include <sys/stat.h>
#ifndef __GNU_LIBRARY__
#define __GNU_LIBRARY__				// Skip warnings in getopt.h
#endif
#include <getopt.h>
#ifdef HAVE_SYSENT_H
#include <sysent.h>
#endif
#ifdef HAVE_PWD_H
#include <pwd.h>				// For getpwent
#endif
#ifdef HAVE_GRP_H
#include <grp.h>
#endif

#if defined(OS2)
#  include <sys/un.h>
#elif !defined( __WIN__)
#include <sys/resource.h>
#ifdef HAVE_SYS_UN_H
#  include <sys/un.h>
#endif
#include <netdb.h>
#ifdef HAVE_SELECT_H
#  include <select.h>
#endif
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#include <sys/utsname.h>
#else
#include <windows.h>
#endif // __WIN__

#ifdef HAVE_LIBWRAP
#include <tcpd.h>
#include <syslog.h>
#ifdef NEED_SYS_SYSLOG_H
#include <sys/syslog.h>
#endif /* NEED_SYS_SYSLOG_H */
int allow_severity = LOG_INFO;
int deny_severity = LOG_WARNING;
#endif /* HAVE_LIBWRAP */

#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif

#ifdef _AIX41
int initgroups(const char *,unsigned int);
#endif

#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
#include <ieeefp.h>
#ifdef HAVE_FP_EXCEPT				// Fix type conflict
typedef fp_except fp_except_t;
#endif

  /* We can't handle floating point expections with threads, so disable
     this on freebsd
  */

inline void reset_floating_point_exceptions()
{
  /* Don't fall for overflow, underflow,divide-by-zero or loss of precision */
  fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL |
	      FP_X_DZ | FP_X_IMP));
}
#else
#define reset_floating_point_exceptions()
#endif /* __FreeBSD__ && HAVE_IEEEFP_H */

} /* cplusplus */


#if defined(HAVE_LINUXTHREADS)
#define THR_KILL_SIGNAL SIGINT
#else
#define THR_KILL_SIGNAL SIGUSR2		// Can't use this with LinuxThreads
#endif

#ifdef HAVE_GLIBC2_STYLE_GETHOSTBYNAME_R
#include <sys/types.h>
#else
#include <my_pthread.h>			// For thr_setconcurency()
#endif
#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) && !defined(HAVE_mit_thread)
#define SET_RLIMIT_NOFILE
#endif

#ifdef SOLARIS
extern "C" int gethostname(char *name, int namelen);
#endif

#define MYSQL_KILL_SIGNAL SIGTERM

#ifndef DBUG_OFF
static const char* default_dbug_option=IF_WIN("d:t:i:O,\\mysqld.trace",
					      "d:t:i:o,/tmp/mysqld.trace");
#endif

#ifdef __NT__
static char szPipeName [ 257 ];
static SECURITY_ATTRIBUTES saPipeSecurity;
static SECURITY_DESCRIPTOR sdPipeDescriptor;
static HANDLE hPipe = INVALID_HANDLE_VALUE;
static pthread_cond_t COND_handler_count;
static uint handler_count;
#endif
#ifdef __WIN__
static bool opt_console=0,start_mode=0;
#endif

/* Set prefix for windows binary */
#ifdef __WIN__
#undef MYSQL_SERVER_SUFFIX
#ifdef __NT__
#if defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB)
#define MYSQL_SERVER_SUFFIX "-max-nt"
#else
#define MYSQL_SERVER_SUFFIX "-nt"
#endif /* ...DB */
#elif defined(HAVE_INNOBASE_DB) || defined(HAVE_BERKELEY_DB)
#define MYSQL_SERVER_SUFFIX "-max"
#else
#define MYSQL_SERVER_SUFFIX ""
#endif /* __NT__ */
#endif

#ifdef HAVE_BERKELEY_DB
SHOW_COMP_OPTION have_berkeley_db=SHOW_OPTION_YES;
#else
SHOW_COMP_OPTION have_berkeley_db=SHOW_OPTION_NO;
#endif
#ifdef HAVE_GEMINI_DB
SHOW_COMP_OPTION have_gemini=SHOW_OPTION_YES;
#else
SHOW_COMP_OPTION have_gemini=SHOW_OPTION_NO;
#endif
#ifdef HAVE_INNOBASE_DB
SHOW_COMP_OPTION have_innodb=SHOW_OPTION_YES;
#else
SHOW_COMP_OPTION have_innodb=SHOW_OPTION_NO;
#endif
#ifndef NO_ISAM
SHOW_COMP_OPTION have_isam=SHOW_OPTION_YES;
#else
SHOW_COMP_OPTION have_isam=SHOW_OPTION_NO;
#endif
#ifdef USE_RAID
SHOW_COMP_OPTION have_raid=SHOW_OPTION_YES;
#else
SHOW_COMP_OPTION have_raid=SHOW_OPTION_NO;
#endif
#ifdef HAVE_OPENSSL
SHOW_COMP_OPTION have_ssl=SHOW_OPTION_YES;
#else
SHOW_COMP_OPTION have_ssl=SHOW_OPTION_NO;
#endif


static bool opt_skip_slave_start = 0; // if set, slave is not autostarted
static ulong opt_specialflag=SPECIAL_ENGLISH;
static my_socket unix_sock= INVALID_SOCKET,ip_sock= INVALID_SOCKET;
static ulong back_log,connect_timeout,concurrency;
static my_string opt_logname=0,opt_update_logname=0,
       opt_binlog_index_name = 0,opt_slow_logname=0;
static char mysql_home[FN_REFLEN],pidfile_name[FN_REFLEN];
static pthread_t select_thread;
static bool opt_log,opt_update_log,opt_bin_log,opt_slow_log,opt_noacl,
	    opt_disable_networking=0, opt_bootstrap=0,opt_skip_show_db=0,
	    opt_myisam_log=0,
            opt_large_files=sizeof(my_off_t) > 4;
bool opt_sql_bin_update = 0, opt_log_slave_updates = 0, opt_safe_show_db=0,
     opt_safe_user_create=0;
FILE *bootstrap_file=0;
int segfaulted = 0; // ensure we do not enter SIGSEGV handler twice
extern MASTER_INFO glob_mi;
extern int init_master_info(MASTER_INFO* mi);

// if sql_bin_update is true, SQL_LOG_UPDATE and SQL_LOG_BIN are kept in sync,
// and are treated as aliases for each other

static bool kill_in_progress=FALSE;
static struct rand_struct sql_rand;
static int cleanup_done;
static char **defaults_argv,time_zone[30];
static const char *default_table_type_name;
static char glob_hostname[FN_REFLEN];

#ifdef HAVE_OPENSSL
static bool opt_use_ssl = FALSE;
static char *opt_ssl_key = 0;
static char *opt_ssl_cert = 0;
static char *opt_ssl_ca = 0;
static char *opt_ssl_capath = 0;
static VioSSLAcceptorFd* ssl_acceptor_fd = 0;
#endif /* HAVE_OPENSSL */


I_List <i_string_pair> replicate_rewrite_db;
I_List<i_string> replicate_do_db, replicate_ignore_db;
// allow the user to tell us which db to replicate and which to ignore
I_List<i_string> binlog_do_db, binlog_ignore_db;

/* if we guessed server_id , we need to know about it */
uint32 server_id = 0;
bool server_id_supplied = 0;

uint mysql_port;
uint test_flags, select_errors=0, dropping_tables=0,ha_open_options=0;
uint volatile thread_count=0, thread_running=0, kill_cached_threads=0,
	      wake_thread=0, global_read_lock=0;
ulong thd_startup_options=(OPTION_UPDATE_LOG | OPTION_AUTO_IS_NULL |
			   OPTION_BIN_LOG | OPTION_QUOTE_SHOW_CREATE );
uint protocol_version=PROTOCOL_VERSION;
ulong keybuff_size,sortbuff_size,max_item_sort_length,table_cache_size,
      max_join_size,join_buff_size,tmp_table_size,thread_stack,
      thread_stack_min,net_wait_timeout,what_to_log= ~ (1L << (uint) COM_TIME),
      query_buff_size, lower_case_table_names, mysqld_net_retry_count,
      net_interactive_timeout, slow_launch_time = 2L,
      net_read_timeout,net_write_timeout,slave_open_temp_tables=0,
      open_files_limit=0, max_binlog_size, record_rnd_cache_size;
ulong com_stat[(uint) SQLCOM_END], com_other;
ulong slave_net_timeout;
ulong thread_cache_size=0, binlog_cache_size=0, max_binlog_cache_size=0;
volatile ulong cached_thread_count=0;

// replication parameters, if master_host is not NULL, we are a slave
my_string master_user = (char*) "test", master_password = 0, master_host=0,
  master_info_file = (char*) "master.info";
const char *localhost=LOCAL_HOST;
const char *delayed_user="DELAYED";
uint master_port = MYSQL_PORT, master_connect_retry = 60;

ulong max_tmp_tables,max_heap_table_size,master_retry_count=0;
ulong bytes_sent = 0L, bytes_received = 0L;

bool opt_endinfo,using_udf_functions,low_priority_updates, locked_in_memory;
bool opt_using_transactions, using_update_log, opt_warnings=0;
bool opt_local_infile;
bool volatile abort_loop,select_thread_in_use,grant_option;
bool volatile ready_to_exit,shutdown_in_progress;
ulong refresh_version=1L,flush_version=1L;	/* Increments on each reload */
ulong query_id=1L,long_query_count,long_query_time,aborted_threads,
      aborted_connects,delayed_insert_timeout,delayed_insert_limit,
      delayed_queue_size,delayed_insert_threads,delayed_insert_writes,
      delayed_rows_in_use,delayed_insert_errors,flush_time, thread_created;
ulong filesort_rows, filesort_range_count, filesort_scan_count;
ulong filesort_merge_passes;
ulong select_range_check_count, select_range_count, select_scan_count;
ulong select_full_range_join_count,select_full_join_count;
ulong specialflag=0,opened_tables=0,created_tmp_tables=0,
      created_tmp_disk_tables=0;
ulong max_connections,max_insert_delayed_threads,max_used_connections,
      max_connect_errors, max_user_connections = 0;
ulong thread_id=1L,current_pid;
ulong slow_launch_threads = 0;
ulong myisam_max_sort_file_size, myisam_max_extra_sort_file_size;
  
char mysql_real_data_home[FN_REFLEN],
     mysql_data_home[2],language[LIBLEN],reg_ext[FN_EXTLEN],
     default_charset[LIBLEN],mysql_charsets_dir[FN_REFLEN], *charsets_list,
     blob_newline,f_fyllchar,max_sort_char,*mysqld_user,*mysqld_chroot,
     *opt_init_file;
char *opt_bin_logname = 0; // this one needs to be seen in sql_parse.cc
char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION;
const char *first_keyword="first";
const char **errmesg;			/* Error messages */
const char *myisam_recover_options_str="OFF";
const char *sql_mode_str="OFF";
const char *default_tx_isolation_name;
enum_tx_isolation default_tx_isolation=ISO_READ_COMMITTED;

#ifdef HAVE_GEMINI_DB
const char *gemini_recovery_options_str="FULL";
#endif
my_string mysql_unix_port=NULL,mysql_tmpdir=NULL;
ulong my_bind_addr;			/* the address we bind to */
DATE_FORMAT dayord;
double log_10[32];			/* 10 potences */
I_List<THD> threads,thread_cache;
time_t start_time;

ulong opt_sql_mode = 0L;
const char *sql_mode_names[] =
{ "REAL_AS_FLOAT", "PIPES_AS_CONCAT", "ANSI_QUOTES", "IGNORE_SPACE",
  "SERIALIZE","ONLY_FULL_GROUP_BY", NullS };
TYPELIB sql_mode_typelib= {array_elements(sql_mode_names),"",
			   sql_mode_names};

MY_BITMAP temp_pool;
bool use_temp_pool=0;

pthread_key(MEM_ROOT*,THR_MALLOC);
pthread_key(THD*, THR_THD);
pthread_key(NET*, THR_NET);
pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
		LOCK_mapped_file, LOCK_status, LOCK_grant,
		LOCK_error_log,
		LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
		LOCK_crypt, LOCK_bytes_sent, LOCK_bytes_received,
                LOCK_binlog_update, LOCK_slave, LOCK_server_id,
		LOCK_user_conn;

pthread_cond_t COND_refresh,COND_thread_count,COND_binlog_update,
  COND_slave_stopped, COND_slave_start;
pthread_cond_t COND_thread_cache,COND_flush_thread_cache;
pthread_t signal_thread;
pthread_attr_t connection_attrib;
enum db_type default_table_type=DB_TYPE_MYISAM;

#ifdef __WIN__
#undef	 getpid
#include <process.h>
HANDLE hEventShutdown;
#include "nt_servc.h"
static	 NTService  Service;	      // Service object for WinNT
#endif

#ifdef OS2
pthread_cond_t eventShutdown;
#endif

static void start_signal_handler(void);
static void *signal_hand(void *arg);
static void set_options(void);
static void get_options(int argc,char **argv);
static char *get_relative_path(const char *path);
static void fix_paths(void);
static pthread_handler_decl(handle_connections_sockets,arg);
static pthread_handler_decl(kill_server_thread,arg);
static int bootstrap(FILE *file);
static bool read_init_file(char *file_name);
#ifdef __NT__
static pthread_handler_decl(handle_connections_namedpipes,arg);
#endif
extern pthread_handler_decl(handle_slave,arg);
#ifdef SET_RLIMIT_NOFILE
static uint set_maximum_open_files(uint max_file_limit);
#endif
static ulong find_bit_type(const char *x, TYPELIB *bit_lib);

/****************************************************************************
** Code to end mysqld
****************************************************************************/

static void close_connections(void)
{
#ifdef EXTRA_DEBUG
  int count=0;
#endif
  NET net;
  DBUG_ENTER("close_connections");

  /* Clear thread cache */
  kill_cached_threads++;
  flush_thread_cache();

  /* kill flush thread */
  (void) pthread_mutex_lock(&LOCK_manager);
  if (manager_thread_in_use)
  {
    DBUG_PRINT("quit",("killing manager thread: %lx",manager_thread));
   (void) pthread_cond_signal(&COND_manager);
  }
  (void) pthread_mutex_unlock(&LOCK_manager);

  /* kill connection thread */
#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2)
  DBUG_PRINT("quit",("waiting for select thread: %lx",select_thread));
  (void) pthread_mutex_lock(&LOCK_thread_count);

  while (select_thread_in_use)
  {
    struct timespec abstime;
    int error;
    LINT_INIT(error);
#ifndef DONT_USE_THR_ALARM
    if (pthread_kill(select_thread,THR_CLIENT_ALARM))
      break;					// allready dead
#endif
#ifdef HAVE_TIMESPEC_TS_SEC
    abstime.ts_sec=time(NULL)+2;		// Bsd 2.1
    abstime.ts_nsec=0;
#else
    struct timeval tv;
    gettimeofday(&tv,0);
    abstime.tv_sec=tv.tv_sec+2;
    abstime.tv_nsec=tv.tv_usec*1000;
#endif
    for (uint tmp=0 ; tmp < 10 ; tmp++)
    {
      error=pthread_cond_timedwait(&COND_thread_count,&LOCK_thread_count,
				   &abstime);
      if (error != EINTR)
	break;
    }
#ifdef EXTRA_DEBUG
    if (error != 0 && !count++)
      sql_print_error("Got error %d from pthread_cond_timedwait",error);
#endif
#if defined(HAVE_DEC_3_2_THREADS) || defined(SIGNALS_DONT_BREAK_READ)
    close_server_sock();
#endif
  }
  (void) pthread_mutex_unlock(&LOCK_thread_count);
#endif /* __WIN__ */


  /* Abort listening to new connections */
  DBUG_PRINT("quit",("Closing sockets"));
  if ( !opt_disable_networking )
  {
    if (ip_sock != INVALID_SOCKET)
    {
      (void) shutdown(ip_sock,2);
      (void) closesocket(ip_sock);
      ip_sock= INVALID_SOCKET;
    }
  }
#ifdef __NT__
  if ( hPipe != INVALID_HANDLE_VALUE )
  {
    HANDLE hTempPipe = &hPipe;
    DBUG_PRINT( "quit", ("Closing named pipes") );
    hPipe = INVALID_HANDLE_VALUE;
    CancelIo( hTempPipe );
    DisconnectNamedPipe( hTempPipe );
    CloseHandle( hTempPipe );
  }
#endif
#ifdef HAVE_SYS_UN_H
  if (unix_sock != INVALID_SOCKET)
  {
    (void) shutdown(unix_sock,2);
    (void) closesocket(unix_sock);
    (void) unlink(mysql_unix_port);
    unix_sock= INVALID_SOCKET;
  }
#endif
  end_thr_alarm();			 // Don't allow alarms
  end_slave();

  /* First signal all threads that it's time to die */

  THD *tmp;
  (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list

  I_List_iterator<THD> it(threads);
  while ((tmp=it++))
  {
    DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
		       tmp->thread_id));
    tmp->killed=1;
    if (tmp->mysys_var)
    {
      tmp->mysys_var->abort=1;
      pthread_mutex_lock(&tmp->mysys_var->mutex);
      if (tmp->mysys_var->current_cond)
      {
	pthread_mutex_lock(tmp->mysys_var->current_mutex);
	pthread_cond_broadcast(tmp->mysys_var->current_cond);
	pthread_mutex_unlock(tmp->mysys_var->current_mutex);
      }
      pthread_mutex_unlock(&tmp->mysys_var->mutex);
    }
  }
  (void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list

  if (thread_count)
  {
    sleep(1);					// Give threads time to die
  }

  /* Force remaining threads to die by closing the connection to the client */

  (void) my_net_init(&net, (Vio*) 0);
  for (;;)
  {
    DBUG_PRINT("quit",("Locking LOCK_thread_count"));
    (void) pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
    if (!(tmp=threads.get()))
    {
      DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
      (void) pthread_mutex_unlock(&LOCK_thread_count);
      break;
    }
#ifndef __bsdi__				// Bug in BSDI kernel
    if ((net.vio=tmp->net.vio) != 0)
    {
      sql_print_error(ER(ER_FORCING_CLOSE),my_progname,
		      tmp->thread_id,tmp->user ? tmp->user : "");
      close_connection(&net,0,0);
    }
#endif
    DBUG_PRINT("quit",("Unlocking LOCK_thread_count"));
    (void) pthread_mutex_unlock(&LOCK_thread_count);
  }
  net_end(&net);
  /* All threads has now been aborted */
  DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count));
  (void) pthread_mutex_lock(&LOCK_thread_count);
  while (thread_count)
  {
    (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
    DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
  }
  (void) pthread_mutex_unlock(&LOCK_thread_count);

  mysql_log.close(1);
  mysql_slow_log.close(1);
  mysql_update_log.close(1);
  mysql_bin_log.close(1);
  DBUG_PRINT("quit",("close_connections thread"));
  DBUG_VOID_RETURN;
}

#ifdef HAVE_CLOSE_SERVER_SOCK
void close_server_sock()
{
  DBUG_ENTER("close_server_sock");
  if (ip_sock != INVALID_SOCKET)
  {
    DBUG_PRINT("info",("closing TCP/IP socket"));
    VOID(shutdown(ip_sock,2));
    VOID(closesocket(ip_sock));
    ip_sock=INVALID_SOCKET;
  }
  if (unix_sock != INVALID_SOCKET)
  {
    DBUG_PRINT("info",("closing Unix socket"));
    VOID(shutdown(unix_sock,2));
    VOID(closesocket(unix_sock));
    VOID(unlink(mysql_unix_port));
    unix_sock=INVALID_SOCKET;
  }
  DBUG_VOID_RETURN;
}
#endif

void kill_mysql(void)
{
  DBUG_ENTER("kill_mysql");
#ifdef SIGNALS_DONT_BREAK_READ
  close_server_sock(); /* force accept to wake up */
#endif 
#if defined(__WIN__)
  {
    if (!SetEvent(hEventShutdown))
    {
      DBUG_PRINT("error",("Got error: %ld from SetEvent",GetLastError()));
    }
    // or:
    // HANDLE hEvent=OpenEvent(0, FALSE, "MySqlShutdown");
    // SetEvent(hEventShutdown);
    // CloseHandle(hEvent);
  }
#elif defined(OS2)
  pthread_cond_signal( &eventShutdown);		// post semaphore
#elif defined(HAVE_PTHREAD_KILL)
  if (pthread_kill(signal_thread,MYSQL_KILL_SIGNAL))// End everything nicely
  {
    DBUG_PRINT("error",("Got error %d from pthread_kill",errno)); /* purecov: inspected */
  }
#elif !defined(SIGNALS_DONT_BREAK_READ)
  kill(current_pid,MYSQL_KILL_SIGNAL);
#endif
  DBUG_PRINT("quit",("After pthread_kill"));
  shutdown_in_progress=1;			// Safety if kill didn't work
#ifdef SIGNALS_DONT_BREAK_READ    
  if (!abort_loop)
  {
    pthread_t tmp;
    abort_loop=1;
    if (pthread_create(&tmp,&connection_attrib, kill_server_thread,
			   (void*) 0))
      sql_print_error("Error: Can't create thread to kill server");
  }
#endif    
  DBUG_VOID_RETURN;
}


	/* Force server down. kill all connections and threads and exit */

#if defined(OS2)
extern "C" void kill_server(int sig_ptr)
#define RETURN_FROM_KILL_SERVER return
#elif !defined(__WIN__)
static void *kill_server(void *sig_ptr)
#define RETURN_FROM_KILL_SERVER return 0
#else
static void __cdecl kill_server(int sig_ptr)
#define RETURN_FROM_KILL_SERVER return
#endif
{
  int sig=(int) (long) sig_ptr;			// This is passed a int
  DBUG_ENTER("kill_server");

  // if there is a signal during the kill in progress, we do not need
  // another one
  if (kill_in_progress)				// Safety
    RETURN_FROM_KILL_SERVER;
  kill_in_progress=TRUE;
  abort_loop=1;					// This should be set
  signal(sig,SIG_IGN);
  if (sig == MYSQL_KILL_SIGNAL || sig == 0)
    sql_print_error(ER(ER_NORMAL_SHUTDOWN),my_progname);
  else
    sql_print_error(ER(ER_GOT_SIGNAL),my_progname,sig); /* purecov: inspected */

#if defined(USE_ONE_SIGNAL_HAND) && !defined(__WIN__) && !defined(OS2)
  my_thread_init();				// If this is a new thread
#endif
  close_connections();
  if (sig != MYSQL_KILL_SIGNAL && sig != 0)
    unireg_abort(1);				/* purecov: inspected */
  else
    unireg_end(0);
  pthread_exit(0);				/* purecov: deadcode */
  RETURN_FROM_KILL_SERVER;
}


#ifdef USE_ONE_SIGNAL_HAND
pthread_handler_decl(kill_server_thread,arg __attribute__((unused)))
{
  my_thread_init();				// Initialize new thread
  kill_server(0);
  my_thread_end();				// Normally never reached
  return 0;
}
#endif

static sig_handler print_signal_warning(int sig)
{
  if (opt_warnings)
    sql_print_error("Warning: Got signal %d from thread %d",
		    sig,my_thread_id());
#ifdef DONT_REMEMBER_SIGNAL
  sigset(sig,print_signal_warning);		/* int. thread system calls */
#endif
#if !defined(__WIN__) && !defined(OS2)
  if (sig == SIGALRM)
    alarm(2);					/* reschedule alarm */
#endif
}


void unireg_end(int signal_number __attribute__((unused)))
{
  clean_up();
  pthread_exit(0);				// Exit is in main thread
}


void unireg_abort(int exit_code)
{
  if (exit_code)
    sql_print_error("Aborting\n");
  clean_up(); /* purecov: inspected */
  exit(exit_code); /* purecov: inspected */
}


void clean_up(bool print_message)
{
  DBUG_PRINT("exit",("clean_up"));
  if (cleanup_done++)
    return; /* purecov: inspected */
  if (use_slave_mask)
    bitmap_free(&slave_error_mask);
  acl_free(1);
  grant_free();
  sql_cache_free();
  table_cache_free();
  hostname_cache_free();
  item_user_lock_free();
  lex_free();				/* Free some memory */
#ifdef HAVE_DLOPEN
  if (!opt_noacl)
    udf_free();
#endif
  (void) ha_panic(HA_PANIC_CLOSE);	/* close all tables and logs */
  end_key_cache();
#ifdef USE_RAID
  end_raid();
#endif
  free_defaults(defaults_argv);
  my_free(charsets_list, MYF(MY_ALLOW_ZERO_PTR));
  my_free(mysql_tmpdir,MYF(0));
  x_free(opt_bin_logname);
  bitmap_free(&temp_pool);
  free_max_user_conn();
#ifndef __WIN__
  if (!opt_bootstrap)
    (void) my_delete(pidfile_name,MYF(0));	// This may not always exist
#endif
  if (print_message)
    sql_print_error(ER(ER_SHUTDOWN_COMPLETE),my_progname);
  x_free((gptr) my_errmsg[ERRMAPP]);	/* Free messages */
  my_thread_end();

  /* Tell main we are ready */
  (void) pthread_mutex_lock(&LOCK_thread_count);
  ready_to_exit=1;
  /* do the broadcast inside the lock to ensure that my_end() is not called */
  (void) pthread_cond_broadcast(&COND_thread_count);
  (void) pthread_mutex_unlock(&LOCK_thread_count);
} /* clean_up */



/****************************************************************************
** Init IP and UNIX socket
****************************************************************************/

static void set_ports()
{
  char	*env;
  if (!mysql_port && !opt_disable_networking)
  {					// Get port if not from commandline
    struct  servent *serv_ptr;
    mysql_port = MYSQL_PORT;
    if ((serv_ptr = getservbyname("mysql", "tcp")))
      mysql_port = ntohs((u_short) serv_ptr->s_port); /* purecov: inspected */
    if ((env = getenv("MYSQL_TCP_PORT")))
      mysql_port = (uint) atoi(env);		/* purecov: inspected */
  }
  if (!mysql_unix_port)
  {
#ifdef __WIN__
    mysql_unix_port = (char*) MYSQL_NAMEDPIPE;
#else
    mysql_unix_port = (char*) MYSQL_UNIX_ADDR;
#endif
    if ((env = getenv("MYSQL_UNIX_PORT")))
      mysql_unix_port = env;			/* purecov: inspected */
  }
}

/* Change to run as another user if started with --user */

static void set_user(const char *user)
{
#if !defined(__WIN__) && !defined(OS2)
    struct passwd *ent;

  // don't bother if we aren't superuser
  if (geteuid())
  {
    if (user)
      fprintf(stderr,
	      "Warning: One can only use the --user switch if running as root\n");
    return;
  }
  else if (!user)
  {
    if (!opt_bootstrap)
    {
      fprintf(stderr,"Fatal error: Please read \"Security\" section of the manual to find out how to run mysqld as root!\n");
      unireg_abort(1);
    }
    return;
  }
  if (!strcmp(user,"root"))
    return;				// Avoid problem with dynamic libraries

  if (!(ent = getpwnam(user)))
  {
    fprintf(stderr,"Fatal error: Can't change to run as user '%s' ;  Please check that the user exists!\n",user);
    unireg_abort(1);
  }
#ifdef HAVE_INITGROUPS
  initgroups((char*) user,ent->pw_gid);
#endif
  if (setgid(ent->pw_gid) == -1)
  {
    sql_perror("setgid");
    unireg_abort(1);
  }
  if (setuid(ent->pw_uid) == -1)
  {
    sql_perror("setuid");
    unireg_abort(1);
  }
#endif
}

/* Change root user if started with  --chroot */

static void set_root(const char *path)
{
#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2)
  if (chroot(path) == -1)
  {
    sql_perror("chroot");
    unireg_abort(1);
  }
#endif
}

static void server_init(void)
{
  struct sockaddr_in	IPaddr;
#ifdef HAVE_SYS_UN_H
  struct sockaddr_un	UNIXaddr;
#endif
  int	arg=1;
  DBUG_ENTER("server_init");

#ifdef	__WIN__
  if ( !opt_disable_networking )
  {
    WSADATA WsaData;
    if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
    {
      my_message(0,"WSAStartup Failed\n",MYF(0));
      unireg_abort(1);
    }
  }
#endif /* __WIN__ */

  set_ports();

  if (mysql_port != 0 && !opt_disable_networking && !opt_bootstrap)
  {
    DBUG_PRINT("general",("IP Socket is %d",mysql_port));
    ip_sock = socket(AF_INET, SOCK_STREAM, 0);
    if (ip_sock == INVALID_SOCKET)
    {
      DBUG_PRINT("error",("Got error: %d from socket()",socket_errno));
      sql_perror(ER(ER_IPSOCK_ERROR));		/* purecov: tested */
      unireg_abort(1);				/* purecov: tested */
    }
    bzero((char*) &IPaddr, sizeof(IPaddr));
    IPaddr.sin_family = AF_INET;
    IPaddr.sin_addr.s_addr = my_bind_addr;
    IPaddr.sin_port = (unsigned short) htons((unsigned short) mysql_port);
    (void) setsockopt(ip_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,sizeof(arg));
    for(;;)
    {
      if (bind(ip_sock, my_reinterpret_cast(struct sockaddr *) (&IPaddr),
	       sizeof(IPaddr)) >= 0)
	break;
      DBUG_PRINT("error",("Got error: %d from bind",socket_errno));
      sql_perror("Can't start server: Bind on TCP/IP port");/* Had a loop here */
      sql_print_error("Do you already have another mysqld server running on port: %d ?",mysql_port);
      unireg_abort(1);
    }
    if (listen(ip_sock,(int) back_log) < 0)
      sql_print_error("Warning:  listen() on TCP/IP failed with error %d",
		      socket_errno);
  }

  if (mysqld_chroot)
    set_root(mysqld_chroot);

  set_user(mysqld_user); // set_user now takes care of mysqld_user==NULL

#ifdef __NT__
  /* create named pipe */
  if (Service.IsNT() && mysql_unix_port[0] && !opt_bootstrap)
  {
    sprintf( szPipeName, "\\\\.\\pipe\\%s", mysql_unix_port );
    ZeroMemory( &saPipeSecurity, sizeof(saPipeSecurity) );
    ZeroMemory( &sdPipeDescriptor, sizeof(sdPipeDescriptor) );
    if ( !InitializeSecurityDescriptor(&sdPipeDescriptor,
				       SECURITY_DESCRIPTOR_REVISION) )
    {
      sql_perror("Can't start server : Initialize security descriptor");
      unireg_abort(1);
    }
    if (!SetSecurityDescriptorDacl(&sdPipeDescriptor, TRUE, NULL, FALSE))
    {
      sql_perror("Can't start server : Set security descriptor");
      unireg_abort(1);
    }
    saPipeSecurity.nLength = sizeof( SECURITY_ATTRIBUTES );
    saPipeSecurity.lpSecurityDescriptor = &sdPipeDescriptor;
    saPipeSecurity.bInheritHandle = FALSE;
    if ((hPipe = CreateNamedPipe(szPipeName,
				 PIPE_ACCESS_DUPLEX,
				 PIPE_TYPE_BYTE |
				 PIPE_READMODE_BYTE |
				 PIPE_WAIT,
				 PIPE_UNLIMITED_INSTANCES,
				 (int) net_buffer_length,
				 (int) net_buffer_length,
				 NMPWAIT_USE_DEFAULT_WAIT,
				 &saPipeSecurity )) == INVALID_HANDLE_VALUE)
      {
	LPVOID lpMsgBuf;
	int error=GetLastError();
	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
		      FORMAT_MESSAGE_FROM_SYSTEM,
		      NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
		      (LPTSTR) &lpMsgBuf, 0, NULL );
	MessageBox( NULL, (LPTSTR) lpMsgBuf, "Error from CreateNamedPipe",
		    MB_OK|MB_ICONINFORMATION );
	LocalFree( lpMsgBuf );
	unireg_abort(1);
      }
  }
#endif

#if defined(HAVE_SYS_UN_H)
  /*
  ** Create the UNIX socket
  */
  if (mysql_unix_port[0] && !opt_bootstrap)
  {
    DBUG_PRINT("general",("UNIX Socket is %s",mysql_unix_port));

    if ((unix_sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
    {
      sql_perror("Can't start server : UNIX Socket "); /* purecov: inspected */
      unireg_abort(1);				/* purecov: inspected */
    }
    bzero((char*) &UNIXaddr, sizeof(UNIXaddr));
    UNIXaddr.sun_family = AF_UNIX;
    strmov(UNIXaddr.sun_path, mysql_unix_port);
    (void) unlink(mysql_unix_port);
    (void) setsockopt(unix_sock,SOL_SOCKET,SO_REUSEADDR,(char*)&arg,
		      sizeof(arg));
    umask(0);
    if (bind(unix_sock, my_reinterpret_cast(struct sockaddr *) (&UNIXaddr),
	     sizeof(UNIXaddr)) < 0)
    {
      sql_perror("Can't start server : Bind on unix socket"); /* purecov: tested */
      sql_print_error("Do you already have another mysqld server running on socket: %s ?",mysql_unix_port);
      unireg_abort(1);					/* purecov: tested */
    }
    umask(((~my_umask) & 0666));
#if defined(S_IFSOCK) && defined(SECURE_SOCKETS)
    (void) chmod(mysql_unix_port,S_IFSOCK);	/* Fix solaris 2.6 bug */
#endif
    if (listen(unix_sock,(int) back_log) < 0)
      sql_print_error("Warning:  listen() on Unix socket failed with error %d",
		      socket_errno);
  }
#endif
  DBUG_PRINT("info",("server started"));
  DBUG_VOID_RETURN;
}


void yyerror(const char *s)
{
  NET *net=my_pthread_getspecific_ptr(NET*,THR_NET);
  char *yytext=(char*) current_lex->tok_start;
  if (!strcmp(s,"parse error"))
    s=ER(ER_SYNTAX_ERROR);
  net_printf(net,ER_PARSE_ERROR, s, yytext ? (char*) yytext : "",
	     current_lex->yylineno);
}


void close_connection(NET *net,uint errcode,bool lock)
{
  Vio* vio;
  DBUG_ENTER("close_connection");
  DBUG_PRINT("enter",("fd: %s  error: '%s'",
                    net->vio? vio_description(net->vio):"(not connected)",
                    errcode ? ER(errcode) : ""));
  if (lock)
    (void) pthread_mutex_lock(&LOCK_thread_count);
  if ((vio=net->vio) != 0)
  {
    if (errcode)
      send_error(net,errcode,ER(errcode));	/* purecov: inspected */
    vio_close(vio);			/* vio is freed in delete thd */
  }
  if (lock)
    (void) pthread_mutex_unlock(&LOCK_thread_count);
  DBUG_VOID_RETURN;
}

	/* Called when a thread is aborted */
	/* ARGSUSED */

sig_handler end_thread_signal(int sig __attribute__((unused)))
{
  THD *thd=current_thd;
  DBUG_ENTER("end_thread_signal");
  if (thd)
    end_thread(thd,0);
  DBUG_VOID_RETURN;				/* purecov: deadcode */
}


void end_thread(THD *thd, bool put_in_cache)
{
  DBUG_ENTER("end_thread");
  thd->cleanup();
  (void) pthread_mutex_lock(&LOCK_thread_count);
  thread_count--;
  delete thd;

  if (put_in_cache && cached_thread_count < thread_cache_size &&
      ! abort_loop && !kill_cached_threads)
  {
    /* Don't kill the thread, just put it in cache for reuse */
    DBUG_PRINT("info", ("Adding thread to cache"))
    cached_thread_count++;
    while (!abort_loop && ! wake_thread && ! kill_cached_threads)
      (void) pthread_cond_wait(&COND_thread_cache, &LOCK_thread_count);
    cached_thread_count--;
    if (kill_cached_threads)
      pthread_cond_signal(&COND_flush_thread_cache);
    if (wake_thread)
    {
      wake_thread--;
      thd=thread_cache.get();
      thd->real_id=pthread_self();
      (void) thd->store_globals();
      threads.append(thd);
      pthread_mutex_unlock(&LOCK_thread_count);
      DBUG_VOID_RETURN;
    }
  }

  DBUG_PRINT("info", ("sending a broadcast"))

  /* Tell main we are ready */
  (void) pthread_mutex_unlock(&LOCK_thread_count);
  (void) pthread_cond_broadcast(&COND_thread_count);
  DBUG_PRINT("info", ("unlocked thread_count mutex"))
#ifdef ONE_THREAD
  if (!(test_flags & TEST_NO_THREADS))	// For debugging under Linux
#endif
  {
    my_thread_end();
    pthread_exit(0);
  }
  DBUG_VOID_RETURN;
}

#ifdef SIGNALS_DONT_BREAK_READ
inline void kill_broken_server()
{
  /* hack to get around signals ignored in syscalls for problem OS's */
  if (unix_sock == INVALID_SOCKET || ip_sock ==INVALID_SOCKET)
  {
    select_thread_in_use = 0;
    kill_server((void*)MYSQL_KILL_SIGNAL); /* never returns */
  }
}
#define MAYBE_BROKEN_SYSCALL kill_broken_server();
#else
#define MAYBE_BROKEN_SYSCALL
#endif

/* Start a cached thread. LOCK_thread_count is locked on entry */

static void start_cached_thread(THD *thd)
{
  thread_cache.append(thd);
  wake_thread++;
  thread_count++;
  pthread_cond_signal(&COND_thread_cache);
}


void flush_thread_cache()
{
  (void) pthread_mutex_lock(&LOCK_thread_count);
  kill_cached_threads++;
  while (cached_thread_count)
  {
    pthread_cond_broadcast(&COND_thread_cache);
    pthread_cond_wait(&COND_flush_thread_cache,&LOCK_thread_count);
  }
  kill_cached_threads--;
  (void) pthread_mutex_unlock(&LOCK_thread_count);
}


	/*
	** Aborts a thread nicely. Commes here on SIGPIPE
	** TODO: One should have to fix that thr_alarm know about this
	** thread too
	*/

#ifdef THREAD_SPECIFIC_SIGPIPE
static sig_handler abort_thread(int sig __attribute__((unused)))
{
  THD *thd=current_thd;
  DBUG_ENTER("abort_thread");
  if (thd)
    thd->killed=1;
  DBUG_VOID_RETURN;
}
#endif

/******************************************************************************
** Setup a signal thread with handles all signals
** Because linux doesn't support scemas use a mutex to check that
** the signal thread is ready before continuing
******************************************************************************/

#if defined(__WIN__) || defined(OS2)
static void init_signals(void)
{
  int signals[] = {SIGINT,SIGILL,SIGFPE,SIGSEGV,SIGTERM,SIGABRT } ;
  for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++)
    signal( signals[i], kill_server) ;
#if defined(__WIN__)
  signal(SIGBREAK,SIG_IGN);	//ignore SIGBREAK for NT
#else
  signal(SIGBREAK, kill_server);
#endif
}

static void start_signal_handler(void)
{
}

#elif defined(__EMX__)
static void init_signals(void)
{
  signal(SIGQUIT, sig_kill);
  signal(SIGKILL, sig_kill);
  signal(SIGTERM, sig_kill);
  signal(SIGINT,  sig_kill);
  signal(SIGHUP,  sig_reload);	// Flush everything
  signal(SIGALRM, SIG_IGN);
  signal(SIGBREAK,SIG_IGN);
  signal_thread = pthread_self();
}


static void sig_reload(int signo)
{
  reload_acl_and_cache((THD*) 0,REFRESH_LOG, (TABLE_LIST*) 0); // Flush everything
  signal(signo, SIG_ACK);
}

static void sig_kill(int signo)
{
  if (!abort_loop)
  {
    abort_loop=1;				// mark abort for threads
    kill_server((void*) signo);
  }
  signal(signo, SIG_ACK);
}


static void start_signal_handler(void)
{
}
#else /* if ! __WIN__ && ! __EMX__ */

#ifdef HAVE_LINUXTHREADS
#define UNSAFE_DEFAULT_LINUX_THREADS 200
#endif

static sig_handler handle_segfault(int sig)
{
  THD *thd=current_thd;
  /*
    Strictly speaking, we should need a mutex here
    but since we have got SIGSEGV already, things are a mess
    so not having the mutex is not as bad as possibly using a buggy
    mutex - so we keep things simple.
  */
  if (segfaulted)
  {
    fprintf(stderr, "Fatal signal %d while backtracing\n", sig);
    exit(1);
  }
  
  segfaulted = 1;
  fprintf(stderr,"\
mysqld got signal %d;\n\
This could be because you hit a bug. It is also possible that this binary\n\
or one of the libraries it was linked agaist is corrupt, improperly built,\n\
or misconfigured. This error can also be caused by malfunctioning hardware.\n",
	  sig);
  fprintf(stderr, "\
We will try our best to scrape up some info that will hopefully help diagnose\n\
the problem, but since we have already crashed, something is definitely wrong\n\
and this may fail\n\n");
  fprintf(stderr, "key_buffer_size=%ld\n", keybuff_size);
  fprintf(stderr, "record_buffer=%ld\n", my_default_record_cache_size);
  fprintf(stderr, "sort_buffer=%ld\n", sortbuff_size);
  fprintf(stderr, "max_used_connections=%ld\n", max_used_connections);
  fprintf(stderr, "max_connections=%ld\n", max_connections);
  fprintf(stderr, "threads_connected=%d\n", thread_count);
  fprintf(stderr, "It is possible that mysqld could use up to \n\
key_buffer_size + (record_buffer + sort_buffer)*max_connections = %ld K\n\
bytes of memory\n", (keybuff_size + (my_default_record_cache_size +
			     sortbuff_size) * max_connections)/ 1024);
  fprintf(stderr, "Hope that's ok, if not, decrease some variables in the equation\n\n");
  
#if defined(HAVE_LINUXTHREADS)
  if (sizeof(char*) == 4 && thread_count > UNSAFE_DEFAULT_LINUX_THREADS)
  {
    fprintf(stderr, "\
You seem to be running 32-bit Linux and have %d concurrent connections.\n\
If you have not changed STACK_SIZE in LinuxThreads and build the binary \n\
yourself, LinuxThreads is quite likely to steal a part of global heap for\n\
the thread stack. Please read http://www.mysql.com/doc/L/i/Linux.html\n\n",
	    thread_count);
  }
#endif /* HAVE_LINUXTHREADS */

#ifdef HAVE_STACKTRACE
  if(!(test_flags & TEST_NO_STACKTRACE))
  {
#ifdef HAVE_GEMINI_DB
    utrace();
#endif
    print_stacktrace(thd ? (gptr) thd->thread_stack : (gptr) 0,
		     thread_stack);
  }
  if (thd)
  {
    fprintf(stderr, "Trying to get some variables.\n\
Some pointers may be invalid and cause the dump to abort...\n");
    safe_print_str("thd->query", thd->query, 1024);
    fprintf(stderr, "thd->thread_id=%ld\n", thd->thread_id);
    fprintf(stderr, "\n\
Successfully dumped variables, if you ran with --log, take a look at the\n\
details of what thread %ld did to cause the crash.  In some cases of really\n\
bad corruption, the values shown above may be invalid\n\n",
	  thd->thread_id);
  }
  fprintf(stderr, "\
The manual page at http://www.mysql.com/doc/C/r/Crashing.html contains\n\
information that should help you find out what is causing the crash\n");
  fflush(stderr);
#endif /* HAVE_STACKTRACE */

 if (test_flags & TEST_CORE_ON_SIGNAL)
   write_core(sig);
 exit(1);
}

#ifndef SA_RESETHAND
#define SA_RESETHAND 0
#endif
#ifndef SA_NODEFER
#define SA_NODEFER 0
#endif

static void init_signals(void)
{
  sigset_t set;
  DBUG_ENTER("init_signals");

  sigset(THR_KILL_SIGNAL,end_thread_signal);
  sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!

  if (!(test_flags & TEST_NO_STACKTRACE) || (test_flags & TEST_CORE_ON_SIGNAL))
  {
    struct sigaction sa;
    sa.sa_flags = SA_RESETHAND | SA_NODEFER;
    sigemptyset(&sa.sa_mask);
    sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);

    init_stacktrace();
    sa.sa_handler=handle_segfault;
    sigaction(SIGSEGV, &sa, NULL);
#ifdef SIGBUS
    sigaction(SIGBUS, &sa, NULL);
#endif
    sigaction(SIGILL, &sa, NULL);
  }
  (void) sigemptyset(&set);
#ifdef THREAD_SPECIFIC_SIGPIPE
  sigset(SIGPIPE,abort_thread);
  sigaddset(&set,SIGPIPE);
#else
  (void) signal(SIGPIPE,SIG_IGN);		// Can't know which thread
  sigaddset(&set,SIGPIPE);
#endif
  sigaddset(&set,SIGINT);
  sigaddset(&set,SIGQUIT);
  sigaddset(&set,SIGTERM);
  sigaddset(&set,SIGHUP);
  sigset(SIGTERM,print_signal_warning);		// If it's blocked by parent
  signal(SIGHUP,print_signal_warning);		// If it's blocked by parent
#ifdef SIGTSTP
  sigaddset(&set,SIGTSTP);
#endif
  sigaddset(&set,THR_SERVER_ALARM);
  sigdelset(&set,THR_KILL_SIGNAL);		// May be SIGINT
  sigdelset(&set,THR_CLIENT_ALARM);		// For alarms
  (void) pthread_sigmask(SIG_SETMASK,&set,NULL);
  DBUG_VOID_RETURN;
}


static void start_signal_handler(void)
{
  int error;
  pthread_attr_t thr_attr;
  DBUG_ENTER("start_signal_handler");

  (void) pthread_attr_init(&thr_attr);
#if !defined(HAVE_DEC_3_2_THREADS)
  pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM);
  (void) pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
  if (!(opt_specialflag & SPECIAL_NO_PRIOR))
    my_pthread_attr_setprio(&thr_attr,INTERRUPT_PRIOR);
  pthread_attr_setstacksize(&thr_attr,32768);
#endif

  (void) pthread_mutex_lock(&LOCK_thread_count);
  if ((error=pthread_create(&signal_thread,&thr_attr,signal_hand,0)))
  {
    sql_print_error("Can't create interrupt-thread (error %d, errno: %d)",
		    error,errno);
    exit(1);
  }
  (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
  pthread_mutex_unlock(&LOCK_thread_count);

  (void) pthread_attr_destroy(&thr_attr);
  DBUG_VOID_RETURN;
}


/*
** This threads handles all signals and alarms
*/

/* ARGSUSED */
static void *signal_hand(void *arg __attribute__((unused)))
{
  sigset_t set;
  int sig;
  my_thread_init();				// Init new thread
  DBUG_ENTER("signal_hand");

  /* Setup alarm handler */
  init_thr_alarm(max_connections+max_insert_delayed_threads);
#if SIGINT != THR_KILL_SIGNAL
  (void) sigemptyset(&set);			// Setup up SIGINT for debug
  (void) sigaddset(&set,SIGINT);		// For debugging
  (void) pthread_sigmask(SIG_UNBLOCK,&set,NULL);
#endif
  (void) sigemptyset(&set);			// Setup up SIGINT for debug
#ifdef USE_ONE_SIGNAL_HAND
  (void) sigaddset(&set,THR_SERVER_ALARM);	// For alarms
#endif
  (void) sigaddset(&set,SIGQUIT);
  (void) sigaddset(&set,SIGTERM);
#if THR_CLIENT_ALARM != SIGHUP
  (void) sigaddset(&set,SIGHUP);
#endif
  (void) sigaddset(&set,SIGTSTP);

  /* Save pid to this process (or thread on Linux) */
  if (!opt_bootstrap)
  {
    File pidFile;
    if ((pidFile = my_create(pidfile_name,0664, O_WRONLY, MYF(MY_WME))) >= 0)
    {
      char buff[21];
      sprintf(buff,"%lu",(ulong) getpid());
      (void) my_write(pidFile, buff,strlen(buff),MYF(MY_WME));
      (void) my_close(pidFile,MYF(0));
    }
  }

  // signal to start_signal_handler that we are ready
  (void) pthread_mutex_lock(&LOCK_thread_count);
  (void) pthread_cond_signal(&COND_thread_count);
  (void) pthread_mutex_unlock(&LOCK_thread_count);

  for (;;)
  {
    int error;					// Used when debugging
    if (shutdown_in_progress && !abort_loop)
    {
      sig= MYSQL_KILL_SIGNAL;
      error=0;
    }
    else
      while ((error=my_sigwait(&set,&sig)) == EINTR) ;
    if (cleanup_done)
      pthread_exit(0);				// Safety
    switch (sig) {
    case SIGTERM:
    case SIGQUIT:
    case SIGKILL:
#ifdef EXTRA_DEBUG
      sql_print_error("Got signal %d to shutdown mysqld",sig);
#endif
      DBUG_PRINT("info",("Got signal: %d  abort_loop: %d",sig,abort_loop));
      if (!abort_loop)
      {
	abort_loop=1;				// mark abort for threads
#ifdef USE_ONE_SIGNAL_HAND
	pthread_t tmp;
	if (!(opt_specialflag & SPECIAL_NO_PRIOR))
	  my_pthread_attr_setprio(&connection_attrib,INTERRUPT_PRIOR);
	if (pthread_create(&tmp,&connection_attrib, kill_server_thread,
			   (void*) 0))
	  sql_print_error("Error: Can't create thread to kill server");
#else
	  kill_server((void*) sig);		// MIT THREAD has a alarm thread
#endif
      }
      break;
    case SIGHUP:
      reload_acl_and_cache((THD*) 0,REFRESH_LOG,
			   (TABLE_LIST*) 0); // Flush logs
      mysql_print_status((THD*) 0);		// Send debug some info
      break;
#ifdef USE_ONE_SIGNAL_HAND
    case THR_SERVER_ALARM:
      process_alarm(sig);			// Trigger alarms.
      break;
#endif
    default:
#ifdef EXTRA_DEBUG
      sql_print_error("Warning: Got signal: %d, error: %d",sig,error); /* purecov: tested */
#endif
      break;					/* purecov: tested */
    }
  }
  return(0);					/* purecov: deadcode */
}

#endif	/* __WIN__*/


/*
** All global error messages are sent here where the first one is stored for
** the client
*/


/* ARGSUSED */
static int my_message_sql(uint error, const char *str,
			  myf MyFlags __attribute__((unused)))
{
  NET *net;
  DBUG_ENTER("my_message_sql");
  DBUG_PRINT("error",("Message: '%s'",str));
  if ((net=my_pthread_getspecific_ptr(NET*,THR_NET)))
  {
    if (!net->last_error[0])			// Return only first message
    {
      strmake(net->last_error,str,sizeof(net->last_error)-1);
      net->last_errno=error ? error : ER_UNKNOWN_ERROR;
    }
  }
  else
    sql_print_error("%s: %s",my_progname,str); /* purecov: inspected */
  DBUG_RETURN(0);
}

#ifdef __WIN__

struct utsname
{
  char nodename[FN_REFLEN];
};

int uname(struct utsname *a)
{
  return -1;
}
#endif


#ifdef __WIN__
pthread_handler_decl(handle_shutdown,arg)
{
  MSG msg;
  my_thread_init();

  /* this call should create the message queue for this thread */
  PeekMessage(&msg, NULL, 1, 65534,PM_NOREMOVE);

  if (WaitForSingleObject(hEventShutdown,INFINITE)==WAIT_OBJECT_0)
     kill_server(MYSQL_KILL_SIGNAL);
  return 0;
}

int __stdcall handle_kill(ulong ctrl_type)
{
  if (ctrl_type == CTRL_CLOSE_EVENT ||
      ctrl_type == CTRL_SHUTDOWN_EVENT)
  {
    kill_server(MYSQL_KILL_SIGNAL);
    return TRUE;
  }
  return FALSE;
}
#endif

#ifdef OS2
pthread_handler_decl(handle_shutdown,arg)
{
  my_thread_init();

  // wait semaphore
  pthread_cond_wait( &eventShutdown, NULL);

  // close semaphore and kill server
  pthread_cond_destroy( &eventShutdown);

  // exit main loop on main thread, so kill will be done from
  // main thread (this is thread 2)
  abort_loop = 1;

  // unblock select()
  so_cancel( ip_sock);
  so_cancel( unix_sock);

  return 0;
}
#endif

const char *load_default_groups[]= { "mysqld","server",0 };

#ifdef HAVE_LIBWRAP
char *libwrapName=NULL;
#endif

static void open_log(MYSQL_LOG *log, const char *hostname,
		     const char *opt_name, const char *extension,
		     enum_log_type type)
{
  char tmp[FN_REFLEN];
  if (!opt_name || !opt_name[0])
  {
    /* TODO: The following should be using fn_format();  We just need to
     first change fn_format() to cut the file name if it's too long.
    */
    strmake(tmp,hostname,FN_REFLEN-5);
    strmov(strcend(tmp,'.'),extension);
    opt_name=tmp;
  }
  // get rid of extention if the log is binary to avoid problems
  if (type == LOG_BIN)
  {
    char *p = fn_ext(opt_name);
    if (p)
    {
      uint length=(uint) (p-opt_name);
      strmake(tmp,opt_name,min(length,FN_REFLEN));
      opt_name=tmp;
    }
  }
  log->open(opt_name,type);
}



#ifdef __WIN__
int win_main(int argc, char **argv)
#else
int main(int argc, char **argv)
#endif
{
  DEBUGGER_OFF;

  my_umask=0660;		// Default umask for new files
  my_umask_dir=0700;		// Default umask for new directories
  MY_INIT(argv[0]);		// init my_sys library & pthreads
  tzset();			// Set tzname

  start_time=time((time_t*) 0);
#ifdef OS2
  {
    // fix timezone for daylight saving
    struct tm *ts = localtime(&start_time);
    if (ts->tm_isdst > 0)
      _timezone -= 3600;
  }
#endif
#ifdef HAVE_TZNAME
#if defined(HAVE_LOCALTIME_R) && defined(_REENTRANT)
  {
    struct tm tm_tmp;
    localtime_r(&start_time,&tm_tmp);
    strmov(time_zone,tzname[tm_tmp.tm_isdst != 0 ? 1 : 0]);
  }
#else
  {
    struct tm *start_tm;
    start_tm=localtime(&start_time);
    strmov(time_zone,tzname[start_tm->tm_isdst != 0 ? 1 : 0]);
  }
#endif
#endif

  if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
    strmov(glob_hostname,"mysql");
  strmov(pidfile_name,glob_hostname);
  strmov(strcend(pidfile_name,'.'),".pid");	// Add extension
#ifndef DBUG_OFF
  strxmov(strend(server_version),MYSQL_SERVER_SUFFIX,"-debug",NullS);
#else
  strmov(strend(server_version),MYSQL_SERVER_SUFFIX);
#endif
#ifdef _CUSTOMSTARTUPCONFIG_
  if (_cust_check_startup())
  {
    /* _cust_check_startup will report startup failure error */
    exit( 1 );
  }
#endif
  load_defaults("my",load_default_groups,&argc,&argv);
  defaults_argv=argv;
  mysql_tmpdir=getenv("TMPDIR");	/* Use this if possible */
#if defined( __WIN__) || defined(OS2)
  if (!mysql_tmpdir)
    mysql_tmpdir=getenv("TEMP");
  if (!mysql_tmpdir)
    mysql_tmpdir=getenv("TMP");
#endif
  if (!mysql_tmpdir || !mysql_tmpdir[0])
    mysql_tmpdir=(char*) P_tmpdir;		/* purecov: inspected */

  set_options();
  get_options(argc,argv);
  if (opt_log || opt_update_log || opt_slow_log || opt_bin_log)
    strcat(server_version,"-log");
  DBUG_PRINT("info",("%s  Ver %s for %s on %s\n",my_progname,
		     server_version, SYSTEM_TYPE,MACHINE_TYPE));

  /* These must be set early */

  (void) pthread_mutex_init(&LOCK_mysql_create_db,MY_MUTEX_INIT_SLOW);
  (void) pthread_mutex_init(&LOCK_Acl,MY_MUTEX_INIT_SLOW);
  (void) pthread_mutex_init(&LOCK_grant,MY_MUTEX_INIT_FAST);
  (void) pthread_mutex_init(&LOCK_open,MY_MUTEX_INIT_FAST);
  (void) pthread_mutex_init(&LOCK_thread_count,MY_MUTEX_INIT_FAST);
  (void) pthread_mutex_init(&LOCK_mapped_file,MY_MUTEX_INIT_SLOW);
  (void) pthread_mutex_init(&LOCK_status,MY_MUTEX_INIT_FAST);
  (void) pthread_mutex_init(&LOCK_error_log,MY_MUTEX_INIT_FAST);
  (void) pthread_mutex_init(&LOCK_delayed_insert,MY_MUTEX_INIT_FAST);
  (void) pthread_mutex_init(&LOCK_delayed_status,MY_MUTEX_INIT_FAST);
  (void) pthread_mutex_init(&LOCK_delayed_create,MY_MUTEX_INIT_SLOW);
  (void) pthread_mutex_init(&LOCK_manager,MY_MUTEX_INIT_FAST);
  (void) pthread_mutex_init(&LOCK_crypt,MY_MUTEX_INIT_FAST);
  (void) pthread_mutex_init(&LOCK_bytes_sent,MY_MUTEX_INIT_FAST);
  (void) pthread_mutex_init(&LOCK_bytes_received,MY_MUTEX_INIT_FAST);
  (void) pthread_mutex_init(&LOCK_timezone,MY_MUTEX_INIT_FAST);
  (void) pthread_mutex_init(&LOCK_binlog_update, MY_MUTEX_INIT_FAST);	// QQ NOT USED
  (void) pthread_mutex_init(&LOCK_slave, MY_MUTEX_INIT_FAST);
  (void) pthread_mutex_init(&LOCK_server_id, MY_MUTEX_INIT_FAST);
  (void) pthread_mutex_init(&LOCK_user_conn, MY_MUTEX_INIT_FAST);
  (void) pthread_cond_init(&COND_thread_count,NULL);
  (void) pthread_cond_init(&COND_refresh,NULL);
  (void) pthread_cond_init(&COND_thread_cache,NULL);
  (void) pthread_cond_init(&COND_flush_thread_cache,NULL);
  (void) pthread_cond_init(&COND_manager,NULL);
  (void) pthread_cond_init(&COND_binlog_update, NULL);
  (void) pthread_cond_init(&COND_slave_stopped, NULL);
  (void) pthread_cond_init(&COND_slave_start, NULL);
  init_signals();

  if (set_default_charset_by_name(default_charset, MYF(MY_WME)))
    unireg_abort(1);
  charsets_list = list_charsets(MYF(MY_COMPILED_SETS|MY_CONFIG_SETS));

#ifdef HAVE_OPENSSL
  if (opt_use_ssl)
  {
    ssl_acceptor_fd = VioSSLAcceptorFd_new(opt_ssl_key, opt_ssl_cert,
					   opt_ssl_ca, opt_ssl_capath);
    if (!ssl_acceptor_fd)
      opt_use_ssl=0;
    /* having ssl_acceptor_fd!=0 signals the use of SSL */
  }
#endif /* HAVE_OPENSSL */

#ifdef HAVE_LIBWRAP
  libwrapName= my_progname+dirname_length(my_progname);
  openlog(libwrapName, LOG_PID, LOG_AUTH);
#endif

  if (!(opt_specialflag & SPECIAL_NO_PRIOR))
    my_pthread_setprio(pthread_self(),CONNECT_PRIOR);
  /* Parameter for threads created for connections */
  (void) pthread_attr_init(&connection_attrib);
  (void) pthread_attr_setdetachstate(&connection_attrib,
				     PTHREAD_CREATE_DETACHED);
  pthread_attr_setstacksize(&connection_attrib,thread_stack);

  if (!(opt_specialflag & SPECIAL_NO_PRIOR))
    my_pthread_attr_setprio(&connection_attrib,WAIT_PRIOR);
  pthread_attr_setscope(&connection_attrib, PTHREAD_SCOPE_SYSTEM);

#if defined( SET_RLIMIT_NOFILE) || defined( OS2)
  /* connections and databases neads lots of files */
  {
    uint wanted_files=10+(uint) max(max_connections*5,
				    max_connections+table_cache_size*2);
    set_if_bigger(wanted_files, open_files_limit);
    // Note that some system returns 0 if we succeed here:
    uint files=set_maximum_open_files(wanted_files);
    if (files && files < wanted_files && ! open_files_limit)
    {
      max_connections=	(ulong) min((files-10),max_connections);
      table_cache_size= (ulong) max((files-10-max_connections)/2,64);
      DBUG_PRINT("warning",
		 ("Changed limits: max_connections: %ld  table_cache: %ld",
		  max_connections,table_cache_size));
      sql_print_error("Warning: Changed limits: max_connections: %ld  table_cache: %ld",max_connections,table_cache_size);
    }
  }
#endif
  unireg_init(opt_specialflag); /* Set up extern variabels */
  init_errmessage();		/* Read error messages from file */
  lex_init();
  item_init();
  mysys_uses_curses=0;
#ifdef USE_REGEX
  regex_init();
#endif
  select_thread=pthread_self();
  select_thread_in_use=1;
  if (use_temp_pool && bitmap_init(&temp_pool,1024,1))
    unireg_abort(1);

  /*
  ** We have enough space for fiddling with the argv, continue
  */
  umask(((~my_umask) & 0666));
  if (my_setwd(mysql_real_data_home,MYF(MY_WME)))
  {
    unireg_abort(1);				/* purecov: inspected */
  }
  mysql_data_home[0]=FN_CURLIB;		// all paths are relative from here
  mysql_data_home[1]=0;
  server_init();
  table_cache_init();
  hostname_cache_init();
  sql_cache_init();
  randominit(&sql_rand,(ulong) start_time,(ulong) start_time/2);
  reset_floating_point_exceptions();
  init_thr_lock();

  /* Fix varibles that are base 1024*1024 */
  myisam_max_temp_length= (my_off_t) min(((ulonglong) myisam_max_sort_file_size)*1024*1024, (ulonglong) MAX_FILE_SIZE);
  myisam_max_extra_temp_length= (my_off_t) min(((ulonglong) myisam_max_extra_sort_file_size)*1024*1024, (ulonglong) MAX_FILE_SIZE);

  /* Setup log files */
  if (opt_log)
    open_log(&mysql_log, glob_hostname, opt_logname, ".log", LOG_NORMAL);
  if (opt_update_log)
  {
    open_log(&mysql_update_log, glob_hostname, opt_update_logname, "",
	     LOG_NEW);
    using_update_log=1;
  }

  //make sure slave thread gets started
  // if server_id is set, valid master.info is present, and master_host has
  // not been specified
  if(server_id && !master_host)
    {
      char fname[FN_REFLEN+128];
      MY_STAT stat_area;
      fn_format(fname, master_info_file, mysql_data_home, "", 4+16+32);
      if(my_stat(fname, &stat_area, MYF(0)) && !init_master_info(&glob_mi))
        master_host = glob_mi.host;
    }

  if (opt_bin_log && !server_id)
  {
    server_id= !master_host ? 1 : 2;
    switch (server_id) {
#ifdef EXTRA_DEBUG
    case 1:
      sql_print_error("\
Warning: You have enabled the binary log, but you haven't set server-id:\n\
Updates will be logged to the binary log, but connections to slaves will\n\
not be accepted.");
      break;
#endif
    case 2:
      sql_print_error("\
Warning: You should set server-id to a non-0 value if master_host is set.\n\
The server will not act as a slave.");
      break;
    }
  }
  if (opt_bin_log)
  {
    if (!opt_bin_logname)
    {
      char tmp[FN_REFLEN];
      /* TODO: The following should be using fn_format();  We just need to
	 first change fn_format() to cut the file name if it's too long.
      */
      strmake(tmp,glob_hostname,FN_REFLEN-5);
      strmov(strcend(tmp,'.'),"-bin");
      opt_bin_logname=my_strdup(tmp,MYF(MY_WME));
    }
    mysql_bin_log.set_index_file_name(opt_binlog_index_name);
    open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin",
	     LOG_BIN);
    using_update_log=1;
  }
  
  if (opt_slow_log)
    open_log(&mysql_slow_log, glob_hostname, opt_slow_logname, "-slow.log",
	     LOG_NORMAL);
  if (ha_init())
  {
    sql_print_error("Can't init databases");
    exit(1);
  }
  ha_key_cache();
#if defined(HAVE_MLOCKALL) && defined(MCL_CURRENT)
  if (locked_in_memory && !geteuid())
  {
    if (mlockall(MCL_CURRENT))
    {
      sql_print_error("Warning: Failed to lock memory. Errno: %d\n",errno);
    }
    else
      locked_in_memory=1;
  }
#else
  locked_in_memory=0;
#endif    

  if (opt_myisam_log)
    (void) mi_log( 1 );
  ft_init_stopwords(ft_precompiled_stopwords);       /* SerG */

#ifdef __WIN__
#define MYSQL_ERR_FILE "mysql.err"
  if (!opt_console)
  {
    freopen(MYSQL_ERR_FILE,"a+",stdout);
    freopen(MYSQL_ERR_FILE,"a+",stderr);
    FreeConsole();				// Remove window
  }
#endif

  /*
    init signals & alarm
    After this we can't quit by a simple unireg_abort
  */
  error_handler_hook = my_message_sql;
  if (pthread_key_create(&THR_THD,NULL) || pthread_key_create(&THR_NET,NULL) ||
      pthread_key_create(&THR_MALLOC,NULL))
  {
    sql_print_error("Can't create thread-keys");
    exit(1);
  }
  start_signal_handler();				// Creates pidfile
  if (acl_init(opt_noacl))
  {
    select_thread_in_use=0;
    (void) pthread_kill(signal_thread,MYSQL_KILL_SIGNAL);
#ifndef __WIN__
    if (!opt_bootstrap)
      (void) my_delete(pidfile_name,MYF(MY_WME));	// Not neaded anymore
#endif
    exit(1);
  }
  if (!opt_noacl)
    (void) grant_init();
  if (max_user_connections)
    init_max_user_conn();

#ifdef HAVE_DLOPEN
  if (!opt_noacl)
    udf_init();
#endif

  if (opt_bootstrap)
  {
    int error=bootstrap(stdin);
    end_thr_alarm();				// Don't allow alarms
    unireg_abort(error ? 1 : 0);
  }
  if (opt_init_file)
  {
    if (read_init_file(opt_init_file))
    {
      end_thr_alarm();				// Don't allow alarms
      unireg_abort(1);
    }
  }
  (void) thr_setconcurrency(concurrency);	// 10 by default
#ifdef __WIN__			        //IRENA
  {
    hEventShutdown=CreateEvent(0, FALSE, FALSE, "MySqlShutdown");
    pthread_t hThread;
    if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
      sql_print_error("Warning: Can't create thread to handle shutdown requests");

    // On "Stop Service" we have to do regular shutdown
    Service.SetShutdownEvent(hEventShutdown);
  }
#endif
#ifdef OS2
  {
    pthread_cond_init( &eventShutdown, NULL);
    pthread_t hThread;
    if (pthread_create(&hThread,&connection_attrib,handle_shutdown,0))
      sql_print_error("Warning: Can't create thread to handle shutdown requests");
  }
#endif

  if (
#ifdef HAVE_BERKELEY_DB
      !berkeley_skip ||
#endif
      (flush_time && flush_time != ~(ulong) 0L))
  {
    pthread_t hThread;
    if (pthread_create(&hThread,&connection_attrib,handle_manager,0))
      sql_print_error("Warning: Can't create thread to manage maintenance");
  }

  // slave thread
  if (master_host)
  {
    pthread_t hThread;
    if (!opt_skip_slave_start &&
       pthread_create(&hThread, &connection_attrib, handle_slave, 0))
      sql_print_error("Warning: Can't create thread to handle slave");
    else if(opt_skip_slave_start)
      init_master_info(&glob_mi);
  }

  printf(ER(ER_READY),my_progname,server_version,"");
  fflush(stdout);

#ifdef __NT__
  if (hPipe == INVALID_HANDLE_VALUE && !have_tcpip)
  {
    sql_print_error("TCP/IP must be installed on Win98 platforms");
  }
  else
  {
    pthread_mutex_lock(&LOCK_thread_count);
    (void) pthread_cond_init(&COND_handler_count,NULL);
    {
      pthread_t hThread;
      handler_count=0;
      if ( hPipe != INVALID_HANDLE_VALUE )
      {
	handler_count++;
	if (pthread_create(&hThread,&connection_attrib,
			   handle_connections_namedpipes, 0))
	{
	  sql_print_error("Warning: Can't create thread to handle named pipes");
	  handler_count--;
	}
      }
      if (have_tcpip && !opt_disable_networking)
      {
	handler_count++;
	if (pthread_create(&hThread,&connection_attrib,
			   handle_connections_sockets, 0))
	{
	  sql_print_error("Warning: Can't create thread to handle named pipes");
	  handler_count--;
	}
      }
      while (handler_count > 0)
      {
	pthread_cond_wait(&COND_handler_count,&LOCK_thread_count);
      }
    }
    pthread_mutex_unlock(&LOCK_thread_count);
  }
#else
  handle_connections_sockets(0);
#ifdef EXTRA_DEBUG
  sql_print_error("Exiting main thread");
#endif
#endif /* __NT__ */

  /* (void) pthread_attr_destroy(&connection_attrib); */

  DBUG_PRINT("quit",("Exiting main thread"));

#ifndef __WIN__
#ifdef EXTRA_DEBUG
  sql_print_error("Before Lock_thread_count");
#endif
  (void) pthread_mutex_lock(&LOCK_thread_count);
  select_thread_in_use=0;			// For close_connections
  (void) pthread_cond_broadcast(&COND_thread_count);
  (void) pthread_mutex_unlock(&LOCK_thread_count);
#ifdef EXTRA_DEBUG
  sql_print_error("After lock_thread_count");
#endif
#else
  if (Service.IsNT())
  {
    if(start_mode)
    {
      if (WaitForSingleObject(hEventShutdown,1000)==WAIT_TIMEOUT)
        Service.Stop();
    }
    else
    {
      Service.SetShutdownEvent(0);
      if(hEventShutdown) CloseHandle(hEventShutdown);
    }
  }
  else
  {
    Service.SetShutdownEvent(0);
    if(hEventShutdown) CloseHandle(hEventShutdown);
  }
#endif

  /* Wait until cleanup is done */
  (void) pthread_mutex_lock(&LOCK_thread_count);
  while (!ready_to_exit)
  {
    pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
  }
  (void) pthread_mutex_unlock(&LOCK_thread_count);
  my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
  exit(0);
  return(0);					/* purecov: deadcode */
}


#ifdef __WIN__
/* ------------------------------------------------------------------------
   main and thread entry function for Win32
   (all this is needed only to run mysqld as a service on WinNT)
 -------------------------------------------------------------------------- */
int mysql_service(void *p)
{
  win_main(Service.my_argc, Service.my_argv);
  return 0;
}

int main(int argc, char **argv)
{
  // check  environment variable OS
  if (Service.GetOS())	// "OS" defined; Should be NT
  {
    if (argc == 2)
    {
      char path[FN_REFLEN];
      my_path(path, argv[0], "");		   // Find name in path
      fn_format(path,argv[0],path,"",1+4+16);    // Force use of full path

      if (!strcmp(argv[1],"-install") || !strcmp(argv[1],"--install"))
      {
	Service.Install(1,MYSQL_SERVICENAME,MYSQL_SERVICENAME,path);
	return 0;
      }
      else if (!strcmp(argv[1],"-install-manual") || !strcmp(argv[1],"--install-manual"))
      {
        Service.Install(0,MYSQL_SERVICENAME,MYSQL_SERVICENAME,path);
	return 0;
      }
      else if (!strcmp(argv[1],"-remove") || !strcmp(argv[1],"--remove"))
      {
	Service.Remove(MYSQL_SERVICENAME);
	return 0;
      }
    }
    else if (argc == 1)		   // No arguments; start as a service
    {
      // init service
      start_mode = 1;
      long tmp=Service.Init(MYSQL_SERVICENAME,mysql_service);
      return 0;
    }
  }

  // This is a WIN95 machine or a start of mysqld as a standalone program
  // we have to pass the arguments, in case of NT-service this will be done
  // by ServiceMain()

  Service.my_argc=argc;
  Service.my_argv=argv;
  mysql_service(NULL);
  return 0;
}
/* ------------------------------------------------------------------------ */
#endif


static int bootstrap(FILE *file)
{
  THD *thd= new THD;
  int error;
  thd->bootstrap=1;
  thd->client_capabilities=0;
  my_net_init(&thd->net,(Vio*) 0);
  thd->max_packet_length=thd->net.max_packet;
  thd->master_access= ~0;
  thd->thread_id=thread_id++;
  thread_count++;

  bootstrap_file=file;
  if (pthread_create(&thd->real_id,&connection_attrib,handle_bootstrap,
		     (void*) thd))
  {
    sql_print_error("Warning: Can't create thread to handle bootstrap");    
    return -1;
  }
  /* Wait for thread to die */
  (void) pthread_mutex_lock(&LOCK_thread_count);
  while (thread_count)
  {
    (void) pthread_cond_wait(&COND_thread_count,&LOCK_thread_count);
    DBUG_PRINT("quit",("One thread died (count=%u)",thread_count));
  }
  (void) pthread_mutex_unlock(&LOCK_thread_count);
  error= thd->fatal_error;
  net_end(&thd->net);
  thd->cleanup();
  delete thd;
  return error;
}

static bool read_init_file(char *file_name)
{
  FILE *file;
  DBUG_ENTER("read_init_file");
  DBUG_PRINT("enter",("name: %s",file_name));
  if (!(file=my_fopen(file_name,O_RDONLY,MYF(MY_WME))))
    return(1);
  bootstrap(file);				/* Ignore errors from this */
  (void) my_fclose(file,MYF(MY_WME));
  return 0;
}


static void create_new_thread(THD *thd)
{
  DBUG_ENTER("create_new_thread");

  NET *net=&thd->net;				// For easy ref
  net->timeout = (uint) connect_timeout;	// Timeout for read
  if (protocol_version > 9)
    net->return_errno=1;

  /* don't allow too many connections */
  if (thread_count - delayed_insert_threads >= max_connections+1 || abort_loop)
  {
    DBUG_PRINT("error",("Too many connections"));
    close_connection(net,ER_CON_COUNT_ERROR);
    delete thd;
    DBUG_VOID_RETURN;
  }
  if (pthread_mutex_lock(&LOCK_thread_count))
  {
    DBUG_PRINT("error",("Can't lock LOCK_thread_count"));
    close_connection(net,ER_OUT_OF_RESOURCES);
    delete thd;
    DBUG_VOID_RETURN;
  }
  if (thread_count-delayed_insert_threads > max_used_connections)
    max_used_connections=thread_count-delayed_insert_threads;
  thd->thread_id=thread_id++;
  for (uint i=0; i < 8 ; i++)			// Generate password teststring
    thd->scramble[i]= (char) (rnd(&sql_rand)*94+33);
  thd->scramble[8]=0;
  thd->rand=sql_rand;
  thd->real_id=pthread_self();			// Keep purify happy

  /* Start a new thread to handle connection */
#ifdef ONE_THREAD
  if (test_flags & TEST_NO_THREADS)		// For debugging under Linux
  {
    thread_cache_size=0;			// Safety
    thread_count++;
    threads.append(thd);
    thd->real_id=pthread_self();
    (void) pthread_mutex_unlock(&LOCK_thread_count);
    handle_one_connection((void*) thd);
  }
  else
#endif
  {
    if (cached_thread_count > wake_thread)
    {
      start_cached_thread(thd);
      (void) pthread_mutex_unlock(&LOCK_thread_count);
    }
    else
    {
      int error;
      thread_count++;
      thread_created++;
      threads.append(thd);
      DBUG_PRINT("info",(("creating thread %d"), thd->thread_id));
      thd->connect_time = time(NULL);
      if ((error=pthread_create(&thd->real_id,&connection_attrib,
				handle_one_connection,
				(void*) thd)))
      {
	DBUG_PRINT("error",
		   ("Can't create thread to handle request (error %d)",
		    error));
	thread_count--;
	thd->killed=1;				// Safety
	(void) pthread_mutex_unlock(&LOCK_thread_count);
	net_printf(net,ER_CANT_CREATE_THREAD,error);
	(void) pthread_mutex_lock(&LOCK_thread_count);
	close_connection(net,0,0);
	delete thd;
	(void) pthread_mutex_unlock(&LOCK_thread_count);
	DBUG_VOID_RETURN;
      }
      
      (void) pthread_mutex_unlock(&LOCK_thread_count);
    }
  }
  DBUG_PRINT("info",("Thread created"));
  DBUG_VOID_RETURN;
}


	/* Handle new connections and spawn new process to handle them */

pthread_handler_decl(handle_connections_sockets,arg __attribute__((unused)))
{
  my_socket sock,new_sock;
  uint error_count=0;
  uint max_used_connection= (uint) (max(ip_sock,unix_sock)+1);
  fd_set readFDs,clientFDs;
  THD *thd;
  struct sockaddr_in cAddr;
  int ip_flags=0,socket_flags=0,flags;
  Vio *vio_tmp;
  DBUG_ENTER("handle_connections_sockets");

  LINT_INIT(new_sock);

  (void) my_pthread_getprio(pthread_self());		// For debugging

  FD_ZERO(&clientFDs);
  if (ip_sock != INVALID_SOCKET)
  {
    FD_SET(ip_sock,&clientFDs);
#ifdef HAVE_FCNTL
    ip_flags = fcntl(ip_sock, F_GETFL, 0);
#endif
  }
#ifdef HAVE_SYS_UN_H
  FD_SET(unix_sock,&clientFDs);
#ifdef HAVE_FCNTL
  socket_flags=fcntl(unix_sock, F_GETFL, 0);
#endif
#endif

  DBUG_PRINT("general",("Waiting for connections."));
  MAYBE_BROKEN_SYSCALL;
  while (!abort_loop)
  {
    readFDs=clientFDs;
#ifdef HPUX
    if (select(max_used_connection,(int*) &readFDs,0,0,0) < 0)
      continue;
#else
    if (select((int) max_used_connection,&readFDs,0,0,0) < 0)
    {
      if (socket_errno != SOCKET_EINTR)
      {
	if (!select_errors++ && !abort_loop)	/* purecov: inspected */
	  sql_print_error("mysqld: Got error %d from select",socket_errno); /* purecov: inspected */
      }
      MAYBE_BROKEN_SYSCALL;
      continue;
    }
#endif	/* HPUX */
    if (abort_loop)
      break;

    /*
    ** Is this a new connection request
    */

#ifdef HAVE_SYS_UN_H
    if (FD_ISSET(unix_sock,&readFDs))
    {
      sock = unix_sock;
      flags= socket_flags;
    }
    else
#endif
    {
      sock = ip_sock;
      flags= ip_flags;
    }

#if !defined(NO_FCNTL_NONBLOCK)
    if (!(test_flags & TEST_BLOCKING))
    {
#if defined(O_NONBLOCK)
      fcntl(sock, F_SETFL, flags | O_NONBLOCK);
#elif defined(O_NDELAY)
      fcntl(sock, F_SETFL, flags | O_NDELAY);
#endif
    }
#endif /* NO_FCNTL_NONBLOCK */
    for (uint retry=0; retry < MAX_ACCEPT_RETRY; retry++)
    {
      size_socket length=sizeof(struct sockaddr_in);
      new_sock = accept(sock, my_reinterpret_cast(struct sockaddr *) (&cAddr),
			&length);
      if (new_sock != INVALID_SOCKET ||
	  (socket_errno != SOCKET_EINTR && socket_errno != SOCKET_EAGAIN))
	break;
      MAYBE_BROKEN_SYSCALL;
#if !defined(NO_FCNTL_NONBLOCK)
      if (!(test_flags & TEST_BLOCKING))
      {
	if (retry == MAX_ACCEPT_RETRY - 1)
	  fcntl(sock, F_SETFL, flags);		// Try without O_NONBLOCK
      }
#endif
    }
#if !defined(NO_FCNTL_NONBLOCK)
    if (!(test_flags & TEST_BLOCKING))
      fcntl(sock, F_SETFL, flags);
#endif
    if (new_sock == INVALID_SOCKET)
    {
      if ((error_count++ & 255) == 0)		// This can happen often
	sql_perror("Error in accept");
      MAYBE_BROKEN_SYSCALL;
      if (socket_errno == SOCKET_ENFILE || socket_errno == SOCKET_EMFILE)
	sleep(1);				// Give other threads some time
      continue;
    }

#ifdef HAVE_LIBWRAP
    {
      if (sock == ip_sock)
      {
	struct request_info req;
	signal(SIGCHLD, SIG_DFL);
	request_init(&req, RQ_DAEMON, libwrapName, RQ_FILE, new_sock, NULL);
	fromhost(&req);
	if (!hosts_access(&req))
	{
	  // This may be stupid but refuse() includes an exit(0)
	  // which we surely don't want...
	  // clean_exit() - same stupid thing ...
	  syslog(deny_severity, "refused connect from %s", eval_client(&req));
	  if (req.sink)
	    ((void (*)(int))req.sink)(req.fd);

	  // C++ sucks (the gibberish in front just translates the supplied
	  // sink function pointer in the req structure from a void (*sink)();
	  // to a void(*sink)(int) if you omit the cast, the C++ compiler
	  // will cry...

	  (void) shutdown(new_sock,2);  // This looks fine to me...
	  (void) closesocket(new_sock);
	  continue;
	}
      }
    }
#endif /* HAVE_LIBWRAP */

    {
      size_socket dummyLen;
      struct sockaddr dummy;
      dummyLen = sizeof(struct sockaddr);
      if (getsockname(new_sock,&dummy, &dummyLen) < 0)
      {
	sql_perror("Error on new connection socket");
	(void) shutdown(new_sock,2);
	(void) closesocket(new_sock);
	continue;
      }
    }

    /*
    ** Don't allow too many connections
    */

    if (!(thd= new THD))
    {
      (void) shutdown(new_sock,2); VOID(closesocket(new_sock));
      continue;
    }
    if (!(vio_tmp=vio_new(new_sock,
			  sock == unix_sock ? VIO_TYPE_SOCKET :
			  VIO_TYPE_TCPIP,
			  sock == unix_sock)) ||
	my_net_init(&thd->net,vio_tmp))
    {
      if (vio_tmp)
	vio_delete(vio_tmp);
      else
      {
	(void) shutdown(new_sock,2);
	(void) closesocket(new_sock);
      }
      delete thd;
      continue;
    }
    if (sock == unix_sock)
      thd->host=(char*) localhost;
    create_new_thread(thd);
  }

#ifdef OS2
  // kill server must be invoked from thread 1!
  kill_server(MYSQL_KILL_SIGNAL);
#endif

#ifdef __NT__
  pthread_mutex_lock(&LOCK_thread_count);
  handler_count--;
  pthread_mutex_unlock(&LOCK_thread_count);
  pthread_cond_signal(&COND_handler_count);
#endif
  DBUG_RETURN(0);
}


#ifdef __NT__
pthread_handler_decl(handle_connections_namedpipes,arg)
{
  HANDLE hConnectedPipe;
  BOOL fConnected;
  THD *thd;
  my_thread_init();
  DBUG_ENTER("handle_connections_namedpipes");
  (void) my_pthread_getprio(pthread_self());		// For debugging

  DBUG_PRINT("general",("Waiting for named pipe connections."));
  while (!abort_loop)
  {
    /* wait for named pipe connection */
    fConnected = ConnectNamedPipe( hPipe, NULL );
    if (abort_loop)
      break;
    if ( !fConnected )
      fConnected = GetLastError() == ERROR_PIPE_CONNECTED;
    if ( !fConnected )
    {
      CloseHandle( hPipe );
      if ((hPipe = CreateNamedPipe(szPipeName,
				   PIPE_ACCESS_DUPLEX,
				   PIPE_TYPE_BYTE |
				   PIPE_READMODE_BYTE |
				   PIPE_WAIT,
				   PIPE_UNLIMITED_INSTANCES,
				   (int) net_buffer_length,
				   (int) net_buffer_length,
				   NMPWAIT_USE_DEFAULT_WAIT,
				   &saPipeSecurity )) ==
	  INVALID_HANDLE_VALUE )
      {
	sql_perror("Can't create new named pipe!");
	break;					// Abort
      }
    }
    hConnectedPipe = hPipe;
    /* create new pipe for new connection */
    if ((hPipe = CreateNamedPipe(szPipeName,
				 PIPE_ACCESS_DUPLEX,
				 PIPE_TYPE_BYTE |
				 PIPE_READMODE_BYTE |
				 PIPE_WAIT,
				 PIPE_UNLIMITED_INSTANCES,
				 (int) net_buffer_length,
				 (int) net_buffer_length,
				 NMPWAIT_USE_DEFAULT_WAIT,
				 &saPipeSecurity)) ==
	INVALID_HANDLE_VALUE)
    {
      sql_perror("Can't create new named pipe!");
      hPipe=hConnectedPipe;
      continue;					// We have to try again
    }

    if ( !(thd = new THD))
    {
      DisconnectNamedPipe( hConnectedPipe );
      CloseHandle( hConnectedPipe );
      continue;
    }
    if (!(thd->net.vio = vio_new_win32pipe(hConnectedPipe)) ||
	my_net_init(&thd->net, thd->net.vio))
    {
      close_connection(&thd->net,ER_OUT_OF_RESOURCES);
      delete thd;
      continue;
    }
    /* host name is unknown */
    thd->host = my_strdup(localhost,MYF(0)); /* Host is unknown */
    create_new_thread(thd);
  }

  pthread_mutex_lock(&LOCK_thread_count);
  handler_count--;
  pthread_cond_signal(&COND_handler_count);
  pthread_mutex_unlock(&LOCK_thread_count);
  DBUG_RETURN(0);
}
#endif /* __NT__ */


/******************************************************************************
** handle start options
******************************************************************************/

enum options {
               OPT_ISAM_LOG=256,            OPT_SKIP_NEW, 
               OPT_SKIP_GRANT,              OPT_SKIP_LOCK, 
               OPT_ENABLE_LOCK,             OPT_USE_LOCKING,
               OPT_SOCKET,                  OPT_UPDATE_LOG, 
               OPT_BIN_LOG,                 OPT_SKIP_RESOLVE, 
               OPT_SKIP_NETWORKING,         OPT_BIN_LOG_INDEX,
               OPT_BIND_ADDRESS,            OPT_PID_FILE,
               OPT_SKIP_PRIOR,              OPT_BIG_TABLES,    
               OPT_STANDALONE,              OPT_ONE_THREAD,
               OPT_CONSOLE,                 OPT_LOW_PRIORITY_UPDATES,
               OPT_SKIP_HOST_CACHE,         OPT_LONG_FORMAT,   
               OPT_FLUSH,                   OPT_SAFE, 
               OPT_BOOTSTRAP,               OPT_SKIP_SHOW_DB,
               OPT_TABLE_TYPE,              OPT_INIT_FILE,   
               OPT_DELAY_KEY_WRITE,         OPT_SLOW_QUERY_LOG, 
               OPT_SKIP_DELAY_KEY_WRITE,    OPT_CHARSETS_DIR,
               OPT_BDB_HOME,                OPT_BDB_LOG,  
               OPT_BDB_TMP,                 OPT_BDB_NOSYNC,
               OPT_BDB_LOCK,                OPT_BDB_SKIP, 
               OPT_BDB_NO_RECOVER,	    OPT_BDB_SHARED,
	       OPT_MASTER_HOST,             OPT_MASTER_USER,
               OPT_MASTER_PASSWORD,         OPT_MASTER_PORT,
               OPT_MASTER_INFO_FILE,        OPT_MASTER_CONNECT_RETRY,
	       OPT_MASTER_RETRY_COUNT,
               OPT_SQL_BIN_UPDATE_SAME,     OPT_REPLICATE_DO_DB,      
               OPT_REPLICATE_IGNORE_DB,     OPT_LOG_SLAVE_UPDATES,
               OPT_BINLOG_DO_DB,            OPT_BINLOG_IGNORE_DB,
               OPT_WANT_CORE,               OPT_SKIP_CONCURRENT_INSERT,
               OPT_MEMLOCK,                 OPT_MYISAM_RECOVER,
               OPT_REPLICATE_REWRITE_DB,    OPT_SERVER_ID, 
               OPT_SKIP_SLAVE_START,        OPT_SKIP_INNOBASE,
               OPT_SAFEMALLOC_MEM_LIMIT,    OPT_REPLICATE_DO_TABLE, 
               OPT_REPLICATE_IGNORE_TABLE,  OPT_REPLICATE_WILD_DO_TABLE, 
               OPT_REPLICATE_WILD_IGNORE_TABLE, 
               OPT_DISCONNECT_SLAVE_EVENT_COUNT, 
               OPT_ABORT_SLAVE_EVENT_COUNT,
	       OPT_INNODB_DATA_HOME_DIR,
               OPT_INNODB_DATA_FILE_PATH,
	       OPT_INNODB_LOG_GROUP_HOME_DIR, 
               OPT_INNODB_LOG_ARCH_DIR, 
               OPT_INNODB_LOG_ARCHIVE, 
               OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT, 
               OPT_INNODB_FAST_SHUTDOWN, 
               OPT_INNODB_UNIX_FILE_FLUSH_METHOD,
               OPT_SAFE_SHOW_DB,
	       OPT_GEMINI_SKIP, OPT_INNODB_SKIP,
               OPT_TEMP_POOL, OPT_TX_ISOLATION,
	       OPT_GEMINI_FLUSH_LOG, OPT_GEMINI_RECOVER,
               OPT_GEMINI_UNBUFFERED_IO, OPT_SKIP_SAFEMALLOC,
	       OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
	       OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL,
	       OPT_SAFE_USER_CREATE, OPT_SQL_MODE,
	       OPT_SLAVE_SKIP_ERRORS, OPT_LOCAL_INFILE
};

static struct option long_options[] = {
  {"ansi",                  no_argument,       0, 'a'},
  {"basedir",               required_argument, 0, 'b'},
#ifdef HAVE_BERKELEY_DB
  {"bdb-home",              required_argument, 0, (int) OPT_BDB_HOME},
  {"bdb-lock-detect",       required_argument, 0, (int) OPT_BDB_LOCK},
  {"bdb-logdir",            required_argument, 0, (int) OPT_BDB_LOG},
  {"bdb-no-recover",        no_argument,       0, (int) OPT_BDB_NO_RECOVER},
  {"bdb-no-sync",           no_argument,       0, (int) OPT_BDB_NOSYNC},
  {"bdb-shared-data",       no_argument,       0, (int) OPT_BDB_SHARED},
  {"bdb-tmpdir",            required_argument, 0, (int) OPT_BDB_TMP},
#endif
  {"big-tables",            no_argument,       0, (int) OPT_BIG_TABLES},
  {"binlog-do-db",          required_argument, 0, (int) OPT_BINLOG_DO_DB},
  {"binlog-ignore-db",      required_argument, 0, (int) OPT_BINLOG_IGNORE_DB},
  {"bind-address",          required_argument, 0, (int) OPT_BIND_ADDRESS},
  {"bootstrap",             no_argument,       0, (int) OPT_BOOTSTRAP},
#ifdef __WIN__
  {"console",               no_argument,       0, (int) OPT_CONSOLE},
#endif
  {"core-file",             no_argument,       0, (int) OPT_WANT_CORE},
  {"chroot",                required_argument, 0, 'r'},
  {"character-sets-dir",    required_argument, 0, (int) OPT_CHARSETS_DIR},
  {"datadir",               required_argument, 0, 'h'},
  {"debug",                 optional_argument, 0, '#'},
  {"default-character-set", required_argument, 0, 'C'},
  {"default-table-type",    required_argument, 0, (int) OPT_TABLE_TYPE},
  {"delay-key-write-for-all-tables",
                            no_argument,       0, (int) OPT_DELAY_KEY_WRITE},
  {"enable-locking",        no_argument,       0, (int) OPT_ENABLE_LOCK},
  {"exit-info",             optional_argument, 0, 'T'},
  {"flush",                 no_argument,       0, (int) OPT_FLUSH},
#ifdef HAVE_GEMINI_DB
  {"gemini-flush-log-at-commit",no_argument,   0, (int) OPT_GEMINI_FLUSH_LOG},
  {"gemini-recovery",	    required_argument, 0, (int) OPT_GEMINI_RECOVER},
  {"gemini-unbuffered-io",  no_argument,       0, (int) OPT_GEMINI_UNBUFFERED_IO},
#endif
  /* We must always support this option to make scripts like mysqltest easier
     to do */
  {"innodb_data_file_path", required_argument, 0,
     OPT_INNODB_DATA_FILE_PATH},
#ifdef HAVE_INNOBASE_DB
  {"innodb_data_home_dir", required_argument, 0,
     OPT_INNODB_DATA_HOME_DIR},
  {"innodb_log_group_home_dir", required_argument, 0,
    OPT_INNODB_LOG_GROUP_HOME_DIR},
  {"innodb_log_arch_dir", required_argument, 0,
    OPT_INNODB_LOG_ARCH_DIR},
  {"innodb_log_archive", optional_argument, 0,
     OPT_INNODB_LOG_ARCHIVE},
  {"innodb_flush_log_at_trx_commit", optional_argument, 0,
     OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT},
  {"innodb_fast_shutdown", optional_argument, 0,
     OPT_INNODB_FAST_SHUTDOWN},
  {"innodb_flush_method", required_argument, 0,
    OPT_INNODB_UNIX_FILE_FLUSH_METHOD},
#endif
  {"help",                  no_argument,       0, '?'},
  {"init-file",             required_argument, 0, (int) OPT_INIT_FILE},
  {"log",                   optional_argument, 0, 'l'},
  {"language",              required_argument, 0, 'L'},
  {"local-infile",	    optional_argument, 0, (int) OPT_LOCAL_INFILE},
  {"log-bin",               optional_argument, 0, (int) OPT_BIN_LOG},
  {"log-bin-index",         required_argument, 0, (int) OPT_BIN_LOG_INDEX},
  {"log-isam",              optional_argument, 0, (int) OPT_ISAM_LOG},
  {"log-update",            optional_argument, 0, (int) OPT_UPDATE_LOG},
  {"log-slow-queries",      optional_argument, 0, (int) OPT_SLOW_QUERY_LOG},
  {"log-long-format",       no_argument,       0, (int) OPT_LONG_FORMAT},
  {"log-slave-updates",     no_argument,       0, (int) OPT_LOG_SLAVE_UPDATES},
  {"low-priority-updates",  no_argument,       0, (int) OPT_LOW_PRIORITY_UPDATES},
  {"master-host",           required_argument, 0, (int) OPT_MASTER_HOST},
  {"master-user",           required_argument, 0, (int) OPT_MASTER_USER},
  {"master-password",       required_argument, 0, (int) OPT_MASTER_PASSWORD},
  {"master-port",           required_argument, 0, (int) OPT_MASTER_PORT},
  {"master-connect-retry",  required_argument, 0, (int) OPT_MASTER_CONNECT_RETRY},
  {"master-retry-count",    required_argument, 0, (int) OPT_MASTER_RETRY_COUNT},
  {"master-info-file",      required_argument, 0, (int) OPT_MASTER_INFO_FILE},
  {"myisam-recover",	    optional_argument, 0, (int) OPT_MYISAM_RECOVER},
  {"memlock",		    no_argument,       0, (int) OPT_MEMLOCK},
    // needs to be available for the test case to pass in non-debugging mode
    // is a no-op
  {"disconnect-slave-event-count",      required_argument, 0,
     (int) OPT_DISCONNECT_SLAVE_EVENT_COUNT},
  {"abort-slave-event-count",      required_argument, 0,
     (int) OPT_ABORT_SLAVE_EVENT_COUNT},
  {"max-binlog-dump-events",      required_argument, 0,
     (int) OPT_MAX_BINLOG_DUMP_EVENTS},
  {"sporadic-binlog-dump-fail", no_argument, 0,
     (int) OPT_SPORADIC_BINLOG_DUMP_FAIL},
  {"safemalloc-mem-limit",  required_argument, 0, (int)
     OPT_SAFEMALLOC_MEM_LIMIT},
  {"new",                   no_argument,       0, 'n'},
  {"old-protocol",          no_argument,       0, 'o'},
#ifdef ONE_THREAD
  {"one-thread",            no_argument,       0, (int) OPT_ONE_THREAD},
#endif
  {"pid-file",              required_argument, 0, (int) OPT_PID_FILE},
  {"port",                  required_argument, 0, 'P'},
  {"replicate-do-db",       required_argument, 0, (int) OPT_REPLICATE_DO_DB},
  {"replicate-do-table",       required_argument, 0,
   (int) OPT_REPLICATE_DO_TABLE},
  {"replicate-wild-do-table",       required_argument, 0,
   (int) OPT_REPLICATE_WILD_DO_TABLE},
  {"replicate-ignore-db",   required_argument, 0,
   (int) OPT_REPLICATE_IGNORE_DB},
  {"replicate-ignore-table",   required_argument, 0,
   (int) OPT_REPLICATE_IGNORE_TABLE},
  {"replicate-wild-ignore-table",   required_argument, 0,
   (int) OPT_REPLICATE_WILD_IGNORE_TABLE},
  {"replicate-rewrite-db",   required_argument, 0,
     (int) OPT_REPLICATE_REWRITE_DB},
  {"safe-mode",             no_argument,       0, (int) OPT_SAFE},
  {"safe-show-database",    no_argument,       0, (int) OPT_SAFE_SHOW_DB},
  {"safe-user-create",	    no_argument,       0, (int) OPT_SAFE_USER_CREATE},
  {"server-id",		    required_argument, 0, (int) OPT_SERVER_ID},
  {"set-variable",          required_argument, 0, 'O'},
  {"skip-bdb",              no_argument,       0, (int) OPT_BDB_SKIP},
  {"skip-innodb",           no_argument,       0, (int) OPT_INNODB_SKIP},
  {"skip-gemini",           no_argument,       0, (int) OPT_GEMINI_SKIP},
  {"skip-concurrent-insert", no_argument,      0, (int) OPT_SKIP_CONCURRENT_INSERT},
  {"skip-delay-key-write",  no_argument,       0, (int) OPT_SKIP_DELAY_KEY_WRITE},
  {"skip-grant-tables",     no_argument,       0, (int) OPT_SKIP_GRANT},
  {"skip-locking",          no_argument,       0, (int) OPT_SKIP_LOCK},
  {"skip-host-cache",       no_argument,       0, (int) OPT_SKIP_HOST_CACHE},
  {"skip-name-resolve",     no_argument,       0, (int) OPT_SKIP_RESOLVE},
  {"skip-networking",       no_argument,       0, (int) OPT_SKIP_NETWORKING},
  {"skip-new",              no_argument,       0, (int) OPT_SKIP_NEW},
  {"skip-safemalloc",	    no_argument,       0, (int) OPT_SKIP_SAFEMALLOC},
  {"skip-show-database",    no_argument,       0, (int) OPT_SKIP_SHOW_DB},
  {"skip-slave-start",      no_argument,       0, (int) OPT_SKIP_SLAVE_START},
  {"skip-stack-trace",	    no_argument,       0, (int) OPT_SKIP_STACK_TRACE},
  {"skip-symlink",	    no_argument,       0, (int) OPT_SKIP_SYMLINKS},
  {"skip-thread-priority",  no_argument,       0, (int) OPT_SKIP_PRIOR},
  {"slave-skip-errors", required_argument,0,
   (int) OPT_SLAVE_SKIP_ERRORS},
  {"socket",                required_argument, 0, (int) OPT_SOCKET},
  {"sql-bin-update-same",   no_argument,       0, (int) OPT_SQL_BIN_UPDATE_SAME},
  {"sql-mode",              required_argument, 0, (int) OPT_SQL_MODE},
#include "sslopt-longopts.h"
#ifdef __WIN__
  {"standalone",            no_argument,       0, (int) OPT_STANDALONE},
#endif
  {"transaction-isolation", required_argument, 0, (int) OPT_TX_ISOLATION},
  {"temp-pool",             no_argument,       0, (int) OPT_TEMP_POOL},
  {"tmpdir",                required_argument, 0, 't'},
  {"use-locking",           no_argument,       0, (int) OPT_USE_LOCKING},
#ifdef USE_SYMDIR
  {"use-symbolic-links",    no_argument,       0, 's'},
#endif
  {"user",                  required_argument, 0, 'u'},
  {"version",               no_argument,       0, 'V'},
  {"warnings",		    no_argument,       0, 'W'},
  {0, 0, 0, 0}
};

#define LONG_TIMEOUT ((ulong) 3600L*24L*365L)

CHANGEABLE_VAR changeable_vars[] = {
  { "back_log",                (long*) &back_log, 
      50, 1, 65535, 0, 1 },
#ifdef HAVE_BERKELEY_DB
  { "bdb_cache_size",          (long*) &berkeley_cache_size, 
      KEY_CACHE_SIZE, 20*1024, (long) ~0, 0, IO_SIZE },
  {"bdb_log_buffer_size",      (long*) &berkeley_log_buffer_size, 0, 256*1024L,
     ~0L, 0, 1024},
  { "bdb_max_lock",            (long*) &berkeley_max_lock, 
      10000, 0, (long) ~0, 0, 1 },
    /* QQ: The following should be removed soon! */
  { "bdb_lock_max",            (long*) &berkeley_max_lock, 
      10000, 0, (long) ~0, 0, 1 },
#endif
  { "binlog_cache_size",       (long*) &binlog_cache_size,
      32*1024L, IO_SIZE, ~0L, 0, IO_SIZE },
  { "connect_timeout",         (long*) &connect_timeout,
      CONNECT_TIMEOUT, 2, LONG_TIMEOUT, 0, 1 },
  { "delayed_insert_timeout",  (long*) &delayed_insert_timeout, 
      DELAYED_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1 },
  { "delayed_insert_limit",    (long*) &delayed_insert_limit, 
      DELAYED_LIMIT, 1, ~0L, 0, 1 },
  { "delayed_queue_size",      (long*) &delayed_queue_size,
      DELAYED_QUEUE_SIZE, 1, ~0L, 0, 1 },
  { "flush_time",              (long*) &flush_time,
      FLUSH_TIME, 0, LONG_TIMEOUT, 0, 1 },
#ifdef HAVE_GEMINI_DB
  { "gemini_buffer_cache",     (long*) &gemini_buffer_cache,
      128 * 8192, 16, LONG_MAX, 0, 1 },
  { "gemini_connection_limit", (long*) &gemini_connection_limit,
      100, 10, LONG_MAX, 0, 1 },
  { "gemini_io_threads",       (long*) &gemini_io_threads,
      2, 0, 256, 0, 1 },
  { "gemini_log_cluster_size", (long*) &gemini_log_cluster_size,
      256 * 1024, 16 * 1024, LONG_MAX, 0, 1 },
  { "gemini_lock_table_size",  (long*) &gemini_locktablesize,
      4096, 1024, LONG_MAX, 0, 1 },
  { "gemini_lock_wait_timeout",(long*) &gemini_lock_wait_timeout,
      10, 1, LONG_MAX, 0, 1 },
  { "gemini_spin_retries",     (long*) &gemini_spin_retries,
      1, 0, LONG_MAX, 0, 1 },
#endif
#ifdef HAVE_INNOBASE_DB
  {"innodb_mirrored_log_groups",
   (long*) &innobase_mirrored_log_groups, 1, 1, 10, 0, 1},
  {"innodb_log_files_in_group",
     (long*) &innobase_log_files_in_group, 2, 2, 100, 0, 1},
  {"innodb_log_file_size",
     (long*) &innobase_log_file_size, 5*1024*1024L, 1*1024*1024L,
     ~0L, 0, 1024*1024L},
  {"innodb_log_buffer_size",
     (long*) &innobase_log_buffer_size, 1024*1024L, 256*1024L,
     ~0L, 0, 1024},
  {"innodb_buffer_pool_size",
     (long*) &innobase_buffer_pool_size, 8*1024*1024L, 1024*1024L,
     ~0L, 0, 1024*1024L},
  {"innodb_additional_mem_pool_size",
   (long*) &innobase_additional_mem_pool_size, 1*1024*1024L, 512*1024L,
     ~0L, 0, 1024},
  {"innodb_file_io_threads",
     (long*) &innobase_file_io_threads, 4, 4, 64, 0, 1},
  {"innodb_lock_wait_timeout",
     (long*) &innobase_lock_wait_timeout, 50, 1,
						1024 * 1024 * 1024, 0, 1},
  {"innodb_thread_concurrency",
     (long*) &innobase_thread_concurrency, 8, 1, 1000, 0, 1},
  {"innodb_force_recovery",
     (long*) &innobase_force_recovery, 0, 0, 6, 0, 1},
#endif
  { "interactive_timeout",     (long*) &net_interactive_timeout,
      NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1 },
  { "join_buffer_size",        (long*) &join_buff_size,
      128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE },
  { "key_buffer_size",         (long*) &keybuff_size,
      KEY_CACHE_SIZE, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD, IO_SIZE },
  { "long_query_time",         (long*) &long_query_time,
      10, 1, LONG_TIMEOUT, 0, 1 },
  { "lower_case_table_names",  (long*) &lower_case_table_names,
      IF_WIN(1,0), 0, 1, 0, 1 },
  { "max_allowed_packet",      (long*) &max_allowed_packet,
      1024*1024L, 80, 64*1024*1024L, MALLOC_OVERHEAD, 1024 },
  { "max_binlog_cache_size",   (long*) &max_binlog_cache_size,
      ~0L, IO_SIZE, ~0L, 0, IO_SIZE },
  { "max_binlog_size",         (long*) &max_binlog_size,
      1024*1024L*1024L, 1024, 1024*1024L*1024L, 0, 1 },
  { "max_connections",         (long*) &max_connections,
      100, 1, 16384, 0, 1 },
  { "max_connect_errors",      (long*) &max_connect_errors,
      MAX_CONNECT_ERRORS, 1, ~0L, 0, 1 },
  { "max_delayed_threads",     (long*) &max_insert_delayed_threads,
      20, 1, 16384, 0, 1 },
  { "max_heap_table_size",     (long*) &max_heap_table_size,
      16*1024*1024L, 16384, ~0L, MALLOC_OVERHEAD, 1024 },
  { "max_join_size",           (long*) &max_join_size,
      ~0L, 1, ~0L, 0, 1 },
  { "max_sort_length",         (long*) &max_item_sort_length,
      1024, 4, 8192*1024L, 0, 1 },
  { "max_tmp_tables",          (long*) &max_tmp_tables,
      32, 1, ~0L, 0, 1 },
  { "max_user_connections",    (long*) &max_user_connections,
      0, 1, ~0L, 0, 1 },
  { "max_write_lock_count",    (long*) &max_write_lock_count,
      ~0L, 1, ~0L, 0, 1 },
  { "myisam_max_extra_sort_file_size",
    (long*) &myisam_max_extra_sort_file_size,
    (long) (MI_MAX_TEMP_LENGTH/(1024L*1024L)), 0, ~0L, 0, 1 },
  { "myisam_max_sort_file_size", (long*) &myisam_max_sort_file_size,
    (long) (LONG_MAX/(1024L*1024L)), 0, ~0L, 0, 1 },
  { "myisam_sort_buffer_size", (long*) &myisam_sort_buffer_size,
      8192*1024, 4, ~0L, 0, 1 },
  { "net_buffer_length",       (long*) &net_buffer_length,
      16384, 1024, 1024*1024L, MALLOC_OVERHEAD, 1024 },
  { "net_retry_count",         (long*) &mysqld_net_retry_count,
      MYSQLD_NET_RETRY_COUNT, 1, ~0L, 0, 1 },
  { "net_read_timeout",        (long*) &net_read_timeout, 
      NET_READ_TIMEOUT, 1, LONG_TIMEOUT, 0, 1 },
  { "net_write_timeout",       (long*) &net_write_timeout,
      NET_WRITE_TIMEOUT, 1, LONG_TIMEOUT, 0, 1 },
  { "open_files_limit",        (long*) &open_files_limit,
      0, 0, 65535, 0, 1},
  { "query_buffer_size",       (long*) &query_buff_size,
      0, MALLOC_OVERHEAD, (long) ~0, MALLOC_OVERHEAD, IO_SIZE },
  { "record_buffer",           (long*) &my_default_record_cache_size,
      128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE },
  { "record_rnd_buffer",           (long*) &record_rnd_cache_size,
      0, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE },
  { "slave_net_timeout",        (long*) &slave_net_timeout, 
      SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1 },
  { "slow_launch_time",        (long*) &slow_launch_time, 
      2L, 0L, LONG_TIMEOUT, 0, 1 },
  { "sort_buffer",             (long*) &sortbuff_size,
      MAX_SORT_MEMORY, MIN_SORT_MEMORY+MALLOC_OVERHEAD*2, ~0L, MALLOC_OVERHEAD, 1 },
  { "table_cache",             (long*) &table_cache_size,
      64, 1, 16384, 0, 1 },
  { "thread_concurrency",      (long*) &concurrency,
      DEFAULT_CONCURRENCY, 1, 512, 0, 1 },
  { "thread_cache_size",       (long*) &thread_cache_size,
      0, 0, 16384, 0, 1 },
  { "tmp_table_size",          (long*) &tmp_table_size,
    32*1024*1024L, 1024, ~0L, 0, 1 },
  { "thread_stack",            (long*) &thread_stack,
      DEFAULT_THREAD_STACK, 1024*32, ~0L, 0, 1024 },
  { "wait_timeout",            (long*) &net_wait_timeout,
      NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1 },
  { NullS, (long*) 0, 0, 0, 0, 0, 0}
};


struct show_var_st init_vars[]= {
  {"back_log",                (char*) &back_log,                    SHOW_LONG},
  {"basedir",                 mysql_home,                           SHOW_CHAR},
#ifdef HAVE_BERKELEY_DB
  {"bdb_cache_size",          (char*) &berkeley_cache_size,         SHOW_LONG},
  {"bdb_log_buffer_size",     (char*) &berkeley_log_buffer_size,    SHOW_LONG},
  {"bdb_home",                (char*) &berkeley_home,               SHOW_CHAR_PTR},
  {"bdb_max_lock",            (char*) &berkeley_max_lock,	    SHOW_LONG},
  {"bdb_logdir",              (char*) &berkeley_logdir,             SHOW_CHAR_PTR},
  {"bdb_shared_data",	      (char*) &berkeley_shared_data,	    SHOW_BOOL},
  {"bdb_tmpdir",              (char*) &berkeley_tmpdir,             SHOW_CHAR_PTR},
  {"bdb_version",             (char*) DB_VERSION_STRING,            SHOW_CHAR},
#endif
  {"binlog_cache_size",       (char*) &binlog_cache_size,	    SHOW_LONG},
  {"character_set",           default_charset,                      SHOW_CHAR},
  {"character_sets",          (char*) &charsets_list,               SHOW_CHAR_PTR},
  {"concurrent_insert",       (char*) &myisam_concurrent_insert,    SHOW_MY_BOOL},
  {"connect_timeout",         (char*) &connect_timeout,             SHOW_LONG},
  {"datadir",                 mysql_real_data_home,                 SHOW_CHAR},
  {"delay_key_write",         (char*) &myisam_delay_key_write,      SHOW_MY_BOOL},
  {"delayed_insert_limit",    (char*) &delayed_insert_limit,        SHOW_LONG},
  {"delayed_insert_timeout",  (char*) &delayed_insert_timeout,      SHOW_LONG},
  {"delayed_queue_size",      (char*) &delayed_queue_size,          SHOW_LONG},
  {"flush",                   (char*) &myisam_flush,                SHOW_MY_BOOL},
  {"flush_time",              (char*) &flush_time,                  SHOW_LONG},
#ifdef HAVE_GEMINI_DB
  {"gemini_buffer_cache",     (char*) &gemini_buffer_cache,         SHOW_LONG},
  {"gemini_connection_limit", (char*) &gemini_connection_limit,     SHOW_LONG},
  {"gemini_io_threads",       (char*) &gemini_io_threads,           SHOW_LONG},
  {"gemini_log_cluster_size", (char*) &gemini_log_cluster_size,     SHOW_LONG}, 
  {"gemini_lock_table_size",  (char*) &gemini_locktablesize,        SHOW_LONG}, 
  {"gemini_lock_wait_timeout",(char*) &gemini_lock_wait_timeout,    SHOW_LONG}, 
  {"gemini_recovery_options", (char*) &gemini_recovery_options_str, SHOW_CHAR_PTR},
  {"gemini_spin_retries",     (char*) &gemini_spin_retries,         SHOW_LONG},
#endif
  {"have_bdb",		      (char*) &have_berkeley_db,	    SHOW_HAVE},
  {"have_gemini",	      (char*) &have_gemini,		    SHOW_HAVE},
  {"have_innodb",	      (char*) &have_innodb,		    SHOW_HAVE},
  {"have_isam",	      	      (char*) &have_isam,		    SHOW_HAVE},
  {"have_raid",		      (char*) &have_raid,		    SHOW_HAVE},
  {"have_openssl",	      (char*) &have_ssl,		    SHOW_HAVE},
  {"init_file",               (char*) &opt_init_file,               SHOW_CHAR_PTR},
#ifdef HAVE_INNOBASE_DB
  {"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG },
  {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONG },
  {"innodb_data_file_path", (char*) &innobase_data_file_path,	    SHOW_CHAR_PTR},
  {"innodb_data_home_dir",  (char*) &innobase_data_home_dir,	    SHOW_CHAR_PTR},
  {"innodb_file_io_threads", (char*) &innobase_file_io_threads, SHOW_LONG },
  {"innodb_force_recovery", (char*) &innobase_force_recovery, SHOW_LONG },
  {"innodb_thread_concurrency", (char*) &innobase_thread_concurrency, SHOW_LONG },
  {"innodb_flush_log_at_trx_commit", (char*) &innobase_flush_log_at_trx_commit, SHOW_MY_BOOL},
  {"innodb_fast_shutdown", (char*) &innobase_fast_shutdown, SHOW_MY_BOOL},
  {"innodb_flush_method",    (char*) &innobase_unix_file_flush_method, SHOW_CHAR_PTR},
  {"innodb_lock_wait_timeout", (char*) &innobase_lock_wait_timeout, SHOW_LONG },
  {"innodb_log_arch_dir",   (char*) &innobase_log_arch_dir, 	    SHOW_CHAR_PTR},
  {"innodb_log_archive",    (char*) &innobase_log_archive, 	    SHOW_MY_BOOL},
  {"innodb_log_buffer_size", (char*) &innobase_log_buffer_size, SHOW_LONG },
  {"innodb_log_file_size", (char*) &innobase_log_file_size, SHOW_LONG},
  {"innodb_log_files_in_group", (char*) &innobase_log_files_in_group,	SHOW_LONG},
  {"innodb_log_group_home_dir", (char*) &innobase_log_group_home_dir, SHOW_CHAR_PTR},
  {"innodb_mirrored_log_groups", (char*) &innobase_mirrored_log_groups, SHOW_LONG},
#endif
  {"interactive_timeout",     (char*) &net_interactive_timeout,     SHOW_LONG},
  {"join_buffer_size",        (char*) &join_buff_size,              SHOW_LONG},
  {"key_buffer_size",         (char*) &keybuff_size,                SHOW_LONG},
  {"language",                language,                             SHOW_CHAR},
  {"large_files_support",     (char*) &opt_large_files,             SHOW_BOOL},	
#ifdef HAVE_MLOCKALL
  {"locked_in_memory",	      (char*) &locked_in_memory,	    SHOW_BOOL},
#endif
  {"log",                     (char*) &opt_log,                     SHOW_BOOL},
  {"log_update",              (char*) &opt_update_log,              SHOW_BOOL},
  {"log_bin",                 (char*) &opt_bin_log,                 SHOW_BOOL},
  {"log_slave_updates",       (char*) &opt_log_slave_updates,       SHOW_BOOL},
  {"log_long_queries",        (char*) &opt_slow_log,                SHOW_BOOL},
  {"long_query_time",         (char*) &long_query_time,             SHOW_LONG},
  {"low_priority_updates",    (char*) &low_priority_updates,        SHOW_BOOL},
  {"lower_case_table_names",  (char*) &lower_case_table_names,      SHOW_LONG},
  {"max_allowed_packet",      (char*) &max_allowed_packet,          SHOW_LONG},
  {"max_binlog_cache_size",   (char*) &max_binlog_cache_size,	    SHOW_LONG},
  {"max_binlog_size",         (char*) &max_binlog_size,	            SHOW_LONG},
  {"max_connections",         (char*) &max_connections,             SHOW_LONG},
  {"max_connect_errors",      (char*) &max_connect_errors,          SHOW_LONG},
  {"max_delayed_threads",     (char*) &max_insert_delayed_threads,  SHOW_LONG},
  {"max_heap_table_size",     (char*) &max_heap_table_size,         SHOW_LONG},
  {"max_join_size",           (char*) &max_join_size,               SHOW_LONG},
  {"max_sort_length",         (char*) &max_item_sort_length,        SHOW_LONG},
  {"max_user_connections",    (char*) &max_user_connections,        SHOW_LONG},
  {"max_tmp_tables",          (char*) &max_tmp_tables,              SHOW_LONG},
  {"max_write_lock_count",    (char*) &max_write_lock_count,        SHOW_LONG},
  {"myisam_max_extra_sort_file_size", (char*) &myisam_max_extra_sort_file_size,
   SHOW_LONG},
  {"myisam_max_sort_file_size",(char*) &myisam_max_sort_file_size,  SHOW_LONG},
  {"myisam_recover_options",  (char*) &myisam_recover_options,      SHOW_LONG},
  {"myisam_sort_buffer_size", (char*) &myisam_sort_buffer_size,     SHOW_LONG},
  {"net_buffer_length",       (char*) &net_buffer_length,           SHOW_LONG},
  {"net_read_timeout",        (char*) &net_read_timeout,	    SHOW_LONG},
  {"net_retry_count",         (char*) &mysqld_net_retry_count,      SHOW_LONG},
  {"net_write_timeout",       (char*) &net_write_timeout,	    SHOW_LONG},
  {"open_files_limit",	      (char*) &open_files_limit,	    SHOW_LONG},
  {"pid_file",                (char*) pidfile_name,                 SHOW_CHAR},
  {"port",                    (char*) &mysql_port,                  SHOW_INT},
  {"protocol_version",        (char*) &protocol_version,            SHOW_INT},
  {"record_buffer",           (char*) &my_default_record_cache_size,SHOW_LONG},
  {"record_rnd_buffer",       (char*) &record_rnd_cache_size,	    SHOW_LONG},
  {"query_buffer_size",       (char*) &query_buff_size,		    SHOW_LONG},
  {"safe_show_database",      (char*) &opt_safe_show_db,            SHOW_BOOL},
  {"server_id",               (char*) &server_id,		    SHOW_LONG},
  {"slave_net_timeout",       (char*) &slave_net_timeout,	    SHOW_LONG},
  {"skip_locking",            (char*) &my_disable_locking,          SHOW_MY_BOOL},
  {"skip_networking",         (char*) &opt_disable_networking,      SHOW_BOOL},
  {"skip_show_database",      (char*) &opt_skip_show_db,            SHOW_BOOL},
  {"slow_launch_time",        (char*) &slow_launch_time,            SHOW_LONG},
  {"socket",                  (char*) &mysql_unix_port,             SHOW_CHAR_PTR},
  {"sort_buffer",             (char*) &sortbuff_size,               SHOW_LONG},
  {"sql_mode",                (char*) &opt_sql_mode,                SHOW_LONG},
  {"table_cache",             (char*) &table_cache_size,            SHOW_LONG},
  {"table_type",              (char*) &default_table_type_name,     SHOW_CHAR_PTR},
  {"thread_cache_size",       (char*) &thread_cache_size,           SHOW_LONG},
#ifdef HAVE_THR_SETCONCURRENCY
  {"thread_concurrency",      (char*) &concurrency,                 SHOW_LONG},
#endif
  {"thread_stack",            (char*) &thread_stack,                SHOW_LONG},
  {"transaction_isolation",   (char*) &default_tx_isolation_name,   SHOW_CHAR_PTR},
#ifdef HAVE_TZNAME
  {"timezone",                time_zone,                            SHOW_CHAR},
#endif
  {"tmp_table_size",          (char*) &tmp_table_size,              SHOW_LONG},
  {"tmpdir",                  (char*) &mysql_tmpdir,                SHOW_CHAR_PTR},
  {"version",                 server_version,                       SHOW_CHAR},
  {"wait_timeout",            (char*) &net_wait_timeout,            SHOW_LONG},
  {NullS, NullS, SHOW_LONG}
};

struct show_var_st status_vars[]= {
  {"Aborted_clients",          (char*) &aborted_threads,        SHOW_LONG},
  {"Aborted_connects",         (char*) &aborted_connects,       SHOW_LONG},
  {"Bytes_received",           (char*) &bytes_received,         SHOW_LONG},
  {"Bytes_sent",               (char*) &bytes_sent,             SHOW_LONG},
  {"Com_admin_commands",       (char*) &com_other,		SHOW_LONG},
  {"Com_alter_table",	       (char*) (com_stat+(uint) SQLCOM_ALTER_TABLE),SHOW_LONG},
  {"Com_analyze",	       (char*) (com_stat+(uint) SQLCOM_ANALYZE),SHOW_LONG},
  {"Com_backup_table",	       (char*) (com_stat+(uint) SQLCOM_BACKUP_TABLE),SHOW_LONG},
  {"Com_begin",		       (char*) (com_stat+(uint) SQLCOM_BEGIN),SHOW_LONG},
  {"Com_change_db",	       (char*) (com_stat+(uint) SQLCOM_CHANGE_DB),SHOW_LONG},
  {"Com_change_master",	       (char*) (com_stat+(uint) SQLCOM_CHANGE_MASTER),SHOW_LONG},
  {"Com_check",		       (char*) (com_stat+(uint) SQLCOM_CHECK),SHOW_LONG},
  {"Com_commit",	       (char*) (com_stat+(uint) SQLCOM_COMMIT),SHOW_LONG},
  {"Com_create_db",	       (char*) (com_stat+(uint) SQLCOM_CREATE_DB),SHOW_LONG},
  {"Com_create_function",      (char*) (com_stat+(uint) SQLCOM_CREATE_FUNCTION),SHOW_LONG},
  {"Com_create_index",	       (char*) (com_stat+(uint) SQLCOM_CREATE_INDEX),SHOW_LONG},
  {"Com_create_table",	       (char*) (com_stat+(uint) SQLCOM_CREATE_TABLE),SHOW_LONG},
  {"Com_delete",	       (char*) (com_stat+(uint) SQLCOM_DELETE),SHOW_LONG},
  {"Com_drop_db",	       (char*) (com_stat+(uint) SQLCOM_DROP_DB),SHOW_LONG},
  {"Com_drop_function",	       (char*) (com_stat+(uint) SQLCOM_DROP_FUNCTION),SHOW_LONG},
  {"Com_drop_index",	       (char*) (com_stat+(uint) SQLCOM_DROP_INDEX),SHOW_LONG},
  {"Com_drop_table",	       (char*) (com_stat+(uint) SQLCOM_DROP_TABLE),SHOW_LONG},
  {"Com_flush",		       (char*) (com_stat+(uint) SQLCOM_FLUSH),SHOW_LONG},
  {"Com_grant",		       (char*) (com_stat+(uint) SQLCOM_GRANT),SHOW_LONG},
  {"Com_insert",	       (char*) (com_stat+(uint) SQLCOM_INSERT),SHOW_LONG},
  {"Com_insert_select",	       (char*) (com_stat+(uint) SQLCOM_INSERT_SELECT),SHOW_LONG},
  {"Com_kill",		       (char*) (com_stat+(uint) SQLCOM_KILL),SHOW_LONG},
  {"Com_load",		       (char*) (com_stat+(uint) SQLCOM_LOAD),SHOW_LONG},
  {"Com_load_master_table",    (char*) (com_stat+(uint) SQLCOM_LOAD_MASTER_TABLE),SHOW_LONG},
  {"Com_lock_tables",	       (char*) (com_stat+(uint) SQLCOM_LOCK_TABLES),SHOW_LONG},
  {"Com_optimize",	       (char*) (com_stat+(uint) SQLCOM_OPTIMIZE),SHOW_LONG},
  {"Com_purge",		       (char*) (com_stat+(uint) SQLCOM_PURGE),SHOW_LONG},
  {"Com_rename_table",	       (char*) (com_stat+(uint) SQLCOM_RENAME_TABLE),SHOW_LONG},
  {"Com_repair",	       (char*) (com_stat+(uint) SQLCOM_REPAIR),SHOW_LONG},
  {"Com_replace",	       (char*) (com_stat+(uint) SQLCOM_REPLACE),SHOW_LONG},
  {"Com_replace_select",       (char*) (com_stat+(uint) SQLCOM_REPLACE_SELECT),SHOW_LONG},
  {"Com_reset",		       (char*) (com_stat+(uint) SQLCOM_RESET),SHOW_LONG},
  {"Com_restore_table",	       (char*) (com_stat+(uint) SQLCOM_RESTORE_TABLE),SHOW_LONG},
  {"Com_revoke",	       (char*) (com_stat+(uint) SQLCOM_REVOKE),SHOW_LONG},
  {"Com_rollback",	       (char*) (com_stat+(uint) SQLCOM_ROLLBACK),SHOW_LONG},
  {"Com_select",	       (char*) (com_stat+(uint) SQLCOM_SELECT),SHOW_LONG},
  {"Com_set_option",	       (char*) (com_stat+(uint) SQLCOM_SET_OPTION),SHOW_LONG},
  {"Com_show_binlogs",	       (char*) (com_stat+(uint) SQLCOM_SHOW_BINLOGS),SHOW_LONG},
  {"Com_show_create",	       (char*) (com_stat+(uint) SQLCOM_SHOW_CREATE),SHOW_LONG},
  {"Com_show_databases",       (char*) (com_stat+(uint) SQLCOM_SHOW_DATABASES),SHOW_LONG},
  {"Com_show_fields",	       (char*) (com_stat+(uint) SQLCOM_SHOW_FIELDS),SHOW_LONG},
  {"Com_show_grants",	       (char*) (com_stat+(uint) SQLCOM_SHOW_GRANTS),SHOW_LONG},
  {"Com_show_keys",	       (char*) (com_stat+(uint) SQLCOM_SHOW_KEYS),SHOW_LONG},
  {"Com_show_logs",	       (char*) (com_stat+(uint) SQLCOM_SHOW_LOGS),SHOW_LONG},
  {"Com_show_master_stat",     (char*) (com_stat+(uint) SQLCOM_SHOW_MASTER_STAT),SHOW_LONG},
  {"Com_show_open_tables",     (char*) (com_stat+(uint) SQLCOM_SHOW_OPEN_TABLES),SHOW_LONG},
  {"Com_show_processlist",     (char*) (com_stat+(uint) SQLCOM_SHOW_PROCESSLIST),SHOW_LONG},
  {"Com_show_slave_stat",      (char*) (com_stat+(uint) SQLCOM_SHOW_SLAVE_STAT),SHOW_LONG},
  {"Com_show_status",	       (char*) (com_stat+(uint) SQLCOM_SHOW_STATUS),SHOW_LONG},
  {"Com_show_tables",	       (char*) (com_stat+(uint) SQLCOM_SHOW_TABLES),SHOW_LONG},
  {"Com_show_variables",       (char*) (com_stat+(uint) SQLCOM_SHOW_VARIABLES),SHOW_LONG},
  {"Com_slave_start",	       (char*) (com_stat+(uint) SQLCOM_SLAVE_START),SHOW_LONG},
  {"Com_slave_stop",	       (char*) (com_stat+(uint) SQLCOM_SLAVE_STOP),SHOW_LONG},
  {"Com_truncate",	       (char*) (com_stat+(uint) SQLCOM_TRUNCATE),SHOW_LONG},
  {"Com_unlock_tables",	       (char*) (com_stat+(uint) SQLCOM_UNLOCK_TABLES),SHOW_LONG},
  {"Com_update",	       (char*) (com_stat+(uint) SQLCOM_UPDATE),SHOW_LONG},
  {"Connections",              (char*) &thread_id,              SHOW_LONG_CONST},
  {"Created_tmp_disk_tables",  (char*) &created_tmp_disk_tables,SHOW_LONG},
  {"Created_tmp_tables",       (char*) &created_tmp_tables,     SHOW_LONG},
  {"Created_tmp_files",	       (char*) &my_tmp_file_created,	SHOW_LONG},
  {"Delayed_insert_threads",   (char*) &delayed_insert_threads, SHOW_LONG},
  {"Delayed_writes",           (char*) &delayed_insert_writes,  SHOW_LONG},
  {"Delayed_errors",           (char*) &delayed_insert_errors,  SHOW_LONG},
  {"Flush_commands",           (char*) &refresh_version,        SHOW_LONG_CONST},
  {"Handler_delete",           (char*) &ha_delete_count,        SHOW_LONG},
  {"Handler_read_first",       (char*) &ha_read_first_count,    SHOW_LONG},
  {"Handler_read_key",         (char*) &ha_read_key_count,      SHOW_LONG},
  {"Handler_read_next",        (char*) &ha_read_next_count,     SHOW_LONG},
  {"Handler_read_prev",        (char*) &ha_read_prev_count,     SHOW_LONG},
  {"Handler_read_rnd",         (char*) &ha_read_rnd_count,      SHOW_LONG},
  {"Handler_read_rnd_next",    (char*) &ha_read_rnd_next_count, SHOW_LONG},
  {"Handler_update",           (char*) &ha_update_count,        SHOW_LONG},
  {"Handler_write",            (char*) &ha_write_count,         SHOW_LONG},
  {"Key_blocks_used",          (char*) &_my_blocks_used,        SHOW_LONG_CONST},
  {"Key_read_requests",        (char*) &_my_cache_r_requests,   SHOW_LONG},
  {"Key_reads",                (char*) &_my_cache_read,         SHOW_LONG},
  {"Key_write_requests",       (char*) &_my_cache_w_requests,   SHOW_LONG},
  {"Key_writes",               (char*) &_my_cache_write,        SHOW_LONG},
  {"Max_used_connections",     (char*) &max_used_connections,   SHOW_LONG},
  {"Not_flushed_key_blocks",   (char*) &_my_blocks_changed,     SHOW_LONG_CONST},
  {"Not_flushed_delayed_rows", (char*) &delayed_rows_in_use,    SHOW_LONG_CONST},
  {"Open_tables",              (char*) 0,                       SHOW_OPENTABLES},
  {"Open_files",               (char*) &my_file_opened,         SHOW_INT_CONST},
  {"Open_streams",             (char*) &my_stream_opened,       SHOW_INT_CONST},
  {"Opened_tables",            (char*) &opened_tables,          SHOW_LONG},
  {"Questions",                (char*) 0,                       SHOW_QUESTION},
  {"Select_full_join",         (char*) &select_full_join_count, SHOW_LONG},
  {"Select_full_range_join",   (char*) &select_full_range_join_count, SHOW_LONG},
  {"Select_range",             (char*) &select_range_count, 	SHOW_LONG},
  {"Select_range_check",       (char*) &select_range_check_count, SHOW_LONG},
  {"Select_scan",	       (char*) &select_scan_count,	SHOW_LONG},
  {"Slave_running",            (char*) &slave_running,          SHOW_BOOL},
  {"Slave_open_temp_tables",   (char*) &slave_open_temp_tables, SHOW_LONG},
  {"Slow_launch_threads",      (char*) &slow_launch_threads,    SHOW_LONG},
  {"Slow_queries",             (char*) &long_query_count,       SHOW_LONG},
  {"Sort_merge_passes",	       (char*) &filesort_merge_passes,  SHOW_LONG},
  {"Sort_range",	       (char*) &filesort_range_count,   SHOW_LONG},
  {"Sort_rows",		       (char*) &filesort_rows,	        SHOW_LONG},
  {"Sort_scan",		       (char*) &filesort_scan_count,    SHOW_LONG},
  {"Table_locks_immediate",    (char*) &locks_immediate,        SHOW_LONG},
  {"Table_locks_waited",       (char*) &locks_waited,           SHOW_LONG},
  {"Threads_cached",           (char*) &cached_thread_count,    SHOW_LONG_CONST},
  {"Threads_created",	       (char*) &thread_created,		SHOW_LONG_CONST},
  {"Threads_connected",        (char*) &thread_count,           SHOW_INT_CONST},
  {"Threads_running",          (char*) &thread_running,         SHOW_INT_CONST},
  {"Uptime",                   (char*) 0,                       SHOW_STARTTIME},
  {NullS, NullS, SHOW_LONG}
};

static void print_version(void)
{
  printf("%s  Ver %s for %s on %s\n",my_progname,
	 server_version,SYSTEM_TYPE,MACHINE_TYPE);
}

static void use_help(void)
{
  print_version();
  printf("Use '--help' or '--no-defaults --help' for a list of available options\n");
}  

static void usage(void)
{
  print_version();
  puts("\
Copyright (C) 2000 MySQL AB, by Monty and others\n\
This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
and you are welcome to modify and redistribute it under the GPL license\n\
Starts the MySQL server\n");

  printf("Usage: %s [OPTIONS]\n", my_progname);
  puts("\n\
  --ansi		Use ANSI SQL syntax instead of MySQL syntax\n\
  -b, --basedir=path	Path to installation directory. All paths are\n\
			usually resolved relative to this\n\
  --big-tables		Allow big result sets by saving all temporary sets\n\
			on file (Solves most 'table full' errors)\n\
  --bind-address=IP	Ip address to bind to\n\
  --bootstrap		Used by mysql installation scripts\n\
  --character-sets-dir=...\n\
                        Directory where character sets are\n\
  --chroot=path		Chroot mysqld daemon during startup\n\
  --core-file		Write core on errors\n\
  -h, --datadir=path	Path to the database root");
#ifndef DBUG_OFF
  printf("\
  -#, --debug[=...]     Debug log. Default is '%s'\n",default_dbug_option);
#ifdef SAFEMALLOC
  puts("\
  --skip-safemalloc     Don't use the memory allocation checking");
#endif
#endif
  puts("\
  --default-character-set=charset\n\
			Set the default character set\n\
  --default-table-type=type\n\
			Set the default table type for tables\n\
  --delay-key-write-for-all-tables\n\
			Don't flush key buffers between writes for any MyISAM\n\
			table\n\
  --enable-locking	Enable system locking\n\
  -T, --exit-info	Used for debugging;  Use at your own risk!\n\
  --flush		Flush tables to disk between SQL commands\n\
  -?, --help		Display this help and exit\n\
  --init-file=file	Read SQL commands from this file at startup\n\
  -L, --language=...	Client error messages in given language. May be\n\
			given as a full path\n\
  -l, --log[=file]	Log connections and queries to file\n\
  --log-bin[=file]      Log queries in new binary format (for replication)\n\
  --log-bin-index=file  File that holds the names for last binary log files\n\
  --log-update[=file]	Log updates to file.# where # is a unique number\n\
			if not given.\n\
  --log-isam[=file]	Log all MyISAM changes to file\n\
  --log-long-format	Log some extra information to update log\n\
  --low-priority-updates INSERT/DELETE/UPDATE has lower priority than selects\n\
  --log-slow-queries=[file]\n\
			Log slow queries to this log file.  Defaults logging\n\
                        to hostname-slow.log\n\
  --pid-file=path	Pid file used by safe_mysqld\n\
  --myisam-recover[=option[,option...]] where options is one of DEAULT,\n\
			BACKUP or FORCE.\n\
  --memlock		Lock mysqld in memory\n\
  -n, --new		Use very new possible 'unsafe' functions\n\
  -o, --old-protocol	Use the old (3.20) protocol\n\
  -P, --port=...	Port number to use for connection\n");
#ifdef ONE_THREAD
  puts("\
  --one-thread		Only use one thread (for debugging under Linux)\n");
#endif
  puts("\
  -O, --set-variable var=option\n\
			Give a variable an value. --help lists variables\n\
  -Sg, --skip-grant-tables\n\
			Start without grant tables. This gives all users\n\
			FULL ACCESS to all tables!\n\
  --safe-mode		Skip some optimize stages (for testing)\n\
  --safe-show-database  Don't show databases for which the user has no\n\
                        privileges\n\
  --safe-user-create	Don't new users cretaion without privileges to the\n\
		        mysql.user table\n\
  --skip-concurrent-insert\n\
		        Don't use concurrent insert with MyISAM\n\
  --skip-delay-key-write\n\
			Ignore the delay_key_write option for all tables\n\
  --skip-host-cache	Don't cache host names\n\
  --skip-locking	Don't use system locking. To use isamchk one has\n\
			to shut down the server.\n\
  --skip-name-resolve	Don't resolve hostnames.\n\
			All hostnames are IP's or 'localhost'\n\
  --skip-networking	Don't allow connection with TCP/IP.\n\
  --skip-new		Don't use new, possible wrong routines.\n");
  /* We have to break the string here because of VC++ limits */
  puts("\
  --skip-stack-trace    Don't print a stack trace on failure\n\
  --skip-show-database  Don't allow 'SHOW DATABASE' commands\n\
  --skip-thread-priority\n\
			Don't give threads different priorities.\n\
  --socket=...		Socket file to use for connection\n\
  -t, --tmpdir=path	Path for temporary files\n\
  --sql-mode=option[,option[,option...]] where option can be one of:\n\
                        REAL_AS_FLOAT, PIPES_AS_CONCAT, ANSI_QUOTES,\n\
                        IGNORE_SPACE, SERIALIZE, ONLY_FULL_GROUP_BY.\n\
  --transaction-isolation\n\
		        Default transaction isolation level\n\
  --temp-pool           Use a pool of temporary files\n\
  -u, --user=user_name	Run mysqld daemon as user\n\
  -V, --version		output version information and exit\n\
  -W, --warnings        Log some not critical warnings to the log file\n");
#ifdef __WIN__
  puts("NT and Win32 specific options:\n\
  --console		Don't remove the console window\n\
  --install		Install mysqld as a service (NT)\n\
  --remove		Remove mysqld from the service list (NT)\n\
  --standalone		Dummy option to start as a standalone program (NT)\
");
#ifdef USE_SYMDIR
  puts("--use-symbolic-links	Enable symbolic link support");
#endif
  puts("");
#endif
#ifdef HAVE_BERKELEY_DB
  puts("\
  --bdb-home=  directory  Berkeley home direcory\n\
  --bdb-lock-detect=#	  Berkeley lock detect\n\
                          (DEFAULT, OLDEST, RANDOM or YOUNGEST, # sec)\n\
  --bdb-logdir=directory  Berkeley DB log file directory\n\
  --bdb-no-sync		  Don't synchronously flush logs\n\
  --bdb-no-recover	  Don't try to recover Berkeley DB tables on start\n\
  --bdb-shared-data	  Start Berkeley DB in multi-process mode\n\
  --bdb-tmpdir=directory  Berkeley DB tempfile name\n\
  --skip-bdb		  Don't use berkeley db (will save memory)\n\
");
#endif /* HAVE_BERKELEY_DB */
#ifdef HAVE_GEMINI_DB
  puts("\
  --gemini-recovery=mode  Set Crash Recovery operating mode\n\
                          (FULL, NONE, FORCE - default FULL)\n\
  --gemini-flush-log-at-commit\n\
                          Every commit forces a write to the reovery log\n\
  --gemini-unbuffered-io  Use unbuffered i/o\n\
  --skip-gemini		  Don't use gemini (will save memory)\n\
");
#endif
#ifdef HAVE_INNOBASE_DB
  puts("\
  --innodb_data_home_dir=dir   The common part for Innodb table spaces\n\
  --innodb_data_file_path=dir  Path to individual files and their sizes\n\
  --innodb_flush_method=#  With which method to flush data\n\
  --innodb_flush_log_at_trx_commit[=#]\n\
			       Set to 0 if you don't want to flush logs\n\
  --innodb_log_arch_dir=dir    Where full logs should be archived\n\
  --innodb_log_archive[=#]     Set to 1 if you want to have logs archived\n\
  --innodb_log_group_home_dir=dir  Path to innodb log files.\n\
  --skip-innodb		       Don't use Innodb (will save memory)\n\
");
#endif /* HAVE_INNOBASE_DB */
  print_defaults("my",load_default_groups);
  puts("");

#include "sslopt-usage.h"

  fix_paths();
  set_ports();
  printf("\
To see what values a running MySQL server is using, type\n\
'mysqladmin variables' instead of 'mysqld --help'.\n\
The default values (after parsing the command line arguments) are:\n\n");

  printf("basedir:     %s\n",mysql_home);
  printf("datadir:     %s\n",mysql_real_data_home);
  printf("tmpdir:      %s\n",mysql_tmpdir);
  printf("language:    %s\n",language);
#ifndef __WIN__
  printf("pid file:    %s\n",pidfile_name);
#endif
  if (opt_logname)
    printf("logfile:     %s\n",opt_logname);
  if (opt_update_logname)
    printf("update log:  %s\n",opt_update_logname);
  if (opt_bin_log)
  {
    printf("binary log:  %s\n",opt_bin_logname ? opt_bin_logname : "");
    printf("binary log index:  %s\n",
	   opt_binlog_index_name ? opt_binlog_index_name : "");
  }
  if (opt_slow_logname)
    printf("update log:  %s\n",opt_slow_logname);
  printf("TCP port:    %d\n",mysql_port);
#if defined(HAVE_SYS_UN_H)
  printf("Unix socket: %s\n",mysql_unix_port);
#endif
  if (my_disable_locking)
    puts("\nsystem locking is not in use");
  if (opt_noacl)
    puts("\nGrant tables are not used. All users have full access rights");
  printf("\nPossible variables for option --set-variable (-O) are:\n");
  for (uint i=0 ; changeable_vars[i].name ; i++)
    printf("%-20s  current value: %lu\n",
	   changeable_vars[i].name,
	   (ulong) *changeable_vars[i].varptr);
}


static void set_options(void)
{
  set_all_changeable_vars( changeable_vars );
#if !defined( my_pthread_setprio ) && !defined( HAVE_PTHREAD_SETSCHEDPARAM )
  opt_specialflag |= SPECIAL_NO_PRIOR;
#endif

  (void) strmov( default_charset, MYSQL_CHARSET);
  (void) strmov( language, LANGUAGE);
  (void) strmov( mysql_real_data_home, get_relative_path(DATADIR));
#ifdef __WIN__
  /* Allow Win32 users to move MySQL anywhere */
  {
    char prg_dev[LIBLEN];
    my_path(prg_dev,my_progname,"mysql/bin");
    strcat(prg_dev,"/../");			// Remove 'bin' to get base dir
    cleanup_dirname(mysql_home,prg_dev);
  }
#else
  const char *tmpenv;
  if ( !(tmpenv = getenv("MY_BASEDIR_VERSION")))
    tmpenv = DEFAULT_MYSQL_HOME;
  (void) strmov( mysql_home, tmpenv );
#endif

#if defined( HAVE_mit_thread ) || defined( __WIN__ ) || defined( HAVE_LINUXTHREADS )
  my_disable_locking = 1;
#endif
  my_bind_addr = htonl( INADDR_ANY );
}

	/* Initiates DEBUG - but no debugging here ! */

static void get_options(int argc,char **argv)
{
  int c,option_index=0;

  myisam_delay_key_write=1;			// Allow use of this
  while ((c=getopt_long(argc,argv,"ab:C:h:#::T::?l::L:O:P:sS::t:u:noVvWI?",
			long_options, &option_index)) != EOF)
  {
    switch(c) {
    case '#':
#ifndef DBUG_OFF
      DBUG_PUSH(optarg ? optarg : default_dbug_option);
#endif
      opt_endinfo=1;				/* unireg: memory allocation */
      break;
    case 'W':
      opt_warnings=1;
      break;
    case 'a':
      opt_sql_mode = (MODE_REAL_AS_FLOAT | MODE_PIPES_AS_CONCAT |
		      MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | MODE_SERIALIZABLE
		      | MODE_ONLY_FULL_GROUP_BY);
      default_tx_isolation= ISO_SERIALIZABLE;
      break;
    case 'b':
      strmov(mysql_home,optarg);
      break;
    case 'l':
      opt_log=1;
      opt_logname=optarg;			// Use hostname.log if null
      break;
    case 'h':
      strmov(mysql_real_data_home,optarg);
      break;
    case 'L':
      strmov(language,optarg);
      break;
    case 'n':
      opt_specialflag|= SPECIAL_NEW_FUNC;
      break;
    case 'o':
      protocol_version=PROTOCOL_VERSION-1;
      break;
    case 'O':
      if (set_changeable_var(optarg, changeable_vars))
      {
	use_help();
	exit(1);
      }
      break;
    case 'P':
      mysql_port= (unsigned int) atoi(optarg);
      break;
    case OPT_LOCAL_INFILE:
      opt_local_infile= test(optarg || atoi(optarg) != 0);
      break;
    case OPT_SLAVE_SKIP_ERRORS:
      init_slave_skip_errors(optarg);
      break;
    case OPT_SAFEMALLOC_MEM_LIMIT:
#if !defined(DBUG_OFF) && defined(SAFEMALLOC)      
      safemalloc_mem_limit = atoi(optarg);
#endif      
      break;
    case OPT_SOCKET:
      mysql_unix_port= optarg;
      break;
    case 'r':
      mysqld_chroot=optarg;
      break;
#ifdef USE_SYMDIR
    case 's':
      my_use_symdir=1;			/* Use internal symbolic links */
      break;
#endif
    case 't':
      mysql_tmpdir=optarg;
      break;
    case OPT_TEMP_POOL:
      use_temp_pool=1;
      break;
    case 'u':
      mysqld_user=optarg;
      break;
    case 'v':
    case 'V':
      print_version();
      exit(0);
    case 'I':
    case '?':
      usage();
      exit(0);
    case 'T':
      test_flags= optarg ? (uint) atoi(optarg) : 0;
      opt_endinfo=1;
      break;
    case 'S':
      if (!optarg)
	opt_specialflag|= SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE;
      else if (!strcmp(optarg,"l"))
	my_disable_locking=1;
      else if (!strcmp(optarg,"g"))
	opt_noacl=1;
      else
      {
	fprintf(stderr,"%s: Unrecognized option: %s\n",my_progname,optarg);
	use_help();
	exit(1);
      }
      break;
    case (int) OPT_BIG_TABLES:
      thd_startup_options|=OPTION_BIG_TABLES;
      break;
    case (int) OPT_ISAM_LOG:
      opt_myisam_log=1;
      if (optarg)
	myisam_log_filename=optarg;
      break;
    case (int) OPT_UPDATE_LOG:
      opt_update_log=1;
      opt_update_logname=optarg;		// Use hostname.# if null
      break;
    case (int) OPT_BIN_LOG_INDEX:
      opt_binlog_index_name = optarg;
      break;
    case (int) OPT_BIN_LOG:
      opt_bin_log=1;
      x_free(opt_bin_logname);
      if (optarg && optarg[0])
	opt_bin_logname=my_strdup(optarg,MYF(0));
      break;
      // needs to be handled (as no-op) in non-debugging mode for test suite
    case (int)OPT_DISCONNECT_SLAVE_EVENT_COUNT:
#ifndef DBUG_OFF      
      disconnect_slave_event_count = atoi(optarg);
#endif      
      break;
    case (int)OPT_ABORT_SLAVE_EVENT_COUNT:
#ifndef DBUG_OFF      
      abort_slave_event_count = atoi(optarg);
#endif      
      break;
    case (int)OPT_SPORADIC_BINLOG_DUMP_FAIL:
#ifndef DBUG_OFF      
      opt_sporadic_binlog_dump_fail = 1;
#endif      
      break;
     case (int)OPT_MAX_BINLOG_DUMP_EVENTS:
#ifndef DBUG_OFF      
      max_binlog_dump_events = atoi(optarg);
#endif      
      break;

    case (int) OPT_LOG_SLAVE_UPDATES:
      opt_log_slave_updates = 1;
      break;

    case (int)OPT_REPLICATE_IGNORE_DB:
      {
	i_string *db = new i_string(optarg);
	replicate_ignore_db.push_back(db);
        break;
      }
    case (int)OPT_REPLICATE_DO_DB:
      {
	i_string *db = new i_string(optarg);
	replicate_do_db.push_back(db);
        break;
      }
    case (int)OPT_REPLICATE_REWRITE_DB:
      {
	char* key = optarg,*p, *val;
	p = strstr(optarg, "->");
	if (!p)
	  {
	    fprintf(stderr,
		    "Bad syntax in replicate-rewrite-db - missing '->'!\n");
	    exit(1);
	  }
	val = p--;
	while(isspace(*p) && p > optarg) *p-- = 0;
	if(p == optarg)
	  {
	    fprintf(stderr,
		    "Bad syntax in replicate-rewrite-db - empty FROM db!\n");
	    exit(1);
	  }
	*val = 0;
	val += 2;
	while(*val && isspace(*val)) *val++;
	if (!*val)
	  {
	    fprintf(stderr,
		    "Bad syntax in replicate-rewrite-db - empty TO db!\n");
	    exit(1);
	  }

	i_string_pair* db_pair = new i_string_pair(key, val);
	replicate_rewrite_db.push_back(db_pair);
	break;
      }

    case (int)OPT_BINLOG_IGNORE_DB:
      {
	i_string *db = new i_string(optarg);
	binlog_ignore_db.push_back(db);
        break;
      }
    case (int)OPT_BINLOG_DO_DB:
      {
	i_string *db = new i_string(optarg);
	binlog_do_db.push_back(db);
        break;
      }
    case (int)OPT_REPLICATE_DO_TABLE:
      {
	if (!do_table_inited)
	  init_table_rule_hash(&replicate_do_table, &do_table_inited);
	if(add_table_rule(&replicate_do_table, optarg))
	  {
	    fprintf(stderr, "Could not add do table rule '%s'!\n", optarg);
	    exit(1);
	  }
	table_rules_on = 1;
	break;
      }
    case (int)OPT_REPLICATE_WILD_DO_TABLE:
      {
	if (!wild_do_table_inited)
	  init_table_rule_array(&replicate_wild_do_table,
				&wild_do_table_inited);
	if(add_wild_table_rule(&replicate_wild_do_table, optarg))
	  {
	    fprintf(stderr, "Could not add do table rule '%s'!\n", optarg);
	    exit(1);
	  }
	table_rules_on = 1;
	break;
      }
    case (int)OPT_REPLICATE_WILD_IGNORE_TABLE:
      {
	if (!wild_ignore_table_inited)
	  init_table_rule_array(&replicate_wild_ignore_table,
				&wild_ignore_table_inited);
	if(add_wild_table_rule(&replicate_wild_ignore_table, optarg))
	  {
	    fprintf(stderr, "Could not add ignore table rule '%s'!\n", optarg);
	    exit(1);
	  }
	table_rules_on = 1;
	break;
      }
    case (int)OPT_REPLICATE_IGNORE_TABLE:
      {
	if (!ignore_table_inited)
	  init_table_rule_hash(&replicate_ignore_table, &ignore_table_inited);
	if(add_table_rule(&replicate_ignore_table, optarg))
	  {
	    fprintf(stderr, "Could not add ignore table rule '%s'!\n", optarg);
	    exit(1);
	  }
	table_rules_on = 1;
	break;
      }
    case (int) OPT_SQL_BIN_UPDATE_SAME:
      opt_sql_bin_update  = 1;
      break;
    case (int) OPT_SLOW_QUERY_LOG:
      opt_slow_log=1;
      opt_slow_logname=optarg;
      break;
    case (int)OPT_SKIP_SLAVE_START:
      opt_skip_slave_start = 1;
      break;
    case (int) OPT_SKIP_NEW:
      opt_specialflag|= SPECIAL_NO_NEW_FUNC;
      default_table_type=DB_TYPE_ISAM;
      myisam_delay_key_write=0;
      myisam_concurrent_insert=0;
      myisam_recover_options= HA_RECOVER_NONE;
      my_disable_symlinks=1;
      ha_open_options&= ~HA_OPEN_ABORT_IF_CRASHED;
      break;
    case (int) OPT_SAFE:
      opt_specialflag|= SPECIAL_SAFE_MODE;
      myisam_delay_key_write=0;
      myisam_recover_options= HA_RECOVER_NONE;	// To be changed
      ha_open_options&= ~HA_OPEN_ABORT_IF_CRASHED;
      break;
    case (int) OPT_SKIP_CONCURRENT_INSERT:
      myisam_concurrent_insert=0;
      break;
    case (int) OPT_SKIP_PRIOR:
      opt_specialflag|= SPECIAL_NO_PRIOR;
      break;
    case (int) OPT_SKIP_GRANT:
      opt_noacl=1;
      break;
    case (int) OPT_SKIP_LOCK:
      my_disable_locking=1;
      break;
    case (int) OPT_SKIP_HOST_CACHE:
      opt_specialflag|= SPECIAL_NO_HOST_CACHE;
      break;
    case (int) OPT_ENABLE_LOCK:
      my_disable_locking=0;
      break;
    case (int) OPT_USE_LOCKING:
      my_disable_locking=0;
      break;
    case (int) OPT_SKIP_RESOLVE:
      opt_specialflag|=SPECIAL_NO_RESOLVE;
      break;
    case (int) OPT_LONG_FORMAT:
      opt_specialflag|=SPECIAL_LONG_LOG_FORMAT;
      break;
    case (int) OPT_SKIP_NETWORKING:
      opt_disable_networking=1;
      mysql_port=0;
      break;
    case (int) OPT_SKIP_SHOW_DB:
      opt_skip_show_db=1;
      opt_specialflag|=SPECIAL_SKIP_SHOW_DB;
      mysql_port=0;
      break;
    case (int) OPT_MEMLOCK:
      locked_in_memory=1;
      break;
    case (int) OPT_ONE_THREAD:
      test_flags |= TEST_NO_THREADS;
      break;
    case (int) OPT_WANT_CORE:
      test_flags |= TEST_CORE_ON_SIGNAL;
      break;
    case (int) OPT_SKIP_STACK_TRACE:
      test_flags|=TEST_NO_STACKTRACE;
      break;
    case (int) OPT_SKIP_SYMLINKS:
      my_disable_symlinks=1;
      break;
    case (int) OPT_BIND_ADDRESS:
      if (optarg && isdigit(optarg[0]))
      {
	my_bind_addr = (ulong) inet_addr(optarg);
      }
      else
      {
	struct hostent *ent;
	if (!optarg || !optarg[0])
	  ent=gethostbyname(optarg);
	else
	{
	  char myhostname[255];
	  if (gethostname(myhostname,sizeof(myhostname)) < 0)
	  {
	    sql_perror("Can't start server: cannot get my own hostname!");
	    exit(1);
	  }
	  ent=gethostbyname(myhostname);
	}
	if (!ent)
	{
	  sql_perror("Can't start server: cannot resolve hostname!");
	  exit(1);
	}
	my_bind_addr = (ulong) ((in_addr*)ent->h_addr_list[0])->s_addr;
      }
      break;
    case (int) OPT_PID_FILE:
      strmov(pidfile_name,optarg);
      break;
    case (int) OPT_INIT_FILE:
      opt_init_file=optarg;
      break;
#ifdef __WIN__
    case (int) OPT_STANDALONE:		/* Dummy option for NT */
      break;
    case (int) OPT_CONSOLE:
      opt_console=1;
      break;
#endif
    case (int) OPT_FLUSH:
      nisam_flush=myisam_flush=1;
      flush_time=0;			// No auto flush
      break;
    case OPT_LOW_PRIORITY_UPDATES:
      thd_startup_options|=OPTION_LOW_PRIORITY_UPDATES;
      thr_upgraded_concurrent_insert_lock= TL_WRITE_LOW_PRIORITY;
      low_priority_updates=1;
      break;
    case OPT_BOOTSTRAP:
      opt_noacl=opt_bootstrap=1;
      break;
    case OPT_TABLE_TYPE:
    {
      int type;
      if ((type=find_type(optarg, &ha_table_typelib, 2)) <= 0)
      {
	fprintf(stderr,"Unknown table type: %s\n",optarg);
	exit(1);
      }
      default_table_type= (enum db_type) type;
      break;
    }
    case OPT_SERVER_ID:
      server_id = atoi(optarg);
      server_id_supplied = 1;
      break;
    case OPT_DELAY_KEY_WRITE:
      ha_open_options|=HA_OPEN_DELAY_KEY_WRITE;
      myisam_delay_key_write=1;
      break;
    case OPT_SKIP_DELAY_KEY_WRITE:
      myisam_delay_key_write=0;
      break;
    case 'C':
      strmov(default_charset,optarg);
      break;
    case OPT_CHARSETS_DIR:
      strmov(mysql_charsets_dir, optarg);
      charsets_dir = mysql_charsets_dir;
      break;
#include "sslopt-case.h"
    case OPT_TX_ISOLATION:
    {
      int type;
      if ((type=find_type(optarg, &tx_isolation_typelib, 2)) <= 0)
      {
	fprintf(stderr,"Unknown transaction isolation type: %s\n",optarg);
	exit(1);
      }
      default_tx_isolation= (enum_tx_isolation) (type-1);
      break;
    }
#ifdef HAVE_BERKELEY_DB
    case OPT_BDB_LOG:
      berkeley_logdir=optarg;
      break;
    case OPT_BDB_HOME:
      berkeley_home=optarg;
      break;
    case OPT_BDB_NOSYNC:
      berkeley_env_flags|=DB_TXN_NOSYNC;
      break;
    case OPT_BDB_NO_RECOVER:
      berkeley_init_flags&= ~(DB_RECOVER);
      break;
    case OPT_BDB_TMP:
      berkeley_tmpdir=optarg;
      break;
    case OPT_BDB_LOCK:
    {
      int type;
      if ((type=find_type(optarg, &berkeley_lock_typelib, 2)) > 0)
	berkeley_lock_type=berkeley_lock_types[type-1];
      else
      {
	if (test_if_int(optarg,(uint) strlen(optarg)))
	  berkeley_lock_scan_time=atoi(optarg);
	else
	{
	  fprintf(stderr,"Unknown lock type: %s\n",optarg);
	  exit(1);
	}
      }
      break;
    }
    case OPT_BDB_SHARED:
      berkeley_init_flags&= ~(DB_PRIVATE);
      berkeley_shared_data=1;
      break;
#endif /* HAVE_BERKELEY_DB */
    case OPT_BDB_SKIP:
#ifdef HAVE_BERKELEY_DB
      berkeley_skip=1;
      have_berkeley_db=SHOW_OPTION_DISABLED;
#endif
      break;
    case OPT_GEMINI_SKIP:
#ifdef HAVE_GEMINI_DB
      gemini_skip=1;
      have_gemini=SHOW_OPTION_DISABLED;  
      break;
    case OPT_GEMINI_RECOVER:
      gemini_recovery_options_str=optarg;
      if ((gemini_recovery_options=
	   find_bit_type(optarg, &gemini_recovery_typelib)) == ~(ulong) 0)
      {
        fprintf(stderr, "Unknown option to gemini-recovery: %s\n",optarg);
        exit(1);
      }
      break;
    case OPT_GEMINI_FLUSH_LOG:
      gemini_options |= GEMOPT_FLUSH_LOG;
      break;
    case OPT_GEMINI_UNBUFFERED_IO:
      gemini_options |= GEMOPT_UNBUFFERED_IO;
#endif
      break;
    case OPT_INNODB_SKIP:
#ifdef HAVE_INNOBASE_DB
      innodb_skip=1;
      have_innodb=SHOW_OPTION_DISABLED;
#endif
      break;
    case OPT_INNODB_DATA_FILE_PATH:
#ifdef HAVE_INNOBASE_DB
      innobase_data_file_path=optarg;
#endif
      break;
#ifdef HAVE_INNOBASE_DB
    case OPT_INNODB_DATA_HOME_DIR:
      innobase_data_home_dir=optarg;
      break;
    case OPT_INNODB_LOG_GROUP_HOME_DIR:
      innobase_log_group_home_dir=optarg;
      break;
    case OPT_INNODB_LOG_ARCH_DIR:
      innobase_log_arch_dir=optarg;
      break;
    case OPT_INNODB_LOG_ARCHIVE:
      innobase_log_archive= optarg ? test(atoi(optarg)) : 1;
      break;
    case OPT_INNODB_FLUSH_LOG_AT_TRX_COMMIT:
      innobase_flush_log_at_trx_commit= optarg ? test(atoi(optarg)) : 1;
      break;
    case OPT_INNODB_FAST_SHUTDOWN:
      innobase_fast_shutdown= optarg ? test(atoi(optarg)) : 1;
      break;
    case OPT_INNODB_UNIX_FILE_FLUSH_METHOD:
      innobase_unix_file_flush_method=optarg;
      break;
#endif /* HAVE_INNOBASE_DB */
    case OPT_MYISAM_RECOVER:
    {
      if (!optarg)
      {
	myisam_recover_options=    HA_RECOVER_DEFAULT;
	myisam_recover_options_str= myisam_recover_typelib.type_names[0];
      }
      else
      {
	myisam_recover_options_str=optarg;
	if ((myisam_recover_options=
		find_bit_type(optarg, &myisam_recover_typelib)) == ~(ulong) 0)
	{
	  fprintf(stderr, "Unknown option to myisam-recover: %s\n",optarg);
	  exit(1);
	}
      }
      ha_open_options|=HA_OPEN_ABORT_IF_CRASHED;
      break;
    }
    case OPT_SQL_MODE:
    {
      sql_mode_str = optarg;
      if ((opt_sql_mode =
	   find_bit_type(optarg, &sql_mode_typelib)) == ~(ulong) 0)
      {
	fprintf(stderr, "Unknown option to sql-mode: %s\n", optarg);
	exit(1);
      }
      default_tx_isolation= ((opt_sql_mode & MODE_SERIALIZABLE) ?
			     ISO_SERIALIZABLE :
			     ISO_READ_COMMITTED);
      break;
    }
    case OPT_MASTER_HOST:
      master_host=optarg;
      break;
    case OPT_MASTER_USER:
      master_user=optarg;
      break;
    case OPT_MASTER_PASSWORD:
      master_password=optarg;
      break;
    case OPT_MASTER_INFO_FILE:
      master_info_file=optarg;
      break;
    case OPT_MASTER_PORT:
      master_port= atoi(optarg);
      break;
    case OPT_MASTER_CONNECT_RETRY:
      master_connect_retry= atoi(optarg);
      break;
    case OPT_MASTER_RETRY_COUNT:
      master_retry_count= atoi(optarg);
      break;
    case OPT_SAFE_SHOW_DB:
      opt_safe_show_db=1;
      break;
    case OPT_SAFE_USER_CREATE:
      opt_safe_user_create=1;
      break;
    case OPT_SKIP_SAFEMALLOC:
#ifdef SAFEMALLOC
      sf_malloc_quick=1;
#endif
      break;
    default:
      fprintf(stderr,"%s: Unrecognized option: %c\n",my_progname,c);
      use_help();
      exit(1);
    }
  }
  // Skipp empty arguments (from shell)
  while (argc != optind && !argv[optind][0])
    optind++;
  if (argc != optind)
  {
    fprintf(stderr,"%s: Too many parameters\n",my_progname);
    use_help();
    exit(1);
  }
  fix_paths();
  default_table_type_name=ha_table_typelib.type_names[default_table_type-1];
  default_tx_isolation_name=tx_isolation_typelib.type_names[default_tx_isolation];
  /* To be deleted in MySQL 4.0 */
  if (!record_rnd_cache_size)
    record_rnd_cache_size=my_default_record_cache_size;
}


static char *get_relative_path(const char *path)
{
  if (test_if_hard_path(path) &&
      is_prefix(path,DEFAULT_MYSQL_HOME) &&
      strcmp(DEFAULT_MYSQL_HOME,FN_ROOTDIR))
  {
    path+=(uint) strlen(DEFAULT_MYSQL_HOME);
    while (*path == FN_LIBCHAR)
      path++;
  }
  return (char*) path;
}


static void fix_paths(void)
{
  (void) fn_format(mysql_home,mysql_home,"","",16); // Remove symlinks
  convert_dirname(mysql_home);
  convert_dirname(mysql_real_data_home);
  convert_dirname(language);
  (void) my_load_path(mysql_home,mysql_home,""); // Resolve current dir
  (void) my_load_path(mysql_real_data_home,mysql_real_data_home,mysql_home);
  (void) my_load_path(pidfile_name,pidfile_name,mysql_real_data_home);

  char buff[FN_REFLEN],*sharedir=get_relative_path(SHAREDIR);
  if (test_if_hard_path(sharedir))
    strmov(buff,sharedir);			/* purecov: tested */
  else
    strxmov(buff,mysql_home,sharedir,NullS);
  convert_dirname(buff);
  (void) my_load_path(language,language,buff);

  /* If --character-sets-dir isn't given, use shared library dir */
  if (charsets_dir != mysql_charsets_dir)
  {
    strmov(strmov(mysql_charsets_dir,buff),CHARSET_DIR);
    charsets_dir=mysql_charsets_dir;
  }

  /* Add '/' to TMPDIR if needed */
  char *tmp= (char*) my_malloc(FN_REFLEN,MYF(MY_FAE));
  if (tmp)
  {
    strmov(tmp,mysql_tmpdir);
    mysql_tmpdir=tmp;
    convert_dirname(mysql_tmpdir);
    mysql_tmpdir=(char*) my_realloc(mysql_tmpdir,(uint) strlen(mysql_tmpdir)+1,
				    MYF(MY_HOLD_ON_ERROR));
  }
}


#ifdef SET_RLIMIT_NOFILE
static uint set_maximum_open_files(uint max_file_limit)
{
  struct rlimit rlimit;
  ulong old_cur;

  if (!getrlimit(RLIMIT_NOFILE,&rlimit))
  {
    old_cur=rlimit.rlim_cur;
    if (rlimit.rlim_cur >= max_file_limit)	// Nothing to do
      return rlimit.rlim_cur;			/* purecov: inspected */
    rlimit.rlim_cur=rlimit.rlim_max=max_file_limit;
    if (setrlimit(RLIMIT_NOFILE,&rlimit))
    {
      sql_print_error("Warning: setrlimit couldn't increase number of open files to more than %ld",
	      old_cur);		/* purecov: inspected */
      max_file_limit=old_cur;
    }
    else
    {
      (void) getrlimit(RLIMIT_NOFILE,&rlimit);
      if ((uint) rlimit.rlim_cur != max_file_limit)
	sql_print_error("Warning: setrlimit returned ok, but didn't change limits. Max open files is %ld",
			  (ulong) rlimit.rlim_cur); /* purecov: inspected */
      max_file_limit=rlimit.rlim_cur;
    }
  }
  return max_file_limit;
}
#endif

#ifdef OS2
static uint set_maximum_open_files(uint max_file_limit)
{
   LONG     cbReqCount;
   ULONG    cbCurMaxFH, cbCurMaxFH0;
   APIRET   ulrc;

   // get current limit
   cbReqCount = 0;
   DosSetRelMaxFH( &cbReqCount, &cbCurMaxFH0);

   // set new limit
   cbReqCount = max_file_limit - cbCurMaxFH0;
   ulrc = DosSetRelMaxFH( &cbReqCount, &cbCurMaxFH);
   if (ulrc) {
      sql_print_error("Warning: DosSetRelMaxFH couldn't increase number of open files to more than %d",
         cbCurMaxFH0);
      cbCurMaxFH = cbCurMaxFH0;
   }

   return cbCurMaxFH;
}
#endif

	/*
	  Return a bitfield from a string of substrings separated by ','
	  returns ~(ulong) 0 on error.
	*/

static ulong find_bit_type(const char *x, TYPELIB *bit_lib)
{
  bool found_end;
  int  found_count;
  const char *end,*i,*j;
  const char **array, *pos;
  ulong found,found_int,bit;
  DBUG_ENTER("find_bit_type");
  DBUG_PRINT("enter",("x: '%s'",x));

  found=0;
  pos=(my_string) x;
  while (*pos == ' ') pos++;
  found_end= *pos == 0;
  while (!found_end)
  {
    if (!*(end=strcend(pos,',')))		/* Let end point at fieldend */
    {
      while (end > pos && end[-1] == ' ')
	end--;					/* Skipp end-space */
      found_end=1;
    }
    found_int=0; found_count=0;
    for (array=bit_lib->type_names, bit=1 ; (i= *array++) ; bit<<=1)
    {
      j=pos;
      while (j != end)
      {
	if (toupper(*i++) != toupper(*j++))
	  goto skipp;
      }
      found_int=bit;
      if (! *i)
      {
	found_count=1;
	break;
      }
      else if (j != pos)			// Half field found
      {
	found_count++;				// Could be one of two values
      }
skipp: ;
    }
    if (found_count != 1)
      DBUG_RETURN(~(ulong) 0);				// No unique value
    found|=found_int;
    pos=end+1;
  }

  DBUG_PRINT("exit",("bit-field: %ld",(ulong) found));
  DBUG_RETURN(found);
} /* find_bit_type */


/*****************************************************************************
** Instantiate templates
*****************************************************************************/

#ifdef __GNUC__
/* Used templates */
template class I_List<THD>;
template class I_List_iterator<THD>;
template class I_List<i_string>;
template class I_List<i_string_pair>;
#endif