/*
 * nwpe
 *
 * get nagios service check data via http w/libcurl
 *
 * ATonns Thu Jun 19 19:14:47 EDT 2003
 *
 * $Id: nwpe.c,v 1.7 2003/07/09 21:55:48 atonns Exp atonns $
 *
 */

/*
#
# nwpe - get nagios service check data via http w/libcurl
# Copyright (C) 2003 - iVillage.com, Anthony Tonns
#
# 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 2
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
*/

/*	add HTTP Basic Auth functionality
	(requires libcurl-7.10.6 or later */
#define ENABLE_BASIC_AUTH

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <curl/types.h>
#include <curl/easy.h>

/* for curl_easy_setopt */
#define FALSE 0
#define TRUE 1

/* nagios return values */
#define OK 0
#define WARNING 1
#define CRITICAL 2
#define UNKNOWN 3

/* for loading HTTP headers in memory */
struct headers {
	char *data;
	size_t size;
};

/* print help for the user */
void usage(void)
{
	printf("nwpe:	-U http[s]://url.of.nagios/service/check\n");
	printf("	-a \"args=args for the service check\"\n");
#ifdef ENABLE_BASIC_AUTH
	printf("	[-u username -p password]\n");
#endif /* ENABLE_BASIC_AUTH */
	exit(1);
}

/* for rewriting output of CGI */
size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
	int written = fwrite(ptr,size,nmemb,(FILE *)stream);
	return written;
}

/* for storing HTTP headers in memory */
size_t header_data(void *ptr, size_t size, size_t nmemb, void *data)
{
	register int realsize = size * nmemb;
	struct headers *h = (struct headers *)data;

	h->data = (char *)realloc(h->data, h->size + realsize + 1);
	if ( h->data ) {
		memcpy(&(h->data[h->size]),ptr,realsize);
		h->size += realsize;
		h->data[h->size] = NULL;
	}
	return realsize;
}

int main(int argc, char **argv)
{
    CURL *curl;
    CURLcode res;
	char error_str[CURL_ERROR_SIZE];

	struct HttpPost *formpost=NULL;
	struct HttpPost *lastptr=NULL;
	struct curl_slist *headerlist=NULL;

	struct headers h;
	char *p, *s, *url, *args;
#ifdef ENABLE_BASIC_AUTH
	char *username, *password, *userpwd;
#endif /* ENABLE_BASIC_AUTH */
	int retval=UNKNOWN;

	int c;
	extern char *optarg;
	extern int optind, opterr;

	/* initialize header data */
	h.data=NULL;
	h.size=0;

	url=args=NULL;
#ifdef ENABLE_BASIC_AUTH
	username=password=userpwd=NULL;
#endif /* ENABLE_BASIC_AUTH */
	while ((c = getopt(argc, argv, "U:a:u:p:h")) != EOF)
		switch (c) {
		case 'U':
			url = optarg;
			break;
		case 'a':
			args = optarg;
			break;
#ifdef ENABLE_BASIC_AUTH
		case 'u':
			username = optarg;
			break;
		case 'p':
			password = optarg;
			break;
#endif /* ENABLE_BASIC_AUTH */
		case 'h':
		default:
			usage();
			break;
		}

	/* must have url and service check args */
	if ( url == NULL || args == NULL )
		usage();

#ifdef ENABLE_BASIC_AUTH
	/* if username is provided, require a password */
	if ( username != NULL && password == NULL )
		usage();

	/* create the combined username:password array for libcurl */
	if ( username != NULL ) {
		userpwd = (char *)malloc(sizeof(char) * (strlen(username) + strlen(password) + 2));
		strcpy(userpwd,username);
		strcat(userpwd,":");
		strcat(userpwd,password);
	}
#endif /* ENABLE_BASIC_AUTH */

    curl = curl_easy_init();
    if(curl) {
		/* the URL */
        curl_easy_setopt(curl, CURLOPT_URL,				url);

		/* the verbosity and error strings */
        curl_easy_setopt(curl, CURLOPT_NOPROGRESS,		TRUE);
        curl_easy_setopt(curl, CURLOPT_MUTE,			TRUE);
        curl_easy_setopt(curl, CURLOPT_ERRORBUFFER,		error_str);

		/* if it's an SSL URL, don't verify the cert with a CA */
		curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,	(long)0);
		curl_easy_setopt(curl,CURLOPT_SSL_VERIFYHOST,	(long)0);

		/* write to stdout explicitly */
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION,	write_data);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA,		stdout);

		/* store HTTP headers in memory with header_data function */
        curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION,	header_data);
        curl_easy_setopt(curl, CURLOPT_WRITEHEADER,		(void *)&h);

		/* post args */
        curl_easy_setopt(curl, CURLOPT_POST,			TRUE);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS,		args);

#ifdef ENABLE_BASIC_AUTH
		/* if we have the combined username password, set the option */
		if ( userpwd != NULL ) {
	        curl_easy_setopt(curl, CURLOPT_USERPWD,		userpwd);
	        curl_easy_setopt(curl, CURLOPT_HTTPAUTH,	CURLAUTH_BASIC);
		}
#endif /* ENABLE_BASIC_AUTH */

		/* run curl */
        res = curl_easy_perform(curl);

		/* non-zero means error */
		if ( res ) {
        	curl_easy_cleanup(curl);
			printf("%s\n",error_str);
			exit(UNKNOWN);
		}

		/* parse the HTTP headers */
		p=h.data;
		while(*p != NULL) {
			s=p;
			/* find the newline at the end of this header ... */
			while(*p != '\n' && *p != NULL) {
				p++;
			}
			/* ... and make it null */
			*p=NULL; p++;
			/* now check to see if the header is the nagios Return-value */
			if ( strstr(s,"Return-value") ) {
				/* skip ahead to the value */
				s += 14;
				/* store the return value */
				retval = atoi(s);
				/* stop processing headers */
				break;
			}
		}

		/* cleanup */
        curl_easy_cleanup(curl);
    }

	/* return the Return-value header (or the default of UNKNOWN if not set) */
    return retval;
}

