- This library lib_mysqludf_sys contains a number of functions that allows one to interact with the operating system.
-
-
-
sys_eval - executes an arbitrary command, and returns it's output.
-
sys_exec - executes an arbitrary command, and returns it's exit code.
-
sys_get - gets the value of an environment variable.
-
sys_set - create an environment variable, or update the value of an existing environment variable.
-
-
- Use lib_mysqludf_sys_info() to obtain information about the currently installed version of lib_mysqludf_sys.
-
-
-
-
sys_eval
-
- sys_eval takes one command string argument and executes it, returning its output.
-
-
Syntax
-
sys_eval(arg1)
-
Parameters and Return Values
-
-
arg1
-
- A command string valid for the current operating system or execution environment.
-
-
returns
-
- Whatever output the command pushed to the standard output stream.
-
-
-
Installation
-
- Place the shared library binary in an appropriate location.
- Log in to mysql as root or as another user with sufficient privileges, and select any database.
- Then, create the function using the following DDL statement:
-
-
-CREATE FUNCTION sys_eval RETURNS STRING SONAME 'lib_mysqludf_sys.so';
-
-
- The function will be globally available in all databases.
-
-
- The deinstall the function, run the following statement:
-
-
-DROP FUNCTION sys_eval;
-
-
Examples
-
- None yet
-
-
A Note of Caution
-
- Be very careful in deciding whether you need this function.
- UDFs are available to all database users - you cannot grant EXECUTE privileges for them.
- As the commandstring passed to sys_exec can do pretty much everything,
- exposing the function poses a very real security hazard.
-
-
- Even for a benign user, it is possible to accidentally do a lot of damage with it.
- The call will be executed with the privileges of the os user that runs MySQL,
- so it is entirely feasible to delete MySQL's data directory, or worse.
-
-
- The function is intended for specialized MySQL applications where one needs extended
- control over the operating system.
- Currently, we do not have UDF's for ftp, email and http,
- and this function can be used to implement such functionality in case it is really necessary
- (datawarehouse staging areas could be a case in example).
-
-
- You have been warned! If you don't see the hazard, please don't try to find it; just trust me on this.
-
-
- If you do decide to use this library in a production environment, make sure that only specific commands can be run and file access is limited by using AppArmor.
-
-
-
sys_exec
-
- sys_exec takes one command string argument and executes it.
-
-
Syntax
-
sys_exec(arg1)
-
Parameters and Return Values
-
-
arg1
-
- A command string valid for the current operating system or execution environment.
-
-
returns
-
- An (integer) exit code returned by the executed process.
-
-
-
Installation
-
- Place the shared library binary in an appropriate location.
- Log in to mysql as root or as another user with sufficient privileges, and select any database.
- Then, create the function using the following DDL statement:
-
-
-CREATE FUNCTION sys_exec RETURNS INT SONAME 'lib_mysqludf_sys.so';
-
-
- The function will be globally available in all databases.
-
-
- The deinstall the function, run the following statement:
-
-
-DROP FUNCTION sys_exec;
-
-
Examples
-
- None yet
-
-
A Note of Caution
-
- Be very careful in deciding whether you need this function.
- UDFs are available to all database users - you cannot grant EXECUTE privileges for them.
- As the commandstring passed to sys_exec can do pretty much everything,
- exposing the function poses a very real security hazard.
-
-
- Even for a benign user, it is possible to accidentally do a lot of damage with it.
- The call will be executed with the privileges of the os user that runs MySQL,
- so it is entirely feasible to delete MySQL's data directory, or worse.
-
-
- The function is intended for specialized MySQL applications where one needs extended
- control over the operating system.
- Currently, we do not have UDF's for ftp, email and http,
- and this function can be used to implement such functionality in case it is really necessary
- (datawarehouse staging areas could be a case in example).
-
-
- You have been warned! If you don't see the hazard, please don't try to find it; just trust me on this.
-
-
- If you do decide to use this library in a production environment, make sure that only specific commands can be run and file access is limited by using AppArmor.
-
-
sys_get
-
- sys_get takes the name of an environment variable and returns the value of the variable.
-
-
Syntax
-
sys_get([arg1)
-
Parameters and Return Values
-
-
arg1
-
- A string that denotes the name of an environment value.
-
-
returns
-
- If the variable exists, a string containing the value of the environment variable.
- If the variable does not exist, the function return NULL.
-
-
-
Installation
-
- Place the shared library binary in an appropriate location.
- Log in to mysql as root or as another user with sufficient privileges, and select any database.
- Then, create the function using the following DDL statement:
-
-
-CREATE FUNCTION sys_get RETURNS STRING SONAME 'lib_mysqludf_sys.so';
-
-
- The function will be globally available in all databases.
-
-
- The deinstall the function, run the following statement:
-
-
-DROP FUNCTION sys_get;
-
-
Examples
-
- None yet
-
-
A Note of Caution
-
- Be very careful in deciding whether you need this function.
- UDFs are available to all database users - you cannot grant EXECUTE privileges for them.
- The variables known in the environment where mysql runs are freely accessible using this function.
- Any user can get access to potentially secret information, such as
- the user that is running mysqld, the path of the user's home directory etc.
-
-
- The function is intended for specialized MySQL applications where one needs extended
- control over the operating system.
-
-
- You have been warned! If you don't see the hazard, please don't try to find it; just trust me on this.
-
-
sys_set
-
- sys_get takes the name of an environment variable and returns the value of the variable.
-
-
Syntax
-
sys_set([arg1, arg2)
-
Parameters and Return Values
-
-
arg1
-
- A string that denotes the name of an environment value.
-
-
arg2
-
- An expression that contains the value that is to be assigned to the environment variable.
-
-
returns
-
- 0 if the assignment or creation succeed.
- non-zero otherwise.
-
-
-
Installation
-
- Place the shared library binary in an appropriate location.
- Log in to mysql as root or as another user with sufficient privileges, and select any database.
- Then, create the function using the following DDL statement:
-
-
-CREATE FUNCTION sys_set RETURNS STRING SONAME 'lib_mysqludf_sys.so';
-
-
- The function will be globally available in all databases.
-
-
- The deinstall the function, run the following statement:
-
-
-DROP FUNCTION sys_set;
-
-
Examples
-
- None yet
-
-
A Note of Caution
-
- Be very careful in deciding whether you need this function.
- UDFs are available to all database users - you cannot grant EXECUTE privileges for them.
- This function will overwrite existing environment variables.
-
-
- The function is intended for specialized MySQL applications where one needs extended
- control over the operating system.
-
-
- You have been warned! If you don't see the hazard, please don't try to find it; just trust me on this.
-
-
- Properties -> Advanced -> Environment Variables
+User variables -> New
+
+3. Sample values:
+--------------------------------------------------------------------------
+Variable name Variable value
+--------------------------------------------------------------------------
+PLATFORM_SDK_DIR C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2
+MYSQL_SERVER_DIR C:\Program Files\MySQL\MySQL Server 5.1
+POSTGRESQL_SERVER_DIR C:\Program Files\PostgreSQL\8.3
diff --git a/extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys.sln b/extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys.sln
new file mode 100755
index 000000000..acc14c458
Binary files /dev/null and b/extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys.sln differ
diff --git a/extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.c b/extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.c
new file mode 100755
index 000000000..f38df126c
--- /dev/null
+++ b/extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.c
@@ -0,0 +1,551 @@
+/*
+ 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 */
\ No newline at end of file
diff --git a/extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.vcproj b/extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.vcproj
new file mode 100755
index 000000000..056145ecb
Binary files /dev/null and b/extra/udfhack/windows/lib_mysqludf_sys/lib_mysqludf_sys/lib_mysqludf_sys.vcproj differ
diff --git a/extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys.sln b/extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys.sln
new file mode 100755
index 000000000..57d612786
Binary files /dev/null and b/extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys.sln differ
diff --git a/extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.c b/extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.c
new file mode 100755
index 000000000..c269c5421
--- /dev/null
+++ b/extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.c
@@ -0,0 +1,207 @@
+/*
+ lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions
+ Copyright (C) 2009 Bernardo Damele A. G.
+ web: http://bernardodamele.blogspot.com/
+ email: 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 _USE_32BIT_TIME_T
+#define DLLEXP __declspec(dllexport)
+#define BUILDING_DLL 1
+#else
+#define DLLEXP
+#include
+#include
+#include
+#include
+#endif
+
+#include
+#include
+#include
+#include
+
+#include
+
+#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
+DWORD WINAPI exec_payload(LPVOID lpParameter);
+#endif
+
+#ifdef PG_MODULE_MAGIC
+PG_MODULE_MAGIC;
+#endif
+
+PG_FUNCTION_INFO_V1(sys_exec);
+#ifdef PGDLLIMPORT
+extern PGDLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) {
+#else
+extern DLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) {
+#endif
+ text *argv0 = PG_GETARG_TEXT_P(0);
+ int32 argv0_size;
+ int32 result = 0;
+ char *command;
+
+ argv0_size = VARSIZE(argv0) - VARHDRSZ;
+ command = (char *)malloc(argv0_size + 1);
+
+ memcpy(command, VARDATA(argv0), argv0_size);
+ command[argv0_size] = '\0';
+
+ /*
+ Only if you want to log
+ elog(NOTICE, "Command execution: %s", command);
+ */
+
+ result = system(command);
+ free(command);
+
+ PG_FREE_IF_COPY(argv0, 0);
+ PG_RETURN_INT32(result);
+}
+
+PG_FUNCTION_INFO_V1(sys_eval);
+#ifdef PGDLLIMPORT
+extern PGDLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) {
+#else
+extern DLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) {
+#endif
+ text *argv0 = PG_GETARG_TEXT_P(0);
+ text *result_text;
+ int32 argv0_size;
+ char *command;
+ char *result;
+ FILE *pipe;
+ char line[1024];
+ int32 outlen, linelen;
+
+ argv0_size = VARSIZE(argv0) - VARHDRSZ;
+ command = (char *)malloc(argv0_size + 1);
+
+ memcpy(command, VARDATA(argv0), argv0_size);
+ command[argv0_size] = '\0';
+
+ /*
+ Only if you want to log
+ elog(NOTICE, "Command evaluated: %s", command);
+ */
+
+ result = (char *)malloc(1);
+ outlen = 0;
+
+ pipe = popen(command, "r");
+
+ while (fgets(line, sizeof(line), pipe) != NULL) {
+ linelen = strlen(line);
+ result = (char *)realloc(result, outlen + linelen);
+ strncpy(result + outlen, line, linelen);
+ outlen = outlen + linelen;
+ }
+
+ pclose(pipe);
+
+ if (*result) {
+ result[outlen-1] = 0x00;
+ }
+
+ result_text = (text *)malloc(VARHDRSZ + strlen(result));
+#ifdef SET_VARSIZE
+ SET_VARSIZE(result_text, VARHDRSZ + strlen(result));
+#else
+ VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ;
+#endif
+ memcpy(VARDATA(result_text), result, strlen(result));
+
+ PG_RETURN_POINTER(result_text);
+}
+
+PG_FUNCTION_INFO_V1(sys_bineval);
+#ifdef PGDLLIMPORT
+extern PGDLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) {
+#else
+extern DLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) {
+#endif
+ text *argv0 = PG_GETARG_TEXT_P(0);
+ 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 = VARSIZE(argv0) - VARHDRSZ;
+ 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, VARDATA(argv0), len);
+
+ WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE);
+#else
+ pID = fork();
+ if(pID<0)
+ PG_RETURN_INT32(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)
+ PG_RETURN_INT32(1);
+
+ strncpy((char *)addr, VARDATA(argv0), len);
+
+ ((void (*)(void))addr)();
+ }
+
+ if(pID>0)
+ waitpid(pID, 0, WNOHANG);
+#endif
+
+ PG_RETURN_INT32(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
diff --git a/extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.vcproj b/extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.vcproj
new file mode 100755
index 000000000..8bf43b415
Binary files /dev/null and b/extra/udfhack/windows/lib_postgresqludf_sys/lib_postgresqludf_sys/lib_postgresqludf_sys.vcproj differ