From 161590e121c279b264b48592f6ebc5889ab0213e Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Sat, 17 Jan 2009 00:13:16 +0000 Subject: [PATCH] Added MySQL UDF to execute commands on the underlying system: * sys_eval() to return the standard output * sys_exec() to return the exit status It's a patched version of http://mysqludf.org/lib_mysqludf_sys/index.php --- extra/mysqludfsys/lib_mysqludf_sys/Makefile | 4 + extra/mysqludfsys/lib_mysqludf_sys/install.sh | 25 + .../lib_mysqludf_sys/lib_mysqludf_sys.c | 426 ++++++++++++++++++ .../lib_mysqludf_sys/lib_mysqludf_sys.html | 208 +++++++++ .../lib_mysqludf_sys/lib_mysqludf_sys.so | Bin 0 -> 12896 bytes .../lib_mysqludf_sys/lib_mysqludf_sys.sql | 33 ++ .../mysqludfsys/lib_mysqludf_sys_0.0.3.patch | 213 +++++++++ .../mysqludfsys/lib_mysqludf_sys_0.0.3.tar.gz | Bin 0 -> 8439 bytes 8 files changed, 909 insertions(+) create mode 100644 extra/mysqludfsys/lib_mysqludf_sys/Makefile create mode 100755 extra/mysqludfsys/lib_mysqludf_sys/install.sh create mode 100644 extra/mysqludfsys/lib_mysqludf_sys/lib_mysqludf_sys.c create mode 100644 extra/mysqludfsys/lib_mysqludf_sys/lib_mysqludf_sys.html create mode 100755 extra/mysqludfsys/lib_mysqludf_sys/lib_mysqludf_sys.so create mode 100644 extra/mysqludfsys/lib_mysqludf_sys/lib_mysqludf_sys.sql create mode 100644 extra/mysqludfsys/lib_mysqludf_sys_0.0.3.patch create mode 100644 extra/mysqludfsys/lib_mysqludf_sys_0.0.3.tar.gz diff --git a/extra/mysqludfsys/lib_mysqludf_sys/Makefile b/extra/mysqludfsys/lib_mysqludf_sys/Makefile new file mode 100644 index 000000000..dbeb72923 --- /dev/null +++ b/extra/mysqludfsys/lib_mysqludf_sys/Makefile @@ -0,0 +1,4 @@ +LIBDIR=/usr/lib + +install: + gcc -Wall -I/usr/include/mysql -I. -shared lib_mysqludf_sys.c -o $(LIBDIR)/lib_mysqludf_sys.so diff --git a/extra/mysqludfsys/lib_mysqludf_sys/install.sh b/extra/mysqludfsys/lib_mysqludf_sys/install.sh new file mode 100755 index 000000000..401bd68d6 --- /dev/null +++ b/extra/mysqludfsys/lib_mysqludf_sys/install.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +echo "Compiling the MySQL UDF" +make + +if test $? -ne 0; then + echo "ERROR: You need libmysqlclient development software installed " + echo "to be able to compile this UDF, on Debian/Ubuntu just run:" + echo "apt-get install libmysqlclient15-dev" + exit 1 +else + echo "MySQL UDF compiled successfully" +fi + +echo -e "\nPlease provide your MySQL root password and press RETURN: \c" +read PASSWORD + +mysql -u root --password=$PASSWORD mysql < lib_mysqludf_sys.sql + +if test $? -ne 0; then + echo "ERROR: unable to install the UDF" + exit 1 +else + echo "MySQL UDF installed successfully" +fi diff --git a/extra/mysqludfsys/lib_mysqludf_sys/lib_mysqludf_sys.c b/extra/mysqludfsys/lib_mysqludf_sys/lib_mysqludf_sys.c new file mode 100644 index 000000000..8d1adfd1c --- /dev/null +++ b/extra/mysqludfsys/lib_mysqludf_sys/lib_mysqludf_sys.c @@ -0,0 +1,426 @@ +/* + 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 +#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 +); + + +#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] = 0x00; + *length = strlen(result); + } + + return result; +} + + +#endif /* HAVE_DLOPEN */ diff --git a/extra/mysqludfsys/lib_mysqludf_sys/lib_mysqludf_sys.html b/extra/mysqludfsys/lib_mysqludf_sys/lib_mysqludf_sys.html new file mode 100644 index 000000000..2997df399 --- /dev/null +++ b/extra/mysqludfsys/lib_mysqludf_sys/lib_mysqludf_sys.html @@ -0,0 +1,208 @@ + + + + + + +lib_mysqludf_sys - A library of MySQL UDFs for working with the environment in which MySQL runs + + +
+ Top + | Up +
+

