diff options
-rw-r--r-- | VC++Files/mysys/mysys.dsp | 4 | ||||
-rw-r--r-- | VC++Files/mysys/mysys_ia64.dsp | 4 | ||||
-rw-r--r-- | client/mysql.cc | 31 | ||||
-rw-r--r-- | include/my_sys.h | 3 | ||||
-rw-r--r-- | mysys/my_conio.c | 217 |
5 files changed, 256 insertions, 3 deletions
diff --git a/VC++Files/mysys/mysys.dsp b/VC++Files/mysys/mysys.dsp index f47203d37bf..2f3d7bb272c 100644 --- a/VC++Files/mysys/mysys.dsp +++ b/VC++Files/mysys/mysys.dsp @@ -361,6 +361,10 @@ SOURCE=.\my_compress.c # End Source File # Begin Source File +SOURCE=.\my_conio.c +# End Source File +# Begin Source File + SOURCE=.\my_copy.c # End Source File # Begin Source File diff --git a/VC++Files/mysys/mysys_ia64.dsp b/VC++Files/mysys/mysys_ia64.dsp index a0877457286..622ae1d5bce 100644 --- a/VC++Files/mysys/mysys_ia64.dsp +++ b/VC++Files/mysys/mysys_ia64.dsp @@ -362,6 +362,10 @@ SOURCE=.\my_compress.c # End Source File # Begin Source File +SOURCE=.\my_conio.c +# End Source File +# Begin Source File + SOURCE=.\my_copy.c # End Source File # Begin Source File diff --git a/client/mysql.cc b/client/mysql.cc index 51822b64c82..be1541faaf5 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -938,10 +938,15 @@ static int get_options(int argc, char **argv) static int read_lines(bool execute_commands) { -#if defined( __WIN__) || defined(OS2) || defined(__NETWARE__) +#if defined(OS2) || defined(__NETWARE__) char linebuffer[254]; String buffer; #endif +#if defined(__WIN__) + String tmpbuf; + String buffer; +#endif + char *line; char in_string=0; ulong line_number=0; @@ -972,7 +977,7 @@ static int read_lines(bool execute_commands) #if defined( __WIN__) || defined(OS2) || defined(__NETWARE__) tee_fputs(prompt, stdout); -#ifdef __NETWARE__ +#if defined(__NETWARE__) line=fgets(linebuffer, sizeof(linebuffer)-1, stdin); /* Remove the '\n' */ if (line) @@ -981,7 +986,22 @@ static int read_lines(bool execute_commands) if (p != NULL) *p = '\0'; } -#else +#elif defined(__WIN__) + if (!tmpbuf.is_alloced()) + tmpbuf.alloc(65535); + buffer.length(0); + unsigned long clen; + do + { + line= my_cgets(tmpbuf.c_ptr(), tmpbuf.alloced_length(), &clen); + buffer.append(line, clen); + /* + if we got buffer fully filled than there is a chance that + something else is still in console input buffer + */ + } while (tmpbuf.alloced_length() <= clen + 1); + line= buffer.c_ptr(); +#else /* OS2 */ buffer.length(0); /* _cgets() expects the buffer size - 3 as the first byte */ linebuffer[0]= (char) sizeof(linebuffer) - 3; @@ -1057,9 +1077,14 @@ static int read_lines(bool execute_commands) status.exit_status=0; } } + #if defined( __WIN__) || defined(OS2) || defined(__NETWARE__) buffer.free(); #endif +#if defined( __WIN__) + tmpbuf.free(); +#endif + return status.exit_status; } diff --git a/include/my_sys.h b/include/my_sys.h index 9127a58d71c..02ea188a18e 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -801,6 +801,9 @@ int my_security_attr_create(SECURITY_ATTRIBUTES **psa, const char **perror, void my_security_attr_free(SECURITY_ATTRIBUTES *sa); +/* implemented in my_conio.c */ +char* my_cgets(char *string, unsigned long clen, unsigned long* plen); + #endif #ifdef __NETWARE__ void netware_reg_user(const char *ip, const char *user, diff --git a/mysys/my_conio.c b/mysys/my_conio.c new file mode 100644 index 00000000000..e381f9f23ef --- /dev/null +++ b/mysys/my_conio.c @@ -0,0 +1,217 @@ +/* Copyright (C) 2000 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#include "mysys_priv.h" + +#ifdef __WIN__ + +static HANDLE my_coninpfh= 0; /* console input */ + +/* + functions my_pthread_auto_mutex_lock & my_pthread_auto_mutex_free + are experimental at this moment, they are intended to bring + ability of protecting code sections without necessity to explicitly + initialize synchronization object in one of threads + + if found useful they are to be exported in mysys +*/ + +/* + int my_pthread_auto_mutex_lock(HANDLE* ph, const char* name, + int id, int time) + + NOTES + creates a mutex with given name and tries to lock it time msec. + mutex name is appended with id to allow system wide or process wide + locks. Handle to created mutex returned in ph argument. + + RETURN + 0 thread owns mutex + <>0 error + +*/ +static +int my_pthread_auto_mutex_lock(HANDLE* ph, const char* name, int id, int time) +{ + int res; + char tname[FN_REFLEN]; + + sprintf(tname, "%s-%08X", name, id); + + *ph= CreateMutex(NULL, FALSE, tname); + if (*ph == NULL) + return GetLastError(); + + res= WaitForSingleObject(*ph, time); + + if (res == WAIT_TIMEOUT) + return ERROR_SEM_TIMEOUT; + + if (res == WAIT_FAILED) + return GetLastError(); + + return 0; +} + +/* + int my_pthread_auto_mutex_free(HANDLE* ph) + + + NOTES + releases a mutex. + + RETURN + 0 thread released mutex + <>0 error + +*/ +static +int my_pthread_auto_mutex_free(HANDLE* ph) +{ + if (*ph) + { + ReleaseMutex(*ph); + CloseHandle(*ph); + *ph= NULL; + } + + return 0; +} + + +#define pthread_auto_mutex_decl(name) \ + HANDLE __h##name= NULL; + +#define pthread_auto_mutex_lock(name, proc, time) \ + my_pthread_auto_mutex_lock(&__h##name, #name, (proc), (time)) + +#define pthread_auto_mutex_free(name) \ + my_pthread_auto_mutex_free(&__h##name) + + +/* + char* my_cgets(char *string, unsigned long clen, unsigned long* plen) + + NOTES + Replaces _cgets from libc to support input of more than 255 chars. + Reads from the console via ReadConsole into buffer which + should be at least clen characters. + Actual length of string returned in plen. + + WARNING + my_cgets() does NOT check the pushback character buffer (i.e., _chbuf). + Thus, my_cgets() will not return any character that is pushed back by + the _ungetch() call. + + RETURN + string pointer ok + NULL Error + +*/ +char* my_cgets(char *buffer, unsigned long clen, unsigned long* plen) +{ + ULONG state; + char *result; + CONSOLE_SCREEN_BUFFER_INFO csbi; + + pthread_auto_mutex_decl(my_conio_cs); + + /* lock the console for the current process*/ + if (pthread_auto_mutex_lock(my_conio_cs, GetCurrentProcessId(), INFINITE)) + { + /* can not lock console */ + pthread_auto_mutex_free(my_conio_cs); + return NULL; + } + + /* init console input */ + if (my_coninpfh == 0) + { + /* same handle will be used until process termination */ + my_coninpfh= CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + } + + if (my_coninpfh == INVALID_HANDLE_VALUE) + { + /* unlock the console */ + pthread_auto_mutex_free(my_conio_cs); + return(NULL); + } + + GetConsoleMode((HANDLE)my_coninpfh, &state); + SetConsoleMode((HANDLE)my_coninpfh, ENABLE_LINE_INPUT | + ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT); + + GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi); + + /* + there is no known way to determine allowed buffer size for input + though it is known it should not be more than 64K + so we cut 64K and try first size of screen buffer + if it is still to large we cut half of it and try again + later we may want to cycle from min(clen, 65535) to allowed size + with small decrement to determine exact allowed buffer + */ + clen= min(clen, 65535); + do + { + clen= min(clen, (unsigned long)csbi.dwSize.X*csbi.dwSize.Y); + if (!ReadConsole((HANDLE)my_coninpfh, (LPVOID)buffer, clen - 1, plen, NULL)) + { + result= NULL; + clen>>= 1; + } + else + { + result= buffer; + break; + } + } + while (GetLastError() == ERROR_NOT_ENOUGH_MEMORY); + + + if (result != NULL) + { + if (buffer[*plen - 2] == '\r') + { + *plen= *plen - 2; + } + else + { + if (buffer[*plen - 1] == '\r') + { + char tmp[3]; + int tmplen= sizeof(tmp); + + *plen= *plen - 1; + /* read /n left in the buffer */ + ReadConsole((HANDLE)my_coninpfh, (LPVOID)tmp, tmplen, &tmplen, NULL); + } + } + buffer[*plen]= '\0'; + } + + SetConsoleMode((HANDLE)my_coninpfh, state); + /* unlock the console */ + pthread_auto_mutex_free(my_conio_cs); + + return result; +} + +#endif /* __WIN__ */ |