summaryrefslogtreecommitdiffstats
path: root/plugins/check_dbi.c
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2024-10-31 15:27:01 +0100
committerLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2024-10-31 15:27:01 +0100
commitfa15fdcf5dc2d40aba2f8520108e552b73b1df2b (patch)
treed51d62db024b317091f42d9ee540da7371e9d170 /plugins/check_dbi.c
parent0fd0421052fed1972ecbdfdabecba5a616eaa109 (diff)
parent87eb2bef1ee2a6a42793437b2f5d63f41b1e1806 (diff)
downloadmonitoring-plugins-fa15fdc.tar.gz
Merge branch 'master' into fix/check_ssh-variable-stuff
Diffstat (limited to 'plugins/check_dbi.c')
-rw-r--r--plugins/check_dbi.c827
1 files changed, 387 insertions, 440 deletions
diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c
index 29c85206..96575672 100644
--- a/plugins/check_dbi.c
+++ b/plugins/check_dbi.c
@@ -1,36 +1,36 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_dbi plugin 3 * Monitoring check_dbi plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2011 Monitoring Plugins Development Team 6 * Copyright (c) 2011-2024 Monitoring Plugins Development Team
7* Author: Sebastian 'tokkee' Harl <sh@teamix.net> 7 * Original Author: Sebastian 'tokkee' Harl <sh@teamix.net>
8* 8 *
9* Description: 9 * Description:
10* 10 *
11* This file contains the check_dbi plugin 11 * This file contains the check_dbi plugin
12* 12 *
13* Runs an arbitrary (SQL) command and checks the result. 13 * Runs an arbitrary (SQL) command and checks the result.
14* 14 *
15* 15 *
16* This program is free software: you can redistribute it and/or modify 16 * This program is free software: you can redistribute it and/or modify
17* it under the terms of the GNU General Public License as published by 17 * it under the terms of the GNU General Public License as published by
18* the Free Software Foundation, either version 3 of the License, or 18 * the Free Software Foundation, either version 3 of the License, or
19* (at your option) any later version. 19 * (at your option) any later version.
20* 20 *
21* This program is distributed in the hope that it will be useful, 21 * This program is distributed in the hope that it will be useful,
22* but WITHOUT ANY WARRANTY; without even the implied warranty of 22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24* GNU General Public License for more details. 24 * GNU General Public License for more details.
25* 25 *
26* You should have received a copy of the GNU General Public License 26 * You should have received a copy of the GNU General Public License
27* along with this program. If not, see <http://www.gnu.org/licenses/>. 27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28* 28 *
29* 29 *
30*****************************************************************************/ 30 *****************************************************************************/
31 31
32const char *progname = "check_dbi"; 32const char *progname = "check_dbi";
33const char *copyright = "2011"; 33const char *copyright = "2011-2024";
34const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
35 35
36#include "common.h" 36#include "common.h"
@@ -43,7 +43,7 @@ const char *email = "devel@monitoring-plugins.org";
43 43
44/* required for NAN */ 44/* required for NAN */
45#ifndef _ISOC99_SOURCE 45#ifndef _ISOC99_SOURCE
46#define _ISOC99_SOURCE 46# define _ISOC99_SOURCE
47#endif 47#endif
48 48
49#include <assert.h> 49#include <assert.h>
@@ -70,42 +70,40 @@ typedef struct {
70 char *value; 70 char *value;
71} driver_option_t; 71} driver_option_t;
72 72
73char *host = NULL; 73static char *host = NULL;
74int verbose = 0; 74static int verbose = 0;
75 75
76char *warning_range = NULL; 76static char *warning_range = NULL;
77char *critical_range = NULL; 77static char *critical_range = NULL;
78thresholds *dbi_thresholds = NULL; 78static thresholds *dbi_thresholds = NULL;
79 79
80char *expect = NULL; 80static char *expect = NULL;
81 81
82regex_t expect_re; 82static regex_t expect_re;
83char *expect_re_str = NULL; 83static char *expect_re_str = NULL;
84int expect_re_cflags = 0; 84static int expect_re_cflags = 0;
85 85
86np_dbi_metric_t metric = METRIC_QUERY_RESULT; 86static np_dbi_metric_t metric = METRIC_QUERY_RESULT;
87np_dbi_type_t type = TYPE_NUMERIC; 87static np_dbi_type_t type = TYPE_NUMERIC;
88 88
89char *np_dbi_driver = NULL; 89static char *np_dbi_driver = NULL;
90driver_option_t *np_dbi_options = NULL; 90static driver_option_t *np_dbi_options = NULL;
91int np_dbi_options_num = 0; 91static int np_dbi_options_num = 0;
92char *np_dbi_database = NULL; 92static char *np_dbi_database = NULL;
93char *np_dbi_query = NULL; 93static char *np_dbi_query = NULL;
94 94
95int process_arguments (int, char **); 95static int process_arguments(int, char **);
96int validate_arguments (void); 96static int validate_arguments(void);
97void print_usage (void); 97void print_usage(void);
98void print_help (void); 98static void print_help(void);
99 99
100double timediff (struct timeval, struct timeval); 100static double timediff(struct timeval, struct timeval);
101 101
102void np_dbi_print_error (dbi_conn, char *, ...); 102static void np_dbi_print_error(dbi_conn, char *, ...);
103 103
104int do_query (dbi_conn, const char **, double *, double *); 104static int do_query(dbi_conn, const char **, double *, double *);
105 105
106int 106int main(int argc, char **argv) {
107main (int argc, char **argv)
108{
109 int status = STATE_UNKNOWN; 107 int status = STATE_UNKNOWN;
110 108
111 dbi_driver driver; 109 dbi_driver driver;
@@ -113,7 +111,8 @@ main (int argc, char **argv)
113 111
114 unsigned int server_version; 112 unsigned int server_version;
115 113
116 struct timeval start_timeval, end_timeval; 114 struct timeval start_timeval;
115 struct timeval end_timeval;
117 double conn_time = 0.0; 116 double conn_time = 0.0;
118 double query_time = 0.0; 117 double query_time = 0.0;
119 118
@@ -122,59 +121,58 @@ main (int argc, char **argv)
122 121
123 int i; 122 int i;
124 123
125 setlocale (LC_ALL, ""); 124 setlocale(LC_ALL, "");
126 bindtextdomain (PACKAGE, LOCALEDIR); 125 bindtextdomain(PACKAGE, LOCALEDIR);
127 textdomain (PACKAGE); 126 textdomain(PACKAGE);
128 127
129 /* Parse extra opts if any */ 128 /* Parse extra opts if any */
130 argv = np_extra_opts (&argc, argv, progname); 129 argv = np_extra_opts(&argc, argv, progname);
131 130
132 if (process_arguments (argc, argv) == ERROR) 131 if (process_arguments(argc, argv) == ERROR)
133 usage4 (_("Could not parse arguments")); 132 usage4(_("Could not parse arguments"));
134 133
135 /* Set signal handling and alarm */ 134 /* Set signal handling and alarm */
136 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { 135 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
137 usage4 (_("Cannot catch SIGALRM")); 136 usage4(_("Cannot catch SIGALRM"));
138 } 137 }
139 alarm (timeout_interval); 138 alarm(timeout_interval);
140 139
141 if (verbose > 2) 140 if (verbose > 2)
142 printf ("Initializing DBI\n"); 141 printf("Initializing DBI\n");
143 142
144 dbi_inst *instance_p = { 0 }; 143 dbi_inst *instance_p = {0};
145 144
146 if (dbi_initialize_r(NULL, instance_p) < 0) { 145 if (dbi_initialize_r(NULL, instance_p) < 0) {
147 printf ("UNKNOWN - failed to initialize DBI; possibly you don't have any drivers installed.\n"); 146 printf("UNKNOWN - failed to initialize DBI; possibly you don't have any drivers installed.\n");
148 return STATE_UNKNOWN; 147 return STATE_UNKNOWN;
149 } 148 }
150 149
151 if (instance_p == NULL) { 150 if (instance_p == NULL) {
152 printf ("UNKNOWN - failed to initialize DBI.\n"); 151 printf("UNKNOWN - failed to initialize DBI.\n");
153 return STATE_UNKNOWN; 152 return STATE_UNKNOWN;
154 } 153 }
155 154
156 if (verbose) 155 if (verbose)
157 printf ("Opening DBI driver '%s'\n", np_dbi_driver); 156 printf("Opening DBI driver '%s'\n", np_dbi_driver);
158 157
159 driver = dbi_driver_open_r(np_dbi_driver, instance_p); 158 driver = dbi_driver_open_r(np_dbi_driver, instance_p);
160 if (! driver) { 159 if (!driver) {
161 printf ("UNKNOWN - failed to open DBI driver '%s'; possibly it's not installed.\n", 160 printf("UNKNOWN - failed to open DBI driver '%s'; possibly it's not installed.\n", np_dbi_driver);
162 np_dbi_driver);
163 161
164 printf ("Known drivers:\n"); 162 printf("Known drivers:\n");
165 for (driver = dbi_driver_list_r(NULL, instance_p); driver; driver = dbi_driver_list_r(driver, instance_p)) { 163 for (driver = dbi_driver_list_r(NULL, instance_p); driver; driver = dbi_driver_list_r(driver, instance_p)) {
166 printf (" - %s\n", dbi_driver_get_name (driver)); 164 printf(" - %s\n", dbi_driver_get_name(driver));
167 } 165 }
168 return STATE_UNKNOWN; 166 return STATE_UNKNOWN;
169 } 167 }
170 168
171 /* make a connection to the database */ 169 /* make a connection to the database */
172 gettimeofday (&start_timeval, NULL); 170 gettimeofday(&start_timeval, NULL);
173 171
174 conn = dbi_conn_open (driver); 172 conn = dbi_conn_open(driver);
175 if (! conn) { 173 if (!conn) {
176 printf ("UNKNOWN - failed top open connection object.\n"); 174 printf("UNKNOWN - failed top open connection object.\n");
177 dbi_conn_close (conn); 175 dbi_conn_close(conn);
178 return STATE_UNKNOWN; 176 return STATE_UNKNOWN;
179 } 177 }
180 178
@@ -182,210 +180,190 @@ main (int argc, char **argv)
182 const char *opt; 180 const char *opt;
183 181
184 if (verbose > 1) 182 if (verbose > 1)
185 printf ("Setting DBI driver option '%s' to '%s'\n", 183 printf("Setting DBI driver option '%s' to '%s'\n", np_dbi_options[i].key, np_dbi_options[i].value);
186 np_dbi_options[i].key, np_dbi_options[i].value);
187 184
188 if (! dbi_conn_set_option (conn, np_dbi_options[i].key, np_dbi_options[i].value)) 185 if (!dbi_conn_set_option(conn, np_dbi_options[i].key, np_dbi_options[i].value))
189 continue; 186 continue;
190 /* else: status != 0 */ 187 /* else: status != 0 */
191 188
192 np_dbi_print_error (conn, "UNKNOWN - failed to set option '%s' to '%s'", 189 np_dbi_print_error(conn, "UNKNOWN - failed to set option '%s' to '%s'", np_dbi_options[i].key, np_dbi_options[i].value);
193 np_dbi_options[i].key, np_dbi_options[i].value); 190 printf("Known driver options:\n");
194 printf ("Known driver options:\n");
195 191
196 for (opt = dbi_conn_get_option_list (conn, NULL); opt; 192 for (opt = dbi_conn_get_option_list(conn, NULL); opt; opt = dbi_conn_get_option_list(conn, opt)) {
197 opt = dbi_conn_get_option_list (conn, opt)) { 193 printf(" - %s\n", opt);
198 printf (" - %s\n", opt);
199 } 194 }
200 dbi_conn_close (conn); 195 dbi_conn_close(conn);
201 return STATE_UNKNOWN; 196 return STATE_UNKNOWN;
202 } 197 }
203 198
204 if (host) { 199 if (host) {
205 if (verbose > 1) 200 if (verbose > 1)
206 printf ("Setting DBI driver option 'host' to '%s'\n", host); 201 printf("Setting DBI driver option 'host' to '%s'\n", host);
207 dbi_conn_set_option (conn, "host", host); 202 dbi_conn_set_option(conn, "host", host);
208 } 203 }
209 204
210 if (verbose) { 205 if (verbose) {
211 const char *dbname, *host; 206 const char *dbname;
207 const char *host;
212 208
213 dbname = dbi_conn_get_option (conn, "dbname"); 209 dbname = dbi_conn_get_option(conn, "dbname");
214 host = dbi_conn_get_option (conn, "host"); 210 host = dbi_conn_get_option(conn, "host");
215 211
216 if (! dbname) 212 if (!dbname)
217 dbname = "<unspecified>"; 213 dbname = "<unspecified>";
218 if (! host) 214 if (!host)
219 host = "<unspecified>"; 215 host = "<unspecified>";
220 216
221 printf ("Connecting to database '%s' at host '%s'\n", 217 printf("Connecting to database '%s' at host '%s'\n", dbname, host);
222 dbname, host);
223 } 218 }
224 219
225 if (dbi_conn_connect (conn) < 0) { 220 if (dbi_conn_connect(conn) < 0) {
226 np_dbi_print_error (conn, "UNKNOWN - failed to connect to database"); 221 np_dbi_print_error(conn, "UNKNOWN - failed to connect to database");
227 return STATE_UNKNOWN; 222 return STATE_UNKNOWN;
228 } 223 }
229 224
230 gettimeofday (&end_timeval, NULL); 225 gettimeofday(&end_timeval, NULL);
231 conn_time = timediff (start_timeval, end_timeval); 226 conn_time = timediff(start_timeval, end_timeval);
232 227
233 server_version = dbi_conn_get_engine_version (conn); 228 server_version = dbi_conn_get_engine_version(conn);
234 if (verbose) 229 if (verbose)
235 printf ("Connected to server version %u\n", server_version); 230 printf("Connected to server version %u\n", server_version);
236 231
237 if (metric == METRIC_SERVER_VERSION) 232 if (metric == METRIC_SERVER_VERSION)
238 status = get_status (server_version, dbi_thresholds); 233 status = get_status(server_version, dbi_thresholds);
239 234
240 if (verbose) 235 if (verbose)
241 printf ("Time elapsed: %f\n", conn_time); 236 printf("Time elapsed: %f\n", conn_time);
242 237
243 if (metric == METRIC_CONN_TIME) 238 if (metric == METRIC_CONN_TIME)
244 status = get_status (conn_time, dbi_thresholds); 239 status = get_status(conn_time, dbi_thresholds);
245 240
246 /* select a database */ 241 /* select a database */
247 if (np_dbi_database) { 242 if (np_dbi_database) {
248 if (verbose > 1) 243 if (verbose > 1)
249 printf ("Selecting database '%s'\n", np_dbi_database); 244 printf("Selecting database '%s'\n", np_dbi_database);
250 245
251 if (dbi_conn_select_db (conn, np_dbi_database)) { 246 if (dbi_conn_select_db(conn, np_dbi_database)) {
252 np_dbi_print_error (conn, "UNKNOWN - failed to select database '%s'", 247 np_dbi_print_error(conn, "UNKNOWN - failed to select database '%s'", np_dbi_database);
253 np_dbi_database);
254 return STATE_UNKNOWN; 248 return STATE_UNKNOWN;
255 } 249 }
256 } 250 }
257 251
258 if (np_dbi_query) { 252 if (np_dbi_query) {
259 /* execute query */ 253 /* execute query */
260 status = do_query (conn, &query_val_str, &query_val, &query_time); 254 status = do_query(conn, &query_val_str, &query_val, &query_time);
261 if (status != STATE_OK) 255 if (status != STATE_OK)
262 /* do_query prints an error message in this case */ 256 /* do_query prints an error message in this case */
263 return status; 257 return status;
264 258
265 if (metric == METRIC_QUERY_RESULT) { 259 if (metric == METRIC_QUERY_RESULT) {
266 if (expect) { 260 if (expect) {
267 if ((! query_val_str) || strcmp (query_val_str, expect)) 261 if ((!query_val_str) || strcmp(query_val_str, expect))
268 status = STATE_CRITICAL; 262 status = STATE_CRITICAL;
269 else 263 else
270 status = STATE_OK; 264 status = STATE_OK;
271 } 265 } else if (expect_re_str) {
272 else if (expect_re_str) {
273 int err; 266 int err;
274 267
275 err = regexec (&expect_re, query_val_str, 0, NULL, /* flags = */ 0); 268 err = regexec(&expect_re, query_val_str, 0, NULL, /* flags = */ 0);
276 if (! err) 269 if (!err)
277 status = STATE_OK; 270 status = STATE_OK;
278 else if (err == REG_NOMATCH) 271 else if (err == REG_NOMATCH)
279 status = STATE_CRITICAL; 272 status = STATE_CRITICAL;
280 else { 273 else {
281 char errmsg[1024]; 274 char errmsg[1024];
282 regerror (err, &expect_re, errmsg, sizeof (errmsg)); 275 regerror(err, &expect_re, errmsg, sizeof(errmsg));
283 printf ("ERROR - failed to execute regular expression: %s\n", 276 printf("ERROR - failed to execute regular expression: %s\n", errmsg);
284 errmsg);
285 status = STATE_CRITICAL; 277 status = STATE_CRITICAL;
286 } 278 }
287 } 279 } else
288 else 280 status = get_status(query_val, dbi_thresholds);
289 status = get_status (query_val, dbi_thresholds); 281 } else if (metric == METRIC_QUERY_TIME)
290 } 282 status = get_status(query_time, dbi_thresholds);
291 else if (metric == METRIC_QUERY_TIME)
292 status = get_status (query_time, dbi_thresholds);
293 } 283 }
294 284
295 if (verbose) 285 if (verbose)
296 printf("Closing connection\n"); 286 printf("Closing connection\n");
297 dbi_conn_close (conn); 287 dbi_conn_close(conn);
298 288
299 /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error 289 /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error
300 * which should have been reported and handled (abort) before 290 * which should have been reported and handled (abort) before
301 * ... unless we expected a string to be returned */ 291 * ... unless we expected a string to be returned */
302 assert ((metric != METRIC_QUERY_RESULT) || (! isnan (query_val)) 292 assert((metric != METRIC_QUERY_RESULT) || (!isnan(query_val)) || (type == TYPE_STRING));
303 || (type == TYPE_STRING));
304 293
305 assert ((type != TYPE_STRING) || (expect || expect_re_str)); 294 assert((type != TYPE_STRING) || (expect || expect_re_str));
306 295
307 printf ("%s - connection time: %fs", state_text (status), conn_time); 296 printf("%s - connection time: %fs", state_text(status), conn_time);
308 if (np_dbi_query) { 297 if (np_dbi_query) {
309 if (type == TYPE_STRING) { 298 if (type == TYPE_STRING) {
310 assert (expect || expect_re_str); 299 assert(expect || expect_re_str);
311 printf (", '%s' returned '%s' in %fs", np_dbi_query, 300 printf(", '%s' returned '%s' in %fs", np_dbi_query, query_val_str ? query_val_str : "<nothing>", query_time);
312 query_val_str ? query_val_str : "<nothing>", query_time);
313 if (status != STATE_OK) { 301 if (status != STATE_OK) {
314 if (expect) 302 if (expect)
315 printf (" (expected '%s')", expect); 303 printf(" (expected '%s')", expect);
316 else if (expect_re_str) 304 else if (expect_re_str)
317 printf (" (expected regex /%s/%s)", expect_re_str, 305 printf(" (expected regex /%s/%s)", expect_re_str, ((expect_re_cflags & REG_ICASE) ? "i" : ""));
318 ((expect_re_cflags & REG_ICASE) ? "i" : ""));
319 } 306 }
320 } 307 } else if (isnan(query_val))
321 else if (isnan (query_val)) 308 printf(", '%s' query execution time: %fs", np_dbi_query, query_time);
322 printf (", '%s' query execution time: %fs", np_dbi_query, query_time);
323 else 309 else
324 printf (", '%s' returned %f in %fs", np_dbi_query, query_val, query_time); 310 printf(", '%s' returned %f in %fs", np_dbi_query, query_val, query_time);
325 } 311 }
326 312
327 printf (" | conntime=%fs;%s;%s;0; server_version=%u;%s;%s;0;", conn_time, 313 printf(" | conntime=%fs;%s;%s;0; server_version=%u;%s;%s;0;", conn_time,
328 ((metric == METRIC_CONN_TIME) && warning_range) ? warning_range : "", 314 ((metric == METRIC_CONN_TIME) && warning_range) ? warning_range : "",
329 ((metric == METRIC_CONN_TIME) && critical_range) ? critical_range : "", 315 ((metric == METRIC_CONN_TIME) && critical_range) ? critical_range : "", server_version,
330 server_version, 316 ((metric == METRIC_SERVER_VERSION) && warning_range) ? warning_range : "",
331 ((metric == METRIC_SERVER_VERSION) && warning_range) ? warning_range : "", 317 ((metric == METRIC_SERVER_VERSION) && critical_range) ? critical_range : "");
332 ((metric == METRIC_SERVER_VERSION) && critical_range) ? critical_range : "");
333 if (np_dbi_query) { 318 if (np_dbi_query) {
334 if (! isnan (query_val)) /* this is also true when -e is used */ 319 if (!isnan(query_val)) /* this is also true when -e is used */
335 printf (" query=%f;%s;%s;;", query_val, 320 printf(" query=%f;%s;%s;;", query_val, ((metric == METRIC_QUERY_RESULT) && warning_range) ? warning_range : "",
336 ((metric == METRIC_QUERY_RESULT) && warning_range) ? warning_range : "", 321 ((metric == METRIC_QUERY_RESULT) && critical_range) ? critical_range : "");
337 ((metric == METRIC_QUERY_RESULT) && critical_range) ? critical_range : ""); 322 printf(" querytime=%fs;%s;%s;0;", query_time, ((metric == METRIC_QUERY_TIME) && warning_range) ? warning_range : "",
338 printf (" querytime=%fs;%s;%s;0;", query_time, 323 ((metric == METRIC_QUERY_TIME) && critical_range) ? critical_range : "");
339 ((metric == METRIC_QUERY_TIME) && warning_range) ? warning_range : "",
340 ((metric == METRIC_QUERY_TIME) && critical_range) ? critical_range : "");
341 } 324 }
342 printf ("\n"); 325 printf("\n");
343 return status; 326 return status;
344} 327}
345 328
346/* process command-line arguments */ 329/* process command-line arguments */
347int 330int process_arguments(int argc, char **argv) {
348process_arguments (int argc, char **argv)
349{
350 int c; 331 int c;
351 332
352 int option = 0; 333 int option = 0;
353 static struct option longopts[] = { 334 static struct option longopts[] = {STD_LONG_OPTS,
354 STD_LONG_OPTS, 335
355 336 {"expect", required_argument, 0, 'e'},
356 {"expect", required_argument, 0, 'e'}, 337 {"regex", required_argument, 0, 'r'},
357 {"regex", required_argument, 0, 'r'}, 338 {"regexi", required_argument, 0, 'R'},
358 {"regexi", required_argument, 0, 'R'}, 339 {"metric", required_argument, 0, 'm'},
359 {"metric", required_argument, 0, 'm'}, 340 {"driver", required_argument, 0, 'd'},
360 {"driver", required_argument, 0, 'd'}, 341 {"option", required_argument, 0, 'o'},
361 {"option", required_argument, 0, 'o'}, 342 {"query", required_argument, 0, 'q'},
362 {"query", required_argument, 0, 'q'}, 343 {"database", required_argument, 0, 'D'},
363 {"database", required_argument, 0, 'D'}, 344 {0, 0, 0, 0}};
364 {0, 0, 0, 0}
365 };
366 345
367 while (1) { 346 while (1) {
368 c = getopt_long (argc, argv, "Vvht:c:w:e:r:R:m:H:d:o:q:D:", 347 c = getopt_long(argc, argv, "Vvht:c:w:e:r:R:m:H:d:o:q:D:", longopts, &option);
369 longopts, &option);
370 348
371 if (c == EOF) 349 if (c == EOF)
372 break; 350 break;
373 351
374 switch (c) { 352 switch (c) {
375 case '?': /* usage */ 353 case '?': /* usage */
376 usage5 (); 354 usage5();
377 case 'h': /* help */ 355 case 'h': /* help */
378 print_help (); 356 print_help();
379 exit (STATE_UNKNOWN); 357 exit(STATE_UNKNOWN);
380 case 'V': /* version */ 358 case 'V': /* version */
381 print_revision (progname, NP_VERSION); 359 print_revision(progname, NP_VERSION);
382 exit (STATE_UNKNOWN); 360 exit(STATE_UNKNOWN);
383 361
384 case 'c': /* critical range */ 362 case 'c': /* critical range */
385 critical_range = optarg; 363 critical_range = optarg;
386 type = TYPE_NUMERIC; 364 type = TYPE_NUMERIC;
387 break; 365 break;
388 case 'w': /* warning range */ 366 case 'w': /* warning range */
389 warning_range = optarg; 367 warning_range = optarg;
390 type = TYPE_NUMERIC; 368 type = TYPE_NUMERIC;
391 break; 369 break;
@@ -396,47 +374,45 @@ process_arguments (int argc, char **argv)
396 case 'R': 374 case 'R':
397 expect_re_cflags = REG_ICASE; 375 expect_re_cflags = REG_ICASE;
398 /* fall through */ 376 /* fall through */
399 case 'r': 377 case 'r': {
400 { 378 int err;
401 int err;
402 379
403 expect_re_cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE; 380 expect_re_cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE;
404 expect_re_str = optarg; 381 expect_re_str = optarg;
405 type = TYPE_STRING; 382 type = TYPE_STRING;
406 383
407 err = regcomp (&expect_re, expect_re_str, expect_re_cflags); 384 err = regcomp(&expect_re, expect_re_str, expect_re_cflags);
408 if (err) { 385 if (err) {
409 char errmsg[1024]; 386 char errmsg[1024];
410 regerror (err, &expect_re, errmsg, sizeof (errmsg)); 387 regerror(err, &expect_re, errmsg, sizeof(errmsg));
411 printf ("ERROR - failed to compile regular expression: %s\n", 388 printf("ERROR - failed to compile regular expression: %s\n", errmsg);
412 errmsg); 389 return ERROR;
413 return ERROR;
414 }
415 break;
416 } 390 }
391 break;
392 }
417 393
418 case 'm': 394 case 'm':
419 if (! strcasecmp (optarg, "CONN_TIME")) 395 if (!strcasecmp(optarg, "CONN_TIME"))
420 metric = METRIC_CONN_TIME; 396 metric = METRIC_CONN_TIME;
421 else if (! strcasecmp (optarg, "SERVER_VERSION")) 397 else if (!strcasecmp(optarg, "SERVER_VERSION"))
422 metric = METRIC_SERVER_VERSION; 398 metric = METRIC_SERVER_VERSION;
423 else if (! strcasecmp (optarg, "QUERY_RESULT")) 399 else if (!strcasecmp(optarg, "QUERY_RESULT"))
424 metric = METRIC_QUERY_RESULT; 400 metric = METRIC_QUERY_RESULT;
425 else if (! strcasecmp (optarg, "QUERY_TIME")) 401 else if (!strcasecmp(optarg, "QUERY_TIME"))
426 metric = METRIC_QUERY_TIME; 402 metric = METRIC_QUERY_TIME;
427 else 403 else
428 usage2 (_("Invalid metric"), optarg); 404 usage2(_("Invalid metric"), optarg);
429 break; 405 break;
430 case 't': /* timeout */ 406 case 't': /* timeout */
431 if (!is_intnonneg (optarg)) 407 if (!is_intnonneg(optarg))
432 usage2 (_("Timeout interval must be a positive integer"), optarg); 408 usage2(_("Timeout interval must be a positive integer"), optarg);
433 else 409 else
434 timeout_interval = atoi (optarg); 410 timeout_interval = atoi(optarg);
435 411
436 break; 412 break;
437 case 'H': /* host */ 413 case 'H': /* host */
438 if (!is_host (optarg)) 414 if (!is_host(optarg))
439 usage2 (_("Invalid hostname/address"), optarg); 415 usage2(_("Invalid hostname/address"), optarg);
440 else 416 else
441 host = optarg; 417 host = optarg;
442 break; 418 break;
@@ -447,36 +423,34 @@ process_arguments (int argc, char **argv)
447 case 'd': 423 case 'd':
448 np_dbi_driver = optarg; 424 np_dbi_driver = optarg;
449 break; 425 break;
450 case 'o': 426 case 'o': {
451 { 427 driver_option_t *new;
452 driver_option_t *new;
453 428
454 char *k, *v; 429 char *k;
430 char *v;
455 431
456 k = optarg; 432 k = optarg;
457 v = strchr (k, (int)'='); 433 v = strchr(k, (int)'=');
458 434
459 if (! v) 435 if (!v)
460 usage2 (_("Option must be '<key>=<value>'"), optarg); 436 usage2(_("Option must be '<key>=<value>'"), optarg);
461 437
462 *v = '\0'; 438 *v = '\0';
463 ++v; 439 ++v;
464 440
465 new = realloc (np_dbi_options, 441 new = realloc(np_dbi_options, (np_dbi_options_num + 1) * sizeof(*new));
466 (np_dbi_options_num + 1) * sizeof (*new)); 442 if (!new) {
467 if (! new) { 443 printf("UNKNOWN - failed to reallocate memory\n");
468 printf ("UNKNOWN - failed to reallocate memory\n"); 444 exit(STATE_UNKNOWN);
469 exit (STATE_UNKNOWN); 445 }
470 }
471 446
472 np_dbi_options = new; 447 np_dbi_options = new;
473 new = np_dbi_options + np_dbi_options_num; 448 new = np_dbi_options + np_dbi_options_num;
474 ++np_dbi_options_num; 449 ++np_dbi_options_num;
475 450
476 new->key = k; 451 new->key = k;
477 new->value = v; 452 new->value = v;
478 } 453 } break;
479 break;
480 case 'q': 454 case 'q':
481 np_dbi_query = optarg; 455 np_dbi_query = optarg;
482 break; 456 break;
@@ -486,341 +460,314 @@ process_arguments (int argc, char **argv)
486 } 460 }
487 } 461 }
488 462
489 set_thresholds (&dbi_thresholds, warning_range, critical_range); 463 set_thresholds(&dbi_thresholds, warning_range, critical_range);
490 464
491 return validate_arguments (); 465 return validate_arguments();
492} 466}
493 467
494int 468int validate_arguments(void) {
495validate_arguments () 469 if (!np_dbi_driver)
496{ 470 usage("Must specify a DBI driver");
497 if (! np_dbi_driver)
498 usage ("Must specify a DBI driver");
499 471
500 if (((metric == METRIC_QUERY_RESULT) || (metric == METRIC_QUERY_TIME)) 472 if (((metric == METRIC_QUERY_RESULT) || (metric == METRIC_QUERY_TIME)) && (!np_dbi_query))
501 && (! np_dbi_query)) 473 usage("Must specify a query to execute (metric == QUERY_RESULT)");
502 usage ("Must specify a query to execute (metric == QUERY_RESULT)");
503 474
504 if ((metric != METRIC_CONN_TIME) 475 if ((metric != METRIC_CONN_TIME) && (metric != METRIC_SERVER_VERSION) && (metric != METRIC_QUERY_RESULT) &&
505 && (metric != METRIC_SERVER_VERSION) 476 (metric != METRIC_QUERY_TIME))
506 && (metric != METRIC_QUERY_RESULT) 477 usage("Invalid metric specified");
507 && (metric != METRIC_QUERY_TIME))
508 usage ("Invalid metric specified");
509 478
510 if (expect && (warning_range || critical_range || expect_re_str)) 479 if (expect && (warning_range || critical_range || expect_re_str))
511 usage ("Do not mix -e and -w/-c/-r/-R"); 480 usage("Do not mix -e and -w/-c/-r/-R");
512 481
513 if (expect_re_str && (warning_range || critical_range || expect)) 482 if (expect_re_str && (warning_range || critical_range || expect))
514 usage ("Do not mix -r/-R and -w/-c/-e"); 483 usage("Do not mix -r/-R and -w/-c/-e");
515 484
516 if (expect && (metric != METRIC_QUERY_RESULT)) 485 if (expect && (metric != METRIC_QUERY_RESULT))
517 usage ("Option -e requires metric QUERY_RESULT"); 486 usage("Option -e requires metric QUERY_RESULT");
518 487
519 if (expect_re_str && (metric != METRIC_QUERY_RESULT)) 488 if (expect_re_str && (metric != METRIC_QUERY_RESULT))
520 usage ("Options -r/-R require metric QUERY_RESULT"); 489 usage("Options -r/-R require metric QUERY_RESULT");
521 490
522 return OK; 491 return OK;
523} 492}
524 493
525void 494void print_help(void) {
526print_help (void) 495 print_revision(progname, NP_VERSION);
527{
528 print_revision (progname, NP_VERSION);
529 496
530 printf (COPYRIGHT, copyright, email); 497 printf(COPYRIGHT, copyright, email);
531 498
532 printf (_("This program connects to an (SQL) database using DBI and checks the\n" 499 printf(_("This program connects to an (SQL) database using DBI and checks the\n"
533 "specified metric against threshold levels. The default metric is\n" 500 "specified metric against threshold levels. The default metric is\n"
534 "the result of the specified query.\n")); 501 "the result of the specified query.\n"));
535 502
536 printf ("\n\n"); 503 printf("\n\n");
537 504
538 print_usage (); 505 print_usage();
539 506
540 printf (UT_HELP_VRSN); 507 printf(UT_HELP_VRSN);
541/* include this conditionally to avoid 'zero-length printf format string' 508/* include this conditionally to avoid 'zero-length printf format string'
542 * compiler warnings */ 509 * compiler warnings */
543#ifdef NP_EXTRA_OPTS 510#ifdef NP_EXTRA_OPTS
544 printf (UT_EXTRA_OPTS); 511 printf(UT_EXTRA_OPTS);
545#endif 512#endif
546 printf ("\n"); 513 printf("\n");
547 514
548 printf (" %s\n", "-d, --driver=STRING"); 515 printf(" %s\n", "-d, --driver=STRING");
549 printf (" %s\n", _("DBI driver to use")); 516 printf(" %s\n", _("DBI driver to use"));
550 printf (" %s\n", "-o, --option=STRING"); 517 printf(" %s\n", "-o, --option=STRING");
551 printf (" %s\n", _("DBI driver options")); 518 printf(" %s\n", _("DBI driver options"));
552 printf (" %s\n", "-q, --query=STRING"); 519 printf(" %s\n", "-q, --query=STRING");
553 printf (" %s\n", _("query to execute")); 520 printf(" %s\n", _("query to execute"));
554 printf ("\n"); 521 printf("\n");
555 522
556 printf (UT_WARN_CRIT_RANGE); 523 printf(UT_WARN_CRIT_RANGE);
557 printf (" %s\n", "-e, --expect=STRING"); 524 printf(" %s\n", "-e, --expect=STRING");
558 printf (" %s\n", _("String to expect as query result")); 525 printf(" %s\n", _("String to expect as query result"));
559 printf (" %s\n", _("Do not mix with -w, -c, -r, or -R!")); 526 printf(" %s\n", _("Do not mix with -w, -c, -r, or -R!"));
560 printf (" %s\n", "-r, --regex=REGEX"); 527 printf(" %s\n", "-r, --regex=REGEX");
561 printf (" %s\n", _("Extended POSIX regular expression to check query result against")); 528 printf(" %s\n", _("Extended POSIX regular expression to check query result against"));
562 printf (" %s\n", _("Do not mix with -w, -c, -e, or -R!")); 529 printf(" %s\n", _("Do not mix with -w, -c, -e, or -R!"));
563 printf (" %s\n", "-R, --regexi=REGEX"); 530 printf(" %s\n", "-R, --regexi=REGEX");
564 printf (" %s\n", _("Case-insensitive extended POSIX regex to check query result against")); 531 printf(" %s\n", _("Case-insensitive extended POSIX regex to check query result against"));
565 printf (" %s\n", _("Do not mix with -w, -c, -e, or -r!")); 532 printf(" %s\n", _("Do not mix with -w, -c, -e, or -r!"));
566 printf (" %s\n", "-m, --metric=METRIC"); 533 printf(" %s\n", "-m, --metric=METRIC");
567 printf (" %s\n", _("Metric to check thresholds against. Available metrics:")); 534 printf(" %s\n", _("Metric to check thresholds against. Available metrics:"));
568 printf (" CONN_TIME - %s\n", _("time used for setting up the database connection")); 535 printf(" CONN_TIME - %s\n", _("time used for setting up the database connection"));
569 printf (" QUERY_RESULT - %s\n", _("result (first column of first row) of the query")); 536 printf(" QUERY_RESULT - %s\n", _("result (first column of first row) of the query"));
570 printf (" QUERY_TIME - %s\n", _("time used to execute the query")); 537 printf(" QUERY_TIME - %s\n", _("time used to execute the query"));
571 printf (" %s\n", _("(ignore the query result)")); 538 printf(" %s\n", _("(ignore the query result)"));
572 printf ("\n"); 539 printf("\n");
573 540
574 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 541 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
575 542
576 printf (UT_VERBOSE); 543 printf(UT_VERBOSE);
577 544
578 printf ("\n"); 545 printf("\n");
579 printf (" %s\n", _("A DBI driver (-d option) is required. If the specified metric operates")); 546 printf(" %s\n", _("A DBI driver (-d option) is required. If the specified metric operates"));
580 printf (" %s\n\n", _("on a query, one has to be specified (-q option).")); 547 printf(" %s\n\n", _("on a query, one has to be specified (-q option)."));
581 548
582 printf (" %s\n", _("This plugin connects to an (SQL) database using libdbi and, optionally,")); 549 printf(" %s\n", _("This plugin connects to an (SQL) database using libdbi and, optionally,"));
583 printf (" %s\n", _("executes the specified query. The first column of the first row of the")); 550 printf(" %s\n", _("executes the specified query. The first column of the first row of the"));
584 printf (" %s\n", _("result will be parsed and, in QUERY_RESULT mode, compared with the")); 551 printf(" %s\n", _("result will be parsed and, in QUERY_RESULT mode, compared with the"));
585 printf (" %s\n", _("warning and critical ranges. The result from the query has to be numeric")); 552 printf(" %s\n", _("warning and critical ranges. The result from the query has to be numeric"));
586 printf (" %s\n\n", _("(strings representing numbers are fine).")); 553 printf(" %s\n\n", _("(strings representing numbers are fine)."));
587 554
588 printf (" %s\n", _("The number and type of required DBI driver options depends on the actual")); 555 printf(" %s\n", _("The number and type of required DBI driver options depends on the actual"));
589 printf (" %s\n", _("driver. See its documentation at http://libdbi-drivers.sourceforge.net/")); 556 printf(" %s\n", _("driver. See its documentation at http://libdbi-drivers.sourceforge.net/"));
590 printf (" %s\n\n", _("for details.")); 557 printf(" %s\n\n", _("for details."));
591 558
592 printf (" %s\n", _("Examples:")); 559 printf(" %s\n", _("Examples:"));
593 printf (" check_dbi -d pgsql -o username=postgres -m QUERY_RESULT \\\n"); 560 printf(" check_dbi -d pgsql -o username=postgres -m QUERY_RESULT \\\n");
594 printf (" -q 'SELECT COUNT(*) FROM pg_stat_activity' -w 5 -c 10\n"); 561 printf(" -q 'SELECT COUNT(*) FROM pg_stat_activity' -w 5 -c 10\n");
595 printf (" Warning if more than five connections; critical if more than ten.\n\n"); 562 printf(" Warning if more than five connections; critical if more than ten.\n\n");
596 563
597 printf (" check_dbi -d mysql -H localhost -o username=user -o password=secret \\\n"); 564 printf(" check_dbi -d mysql -H localhost -o username=user -o password=secret \\\n");
598 printf (" -q 'SELECT COUNT(*) FROM logged_in_users -w 5:20 -c 0:50\n"); 565 printf(" -q 'SELECT COUNT(*) FROM logged_in_users -w 5:20 -c 0:50\n");
599 printf (" Warning if less than 5 or more than 20 users are logged in; critical\n"); 566 printf(" Warning if less than 5 or more than 20 users are logged in; critical\n");
600 printf (" if more than 50 users.\n\n"); 567 printf(" if more than 50 users.\n\n");
601 568
602 printf (" check_dbi -d firebird -o username=user -o password=secret -o dbname=foo \\\n"); 569 printf(" check_dbi -d firebird -o username=user -o password=secret -o dbname=foo \\\n");
603 printf (" -m CONN_TIME -w 0.5 -c 2\n"); 570 printf(" -m CONN_TIME -w 0.5 -c 2\n");
604 printf (" Warning if connecting to the database takes more than half of a second;\n"); 571 printf(" Warning if connecting to the database takes more than half of a second;\n");
605 printf (" critical if it takes more than 2 seconds.\n\n"); 572 printf(" critical if it takes more than 2 seconds.\n\n");
606 573
607 printf (" check_dbi -d mysql -H localhost -o username=user \\\n"); 574 printf(" check_dbi -d mysql -H localhost -o username=user \\\n");
608 printf (" -q 'SELECT concat(@@version, \" \", @@version_comment)' \\\n"); 575 printf(" -q 'SELECT concat(@@version, \" \", @@version_comment)' \\\n");
609 printf (" -r '^5\\.[01].*MySQL Enterprise Server'\n"); 576 printf(" -r '^5\\.[01].*MySQL Enterprise Server'\n");
610 printf (" Critical if the database server is not a MySQL enterprise server in either\n"); 577 printf(" Critical if the database server is not a MySQL enterprise server in either\n");
611 printf (" version 5.0.x or 5.1.x.\n\n"); 578 printf(" version 5.0.x or 5.1.x.\n\n");
612 579
613 printf (" check_dbi -d pgsql -u username=user -m SERVER_VERSION \\\n"); 580 printf(" check_dbi -d pgsql -u username=user -m SERVER_VERSION \\\n");
614 printf (" -w 090000:090099 -c 090000:090199\n"); 581 printf(" -w 090000:090099 -c 090000:090199\n");
615 printf (" Warn if the PostgreSQL server version is not 9.0.x; critical if the version\n"); 582 printf(" Warn if the PostgreSQL server version is not 9.0.x; critical if the version\n");
616 printf (" is less than 9.x or higher than 9.1.x.\n"); 583 printf(" is less than 9.x or higher than 9.1.x.\n");
617 584
618 printf (UT_SUPPORT); 585 printf(UT_SUPPORT);
619} 586}
620 587
621void 588void print_usage(void) {
622print_usage (void) 589 printf("%s\n", _("Usage:"));
623{ 590 printf("%s -d <DBI driver> [-o <DBI driver option> [...]] [-q <query>]\n", progname);
624 printf ("%s\n", _("Usage:")); 591 printf(" [-H <host>] [-c <critical range>] [-w <warning range>] [-m <metric>]\n");
625 printf ("%s -d <DBI driver> [-o <DBI driver option> [...]] [-q <query>]\n", progname); 592 printf(" [-e <string>] [-r|-R <regex>]\n");
626 printf (" [-H <host>] [-c <critical range>] [-w <warning range>] [-m <metric>]\n");
627 printf (" [-e <string>] [-r|-R <regex>]\n");
628} 593}
629 594
630#define CHECK_IGNORE_ERROR(s) \ 595#define CHECK_IGNORE_ERROR(s) \
631 do { \ 596 do { \
632 if (metric != METRIC_QUERY_RESULT) \ 597 if (metric != METRIC_QUERY_RESULT) \
633 return (s); \ 598 return (s); \
634 } while (0) 599 } while (0)
635 600
636const char * 601const char *get_field_str(dbi_conn conn, dbi_result res, unsigned short field_type) {
637get_field_str (dbi_conn conn, dbi_result res, unsigned short field_type)
638{
639 const char *str; 602 const char *str;
640 603
641 if (field_type != DBI_TYPE_STRING) { 604 if (field_type != DBI_TYPE_STRING) {
642 printf ("CRITICAL - result value is not a string\n"); 605 printf("CRITICAL - result value is not a string\n");
643 return NULL; 606 return NULL;
644 } 607 }
645 608
646 str = dbi_result_get_string_idx (res, 1); 609 str = dbi_result_get_string_idx(res, 1);
647 if ((! str) || (strcmp (str, "ERROR") == 0)) { 610 if ((!str) || (strcmp(str, "ERROR") == 0)) {
648 CHECK_IGNORE_ERROR (NULL); 611 CHECK_IGNORE_ERROR(NULL);
649 np_dbi_print_error (conn, "CRITICAL - failed to fetch string value"); 612 np_dbi_print_error(conn, "CRITICAL - failed to fetch string value");
650 return NULL; 613 return NULL;
651 } 614 }
652 615
653 if ((verbose && (type == TYPE_STRING)) || (verbose > 2)) 616 if ((verbose && (type == TYPE_STRING)) || (verbose > 2))
654 printf ("Query returned string '%s'\n", str); 617 printf("Query returned string '%s'\n", str);
655 return str; 618 return str;
656} 619}
657 620
658double 621double get_field(dbi_conn conn, dbi_result res, unsigned short *field_type) {
659get_field (dbi_conn conn, dbi_result res, unsigned short *field_type)
660{
661 double val = NAN; 622 double val = NAN;
662 623
663 if (*field_type == DBI_TYPE_INTEGER) { 624 if (*field_type == DBI_TYPE_INTEGER) {
664 val = (double)dbi_result_get_longlong_idx (res, 1); 625 val = (double)dbi_result_get_longlong_idx(res, 1);
665 } 626 } else if (*field_type == DBI_TYPE_DECIMAL) {
666 else if (*field_type == DBI_TYPE_DECIMAL) { 627 val = dbi_result_get_double_idx(res, 1);
667 val = dbi_result_get_double_idx (res, 1); 628 } else if (*field_type == DBI_TYPE_STRING) {
668 }
669 else if (*field_type == DBI_TYPE_STRING) {
670 const char *val_str; 629 const char *val_str;
671 char *endptr = NULL; 630 char *endptr = NULL;
672 631
673 val_str = get_field_str (conn, res, *field_type); 632 val_str = get_field_str(conn, res, *field_type);
674 if (! val_str) { 633 if (!val_str) {
675 CHECK_IGNORE_ERROR (NAN); 634 CHECK_IGNORE_ERROR(NAN);
676 *field_type = DBI_TYPE_ERROR; 635 *field_type = DBI_TYPE_ERROR;
677 return NAN; 636 return NAN;
678 } 637 }
679 638
680 val = strtod (val_str, &endptr); 639 val = strtod(val_str, &endptr);
681 if (endptr == val_str) { 640 if (endptr == val_str) {
682 CHECK_IGNORE_ERROR (NAN); 641 CHECK_IGNORE_ERROR(NAN);
683 printf ("CRITICAL - result value is not a numeric: %s\n", val_str); 642 printf("CRITICAL - result value is not a numeric: %s\n", val_str);
684 *field_type = DBI_TYPE_ERROR; 643 *field_type = DBI_TYPE_ERROR;
685 return NAN; 644 return NAN;
686 } 645 }
687 else if ((endptr != NULL) && (*endptr != '\0')) { 646 if ((endptr != NULL) && (*endptr != '\0')) {
688 if (verbose) 647 if (verbose)
689 printf ("Garbage after value: %s\n", endptr); 648 printf("Garbage after value: %s\n", endptr);
690 } 649 }
691 } 650 } else {
692 else { 651 CHECK_IGNORE_ERROR(NAN);
693 CHECK_IGNORE_ERROR (NAN); 652 printf("CRITICAL - cannot parse value of type %s (%i)\n",
694 printf ("CRITICAL - cannot parse value of type %s (%i)\n", 653 (*field_type == DBI_TYPE_BINARY) ? "BINARY"
695 (*field_type == DBI_TYPE_BINARY) 654 : (*field_type == DBI_TYPE_DATETIME) ? "DATETIME"
696 ? "BINARY" 655 : "<unknown>",
697 : (*field_type == DBI_TYPE_DATETIME) 656 *field_type);
698 ? "DATETIME"
699 : "<unknown>",
700 *field_type);
701 *field_type = DBI_TYPE_ERROR; 657 *field_type = DBI_TYPE_ERROR;
702 return NAN; 658 return NAN;
703 } 659 }
704 return val; 660 return val;
705} 661}
706 662
707double 663double get_query_result(dbi_conn conn, dbi_result res, const char **res_val_str, double *res_val) {
708get_query_result (dbi_conn conn, dbi_result res, const char **res_val_str, double *res_val)
709{
710 unsigned short field_type; 664 unsigned short field_type;
711 double val = NAN; 665 double val = NAN;
712 666
713 if (dbi_result_get_numrows (res) == DBI_ROW_ERROR) { 667 if (dbi_result_get_numrows(res) == DBI_ROW_ERROR) {
714 CHECK_IGNORE_ERROR (STATE_OK); 668 CHECK_IGNORE_ERROR(STATE_OK);
715 np_dbi_print_error (conn, "CRITICAL - failed to fetch rows"); 669 np_dbi_print_error(conn, "CRITICAL - failed to fetch rows");
716 return STATE_CRITICAL; 670 return STATE_CRITICAL;
717 } 671 }
718 672
719 if (dbi_result_get_numrows (res) < 1) { 673 if (dbi_result_get_numrows(res) < 1) {
720 CHECK_IGNORE_ERROR (STATE_OK); 674 CHECK_IGNORE_ERROR(STATE_OK);
721 printf ("WARNING - no rows returned\n"); 675 printf("WARNING - no rows returned\n");
722 return STATE_WARNING; 676 return STATE_WARNING;
723 } 677 }
724 678
725 if (dbi_result_get_numfields (res) == DBI_FIELD_ERROR) { 679 if (dbi_result_get_numfields(res) == DBI_FIELD_ERROR) {
726 CHECK_IGNORE_ERROR (STATE_OK); 680 CHECK_IGNORE_ERROR(STATE_OK);
727 np_dbi_print_error (conn, "CRITICAL - failed to fetch fields"); 681 np_dbi_print_error(conn, "CRITICAL - failed to fetch fields");
728 return STATE_CRITICAL; 682 return STATE_CRITICAL;
729 } 683 }
730 684
731 if (dbi_result_get_numfields (res) < 1) { 685 if (dbi_result_get_numfields(res) < 1) {
732 CHECK_IGNORE_ERROR (STATE_OK); 686 CHECK_IGNORE_ERROR(STATE_OK);
733 printf ("WARNING - no fields returned\n"); 687 printf("WARNING - no fields returned\n");
734 return STATE_WARNING; 688 return STATE_WARNING;
735 } 689 }
736 690
737 if (dbi_result_first_row (res) != 1) { 691 if (dbi_result_first_row(res) != 1) {
738 CHECK_IGNORE_ERROR (STATE_OK); 692 CHECK_IGNORE_ERROR(STATE_OK);
739 np_dbi_print_error (conn, "CRITICAL - failed to fetch first row"); 693 np_dbi_print_error(conn, "CRITICAL - failed to fetch first row");
740 return STATE_CRITICAL; 694 return STATE_CRITICAL;
741 } 695 }
742 696
743 field_type = dbi_result_get_field_type_idx (res, 1); 697 field_type = dbi_result_get_field_type_idx(res, 1);
744 if (field_type != DBI_TYPE_ERROR) { 698 if (field_type != DBI_TYPE_ERROR) {
745 if (type == TYPE_STRING) 699 if (type == TYPE_STRING)
746 /* the value will be freed in dbi_result_free */ 700 /* the value will be freed in dbi_result_free */
747 *res_val_str = strdup (get_field_str (conn, res, field_type)); 701 *res_val_str = strdup(get_field_str(conn, res, field_type));
748 else 702 else
749 val = get_field (conn, res, &field_type); 703 val = get_field(conn, res, &field_type);
750 } 704 }
751 705
752 *res_val = val; 706 *res_val = val;
753 707
754 if (field_type == DBI_TYPE_ERROR) { 708 if (field_type == DBI_TYPE_ERROR) {
755 CHECK_IGNORE_ERROR (STATE_OK); 709 CHECK_IGNORE_ERROR(STATE_OK);
756 np_dbi_print_error (conn, "CRITICAL - failed to fetch data"); 710 np_dbi_print_error(conn, "CRITICAL - failed to fetch data");
757 return STATE_CRITICAL; 711 return STATE_CRITICAL;
758 } 712 }
759 713
760 dbi_result_free (res); 714 dbi_result_free(res);
761 return STATE_OK; 715 return STATE_OK;
762} 716}
763 717
764#undef CHECK_IGNORE_ERROR 718#undef CHECK_IGNORE_ERROR
765 719
766int 720int do_query(dbi_conn conn, const char **res_val_str, double *res_val, double *res_time) {
767do_query (dbi_conn conn, const char **res_val_str, double *res_val, double *res_time)
768{
769 dbi_result res; 721 dbi_result res;
770 722
771 struct timeval timeval_start, timeval_end; 723 struct timeval timeval_start;
724 struct timeval timeval_end;
772 int status = STATE_OK; 725 int status = STATE_OK;
773 726
774 assert (np_dbi_query); 727 assert(np_dbi_query);
775 728
776 if (verbose) 729 if (verbose)
777 printf ("Executing query '%s'\n", np_dbi_query); 730 printf("Executing query '%s'\n", np_dbi_query);
778 731
779 gettimeofday (&timeval_start, NULL); 732 gettimeofday(&timeval_start, NULL);
780 733
781 res = dbi_conn_query (conn, np_dbi_query); 734 res = dbi_conn_query(conn, np_dbi_query);
782 if (! res) { 735 if (!res) {
783 np_dbi_print_error (conn, "CRITICAL - failed to execute query '%s'", np_dbi_query); 736 np_dbi_print_error(conn, "CRITICAL - failed to execute query '%s'", np_dbi_query);
784 return STATE_CRITICAL; 737 return STATE_CRITICAL;
785 } 738 }
786 739
787 status = get_query_result (conn, res, res_val_str, res_val); 740 status = get_query_result(conn, res, res_val_str, res_val);
788 741
789 gettimeofday (&timeval_end, NULL); 742 gettimeofday(&timeval_end, NULL);
790 *res_time = timediff (timeval_start, timeval_end); 743 *res_time = timediff(timeval_start, timeval_end);
791 744
792 if (verbose) 745 if (verbose)
793 printf ("Time elapsed: %f\n", *res_time); 746 printf("Time elapsed: %f\n", *res_time);
794 747
795 return status; 748 return status;
796} 749}
797 750
798double 751double timediff(struct timeval start, struct timeval end) {
799timediff (struct timeval start, struct timeval end)
800{
801 double diff; 752 double diff;
802 753
803 while (start.tv_usec > end.tv_usec) { 754 while (start.tv_usec > end.tv_usec) {
804 --end.tv_sec; 755 --end.tv_sec;
805 end.tv_usec += 1000000; 756 end.tv_usec += 1000000;
806 } 757 }
807 diff = (double)(end.tv_sec - start.tv_sec) 758 diff = (double)(end.tv_sec - start.tv_sec) + (double)(end.tv_usec - start.tv_usec) / 1000000.0;
808 + (double)(end.tv_usec - start.tv_usec) / 1000000.0;
809 return diff; 759 return diff;
810} 760}
811 761
812void 762void np_dbi_print_error(dbi_conn conn, char *fmt, ...) {
813np_dbi_print_error (dbi_conn conn, char *fmt, ...)
814{
815 const char *errmsg = NULL; 763 const char *errmsg = NULL;
816 va_list ap; 764 va_list ap;
817 765
818 va_start (ap, fmt); 766 va_start(ap, fmt);
819 767
820 dbi_conn_error (conn, &errmsg); 768 dbi_conn_error(conn, &errmsg);
821 vprintf (fmt, ap); 769 vprintf(fmt, ap);
822 printf (": %s\n", errmsg); 770 printf(": %s\n", errmsg);
823 771
824 va_end (ap); 772 va_end(ap);
825} 773}
826