lib_mysqludf_sys

+ +

+ This library lib_mysqludf_sys contains a number of functions that allows one to interact with the operating system. +

+
    +
  1. sys_exec - executes an arbitrary command, and can thus be used to launch an external application.
  2. +
  3. sys_get - gets the value of an environment variable.
  4. +
  5. sys_set - create an environment variable, or update the value of an existing environment variable.
  6. +
+

+ Use lib_mysqludf_sys_info() to obtain information about the currently installed version of lib_mysqludf_sys. +

+ +

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. +

+

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. +

+ +&FDr1>2#N@=@C|^s(7}*(}}crn_%x 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 G>G+?2GmVY_ literal 0 HcmV?d00001 diff --git a/extra/mysqludfsys/lib_mysqludf_sys/lib_mysqludf_sys.sql b/extra/mysqludfsys/lib_mysqludf_sys/lib_mysqludf_sys.sql new file mode 100644 index 000000000..7abb3d012 --- /dev/null +++ b/extra/mysqludfsys/lib_mysqludf_sys/lib_mysqludf_sys.sql @@ -0,0 +1,33 @@ +/* + 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 +*/ + +DROP FUNCTION IF EXISTS lib_mysqludf_sys_info; +DROP FUNCTION IF EXISTS sys_get; +DROP FUNCTION IF EXISTS sys_set; +DROP FUNCTION IF EXISTS sys_exec; +DROP FUNCTION IF EXISTS sys_eval; + +CREATE FUNCTION lib_mysqludf_sys_info RETURNS string SONAME 'lib_mysqludf_sys.so'; +CREATE FUNCTION sys_get RETURNS string SONAME 'lib_mysqludf_sys.so'; +CREATE FUNCTION sys_set RETURNS int SONAME 'lib_mysqludf_sys.so'; +CREATE FUNCTION sys_exec RETURNS int SONAME 'lib_mysqludf_sys.so'; +CREATE FUNCTION sys_eval RETURNS string SONAME 'lib_mysqludf_sys.so'; diff --git a/extra/mysqludfsys/lib_mysqludf_sys_0.0.3.patch b/extra/mysqludfsys/lib_mysqludf_sys_0.0.3.patch new file mode 100644 index 000000000..8d2a4a41f --- /dev/null +++ b/extra/mysqludfsys/lib_mysqludf_sys_0.0.3.patch @@ -0,0 +1,213 @@ +diff -uN lib_mysqludf_sys/install.sh lib_mysqludf_sys_0.0.3/install.sh +--- lib_mysqludf_sys/install.sh 1970-01-01 01:00:00.000000000 +0100 ++++ lib_mysqludf_sys_0.0.3/install.sh 2009-01-15 16:04:50.000000000 +0000 +@@ -0,0 +1,25 @@ ++#!/bin/bash ++ ++echo "Compiling the MySQL UDF" ++make ++ ++if test $? -ne 0; then ++ echo "ERROR: You need libmysqlclient development software installed " ++ echo "to be able to compile this UDF, on Debian/Ubuntu just run:" ++ echo "apt-get install libmysqlclient15-dev" ++ exit 1 ++else ++ echo "MySQL UDF compiled successfully" ++fi ++ ++echo -e "\nPlease provide your MySQL root password and press RETURN: \c" ++read PASSWORD ++ ++mysql -u root --password=$PASSWORD mysql < lib_mysqludf_sys.sql ++ ++if test $? -ne 0; then ++ echo "ERROR: unable to install the UDF" ++ exit 1 ++else ++ echo "MySQL UDF installed successfully" ++fi +Binary files lib_mysqludf_sys/lib_mysqludf_sys_0.0.2.tar.gz and lib_mysqludf_sys_0.0.3/lib_mysqludf_sys_0.0.2.tar.gz differ +diff -uN lib_mysqludf_sys/lib_mysqludf_sys.c lib_mysqludf_sys_0.0.3/lib_mysqludf_sys.c +--- lib_mysqludf_sys/lib_mysqludf_sys.c 2007-08-05 13:46:43.000000000 +0100 ++++ lib_mysqludf_sys_0.0.3/lib_mysqludf_sys.c 2009-01-15 15:55:33.000000000 +0000 +@@ -1,8 +1,9 @@ + /* + lib_mysqludf_sys - a library with miscellaneous (operating) system level functions + Copyright (C) 2007 Roland Bouman +- web: http://www.xcdsql.org/MySQL/UDF/ +- email: mysqludfs@gmail.com ++ 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 +@@ -51,7 +52,7 @@ + extern "C" { + #endif + +-#define LIBVERSION "lib_mysqludf_sys version 0.0.2" ++#define LIBVERSION "lib_mysqludf_sys version 0.0.3" + + #ifdef __WIN__ + #define SETENV(name,value) SetEnvironmentVariable(name,value); +@@ -139,7 +140,7 @@ + /** + * sys_exec + * +- * executes the argument commandstring. ++ * executes the argument commandstring and returns its exit status. + * Beware that this can be a security hazard. + */ + DLLEXP +@@ -162,6 +163,34 @@ + , 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 ++); ++ + + #ifdef __cplusplus + } +@@ -336,5 +365,62 @@ + 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] = 0x00; ++ *length = strlen(result); ++ } ++ ++ return result; ++} ++ + + #endif /* HAVE_DLOPEN */ +Binary files lib_mysqludf_sys/lib_mysqludf_sys.so and lib_mysqludf_sys_0.0.3/lib_mysqludf_sys.so differ +diff -uN lib_mysqludf_sys/lib_mysqludf_sys.sql lib_mysqludf_sys_0.0.3/lib_mysqludf_sys.sql +--- lib_mysqludf_sys/lib_mysqludf_sys.sql 2007-06-02 20:42:53.000000000 +0100 ++++ lib_mysqludf_sys_0.0.3/lib_mysqludf_sys.sql 2009-01-15 15:57:34.000000000 +0000 +@@ -1,8 +1,9 @@ + /* + lib_mysqludf_sys - a library with miscellaneous (operating) system level functions + Copyright (C) 2007 Roland Bouman +- web: http://www.xcdsql.org/MySQL/UDF/ +- email: mysqludfs@gmail.com ++ 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 +@@ -19,12 +20,14 @@ + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +-drop function lib_mysqludf_sys_info; +-drop function sys_get; +-drop function sys_set; +-drop function sys_exec; ++DROP FUNCTION IF EXISTS lib_mysqludf_sys_info; ++DROP FUNCTION IF EXISTS sys_get; ++DROP FUNCTION IF EXISTS sys_set; ++DROP FUNCTION IF EXISTS sys_exec; ++DROP FUNCTION IF EXISTS sys_eval; + +-create function lib_mysqludf_sys_info returns string soname 'lib_mysqludf_sys.so'; +-create function sys_get returns string soname 'lib_mysqludf_sys.so'; +-create function sys_set returns int soname 'lib_mysqludf_sys.so'; +-create function sys_exec returns int soname 'lib_mysqludf_sys.so'; ++CREATE FUNCTION lib_mysqludf_sys_info RETURNS string SONAME 'lib_mysqludf_sys.so'; ++CREATE FUNCTION sys_get RETURNS string SONAME 'lib_mysqludf_sys.so'; ++CREATE FUNCTION sys_set RETURNS int SONAME 'lib_mysqludf_sys.so'; ++CREATE FUNCTION sys_exec RETURNS int SONAME 'lib_mysqludf_sys.so'; ++CREATE FUNCTION sys_eval RETURNS string SONAME 'lib_mysqludf_sys.so'; +diff -uN lib_mysqludf_sys/Makefile lib_mysqludf_sys_0.0.3/Makefile +--- lib_mysqludf_sys/Makefile 2007-08-05 12:54:53.000000000 +0100 ++++ lib_mysqludf_sys_0.0.3/Makefile 2009-01-15 15:52:48.000000000 +0000 +@@ -1,6 +1,4 @@ +-linux: \ +- lib_mysqludf_sys.so ++LIBDIR=/usr/lib + +-lib_mysqludf_sys.so: \ +- +- gcc -Wall -I/opt/mysql/mysql/include -I. -shared lib_mysqludf_sys.c -o lib_mysqludf_sys.so ++install: ++ gcc -Wall -I/usr/include/mysql -I. -shared lib_mysqludf_sys.c -o $(LIBDIR)/lib_mysqludf_sys.so diff --git a/extra/mysqludfsys/lib_mysqludf_sys_0.0.3.tar.gz b/extra/mysqludfsys/lib_mysqludf_sys_0.0.3.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..9c704ced7b5b7b5446853f2851baeea191250afc GIT binary patch literal 8439 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 ZvXrGPWhqNp%JS2d{{i@G^Kby5003gHviAT0 literal 0 HcmV?d00001