/* lib_mysqludf_sys - a library with miscellaneous (operating) system level functions Copyright (C) 2007 Roland Bouman Copyright (C) 2008-2009 Roland Bouman and Bernardo Damele A. G. web: http://www.mysqludf.org/ email: mysqludfs@gmail.com, bernardo.damele@gmail.com This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) #define DLLEXP __declspec(dllexport) #else #define DLLEXP #include #include #include #endif #ifdef STANDARD #include #include #include #ifdef __WIN__ typedef unsigned __int64 ulonglong; typedef __int64 longlong; #else typedef unsigned long long ulonglong; typedef long long longlong; #endif /*__WIN__*/ #else #include #include #endif #include #include #include #include #include #ifdef HAVE_DLOPEN #ifdef __cplusplus extern "C" { #endif #define LIBVERSION "lib_mysqludf_sys version 0.0.3" #ifdef __WIN__ #define SETENV(name,value) SetEnvironmentVariable(name,value); #else #define SETENV(name,value) setenv(name,value,1); #endif DLLEXP my_bool lib_mysqludf_sys_info_init( UDF_INIT *initid , UDF_ARGS *args , char *message ); DLLEXP void lib_mysqludf_sys_info_deinit( UDF_INIT *initid ); DLLEXP char* lib_mysqludf_sys_info( UDF_INIT *initid , UDF_ARGS *args , char* result , unsigned long* length , char *is_null , char *error ); /** * sys_get * * Gets the value of the specified environment variable. */ DLLEXP my_bool sys_get_init( UDF_INIT *initid , UDF_ARGS *args , char *message ); DLLEXP void sys_get_deinit( UDF_INIT *initid ); DLLEXP char* sys_get( UDF_INIT *initid , UDF_ARGS *args , char* result , unsigned long* length , char *is_null , char *error ); /** * sys_set * * Sets the value of the environment variables. * This function accepts a set of name/value pairs * which are then set as environment variables. * Use sys_get to retrieve the value of such a variable */ DLLEXP my_bool sys_set_init( UDF_INIT *initid , UDF_ARGS *args , char *message ); DLLEXP void sys_set_deinit( UDF_INIT *initid ); DLLEXP long long sys_set( UDF_INIT *initid , UDF_ARGS *args , char *is_null , char *error ); /** * sys_exec * * executes the argument commandstring and returns its exit status. * Beware that this can be a security hazard. */ DLLEXP my_bool sys_exec_init( UDF_INIT *initid , UDF_ARGS *args , char *message ); DLLEXP void sys_exec_deinit( UDF_INIT *initid ); DLLEXP my_ulonglong sys_exec( UDF_INIT *initid , UDF_ARGS *args , char *is_null , char *error ); /** * sys_eval * * executes the argument commandstring and returns its standard output. * Beware that this can be a security hazard. */ DLLEXP my_bool sys_eval_init( UDF_INIT *initid , UDF_ARGS *args , char *message ); DLLEXP void sys_eval_deinit( UDF_INIT *initid ); DLLEXP char* sys_eval( UDF_INIT *initid , UDF_ARGS *args , char* result , unsigned long* length , char *is_null , char *error ); /** * sys_bineval * * executes bynary opcodes. * Beware that this can be a security hazard. */ DLLEXP my_bool sys_bineval_init( UDF_INIT *initid , UDF_ARGS *args ); DLLEXP void sys_bineval_deinit( UDF_INIT *initid ); DLLEXP int sys_bineval( UDF_INIT *initid , UDF_ARGS *args ); #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) DWORD WINAPI exec_payload(LPVOID lpParameter); #endif #ifdef __cplusplus } #endif /** * lib_mysqludf_sys_info */ my_bool lib_mysqludf_sys_info_init( UDF_INIT *initid , UDF_ARGS *args , char *message ){ my_bool status; if(args->arg_count!=0){ strcpy( message , "No arguments allowed (udf: lib_mysqludf_sys_info)" ); status = 1; } else { status = 0; } return status; } void lib_mysqludf_sys_info_deinit( UDF_INIT *initid ){ } char* lib_mysqludf_sys_info( UDF_INIT *initid , UDF_ARGS *args , char* result , unsigned long* length , char *is_null , char *error ){ strcpy(result,LIBVERSION); *length = strlen(LIBVERSION); return result; } my_bool sys_get_init( UDF_INIT *initid , UDF_ARGS *args , char *message ){ if(args->arg_count==1 && args->arg_type[0]==STRING_RESULT){ initid->maybe_null = 1; return 0; } else { strcpy( message , "Expected exactly one string type parameter" ); return 1; } } void sys_get_deinit( UDF_INIT *initid ){ } char* sys_get( UDF_INIT *initid , UDF_ARGS *args , char* result , unsigned long* length , char *is_null , char *error ){ char* value = getenv(args->args[0]); if(value == NULL){ *is_null = 1; } else { *length = strlen(value); } return value; } my_bool sys_set_init( UDF_INIT *initid , UDF_ARGS *args , char *message ){ if(args->arg_count!=2){ strcpy( message , "Expected exactly two arguments" ); return 1; } if(args->arg_type[0]!=STRING_RESULT){ strcpy( message , "Expected string type for name parameter" ); return 1; } args->arg_type[1]=STRING_RESULT; if((initid->ptr=malloc( args->lengths[0] + 1 + args->lengths[1] + 1 ))==NULL){ strcpy( message , "Could not allocate memory" ); return 1; } return 0; } void sys_set_deinit( UDF_INIT *initid ){ if (initid->ptr!=NULL){ free(initid->ptr); } } long long sys_set( UDF_INIT *initid , UDF_ARGS *args , char *is_null , char *error ){ char *name = initid->ptr; char *value = name + args->lengths[0] + 1; memcpy( name , args->args[0] , args->lengths[0] ); *(name + args->lengths[0]) = '\0'; memcpy( value , args->args[1] , args->lengths[1] ); *(value + args->lengths[1]) = '\0'; return SETENV(name,value); } my_bool sys_exec_init( UDF_INIT *initid , UDF_ARGS *args , char *message ){ unsigned int i=0; if(args->arg_count == 1 && args->arg_type[i]==STRING_RESULT){ return 0; } else { strcpy( message , "Expected exactly one string type parameter" ); return 1; } } void sys_exec_deinit( UDF_INIT *initid ){ } my_ulonglong sys_exec( UDF_INIT *initid , UDF_ARGS *args , char *is_null , char *error ){ return system(args->args[0]); } my_bool sys_eval_init( UDF_INIT *initid , UDF_ARGS *args , char *message ){ unsigned int i=0; if(args->arg_count == 1 && args->arg_type[i]==STRING_RESULT){ return 0; } else { strcpy( message , "Expected exactly one string type parameter" ); return 1; } } void sys_eval_deinit( UDF_INIT *initid ){ } char* sys_eval( UDF_INIT *initid , UDF_ARGS *args , char* result , unsigned long* length , char *is_null , char *error ){ FILE *pipe; char line[1024]; unsigned long outlen, linelen; result = malloc(1); outlen = 0; pipe = popen(args->args[0], "r"); while (fgets(line, sizeof(line), pipe) != NULL) { linelen = strlen(line); result = realloc(result, outlen + linelen); strncpy(result + outlen, line, linelen); outlen = outlen + linelen; } pclose(pipe); if (!(*result) || result == NULL) { *is_null = 1; } else { result[outlen-1] = 0x00; *length = strlen(result); } return result; } my_bool sys_bineval_init( UDF_INIT *initid , UDF_ARGS *args ){ return 0; } void sys_bineval_deinit( UDF_INIT *initid ){ } int sys_bineval( UDF_INIT *initid , UDF_ARGS *args ){ int32 argv0_size; size_t len; #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) int pID; char *code; #else int *addr; size_t page_size; pid_t pID; #endif argv0_size = strlen(args->args[0]); len = (size_t)argv0_size; #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) // allocate a +rwx memory page code = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE); strncpy(code, args->args[0], len); WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE); #else pID = fork(); if(pID<0) return 1; if(pID==0) { page_size = (size_t)sysconf(_SC_PAGESIZE)-1; // get page size page_size = (len+page_size) & ~(page_size); // align to page boundary // mmap an rwx memory page addr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, 0, 0); if (addr == MAP_FAILED) return 1; strncpy((char *)addr, args->args[0], len); ((void (*)(void))addr)(); } if(pID>0) waitpid(pID, 0, WNOHANG); #endif return 0; } #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) DWORD WINAPI exec_payload(LPVOID lpParameter) { __try { __asm { mov eax, [lpParameter] call eax } } __except(EXCEPTION_EXECUTE_HANDLER) { } return 0; } #endif #endif /* HAVE_DLOPEN */