diff options
Diffstat (limited to 'mysql-test/my_manage.c')
-rw-r--r-- | mysql-test/my_manage.c | 851 |
1 files changed, 851 insertions, 0 deletions
diff --git a/mysql-test/my_manage.c b/mysql-test/my_manage.c new file mode 100644 index 00000000000..ba5c674d105 --- /dev/null +++ b/mysql-test/my_manage.c @@ -0,0 +1,851 @@ +/* + 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> +#ifndef __WIN__ +#include <dirent.h> +#endif +#include <string.h> +#ifdef __NETWARE__ +#include <screen.h> +#include <proc.h> +#else +#include <sys/types.h> +#ifndef __WIN__ +#include <sys/wait.h> +#include <unistd.h> +#include <fnmatch.h> +#else +#include <direct.h> +#include <stdlib.h> +#include <stdio.h> +#endif +#endif +#include <ctype.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <assert.h> + +#include "my_manage.h" + +#ifndef __NETWARE__ +#define ASSERT assert +extern char **environ; +#endif + + + +/****************************************************************************** + + macros + +******************************************************************************/ + +/****************************************************************************** + + global variables + +******************************************************************************/ + +/****************************************************************************** + + functions + +******************************************************************************/ + +/****************************************************************************** + + init_args() + + Init an argument list. + +******************************************************************************/ + +void init_args(arg_list_t *al) +{ + ASSERT(al != NULL); + + al->argc= 0; + al->size= ARG_BUF; + al->argv= malloc(al->size * sizeof(char *)); + ASSERT(al->argv != NULL); + + return; +} + +/****************************************************************************** + + add_arg() + + Add an argument to a list. + +******************************************************************************/ + +void add_arg(arg_list_t *al, const char *format, ...) +{ + va_list ap; + char temp[PATH_MAX]; + + ASSERT(al != NULL); + + /* increase size */ + if (al->argc >= (int)al->size) + { + al->size+= ARG_BUF; + al->argv= realloc(al->argv, al->size * sizeof(char *)); + ASSERT(al->argv != NULL); + } + + if (format) + { + va_start(ap, format); + vsprintf(temp, format, ap); + va_end(ap); + + al->argv[al->argc]= malloc(strlen(temp)+1); + ASSERT(al->argv[al->argc] != NULL); + strcpy(al->argv[al->argc], temp); + + ++(al->argc); + } + else + { + al->argv[al->argc]= NULL; + } + + return; +} + +/****************************************************************************** + + free_args() + + Free an argument list. + +******************************************************************************/ + +void free_args(arg_list_t *al) +{ + int i; + + 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->argv); + al->argc= 0; + al->argv= NULL; + + return; +} + +/****************************************************************************** + + sleep_until_file_deleted() + + Sleep until the given file is no longer found. + +******************************************************************************/ + +#ifndef __WIN__ +int sleep_until_file_deleted(char *pid_file) +#else +int sleep_until_file_deleted(HANDLE pid_file) +#endif +{ + int err= 0; /* Initiate to supress warning */ +#ifndef __WIN__ + struct stat buf; + int i; + + for (i= 0; (i < TRY_MAX) && (err= !stat(pid_file, &buf)); i++) sleep(1); + + if (err != 0) err= errno; +#else + err= (WaitForSingleObject(pid_file, TRY_MAX*1000) == WAIT_TIMEOUT); +#endif + return err; +} + +/****************************************************************************** + + sleep_until_file_exists() + + Sleep until the given file exists. + +******************************************************************************/ + +#ifndef __WIN__ +int sleep_until_file_exists(char *pid_file) +#else +int sleep_until_file_exists(HANDLE pid_file) +#endif +{ + int err= 0; /* Initiate to supress warning */ +#ifndef __WIN__ + struct stat buf; + int i; + + for (i= 0; (i < TRY_MAX) && (err= stat(pid_file, &buf)); i++) sleep(1); + + if (err != 0) err= errno; +#else + err= (WaitForSingleObject(pid_file, TRY_MAX*1000) == WAIT_TIMEOUT); +#endif + return err; +} + +/****************************************************************************** + + wait_for_server_start() + + Wait for the server on the given port to start. + +******************************************************************************/ + +int wait_for_server_start(char *bin_dir __attribute__((unused)), + char *mysqladmin_file, + char *user, char *password, int port,char *tmp_dir) +{ + arg_list_t al; + int err= 0, i; + char trash[PATH_MAX]; + + /* mysqladmin file */ + snprintf(trash, PATH_MAX, "%s/trash.out",tmp_dir); + + /* 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"); + +/* #ifdef NOT_USED */ +#ifndef __NETWARE__ + add_arg(&al, "-O"); + add_arg(&al, "connect_timeout=10"); + add_arg(&al, "-w"); +#endif + + add_arg(&al, "--host=localhost"); +#ifndef __NETWARE__ + add_arg(&al, "--protocol=tcp"); +#endif + add_arg(&al, "ping"); + + /* + NetWare does not support the connect timeout in the TCP/IP stack + -- we will try the ping multiple times + */ +#ifndef __WIN__ + for (i= 0; (i < TRY_MAX) + && (err= spawn(mysqladmin_file, &al, TRUE, NULL, + trash, NULL, NULL)); i++) sleep(1); +#else + err= spawn(mysqladmin_file, &al, TRUE, NULL,trash, NULL, NULL); +#endif + + /* free args */ + free_args(&al); + + return err; +} + +/****************************************************************************** + + spawn() + + Spawn the given path with the given arguments. + +******************************************************************************/ + +#ifdef __NETWARE__ +int spawn(char *path, arg_list_t *al, int join, char *input, + char *output, char *error, char *pid_file) +{ + pid_t pid; + int result= 0; + wiring_t wiring= { FD_UNUSED, FD_UNUSED, FD_UNUSED }; + unsigned long flags= PROC_CURRENT_SPACE | PROC_INHERIT_CWD; + + /* open wiring */ + if (input) + wiring.infd= open(input, O_RDONLY); + + if (output) + wiring.outfd= open(output, O_WRONLY | O_CREAT | O_TRUNC); + + if (error) + wiring.errfd= open(error, O_WRONLY | O_CREAT | O_TRUNC); + + /* procve requires a NULL */ + add_arg(al, NULL); + + /* go */ + pid= procve(path, flags, NULL, &wiring, NULL, NULL, 0, + NULL, (const char **)al->argv); + + /* close wiring */ + if (wiring.infd != -1) + close(wiring.infd); + + if (wiring.outfd != -1) + close(wiring.outfd); + + if (wiring.errfd != -1) + close(wiring.errfd); + + return result; +} +#elif __WIN__ + +int spawn(char *path, arg_list_t *al, int join, char *input, + char *output, char *error, HANDLE *pid) +{ + intptr_t result; + int i; + STARTUPINFO startup_info; + PROCESS_INFORMATION process_information; + DWORD exit_code; + char win_args[1024]= ""; + char command_line[1024]= ""; + + /* Skip the first parameter */ + for (i= 1; i < al->argc; i++) + { + ASSERT(al->argv[i] != NULL); + strcat(win_args,al->argv[i]); + strcat(win_args," "); + } + + memset(&startup_info,0,sizeof(STARTUPINFO)); + startup_info.cb= sizeof(STARTUPINFO); + + if (input) + freopen(input, "rb", stdin); + + if (output) + freopen(output, "wb", stdout); + + if (error) + freopen(error, "wb", stderr); + + result= CreateProcess( + path, + (LPSTR)&win_args, + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &startup_info, + &process_information + ); + + if (result && process_information.hProcess) + { + if (join) + { + if (WaitForSingleObject(process_information.hProcess, mysqld_timeout) + == WAIT_TIMEOUT) + { + exit_code= -1; + } + else + { + GetExitCodeProcess(process_information.hProcess, &exit_code); + } + CloseHandle(process_information.hProcess); + } + else + { + exit_code= 0; + } + if (pid != NULL) + *pid= process_information.hProcess; + } + else + { + exit_code= -1; + } + if (input) + freopen("CONIN$","rb",stdin); + if (output) + freopen("CONOUT$","wb",stdout); + if (error) + freopen("CONOUT$","wb",stderr); + + return exit_code; +} +#else +int spawn(char *path, arg_list_t *al, int join, char *input, + char *output, char *error, char *pid_file __attribute__((unused))) +{ + pid_t pid; + int res_exec= 0; + int result= 0; + + pid= fork(); + + if (pid == -1) + { + fprintf(stderr, "fork was't created\n"); + /* We can't create the fork...exit with error */ + return EXIT_FAILURE; + } + + if (pid > 0) + { + /* The parent process is waiting for child process if join is not zero */ + if (join) + { + waitpid(pid, &result, 0); + if (WIFEXITED(result) != 0) + { + result= WEXITSTATUS(result); + } + else + { + result= EXIT_FAILURE; + } + } + } + else + { + + /* Child process */ + add_arg(al, NULL); + + /* Reassign streams */ + if (input) + freopen(input, "r", stdin); + + if (output) + freopen(output, "w", stdout); + + if (error) + freopen(error, "w", stderr); + + /* Spawn the process */ + if ((res_exec= execve(path, al->argv, environ)) < 0) + exit(EXIT_FAILURE); + + /* Restore streams */ + if (input) + freopen("/dev/tty", "r", stdin); + + if (output) + freopen("/dev/tty", "w", stdout); + + if (error) + freopen("/dev/tty", "w", stderr); + + exit(0); + } + + return result; +} +#endif +/****************************************************************************** + + stop_server() + + Stop the server with the given port and pid file. + +******************************************************************************/ + +int stop_server(char *bin_dir __attribute__((unused)), char *mysqladmin_file, + char *user, char *password, int port, +#ifndef __WIN__ + char *pid_file, +#else + HANDLE pid_file, +#endif + char *tmp_dir) +{ + arg_list_t al; + int err= 0; + char trash[PATH_MAX]; + + snprintf(trash, PATH_MAX, "%s/trash.out",tmp_dir); + + /* 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"); +#ifndef __NETWARE__ + add_arg(&al, "--protocol=tcp"); +#endif + add_arg(&al, "shutdown"); + + /* spawn */ + if ((err= spawn(mysqladmin_file, &al, TRUE, NULL, + trash, NULL, NULL)) == 0) + { + sleep_until_file_deleted(pid_file); + } + else + { +#ifndef __WIN__ + 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); +#else + TerminateProcess(pid_file,err); +#endif + } + + /* free args */ + free_args(&al); + + return err; +} + +/****************************************************************************** + + get_server_pid() + + Get the VM id with the given pid file. + +******************************************************************************/ + +#ifndef __WIN__ +pid_t get_server_pid(char *pid_file) +{ + char buf[PATH_MAX]; + int fd, err; + char *p; + pid_t id= 0; + + /* 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= '\0'; + + /* check for a '\r' */ + if ((p= strchr(buf, '\r')) != NULL) + { + *p= '\0'; + } + } + else + { + buf[err]= '\0'; + } + + 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) + { +#if !defined(__NETWARE__) + /* Send SIGTERM to pid */ + kill(pid, SIGTERM); +#else /* __NETWARE__ */ + /* destroy vm */ + NXVmDestroy(pid); +#endif + } +} +#endif +/****************************************************************************** + + del_tree() + + Delete the directory and subdirectories. + +******************************************************************************/ + +void del_tree(char *dir) +{ +#ifndef __WIN__ + DIR *parent= opendir(dir); + struct dirent *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); +#else + struct _finddata_t parent; + intptr_t handle; + char temp[PATH_MAX]; + char mask[PATH_MAX]; + + snprintf(mask,MAX_PATH,"%s/*.*",dir); + + if ((handle=_findfirst(mask,&parent)) == -1L) + { + return; + } + + do + { + /* create long name */ + snprintf(temp, PATH_MAX, "%s/%s", dir, parent.name); + if (parent.name[0] == '.') + { + /* Skip */ + } + else + if (parent.attrib & _A_SUBDIR) + { + /* delete subdirectory */ + del_tree(temp); + } + else + { + /* remove file */ + remove(temp); + } + } while (_findnext(handle,&parent) == 0); + + _findclose(handle); + + /* remove directory */ + _rmdir(dir); +#endif +} + +/****************************************************************************** + + removef() + +******************************************************************************/ + +int removef(const char *format, ...) +{ +#ifdef __NETWARE__ + va_list ap; + char path[PATH_MAX]; + + va_start(ap, format); + + vsnprintf(path, PATH_MAX, format, ap); + + va_end(ap); + return remove(path); + +#eldef __WIN__ + { + va_list ap; + char path[PATH_MAX]; + struct _finddata_t parent; + intptr_t handle; + char temp[PATH_MAX]; + char *p; + + va_start(ap, format); + + vsnprintf(path, PATH_MAX, format, ap); + + va_end(ap); + + p= path + strlen(path); + while (*p != '\\' && *p != '/' && p > path) p--; + + if ((handle=_findfirst(path,&parent)) == -1L) + { + /* if there is not files....it's ok */ + return 0; + } + + *p= '\0'; + + do + { + if (! (parent.attrib & _A_SUBDIR)) + { + snprintf(temp, PATH_MAX, "%s/%s", path, parent.name); + remove(temp); + } + }while (_findnext(handle,&parent) == 0); + + _findclose(handle); + } +#else + DIR *parent; + struct dirent *entry; + char temp[PATH_MAX]; + va_list ap; + char path[PATH_MAX]; + char *p; + /* Get path with mask */ + va_start(ap, format); + + vsnprintf(path, PATH_MAX, format, ap); + + va_end(ap); + + p= path + strlen(path); + while (*p != '\\' && *p != '/' && p > path) p--; + *p= '\0'; + p++; + + parent= opendir(path); + + if (parent == NULL) + { + return 1; /* Error, directory missing */ + } + + while ((entry= readdir(parent)) != NULL) + { + /* entry is not directory and entry matches with mask */ + if (!S_ISDIR(entry->d_type) && !fnmatch(p, entry->d_name,0)) + { + /* create long name */ + snprintf(temp, PATH_MAX, "%s/%s", path, entry->d_name); + /* Delete only files */ + remove(temp); + } + } +#endif + return 0; +} + +/****************************************************************************** + + get_basedir() + +******************************************************************************/ + +void get_basedir(char *argv0, char *basedir) +{ + char temp[PATH_MAX]; + char *p; + int position; + + ASSERT(argv0 != NULL); + ASSERT(basedir != NULL); + + strcpy(temp, strlwr(argv0)); + while ((p= strchr(temp, '\\')) != NULL) *p= '/'; + + if ((position= strinstr(temp, "/bin/")) != 0) + { + p= temp + position; + *p= '\0'; + strcpy(basedir, temp); + } +} + +uint strinstr(reg1 const char *str,reg4 const char *search) +{ + reg2 my_string i,j; + my_string start= (my_string) str; + + skipp: + while (*str != '\0') + { + if (*str++ == *search) + { + i=(my_string) str; + j= (my_string) search+1; + while (*j) + if (*i++ != *j++) goto skipp; + return ((uint) (str - start)); + } + } + return (0); +} + +/****************************************************************************** + + remove_empty_file() + +******************************************************************************/ + +void remove_empty_file(const char *file_name) +{ + struct stat file; + + if (!stat(file_name,&file)) + { + if (!file.st_size) + remove(file_name); + } +} |