summaryrefslogtreecommitdiff
path: root/netware
diff options
context:
space:
mode:
authorunknown <gweir@work.mysql.com>2003-02-01 00:42:26 +0100
committerunknown <gweir@work.mysql.com>2003-02-01 00:42:26 +0100
commit8cfe603dc1a647c2396db4bd73a4590c663c69df (patch)
treef7c383e264e8172bc011c8dc34a02e47c418eeb3 /netware
parente3119b97d7d2b0738e52bf56bfd1f1eb2e6e0cf6 (diff)
downloadmariadb-git-8cfe603dc1a647c2396db4bd73a4590c663c69df.tar.gz
Many files:
new file Makefile.am: Changes from Novell diff netware/Makefile.am: Changes from Novell diff BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted
Diffstat (limited to 'netware')
-rw-r--r--netware/Makefile.am40
-rw-r--r--netware/init_db.sql22
-rw-r--r--netware/install_test_db.ncf1
-rw-r--r--netware/libmysql.imp85
-rw-r--r--netware/libmysqlmain.c38
-rw-r--r--netware/my_manage.c477
-rw-r--r--netware/my_manage.h83
-rw-r--r--netware/mysql_install_db.c437
-rw-r--r--netware/mysql_secure_installation.pl219
-rw-r--r--netware/mysql_test_run.c1150
-rw-r--r--netware/mysqld_safe.c662
-rw-r--r--netware/overlay.tar.gzbin0 -> 2334 bytes
-rw-r--r--netware/test_db.sql17
13 files changed, 3213 insertions, 18 deletions
diff --git a/netware/Makefile.am b/netware/Makefile.am
index 8ab44f23141..5ea76b0a4f5 100644
--- a/netware/Makefile.am
+++ b/netware/Makefile.am
@@ -1,22 +1,26 @@
-# Copyright (C) 2002 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
+# Copyright (c) 2002 Novell, Inc. All Rights Reserved.
+#
+# 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
-## Process this file with automake to create Makefile.in
-
-EXTRA_DIST = netware.patch
+INCLUDES = -I$(srcdir)/../include -I../include -I..
+bin_PROGRAMS = mysqld_safe mysql_install_db mysql_test_run libmysql
+mysqld_safe_SOURCES= mysqld_safe.c my_manage.c
+mysql_install_db_SOURCES= mysql_install_db.c my_manage.c
+mysql_test_run_SOURCES= mysql_test_run.c my_manage.c
+libmysql_SOURCES= libmysqlmain.c
+libmysql_LDADD = ../libmysql/.libs/libmysqlclient.a
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/netware/init_db.sql b/netware/init_db.sql
new file mode 100644
index 00000000000..640fe3a4188
--- /dev/null
+++ b/netware/init_db.sql
@@ -0,0 +1,22 @@
+USE mysql;
+
+CREATE TABLE db (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User)) comment='Database privileges';
+
+INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');
+INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');
+
+CREATE TABLE host (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db)) comment='Host privileges; Merged with database privileges';
+
+CREATE TABLE user (Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') DEFAULT 'N' NOT NULL, File_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User)) comment='Users and global privileges';
+
+INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
+INSERT INTO user VALUES ('%','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
+
+INSERT INTO user (host,user) values ('localhost','');
+INSERT INTO user (host,user) values ('%','');
+
+CREATE TABLE func (name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') NOT NULL, PRIMARY KEY (name)) comment='User defined functions';
+
+CREATE TABLE tables_priv (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(60) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp(14), Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor)) comment='Table privileges';
+
+CREATE TABLE columns_priv (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp(14), Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name)) comment='Column privileges';
diff --git a/netware/install_test_db.ncf b/netware/install_test_db.ncf
new file mode 100644
index 00000000000..06befc5d9bd
--- /dev/null
+++ b/netware/install_test_db.ncf
@@ -0,0 +1 @@
+# This functionality is handled by mysql-test-run.nlm on NetWare
diff --git a/netware/libmysql.imp b/netware/libmysql.imp
new file mode 100644
index 00000000000..75fcc8d1a99
--- /dev/null
+++ b/netware/libmysql.imp
@@ -0,0 +1,85 @@
+myodbc_remove_escape,
+mysql_add_slave,
+mysql_affected_rows,
+mysql_change_user,
+mysql_character_set_name,
+mysql_close,
+mysql_data_seek,
+mysql_debug,
+mysql_disable_reads_from_master,
+mysql_disable_rpl_parse,
+mysql_dump_debug_info,
+mysql_enable_reads_from_master,
+mysql_enable_rpl_parse,
+mysql_eof,
+mysql_errno,
+mysql_error,
+mysql_escape_string,
+mysql_fetch_field,
+mysql_fetch_field_direct,
+mysql_fetch_fields,
+mysql_fetch_lengths,
+mysql_fetch_row,
+mysql_field_count,
+mysql_field_seek,
+mysql_field_tell,
+mysql_free_result,
+mysql_get_client_info,
+mysql_get_host_info,
+mysql_get_proto_info,
+mysql_get_server_info,
+mysql_info,
+mysql_init,
+mysql_insert_id,
+mysql_kill,
+mysql_list_dbs,
+mysql_list_fields,
+mysql_list_processes,
+mysql_list_tables,
+mysql_manager_close,
+mysql_manager_command,
+mysql_manager_connect,
+mysql_manager_fetch_line,
+mysql_manager_init,
+mysql_master_query,
+mysql_master_send_query,
+mysql_num_fields,
+mysql_num_rows,
+mysql_odbc_escape_string,
+mysql_options,
+mysql_ping,
+mysql_query,
+mysql_read_query_result,
+mysql_reads_from_master_enabled,
+mysql_real_connect,
+mysql_real_escape_string,
+mysql_real_query,
+mysql_refresh,
+mysql_row_seek,
+mysql_row_tell,
+mysql_rpl_parse_enabled,
+mysql_rpl_probe,
+mysql_rpl_query_type,
+mysql_select_db,
+mysql_send_query,
+mysql_server_end,
+mysql_server_init,
+mysql_set_master,
+mysql_shutdown,
+mysql_slave_query,
+mysql_slave_send_query,
+mysql_ssl_set,
+mysql_stat,
+mysql_store_result,
+mysql_thread_end,
+mysql_thread_id,
+mysql_thread_init,
+mysql_thread_safe,
+mysql_use_result,
+net_safe_read,
+simple_command,
+mysql_connect,
+mysql_create_db,
+mysql_drop_db,
+
+
diff --git a/netware/libmysqlmain.c b/netware/libmysqlmain.c
new file mode 100644
index 00000000000..03fdb832176
--- /dev/null
+++ b/netware/libmysqlmain.c
@@ -0,0 +1,38 @@
+/*
+ Copyright (c) 2002 Novell, Inc. All Rights Reserved.
+
+ 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 "my_global.h"
+
+my_bool init_available_charsets(myf myflags);
+
+/* this function is required so that global memory is allocated against this
+library nlm, and not against a paticular client */
+int _NonAppStart(void *NLMHandle, void *errorScreen, const char *commandLine,
+ const char *loadDirPath, size_t uninitializedDataLength,
+ void *NLMFileHandle, int (*readRoutineP)( int conn, void *fileHandle,
+ size_t offset, size_t nbytes, size_t *bytesRead, void *buffer ),
+ size_t customDataOffset, size_t customDataSize, int messageCount,
+ const char **messages)
+{
+ mysql_server_init(0, NULL, NULL);
+
+ init_available_charsets(MYF(0));
+
+ return 0;
+}
+
diff --git a/netware/my_manage.c b/netware/my_manage.c
new file mode 100644
index 00000000000..25147b16674
--- /dev/null
+++ b/netware/my_manage.c
@@ -0,0 +1,477 @@
+/*
+ Copyright (c) 2003 Novell, Inc. All Rights Reserved.
+
+ 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 <stdio.h>
+#include <errno.h>
+#include <dirent.h>
+#include <string.h>
+#include <screen.h>
+#include <nks/vm.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include "my_manage.h"
+
+/******************************************************************************
+
+ macros
+
+******************************************************************************/
+
+/******************************************************************************
+
+ global variables
+
+******************************************************************************/
+
+/******************************************************************************
+
+ functions
+
+******************************************************************************/
+
+/******************************************************************************
+
+ init_args()
+
+ Init an argument list.
+
+******************************************************************************/
+void _init_args(arg_list *al)
+{
+ int i;
+
+ *al = malloc(sizeof(arg_list_t));
+
+ (*al)->argc = 0;
+
+ for(i = 0; i < ARG_MAX; i++)
+ {
+ (*al)->argv[i] = NULL;
+ }
+}
+
+/******************************************************************************
+
+ add_arg()
+
+ Add an argument to a list.
+
+******************************************************************************/
+void add_arg(arg_list al, char *format, ...)
+{
+ va_list ap;
+
+ ASSERT(al != NULL);
+ ASSERT(al->argc < ARG_MAX);
+
+ al->argv[al->argc] = malloc(PATH_MAX);
+
+ ASSERT(al->argv[al->argc] != NULL);
+
+ va_start(ap, format);
+
+ vsprintf(al->argv[al->argc], format, ap);
+
+ va_end(ap);
+
+ ++(al->argc);
+}
+
+/******************************************************************************
+
+ _free_args()
+
+ Free an argument list.
+
+******************************************************************************/
+void _free_args(arg_list *al)
+{
+ int i;
+
+ ASSERT(al != NULL);
+ ASSERT(*al != NULL);
+
+ for(i = 0; i < (*al)->argc; i++)
+ {
+ ASSERT((*al)->argv[i] != NULL);
+ free((*al)->argv[i]);
+ (*al)->argv[i] = NULL;
+ }
+
+ free(*al);
+ *al = NULL;
+}
+
+/******************************************************************************
+
+ sleep_until_file_deleted()
+
+ Sleep until the given file is no longer found.
+
+******************************************************************************/
+int sleep_until_file_deleted(char *pid_file)
+{
+ struct stat buf;
+ int i, err;
+
+ for(i = 0; (i < TRY_MAX) && (err = !stat(pid_file, &buf)); i++) sleep(1);
+
+ if (err != 0) err = errno;
+
+ return err;
+}
+
+/******************************************************************************
+
+ sleep_until_file_exists()
+
+ Sleep until the given file exists.
+
+******************************************************************************/
+int sleep_until_file_exists(char *pid_file)
+{
+ struct stat buf;
+ int i, err;
+
+ for(i = 0; (i < TRY_MAX) && (err = stat(pid_file, &buf)); i++) sleep(1);
+
+ if (err != 0) err = errno;
+
+ return err;
+}
+
+/******************************************************************************
+
+ wait_for_server_start()
+
+ Wait for the server on the given port to start.
+
+******************************************************************************/
+int wait_for_server_start(char *bin_dir, char *user, char *password, int port)
+{
+ arg_list al;
+ int err, i;
+ char mysqladmin_file[PATH_MAX];
+ char trash[PATH_MAX];
+
+ // mysqladmin file
+ snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin", bin_dir);
+ snprintf(trash, PATH_MAX, "/tmp/trash.out");
+
+ // args
+ init_args(al);
+ add_arg(al, "%s", mysqladmin_file);
+ add_arg(al, "--no-defaults");
+ add_arg(al, "--port=%u", port);
+ add_arg(al, "--user=%s", user);
+ add_arg(al, "--password=%s", password);
+ add_arg(al, "--silent");
+ add_arg(al, "-O");
+ add_arg(al, "connect_timeout=10");
+ add_arg(al, "-w");
+ add_arg(al, "--host=localhost");
+ add_arg(al, "ping");
+
+ // NetWare does not support the connect timeout in the TCP/IP stack
+ // -- we will try the ping multiple times
+ for(i = 0; (i < TRY_MAX)
+ && (err = spawn(mysqladmin_file, al, TRUE, NULL,
+ trash, NULL)); i++) sleep(1);
+
+ // free args
+ free_args(al);
+
+ return err;
+}
+
+/******************************************************************************
+
+ spawn()
+
+ Spawn the given file with the given arguments.
+
+******************************************************************************/
+int spawn(char *file, arg_list al, int join, char *input,
+ char *output, char *error)
+{
+ NXNameSpec_t name;
+ NXExecEnvSpec_t env;
+ NXVmId_t vm, ignore;
+ int result;
+
+ // name
+ name.ssType = NX_OBJ_FILE;
+ name.ssPathCtx = 0;
+ name.ssPath = file;
+
+ // env
+ env.esArgc = al->argc;
+ env.esArgv = al->argv;
+ env.esEnv = NULL;
+
+ env.esStdin.ssPathCtx = 0;
+ env.esStdout.ssPathCtx = 0;
+ env.esStderr.ssPathCtx = 0;
+
+ if (input == NULL)
+ {
+ env.esStdin.ssType = NX_OBJ_DEFAULT;
+ env.esStdin.ssPath = NULL;
+ }
+ else
+ {
+ env.esStdin.ssType = NX_OBJ_FILE;
+ env.esStdin.ssPath = input;
+ }
+
+ if (output == NULL)
+ {
+ env.esStdout.ssType = NX_OBJ_DEFAULT;
+ env.esStdout.ssPath = NULL;
+ }
+ else
+ {
+ env.esStdout.ssType = NX_OBJ_FILE;
+ env.esStdout.ssPath = output;
+ }
+
+ if (error == NULL)
+ {
+ env.esStderr.ssType = NX_OBJ_DEFAULT;
+ env.esStderr.ssPath = NULL;
+ }
+ else
+ {
+ env.esStderr.ssType = NX_OBJ_FILE;
+ env.esStderr.ssPath = error;
+ }
+
+ result = NXVmSpawn(&name, &env, NX_VM_SAME_ADDRSPACE | NX_VM_INHERIT_ENV, &vm);
+
+ if (!result && join)
+ {
+ NXVmJoin(vm, &ignore, &result);
+ }
+
+ return result;
+}
+
+/******************************************************************************
+
+ stop_server()
+
+ Stop the server with the given port and pid file.
+
+******************************************************************************/
+int stop_server(char *bin_dir, char *user, char *password, int port,
+ char *pid_file)
+{
+ arg_list al;
+ int err, i, argc = 0;
+ char mysqladmin_file[PATH_MAX];
+ char trash[PATH_MAX];
+
+ // mysqladmin file
+ snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin", bin_dir);
+ snprintf(trash, PATH_MAX, "/tmp/trash.out");
+
+ // args
+ init_args(al);
+ add_arg(al, "%s", mysqladmin_file);
+ add_arg(al, "--no-defaults");
+ add_arg(al, "--port=%u", port);
+ add_arg(al, "--user=%s", user);
+ add_arg(al, "--password=%s", password);
+ add_arg(al, "-O");
+ add_arg(al, "shutdown_timeout=20");
+ add_arg(al, "shutdown");
+
+ // spawn
+ if ((err = spawn(mysqladmin_file, al, TRUE, NULL,
+ trash, NULL)) == 0)
+ {
+ sleep_until_file_deleted(pid_file);
+ }
+ else
+ {
+ pid_t pid = get_server_pid(pid_file);
+
+ // shutdown failed - kill server
+ kill_server(pid);
+
+ sleep(TRY_MAX);
+
+ // remove pid file if possible
+ err = remove(pid_file);
+ }
+
+ // free args
+ free_args(al);
+
+ return err;
+}
+
+/******************************************************************************
+
+ get_server_pid()
+
+ Get the VM id with the given pid file.
+
+******************************************************************************/
+pid_t get_server_pid(char *pid_file)
+{
+ char buf[PATH_MAX];
+ int fd, err;
+ char *p;
+ pid_t id;
+
+ // discover id
+ fd = open(pid_file, O_RDONLY);
+
+ err = read(fd, buf, PATH_MAX);
+
+ close(fd);
+
+ if (err > 0)
+ {
+ // terminate string
+ if ((p = strchr(buf, '\n')) != NULL)
+ {
+ *p = NULL;
+
+ // check for a '\r'
+ if ((p = strchr(buf, '\r')) != NULL)
+ {
+ *p = NULL;
+ }
+ }
+ else
+ {
+ buf[err] = NULL;
+ }
+
+ id = strtol(buf, NULL, 0);
+ }
+
+ return id;
+}
+
+/******************************************************************************
+
+ kill_server()
+
+ Force a kill of the server with the given pid.
+
+******************************************************************************/
+void kill_server(pid_t pid)
+{
+ if (pid > 0)
+ {
+ // destroy vm
+ NXVmDestroy(pid);
+ }
+}
+
+/******************************************************************************
+
+ del_tree()
+
+ Delete the directory and subdirectories.
+
+******************************************************************************/
+void del_tree(char *dir)
+{
+ DIR *parent = opendir(dir);
+ DIR *entry;
+ char temp[PATH_MAX];
+
+ if (parent == NULL)
+ {
+ return;
+ }
+
+ while((entry = readdir(parent)) != NULL)
+ {
+ // create long name
+ snprintf(temp, PATH_MAX, "%s/%s", dir, entry->d_name);
+
+ if (entry->d_name[0] == '.')
+ {
+ // Skip
+ }
+ else if (S_ISDIR(entry->d_type))
+ {
+ // delete subdirectory
+ del_tree(temp);
+ }
+ else
+ {
+ // remove file
+ remove(temp);
+ }
+ }
+
+ // remove directory
+ rmdir(dir);
+}
+
+/******************************************************************************
+
+ removef()
+
+******************************************************************************/
+int removef(char *format, ...)
+{
+ va_list ap;
+ char path[PATH_MAX];
+
+ va_start(ap, format);
+
+ vsnprintf(path, PATH_MAX, format, ap);
+
+ va_end(ap);
+
+ return remove(path);
+}
+
+/******************************************************************************
+
+ get_basedir()
+
+******************************************************************************/
+void get_basedir(char *argv0, char *basedir)
+{
+ char temp[PATH_MAX];
+ char *p;
+
+ ASSERT(argv0 != NULL);
+ ASSERT(basedir != NULL);
+
+ strcpy(temp, strlwr(argv0));
+ while((p = strchr(temp, '\\')) != NULL) *p = '/';
+
+ if ((p = strindex(temp, "/bin/")) != NULL)
+ {
+ *p = NULL;
+ strcpy(basedir, temp);
+ }
+}
+
diff --git a/netware/my_manage.h b/netware/my_manage.h
new file mode 100644
index 00000000000..92ed66ea865
--- /dev/null
+++ b/netware/my_manage.h
@@ -0,0 +1,83 @@
+/*
+ Copyright (c) 2002 Novell, Inc. All Rights Reserved.
+
+ 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
+*/
+
+#ifndef _MY_MANAGE
+#define _MY_MANAGE
+
+/******************************************************************************
+
+ includes
+
+******************************************************************************/
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/******************************************************************************
+
+ macros
+
+******************************************************************************/
+
+#define ARG_MAX 50
+#define TRY_MAX 5
+
+#define init_args(al) _init_args(&al);
+#define free_args(al) _free_args(&al);
+
+/******************************************************************************
+
+ structures
+
+******************************************************************************/
+
+typedef struct
+{
+
+ int argc;
+ char *argv[ARG_MAX];
+
+} arg_list_t, * arg_list;
+
+/******************************************************************************
+
+ global variables
+
+******************************************************************************/
+
+/******************************************************************************
+
+ prototypes
+
+******************************************************************************/
+
+void _init_args(arg_list *);
+void add_arg(arg_list, char *, ...);
+void _free_args(arg_list *);
+int sleep_until_file_exists(char *);
+int sleep_until_file_deleted(char *);
+int wait_for_server_start(char *, char *, char *, int);
+int spawn(char *, arg_list, int, char *, char *, char *);
+int stop_server(char *, char *, char *, int, char *);
+pid_t get_server_pid(char *);
+void kill_server(pid_t pid);
+void del_tree(char *);
+int removef(char *, ...);
+void get_basedir(char *, char *);
+
+#endif /* _MY_MANAGE */
diff --git a/netware/mysql_install_db.c b/netware/mysql_install_db.c
new file mode 100644
index 00000000000..96f416880b1
--- /dev/null
+++ b/netware/mysql_install_db.c
@@ -0,0 +1,437 @@
+/*
+ Copyright (c) 2002 Novell, Inc. All Rights Reserved.
+
+ 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 <stdlib.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <sys/stat.h>
+#include <monitor.h>
+#include <strings.h>
+#include <getopt.h>
+#include <screen.h>
+
+#include "my_config.h"
+#include "my_manage.h"
+
+/******************************************************************************
+
+ global variables
+
+******************************************************************************/
+char autoclose;
+char basedir[PATH_MAX];
+char datadir[PATH_MAX];
+char err_log[PATH_MAX];
+char out_log[PATH_MAX];
+char mysqld[PATH_MAX];
+char hostname[PATH_MAX];
+char sql_file[PATH_MAX];
+char default_option[PATH_MAX];
+
+/******************************************************************************
+
+ prototypes
+
+******************************************************************************/
+
+void start_defaults(int, char*[]);
+void finish_defaults();
+void read_defaults(arg_list);
+void parse_args(int, char*[]);
+void get_options(int, char*[]);
+void create_paths();
+int mysql_install_db(int argc, char *argv[]);
+
+/******************************************************************************
+
+ functions
+
+******************************************************************************/
+
+/******************************************************************************
+
+ start_defaults()
+
+ Start setting the defaults.
+
+******************************************************************************/
+void start_defaults(int argc, char *argv[])
+{
+ struct stat buf;
+ int i;
+
+ // default options
+ static char *default_options[] =
+ {
+ "--no-defaults",
+ "--defaults-file=",
+ "--defaults-extra-file=",
+ NULL
+ };
+
+ // autoclose
+ autoclose = FALSE;
+
+ // basedir
+ get_basedir(argv[0], basedir);
+
+ // hostname
+ if (gethostname(hostname,PATH_MAX) < 0)
+ {
+ // default
+ strcpy(hostname,"mysql");
+ }
+
+ // default option
+ default_option[0] = NULL;
+ for (i=0; (argc > 1) && default_options[i]; i++)
+ {
+ if(!strnicmp(argv[1], default_options[i], strlen(default_options[i])))
+ {
+ strncpy(default_option, argv[1], PATH_MAX);
+ break;
+ }
+ }
+
+ // set after basedir is established
+ datadir[0] = NULL;
+ err_log[0] = NULL;
+ out_log[0] = NULL;
+ mysqld[0] = NULL;
+ sql_file[0] = NULL;
+}
+
+/******************************************************************************
+
+ finish_defaults()
+
+ Finish setting the defaults.
+
+******************************************************************************/
+void finish_defaults()
+{
+ struct stat buf;
+ int i;
+
+ // datadir
+ if (!datadir[0]) snprintf(datadir, PATH_MAX, "%s/data", basedir);
+
+ // err-log
+ if (!err_log[0]) snprintf(err_log, PATH_MAX, "%s/%s.err", datadir, hostname);
+
+ // out-log
+ if (!out_log[0]) snprintf(out_log, PATH_MAX, "%s/%s.out", datadir, hostname);
+
+ // sql-file
+ if (!sql_file[0]) snprintf(sql_file, PATH_MAX, "%s/bin/init_db.sql", basedir);
+
+ // mysqld
+ if (!mysqld[0]) snprintf(mysqld, PATH_MAX, "%s/bin/mysqld", basedir);
+}
+
+/******************************************************************************
+
+ read_defaults()
+
+ Read the defaults.
+
+******************************************************************************/
+void read_defaults(arg_list pal)
+{
+ arg_list al;
+ char defaults_file[PATH_MAX];
+ char mydefaults[PATH_MAX];
+ char line[PATH_MAX];
+ FILE *fp;
+
+ // defaults output file
+ snprintf(defaults_file, PATH_MAX, "%s/bin/defaults.out", basedir);
+ remove(defaults_file);
+
+ // mysqladmin file
+ snprintf(mydefaults, PATH_MAX, "%s/bin/my_print_defaults", basedir);
+
+ // args
+ init_args(al);
+ add_arg(al, mydefaults);
+ if (default_option[0]) add_arg(al, default_option);
+ add_arg(al, "mysqld");
+ add_arg(al, "mysql_install_db");
+
+ spawn(mydefaults, al, TRUE, NULL, defaults_file, NULL);
+
+ free_args(al);
+
+ // gather defaults
+ if((fp = fopen(defaults_file, "r")) != NULL)
+ {
+ while(fgets(line, PATH_MAX, fp))
+ {
+ char *p;
+
+ // remove end-of-line character
+ if ((p = strrchr(line, '\n')) != NULL) *p = '\0';
+
+ // add the option as an argument
+ add_arg(pal, line);
+ }
+
+ fclose(fp);
+ }
+
+ // remove file
+ remove(defaults_file);
+}
+
+/******************************************************************************
+
+ parse_args()
+
+ Get the options.
+
+******************************************************************************/
+void parse_args(int argc, char *argv[])
+{
+ int index = 0;
+ int c;
+
+ // parse options
+ enum opts
+ {
+ OPT_BASEDIR = 0xFF,
+ OPT_DATADIR,
+ OPT_SQL_FILE
+ };
+
+ static struct option options[] =
+ {
+ {"autoclose", no_argument, &autoclose, TRUE},
+ {"basedir", required_argument, 0, OPT_BASEDIR},
+ {"datadir", required_argument, 0, OPT_DATADIR},
+ {"sql-file", required_argument, 0, OPT_SQL_FILE},
+ {0, 0, 0, 0}
+ };
+
+ // we have to reset getopt_long because we use it multiple times
+ optind = 1;
+
+ // turn off error reporting
+ opterr = 0;
+
+ while ((c = getopt_long(argc, argv, "b:h:", options, &index)) >= 0)
+ {
+ switch (c)
+ {
+ case OPT_BASEDIR:
+ case 'b':
+ strcpy(basedir, optarg);
+ break;
+
+ case OPT_DATADIR:
+ case 'h':
+ strcpy(datadir, optarg);
+ break;
+
+ case OPT_SQL_FILE:
+ strcpy(sql_file, optarg);
+ break;
+
+ default:
+ // ignore
+ break;
+ }
+ }
+}
+
+/******************************************************************************
+
+ get_options()
+
+ Get the options.
+
+******************************************************************************/
+void get_options(int argc, char *argv[])
+{
+ arg_list al;
+
+ // start defaults
+ start_defaults(argc, argv);
+
+ // default file arguments
+ init_args(al);
+ add_arg(al, "dummy");
+ read_defaults(al);
+ parse_args(al->argc, al->argv);
+ free_args(al);
+
+ // command-line arguments
+ parse_args(argc, argv);
+
+ // finish defaults
+ finish_defaults();
+}
+
+/******************************************************************************
+
+ create_paths()
+
+ Create database paths.
+
+******************************************************************************/
+void create_paths()
+{
+ struct stat info;
+ char temp[PATH_MAX];
+
+ // check for tables
+ snprintf(temp, PATH_MAX, "%s/mysql/host.frm", datadir);
+ if (!stat(temp, &info))
+ {
+ printf("A database already exists in the directory:\n");
+ printf("\t%s\n\n", datadir);
+ exit(-1);
+ }
+
+ // data directory
+ if (stat(datadir, &info))
+ {
+ mkdir(datadir, 0);
+ }
+
+ // mysql directory
+ snprintf(temp, PATH_MAX, "%s/mysql", datadir);
+ if (stat(temp, &info))
+ {
+ mkdir(temp, 0);
+ }
+
+ // test directory
+ snprintf(temp, PATH_MAX, "%s/test", datadir);
+ if (stat(temp, &info))
+ {
+ mkdir(temp, 0);
+ }
+}
+
+/******************************************************************************
+
+ mysql_install_db()
+
+ Install the database.
+
+******************************************************************************/
+int mysql_install_db(int argc, char *argv[])
+{
+ arg_list al;
+ int i, j, err;
+ char skip;
+
+ // private options
+ static char *private_options[] =
+ {
+ "--autoclose",
+ "--sql-file=",
+ NULL
+ };
+
+ // args
+ init_args(al);
+ add_arg(al, "%s", mysqld);
+
+ // parent args
+ for(i = 1; i < argc; i++)
+ {
+ skip = FALSE;
+
+ // skip private arguments
+ for (j=0; private_options[j]; j++)
+ {
+ if(!strnicmp(argv[i], private_options[j], strlen(private_options[j])))
+ {
+ skip = TRUE;
+ break;
+ }
+ }
+
+ if (!skip) add_arg(al, "%s", argv[i]);
+ }
+
+ add_arg(al, "--bootstrap");
+ add_arg(al, "--skip-grant-tables");
+ add_arg(al, "--skip-innodb");
+ add_arg(al, "--skip-bdb");
+
+ // spawn mysqld
+ err = spawn(mysqld, al, TRUE, sql_file, out_log, err_log);
+
+ // free args
+ free_args(al);
+
+ return err;
+}
+
+/******************************************************************************
+
+ main()
+
+******************************************************************************/
+int main(int argc, char **argv)
+{
+ // get options
+ get_options(argc, argv);
+
+ // check for an autoclose option
+ if (!autoclose) setscreenmode(SCR_NO_MODE);
+
+ // create paths
+ create_paths();
+
+ // install the database
+ if (mysql_install_db(argc, argv))
+ {
+ printf("ERROR - The database creation failed!\n");
+ printf("See the following log for more infomration:\n");
+ printf("\t%s\n\n", err_log);
+ exit(-1);
+ }
+
+ // status
+ printf("Initial database successfully created in the directory:\n");
+ printf("\t%s\n", datadir);
+
+ // info
+ printf("\nPLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !\n");
+
+ printf("\nThis is done with:\n");
+ printf("\tmysqladmin -u root password 'new-password'\n");
+
+ printf("\nSee the manual for more instructions.\n");
+
+ printf("\nYou can start the MySQL daemon with:\n");
+ printf("\tmysqld_safe\n");
+
+ printf("\nPlease report any problems with:\n");
+ printf("\t/mysql/mysqlbug.txt\n");
+
+ printf("\nThe latest information about MySQL is available on the web at\n");
+ printf("\thttp://www.mysql.com\n");
+
+ printf("\nSupport MySQL by buying support at https://order.mysql.com\n\n");
+
+ return 0;
+}
diff --git a/netware/mysql_secure_installation.pl b/netware/mysql_secure_installation.pl
new file mode 100644
index 00000000000..e363cacbc0d
--- /dev/null
+++ b/netware/mysql_secure_installation.pl
@@ -0,0 +1,219 @@
+#-----------------------------------------------------------------------------
+# Copyright (C) 2002 MySQL AB and Jeremy Cole
+#
+# 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
+#-----------------------------------------------------------------------------
+
+#-----------------------------------------------------------------------------
+# This notice applies to changes, created by or for Novell, Inc.,
+# to preexisting works for which notices appear elsewhere in this file.
+
+# Copyright (c) 2003 Novell, Inc. All Rights Reserved.
+
+# 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
+#-----------------------------------------------------------------------------
+
+use strict;
+use Mysql;
+
+print "MySQL Secure Installation Script\n\n";
+
+print "NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MySQL\n";
+print " SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!\n\n";
+
+#-----------------------------------------------------------------------------
+# get the current root password
+#-----------------------------------------------------------------------------
+
+print "In order to log into MySQL to secure it, we'll need the current\n";
+print "password for the root user. If you've just installed MySQL, and\n";
+print "you haven't set the root password yet, the password will be blank,\n";
+print "so you should just press enter here.\n\n";
+
+print "Enter the current password for root: ";
+my $password = <STDIN>;
+chomp $password;
+print "\n";
+
+my $conn = Mysql->connect("localhost", "mysql", "root", $password)
+ || die "Unable to connect to MySQL.";
+
+print "OK, successfully used the password, moving on...\n\n";
+
+#-----------------------------------------------------------------------------
+# set the root password
+#-----------------------------------------------------------------------------
+
+unless ($password)
+{
+ print "Setting the root password ensures that no one can log into MySQL\n";
+ print "using the root user without the proper authorization.\n\n";
+
+ print "Set root password (Y/N)? ";
+ my $reply = <STDIN>;
+ chomp $reply;
+ print "\n";
+
+ if ($reply =~ /Y/i)
+ {
+ print "New password for root: ";
+ my $pass1 = <STDIN>;
+ chomp $pass1;
+ print "\n";
+
+ print "Re-enter new password for root: ";
+ my $pass2 = <STDIN>;
+ chomp $pass2;
+ print "\n";
+
+ unless ($pass1 eq $pass2) { die "Sorry, the passwords do not match."; }
+
+ unless ($pass1) { die "Sorry, you can't use an empty password here."; }
+
+ $conn->query("SET PASSWORD FOR root\@localhost=PASSWORD('$pass1')")
+ || die "Unable to set password.";
+
+ print "OK, successfully set the password, moving on...\n\n";
+ }
+ else
+ {
+ print "WARNING, the password is not set, moving on...\n\n";
+ }
+}
+
+#-----------------------------------------------------------------------------
+# remove anonymous users
+#-----------------------------------------------------------------------------
+
+print "By default, a MySQL installation has anonymous users, allowing anyone\n";
+print "to log into MySQL without having to have a user account created for\n";
+print "them. This is intended only for testing, and to make the installation\n";
+print "go a bit smoother. You should remove them before moving into a\n";
+print "production environment.\n\n";
+
+print "Remove anonymous users (Y/N)? ";
+my $reply = <STDIN>;
+chomp $reply;
+print "\n";
+
+if ($reply =~ /Y/i)
+{
+ $conn->query("DELETE FROM mysql.user WHERE user=''")
+ || die "Unable to remove anonymous users.";
+
+ print "OK, successfully removed anonymous users, moving on...\n\n";
+}
+else
+{
+ print "WARNING, the anonymous users have not been removed, moving on...\n\n";
+}
+
+#-----------------------------------------------------------------------------
+# disallow remote root login
+#-----------------------------------------------------------------------------
+
+print "Normally, root should only be allowed to connect from 'localhost'. This\n";
+print "ensures that someone cannot guess at the root password from the network.\n\n";
+
+print "Disallow remote root login (Y/N)? ";
+my $reply = <STDIN>;
+chomp $reply;
+print "\n";
+
+if ($reply =~ /Y/i)
+{
+ $conn->query("DELETE FROM mysql.user WHERE user='root' AND host!='localhost'")
+ || die "Unable to disallow remote root login.";
+
+ print "OK, successfully disallowed remote root login, moving on...\n\n";
+}
+else
+{
+ print "WARNING, remote root login has not been disallowed, moving on...\n\n";
+}
+
+#-----------------------------------------------------------------------------
+# remove test database
+#-----------------------------------------------------------------------------
+
+print "By default, MySQL comes with a database named 'test' that anyone can\n";
+print "access. This is intended only for testing, and should be removed\n";
+print "before moving into a production environment.\n\n";
+
+print "Remove the test database (Y/N)? ";
+my $reply = <STDIN>;
+chomp $reply;
+print "\n";
+
+if ($reply =~ /Y/i)
+{
+ $conn->query("DROP DATABASE IF EXISTS test")
+ || die "Unable to remove test database.";
+
+ $conn->query("DELETE FROM mysql.db WHERE db='test' OR db='test\\_%'")
+ || die "Unable to remove access to the test database.";
+
+ print "OK, successfully removed the test database, moving on...\n\n";
+}
+else
+{
+ print "WARNING, the test database has not been removed, moving on...\n\n";
+}
+
+#-----------------------------------------------------------------------------
+# reload privilege tables
+#-----------------------------------------------------------------------------
+
+print "Reloading the privilege tables will ensure that all changes made so far\n";
+print "will take effect immediately.\n\n";
+
+print "Reload privilege tables (Y/N)? ";
+my $reply = <STDIN>;
+chomp $reply;
+print "\n";
+
+if ($reply =~ /Y/i)
+{
+ $conn->query("FLUSH PRIVILEGES")
+ || die "Unable to reload privilege tables.";
+
+ print "OK, successfully reloaded privilege tables, moving on...\n\n";
+}
+else
+{
+ print "WARNING, the privilege tables have not been reloaded, moving on...\n\n";
+}
+
+#-----------------------------------------------------------------------------
+# done
+#-----------------------------------------------------------------------------
+
+print "\n\nAll done! If you've completed all of the above steps, your MySQL\n";
+print "installation should now be secure.\n\n";
+
+print "Thanks for using MySQL!\n\n";
+
diff --git a/netware/mysql_test_run.c b/netware/mysql_test_run.c
new file mode 100644
index 00000000000..7392a96cc73
--- /dev/null
+++ b/netware/mysql_test_run.c
@@ -0,0 +1,1150 @@
+/*
+ Copyright (c) 2002, 2003 Novell, Inc. All Rights Reserved.
+
+ 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 <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <dirent.h>
+#include <string.h>
+#include <screen.h>
+#include <nks/vm.h>
+#include <ctype.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "my_manage.h"
+
+/******************************************************************************
+
+ macros
+
+******************************************************************************/
+
+#define HEADER "TEST ELAPSED RESULT \n"
+#define DASH "------------------------------------------------------------------------\n"
+
+#define NW_TEST_SUFFIX ".nw-test"
+#define NW_RESULT_SUFFIX ".nw-result"
+#define TEST_SUFFIX ".test"
+#define RESULT_SUFFIX ".result"
+#define REJECT_SUFFIX ".reject"
+#define OUT_SUFFIX ".out"
+#define ERR_SUFFIX ".err"
+
+#define TEST_PASS "[ pass ]"
+#define TEST_SKIP "[ skip ]"
+#define TEST_FAIL "[ fail ]"
+#define TEST_BAD "[ bad ]"
+
+/******************************************************************************
+
+ global variables
+
+******************************************************************************/
+
+char base_dir[PATH_MAX] = "sys:/mysql";
+char db[PATH_MAX] = "test";
+char user[PATH_MAX] = "root";
+char password[PATH_MAX] = "";
+
+int master_port = 9306;
+int slave_port = 9307;
+
+// comma delimited list of tests to skip or empty string
+char skip_test[PATH_MAX] = "";
+
+char bin_dir[PATH_MAX];
+char mysql_test_dir[PATH_MAX];
+char test_dir[PATH_MAX];
+char mysql_tmp_dir[PATH_MAX];
+char result_dir[PATH_MAX];
+char master_dir[PATH_MAX];
+char slave_dir[PATH_MAX];
+char lang_dir[PATH_MAX];
+char char_dir[PATH_MAX];
+
+char mysqladmin_file[PATH_MAX];
+char mysqld_file[PATH_MAX];
+char mysqltest_file[PATH_MAX];
+char master_pid[PATH_MAX];
+char slave_pid[PATH_MAX];
+
+char master_opt[PATH_MAX] = "";
+char slave_opt[PATH_MAX] = "";
+
+char slave_master_info[PATH_MAX] = "";
+
+char master_init_script[PATH_MAX] = "";
+char slave_init_script[PATH_MAX] = "";
+
+int total_skip = 0;
+int total_pass = 0;
+int total_fail = 0;
+int total_test = 0;
+
+double total_time = 0;
+
+int master_running = FALSE;
+int slave_running = FALSE;
+int skip_slave = TRUE;
+int single_test = TRUE;
+
+int restarts = 0;
+
+FILE *log_fd = NULL;
+
+/******************************************************************************
+
+ functions
+
+******************************************************************************/
+
+/******************************************************************************
+
+ prototypes
+
+******************************************************************************/
+
+void report_stats();
+void install_db(char *);
+void mysql_install_db();
+void start_master();
+void start_slave();
+void mysql_start();
+void stop_slave();
+void stop_master();
+void mysql_stop();
+void mysql_restart();
+int read_option(char *, char *);
+void run_test(char *);
+void setup(char *);
+void vlog(char *, va_list);
+void log(char *, ...);
+void log_info(char *, ...);
+void log_error(char *, ...);
+void log_errno(char *, ...);
+void die(char *);
+
+/******************************************************************************
+
+ report_stats()
+
+ Report the gathered statistics.
+
+******************************************************************************/
+void report_stats()
+{
+ if (total_fail == 0)
+ {
+ log("\nAll %d test(s) were successful.\n", total_test);
+ }
+ else
+ {
+ double percent = ((double)total_pass / total_test) * 100;
+
+ log("\nFailed %u/%u test(s), %.02f%% successful.\n",
+ total_fail, total_test, percent);
+ log("\nThe .out and .err files in %s may give you some\n", result_dir);
+ log("hint of what when wrong.\n");
+ log("\nIf you want to report this error, please first read the documentation\n");
+ log("at: http://www.mysql.com/doc/M/y/MySQL_test_suite.html\n");
+ }
+
+ log("\n%.02f total minutes elapsed in the test cases\n\n", total_time / 60);
+}
+
+/******************************************************************************
+
+ install_db()
+
+ Install the a database.
+
+******************************************************************************/
+void install_db(char *datadir)
+{
+ arg_list al;
+ int err, i;
+ char input[PATH_MAX];
+ char output[PATH_MAX];
+ char error[PATH_MAX];
+
+ // input file
+ snprintf(input, PATH_MAX, "%s/bin/init_db.sql", base_dir);
+ snprintf(output, PATH_MAX, "%s/install.out", datadir);
+ snprintf(error, PATH_MAX, "%s/install.err", datadir);
+
+ // args
+ init_args(al);
+ add_arg(al, mysqld_file);
+ add_arg(al, "--bootstrap");
+ add_arg(al, "--skip-grant-tables");
+ add_arg(al, "--basedir=%s", base_dir);
+ add_arg(al, "--datadir=%s", datadir);
+ add_arg(al, "--skip-innodb");
+ add_arg(al, "--skip-bdb");
+
+ // spawn
+ if ((err = spawn(mysqld_file, al, TRUE, input, output, error)) != 0)
+ {
+ die("Unable to create database.");
+ }
+
+ // free args
+ free_args(al);
+}
+
+/******************************************************************************
+
+ mysql_install_db()
+
+ Install the test databases.
+
+******************************************************************************/
+void mysql_install_db()
+{
+ char temp[PATH_MAX];
+
+ // var directory
+ snprintf(temp, PATH_MAX, "%s/var", mysql_test_dir);
+
+ // clean up old direcotry
+ del_tree(temp);
+
+ // create var directory
+ mkdir(temp, S_IRWXU);
+
+ // create subdirectories
+ snprintf(temp, PATH_MAX, "%s/var/run", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+ snprintf(temp, PATH_MAX, "%s/var/tmp", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+ snprintf(temp, PATH_MAX, "%s/var/master-data", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+ snprintf(temp, PATH_MAX, "%s/var/master-data/mysql", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+ snprintf(temp, PATH_MAX, "%s/var/master-data/test", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+ snprintf(temp, PATH_MAX, "%s/var/slave-data", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+ snprintf(temp, PATH_MAX, "%s/var/slave-data/mysql", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+ snprintf(temp, PATH_MAX, "%s/var/slave-data/test", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+
+ // install databases
+ install_db(master_dir);
+ install_db(slave_dir);
+}
+
+/******************************************************************************
+
+ start_master()
+
+ Start the master server.
+
+******************************************************************************/
+void start_master()
+{
+ arg_list al;
+ int err, i;
+ char master_out[PATH_MAX];
+ char master_err[PATH_MAX];
+
+ // remove old berkeley db log files that can confuse the server
+ removef("%s/log.*", master_dir);
+
+ // remove stale binary logs
+ removef("%s/*-bin.*", master_dir);
+
+ // remove stale binary logs
+ removef("%s/*.index", master_dir);
+
+ // remove master.info file
+ removef("%s/master.info", master_dir);
+
+ // remove relay files
+ removef("%s/var/log/*relay*", mysql_test_dir);
+
+ // remove relay-log.info file
+ removef("%s/relay-log.info", master_dir);
+
+ // init script
+ if (master_init_script[0] != NULL)
+ {
+ // run_init_script(master_init_script);
+ }
+
+ // redirection files
+ snprintf(master_out, PATH_MAX, "%s/var/run/master%u.out",
+ mysql_test_dir, restarts);
+ snprintf(master_err, PATH_MAX, "%s/var/run/master%u.err",
+ mysql_test_dir, restarts);
+
+ // args
+ init_args(al);
+ add_arg(al, "%s", mysqld_file);
+ add_arg(al, "--no-defaults");
+ add_arg(al, "--log-bin=master-bin");
+ add_arg(al, "--server-id=1");
+ add_arg(al, "--basedir=%s", base_dir);
+ add_arg(al, "--port=%u", master_port);
+ add_arg(al, "--local-infile");
+ add_arg(al, "--core");
+ add_arg(al, "--datadir=%s", master_dir);
+ add_arg(al, "--pid-file=%s", master_pid);
+ add_arg(al, "--character-sets-dir=%s", char_dir);
+ add_arg(al, "--tmpdir=%s", mysql_tmp_dir);
+ add_arg(al, "--language=%s", lang_dir);
+
+ // $MASTER_40_ARGS
+ add_arg(al, "--rpl-recovery-rank=1");
+ add_arg(al, "--init-rpl-role=master");
+
+ // $SMALL_SERVER
+ add_arg(al, "-O");
+ add_arg(al, "key_buffer_size=1M");
+ add_arg(al, "-O");
+ add_arg(al, "sort_buffer=256K");
+ add_arg(al, "-O");
+ add_arg(al, "max_heap_table_size=1M");
+
+ // $EXTRA_MASTER_OPT
+ if (master_opt[0] != NULL)
+ {
+ char *p;
+
+ p = (char *)strtok(master_opt, " \t");
+
+ while(p)
+ {
+ add_arg(al, "%s", p);
+
+ p = (char *)strtok(NULL, " \t");
+ }
+ }
+
+ // remove the pid file if it exists
+ remove(master_pid);
+
+ // spawn
+ if ((err = spawn(mysqld_file, al, FALSE, NULL, master_out, master_err)) == 0)
+ {
+ sleep_until_file_exists(master_pid);
+
+ if ((err = wait_for_server_start(bin_dir, user, password, master_port)) == 0)
+ {
+ master_running = TRUE;
+ }
+ else
+ {
+ log_error("The master server went down early.");
+ }
+ }
+ else
+ {
+ log_error("Unable to start master server.");
+ }
+
+ // free_args
+ free_args(al);
+}
+
+/******************************************************************************
+
+ start_slave()
+
+ Start the slave server.
+
+******************************************************************************/
+void start_slave()
+{
+ arg_list al;
+ int err, i;
+ char slave_out[PATH_MAX];
+ char slave_err[PATH_MAX];
+ char temp[PATH_MAX];
+
+ // skip?
+ if (skip_slave) return;
+
+ // remove stale binary logs
+ removef("%s/*-bin.*", slave_dir);
+
+ // remove stale binary logs
+ removef("%s/*.index", slave_dir);
+
+ // remove master.info file
+ removef("%s/master.info", slave_dir);
+
+ // remove relay files
+ removef("%s/var/log/*relay*", mysql_test_dir);
+
+ // remove relay-log.info file
+ removef("%s/relay-log.info", slave_dir);
+
+ // init script
+ if (slave_init_script[0] != NULL)
+ {
+ // run_init_script(slave_init_script);
+
+ // TODO: use the scripts
+ if (strindex(slave_init_script, "rpl000016-slave.sh") != NULL)
+ {
+ // create empty master.info file
+ snprintf(temp, PATH_MAX, "%s/master.info", slave_dir);
+ close(open(temp, O_WRONLY | O_CREAT));
+ }
+ else if (strindex(slave_init_script, "rpl000017-slave.sh") != NULL)
+ {
+ FILE *fp;
+
+ // create a master.info file
+ snprintf(temp, PATH_MAX, "%s/master.info", slave_dir);
+ fp = fopen(temp, "wb+");
+
+ fputs("master-bin.001\n", fp);
+ fputs("4\n", fp);
+ fputs("127.0.0.1\n", fp);
+ fputs("replicate\n", fp);
+ fputs("aaaaaaaaaaaaaaabthispartofthepasswordisnotused\n", fp);
+ fputs("9306\n", fp);
+ fputs("1\n", fp);
+ fputs("0\n", fp);
+
+ fclose(fp);
+ }
+ else if (strindex(slave_init_script, "rpl_rotate_logs-slave.sh") != NULL)
+ {
+ // create empty master.info file
+ snprintf(temp, PATH_MAX, "%s/master.info", slave_dir);
+ close(open(temp, O_WRONLY | O_CREAT));
+ }
+ }
+
+ // redirection files
+ snprintf(slave_out, PATH_MAX, "%s/var/run/slave%u.out",
+ mysql_test_dir, restarts);
+ snprintf(slave_err, PATH_MAX, "%s/var/run/slave%u.err",
+ mysql_test_dir, restarts);
+
+ // args
+ init_args(al);
+ add_arg(al, "%s", mysqld_file);
+ add_arg(al, "--no-defaults");
+ add_arg(al, "--log-bin=slave-bin");
+ add_arg(al, "--relay_log=slave-relay-bin");
+ add_arg(al, "--basedir=%s", base_dir);
+ add_arg(al, "--port=%u", slave_port);
+ add_arg(al, "--datadir=%s", slave_dir);
+ add_arg(al, "--pid-file=%s", slave_pid);
+ add_arg(al, "--character-sets-dir=%s", char_dir);
+ add_arg(al, "--core");
+ add_arg(al, "--tmpdir=%s", mysql_tmp_dir);
+ add_arg(al, "--language=%s", lang_dir);
+
+ add_arg(al, "--exit-info=256");
+ add_arg(al, "--log-slave-updates");
+ add_arg(al, "--init-rpl-role=slave");
+ add_arg(al, "--skip-innodb");
+ add_arg(al, "--skip-slave-start");
+ add_arg(al, "--slave-load-tmpdir=../../var/tmp");
+
+ add_arg(al, "--report-user=%s", user);
+ add_arg(al, "--report-host=127.0.0.1");
+ add_arg(al, "--report-port=%u", slave_port);
+
+ add_arg(al, "--master-retry-count=10");
+ add_arg(al, "-O");
+ add_arg(al, "slave_net_timeout=10");
+
+ // slave master info
+ if (slave_master_info[0] != NULL)
+ {
+ char *p;
+
+ p = (char *)strtok(slave_master_info, " \t");
+
+ while(p)
+ {
+ add_arg(al, "%s", p);
+
+ p = (char *)strtok(NULL, " \t");
+ }
+ }
+ else
+ {
+ add_arg(al, "--master-user=%s", user);
+ add_arg(al, "--master-password=%s", password);
+ add_arg(al, "--master-host=127.0.0.1");
+ add_arg(al, "--master-port=%u", master_port);
+ add_arg(al, "--master-connect-retry=1");
+ add_arg(al, "--server-id=2");
+ add_arg(al, "--rpl-recovery-rank=2");
+ }
+
+ // small server
+ add_arg(al, "-O");
+ add_arg(al, "key_buffer_size=1M");
+ add_arg(al, "-O");
+ add_arg(al, "sort_buffer=256K");
+ add_arg(al, "-O");
+ add_arg(al, "max_heap_table_size=1M");
+
+ // opt args
+ if (slave_opt[0] != NULL)
+ {
+ char *p;
+
+ p = (char *)strtok(slave_opt, " \t");
+
+ while(p)
+ {
+ add_arg(al, "%s", p);
+
+ p = (char *)strtok(NULL, " \t");
+ }
+ }
+
+ // remove the pid file if it exists
+ remove(slave_pid);
+
+ // spawn
+ if ((err = spawn(mysqld_file, al, FALSE, NULL, slave_out, slave_err)) == 0)
+ {
+ sleep_until_file_exists(slave_pid);
+
+ if ((err = wait_for_server_start(bin_dir, user, password, slave_port)) == 0)
+ {
+ slave_running = TRUE;
+ }
+ else
+ {
+ log_error("The slave server went down early.");
+ }
+ }
+ else
+ {
+ log_error("Unable to start slave server.");
+ }
+
+ // free args
+ free_args(al);
+}
+
+/******************************************************************************
+
+ mysql_start()
+
+ Start the mysql servers.
+
+******************************************************************************/
+void mysql_start()
+{
+ start_master();
+
+ start_slave();
+
+ // activate the test screen
+ ActivateScreen(getscreenhandle());
+}
+
+/******************************************************************************
+
+ stop_slave()
+
+ Stop the slave server.
+
+******************************************************************************/
+void stop_slave()
+{
+ int err;
+
+ // running?
+ if (!slave_running) return;
+
+ // stop
+ if ((err = stop_server(bin_dir, user, password, slave_port, slave_pid)) == 0)
+ {
+ slave_running = FALSE;
+ }
+ else
+ {
+ log_error("Unable to stop slave server.");
+ }
+}
+
+/******************************************************************************
+
+ stop_master()
+
+ Stop the master server.
+
+******************************************************************************/
+void stop_master()
+{
+ int err;
+
+ // running?
+ if (!master_running) return;
+
+ if ((err = stop_server(bin_dir, user, password, master_port, master_pid)) == 0)
+ {
+ master_running = FALSE;
+ }
+ else
+ {
+ log_error("Unable to stop master server.");
+ }
+}
+
+/******************************************************************************
+
+ mysql_stop()
+
+ Stop the mysql servers.
+
+******************************************************************************/
+void mysql_stop()
+{
+ stop_master();
+
+ stop_slave();
+
+ // activate the test screen
+ ActivateScreen(getscreenhandle());
+}
+
+/******************************************************************************
+
+ mysql_restart()
+
+ Restart the mysql servers.
+
+******************************************************************************/
+void mysql_restart()
+{
+ log_info("Restarting the MySQL server(s): %u", ++restarts);
+
+ mysql_stop();
+
+ mysql_start();
+}
+
+/******************************************************************************
+
+ read_option()
+
+ Read the option file.
+
+******************************************************************************/
+int read_option(char *opt_file, char *opt)
+{
+ int fd, err;
+ int result;
+ char *p;
+ char buf[PATH_MAX];
+
+ // copy current option
+ strncpy(buf, opt, PATH_MAX);
+
+ // open options file
+ fd = open(opt_file, O_RDONLY);
+
+ err = read(fd, opt, PATH_MAX);
+
+ close(fd);
+
+ if (err > 0)
+ {
+ // terminate string
+ if ((p = strchr(opt, '\n')) != NULL)
+ {
+ *p = NULL;
+
+ // check for a '\r'
+ if ((p = strchr(opt, '\r')) != NULL)
+ {
+ *p = NULL;
+ }
+ }
+ else
+ {
+ opt[err] = NULL;
+ }
+
+ // check for $MYSQL_TEST_DIR
+ if ((p = strstr(opt, "$MYSQL_TEST_DIR")) != NULL)
+ {
+ char temp[PATH_MAX];
+
+ *p = NULL;
+
+ strcpy(temp, p + strlen("$MYSQL_TEST_DIR"));
+
+ strcat(opt, mysql_test_dir);
+
+ strcat(opt, temp);
+ }
+ }
+ else
+ {
+ // clear option
+ *opt = NULL;
+ }
+
+ // compare current option with previous
+ return strcmp(opt, buf);
+}
+
+/******************************************************************************
+
+ run_test()
+
+ Run the given test case.
+
+******************************************************************************/
+void run_test(char *test)
+{
+ char temp[PATH_MAX];
+ char *rstr;
+ double elapsed = 0;
+ int skip = FALSE;
+ int restart = FALSE;
+ int flag = FALSE;
+ struct stat info;
+
+ // single test?
+ if (!single_test)
+ {
+ // skip tests in the skip list
+ snprintf(temp, PATH_MAX, " %s ", test);
+ skip = (strindex(skip_test, temp) != NULL);
+ }
+
+ // skip test?
+ if (!skip)
+ {
+ char test_file[PATH_MAX];
+ char master_opt_file[PATH_MAX];
+ char slave_opt_file[PATH_MAX];
+ char slave_master_info_file[PATH_MAX];
+ char result_file[PATH_MAX];
+ char reject_file[PATH_MAX];
+ char out_file[PATH_MAX];
+ char err_file[PATH_MAX];
+ int err;
+ arg_list al;
+ NXTime_t start, stop;
+
+ // skip slave?
+ flag = skip_slave;
+ skip_slave = (strncmp(test, "rpl", 3) != 0);
+ if (flag != skip_slave) restart = TRUE;
+
+ // create files
+ snprintf(master_opt_file, PATH_MAX, "%s/%s-master.opt", test_dir, test);
+ snprintf(slave_opt_file, PATH_MAX, "%s/%s-slave.opt", test_dir, test);
+ snprintf(slave_master_info_file, PATH_MAX, "%s/%s-slave-master-info.opt", test_dir, test);
+ snprintf(reject_file, PATH_MAX, "%s/%s%s", result_dir, test, REJECT_SUFFIX);
+ snprintf(out_file, PATH_MAX, "%s/%s%s", result_dir, test, OUT_SUFFIX);
+ snprintf(err_file, PATH_MAX, "%s/%s%s", result_dir, test, ERR_SUFFIX);
+
+ // netware specific files
+ snprintf(test_file, PATH_MAX, "%s/%s%s", test_dir, test, NW_TEST_SUFFIX);
+ if (stat(test_file, &info))
+ {
+ snprintf(test_file, PATH_MAX, "%s/%s%s", test_dir, test, TEST_SUFFIX);
+ }
+
+ snprintf(result_file, PATH_MAX, "%s/%s%s", result_dir, test, NW_RESULT_SUFFIX);
+ if (stat(result_file, &info))
+ {
+ snprintf(result_file, PATH_MAX, "%s/%s%s", result_dir, test, RESULT_SUFFIX);
+ }
+
+ // init scripts
+ snprintf(master_init_script, PATH_MAX, "%s/%s-master.sh", test_dir, test);
+ if (stat(master_init_script, &info))
+ master_init_script[0] = NULL;
+ else
+ restart = TRUE;
+
+ snprintf(slave_init_script, PATH_MAX, "%s/%s-slave.sh", test_dir, test);
+ if (stat(slave_init_script, &info))
+ slave_init_script[0] = NULL;
+ else
+ restart = TRUE;
+
+ // read options
+ if (read_option(master_opt_file, master_opt)) restart = TRUE;
+ if (read_option(slave_opt_file, slave_opt)) restart = TRUE;
+ if (read_option(slave_master_info_file, slave_master_info)) restart = TRUE;
+
+ // cleanup previous run
+ remove(reject_file);
+ remove(out_file);
+ remove(err_file);
+
+ // start or restart?
+ if (!master_running) mysql_start();
+ else if (restart) mysql_restart();
+
+ // let the system stabalize
+ sleep(1);
+
+ // show test
+ log("%-46s ", test);
+
+ // args
+ init_args(al);
+ add_arg(al, "%s", mysqltest_file);
+ add_arg(al, "--no-defaults");
+ add_arg(al, "--port=%u", master_port);
+ add_arg(al, "--database=%s", db);
+ add_arg(al, "--user=%s", user);
+ add_arg(al, "--password=%s", password);
+ add_arg(al, "--silent");
+ add_arg(al, "--basedir=%s/", mysql_test_dir);
+ add_arg(al, "--host=127.0.0.1");
+ add_arg(al, "-v");
+ add_arg(al, "-R");
+ add_arg(al, "%s", result_file);
+
+ // start timer
+ NXGetTime(NX_SINCE_BOOT, NX_USECONDS, &start);
+
+ // spawn
+ err = spawn(mysqltest_file, al, TRUE, test_file, out_file, err_file);
+
+ // stop timer
+ NXGetTime(NX_SINCE_BOOT, NX_USECONDS, &stop);
+
+ // calculate
+ elapsed = ((double)(stop - start)) / NX_USECONDS;
+ total_time += elapsed;
+
+ // free args
+ free_args(al);
+
+ if (err == 0)
+ {
+ // pass
+ rstr = TEST_PASS;
+ ++total_pass;
+
+ // increment total
+ ++total_test;
+ }
+ else if (err == 2)
+ {
+ // skip
+ rstr = TEST_SKIP;
+ ++total_skip;
+ }
+ else if (err == 1)
+ {
+ // fail
+ rstr = TEST_FAIL;
+ ++total_fail;
+
+ // increment total
+ ++total_test;
+ }
+ else
+ {
+ rstr = TEST_BAD;
+ }
+ }
+ else // early skips
+ {
+ // show test
+ log("%-46s ", test);
+
+ // skip
+ rstr = TEST_SKIP;
+ ++total_skip;
+ }
+
+ // result
+ log("%10.06f %-14s\n", elapsed, rstr);
+}
+
+/******************************************************************************
+
+ vlog()
+
+ Log the message.
+
+******************************************************************************/
+void vlog(char *format, va_list ap)
+{
+ vfprintf(stdout, format, ap);
+ fflush(stdout);
+
+ if (log_fd)
+ {
+ vfprintf(log_fd, format, ap);
+ fflush(log_fd);
+ }
+}
+
+/******************************************************************************
+
+ log()
+
+ Log the message.
+
+******************************************************************************/
+void log(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ vlog(format, ap);
+
+ va_end(ap);
+}
+
+/******************************************************************************
+
+ log_info()
+
+ Log the given information.
+
+******************************************************************************/
+void log_info(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ log("-- INFO : ");
+ vlog(format, ap);
+ log("\n");
+
+ va_end(ap);
+}
+
+/******************************************************************************
+
+ log_error()
+
+ Log the given error.
+
+******************************************************************************/
+void log_error(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ log("-- ERROR: ");
+ vlog(format, ap);
+ log("\n");
+
+ va_end(ap);
+}
+
+/******************************************************************************
+
+ log_errno()
+
+ Log the given error and errno.
+
+******************************************************************************/
+void log_errno(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ log("-- ERROR: (%003u) ", errno);
+ vlog(format, ap);
+ log("\n");
+
+ va_end(ap);
+}
+
+/******************************************************************************
+
+ die()
+
+ Exit the application.
+
+******************************************************************************/
+void die(char *msg)
+{
+ log_error(msg);
+
+ pressanykey();
+
+ exit(-1);
+}
+
+/******************************************************************************
+
+ setup()
+
+ Setup the mysql test enviornment.
+
+******************************************************************************/
+void setup(char *file)
+{
+ char temp[PATH_MAX];
+ char *p;
+
+ // set the timezone for the timestamp test
+ setenv("TZ", "GMT-3", TRUE);
+
+ // find base dir
+ strcpy(temp, strlwr(file));
+ while((p = strchr(temp, '\\')) != NULL) *p = '/';
+
+ if ((p = strindex(temp, "/mysql-test/")) != NULL)
+ {
+ *p = NULL;
+ strcpy(base_dir, temp);
+ }
+
+ // setup paths
+ snprintf(bin_dir, PATH_MAX, "%s/bin", base_dir);
+ snprintf(mysql_test_dir, PATH_MAX, "%s/mysql-test", base_dir);
+ snprintf(test_dir, PATH_MAX, "%s/t", mysql_test_dir);
+ snprintf(mysql_tmp_dir, PATH_MAX, "%s/var/tmp", mysql_test_dir);
+ snprintf(result_dir, PATH_MAX, "%s/r", mysql_test_dir);
+ snprintf(master_dir, PATH_MAX, "%s/var/master-data", mysql_test_dir);
+ snprintf(slave_dir, PATH_MAX, "%s/var/slave-data", mysql_test_dir);
+ snprintf(lang_dir, PATH_MAX, "%s/share/english", base_dir);
+ snprintf(char_dir, PATH_MAX, "%s/share/charsets", base_dir);
+
+ // setup files
+ snprintf(mysqld_file, PATH_MAX, "%s/mysqld", bin_dir);
+ snprintf(mysqltest_file, PATH_MAX, "%s/mysqltest", bin_dir);
+ snprintf(mysqladmin_file, PATH_MAX, "%s/mysqladmin", bin_dir);
+ snprintf(master_pid, PATH_MAX, "%s/var/run/master.pid", mysql_test_dir);
+ snprintf(slave_pid, PATH_MAX, "%s/var/run/slave.pid", mysql_test_dir);
+
+ // create log file
+ snprintf(temp, PATH_MAX, "%s/mysql-test-run.log", mysql_test_dir);
+ if ((log_fd = fopen(temp, "w+")) == NULL)
+ {
+ log_errno("Unable to create log file.");
+ }
+
+ // prepare skip test list
+ while((p = strchr(skip_test, ',')) != NULL) *p = ' ';
+ strcpy(temp, strlwr(skip_test));
+ snprintf(skip_test, PATH_MAX, " %s ", temp);
+
+ // enviornment
+ setenv("MYSQL_TEST_DIR", mysql_test_dir, 1);
+
+ // install test databases
+ mysql_install_db();
+}
+
+/******************************************************************************
+
+ main()
+
+******************************************************************************/
+int main(int argc, char **argv)
+{
+ log("Initializing Tests...\n");
+
+ // setup
+ setup(argv[0]);
+
+ log("Starting Tests...\n");
+
+ log("\n");
+ log(HEADER);
+ log(DASH);
+
+ if (argc > 1)
+ {
+ int i;
+
+ // single test
+ single_test = TRUE;
+
+ for (i = 1; i < argc; i++)
+ {
+ // run given test
+ run_test(argv[i]);
+ }
+ }
+ else
+ {
+ // run all tests
+ DIR *dir = opendir(test_dir);
+ DIR *entry;
+ char test[NAME_MAX];
+ char *p;
+
+ // single test
+ single_test = FALSE;
+
+ if (dir == NULL)
+ {
+ die("Unable to open tests directory.");
+ }
+
+ while((entry = readdir(dir)) != NULL)
+ {
+ if (!S_ISDIR(entry->d_type))
+ {
+ strcpy(test, strlwr(entry->d_name));
+
+ // find the test suffix
+ if ((p = strindex(test, TEST_SUFFIX)) != NULL)
+ {
+ // null terminate at the suffix
+ *p = '\0';
+
+ // run test
+ run_test(test);
+ }
+ }
+ }
+
+ closedir(dir);
+ }
+
+ log(DASH);
+ log("\n");
+
+ log("Ending Tests...\n");
+
+ // stop server
+ mysql_stop();
+
+ // report stats
+ report_stats();
+
+ // close log
+ if (log_fd) fclose(log_fd);
+
+ // keep results up
+ pressanykey();
+
+ return 0;
+}
+
diff --git a/netware/mysqld_safe.c b/netware/mysqld_safe.c
new file mode 100644
index 00000000000..cf0d6989d8d
--- /dev/null
+++ b/netware/mysqld_safe.c
@@ -0,0 +1,662 @@
+/*
+ Copyright (c) 2003 Novell, Inc. All Rights Reserved.
+
+ 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 <stdlib.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <sys/stat.h>
+#include <monitor.h>
+#include <strings.h>
+#include <getopt.h>
+#include <screen.h>
+#include <dirent.h>
+
+#include "my_config.h"
+#include "my_manage.h"
+
+/******************************************************************************
+
+ global variables
+
+******************************************************************************/
+char autoclose;
+char basedir[PATH_MAX];
+char datadir[PATH_MAX];
+char pid_file[PATH_MAX];
+char address[PATH_MAX];
+char port[PATH_MAX];
+char err_log[PATH_MAX];
+char safe_log[PATH_MAX];
+char mysqld[PATH_MAX];
+char hostname[PATH_MAX];
+char default_option[PATH_MAX];
+
+FILE *log_fd = NULL;
+
+/******************************************************************************
+
+ prototypes
+
+******************************************************************************/
+
+void vlog(char *, va_list);
+void log(char *, ...);
+void start_defaults(int, char*[]);
+void finish_defaults();
+void read_defaults(arg_list);
+void parse_args(int, char*[]);
+void get_options(int, char*[]);
+void check_data_vol();
+void check_setup();
+void check_tables();
+void mysql_start(int, char*[]);
+
+/******************************************************************************
+
+ functions
+
+******************************************************************************/
+
+/******************************************************************************
+
+ vlog()
+
+ Log the message.
+
+******************************************************************************/
+void vlog(char *format, va_list ap)
+{
+ vfprintf(stdout, format, ap);
+ fflush(stdout);
+
+ if (log_fd)
+ {
+ vfprintf(log_fd, format, ap);
+ fflush(log_fd);
+ }
+}
+
+/******************************************************************************
+
+ log()
+
+ Log the message.
+
+******************************************************************************/
+void log(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ vlog(format, ap);
+
+ va_end(ap);
+}
+
+/******************************************************************************
+
+ start_defaults()
+
+ Start setting the defaults.
+
+******************************************************************************/
+void start_defaults(int argc, char *argv[])
+{
+ struct stat buf;
+ int i;
+
+ // default options
+ static char *default_options[] =
+ {
+ "--no-defaults",
+ "--defaults-file=",
+ "--defaults-extra-file=",
+ NULL
+ };
+
+ // autoclose
+ autoclose = FALSE;
+
+ // basedir
+ get_basedir(argv[0], basedir);
+
+ // hostname
+ if (gethostname(hostname,PATH_MAX) < 0)
+ {
+ // default
+ strcpy(hostname,"mysql");
+ }
+
+ // address
+ snprintf(address, PATH_MAX, "0.0.0.0");
+
+ // port
+ snprintf(port, PATH_MAX, "3306");
+
+ // default option
+ default_option[0] = NULL;
+ for (i=0; (argc > 1) && default_options[i]; i++)
+ {
+ if(!strnicmp(argv[1], default_options[i], strlen(default_options[i])))
+ {
+ strncpy(default_option, argv[1], PATH_MAX);
+ break;
+ }
+ }
+
+ // set after basedir is established
+ datadir[0] = NULL;
+ pid_file[0] = NULL;
+ err_log[0] = NULL;
+ safe_log[0] = NULL;
+ mysqld[0] = NULL;
+}
+
+/******************************************************************************
+
+ finish_defaults()
+
+ Finish settig the defaults.
+
+******************************************************************************/
+void finish_defaults()
+{
+ struct stat buf;
+ int i;
+
+ // datadir
+ if (!datadir[0]) snprintf(datadir, PATH_MAX, "%s/data", basedir);
+
+ // pid-file
+ if (!pid_file[0]) snprintf(pid_file, PATH_MAX, "%s/%s.pid", datadir, hostname);
+
+ // err-log
+ if (!err_log[0]) snprintf(err_log, PATH_MAX, "%s/%s.err", datadir, hostname);
+
+ // safe-log
+ if (!safe_log[0]) snprintf(safe_log, PATH_MAX, "%s/%s.log", datadir, hostname);
+
+ // mysqld
+ if (!mysqld[0]) snprintf(mysqld, PATH_MAX, "%s/bin/mysqld-max", basedir);
+
+ if (stat(mysqld, &buf))
+ {
+ snprintf(mysqld, PATH_MAX, "%s/bin/mysqld", basedir);
+ }
+}
+
+/******************************************************************************
+
+ read_defaults()
+
+ Read the defaults.
+
+******************************************************************************/
+void read_defaults(arg_list pal)
+{
+ arg_list al;
+ char defaults_file[PATH_MAX];
+ char mydefaults[PATH_MAX];
+ char line[PATH_MAX];
+ FILE *fp;
+
+ // defaults output file
+ snprintf(defaults_file, PATH_MAX, "%s/bin/defaults.out", basedir);
+ remove(defaults_file);
+
+ // mysqladmin file
+ snprintf(mydefaults, PATH_MAX, "%s/bin/my_print_defaults", basedir);
+
+ // args
+ init_args(al);
+ add_arg(al, mydefaults);
+ if (default_option[0]) add_arg(al, default_option);
+ add_arg(al, "mysqld");
+ add_arg(al, "server");
+ add_arg(al, "mysqld_safe");
+ add_arg(al, "safe_mysqld");
+
+ spawn(mydefaults, al, TRUE, NULL, defaults_file, NULL);
+
+ free_args(al);
+
+ // gather defaults
+ if((fp = fopen(defaults_file, "r")) != NULL)
+ {
+ while(fgets(line, PATH_MAX, fp))
+ {
+ char *p;
+
+ // remove end-of-line character
+ if ((p = strrchr(line, '\n')) != NULL) *p = '\0';
+
+ // add the option as an argument
+ add_arg(pal, line);
+ }
+
+ fclose(fp);
+ }
+
+ // remove file
+ remove(defaults_file);
+}
+
+/******************************************************************************
+
+ parse_args()
+
+ Get the options.
+
+******************************************************************************/
+void parse_args(int argc, char *argv[])
+{
+ int index = 0;
+ int c;
+
+ // parse options
+ enum opts
+ {
+ OPT_BASEDIR = 0xFF,
+ OPT_DATADIR,
+ OPT_PID_FILE,
+ OPT_BIND_ADDRESS,
+ OPT_PORT,
+ OPT_ERR_LOG,
+ OPT_SAFE_LOG,
+ OPT_MYSQLD
+ };
+
+ static struct option options[] =
+ {
+ {"autoclose", no_argument, &autoclose, TRUE},
+ {"basedir", required_argument, 0, OPT_BASEDIR},
+ {"datadir", required_argument, 0, OPT_DATADIR},
+ {"pid-file", required_argument, 0, OPT_PID_FILE},
+ {"bind-address", required_argument, 0, OPT_BIND_ADDRESS},
+ {"port", required_argument, 0, OPT_PORT},
+ {"err-log", required_argument, 0, OPT_ERR_LOG},
+ {"safe-log", required_argument, 0, OPT_SAFE_LOG},
+ {"mysqld", required_argument, 0, OPT_MYSQLD},
+ {0, 0, 0, 0}
+ };
+
+ // we have to reset getopt_long because we use it multiple times
+ optind = 1;
+
+ // turn off error reporting
+ opterr = 0;
+
+ while ((c = getopt_long(argc, argv, "b:h:P:", options, &index)) >= 0)
+ {
+ switch (c)
+ {
+ case OPT_BASEDIR:
+ case 'b':
+ strcpy(basedir, optarg);
+ break;
+
+ case OPT_DATADIR:
+ case 'h':
+ strcpy(datadir, optarg);
+ break;
+
+ case OPT_PID_FILE:
+ strcpy(pid_file, optarg);
+ break;
+
+ case OPT_BIND_ADDRESS:
+ strcpy(address, optarg);
+ break;
+
+ case OPT_PORT:
+ case 'P':
+ strcpy(port, optarg);
+ break;
+
+ case OPT_ERR_LOG:
+ strcpy(err_log, optarg);
+ break;
+
+ case OPT_SAFE_LOG:
+ strcpy(safe_log, optarg);
+ break;
+
+ case OPT_MYSQLD:
+ strcpy(mysqld, optarg);
+ break;
+
+ default:
+ // ignore
+ break;
+ }
+ }
+}
+
+/******************************************************************************
+
+ get_options()
+
+ Get the options.
+
+******************************************************************************/
+void get_options(int argc, char *argv[])
+{
+ arg_list al;
+
+ // start defaults
+ start_defaults(argc, argv);
+
+ // default file arguments
+ init_args(al);
+ add_arg(al, "dummy");
+ read_defaults(al);
+ parse_args(al->argc, al->argv);
+ free_args(al);
+
+ // command-line arguments
+ parse_args(argc, argv);
+
+ // finish defaults
+ finish_defaults();
+}
+
+/******************************************************************************
+
+ check_data_vol()
+
+ Check the database volume.
+
+******************************************************************************/
+void check_data_vol()
+{
+ // warn if the data is on a Traditional volume
+ struct volume_info vol;
+ char buff[PATH_MAX];
+ char *p;
+
+ // clear struct
+ memset(&vol, 0, sizeof(vol));
+
+ // find volume name
+ strcpy(buff, datadir);
+ if (p = strchr(buff, ':'))
+ {
+ // terminate after volume name
+ *p = 0;
+ }
+ else
+ {
+ // assume SYS volume
+ strcpy(buff, "SYS");
+ }
+
+ // retrieve information
+ netware_vol_info_from_name(&vol, buff);
+
+ if ((vol.flags & VOL_NSS_PRESENT) == 0)
+ {
+ log("Error: The data directory is not on an NSS volume!\n\n");
+ exit(-1);
+ }
+}
+
+/******************************************************************************
+
+ check_setup()
+
+ Check the current setup.
+
+******************************************************************************/
+void check_setup()
+{
+ struct stat info;
+ char temp[PATH_MAX];
+
+ // remove any current pid_file
+ if (!stat(pid_file, &info) && (remove(pid_file) < 0))
+ {
+ log("ERROR: Unable to remove current pid file!\n\n");
+ exit(-1);
+ }
+
+ // check the data volume
+ check_data_vol();
+
+ // check for a database
+ snprintf(temp, PATH_MAX, "%s/mysql/host.frm", datadir);
+ if (stat(temp, &info))
+ {
+ log("ERROR: No database found in the data directory!\n\n");
+ exit(-1);
+ }
+}
+
+/******************************************************************************
+
+ check_tables()
+
+ Check the database tables.
+
+******************************************************************************/
+void check_tables()
+{
+ arg_list al;
+ char mycheck[PATH_MAX];
+ char table[PATH_MAX];
+ char db[PATH_MAX];
+ DIR *datadir_entry, *db_entry, *table_entry;
+
+ // status
+ log("checking tables...\n");
+
+ // list databases
+ if ((datadir_entry = opendir(datadir)) == NULL)
+ {
+ return;
+ }
+
+ while((db_entry = readdir(datadir_entry)) != NULL)
+ {
+ if (db_entry->d_name[0] == '.')
+ {
+ // Skip
+ }
+ else if (S_ISDIR(db_entry->d_type))
+ {
+ // create long db name
+ snprintf(db, PATH_MAX, "%s/%s", datadir, db_entry->d_name);
+
+ // list tables
+ if ((db_entry = opendir(db)) == NULL)
+ {
+ continue;
+ }
+
+ while((table_entry = readdir(db_entry)) != NULL)
+ {
+ // create long table name
+ snprintf(table, PATH_MAX, "%s/%s", db, strlwr(table_entry->d_name));
+
+ if (strindex(table, ".myi"))
+ {
+ // ** myisamchk
+
+ // mysqladmin file
+ snprintf(mycheck, PATH_MAX, "%s/bin/myisamchk", basedir);
+
+ // args
+ init_args(al);
+ add_arg(al, mycheck);
+ add_arg(al, "--silent");
+ add_arg(al, "--force");
+ add_arg(al, "--fast");
+ add_arg(al, "--medium-check");
+ add_arg(al, "-O");
+ add_arg(al, "key_buffer=64M");
+ add_arg(al, "-O");
+ add_arg(al, "sort_buffer=64M");
+ add_arg(al, table);
+
+ spawn(mycheck, al, TRUE, NULL, NULL, NULL);
+
+ free_args(al);
+ }
+ else if (strindex(table, ".ism"))
+ {
+ // ** isamchk
+
+ // mysqladmin file
+ snprintf(mycheck, PATH_MAX, "%s/bin/isamchk", basedir);
+
+ // args
+ init_args(al);
+ add_arg(al, mycheck);
+ add_arg(al, "--silent");
+ add_arg(al, "--force");
+ add_arg(al, "-O");
+ add_arg(al, "sort_buffer=64M");
+ add_arg(al, table);
+
+ spawn(mycheck, al, TRUE, NULL, NULL, NULL);
+
+ free_args(al);
+ }
+ }
+ }
+ }
+}
+
+/******************************************************************************
+
+ mysql_start()
+
+ Start the mysql server.
+
+******************************************************************************/
+void mysql_start(int argc, char *argv[])
+{
+ arg_list al;
+ int i, j, err;
+ struct stat info;
+ time_t cal;
+ struct tm lt;
+ char stamp[PATH_MAX];
+ char skip;
+
+ // private options
+ static char *private_options[] =
+ {
+ "--autoclose",
+ "--err-log=",
+ "--mysqld=",
+ NULL
+ };
+
+ // args
+ init_args(al);
+ add_arg(al, "%s", mysqld);
+
+ // parent args
+ for(i = 1; i < argc; i++)
+ {
+ skip = FALSE;
+
+ // skip private arguments
+ for (j=0; private_options[j]; j++)
+ {
+ if(!strnicmp(argv[i], private_options[j], strlen(private_options[j])))
+ {
+ skip = TRUE;
+ break;
+ }
+ }
+
+ if (!skip) add_arg(al, "%s", argv[i]);
+ }
+
+ // spawn
+ do
+ {
+ // check the database tables
+ check_tables();
+
+ // status
+ time(&cal);
+ localtime_r(&cal, &lt);
+ strftime(stamp, PATH_MAX, "%d %b %Y %H:%M:%S", &lt);
+ log("mysql started : %s\n", stamp);
+
+ // spawn mysqld
+ spawn(mysqld, al, TRUE, NULL, NULL, err_log);
+ }
+ while (!stat(pid_file, &info));
+
+ // status
+ time(&cal);
+ localtime_r(&cal, &lt);
+ strftime(stamp, PATH_MAX, "%d %b %Y %H:%M:%S", &lt);
+ log("mysql stopped : %s\n\n", stamp);
+
+ // free args
+ free_args(al);
+}
+
+/******************************************************************************
+
+ main()
+
+******************************************************************************/
+int main(int argc, char **argv)
+{
+ char temp[PATH_MAX];
+
+ // get the options
+ get_options(argc, argv);
+
+ // keep the screen up
+ if (!autoclose) setscreenmode(SCR_NO_MODE);
+
+ // create log file
+ log_fd = fopen(safe_log, "w+");
+
+ // header
+ log("MySQL Server %s, for %s (%s)\n\n", VERSION, SYSTEM_TYPE, MACHINE_TYPE);
+
+ // status
+ log("address : %s\n", address);
+ log("port : %s\n", port);
+ log("daemon : %s\n", mysqld);
+ log("base directory : %s\n", basedir);
+ log("data directory : %s\n", datadir);
+ log("pid file : %s\n", pid_file);
+ log("error file : %s\n", err_log);
+ log("log file : %s\n", safe_log);
+ log("\n");
+
+ // check setup
+ check_setup();
+
+ // start the MySQL server
+ mysql_start(argc, argv);
+
+ // close log file
+ if (log_fd) fclose(log_fd);
+
+ return 0;
+}
diff --git a/netware/overlay.tar.gz b/netware/overlay.tar.gz
new file mode 100644
index 00000000000..bff2118b458
--- /dev/null
+++ b/netware/overlay.tar.gz
Binary files differ
diff --git a/netware/test_db.sql b/netware/test_db.sql
new file mode 100644
index 00000000000..453d81693ed
--- /dev/null
+++ b/netware/test_db.sql
@@ -0,0 +1,17 @@
+USE mysql;
+
+CREATE TABLE db (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db,User), KEY User (User)) comment='Database privileges';
+
+CREATE TABLE host (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db)) comment='Host privileges; Merged with database privileges';
+
+CREATE TABLE user (Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(16) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') DEFAULT 'N' NOT NULL, File_priv enum('N','Y') DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL, References_priv enum('N','Y') DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0 NOT NULL, max_updates int(11) unsigned DEFAULT 0 NOT NULL, max_connections int(11) unsigned DEFAULT 0 NOT NULL, PRIMARY KEY Host (Host,User)) comment='Users and global privileges';
+
+INSERT INTO user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
+INSERT INTO user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
+INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
+
+CREATE TABLE func (name char(64) binary DEFAULT '' NOT NULL, ret tinyint(1) DEFAULT '0' NOT NULL, dl char(128) DEFAULT '' NOT NULL, type enum ('function','aggregate') NOT NULL, PRIMARY KEY (name)) comment='User defined functions';
+
+CREATE TABLE tables_priv (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(60) binary DEFAULT '' NOT NULL, Grantor char(77) DEFAULT '' NOT NULL, Timestamp timestamp(14), Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL, Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name), KEY Grantor (Grantor)) comment='Table privileges';
+
+CREATE TABLE columns_priv (Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Table_name char(64) binary DEFAULT '' NOT NULL, Column_name char(64) binary DEFAULT '' NOT NULL, Timestamp timestamp(14), Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL, PRIMARY KEY (Host,Db,User,Table_name,Column_name)) comment='Column privileges';