summaryrefslogtreecommitdiffstats
path: root/plugins/check_pgsql.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_pgsql.c')
-rw-r--r--plugins/check_pgsql.c629
1 files changed, 270 insertions, 359 deletions
diff --git a/plugins/check_pgsql.c b/plugins/check_pgsql.c
index 94d589e..6613634 100644
--- a/plugins/check_pgsql.c
+++ b/plugins/check_pgsql.c
@@ -1,35 +1,35 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_pgsql plugin 3 * Monitoring check_pgsql plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 1999-2011 Monitoring Plugins Development Team 6 * Copyright (c) 1999-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_pgsql plugin 10 * This file contains the check_pgsql plugin
11* 11 *
12* Test whether a PostgreSQL Database is accepting connections. 12 * Test whether a PostgreSQL Database is accepting connections.
13* 13 *
14* 14 *
15* This program is free software: you can redistribute it and/or modify 15 * This program is free software: you can redistribute it and/or modify
16* it under the terms of the GNU General Public License as published by 16 * it under the terms of the GNU General Public License as published by
17* the Free Software Foundation, either version 3 of the License, or 17 * the Free Software Foundation, either version 3 of the License, or
18* (at your option) any later version. 18 * (at your option) any later version.
19* 19 *
20* This program is distributed in the hope that it will be useful, 20 * This program is distributed in the hope that it will be useful,
21* but WITHOUT ANY WARRANTY; without even the implied warranty of 21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23* GNU General Public License for more details. 23 * GNU General Public License for more details.
24* 24 *
25* You should have received a copy of the GNU General Public License 25 * You should have received a copy of the GNU General Public License
26* along with this program. If not, see <http://www.gnu.org/licenses/>. 26 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27* 27 *
28* 28 *
29*****************************************************************************/ 29 *****************************************************************************/
30 30
31const char *progname = "check_pgsql"; 31const char *progname = "check_pgsql";
32const char *copyright = "1999-2011"; 32const char *copyright = "1999-2024";
33const char *email = "devel@monitoring-plugins.org"; 33const char *email = "devel@monitoring-plugins.org";
34 34
35#include "common.h" 35#include "common.h"
@@ -40,22 +40,18 @@ const char *email = "devel@monitoring-plugins.org";
40#include <libpq-fe.h> 40#include <libpq-fe.h>
41#include <pg_config_manual.h> 41#include <pg_config_manual.h>
42 42
43#define DEFAULT_DB "template1" 43#define DEFAULT_DB "template1"
44#define DEFAULT_HOST "127.0.0.1" 44#define DEFAULT_HOST "127.0.0.1"
45 45
46/* return the PSQL server version as a 3-tuple */ 46/* return the PSQL server version as a 3-tuple */
47#define PSQL_SERVER_VERSION3(server_version) \ 47#define PSQL_SERVER_VERSION3(server_version) \
48 (server_version) / 10000, \ 48 (server_version) / 10000, (server_version) / 100 - (int)((server_version) / 10000) * 100, \
49 (server_version) / 100 - (int)((server_version) / 10000) * 100, \ 49 (server_version) - (int)((server_version) / 100) * 100
50 (server_version) - (int)((server_version) / 100) * 100
51/* return true if the given host is a UNIX domain socket */ 50/* return true if the given host is a UNIX domain socket */
52#define PSQL_IS_UNIX_DOMAIN_SOCKET(host) \ 51#define PSQL_IS_UNIX_DOMAIN_SOCKET(host) ((NULL == (host)) || ('\0' == *(host)) || ('/' == *(host)))
53 ((NULL == (host)) || ('\0' == *(host)) || ('/' == *(host)))
54/* return a 3-tuple identifying a host/port independent of the socket type */ 52/* return a 3-tuple identifying a host/port independent of the socket type */
55#define PSQL_SOCKET3(host, port) \ 53#define PSQL_SOCKET3(host, port) \
56 ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, \ 54 ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, PSQL_IS_UNIX_DOMAIN_SOCKET(host) ? "/.s.PGSQL." : ":", port
57 PSQL_IS_UNIX_DOMAIN_SOCKET (host) ? "/.s.PGSQL." : ":", \
58 port
59 55
60enum { 56enum {
61 DEFAULT_PORT = 5432, 57 DEFAULT_PORT = 5432,
@@ -63,33 +59,30 @@ enum {
63 DEFAULT_CRIT = 8 59 DEFAULT_CRIT = 8
64}; 60};
65 61
62static int process_arguments(int /*argc*/, char ** /*argv*/);
63static void print_help(void);
64static bool is_pg_logname(char * /*username*/);
65static int do_query(PGconn * /*conn*/, char * /*query*/);
66void print_usage(void);
67
68static char *pghost = NULL; /* host name of the backend server */
69static char *pgport = NULL; /* port of the backend server */
70static char *pgoptions = NULL;
71static char *pgtty = NULL;
72static char dbName[NAMEDATALEN] = DEFAULT_DB;
73static char *pguser = NULL;
74static char *pgpasswd = NULL;
75static char *pgparams = NULL;
76static double twarn = (double)DEFAULT_WARN;
77static double tcrit = (double)DEFAULT_CRIT;
78static char *pgquery = NULL;
79static char *pgqueryname = NULL;
80static char *query_warning = NULL;
81static char *query_critical = NULL;
82static thresholds *qthresholds = NULL;
83static int verbose = 0;
66 84
67
68int process_arguments (int, char **);
69int validate_arguments (void);
70void print_usage (void);
71void print_help (void);
72bool is_pg_logname (char *);
73int do_query (PGconn *, char *);
74
75char *pghost = NULL; /* host name of the backend server */
76char *pgport = NULL; /* port of the backend server */
77int default_port = DEFAULT_PORT;
78char *pgoptions = NULL;
79char *pgtty = NULL;
80char dbName[NAMEDATALEN] = DEFAULT_DB;
81char *pguser = NULL;
82char *pgpasswd = NULL;
83char *pgparams = NULL;
84double twarn = (double)DEFAULT_WARN;
85double tcrit = (double)DEFAULT_CRIT;
86char *pgquery = NULL;
87#define OPTID_QUERYNAME -1000 85#define OPTID_QUERYNAME -1000
88char *pgqueryname = NULL;
89char *query_warning = NULL;
90char *query_critical = NULL;
91thresholds *qthresholds = NULL;
92int verbose = 0;
93 86
94/****************************************************************************** 87/******************************************************************************
95 88
@@ -141,78 +134,67 @@ Please note that all tags must be lowercase to use the DocBook XML DTD.
141-@@ 134-@@
142******************************************************************************/ 135******************************************************************************/
143 136
144 137int main(int argc, char **argv) {
145 138 setlocale(LC_ALL, "");
146int 139 bindtextdomain(PACKAGE, LOCALEDIR);
147main (int argc, char **argv) 140 textdomain(PACKAGE);
148{
149 PGconn *conn;
150 char *conninfo = NULL;
151
152 struct timeval start_timeval;
153 struct timeval end_timeval;
154 double elapsed_time;
155 int status = STATE_UNKNOWN;
156 int query_status = STATE_UNKNOWN;
157 141
158 /* begin, by setting the parameters for a backend connection if the 142 /* begin, by setting the parameters for a backend connection if the
159 * parameters are null, then the system will try to use reasonable 143 * parameters are null, then the system will try to use reasonable
160 * defaults by looking up environment variables or, failing that, 144 * defaults by looking up environment variables or, failing that,
161 * using hardwired constants */ 145 * using hardwired constants */
162 146
163 pgoptions = NULL; /* special options to start up the backend server */ 147 pgoptions = NULL; /* special options to start up the backend server */
164 pgtty = NULL; /* debugging tty for the backend server */ 148 pgtty = NULL; /* debugging tty for the backend server */
165
166 setlocale (LC_ALL, "");
167 bindtextdomain (PACKAGE, LOCALEDIR);
168 textdomain (PACKAGE);
169 149
170 /* Parse extra opts if any */ 150 /* Parse extra opts if any */
171 argv=np_extra_opts (&argc, argv, progname); 151 argv = np_extra_opts(&argc, argv, progname);
172 152
173 if (process_arguments (argc, argv) == ERROR) 153 if (process_arguments(argc, argv) == ERROR)
174 usage4 (_("Could not parse arguments")); 154 usage4(_("Could not parse arguments"));
175 if (verbose > 2) 155 if (verbose > 2)
176 printf("Arguments initialized\n"); 156 printf("Arguments initialized\n");
177 157
178 /* Set signal handling and alarm */ 158 /* Set signal handling and alarm */
179 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { 159 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
180 usage4 (_("Cannot catch SIGALRM")); 160 usage4(_("Cannot catch SIGALRM"));
181 } 161 }
182 alarm (timeout_interval); 162 alarm(timeout_interval);
183 163
164 char *conninfo = NULL;
184 if (pgparams) 165 if (pgparams)
185 asprintf (&conninfo, "%s ", pgparams); 166 asprintf(&conninfo, "%s ", pgparams);
186 167
187 asprintf (&conninfo, "%sdbname = '%s'", conninfo ? conninfo : "", dbName); 168 asprintf(&conninfo, "%sdbname = '%s'", conninfo ? conninfo : "", dbName);
188 if (pghost) 169 if (pghost)
189 asprintf (&conninfo, "%s host = '%s'", conninfo, pghost); 170 asprintf(&conninfo, "%s host = '%s'", conninfo, pghost);
190 if (pgport) 171 if (pgport)
191 asprintf (&conninfo, "%s port = '%s'", conninfo, pgport); 172 asprintf(&conninfo, "%s port = '%s'", conninfo, pgport);
192 if (pgoptions) 173 if (pgoptions)
193 asprintf (&conninfo, "%s options = '%s'", conninfo, pgoptions); 174 asprintf(&conninfo, "%s options = '%s'", conninfo, pgoptions);
194 /* if (pgtty) -- ignored by PQconnectdb */ 175 /* if (pgtty) -- ignored by PQconnectdb */
195 if (pguser) 176 if (pguser)
196 asprintf (&conninfo, "%s user = '%s'", conninfo, pguser); 177 asprintf(&conninfo, "%s user = '%s'", conninfo, pguser);
197 178
198 if (verbose) /* do not include password (see right below) in output */ 179 if (verbose) /* do not include password (see right below) in output */
199 printf ("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, 180 printf("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, pgpasswd ? " password = <hidden>" : "");
200 pgpasswd ? " password = <hidden>" : "");
201 181
202 if (pgpasswd) 182 if (pgpasswd)
203 asprintf (&conninfo, "%s password = '%s'", conninfo, pgpasswd); 183 asprintf(&conninfo, "%s password = '%s'", conninfo, pgpasswd);
204 184
205 /* make a connection to the database */ 185 /* make a connection to the database */
206 gettimeofday (&start_timeval, NULL); 186 struct timeval start_timeval;
207 conn = PQconnectdb (conninfo); 187 gettimeofday(&start_timeval, NULL);
208 gettimeofday (&end_timeval, NULL); 188 PGconn *conn = PQconnectdb(conninfo);
189 struct timeval end_timeval;
190 gettimeofday(&end_timeval, NULL);
209 191
210 while (start_timeval.tv_usec > end_timeval.tv_usec) { 192 while (start_timeval.tv_usec > end_timeval.tv_usec) {
211 --end_timeval.tv_sec; 193 --end_timeval.tv_sec;
212 end_timeval.tv_usec += 1000000; 194 end_timeval.tv_usec += 1000000;
213 } 195 }
214 elapsed_time = (double)(end_timeval.tv_sec - start_timeval.tv_sec) 196 double elapsed_time =
215 + (double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0; 197 (double)(end_timeval.tv_sec - start_timeval.tv_sec) + (double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0;
216 198
217 if (verbose) 199 if (verbose)
218 printf("Time elapsed: %f\n", elapsed_time); 200 printf("Time elapsed: %f\n", elapsed_time);
@@ -220,152 +202,139 @@ main (int argc, char **argv)
220 /* check to see that the backend connection was successfully made */ 202 /* check to see that the backend connection was successfully made */
221 if (verbose) 203 if (verbose)
222 printf("Verifying connection\n"); 204 printf("Verifying connection\n");
223 if (PQstatus (conn) == CONNECTION_BAD) { 205 if (PQstatus(conn) == CONNECTION_BAD) {
224 printf (_("CRITICAL - no connection to '%s' (%s).\n"), 206 printf(_("CRITICAL - no connection to '%s' (%s).\n"), dbName, PQerrorMessage(conn));
225 dbName, PQerrorMessage (conn)); 207 PQfinish(conn);
226 PQfinish (conn);
227 return STATE_CRITICAL; 208 return STATE_CRITICAL;
228 } 209 }
229 else if (elapsed_time > tcrit) { 210
211 int status = STATE_UNKNOWN;
212 if (elapsed_time > tcrit) {
230 status = STATE_CRITICAL; 213 status = STATE_CRITICAL;
231 } 214 } else if (elapsed_time > twarn) {
232 else if (elapsed_time > twarn) {
233 status = STATE_WARNING; 215 status = STATE_WARNING;
234 } 216 } else {
235 else {
236 status = STATE_OK; 217 status = STATE_OK;
237 } 218 }
238 219
239 if (verbose) { 220 if (verbose) {
240 char *server_host = PQhost (conn); 221 char *server_host = PQhost(conn);
241 int server_version = PQserverVersion (conn); 222 int server_version = PQserverVersion(conn);
242 223
243 printf ("Successfully connected to database %s (user %s) " 224 printf("Successfully connected to database %s (user %s) "
244 "at server %s%s%s (server version: %d.%d.%d, " 225 "at server %s%s%s (server version: %d.%d.%d, "
245 "protocol version: %d, pid: %d)\n", 226 "protocol version: %d, pid: %d)\n",
246 PQdb (conn), PQuser (conn), 227 PQdb(conn), PQuser(conn), PSQL_SOCKET3(server_host, PQport(conn)), PSQL_SERVER_VERSION3(server_version),
247 PSQL_SOCKET3 (server_host, PQport (conn)), 228 PQprotocolVersion(conn), PQbackendPID(conn));
248 PSQL_SERVER_VERSION3 (server_version),
249 PQprotocolVersion (conn), PQbackendPID (conn));
250 } 229 }
251 230
252 printf (_(" %s - database %s (%f sec.)|%s\n"), 231 printf(_(" %s - database %s (%f sec.)|%s\n"), state_text(status), dbName, elapsed_time,
253 state_text(status), dbName, elapsed_time, 232 fperfdata("time", elapsed_time, "s", !!(twarn > 0.0), twarn, !!(tcrit > 0.0), tcrit, true, 0, false, 0));
254 fperfdata("time", elapsed_time, "s",
255 !!(twarn > 0.0), twarn, !!(tcrit > 0.0), tcrit, true, 0, false,0));
256 233
234 int query_status = STATE_UNKNOWN;
257 if (pgquery) 235 if (pgquery)
258 query_status = do_query (conn, pgquery); 236 query_status = do_query(conn, pgquery);
259 237
260 if (verbose) 238 if (verbose)
261 printf("Closing connection\n"); 239 printf("Closing connection\n");
262 PQfinish (conn); 240 PQfinish(conn);
263 return (pgquery && query_status > status) ? query_status : status; 241 return (pgquery && query_status > status) ? query_status : status;
264} 242}
265 243
266
267
268/* process command-line arguments */ 244/* process command-line arguments */
269int 245int process_arguments(int argc, char **argv) {
270process_arguments (int argc, char **argv) 246 static struct option longopts[] = {{"help", no_argument, 0, 'h'},
271{ 247 {"version", no_argument, 0, 'V'},
272 int c; 248 {"timeout", required_argument, 0, 't'},
273 249 {"critical", required_argument, 0, 'c'},
274 int option = 0; 250 {"warning", required_argument, 0, 'w'},
275 static struct option longopts[] = { 251 {"hostname", required_argument, 0, 'H'},
276 {"help", no_argument, 0, 'h'}, 252 {"logname", required_argument, 0, 'l'},
277 {"version", no_argument, 0, 'V'}, 253 {"password", required_argument, 0, 'p'},
278 {"timeout", required_argument, 0, 't'}, 254 {"authorization", required_argument, 0, 'a'},
279 {"critical", required_argument, 0, 'c'}, 255 {"port", required_argument, 0, 'P'},
280 {"warning", required_argument, 0, 'w'}, 256 {"database", required_argument, 0, 'd'},
281 {"hostname", required_argument, 0, 'H'}, 257 {"option", required_argument, 0, 'o'},
282 {"logname", required_argument, 0, 'l'}, 258 {"query", required_argument, 0, 'q'},
283 {"password", required_argument, 0, 'p'}, 259 {"queryname", required_argument, 0, OPTID_QUERYNAME},
284 {"authorization", required_argument, 0, 'a'}, 260 {"query_critical", required_argument, 0, 'C'},
285 {"port", required_argument, 0, 'P'}, 261 {"query_warning", required_argument, 0, 'W'},
286 {"database", required_argument, 0, 'd'}, 262 {"verbose", no_argument, 0, 'v'},
287 {"option", required_argument, 0, 'o'}, 263 {0, 0, 0, 0}};
288 {"query", required_argument, 0, 'q'}, 264
289 {"queryname", required_argument, 0, OPTID_QUERYNAME}, 265 while (true) {
290 {"query_critical", required_argument, 0, 'C'}, 266 int option = 0;
291 {"query_warning", required_argument, 0, 'W'}, 267 int option_char = getopt_long(argc, argv, "hVt:c:w:H:P:d:l:p:a:o:q:C:W:v", longopts, &option);
292 {"verbose", no_argument, 0, 'v'}, 268
293 {0, 0, 0, 0} 269 if (option_char == EOF)
294 };
295
296 while (1) {
297 c = getopt_long (argc, argv, "hVt:c:w:H:P:d:l:p:a:o:q:C:W:v",
298 longopts, &option);
299
300 if (c == EOF)
301 break; 270 break;
302 271
303 switch (c) { 272 switch (option_char) {
304 case '?': /* usage */ 273 case '?': /* usage */
305 usage5 (); 274 usage5();
306 case 'h': /* help */ 275 case 'h': /* help */
307 print_help (); 276 print_help();
308 exit (STATE_UNKNOWN); 277 exit(STATE_UNKNOWN);
309 case 'V': /* version */ 278 case 'V': /* version */
310 print_revision (progname, NP_VERSION); 279 print_revision(progname, NP_VERSION);
311 exit (STATE_UNKNOWN); 280 exit(STATE_UNKNOWN);
312 case 't': /* timeout period */ 281 case 't': /* timeout period */
313 if (!is_integer (optarg)) 282 if (!is_integer(optarg))
314 usage2 (_("Timeout interval must be a positive integer"), optarg); 283 usage2(_("Timeout interval must be a positive integer"), optarg);
315 else 284 else
316 timeout_interval = atoi (optarg); 285 timeout_interval = atoi(optarg);
317 break; 286 break;
318 case 'c': /* critical time threshold */ 287 case 'c': /* critical time threshold */
319 if (!is_nonnegative (optarg)) 288 if (!is_nonnegative(optarg))
320 usage2 (_("Critical threshold must be a positive integer"), optarg); 289 usage2(_("Critical threshold must be a positive integer"), optarg);
321 else 290 else
322 tcrit = strtod (optarg, NULL); 291 tcrit = strtod(optarg, NULL);
323 break; 292 break;
324 case 'w': /* warning time threshold */ 293 case 'w': /* warning time threshold */
325 if (!is_nonnegative (optarg)) 294 if (!is_nonnegative(optarg))
326 usage2 (_("Warning threshold must be a positive integer"), optarg); 295 usage2(_("Warning threshold must be a positive integer"), optarg);
327 else 296 else
328 twarn = strtod (optarg, NULL); 297 twarn = strtod(optarg, NULL);
329 break; 298 break;
330 case 'C': /* critical query threshold */ 299 case 'C': /* critical query threshold */
331 query_critical = optarg; 300 query_critical = optarg;
332 break; 301 break;
333 case 'W': /* warning query threshold */ 302 case 'W': /* warning query threshold */
334 query_warning = optarg; 303 query_warning = optarg;
335 break; 304 break;
336 case 'H': /* host */ 305 case 'H': /* host */
337 if ((*optarg != '/') && (!is_host (optarg))) 306 if ((*optarg != '/') && (!is_host(optarg)))
338 usage2 (_("Invalid hostname/address"), optarg); 307 usage2(_("Invalid hostname/address"), optarg);
339 else 308 else
340 pghost = optarg; 309 pghost = optarg;
341 break; 310 break;
342 case 'P': /* port */ 311 case 'P': /* port */
343 if (!is_integer (optarg)) 312 if (!is_integer(optarg))
344 usage2 (_("Port must be a positive integer"), optarg); 313 usage2(_("Port must be a positive integer"), optarg);
345 else 314 else
346 pgport = optarg; 315 pgport = optarg;
347 break; 316 break;
348 case 'd': /* database name */ 317 case 'd': /* database name */
349 if (strlen(optarg) >= NAMEDATALEN) { 318 if (strlen(optarg) >= NAMEDATALEN) {
350 usage2 (_("Database name exceeds the maximum length"), optarg); 319 usage2(_("Database name exceeds the maximum length"), optarg);
351 } 320 }
352 snprintf(dbName, NAMEDATALEN, "%s", optarg); 321 snprintf(dbName, NAMEDATALEN, "%s", optarg);
353 break; 322 break;
354 case 'l': /* login name */ 323 case 'l': /* login name */
355 if (!is_pg_logname (optarg)) 324 if (!is_pg_logname(optarg))
356 usage2 (_("User name is not valid"), optarg); 325 usage2(_("User name is not valid"), optarg);
357 else 326 else
358 pguser = optarg; 327 pguser = optarg;
359 break; 328 break;
360 case 'p': /* authentication password */ 329 case 'p': /* authentication password */
361 case 'a': 330 case 'a':
362 pgpasswd = optarg; 331 pgpasswd = optarg;
363 break; 332 break;
364 case 'o': 333 case 'o':
365 if (pgparams) 334 if (pgparams)
366 asprintf (&pgparams, "%s %s", pgparams, optarg); 335 asprintf(&pgparams, "%s %s", pgparams, optarg);
367 else 336 else
368 asprintf (&pgparams, "%s", optarg); 337 asprintf(&pgparams, "%s", optarg);
369 break; 338 break;
370 case 'q': 339 case 'q':
371 pgquery = optarg; 340 pgquery = optarg;
@@ -379,37 +348,8 @@ process_arguments (int argc, char **argv)
379 } 348 }
380 } 349 }
381 350
382 set_thresholds (&qthresholds, query_warning, query_critical); 351 set_thresholds(&qthresholds, query_warning, query_critical);
383
384 return validate_arguments ();
385}
386
387
388/******************************************************************************
389
390@@-
391<sect3>
392<title>validate_arguments</title>
393
394<para>&PROTO_validate_arguments;</para>
395
396<para>Given a database name, this function returns true if the string
397is a valid PostgreSQL database name, and returns false if it is
398not.</para>
399 352
400<para>Valid PostgreSQL database names are less than &NAMEDATALEN;
401characters long and consist of letters, numbers, and underscores. The
402first character cannot be a number, however.</para>
403
404</sect3>
405-@@
406******************************************************************************/
407
408
409
410int
411validate_arguments ()
412{
413 return OK; 353 return OK;
414} 354}
415 355
@@ -437,10 +377,8 @@ should be added.</para>
437-@@ 377-@@
438******************************************************************************/ 378******************************************************************************/
439 379
440 380bool is_pg_logname(char *username) {
441 381 if (strlen(username) > NAMEDATALEN - 1)
442bool is_pg_logname (char *username) {
443 if (strlen (username) > NAMEDATALEN - 1)
444 return (false); 382 return (false);
445 return (true); 383 return (true);
446} 384}
@@ -453,182 +391,155 @@ bool is_pg_logname (char *username) {
453-@@ 391-@@
454******************************************************************************/ 392******************************************************************************/
455 393
456 394void print_help(void) {
457
458void
459print_help (void)
460{
461 char *myport; 395 char *myport;
462 396
463 xasprintf (&myport, "%d", DEFAULT_PORT); 397 xasprintf(&myport, "%d", DEFAULT_PORT);
464 398
465 print_revision (progname, NP_VERSION); 399 print_revision(progname, NP_VERSION);
466 400
467 printf (COPYRIGHT, copyright, email); 401 printf(COPYRIGHT, copyright, email);
468 402
469 printf (_("Test whether a PostgreSQL Database is accepting connections.")); 403 printf(_("Test whether a PostgreSQL Database is accepting connections."));
470 404
471 printf ("\n\n"); 405 printf("\n\n");
472 406
473 print_usage (); 407 print_usage();
474 408
475 printf (UT_HELP_VRSN); 409 printf(UT_HELP_VRSN);
476 printf (UT_EXTRA_OPTS); 410 printf(UT_EXTRA_OPTS);
477 411
478 printf (UT_HOST_PORT, 'P', myport); 412 printf(UT_HOST_PORT, 'P', myport);
479 413
480 printf (" %s\n", "-d, --database=STRING"); 414 printf(" %s\n", "-d, --database=STRING");
481 printf (" %s", _("Database to check ")); 415 printf(" %s", _("Database to check "));
482 printf (_("(default: %s)\n"), DEFAULT_DB); 416 printf(_("(default: %s)\n"), DEFAULT_DB);
483 printf (" %s\n", "-l, --logname = STRING"); 417 printf(" %s\n", "-l, --logname = STRING");
484 printf (" %s\n", _("Login name of user")); 418 printf(" %s\n", _("Login name of user"));
485 printf (" %s\n", "-p, --password = STRING"); 419 printf(" %s\n", "-p, --password = STRING");
486 printf (" %s\n", _("Password (BIG SECURITY ISSUE)")); 420 printf(" %s\n", _("Password (BIG SECURITY ISSUE)"));
487 printf (" %s\n", "-o, --option = STRING"); 421 printf(" %s\n", "-o, --option = STRING");
488 printf (" %s\n", _("Connection parameters (keyword = value), see below")); 422 printf(" %s\n", _("Connection parameters (keyword = value), see below"));
489 423
490 printf (UT_WARN_CRIT); 424 printf(UT_WARN_CRIT);
491 425
492 printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 426 printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
493 427
494 printf (" %s\n", "-q, --query=STRING"); 428 printf(" %s\n", "-q, --query=STRING");
495 printf (" %s\n", _("SQL query to run. Only first column in first row will be read")); 429 printf(" %s\n", _("SQL query to run. Only first column in first row will be read"));
496 printf (" %s\n", "--queryname=STRING"); 430 printf(" %s\n", "--queryname=STRING");
497 printf (" %s\n", _("A name for the query, this string is used instead of the query")); 431 printf(" %s\n", _("A name for the query, this string is used instead of the query"));
498 printf (" %s\n", _("in the long output of the plugin")); 432 printf(" %s\n", _("in the long output of the plugin"));
499 printf (" %s\n", "-W, --query-warning=RANGE"); 433 printf(" %s\n", "-W, --query-warning=RANGE");
500 printf (" %s\n", _("SQL query value to result in warning status (double)")); 434 printf(" %s\n", _("SQL query value to result in warning status (double)"));
501 printf (" %s\n", "-C, --query-critical=RANGE"); 435 printf(" %s\n", "-C, --query-critical=RANGE");
502 printf (" %s\n", _("SQL query value to result in critical status (double)")); 436 printf(" %s\n", _("SQL query value to result in critical status (double)"));
503 437
504 printf (UT_VERBOSE); 438 printf(UT_VERBOSE);
505 439
506 printf ("\n"); 440 printf("\n");
507 printf (" %s\n", _("All parameters are optional.")); 441 printf(" %s\n", _("All parameters are optional."));
508 printf (" %s\n", _("This plugin tests a PostgreSQL DBMS to determine whether it is active and")); 442 printf(" %s\n", _("This plugin tests a PostgreSQL DBMS to determine whether it is active and"));
509 printf (" %s\n", _("accepting queries. In its current operation, it simply connects to the")); 443 printf(" %s\n", _("accepting queries. In its current operation, it simply connects to the"));
510 printf (" %s\n", _("specified database, and then disconnects. If no database is specified, it")); 444 printf(" %s\n", _("specified database, and then disconnects. If no database is specified, it"));
511 printf (" %s\n", _("connects to the template1 database, which is present in every functioning")); 445 printf(" %s\n", _("connects to the template1 database, which is present in every functioning"));
512 printf (" %s\n\n", _("PostgreSQL DBMS.")); 446 printf(" %s\n\n", _("PostgreSQL DBMS."));
513 447
514 printf (" %s\n", _("If a query is specified using the -q option, it will be executed after")); 448 printf(" %s\n", _("If a query is specified using the -q option, it will be executed after"));
515 printf (" %s\n", _("connecting to the server. The result from the query has to be numeric.")); 449 printf(" %s\n", _("connecting to the server. The result from the query has to be numeric."));
516 printf (" %s\n", _("Multiple SQL commands, separated by semicolon, are allowed but the result ")); 450 printf(" %s\n", _("Multiple SQL commands, separated by semicolon, are allowed but the result "));
517 printf (" %s\n", _("of the last command is taken into account only. The value of the first")); 451 printf(" %s\n", _("of the last command is taken into account only. The value of the first"));
518 printf (" %s\n", _("column in the first row is used as the check result. If a second column is")); 452 printf(" %s\n", _("column in the first row is used as the check result. If a second column is"));
519 printf (" %s\n", _("present in the result set, this is added to the plugin output with a")); 453 printf(" %s\n", _("present in the result set, this is added to the plugin output with a"));
520 printf (" %s\n", _("prefix of \"Extra Info:\". This information can be displayed in the system")); 454 printf(" %s\n", _("prefix of \"Extra Info:\". This information can be displayed in the system"));
521 printf (" %s\n\n", _("executing the plugin.")); 455 printf(" %s\n\n", _("executing the plugin."));
522 456
523 printf (" %s\n", _("See the chapter \"Monitoring Database Activity\" of the PostgreSQL manual")); 457 printf(" %s\n", _("See the chapter \"Monitoring Database Activity\" of the PostgreSQL manual"));
524 printf (" %s\n\n", _("for details about how to access internal statistics of the database server.")); 458 printf(" %s\n\n", _("for details about how to access internal statistics of the database server."));
525 459
526 printf (" %s\n", _("For a list of available connection parameters which may be used with the -o")); 460 printf(" %s\n", _("For a list of available connection parameters which may be used with the -o"));
527 printf (" %s\n", _("command line option, see the documentation for PQconnectdb() in the chapter")); 461 printf(" %s\n", _("command line option, see the documentation for PQconnectdb() in the chapter"));
528 printf (" %s\n", _("\"libpq - C Library\" of the PostgreSQL manual. For example, this may be")); 462 printf(" %s\n", _("\"libpq - C Library\" of the PostgreSQL manual. For example, this may be"));
529 printf (" %s\n", _("used to specify a service name in pg_service.conf to be used for additional")); 463 printf(" %s\n", _("used to specify a service name in pg_service.conf to be used for additional"));
530 printf (" %s\n", _("connection parameters: -o 'service=<name>' or to specify the SSL mode:")); 464 printf(" %s\n", _("connection parameters: -o 'service=<name>' or to specify the SSL mode:"));
531 printf (" %s\n\n", _("-o 'sslmode=require'.")); 465 printf(" %s\n\n", _("-o 'sslmode=require'."));
532 466
533 printf (" %s\n", _("The plugin will connect to a local postmaster if no host is specified. To")); 467 printf(" %s\n", _("The plugin will connect to a local postmaster if no host is specified. To"));
534 printf (" %s\n", _("connect to a remote host, be sure that the remote postmaster accepts TCP/IP")); 468 printf(" %s\n", _("connect to a remote host, be sure that the remote postmaster accepts TCP/IP"));
535 printf (" %s\n\n", _("connections (start the postmaster with the -i option).")); 469 printf(" %s\n\n", _("connections (start the postmaster with the -i option)."));
536 470
537 printf (" %s\n", _("Typically, the monitoring user (unless the --logname option is used) should be")); 471 printf(" %s\n", _("Typically, the monitoring user (unless the --logname option is used) should be"));
538 printf (" %s\n", _("able to connect to the database without a password. The plugin can also send")); 472 printf(" %s\n", _("able to connect to the database without a password. The plugin can also send"));
539 printf (" %s\n", _("a password, but no effort is made to obscure or encrypt the password.")); 473 printf(" %s\n", _("a password, but no effort is made to obscure or encrypt the password."));
540 474
541 printf (UT_SUPPORT); 475 printf(UT_SUPPORT);
542} 476}
543 477
544 478void print_usage(void) {
545 479 printf("%s\n", _("Usage:"));
546void 480 printf("%s [-H <host>] [-P <port>] [-c <critical time>] [-w <warning time>]\n", progname);
547print_usage (void) 481 printf(" [-t <timeout>] [-d <database>] [-l <logname>] [-p <password>]\n"
548{ 482 "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n");
549 printf ("%s\n", _("Usage:"));
550 printf ("%s [-H <host>] [-P <port>] [-c <critical time>] [-w <warning time>]\n", progname);
551 printf (" [-t <timeout>] [-d <database>] [-l <logname>] [-p <password>]\n"
552 "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n");
553} 483}
554 484
555int 485int do_query(PGconn *conn, char *query) {
556do_query (PGconn *conn, char *query)
557{
558 PGresult *res;
559
560 char *val_str;
561 char *extra_info;
562 double value;
563
564 char *endptr = NULL;
565
566 int my_status = STATE_UNKNOWN;
567
568 if (verbose) 486 if (verbose)
569 printf ("Executing SQL query \"%s\".\n", query); 487 printf("Executing SQL query \"%s\".\n", query);
570 res = PQexec (conn, query); 488 PGresult *res = PQexec(conn, query);
571 489
572 if (PGRES_TUPLES_OK != PQresultStatus (res)) { 490 if (PGRES_TUPLES_OK != PQresultStatus(res)) {
573 printf (_("QUERY %s - %s: %s.\n"), _("CRITICAL"), _("Error with query"), 491 printf(_("QUERY %s - %s: %s.\n"), _("CRITICAL"), _("Error with query"), PQerrorMessage(conn));
574 PQerrorMessage (conn));
575 return STATE_CRITICAL; 492 return STATE_CRITICAL;
576 } 493 }
577 494
578 if (PQntuples (res) < 1) { 495 if (PQntuples(res) < 1) {
579 printf ("QUERY %s - %s.\n", _("WARNING"), _("No rows returned")); 496 printf("QUERY %s - %s.\n", _("WARNING"), _("No rows returned"));
580 return STATE_WARNING; 497 return STATE_WARNING;
581 } 498 }
582 499
583 if (PQnfields (res) < 1) { 500 if (PQnfields(res) < 1) {
584 printf ("QUERY %s - %s.\n", _("WARNING"), _("No columns returned")); 501 printf("QUERY %s - %s.\n", _("WARNING"), _("No columns returned"));
585 return STATE_WARNING; 502 return STATE_WARNING;
586 } 503 }
587 504
588 val_str = PQgetvalue (res, 0, 0); 505 char *val_str = PQgetvalue(res, 0, 0);
589 if (! val_str) { 506 if (!val_str) {
590 printf ("QUERY %s - %s.\n", _("CRITICAL"), _("No data returned")); 507 printf("QUERY %s - %s.\n", _("CRITICAL"), _("No data returned"));
591 return STATE_CRITICAL; 508 return STATE_CRITICAL;
592 } 509 }
593 510
594 value = strtod (val_str, &endptr); 511 char *endptr = NULL;
512 double value = strtod(val_str, &endptr);
595 if (verbose) 513 if (verbose)
596 printf ("Query result: %f\n", value); 514 printf("Query result: %f\n", value);
597 515
598 if (endptr == val_str) { 516 if (endptr == val_str) {
599 printf ("QUERY %s - %s: %s\n", _("CRITICAL"), _("Is not a numeric"), val_str); 517 printf("QUERY %s - %s: %s\n", _("CRITICAL"), _("Is not a numeric"), val_str);
600 return STATE_CRITICAL; 518 return STATE_CRITICAL;
601 } 519 }
602 else if ((endptr != NULL) && (*endptr != '\0')) { 520
521 if ((endptr != NULL) && (*endptr != '\0')) {
603 if (verbose) 522 if (verbose)
604 printf ("Garbage after value: %s.\n", endptr); 523 printf("Garbage after value: %s.\n", endptr);
605 } 524 }
606 525
607 my_status = get_status (value, qthresholds); 526 int my_status = get_status(value, qthresholds);
608 printf ("QUERY %s - ", 527 printf("QUERY %s - ", (my_status == STATE_OK) ? _("OK")
609 (my_status == STATE_OK) 528 : (my_status == STATE_WARNING) ? _("WARNING")
610 ? _("OK") 529 : (my_status == STATE_CRITICAL) ? _("CRITICAL")
611 : (my_status == STATE_WARNING) 530 : _("UNKNOWN"));
612 ? _("WARNING") 531 if (pgqueryname) {
613 : (my_status == STATE_CRITICAL) 532 printf(_("%s returned %f"), pgqueryname, value);
614 ? _("CRITICAL") 533 } else {
615 : _("UNKNOWN")); 534 printf(_("'%s' returned %f"), query, value);
616 if(pgqueryname) {
617 printf (_("%s returned %f"), pgqueryname, value);
618 }
619 else {
620 printf (_("'%s' returned %f"), query, value);
621 } 535 }
622 536
623 printf ("|query=%f;%s;%s;;\n", value, 537 printf("|query=%f;%s;%s;;\n", value, query_warning ? query_warning : "", query_critical ? query_critical : "");
624 query_warning ? query_warning : "", 538 if (PQnfields(res) > 1) {
625 query_critical ? query_critical : ""); 539 char *extra_info = PQgetvalue(res, 0, 1);
626 if (PQnfields (res) > 1) {
627 extra_info = PQgetvalue (res, 0, 1);
628 if (extra_info != NULL) { 540 if (extra_info != NULL) {
629 printf ("Extra Info: %s\n", extra_info); 541 printf("Extra Info: %s\n", extra_info);
630 } 542 }
631 } 543 }
632 return my_status; 544 return my_status;
633} 545}
634