summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndreas Baumann <abaumann@yahoo.com>2008-09-27 17:52:05 +0000
committerAndreas Baumann <abaumann@yahoo.com>2008-09-27 17:52:05 +0000
commit6b1b9863d8fccfe09c2f72c68e1ebfeea54efbe8 (patch)
tree0c4e761c5b5aad7010c210a4519a2a72760af55d /src
parenteedc9cd68aef078e4584e43d8055d70e1fa07351 (diff)
downloadnagios-plugin-curl-6b1b9863d8fccfe09c2f72c68e1ebfeea54efbe8.tar.gz
nagios-plugin-curl-6b1b9863d8fccfe09c2f72c68e1ebfeea54efbe8.tar.bz2
- added first runnig version
Diffstat (limited to 'src')
-rw-r--r--src/GNUmakefile38
-rw-r--r--src/check_curl.c274
-rw-r--r--src/check_curl.ggo90
-rw-r--r--src/common.h31
-rw-r--r--src/curlhelper.c120
-rw-r--r--src/curlhelper.h50
-rw-r--r--src/port/sys.h119
-rw-r--r--src/port/unused.h8
8 files changed, 730 insertions, 0 deletions
diff --git a/src/GNUmakefile b/src/GNUmakefile
new file mode 100644
index 0000000..f28d8b4
--- /dev/null
+++ b/src/GNUmakefile
@@ -0,0 +1,38 @@
+TOPDIR = ..
+
+SUBDIRS =
+
+INCLUDE_DIRS = \
+ -I. `curl-config --cflags`
+
+LDFLAGS_DIR =
+
+LIBS_DIR = \
+ `curl-config --libs`
+
+BINS = \
+ check_curl
+
+OBJS = \
+ curlhelper.o \
+ cmdline.o
+
+-include $(TOPDIR)/makefiles/sub.mk
+
+# ABa: currently a special rule for cmdline.c as gengetopt is not
+# completly fixed yet
+check_curl.d : cmdline.h
+cmdline.c : check_curl.ggo
+ gengetopt --unamed-opts --include-getopt --conf-parser -i $<
+
+cmdline.o : cmdline.c cmdline.h
+ $(CC) -c -o $@ $<
+
+local_all: cmdline.h
+
+local_clean:
+
+local_distclean:
+ -@rm cmdline.c cmdline.h
+
+local_test:
diff --git a/src/check_curl.c b/src/check_curl.c
new file mode 100644
index 0000000..556cd92
--- /dev/null
+++ b/src/check_curl.c
@@ -0,0 +1,274 @@
+/*
+ check_curl - Nagios Curl-based check plugin
+ Copyright (C) 2008 Andreas Baumann
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <curl/curl.h>
+#include <curl/types.h>
+#include <curl/easy.h>
+
+#include "cmdline.h"
+
+#include "common.h"
+#include "curlhelper.h"
+
+#define DEFAULT_TIMEOUT (double)10.0
+
+int main( int argc, char *argv[] ) {
+ struct gengetopt_args_info args_info;
+ curlhelp_curlbuf body_buf;
+ curlhelp_curlbuf header_buf;
+ CURL *curl;
+ char b[2048];
+ CURLcode res;
+ char errbuf[CURL_ERROR_SIZE+1];
+ struct curl_slist *header_list = NULL;
+ long code;
+ double total_time;
+ const char *level_str = "OK";
+ int exit_state = STATE_OK;
+ char perfstring[1024];
+ curlhelp_statusline status_line;
+
+ cmdline_parser_init( &args_info );
+
+ /* read command line arguments (to get the name of the configuration file,
+ * do it without checking for required arguments
+ */
+ if( cmdline_parser2( argc, argv, &args_info, 0, 0, 0 ) != 0 ) {
+ printf( "HTTP CRITICAL - unable to parse arguments\n" );
+ fprintf( stderr, "\n%s\n", gengetopt_args_info_usage );
+ cmdline_parser_free( &args_info );
+ exit( STATE_UNKNOWN );
+ }
+
+ if( args_info.config_file_given ) {
+ /* read command line options from file, allow override of configuration
+ * options from the command line and check for required options
+ */
+ if( cmdline_parser_configfile( args_info.config_file_arg, &args_info, 1, 0, 1 ) != 0 ) {
+ printf( "HTTP CRITICAL - unable to read '%s'\n", args_info.config_file_arg );
+ fprintf( stderr, "\n%s\n", gengetopt_args_info_usage );
+ cmdline_parser_free( &args_info );
+ exit( STATE_UNKNOWN );
+ }
+ } else {
+ /* read command line options again, this time checking for required options */
+ if( cmdline_parser2( argc, argv, &args_info, 1, 0, 1 ) != 0 ) {
+ printf( "HTTP CRITICAL - illegal arguments, check help page\n" );
+ fprintf( stderr, "\n%s\n", gengetopt_args_info_usage );
+ cmdline_parser_free( &args_info );
+ exit( STATE_UNKNOWN );
+ }
+ }
+
+ /* start up curl */
+ if( curl_global_init( CURL_GLOBAL_ALL ) != CURLE_OK ) {
+ printf( "HTTP CRITICAL - curl_global_init failed!\n" );
+ cmdline_parser_free( &args_info );
+ exit( STATE_UNKNOWN );
+ }
+ if( ( curl = curl_easy_init( ) ) == NULL ) {
+ printf( "HTTP CRITICAL - curl_easy_init failed!\n" );
+ cmdline_parser_free( &args_info );
+ curl_global_cleanup( );
+ exit( STATE_UNKNOWN );
+ }
+
+ /* -v: verbosity */
+ curl_easy_setopt( curl, CURLOPT_VERBOSE, args_info.verbose_given );
+
+ /* initialize buffer for body of the answer */
+ if( curlhelp_initbuffer( &body_buf ) < 0 ) {
+ printf( "HTTP CRITICAL - out of memory allocating a buffer\n" );
+ cmdline_parser_free( &args_info );
+ curl_global_cleanup( );
+ exit( STATE_UNKNOWN );
+ }
+ curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, curlhelp_buffer_callback );
+ curl_easy_setopt( curl, CURLOPT_WRITEDATA, (void *)&body_buf );
+
+ /* initialize buffer for header of the answer */
+ if( curlhelp_initbuffer( &header_buf ) < 0 ) {
+ printf( "HTTP CRITICAL - out of memory allocating a buffer\n" );
+ curlhelp_freebuffer( &body_buf );
+ cmdline_parser_free( &args_info );
+ curl_global_cleanup( );
+ exit( STATE_UNKNOWN );
+ }
+ curl_easy_setopt( curl, CURLOPT_HEADERFUNCTION, curlhelp_buffer_callback );
+ curl_easy_setopt( curl, CURLOPT_WRITEHEADER , (void *)&header_buf );
+
+ /* authentication */
+ if( args_info.authorization_given )
+ curl_easy_setopt( curl, CURLOPT_USERPWD, args_info.authorization_arg );
+
+ /* compose URL */
+ snprintf( b, 2048, "http%s://%s%s",
+ args_info.ssl_given ? "s" : "",
+ args_info.ip_arg,
+ args_info.url_given ? args_info.url_arg : "/" );
+ curl_easy_setopt( curl, CURLOPT_URL, b );
+
+ /* set port */
+ if( args_info.port_given )
+ curl_easy_setopt( curl, CURLOPT_PORT, args_info.port_arg );
+
+ /* compose HTTP headers */
+#if 0 /* FIXME: doesn't work with curl 7.15.2 (Centos 5.2)!! Check out why */
+ if( args_info.host_given ) {
+ snprintf( b, 2048, "Host: %s", args_info.host_arg );
+ header_list = curl_slist_append( header_list, b );
+ }
+ curl_easy_setopt( curl, CURLOPT_HTTPHEADER, header_list );
+#endif
+
+ /* set the error buffer */
+ curl_easy_setopt( curl, CURLOPT_ERRORBUFFER, errbuf );
+
+ /* set timeouts */
+ {
+ long timeout;
+
+ if( args_info.timeout_given )
+ timeout = args_info.timeout_arg;
+ else
+ timeout = DEFAULT_TIMEOUT;
+
+ curl_easy_setopt( curl, CURLOPT_CONNECTTIMEOUT, timeout );
+ curl_easy_setopt( curl, CURLOPT_TIMEOUT, timeout );
+ }
+
+ /* do the request */
+ res = curl_easy_perform( curl );
+
+ /* terminate buffer, print it if verbose */
+ if( args_info.verbose_given ) {
+ puts( "--- HEADER ---" );
+ puts( header_buf.buf );
+ }
+ if( args_info.verbose_given ) {
+ puts( "--- BODY ---" );
+ puts( body_buf.buf );
+ }
+
+ /* free header list, we don't need it anymore */
+ curl_slist_free_all( header_list );
+
+ /* Curl errors, result in critical Nagios state */
+ if( res != CURLE_OK ) {
+ printf( "HTTP CRITICAL - %s (error: %d)\n", errbuf, res );
+ curlhelp_freebuffer( &body_buf );
+ curlhelp_freebuffer( &header_buf );
+ curl_easy_cleanup( curl );
+ curl_global_cleanup( );
+ exit( STATE_CRITICAL );
+ }
+
+ /* we got the data and we executed the request in a given time, so we can append
+ * performance data to the answer always
+ */
+ curl_easy_getinfo( curl, CURLINFO_TOTAL_TIME, &total_time );
+ snprintf( perfstring, 1024, "time=%.6gs;%.6g;%.6g;%.6g size=%dB;;;0",
+ total_time,
+ args_info.warning_given ? args_info.warning_arg : 0.0,
+ args_info.critical_given ? args_info.critical_arg : 0.0,
+ 0.0,
+ body_buf.buflen );
+
+ /* -s: check if the excepted string matches */
+ if( args_info.string_given ) {
+ if( strstr( body_buf.buf, args_info.string_arg ) == NULL ) {
+ printf( "HTTP CRITICAL - string not found|%s\n", perfstring );
+ curlhelp_freebuffer( &body_buf );
+ curlhelp_freebuffer( &header_buf );
+ curl_easy_cleanup( curl );
+ curl_global_cleanup( );
+ exit( STATE_CRITICAL );
+ }
+ }
+
+ /* -w, -c: check warning and critical level */
+ if( args_info.critical_given && ( total_time > args_info.critical_arg ) ) {
+ level_str = "CRITICAL";
+ exit_state = STATE_CRITICAL;
+ }
+ if( !( exit_state == STATE_CRITICAL ) && args_info.warning_given && ( total_time > args_info.warning_arg ) ) {
+ level_str = "WARNING";
+ exit_state = STATE_WARNING;
+ }
+
+ /* get status line of answer, check sanity of HTTP code */
+ if( curlhelp_parse_statusline( header_buf.buf, &status_line ) < 0 ) {
+ printf( "HTTP CRITICAL HTTP/1.x %ld unknown - Unparseable status line in %.3g seconds response time|%s\n",
+ code, total_time, perfstring );
+ curlhelp_freebuffer( &body_buf );
+ curlhelp_freebuffer( &header_buf );
+ curl_easy_cleanup( curl );
+ curl_global_cleanup( );
+ exit( STATE_CRITICAL );
+ }
+ curl_easy_getinfo( curl, CURLINFO_RESPONSE_CODE, &code );
+ if( status_line.http_code != code ) {
+ printf( "HTTP CRITICAL HTTP/%d.%d %d %s - different HTTP codes (cUrl has %ld) in %.3g seconds response time|%s\n",
+ status_line.http_major, status_line.http_minor,
+ status_line.http_code, status_line.msg, code,
+ total_time, perfstring );
+ curlhelp_free_statusline( &status_line );
+ curlhelp_freebuffer( &body_buf );
+ curlhelp_freebuffer( &header_buf );
+ curl_easy_cleanup( curl );
+ curl_global_cleanup( );
+ exit( STATE_CRITICAL );
+ }
+
+ /* check status codes, set exit status accordingly */
+ if( code >= 600 || code <= 100 ) {
+ printf( "HTTP CRITICAL HTTP/%d.%d %d %s - Illegal status code (status line: %.40s)\n",
+ status_line.http_major, status_line.http_minor,
+ status_line.http_code, status_line.msg,
+ status_line.first_line );
+ curlhelp_free_statusline( &status_line );
+ curlhelp_freebuffer( &body_buf );
+ curlhelp_freebuffer( &header_buf );
+ curl_easy_cleanup( curl );
+ curl_global_cleanup( );
+ exit( STATE_CRITICAL );
+ }
+ if( code >= 500 ) {
+ level_str = "CRITICAL";
+ exit_state = STATE_CRITICAL;
+ } else if( code >= 400 ) {
+ level_str = "WARNING";
+ exit_state = STATE_WARNING;
+ }
+
+ printf( "HTTP %s HTTP/%d.%d %d %s - %.3g seconds response time|%s\n",
+ level_str, status_line.http_major, status_line.http_minor,
+ status_line.http_code, status_line.msg,
+ total_time, perfstring );
+
+ curlhelp_free_statusline( &status_line );
+ curlhelp_freebuffer( &body_buf );
+ curlhelp_freebuffer( &header_buf );
+ curl_easy_cleanup( curl );
+ curl_global_cleanup( );
+ exit( exit_state );
+}
diff --git a/src/check_curl.ggo b/src/check_curl.ggo
new file mode 100644
index 0000000..f0b8eaa
--- /dev/null
+++ b/src/check_curl.ggo
@@ -0,0 +1,90 @@
+# check_curl - Nagios Curl-based check plugin
+# Copyright (C) 2008 Andreas Baumann
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+
+package "check_url"
+version "0.0.1"
+purpose
+"Nagios plugin using libcurl and libpcre for http checks
+Copyright (c)2008 Andreas Baumann <abaumann at yahoo to com>"
+
+usage "[options] | --config-file <configuration file with options>"
+
+option "config-file" - "The optional configuration file"
+ string
+ typestr="filename"
+ optional
+
+# common options, should remain the same among all plugins (along
+# with -V/--version, and -h/--help which are also standard in gengetopt)
+
+option "verbose" v "Show details for command-line debugging (Nagios may truncate output)"
+ multiple
+ optional
+
+option "timeout" t "Seconds before connection times out (default: 10)"
+ long
+ typestr="INTEGER"
+ optional
+
+option "critical" c "Response time to result in critical status (seconds)"
+ long
+ typestr="INTEGER"
+ optional
+
+option "warning" w "Response time to result in warning"
+ long
+ typestr="INTEGER"
+ optional
+
+option "host" H "The host name in a HTTP 1.1 request (virtual host)"
+ string
+ typestr="host"
+ optional
+
+# plugin specific options
+
+option "ip" I "The host/IP to check"
+ string
+ typestr="host/IP"
+ required
+
+option "port" p "Port number (default: 80)"
+ short
+ typestr="INTEGER"
+ optional
+
+option "url" u "URL to GET or POST (default: /)"
+ string
+ typestr="PATH"
+ optional
+
+option "onredirect" f "How to handle redirected pages"
+ string
+ values="ok","warning","critical","follow"
+ optional
+
+option "authorization" a "Username:password on sites with basic authentication"
+ string
+ typestr="Username:Password"
+ optional
+
+option "string" s "String to expect in the content"
+ string
+ typestr="STRING"
+ optional
+
+option "ssl" S "Connect via SSL. Port defaults to 443"
+ optional
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..807d750
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,31 @@
+/*
+ check_curl - Nagios Curl-based check plugin
+ Copyright (C) 2008 Andreas Baumann
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __COMMON_H
+#define __COMMON_H
+
+/* exit codes as defined by nagios */
+enum {
+ STATE_OK,
+ STATE_WARNING,
+ STATE_CRITICAL,
+ STATE_UNKNOWN,
+ STATE_DEPENDENT
+};
+
+#endif /* __COMMON_H */
diff --git a/src/curlhelper.c b/src/curlhelper.c
new file mode 100644
index 0000000..57d2235
--- /dev/null
+++ b/src/curlhelper.c
@@ -0,0 +1,120 @@
+/*
+ check_curl - Nagios Curl-based check plugin
+ Copyright (C) 2008 Andreas Baumann
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#define _XOPEN_SOURCE 600
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "cmdline.h"
+
+#include "curlhelper.h"
+
+int curlhelp_initbuffer( curlhelp_curlbuf *buf ) {
+ buf->bufsize = 2048;
+ buf->buflen = 0;
+ buf->buf = (char *)malloc( 2048 );
+ if( buf->buf == NULL ) return -1;
+ return 0;
+}
+
+int curlhelp_buffer_callback( void *buffer, size_t size, size_t nmemb, void *stream ) {
+ curlhelp_curlbuf *buf = (curlhelp_curlbuf *)stream;
+
+ while( buf->bufsize < buf->buflen + size * nmemb + 1 ) {
+ buf->bufsize *= buf->bufsize * 1.3;
+ buf->buf = (char *)realloc( buf->buf, buf->bufsize );
+ if( buf->buf == NULL ) {
+ return -1;
+ }
+ }
+
+ memcpy( buf->buf + buf->buflen, buffer, size * nmemb );
+ buf->buflen += size * nmemb;
+ buf->buf[buf->buflen] = '\0';
+
+ return size * nmemb;
+}
+
+void curlhelp_freebuffer( curlhelp_curlbuf *buf ) {
+ free( buf->buf );
+ buf->buf = NULL;
+}
+
+int curlhelp_parse_statusline( char *buf, curlhelp_statusline *status_line ) {
+ char *first_line_end;
+ char *p;
+ size_t first_line_len;
+ char *pp;
+
+ first_line_end = strstr( buf, "\r\n" );
+ if( first_line_end == NULL ) return -1;
+
+ first_line_len = first_line_end - buf;
+ status_line->first_line = (char *)malloc( first_line_len + 1 );
+ if( status_line->first_line == NULL ) return -1;
+ memcpy( status_line->first_line, buf, first_line_len );
+ status_line->first_line[first_line_len] = '\0';
+
+ /* protocol and version: "HTTP/x.x" SP */
+
+ p = strtok( status_line->first_line, "/" );
+ if( p == NULL ) { free( status_line->first_line ); return -1; }
+ if( strcmp( p, "HTTP" ) != 0 ) { free( status_line->first_line ); return -1; }
+
+ p = strtok( NULL, "." );
+ if( p == NULL ) { free( status_line->first_line ); return -1; }
+ status_line->http_major = strtol( p, &pp, 10 );
+ if( *pp != '\0' ) { free( status_line->first_line ); return -1; }
+
+ p = strtok( NULL, " " );
+ if( p == NULL ) { free( status_line->first_line ); return -1; }
+ status_line->http_minor = strtol( p, &pp, 10 );
+ if( *pp != '\0' ) { free( status_line->first_line ); return -1; }
+
+ /* status code: "404" or "404.1", then SP */
+
+ p = strtok( NULL, " ." );
+ if( p == NULL ) { free( status_line->first_line ); return -1; }
+ if( strchr( p, '.' ) != NULL ) {
+ char *ppp;
+ ppp = strtok( p, "." );
+ status_line->http_code = strtol( ppp, &pp, 10 );
+ if( *pp != '\0' ) { free( status_line->first_line ); return -1; }
+
+ ppp = strtok( NULL, "" );
+ status_line->http_subcode = strtol( ppp, &pp, 10 );
+ if( *pp != '\0' ) { free( status_line->first_line ); return -1; }
+ } else {
+ status_line->http_code = strtol( p, &pp, 10 );
+ status_line->http_subcode = -1;
+ if( *pp != '\0' ) { free( status_line->first_line ); return -1; }
+ }
+
+ /* Human readable message: "Not Found" CRLF */
+
+ p = strtok( NULL, "" );
+ if( p == NULL ) { free( status_line->first_line ); return -1; }
+ status_line->msg = p;
+
+ return 0;
+}
+
+void curlhelp_free_statusline( curlhelp_statusline *status_line ) {
+ free( status_line->first_line );
+}
diff --git a/src/curlhelper.h b/src/curlhelper.h
new file mode 100644
index 0000000..a027918
--- /dev/null
+++ b/src/curlhelper.h
@@ -0,0 +1,50 @@
+/*
+ check_curl - Nagios Curl-based check plugin
+ Copyright (C) 2008 Andreas Baumann
+
+ 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 3 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __CURLHELPER_H
+#define __CURLHELPER_H
+
+/* callbacks for body, header, debug output */
+
+typedef struct {
+ char *buf;
+ size_t buflen;
+ size_t bufsize;
+} curlhelp_curlbuf;
+
+int curlhelp_initbuffer( curlhelp_curlbuf *buf );
+int curlhelp_buffer_callback( void *buffer, size_t size, size_t nmemb, void *stream );
+void curlhelp_freebuffer( curlhelp_curlbuf *buf );
+
+/* parsing */
+
+typedef struct {
+ int http_major; /* major version of the protocol, always 1 (HTTP/0.9
+ * never reached the big internet most likely) */
+ int http_minor; /* minor version of the protocol, usually 0 or 1 */
+ int http_code; /* HTTP return code as in RFC 2145 */
+ int http_subcode; /* Microsoft IIS extension, HTTP subcodes, see
+ * http://support.microsoft.com/kb/318380/en-us */
+ char *msg; /* the human readable message */
+ char *first_line; /* a copy of the first line */
+} curlhelp_statusline;
+
+int curlhelp_parse_statusline( char *buf, curlhelp_statusline *status_line );
+void curlhelp_free_statusline( curlhelp_statusline *status_line );
+
+#endif /* __CURLHELPER_H */
diff --git a/src/port/sys.h b/src/port/sys.h
new file mode 100644
index 0000000..65b68e2
--- /dev/null
+++ b/src/port/sys.h
@@ -0,0 +1,119 @@
+#if defined LINUX
+#if OS_MAJOR_VERSION == 2
+#if OS_MINOR_VERSION == 6
+#define _XOPEN_SOURCE 600
+#define HAVE_STDBOOL_H
+#define HAVE_STDINT_H
+#define HAVE_VSNPRINTF
+#define HAVE_SNPRINTF
+#define HAVE_VASPRINTF
+#define HAVE_ASPRINTF
+#define HAVE_STRDUP
+#define HAVE_LOCKF
+#else
+ #error unknown platform
+#endif /* defined OS_MINOR_VERSION == 6 */
+#else
+ #error unknown platform
+#endif /* defined OS_MAJOR_VERSION == 2 */
+#endif /* defined LINUX */
+
+#if defined FREEBSD
+#if OS_MAJOR_VERSION == 7
+#if OS_MINOR_VERSION == 0
+#define _XOPEN_SOURCE 600
+#define HAVE_STDBOOL_H
+#define HAVE_STDINT_H
+#define HAVE_VSNPRINTF
+#define HAVE_SNPRINTF
+#define HAVE_VASPRINTF
+#define HAVE_ASPRINTF
+#define HAVE_STRDUP
+#define HAVE_LOCKF
+#else
+ #error unknown platform
+#endif /* defined OS_MINOR_VERSION == 0 */
+#else
+#if OS_MAJOR_VERSION == 6
+#if OS_MINOR_VERSION == 2
+#define _XOPEN_SOURCE 600
+#define HAVE_STDBOOL_H
+#define HAVE_STDINT_H
+#define HAVE_VSNPRINTF
+#define HAVE_SNPRINTF
+#define HAVE_STRDUP
+#define HAVE_LOCKF
+#else
+ #error unknown platform
+#endif /* defined OS_MINOR_VERSION == 2 */
+#else
+ #error unknown platform
+#endif /* defined OS_MAJOR_VERSION == 6 */
+#endif /* defined OS_MAJOR_VERSION == 7 */
+#endif /* defined FREEBSD */
+
+#if defined OPENBSD
+#if OS_MAJOR_VERSION == 4
+#if OS_MINOR_VERSION >= 2 && OS_MINOR_VERSION <= 3
+#define _XOPEN_SOURCE 600
+#define HAVE_STDBOOL_H
+#define HAVE_STDINT_H
+#define HAVE_VSNPRINTF
+#define HAVE_SNPRINTF
+#define HAVE_VASPRINTF
+#define HAVE_ASPRINTF
+#define HAVE_STRDUP
+#define HAVE_LOCKF
+#else
+ #error unknown platform
+#endif /* defined OS_MINOR_VERSION >= 2 && OS_MINOR_VERSION <= 3 */
+#else
+ #error unknown platform
+#endif /* defined OS_MAJOR_VERSION == 4 */
+#endif /* defined OPENBSD */
+
+#if defined SUNOS
+#if OS_MAJOR_VERSION == 5
+#if OS_MINOR_VERSION == 8
+#if !defined __cplusplus
+#define _XOPEN_SOURCE 600
+#define __EXTENSIONS__
+#endif
+#define HAVE_SNPRINTF
+#define HAVE_VSNPRINTF
+#define HAVE_LOCKF
+#define HAVE_ENUM_BOOL
+#define HAVE_LINK_H
+#else
+#if OS_MINOR_VERSION == 10
+#if !defined __cplusplus
+#define _XOPEN_SOURCE 600
+#define __EXTENSIONS__
+#endif
+#define HAVE_SNPRINTF
+#define HAVE_VSNPRINTF
+#define HAVE_LOCKF
+#define HAVE_STDBOOL_H
+#define HAVE_STDINT_H
+#define HAVE_STRERROR_R
+#else
+ #error unknown platform
+#endif /* OS_MINOR_VERSION == 10 */
+#endif /* OS_MINOR_VERSION == 8 */
+#else
+ #error unknown platform
+#endif /* OS_MAJOR_VERSION == 5 */
+#endif /* defined SUNOS */
+
+#if defined CYGWIN
+#if OS_MAJOR_VERSION == 5
+#if OS_MINOR_VERSION == 0
+#define _XOPEN_SOURCE 600
+#define HAVE_ENUM_BOOL
+#else
+ #error unknown platform
+#endif /* OS_MINOR_VERSION == 0 */
+#else
+ #error unknown platform
+#endif /* OS_MAJOR_VERSION == 5 */
+#endif /* defined CYGWIN */
diff --git a/src/port/unused.h b/src/port/unused.h
new file mode 100644
index 0000000..c7692f6
--- /dev/null
+++ b/src/port/unused.h
@@ -0,0 +1,8 @@
+#ifndef __UNUSED_H
+#define __UNUSED_H
+
+#include "port/sys.h"
+
+#define UNUSED( x ) if( 0 && (x) ) { }
+
+#endif /* ifndef __UNUSED_H */