syslog in mysql function

I experimented with sending UDP messages from MySQL functions, but ended up with simple syslogging UDF

I played a bit with various interaction with outer world ideas in MySQL UDFs and ended up with something what was really really simple – a single libc call. I did shamelessly steal bare bones and simply added a single line of code in it:

#include <mysql.h>
#include <string.h>
#include <syslog.h>

my_bool logger_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
        initid->maybe_null=0;
        return 0;
}

long long logger(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) {
        if (args->arg_count != 1) {
                strcpy(error, "LOGGER(): needs message");
                return 1;
        }

        if (args->arg_type[0] != STRING_RESULT) {
                strcpy(error, "LOGGER() message should be string");
                return 1;
        }

        syslog(LOG_INFO,"%s",args->args[0]);
        *is_null = 0;
        *error = 0;

        return 0;
}

Of course, I had to compile it:

gcc -I /usr/include/mysql/ -shared -o syslogudf.so syslogudf.c

And later load it:

mysql> create function logger returns integer soname 'syslogudf.so';
Query OK, 0 rows affected (0.00 sec)

One more thing… testing:

mysql> select logger(concat(user()," wishes you ",
    -> if(rand()>0.3,"good","bad")," luck"));
+---------------------------------------------------------------------------+
| logger(concat(user()," wishes you ",if(rand()>0.3,"good","bad")," luck")) |
+---------------------------------------------------------------------------+
|                                                                         0 |
+---------------------------------------------------------------------------+
1 row in set (0.00 sec)

So now our systems administrator will see:

$ tail -1 /var/log/messages
Dec 12 01:09:22 flake mysqld-max: root@localhost wishes you bad luck

Oops!

2 thoughts on “syslog in mysql function”

  1. Hello!

    Pretty nice syslog plugin you got there, used it before on 32 bit Linux, unfortunately it won’t compule on a 64 bit system (CentOS 6):

    # gcc -I /usr/include/mysql/ -shared -o syslogudf.so syslogudf.c
    /usr/bin/ld: /tmp/ccb270xG.o: relocation R_X86_64_32 against `.rodata’ can not be used when making a shared object; recompile with -fPIC
    /tmp/ccb270xG.o: could not read symbols: Bad value
    collect2: ld returned exit code 1

    If I try using the “-fPIC” param, it’s even worse.

    Any suggestions? Thx in advance!

  2. SUCCESS! :)

    After lots of googling and man page reading I finally found the solution. I simply copied the 64 bit “udfexample.c” file (from mysql-devel) file and modified it for my needs.

    The following code needs to be compiled using
    # gcc -I /usr/include/mysql/ -shared -o syslogudf.so syslogudf.c -fPIC

    CODE:

    #ifdef STANDARD
    /* STANDARD is defined, don’t use any mysql functions */
    #include
    #include
    #include
    #ifdef __WIN__
    typedef unsigned __int64 ulonglong; /* Microsofts 64 bit types */
    typedef __int64 longlong;
    #else
    typedef unsigned long long ulonglong;
    typedef long long longlong;
    #endif /*__WIN__*/
    #else
    #include
    #include
    #if defined(MYSQL_SERVER)
    #include /* To get strmov() */
    #else
    /* when compiled as standalone */
    #include
    #define strmov(a,b) stpcpy(a,b)
    #define bzero(a,b) memset(a,0,b)
    #define memcpy_fixed(a,b,c) memcpy(a,b,c)
    #endif
    #endif

    #include
    #include
    #include

    #if !defined(HAVE_GETHOSTBYADDR_R) || !defined(HAVE_SOLARIS_STYLE_GETHOST)
    static pthread_mutex_t LOCK_hostname;
    #endif

    /* Logger */

    my_bool logger_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
    initid->maybe_null=0;
    return 0;
    }

    long long logger(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error) {
    if (args->arg_count != 1) {
    strcpy(error, “LOGGER(): needs message”);
    return 1;
    }

    if (args->arg_type[0] != STRING_RESULT) {
    strcpy(error, “LOGGER() message should be string”);
    return 1;
    }

    syslog(LOG_INFO,”%s”,args->args[0]);
    *is_null = 0;
    *error = 0;

    return 0;
    }

Comments are closed.