diff --git a/SRC/PLUGINS b/SRC/PLUGINS index 715a6aa..bf14200 100644 --- a/SRC/PLUGINS +++ b/SRC/PLUGINS @@ -10,8 +10,12 @@ can safely return NULL. void start (struct addrinfo *res) Typically just stores the res structure for later use. -void execute () - Connects and do whatever the protocol requires. +int execute () + Connects and do whatever the protocol requires. It is called once + per iteration. It returns >=0 if it succeeds and -1 if it failed. + +void terminate () + Cleans everything. It is called after all iterations. Start your plugin source code with: diff --git a/SRC/echoping.1 b/SRC/echoping.1 index f12ba6f..86e8995 100644 --- a/SRC/echoping.1 +++ b/SRC/echoping.1 @@ -28,6 +28,7 @@ echoping \- tests a remote host with TCP or UDP .RI [-m plugin] .B hostname [:port] +[plugin options...] .SH DESCRIPTION .LP @@ -126,7 +127,10 @@ or (depending on your Unix). /usr/include/netinet/ip.h may contain interesting constants for setting Type Of Service. .IP -m\ plugin -Load the given plugin. Quite experimental. +Load the given plugin. Quite experimental. The documentation for a +plugin is in echoping_PLUGIN(1). The plugin-specific options appear +.B after +the hostname. .SH EXAMPLES .IP echoping\ \-v\ foobar.example.com Tests the remote machine with TCP echo (one test). @@ -138,6 +142,9 @@ indicate the whole URL. .IP echoping\ \-h\ http://www.example.com/\ cache.example.com:3128 Tests the remote Web proxy-cache and asks a Web page. Note that you must indicate the whole URL. +.IP echoping\ -n\ 3\ -m\ whois\ foobar.example.com\ -r\ tao.example.org +Loads the whois plugin and query the host foobar.example.com. "-r +tao.example.org" are options specific to the whois plugin. .IP echoping\ -u\ \-P\ 0xa0\ foobar.example.com Sends several UDP Echo packets with an IP Precedence of 5. .SH IP TYPE OF SERVICE OCTET diff --git a/SRC/echoping.c b/SRC/echoping.c index 53ff60f..5797bd8 100644 --- a/SRC/echoping.c +++ b/SRC/echoping.c @@ -460,6 +460,12 @@ main (argc, argv) { err_sys ("Cannot find execute in %s: %s", plugin_name, dl_result); } + plugin_terminate = dlsym (plugin, "terminate"); + dl_result = dlerror (); + if (dl_result) + { + err_sys ("Cannot find terminate in %s: %s", plugin_name, dl_result); + } } if (!udp && !ttcp) { @@ -848,6 +854,7 @@ main (argc, argv) if (plugin) { plugin_execute (); + /* TODO: do something with the return code */ } else { @@ -1369,19 +1376,21 @@ main (argc, argv) } } /* End of main loop */ - printstats (); - if (successes >= 1) - exit (0); - else - exit (1); - /* It would be nice to clean here (OpenSSL, etc) */ + /* Clean */ + if (plugin) + plugin_terminate(); + /* It would be nice to clean here for OpenSSL */ #ifdef GNUTLS if (ssl) { gnutls_global_deinit (); } #endif - + printstats (); + if (successes >= 1) + exit (0); + else + exit (1); } void diff --git a/SRC/echoping.h b/SRC/echoping.h index 08013ab..4b5e8a6 100644 --- a/SRC/echoping.h +++ b/SRC/echoping.h @@ -127,8 +127,10 @@ typedef char * (*init_f) (const int argc, const char **argv); init_f plugin_init; typedef void (*start_f) (struct addrinfo *); start_f plugin_start; -typedef void (*execute_f) (); +typedef int (*execute_f) (); execute_f plugin_execute; +typedef void (*terminate_f) (); +terminate_f plugin_terminate; #endif #endif diff --git a/SRC/plugins/Makefile.in b/SRC/plugins/Makefile.in index 1a4e85c..8467f84 100644 --- a/SRC/plugins/Makefile.in +++ b/SRC/plugins/Makefile.in @@ -1,18 +1,23 @@ CCFLAGS=-DHAVE_CONFIG_H -Wall -O0 -g CCDYNAMICFLAGS=${CCFLAGS} -fPIC LDFLAGS= -LDDYNAMICFLAGS=${LDFLAGS} -shared +LDDYNAMICFLAGS=${LDFLAGS} -shared -lpq # TODO: add the flags only when necessary -PLUGINS=random.so whois.so +PLUGINS=random.so whois.so postgres all: $(PLUGINS) +postgres: postgresql.so + %.o: %.c ${CC} ${CCDYNAMICFLAGS} -c -o $@ $< %.so: %.o ${CC} ${LDDYNAMICFLAGS} -o $@ $< +test-postgresql: test-postgresql.o + ${CC} -o $@ -l pq $< + clean: -rm -f *.o *.so program diff --git a/SRC/plugins/postgresql.c b/SRC/plugins/postgresql.c new file mode 100644 index 0000000..389f624 --- /dev/null +++ b/SRC/plugins/postgresql.c @@ -0,0 +1,112 @@ +/* + * PostgreSQL plugin. + * + * $Id$ + */ + +#define IN_PLUGIN +#include "../echoping.h" + +#include + +const char *request = NULL; +int readall = FALSE; +poptContext postgresql_poptcon; +PGconn *conn; +PGresult *res; +char *conninfo; + +void +postgresql_usage (const char *msg) +{ + if (msg) + { + printf ("PostgreSQL plugin error: %s\n", msg); + } + poptPrintUsage (postgresql_poptcon, stdout, 0); + exit (1); +} + +char * +init (const int argc, const char **argv) +{ + int value; + char *msg = malloc (256); + /* popt variables */ + struct poptOption options[] = { + {"conninfo", 'c', POPT_ARG_STRING, &conninfo, 0, + "Connection information for the Postgresql server. Something like 'host=foo dbname=bar''", + "request"}, + {"request", 'r', POPT_ARG_STRING, &request, 0, + "Request/query (in SQL) to send to the Postgresql server. Only SELECT are supported.", + "request"}, + {"readall", 'a', POPT_ARG_NONE, &readall, 0, + "Read all the data sent by the Postgresql server", + ""}, + POPT_AUTOHELP POPT_TABLEEND + }; + postgresql_poptcon = poptGetContext (NULL, argc, + argv, options, + POPT_CONTEXT_KEEP_FIRST); + while ((value = poptGetNextOpt (postgresql_poptcon)) > 0) + { + if (value < -1) + { + sprintf (msg, "%s: %s", + poptBadOption (postgresql_poptcon, POPT_BADOPTION_NOALIAS), + poptStrerror (value)); + postgresql_usage (msg); + } + } + if (request == NULL) + postgresql_usage ("Mandatory request missing"); + if (conninfo == NULL) + postgresql_usage ("Mandatory connection information missing"); + return NULL; /* We only use the conninfo, echoping does not see our hostname or port */ +} + +void +start (struct addrinfo *res) +{ + conn = PQconnectdb (conninfo); + if (conn == NULL) + { + printf ("Cannot create connection\n"); + exit (1); + } + if (PQstatus (conn) == CONNECTION_BAD) + { + printf ("Connection failed: %s\n", PQerrorMessage (conn)); + exit (1); + } +} + +int +execute () +{ + unsigned int row, column; + res = PQexec (conn, request); + if (PQresultStatus (res) != PGRES_TUPLES_OK) + { + printf ("Cannot run \"%s\": %s\n", request, PQresultErrorMessage (res)); + return -1; + } + if (readall) + { + for (row = 0; row++; row < PQntuples (res)) + { + for (column = 0; column++; column < PQnfields (res)) + { + PQgetvalue (res, row, column); + /* TODO: test the return code */ + } + } + } + return 0; +} + +void +terminate () +{ + PQfinish (conn); +} diff --git a/SRC/plugins/random.c b/SRC/plugins/random.c index 7118288..24b1a91 100644 --- a/SRC/plugins/random.c +++ b/SRC/plugins/random.c @@ -22,8 +22,11 @@ void start () { } -void +int execute () { usleep (rand () % 1000000); + return 1; } + +void terminate() {} diff --git a/SRC/plugins/whois.c b/SRC/plugins/whois.c index 3ed4591..3fc1f83 100644 --- a/SRC/plugins/whois.c +++ b/SRC/plugins/whois.c @@ -77,7 +77,7 @@ start (struct addrinfo *res) whois_server = *res; } -void +int execute () { int nr = 0; @@ -102,4 +102,8 @@ execute () if (dump) printf ("\n"); close (sockfd); + return 1; +} + +void terminate() { }