summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/Makefile.am4
-rw-r--r--plugins/check_nagios.c168
-rw-r--r--plugins/check_nagios.d/config.h19
-rw-r--r--plugins/check_nt.c527
-rw-r--r--plugins/check_nt.d/config.h53
-rw-r--r--plugins/check_ntp_time.c210
-rw-r--r--plugins/check_ntp_time.d/config.h28
-rw-r--r--plugins/check_pgsql.c216
-rw-r--r--plugins/check_pgsql.d/config.h61
9 files changed, 747 insertions, 539 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 305924bf..9ea6e85e 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -53,16 +53,20 @@ EXTRA_DIST = t \
53 check_ldap.d \ 53 check_ldap.d \
54 check_hpjd.d \ 54 check_hpjd.d \
55 check_game.d \ 55 check_game.d \
56 check_nagios.d \
56 check_dbi.d \ 57 check_dbi.d \
57 check_ssh.d \ 58 check_ssh.d \
59 check_nt.d \
58 check_dns.d \ 60 check_dns.d \
59 check_mrtgtraf.d \ 61 check_mrtgtraf.d \
60 check_mysql_query.d \ 62 check_mysql_query.d \
61 check_mrtg.d \ 63 check_mrtg.d \
62 check_apt.d \ 64 check_apt.d \
65 check_pgsql.d \
63 check_by_ssh.d \ 66 check_by_ssh.d \
64 check_smtp.d \ 67 check_smtp.d \
65 check_mysql.d \ 68 check_mysql.d \
69 check_ntp_time.d \
66 check_dig.d \ 70 check_dig.d \
67 check_cluster.d \ 71 check_cluster.d \
68 check_fping.d 72 check_fping.d
diff --git a/plugins/check_nagios.c b/plugins/check_nagios.c
index 48629be3..a46dc1ed 100644
--- a/plugins/check_nagios.c
+++ b/plugins/check_nagios.c
@@ -39,47 +39,20 @@ const char *email = "devel@monitoring-plugins.org";
39#include "common.h" 39#include "common.h"
40#include "runcmd.h" 40#include "runcmd.h"
41#include "utils.h" 41#include "utils.h"
42 42#include "states.h"
43static int process_arguments(int /*argc*/, char ** /*argv*/); 43#include "check_nagios.d/config.h"
44
45typedef struct {
46 int errorcode;
47 check_nagios_config config;
48} check_nagios_config_wrapper;
49static check_nagios_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
44static void print_help(void); 50static void print_help(void);
45void print_usage(void); 51void print_usage(void);
46 52
47static char *status_log = NULL;
48static char *process_string = NULL;
49static int expire_minutes = 0;
50
51static int verbose = 0; 53static int verbose = 0;
52 54
53int main(int argc, char **argv) { 55int main(int argc, char **argv) {
54 int result = STATE_UNKNOWN;
55 char input_buffer[MAX_INPUT_BUFFER];
56 unsigned long latest_entry_time = 0L;
57 unsigned long temp_entry_time = 0L;
58 int proc_entries = 0;
59 time_t current_time;
60 char *temp_ptr;
61 FILE *fp;
62 int procuid = 0;
63 int procpid = 0;
64 int procppid = 0;
65 int procvsz = 0;
66 int procrss = 0;
67 float procpcpu = 0;
68 char procstat[8];
69#ifdef PS_USES_PROCETIME
70 char procetime[MAX_INPUT_BUFFER];
71#endif /* PS_USES_PROCETIME */
72 char procprog[MAX_INPUT_BUFFER];
73 char *procargs;
74 int pos;
75 int cols;
76 int expected_cols = PS_COLS - 1;
77 const char *zombie = "Z";
78 char *temp_string;
79 output chld_out;
80 output chld_err;
81 size_t i;
82
83 setlocale(LC_ALL, ""); 56 setlocale(LC_ALL, "");
84 bindtextdomain(PACKAGE, LOCALEDIR); 57 bindtextdomain(PACKAGE, LOCALEDIR);
85 textdomain(PACKAGE); 58 textdomain(PACKAGE);
@@ -87,8 +60,13 @@ int main(int argc, char **argv) {
87 /* Parse extra opts if any */ 60 /* Parse extra opts if any */
88 argv = np_extra_opts(&argc, argv, progname); 61 argv = np_extra_opts(&argc, argv, progname);
89 62
90 if (process_arguments(argc, argv) == ERROR) 63 check_nagios_config_wrapper tmp_config = process_arguments(argc, argv);
64
65 if (tmp_config.errorcode == ERROR) {
91 usage_va(_("Could not parse arguments")); 66 usage_va(_("Could not parse arguments"));
67 }
68
69 const check_nagios_config config = tmp_config.config;
92 70
93 /* Set signal handling and alarm timeout */ 71 /* Set signal handling and alarm timeout */
94 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) { 72 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
@@ -99,13 +77,17 @@ int main(int argc, char **argv) {
99 alarm(timeout_interval); 77 alarm(timeout_interval);
100 78
101 /* open the status log */ 79 /* open the status log */
102 fp = fopen(status_log, "r"); 80 FILE *log_file = fopen(config.status_log, "r");
103 if (fp == NULL) { 81 if (log_file == NULL) {
104 die(STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot open status log for reading!")); 82 die(STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot open status log for reading!"));
105 } 83 }
106 84
85 unsigned long latest_entry_time = 0L;
86 unsigned long temp_entry_time = 0L;
87 char input_buffer[MAX_INPUT_BUFFER];
88 char *temp_ptr;
107 /* get the date/time of the last item updated in the log */ 89 /* get the date/time of the last item updated in the log */
108 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, fp)) { 90 while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, log_file)) {
109 if ((temp_ptr = strstr(input_buffer, "created=")) != NULL) { 91 if ((temp_ptr = strstr(input_buffer, "created=")) != NULL) {
110 temp_entry_time = strtoul(temp_ptr + 8, NULL, 10); 92 temp_entry_time = strtoul(temp_ptr + 8, NULL, 10);
111 latest_entry_time = temp_entry_time; 93 latest_entry_time = temp_entry_time;
@@ -113,22 +95,44 @@ int main(int argc, char **argv) {
113 } 95 }
114 if ((temp_ptr = strtok(input_buffer, "]")) != NULL) { 96 if ((temp_ptr = strtok(input_buffer, "]")) != NULL) {
115 temp_entry_time = strtoul(temp_ptr + 1, NULL, 10); 97 temp_entry_time = strtoul(temp_ptr + 1, NULL, 10);
116 if (temp_entry_time > latest_entry_time) 98 if (temp_entry_time > latest_entry_time) {
117 latest_entry_time = temp_entry_time; 99 latest_entry_time = temp_entry_time;
100 }
118 } 101 }
119 } 102 }
120 fclose(fp); 103 fclose(log_file);
121 104
122 if (verbose >= 2) 105 if (verbose >= 2) {
123 printf("command: %s\n", PS_COMMAND); 106 printf("command: %s\n", PS_COMMAND);
107 }
124 108
125 /* run the command to check for the Nagios process.. */ 109 /* run the command to check for the Nagios process.. */
126 if ((result = np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0)) != 0) 110 mp_state_enum result = STATE_UNKNOWN;
111 output chld_out;
112 output chld_err;
113 if ((result = np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0)) != 0) {
127 result = STATE_WARNING; 114 result = STATE_WARNING;
115 }
128 116
117 int procuid = 0;
118 int procpid = 0;
119 int procppid = 0;
120 int procvsz = 0;
121 int procrss = 0;
122 int proc_entries = 0;
123 float procpcpu = 0;
124 char procstat[8];
125 char procprog[MAX_INPUT_BUFFER];
126 char *procargs;
127#ifdef PS_USES_PROCETIME
128 char procetime[MAX_INPUT_BUFFER];
129#endif /* PS_USES_PROCETIME */
130 int pos;
131 int expected_cols = PS_COLS - 1;
132 const char *zombie = "Z";
129 /* count the number of matching Nagios processes... */ 133 /* count the number of matching Nagios processes... */
130 for (i = 0; i < chld_out.lines; i++) { 134 for (size_t i = 0; i < chld_out.lines; i++) {
131 cols = sscanf(chld_out.line[i], PS_FORMAT, PS_VARLIST); 135 int cols = sscanf(chld_out.line[i], PS_FORMAT, PS_VARLIST);
132 /* Zombie processes do not give a procprog command */ 136 /* Zombie processes do not give a procprog command */
133 if (cols == (expected_cols - 1) && strstr(procstat, zombie)) { 137 if (cols == (expected_cols - 1) && strstr(procstat, zombie)) {
134 cols = expected_cols; 138 cols = expected_cols;
@@ -142,14 +146,14 @@ int main(int argc, char **argv) {
142 strip(procargs); 146 strip(procargs);
143 147
144 /* Some ps return full pathname for command. This removes path */ 148 /* Some ps return full pathname for command. This removes path */
145 temp_string = strtok((char *)procprog, "/"); 149 char *temp_string = strtok((char *)procprog, "/");
146 while (temp_string) { 150 while (temp_string) {
147 strcpy(procprog, temp_string); 151 strcpy(procprog, temp_string);
148 temp_string = strtok(NULL, "/"); 152 temp_string = strtok(NULL, "/");
149 } 153 }
150 154
151 /* May get empty procargs */ 155 /* May get empty procargs */
152 if (!strstr(procargs, argv[0]) && strstr(procargs, process_string) && strcmp(procargs, "")) { 156 if (!strstr(procargs, argv[0]) && strstr(procargs, config.process_string) && strcmp(procargs, "")) {
153 proc_entries++; 157 proc_entries++;
154 if (verbose >= 2) { 158 if (verbose >= 2) {
155 printf(_("Found process: %s %s\n"), procprog, procargs); 159 printf(_("Found process: %s %s\n"), procprog, procargs);
@@ -159,8 +163,9 @@ int main(int argc, char **argv) {
159 } 163 }
160 164
161 /* If we get anything on stderr, at least set warning */ 165 /* If we get anything on stderr, at least set warning */
162 if (chld_err.buflen) 166 if (chld_err.buflen) {
163 result = max_state(result, STATE_WARNING); 167 result = max_state(result, STATE_WARNING);
168 }
164 169
165 /* reset the alarm handler */ 170 /* reset the alarm handler */
166 alarm(0); 171 alarm(0);
@@ -173,8 +178,9 @@ int main(int argc, char **argv) {
173 die(STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot parse Nagios log file for valid time")); 178 die(STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot parse Nagios log file for valid time"));
174 } 179 }
175 180
181 time_t current_time;
176 time(&current_time); 182 time(&current_time);
177 if ((int)(current_time - latest_entry_time) > (expire_minutes * 60)) { 183 if ((int)(current_time - latest_entry_time) > (config.expire_minutes * 60)) {
178 result = STATE_WARNING; 184 result = STATE_WARNING;
179 } else { 185 } else {
180 result = STATE_OK; 186 result = STATE_OK;
@@ -187,39 +193,45 @@ int main(int argc, char **argv) {
187 (int)(current_time - latest_entry_time)); 193 (int)(current_time - latest_entry_time));
188 printf("\n"); 194 printf("\n");
189 195
190 return result; 196 exit(result);
191} 197}
192 198
193/* process command-line arguments */ 199/* process command-line arguments */
194int process_arguments(int argc, char **argv) { 200check_nagios_config_wrapper process_arguments(int argc, char **argv) {
195 int c;
196
197 int option = 0;
198 static struct option longopts[] = {{"filename", required_argument, 0, 'F'}, {"expires", required_argument, 0, 'e'}, 201 static struct option longopts[] = {{"filename", required_argument, 0, 'F'}, {"expires", required_argument, 0, 'e'},
199 {"command", required_argument, 0, 'C'}, {"timeout", optional_argument, 0, 't'}, 202 {"command", required_argument, 0, 'C'}, {"timeout", optional_argument, 0, 't'},
200 {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, 203 {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'},
201 {"verbose", no_argument, 0, 'v'}, {0, 0, 0, 0}}; 204 {"verbose", no_argument, 0, 'v'}, {0, 0, 0, 0}};
202 205
203 if (argc < 2) 206 check_nagios_config_wrapper result = {
204 return ERROR; 207 .errorcode = OK,
208 .config = check_nagios_config_init(),
209 };
210 if (argc < 2) {
211 result.errorcode = ERROR;
212 return result;
213 }
205 214
206 if (!is_option(argv[1])) { 215 if (!is_option(argv[1])) {
207 status_log = argv[1]; 216 result.config.status_log = argv[1];
208 if (is_intnonneg(argv[2])) 217 if (is_intnonneg(argv[2])) {
209 expire_minutes = atoi(argv[2]); 218 result.config.expire_minutes = atoi(argv[2]);
210 else 219 } else {
211 die(STATE_UNKNOWN, _("Expiration time must be an integer (seconds)\n")); 220 die(STATE_UNKNOWN, _("Expiration time must be an integer (seconds)\n"));
212 process_string = argv[3]; 221 }
213 return OK; 222 result.config.process_string = argv[3];
223 return result;
214 } 224 }
215 225
216 while (1) { 226 int option = 0;
217 c = getopt_long(argc, argv, "+hVvF:C:e:t:", longopts, &option); 227 while (true) {
228 int option_index = getopt_long(argc, argv, "+hVvF:C:e:t:", longopts, &option);
218 229
219 if (c == -1 || c == EOF || c == 1) 230 if (option_index == -1 || option_index == EOF || option_index == 1) {
220 break; 231 break;
232 }
221 233
222 switch (c) { 234 switch (option_index) {
223 case 'h': /* help */ 235 case 'h': /* help */
224 print_help(); 236 print_help();
225 exit(STATE_UNKNOWN); 237 exit(STATE_UNKNOWN);
@@ -227,22 +239,24 @@ int process_arguments(int argc, char **argv) {
227 print_revision(progname, NP_VERSION); 239 print_revision(progname, NP_VERSION);
228 exit(STATE_UNKNOWN); 240 exit(STATE_UNKNOWN);
229 case 'F': /* status log */ 241 case 'F': /* status log */
230 status_log = optarg; 242 result.config.status_log = optarg;
231 break; 243 break;
232 case 'C': /* command */ 244 case 'C': /* command */
233 process_string = optarg; 245 result.config.process_string = optarg;
234 break; 246 break;
235 case 'e': /* expiry time */ 247 case 'e': /* expiry time */
236 if (is_intnonneg(optarg)) 248 if (is_intnonneg(optarg)) {
237 expire_minutes = atoi(optarg); 249 result.config.expire_minutes = atoi(optarg);
238 else 250 } else {
239 die(STATE_UNKNOWN, _("Expiration time must be an integer (seconds)\n")); 251 die(STATE_UNKNOWN, _("Expiration time must be an integer (seconds)\n"));
252 }
240 break; 253 break;
241 case 't': /* timeout */ 254 case 't': /* timeout */
242 if (is_intnonneg(optarg)) 255 if (is_intnonneg(optarg)) {
243 timeout_interval = atoi(optarg); 256 timeout_interval = atoi(optarg);
244 else 257 } else {
245 die(STATE_UNKNOWN, _("Timeout must be an integer (seconds)\n")); 258 die(STATE_UNKNOWN, _("Timeout must be an integer (seconds)\n"));
259 }
246 break; 260 break;
247 case 'v': 261 case 'v':
248 verbose++; 262 verbose++;
@@ -252,13 +266,15 @@ int process_arguments(int argc, char **argv) {
252 } 266 }
253 } 267 }
254 268
255 if (status_log == NULL) 269 if (result.config.status_log == NULL) {
256 die(STATE_UNKNOWN, _("You must provide the status_log\n")); 270 die(STATE_UNKNOWN, _("You must provide the status_log\n"));
271 }
257 272
258 if (process_string == NULL) 273 if (result.config.process_string == NULL) {
259 die(STATE_UNKNOWN, _("You must provide a process string\n")); 274 die(STATE_UNKNOWN, _("You must provide a process string\n"));
275 }
260 276
261 return OK; 277 return result;
262} 278}
263 279
264void print_help(void) { 280void print_help(void) {
diff --git a/plugins/check_nagios.d/config.h b/plugins/check_nagios.d/config.h
new file mode 100644
index 00000000..efe139f9
--- /dev/null
+++ b/plugins/check_nagios.d/config.h
@@ -0,0 +1,19 @@
1#pragma once
2
3#include "../../config.h"
4#include <stddef.h>
5
6typedef struct {
7 char *status_log;
8 char *process_string;
9 int expire_minutes;
10} check_nagios_config;
11
12check_nagios_config check_nagios_config_init() {
13 check_nagios_config tmp = {
14 .status_log = NULL,
15 .process_string = NULL,
16 .expire_minutes = 0,
17 };
18 return tmp;
19}
diff --git a/plugins/check_nt.c b/plugins/check_nt.c
index dec0b668..7dd23e5c 100644
--- a/plugins/check_nt.c
+++ b/plugins/check_nt.c
@@ -13,7 +13,7 @@
13 * This plugin collects data from the NSClient service running on a 13 * This plugin collects data from the NSClient service running on a
14 * Windows NT/2000/XP/2003 server. 14 * Windows NT/2000/XP/2003 server.
15 * This plugin requires NSClient software to run on NT 15 * This plugin requires NSClient software to run on NT
16 * (http://nsclient.ready2run.nl/) 16 * (https://nsclient.org/)
17 * 17 *
18 * 18 *
19 * This program is free software: you can redistribute it and/or modify 19 * This program is free software: you can redistribute it and/or modify
@@ -39,82 +39,28 @@ const char *email = "devel@monitoring-plugins.org";
39#include "common.h" 39#include "common.h"
40#include "netutils.h" 40#include "netutils.h"
41#include "utils.h" 41#include "utils.h"
42 42#include "check_nt.d/config.h"
43enum checkvars {
44 CHECK_NONE,
45 CHECK_CLIENTVERSION,
46 CHECK_CPULOAD,
47 CHECK_UPTIME,
48 CHECK_USEDDISKSPACE,
49 CHECK_SERVICESTATE,
50 CHECK_PROCSTATE,
51 CHECK_MEMUSE,
52 CHECK_COUNTER,
53 CHECK_FILEAGE,
54 CHECK_INSTANCES
55};
56 43
57enum { 44enum {
58 MAX_VALUE_LIST = 30, 45 MAX_VALUE_LIST = 30,
59 PORT = 1248
60}; 46};
61 47
62static char *server_address = NULL;
63static int server_port = PORT;
64static char *value_list = NULL;
65static char *req_password = NULL;
66static unsigned long lvalue_list[MAX_VALUE_LIST];
67static unsigned long warning_value = 0L;
68static unsigned long critical_value = 0L;
69static bool check_warning_value = false;
70static bool check_critical_value = false;
71static enum checkvars vars_to_check = CHECK_NONE;
72static bool show_all = false;
73
74static char recv_buffer[MAX_INPUT_BUFFER]; 48static char recv_buffer[MAX_INPUT_BUFFER];
75 49
76static void fetch_data(const char *address, int port, const char *sendb); 50static void fetch_data(const char *address, int port, const char *sendb);
77static int process_arguments(int /*argc*/, char ** /*argv*/); 51
52typedef struct {
53 int errorcode;
54 check_nt_config config;
55} check_nt_config_wrapper;
56static check_nt_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
57
78static void preparelist(char *string); 58static void preparelist(char *string);
79static bool strtoularray(unsigned long *array, char *string, const char *delim); 59static bool strtoularray(unsigned long *array, char *string, const char *delim);
80static void print_help(void); 60static void print_help(void);
81void print_usage(void); 61void print_usage(void);
82 62
83int main(int argc, char **argv) { 63int main(int argc, char **argv) {
84
85 /* should be int result = STATE_UNKNOWN; */
86
87 int return_code = STATE_UNKNOWN;
88 char *send_buffer = NULL;
89 char *output_message = NULL;
90 char *perfdata = NULL;
91 char *temp_string = NULL;
92 char *temp_string_perf = NULL;
93 char *description = NULL, *counter_unit = NULL;
94 char *minval = NULL, *maxval = NULL, *errcvt = NULL;
95 char *fds = NULL, *tds = NULL;
96 char *numstr;
97
98 double total_disk_space = 0;
99 double free_disk_space = 0;
100 double percent_used_space = 0;
101 double warning_used_space = 0;
102 double critical_used_space = 0;
103 double mem_commitLimit = 0;
104 double mem_commitByte = 0;
105 double fminval = 0, fmaxval = 0;
106 unsigned long utilization;
107 unsigned long uptime;
108 unsigned long age_in_minutes;
109 double counter_value = 0.0;
110 int offset = 0;
111 int updays = 0;
112 int uphours = 0;
113 int upminutes = 0;
114
115 bool isPercent = false;
116 bool allRight = false;
117
118 setlocale(LC_ALL, ""); 64 setlocale(LC_ALL, "");
119 bindtextdomain(PACKAGE, LOCALEDIR); 65 bindtextdomain(PACKAGE, LOCALEDIR);
120 textdomain(PACKAGE); 66 textdomain(PACKAGE);
@@ -122,8 +68,12 @@ int main(int argc, char **argv) {
122 /* Parse extra opts if any */ 68 /* Parse extra opts if any */
123 argv = np_extra_opts(&argc, argv, progname); 69 argv = np_extra_opts(&argc, argv, progname);
124 70
125 if (process_arguments(argc, argv) == ERROR) 71 check_nt_config_wrapper tmp_config = process_arguments(argc, argv);
72 if (tmp_config.errorcode == ERROR) {
126 usage4(_("Could not parse arguments")); 73 usage4(_("Could not parse arguments"));
74 }
75
76 const check_nt_config config = tmp_config.config;
127 77
128 /* initialize alarm signal handling */ 78 /* initialize alarm signal handling */
129 signal(SIGALRM, socket_timeout_alarm_handler); 79 signal(SIGALRM, socket_timeout_alarm_handler);
@@ -131,49 +81,57 @@ int main(int argc, char **argv) {
131 /* set socket timeout */ 81 /* set socket timeout */
132 alarm(socket_timeout); 82 alarm(socket_timeout);
133 83
134 switch (vars_to_check) { 84 int return_code = STATE_UNKNOWN;
135 85 char *send_buffer = NULL;
86 char *output_message = NULL;
87 char *perfdata = NULL;
88 char *temp_string = NULL;
89 char *temp_string_perf = NULL;
90 char *description = NULL;
91 char *counter_unit = NULL;
92 char *errcvt = NULL;
93 unsigned long lvalue_list[MAX_VALUE_LIST];
94 switch (config.vars_to_check) {
136 case CHECK_CLIENTVERSION: 95 case CHECK_CLIENTVERSION:
137 96 xasprintf(&send_buffer, "%s&1", config.req_password);
138 xasprintf(&send_buffer, "%s&1", req_password); 97 fetch_data(config.server_address, config.server_port, send_buffer);
139 fetch_data(server_address, server_port, send_buffer); 98 if (config.value_list != NULL && strcmp(recv_buffer, config.value_list) != 0) {
140 if (value_list != NULL && strcmp(recv_buffer, value_list) != 0) { 99 xasprintf(&output_message, _("Wrong client version - running: %s, required: %s"), recv_buffer, config.value_list);
141 xasprintf(&output_message, _("Wrong client version - running: %s, required: %s"), recv_buffer, value_list);
142 return_code = STATE_WARNING; 100 return_code = STATE_WARNING;
143 } else { 101 } else {
144 xasprintf(&output_message, "%s", recv_buffer); 102 xasprintf(&output_message, "%s", recv_buffer);
145 return_code = STATE_OK; 103 return_code = STATE_OK;
146 } 104 }
147 break; 105 break;
148
149 case CHECK_CPULOAD: 106 case CHECK_CPULOAD:
150 107 if (config.value_list == NULL) {
151 if (value_list == NULL)
152 output_message = strdup(_("missing -l parameters")); 108 output_message = strdup(_("missing -l parameters"));
153 else if (!strtoularray(lvalue_list, value_list, ",")) 109 } else if (!strtoularray(lvalue_list, config.value_list, ",")) {
154 output_message = strdup(_("wrong -l parameter.")); 110 output_message = strdup(_("wrong -l parameter."));
155 else { 111 } else {
156 /* -l parameters is present with only integers */ 112 /* -l parameters is present with only integers */
157 return_code = STATE_OK; 113 return_code = STATE_OK;
158 temp_string = strdup(_("CPU Load")); 114 temp_string = strdup(_("CPU Load"));
159 temp_string_perf = strdup(" "); 115 temp_string_perf = strdup(" ");
160 116
161 /* loop until one of the parameters is wrong or not present */ 117 /* loop until one of the parameters is wrong or not present */
118 int offset = 0;
162 while (lvalue_list[0 + offset] > (unsigned long)0 && lvalue_list[0 + offset] <= (unsigned long)17280 && 119 while (lvalue_list[0 + offset] > (unsigned long)0 && lvalue_list[0 + offset] <= (unsigned long)17280 &&
163 lvalue_list[1 + offset] > (unsigned long)0 && lvalue_list[1 + offset] <= (unsigned long)100 && 120 lvalue_list[1 + offset] > (unsigned long)0 && lvalue_list[1 + offset] <= (unsigned long)100 &&
164 lvalue_list[2 + offset] > (unsigned long)0 && lvalue_list[2 + offset] <= (unsigned long)100) { 121 lvalue_list[2 + offset] > (unsigned long)0 && lvalue_list[2 + offset] <= (unsigned long)100) {
165 122
166 /* Send request and retrieve data */ 123 /* Send request and retrieve data */
167 xasprintf(&send_buffer, "%s&2&%lu", req_password, lvalue_list[0 + offset]); 124 xasprintf(&send_buffer, "%s&2&%lu", config.req_password, lvalue_list[0 + offset]);
168 fetch_data(server_address, server_port, send_buffer); 125 fetch_data(config.server_address, config.server_port, send_buffer);
169 126
170 utilization = strtoul(recv_buffer, NULL, 10); 127 unsigned long utilization = strtoul(recv_buffer, NULL, 10);
171 128
172 /* Check if any of the request is in a warning or critical state */ 129 /* Check if any of the request is in a warning or critical state */
173 if (utilization >= lvalue_list[2 + offset]) 130 if (utilization >= lvalue_list[2 + offset]) {
174 return_code = STATE_CRITICAL; 131 return_code = STATE_CRITICAL;
175 else if (utilization >= lvalue_list[1 + offset] && return_code < STATE_WARNING) 132 } else if (utilization >= lvalue_list[1 + offset] && return_code < STATE_WARNING) {
176 return_code = STATE_WARNING; 133 return_code = STATE_WARNING;
134 }
177 135
178 xasprintf(&output_message, _(" %lu%% (%lu min average)"), utilization, lvalue_list[0 + offset]); 136 xasprintf(&output_message, _(" %lu%% (%lu min average)"), utilization, lvalue_list[0 + offset]);
179 xasprintf(&temp_string, "%s%s", temp_string, output_message); 137 xasprintf(&temp_string, "%s%s", temp_string, output_message);
@@ -186,82 +144,87 @@ int main(int argc, char **argv) {
186 if (strlen(temp_string) > 10) { /* we had at least one loop */ 144 if (strlen(temp_string) > 10) { /* we had at least one loop */
187 output_message = strdup(temp_string); 145 output_message = strdup(temp_string);
188 perfdata = temp_string_perf; 146 perfdata = temp_string_perf;
189 } else 147 } else {
190 output_message = strdup(_("not enough values for -l parameters")); 148 output_message = strdup(_("not enough values for -l parameters"));
149 }
191 } 150 }
192 break; 151 break;
193 152 case CHECK_UPTIME: {
194 case CHECK_UPTIME: 153 char *tmp_value_list = config.value_list;
195 154 if (config.value_list == NULL) {
196 if (value_list == NULL) { 155 tmp_value_list = "minutes";
197 value_list = "minutes";
198 } 156 }
199 if (strncmp(value_list, "seconds", strlen("seconds") + 1) && strncmp(value_list, "minutes", strlen("minutes") + 1) && 157 if (strncmp(tmp_value_list, "seconds", strlen("seconds") + 1) && strncmp(tmp_value_list, "minutes", strlen("minutes") + 1) &&
200 strncmp(value_list, "hours", strlen("hours") + 1) && strncmp(value_list, "days", strlen("days") + 1)) { 158 strncmp(config.value_list, "hours", strlen("hours") + 1) && strncmp(tmp_value_list, "days", strlen("days") + 1)) {
201 159
202 output_message = strdup(_("wrong -l argument")); 160 output_message = strdup(_("wrong -l argument"));
203 } else { 161 } else {
204 xasprintf(&send_buffer, "%s&3", req_password); 162 xasprintf(&send_buffer, "%s&3", config.req_password);
205 fetch_data(server_address, server_port, send_buffer); 163 fetch_data(config.server_address, config.server_port, send_buffer);
206 uptime = strtoul(recv_buffer, NULL, 10); 164 unsigned long uptime = strtoul(recv_buffer, NULL, 10);
207 updays = uptime / 86400; 165 int updays = uptime / 86400;
208 uphours = (uptime % 86400) / 3600; 166 int uphours = (uptime % 86400) / 3600;
209 upminutes = ((uptime % 86400) % 3600) / 60; 167 int upminutes = ((uptime % 86400) % 3600) / 60;
210 168
211 if (!strncmp(value_list, "minutes", strlen("minutes"))) 169 if (!strncmp(tmp_value_list, "minutes", strlen("minutes"))) {
212 uptime = uptime / 60; 170 uptime = uptime / 60;
213 else if (!strncmp(value_list, "hours", strlen("hours"))) 171 } else if (!strncmp(tmp_value_list, "hours", strlen("hours"))) {
214 uptime = uptime / 3600; 172 uptime = uptime / 3600;
215 else if (!strncmp(value_list, "days", strlen("days"))) 173 } else if (!strncmp(tmp_value_list, "days", strlen("days"))) {
216 uptime = uptime / 86400; 174 uptime = uptime / 86400;
175 }
217 /* else uptime in seconds, nothing to do */ 176 /* else uptime in seconds, nothing to do */
218 177
219 xasprintf(&output_message, _("System Uptime - %u day(s) %u hour(s) %u minute(s) |uptime=%lu"), updays, uphours, upminutes, 178 xasprintf(&output_message, _("System Uptime - %u day(s) %u hour(s) %u minute(s) |uptime=%lu"), updays, uphours, upminutes,
220 uptime); 179 uptime);
221 180
222 if (check_critical_value && uptime <= critical_value) 181 if (config.check_critical_value && uptime <= config.critical_value) {
223 return_code = STATE_CRITICAL; 182 return_code = STATE_CRITICAL;
224 else if (check_warning_value && uptime <= warning_value) 183 } else if (config.check_warning_value && uptime <= config.warning_value) {
225 return_code = STATE_WARNING; 184 return_code = STATE_WARNING;
226 else 185 } else {
227 return_code = STATE_OK; 186 return_code = STATE_OK;
187 }
228 } 188 }
229 break; 189 } break;
230
231 case CHECK_USEDDISKSPACE: 190 case CHECK_USEDDISKSPACE:
232 191 if (config.value_list == NULL) {
233 if (value_list == NULL)
234 output_message = strdup(_("missing -l parameters")); 192 output_message = strdup(_("missing -l parameters"));
235 else if (strlen(value_list) != 1) 193 } else if (strlen(config.value_list) != 1) {
236 output_message = strdup(_("wrong -l argument")); 194 output_message = strdup(_("wrong -l argument"));
237 else { 195 } else {
238 xasprintf(&send_buffer, "%s&4&%s", req_password, value_list); 196 xasprintf(&send_buffer, "%s&4&%s", config.req_password, config.value_list);
239 fetch_data(server_address, server_port, send_buffer); 197 fetch_data(config.server_address, config.server_port, send_buffer);
240 fds = strtok(recv_buffer, "&"); 198 char *fds = strtok(recv_buffer, "&");
241 tds = strtok(NULL, "&"); 199 char *tds = strtok(NULL, "&");
242 if (fds != NULL) 200 double total_disk_space = 0;
201 double free_disk_space = 0;
202 if (fds != NULL) {
243 free_disk_space = atof(fds); 203 free_disk_space = atof(fds);
244 if (tds != NULL) 204 }
205 if (tds != NULL) {
245 total_disk_space = atof(tds); 206 total_disk_space = atof(tds);
207 }
246 208
247 if (total_disk_space > 0 && free_disk_space >= 0) { 209 if (total_disk_space > 0 && free_disk_space >= 0) {
248 percent_used_space = ((total_disk_space - free_disk_space) / total_disk_space) * 100; 210 double percent_used_space = ((total_disk_space - free_disk_space) / total_disk_space) * 100;
249 warning_used_space = ((float)warning_value / 100) * total_disk_space; 211 double warning_used_space = ((float)config.warning_value / 100) * total_disk_space;
250 critical_used_space = ((float)critical_value / 100) * total_disk_space; 212 double critical_used_space = ((float)config.critical_value / 100) * total_disk_space;
251 213
252 xasprintf(&temp_string, _("%s:\\ - total: %.2f Gb - used: %.2f Gb (%.0f%%) - free %.2f Gb (%.0f%%)"), value_list, 214 xasprintf(&temp_string, _("%s:\\ - total: %.2f Gb - used: %.2f Gb (%.0f%%) - free %.2f Gb (%.0f%%)"), config.value_list,
253 total_disk_space / 1073741824, (total_disk_space - free_disk_space) / 1073741824, percent_used_space, 215 total_disk_space / 1073741824, (total_disk_space - free_disk_space) / 1073741824, percent_used_space,
254 free_disk_space / 1073741824, (free_disk_space / total_disk_space) * 100); 216 free_disk_space / 1073741824, (free_disk_space / total_disk_space) * 100);
255 xasprintf(&temp_string_perf, _("'%s:\\ Used Space'=%.2fGb;%.2f;%.2f;0.00;%.2f"), value_list, 217 xasprintf(&temp_string_perf, _("'%s:\\ Used Space'=%.2fGb;%.2f;%.2f;0.00;%.2f"), config.value_list,
256 (total_disk_space - free_disk_space) / 1073741824, warning_used_space / 1073741824, 218 (total_disk_space - free_disk_space) / 1073741824, warning_used_space / 1073741824,
257 critical_used_space / 1073741824, total_disk_space / 1073741824); 219 critical_used_space / 1073741824, total_disk_space / 1073741824);
258 220
259 if (check_critical_value && percent_used_space >= critical_value) 221 if (config.check_critical_value && percent_used_space >= config.critical_value) {
260 return_code = STATE_CRITICAL; 222 return_code = STATE_CRITICAL;
261 else if (check_warning_value && percent_used_space >= warning_value) 223 } else if (config.check_warning_value && percent_used_space >= config.warning_value) {
262 return_code = STATE_WARNING; 224 return_code = STATE_WARNING;
263 else 225 } else {
264 return_code = STATE_OK; 226 return_code = STATE_OK;
227 }
265 228
266 output_message = strdup(temp_string); 229 output_message = strdup(temp_string);
267 perfdata = temp_string_perf; 230 perfdata = temp_string_perf;
@@ -271,41 +234,40 @@ int main(int argc, char **argv) {
271 } 234 }
272 } 235 }
273 break; 236 break;
274
275 case CHECK_SERVICESTATE: 237 case CHECK_SERVICESTATE:
276 case CHECK_PROCSTATE: 238 case CHECK_PROCSTATE:
277 239 if (config.value_list == NULL) {
278 if (value_list == NULL)
279 output_message = strdup(_("No service/process specified")); 240 output_message = strdup(_("No service/process specified"));
280 else { 241 } else {
281 preparelist(value_list); /* replace , between services with & to send the request */ 242 preparelist(config.value_list); /* replace , between services with & to send the request */
282 xasprintf(&send_buffer, "%s&%u&%s&%s", req_password, (vars_to_check == CHECK_SERVICESTATE) ? 5 : 6, 243 xasprintf(&send_buffer, "%s&%u&%s&%s", config.req_password, (config.vars_to_check == CHECK_SERVICESTATE) ? 5 : 6,
283 (show_all) ? "ShowAll" : "ShowFail", value_list); 244 (config.show_all) ? "ShowAll" : "ShowFail", config.value_list);
284 fetch_data(server_address, server_port, send_buffer); 245 fetch_data(config.server_address, config.server_port, send_buffer);
285 numstr = strtok(recv_buffer, "&"); 246 char *numstr = strtok(recv_buffer, "&");
286 if (numstr == NULL) 247 if (numstr == NULL) {
287 die(STATE_UNKNOWN, _("could not fetch information from server\n")); 248 die(STATE_UNKNOWN, _("could not fetch information from server\n"));
249 }
288 return_code = atoi(numstr); 250 return_code = atoi(numstr);
289 temp_string = strtok(NULL, "&"); 251 temp_string = strtok(NULL, "&");
290 output_message = strdup(temp_string); 252 output_message = strdup(temp_string);
291 } 253 }
292 break; 254 break;
293
294 case CHECK_MEMUSE: 255 case CHECK_MEMUSE:
295 256 xasprintf(&send_buffer, "%s&7", config.req_password);
296 xasprintf(&send_buffer, "%s&7", req_password); 257 fetch_data(config.server_address, config.server_port, send_buffer);
297 fetch_data(server_address, server_port, send_buffer); 258 char *numstr = strtok(recv_buffer, "&");
298 numstr = strtok(recv_buffer, "&"); 259 if (numstr == NULL) {
299 if (numstr == NULL)
300 die(STATE_UNKNOWN, _("could not fetch information from server\n")); 260 die(STATE_UNKNOWN, _("could not fetch information from server\n"));
301 mem_commitLimit = atof(numstr); 261 }
262 double mem_commitLimit = atof(numstr);
302 numstr = strtok(NULL, "&"); 263 numstr = strtok(NULL, "&");
303 if (numstr == NULL) 264 if (numstr == NULL) {
304 die(STATE_UNKNOWN, _("could not fetch information from server\n")); 265 die(STATE_UNKNOWN, _("could not fetch information from server\n"));
305 mem_commitByte = atof(numstr); 266 }
306 percent_used_space = (mem_commitByte / mem_commitLimit) * 100; 267 double mem_commitByte = atof(numstr);
307 warning_used_space = ((float)warning_value / 100) * mem_commitLimit; 268 double percent_used_space = (mem_commitByte / mem_commitLimit) * 100;
308 critical_used_space = ((float)critical_value / 100) * mem_commitLimit; 269 double warning_used_space = ((float)config.warning_value / 100) * mem_commitLimit;
270 double critical_used_space = ((float)config.critical_value / 100) * mem_commitLimit;
309 271
310 /* Divisor should be 1048567, not 3044515, as we are measuring "Commit Charge" here, 272 /* Divisor should be 1048567, not 3044515, as we are measuring "Commit Charge" here,
311 which equals RAM + Pagefiles. */ 273 which equals RAM + Pagefiles. */
@@ -316,15 +278,14 @@ int main(int argc, char **argv) {
316 critical_used_space / 1048567, mem_commitLimit / 1048567); 278 critical_used_space / 1048567, mem_commitLimit / 1048567);
317 279
318 return_code = STATE_OK; 280 return_code = STATE_OK;
319 if (check_critical_value && percent_used_space >= critical_value) 281 if (config.check_critical_value && percent_used_space >= config.critical_value) {
320 return_code = STATE_CRITICAL; 282 return_code = STATE_CRITICAL;
321 else if (check_warning_value && percent_used_space >= warning_value) 283 } else if (config.check_warning_value && percent_used_space >= config.warning_value) {
322 return_code = STATE_WARNING; 284 return_code = STATE_WARNING;
285 }
323 286
324 break; 287 break;
325 288 case CHECK_COUNTER: {
326 case CHECK_COUNTER:
327
328 /* 289 /*
329 CHECK_COUNTER has been modified to provide extensive perfdata information. 290 CHECK_COUNTER has been modified to provide extensive perfdata information.
330 In order to do this, some modifications have been done to the code 291 In order to do this, some modifications have been done to the code
@@ -346,26 +307,32 @@ int main(int argc, char **argv) {
346 strange things will happen when you make graphs of your data. 307 strange things will happen when you make graphs of your data.
347 */ 308 */
348 309
349 if (value_list == NULL) 310 double counter_value = 0.0;
311 if (config.value_list == NULL) {
350 output_message = strdup(_("No counter specified")); 312 output_message = strdup(_("No counter specified"));
351 else { 313 } else {
352 preparelist(value_list); /* replace , between services with & to send the request */ 314 preparelist(config.value_list); /* replace , between services with & to send the request */
353 isPercent = (strchr(value_list, '%') != NULL); 315 bool isPercent = (strchr(config.value_list, '%') != NULL);
354 316
355 strtok(value_list, "&"); /* burn the first parameters */ 317 strtok(config.value_list, "&"); /* burn the first parameters */
356 description = strtok(NULL, "&"); 318 description = strtok(NULL, "&");
357 counter_unit = strtok(NULL, "&"); 319 counter_unit = strtok(NULL, "&");
358 xasprintf(&send_buffer, "%s&8&%s", req_password, value_list); 320 xasprintf(&send_buffer, "%s&8&%s", config.req_password, config.value_list);
359 fetch_data(server_address, server_port, send_buffer); 321 fetch_data(config.server_address, config.server_port, send_buffer);
360 counter_value = atof(recv_buffer); 322 counter_value = atof(recv_buffer);
361 323
362 if (description == NULL) 324 bool allRight = false;
325 if (description == NULL) {
363 xasprintf(&output_message, "%.f", counter_value); 326 xasprintf(&output_message, "%.f", counter_value);
364 else if (isPercent) { 327 } else if (isPercent) {
365 counter_unit = strdup("%"); 328 counter_unit = strdup("%");
366 allRight = true; 329 allRight = true;
367 } 330 }
368 331
332 char *minval = NULL;
333 char *maxval = NULL;
334 double fminval = 0;
335 double fmaxval = 0;
369 if ((counter_unit != NULL) && (!allRight)) { 336 if ((counter_unit != NULL) && (!allRight)) {
370 minval = strtok(NULL, "&"); 337 minval = strtok(NULL, "&");
371 maxval = strtok(NULL, "&"); 338 maxval = strtok(NULL, "&");
@@ -375,16 +342,18 @@ int main(int argc, char **argv) {
375 fminval = (minval != NULL) ? strtod(minval, &errcvt) : -1; 342 fminval = (minval != NULL) ? strtod(minval, &errcvt) : -1;
376 fmaxval = (minval != NULL) ? strtod(maxval, &errcvt) : -1; 343 fmaxval = (minval != NULL) ? strtod(maxval, &errcvt) : -1;
377 344
378 if ((fminval == 0) && (minval == errcvt)) 345 if ((fminval == 0) && (minval == errcvt)) {
379 output_message = strdup(_("Minimum value contains non-numbers")); 346 output_message = strdup(_("Minimum value contains non-numbers"));
380 else { 347 } else {
381 if ((fmaxval == 0) && (maxval == errcvt)) 348 if ((fmaxval == 0) && (maxval == errcvt)) {
382 output_message = strdup(_("Maximum value contains non-numbers")); 349 output_message = strdup(_("Maximum value contains non-numbers"));
383 else 350 } else {
384 allRight = true; /* Everything is OK. */ 351 allRight = true; /* Everything is OK. */
352 }
385 } 353 }
386 } else if ((counter_unit == NULL) && (description != NULL)) 354 } else if ((counter_unit == NULL) && (description != NULL)) {
387 output_message = strdup(_("No unit counter specified")); 355 output_message = strdup(_("No unit counter specified"));
356 }
388 357
389 if (allRight) { 358 if (allRight) {
390 /* Let's format the output string, finally... */ 359 /* Let's format the output string, finally... */
@@ -396,63 +365,65 @@ int main(int argc, char **argv) {
396 } 365 }
397 xasprintf(&output_message, "%s |", output_message); 366 xasprintf(&output_message, "%s |", output_message);
398 xasprintf(&output_message, "%s %s", output_message, 367 xasprintf(&output_message, "%s %s", output_message,
399 fperfdata(description, counter_value, counter_unit, 1, warning_value, 1, critical_value, 368 fperfdata(description, counter_value, counter_unit, 1, config.warning_value, 1, config.critical_value,
400 (!(isPercent) && (minval != NULL)), fminval, (!(isPercent) && (minval != NULL)), fmaxval)); 369 (!(isPercent) && (minval != NULL)), fminval, (!(isPercent) && (minval != NULL)), fmaxval));
401 } 370 }
402 } 371 }
403 372
404 if (critical_value > warning_value) { /* Normal thresholds */ 373 if (config.critical_value > config.warning_value) { /* Normal thresholds */
405 if (check_critical_value && counter_value >= critical_value) 374 if (config.check_critical_value && counter_value >= config.critical_value) {
406 return_code = STATE_CRITICAL; 375 return_code = STATE_CRITICAL;
407 else if (check_warning_value && counter_value >= warning_value) 376 } else if (config.check_warning_value && counter_value >= config.warning_value) {
408 return_code = STATE_WARNING; 377 return_code = STATE_WARNING;
409 else 378 } else {
410 return_code = STATE_OK; 379 return_code = STATE_OK;
380 }
411 } else { /* inverse thresholds */ 381 } else { /* inverse thresholds */
412 return_code = STATE_OK; 382 return_code = STATE_OK;
413 if (check_critical_value && counter_value <= critical_value) 383 if (config.check_critical_value && counter_value <= config.critical_value) {
414 return_code = STATE_CRITICAL; 384 return_code = STATE_CRITICAL;
415 else if (check_warning_value && counter_value <= warning_value) 385 } else if (config.check_warning_value && counter_value <= config.warning_value) {
416 return_code = STATE_WARNING; 386 return_code = STATE_WARNING;
387 }
417 } 388 }
418 break; 389 } break;
419
420 case CHECK_FILEAGE: 390 case CHECK_FILEAGE:
421 391 if (config.value_list == NULL) {
422 if (value_list == NULL)
423 output_message = strdup(_("No counter specified")); 392 output_message = strdup(_("No counter specified"));
424 else { 393 } else {
425 preparelist(value_list); /* replace , between services with & to send the request */ 394 preparelist(config.value_list); /* replace , between services with & to send the request */
426 xasprintf(&send_buffer, "%s&9&%s", req_password, value_list); 395 xasprintf(&send_buffer, "%s&9&%s", config.req_password, config.value_list);
427 fetch_data(server_address, server_port, send_buffer); 396 fetch_data(config.server_address, config.server_port, send_buffer);
428 age_in_minutes = atoi(strtok(recv_buffer, "&")); 397 unsigned long age_in_minutes = atoi(strtok(recv_buffer, "&"));
429 description = strtok(NULL, "&"); 398 description = strtok(NULL, "&");
430 output_message = strdup(description); 399 output_message = strdup(description);
431 400
432 if (critical_value > warning_value) { /* Normal thresholds */ 401 if (config.critical_value > config.warning_value) { /* Normal thresholds */
433 if (check_critical_value && age_in_minutes >= critical_value) 402 if (config.check_critical_value && age_in_minutes >= config.critical_value) {
434 return_code = STATE_CRITICAL; 403 return_code = STATE_CRITICAL;
435 else if (check_warning_value && age_in_minutes >= warning_value) 404 } else if (config.check_warning_value && age_in_minutes >= config.warning_value) {
436 return_code = STATE_WARNING; 405 return_code = STATE_WARNING;
437 else 406 } else {
438 return_code = STATE_OK; 407 return_code = STATE_OK;
408 }
439 } else { /* inverse thresholds */ 409 } else { /* inverse thresholds */
440 if (check_critical_value && age_in_minutes <= critical_value) 410 if (config.check_critical_value && age_in_minutes <= config.critical_value) {
441 return_code = STATE_CRITICAL; 411 return_code = STATE_CRITICAL;
442 else if (check_warning_value && age_in_minutes <= warning_value) 412 } else if (config.check_warning_value && age_in_minutes <= config.warning_value) {
443 return_code = STATE_WARNING; 413 return_code = STATE_WARNING;
444 else 414 } else {
445 return_code = STATE_OK; 415 return_code = STATE_OK;
416 }
446 } 417 }
447 } 418 }
448 break; 419 break;
449 420
450 case CHECK_INSTANCES: 421 case CHECK_INSTANCES:
451 if (value_list == NULL) 422 if (config.value_list == NULL) {
452 output_message = strdup(_("No counter specified")); 423 output_message = strdup(_("No counter specified"));
453 else { 424 } else {
454 xasprintf(&send_buffer, "%s&10&%s", req_password, value_list); 425 xasprintf(&send_buffer, "%s&10&%s", config.req_password, config.value_list);
455 fetch_data(server_address, server_port, send_buffer); 426 fetch_data(config.server_address, config.server_port, send_buffer);
456 if (!strncmp(recv_buffer, "ERROR", 5)) { 427 if (!strncmp(recv_buffer, "ERROR", 5)) {
457 printf("NSClient - %s\n", recv_buffer); 428 printf("NSClient - %s\n", recv_buffer);
458 exit(STATE_UNKNOWN); 429 exit(STATE_UNKNOWN);
@@ -471,18 +442,16 @@ int main(int argc, char **argv) {
471 /* reset timeout */ 442 /* reset timeout */
472 alarm(0); 443 alarm(0);
473 444
474 if (perfdata == NULL) 445 if (perfdata == NULL) {
475 printf("%s\n", output_message); 446 printf("%s\n", output_message);
476 else 447 } else {
477 printf("%s | %s\n", output_message, perfdata); 448 printf("%s | %s\n", output_message, perfdata);
449 }
478 return return_code; 450 return return_code;
479} 451}
480 452
481/* process command-line arguments */ 453/* process command-line arguments */
482int process_arguments(int argc, char **argv) { 454check_nt_config_wrapper process_arguments(int argc, char **argv) {
483 int c;
484
485 int option = 0;
486 static struct option longopts[] = {{"port", required_argument, 0, 'p'}, 455 static struct option longopts[] = {{"port", required_argument, 0, 'p'},
487 {"timeout", required_argument, 0, 't'}, 456 {"timeout", required_argument, 0, 't'},
488 {"critical", required_argument, 0, 'c'}, 457 {"critical", required_argument, 0, 'c'},
@@ -497,34 +466,44 @@ int process_arguments(int argc, char **argv) {
497 {"help", no_argument, 0, 'h'}, 466 {"help", no_argument, 0, 'h'},
498 {0, 0, 0, 0}}; 467 {0, 0, 0, 0}};
499 468
469 check_nt_config_wrapper result = {
470 .errorcode = OK,
471 .config = check_nt_config_init(),
472 };
473
500 /* no options were supplied */ 474 /* no options were supplied */
501 if (argc < 2) 475 if (argc < 2) {
502 return ERROR; 476 result.errorcode = ERROR;
477 return result;
478 }
503 479
504 /* backwards compatibility */ 480 /* backwards compatibility */
505 if (!is_option(argv[1])) { 481 if (!is_option(argv[1])) {
506 server_address = strdup(argv[1]); 482 result.config.server_address = strdup(argv[1]);
507 argv[1] = argv[0]; 483 argv[1] = argv[0];
508 argv = &argv[1]; 484 argv = &argv[1];
509 argc--; 485 argc--;
510 } 486 }
511 487
512 for (c = 1; c < argc; c++) { 488 for (int index = 1; index < argc; index++) {
513 if (strcmp("-to", argv[c]) == 0) 489 if (strcmp("-to", argv[index]) == 0) {
514 strcpy(argv[c], "-t"); 490 strcpy(argv[index], "-t");
515 else if (strcmp("-wv", argv[c]) == 0) 491 } else if (strcmp("-wv", argv[index]) == 0) {
516 strcpy(argv[c], "-w"); 492 strcpy(argv[index], "-w");
517 else if (strcmp("-cv", argv[c]) == 0) 493 } else if (strcmp("-cv", argv[index]) == 0) {
518 strcpy(argv[c], "-c"); 494 strcpy(argv[index], "-c");
495 }
519 } 496 }
520 497
521 while (1) { 498 int option = 0;
522 c = getopt_long(argc, argv, "+hVH:t:c:w:p:v:l:s:d:u", longopts, &option); 499 while (true) {
500 int option_index = getopt_long(argc, argv, "+hVH:t:c:w:p:v:l:s:d:u", longopts, &option);
523 501
524 if (c == -1 || c == EOF || c == 1) 502 if (option_index == -1 || option_index == EOF || option_index == 1) {
525 break; 503 break;
504 }
526 505
527 switch (c) { 506 switch (option_index) {
528 case '?': /* print short usage statement if args not parsable */ 507 case '?': /* print short usage statement if args not parsable */
529 usage5(); 508 usage5();
530 case 'h': /* help */ 509 case 'h': /* help */
@@ -534,118 +513,128 @@ int process_arguments(int argc, char **argv) {
534 print_revision(progname, NP_VERSION); 513 print_revision(progname, NP_VERSION);
535 exit(STATE_UNKNOWN); 514 exit(STATE_UNKNOWN);
536 case 'H': /* hostname */ 515 case 'H': /* hostname */
537 server_address = optarg; 516 result.config.server_address = optarg;
538 break; 517 break;
539 case 's': /* password */ 518 case 's': /* password */
540 req_password = optarg; 519 result.config.req_password = optarg;
541 break; 520 break;
542 case 'p': /* port */ 521 case 'p': /* port */
543 if (is_intnonneg(optarg)) 522 if (is_intnonneg(optarg)) {
544 server_port = atoi(optarg); 523 result.config.server_port = atoi(optarg);
545 else 524 } else {
546 die(STATE_UNKNOWN, _("Server port must be an integer\n")); 525 die(STATE_UNKNOWN, _("Server port must be an integer\n"));
526 }
547 break; 527 break;
548 case 'v': 528 case 'v':
549 if (strlen(optarg) < 4) 529 if (strlen(optarg) < 4) {
550 return ERROR; 530 result.errorcode = ERROR;
551 if (!strcmp(optarg, "CLIENTVERSION")) 531 return result;
552 vars_to_check = CHECK_CLIENTVERSION; 532 }
553 else if (!strcmp(optarg, "CPULOAD")) 533 if (!strcmp(optarg, "CLIENTVERSION")) {
554 vars_to_check = CHECK_CPULOAD; 534 result.config.vars_to_check = CHECK_CLIENTVERSION;
555 else if (!strcmp(optarg, "UPTIME")) 535 } else if (!strcmp(optarg, "CPULOAD")) {
556 vars_to_check = CHECK_UPTIME; 536 result.config.vars_to_check = CHECK_CPULOAD;
557 else if (!strcmp(optarg, "USEDDISKSPACE")) 537 } else if (!strcmp(optarg, "UPTIME")) {
558 vars_to_check = CHECK_USEDDISKSPACE; 538 result.config.vars_to_check = CHECK_UPTIME;
559 else if (!strcmp(optarg, "SERVICESTATE")) 539 } else if (!strcmp(optarg, "USEDDISKSPACE")) {
560 vars_to_check = CHECK_SERVICESTATE; 540 result.config.vars_to_check = CHECK_USEDDISKSPACE;
561 else if (!strcmp(optarg, "PROCSTATE")) 541 } else if (!strcmp(optarg, "SERVICESTATE")) {
562 vars_to_check = CHECK_PROCSTATE; 542 result.config.vars_to_check = CHECK_SERVICESTATE;
563 else if (!strcmp(optarg, "MEMUSE")) 543 } else if (!strcmp(optarg, "PROCSTATE")) {
564 vars_to_check = CHECK_MEMUSE; 544 result.config.vars_to_check = CHECK_PROCSTATE;
565 else if (!strcmp(optarg, "COUNTER")) 545 } else if (!strcmp(optarg, "MEMUSE")) {
566 vars_to_check = CHECK_COUNTER; 546 result.config.vars_to_check = CHECK_MEMUSE;
567 else if (!strcmp(optarg, "FILEAGE")) 547 } else if (!strcmp(optarg, "COUNTER")) {
568 vars_to_check = CHECK_FILEAGE; 548 result.config.vars_to_check = CHECK_COUNTER;
569 else if (!strcmp(optarg, "INSTANCES")) 549 } else if (!strcmp(optarg, "FILEAGE")) {
570 vars_to_check = CHECK_INSTANCES; 550 result.config.vars_to_check = CHECK_FILEAGE;
571 else 551 } else if (!strcmp(optarg, "INSTANCES")) {
572 return ERROR; 552 result.config.vars_to_check = CHECK_INSTANCES;
553 } else {
554 result.errorcode = ERROR;
555 return result;
556 }
573 break; 557 break;
574 case 'l': /* value list */ 558 case 'l': /* value list */
575 value_list = optarg; 559 result.config.value_list = optarg;
576 break; 560 break;
577 case 'w': /* warning threshold */ 561 case 'w': /* warning threshold */
578 warning_value = strtoul(optarg, NULL, 10); 562 result.config.warning_value = strtoul(optarg, NULL, 10);
579 check_warning_value = true; 563 result.config.check_warning_value = true;
580 break; 564 break;
581 case 'c': /* critical threshold */ 565 case 'c': /* critical threshold */
582 critical_value = strtoul(optarg, NULL, 10); 566 result.config.critical_value = strtoul(optarg, NULL, 10);
583 check_critical_value = true; 567 result.config.check_critical_value = true;
584 break; 568 break;
585 case 'd': /* Display select for services */ 569 case 'd': /* Display select for services */
586 if (!strcmp(optarg, "SHOWALL")) 570 if (!strcmp(optarg, "SHOWALL")) {
587 show_all = true; 571 result.config.show_all = true;
572 }
588 break; 573 break;
589 case 'u': 574 case 'u':
590 socket_timeout_state = STATE_UNKNOWN; 575 socket_timeout_state = STATE_UNKNOWN;
591 break; 576 break;
592 case 't': /* timeout */ 577 case 't': /* timeout */
593 socket_timeout = atoi(optarg); 578 socket_timeout = atoi(optarg);
594 if (socket_timeout <= 0) 579 if (socket_timeout <= 0) {
595 return ERROR; 580 result.errorcode = ERROR;
581 return result;
582 }
596 } 583 }
597 } 584 }
598 if (server_address == NULL) 585 if (result.config.server_address == NULL) {
599 usage4(_("You must provide a server address or host name")); 586 usage4(_("You must provide a server address or host name"));
587 }
600 588
601 if (vars_to_check == CHECK_NONE) 589 if (result.config.vars_to_check == CHECK_NONE) {
602 return ERROR; 590 result.errorcode = ERROR;
591 return result;
592 }
603 593
604 if (req_password == NULL) 594 if (result.config.req_password == NULL) {
605 req_password = strdup(_("None")); 595 result.config.req_password = strdup(_("None"));
596 }
606 597
607 return OK; 598 return result;
608} 599}
609 600
610void fetch_data(const char *address, int port, const char *sendb) { 601void fetch_data(const char *address, int port, const char *sendb) {
611 int result; 602 int result = process_tcp_request(address, port, sendb, recv_buffer, sizeof(recv_buffer));
612
613 result = process_tcp_request(address, port, sendb, recv_buffer, sizeof(recv_buffer));
614 603
615 if (result != STATE_OK) 604 if (result != STATE_OK) {
616 die(result, _("could not fetch information from server\n")); 605 die(result, _("could not fetch information from server\n"));
606 }
617 607
618 if (!strncmp(recv_buffer, "ERROR", 5)) 608 if (!strncmp(recv_buffer, "ERROR", 5)) {
619 die(STATE_UNKNOWN, "NSClient - %s\n", recv_buffer); 609 die(STATE_UNKNOWN, "NSClient - %s\n", recv_buffer);
610 }
620} 611}
621 612
622bool strtoularray(unsigned long *array, char *string, const char *delim) { 613bool strtoularray(unsigned long *array, char *string, const char *delim) {
623 /* split a <delim> delimited string into a long array */ 614 /* split a <delim> delimited string into a long array */
624 int idx = 0; 615 for (int idx = 0; idx < MAX_VALUE_LIST; idx++) {
625 char *t1;
626
627 for (idx = 0; idx < MAX_VALUE_LIST; idx++)
628 array[idx] = 0; 616 array[idx] = 0;
617 }
629 618
630 idx = 0; 619 int idx = 0;
631 for (t1 = strtok(string, delim); t1 != NULL; t1 = strtok(NULL, delim)) { 620 for (char *t1 = strtok(string, delim); t1 != NULL; t1 = strtok(NULL, delim)) {
632 if (is_numeric(t1) && idx < MAX_VALUE_LIST) { 621 if (is_numeric(t1) && idx < MAX_VALUE_LIST) {
633 array[idx] = strtoul(t1, NULL, 10); 622 array[idx] = strtoul(t1, NULL, 10);
634 idx++; 623 idx++;
635 } else 624 } else {
636 return false; 625 return false;
626 }
637 } 627 }
638 return true; 628 return true;
639} 629}
640 630
641void preparelist(char *string) { 631void preparelist(char *string) {
642 /* Replace all , with & which is the delimiter for the request */ 632 /* Replace all , with & which is the delimiter for the request */
643 int i; 633 for (int i = 0; (size_t)i < strlen(string); i++) {
644
645 for (i = 0; (size_t)i < strlen(string); i++)
646 if (string[i] == ',') { 634 if (string[i] == ',') {
647 string[i] = '&'; 635 string[i] = '&';
648 } 636 }
637 }
649} 638}
650 639
651void print_help(void) { 640void print_help(void) {
diff --git a/plugins/check_nt.d/config.h b/plugins/check_nt.d/config.h
new file mode 100644
index 00000000..431889cb
--- /dev/null
+++ b/plugins/check_nt.d/config.h
@@ -0,0 +1,53 @@
1#pragma once
2
3#include "../../config.h"
4#include <stddef.h>
5
6enum {
7 PORT = 1248,
8};
9
10enum checkvars {
11 CHECK_NONE,
12 CHECK_CLIENTVERSION,
13 CHECK_CPULOAD,
14 CHECK_UPTIME,
15 CHECK_USEDDISKSPACE,
16 CHECK_SERVICESTATE,
17 CHECK_PROCSTATE,
18 CHECK_MEMUSE,
19 CHECK_COUNTER,
20 CHECK_FILEAGE,
21 CHECK_INSTANCES
22};
23
24typedef struct {
25 char *server_address;
26 int server_port;
27 char *req_password;
28 enum checkvars vars_to_check;
29 bool show_all;
30 char *value_list;
31 bool check_warning_value;
32 unsigned long warning_value;
33 bool check_critical_value;
34 unsigned long critical_value;
35} check_nt_config;
36
37check_nt_config check_nt_config_init() {
38 check_nt_config tmp = {
39 .server_address = NULL,
40 .server_port = PORT,
41 .req_password = NULL,
42
43 .vars_to_check = CHECK_NONE,
44 .show_all = false,
45 .value_list = NULL,
46
47 .check_warning_value = false,
48 .warning_value = 0,
49 .check_critical_value = false,
50 .critical_value = 0,
51 };
52 return tmp;
53}
diff --git a/plugins/check_ntp_time.c b/plugins/check_ntp_time.c
index 703b69df..31162883 100644
--- a/plugins/check_ntp_time.c
+++ b/plugins/check_ntp_time.c
@@ -41,17 +41,18 @@ const char *email = "devel@monitoring-plugins.org";
41#include "common.h" 41#include "common.h"
42#include "netutils.h" 42#include "netutils.h"
43#include "utils.h" 43#include "utils.h"
44#include "states.h"
45#include "thresholds.h"
46#include "check_ntp_time.d/config.h"
44 47
45static char *server_address = NULL;
46static char *port = "123";
47static int verbose = 0; 48static int verbose = 0;
48static bool quiet = false;
49static char *owarn = "60";
50static char *ocrit = "120";
51static int time_offset = 0;
52 49
53static int process_arguments(int, char **); 50typedef struct {
54static thresholds *offset_thresholds = NULL; 51 int errorcode;
52 check_ntp_time_config config;
53} check_ntp_time_config_wrapper;
54static check_ntp_time_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
55
55static void print_help(void); 56static void print_help(void);
56void print_usage(void); 57void print_usage(void);
57 58
@@ -159,7 +160,7 @@ typedef struct {
159#define EPOCHDIFF 0x83aa7e80UL 160#define EPOCHDIFF 0x83aa7e80UL
160 161
161/* extract a 32-bit ntp fixed point number into a double */ 162/* extract a 32-bit ntp fixed point number into a double */
162#define NTP32asDOUBLE(x) (ntohs(L16(x)) + (double)ntohs(R16(x)) / 65536.0) 163#define NTP32asDOUBLE(x) (ntohs(L16(x)) + ((double)ntohs(R16(x)) / 65536.0))
163 164
164/* likewise for a 64-bit ntp fp number */ 165/* likewise for a 64-bit ntp fp number */
165#define NTP64asDOUBLE(n) \ 166#define NTP64asDOUBLE(n) \
@@ -208,56 +209,52 @@ typedef struct {
208 } while (0); 209 } while (0);
209 210
210/* calculate the offset of the local clock */ 211/* calculate the offset of the local clock */
211static inline double calc_offset(const ntp_message *m, const struct timeval *t) { 212static inline double calc_offset(const ntp_message *message, const struct timeval *time_value) {
212 double client_tx = NTP64asDOUBLE(m->origts); 213 double client_tx = NTP64asDOUBLE(message->origts);
213 double peer_rx = NTP64asDOUBLE(m->rxts); 214 double peer_rx = NTP64asDOUBLE(message->rxts);
214 double peer_tx = NTP64asDOUBLE(m->txts); 215 double peer_tx = NTP64asDOUBLE(message->txts);
215 double client_rx = TVasDOUBLE((*t)); 216 double client_rx = TVasDOUBLE((*time_value));
216 return (.5 * ((peer_tx - client_rx) + (peer_rx - client_tx))); 217 return (((peer_tx - client_rx) + (peer_rx - client_tx)) / 2);
217} 218}
218 219
219/* print out a ntp packet in human readable/debuggable format */ 220/* print out a ntp packet in human readable/debuggable format */
220void print_ntp_message(const ntp_message *p) { 221void print_ntp_message(const ntp_message *message) {
221 struct timeval ref; 222 struct timeval ref;
222 struct timeval orig; 223 struct timeval orig;
223 struct timeval rx;
224 struct timeval tx;
225 224
226 NTP64toTV(p->refts, ref); 225 NTP64toTV(message->refts, ref);
227 NTP64toTV(p->origts, orig); 226 NTP64toTV(message->origts, orig);
228 NTP64toTV(p->rxts, rx);
229 NTP64toTV(p->txts, tx);
230 227
231 printf("packet contents:\n"); 228 printf("packet contents:\n");
232 printf("\tflags: 0x%.2x\n", p->flags); 229 printf("\tflags: 0x%.2x\n", message->flags);
233 printf("\t li=%d (0x%.2x)\n", LI(p->flags), p->flags & LI_MASK); 230 printf("\t li=%d (0x%.2x)\n", LI(message->flags), message->flags & LI_MASK);
234 printf("\t vn=%d (0x%.2x)\n", VN(p->flags), p->flags & VN_MASK); 231 printf("\t vn=%d (0x%.2x)\n", VN(message->flags), message->flags & VN_MASK);
235 printf("\t mode=%d (0x%.2x)\n", MODE(p->flags), p->flags & MODE_MASK); 232 printf("\t mode=%d (0x%.2x)\n", MODE(message->flags), message->flags & MODE_MASK);
236 printf("\tstratum = %d\n", p->stratum); 233 printf("\tstratum = %d\n", message->stratum);
237 printf("\tpoll = %g\n", pow(2, p->poll)); 234 printf("\tpoll = %g\n", pow(2, message->poll));
238 printf("\tprecision = %g\n", pow(2, p->precision)); 235 printf("\tprecision = %g\n", pow(2, message->precision));
239 printf("\trtdelay = %-.16g\n", NTP32asDOUBLE(p->rtdelay)); 236 printf("\trtdelay = %-.16g\n", NTP32asDOUBLE(message->rtdelay));
240 printf("\trtdisp = %-.16g\n", NTP32asDOUBLE(p->rtdisp)); 237 printf("\trtdisp = %-.16g\n", NTP32asDOUBLE(message->rtdisp));
241 printf("\trefid = %x\n", p->refid); 238 printf("\trefid = %x\n", message->refid);
242 printf("\trefts = %-.16g\n", NTP64asDOUBLE(p->refts)); 239 printf("\trefts = %-.16g\n", NTP64asDOUBLE(message->refts));
243 printf("\torigts = %-.16g\n", NTP64asDOUBLE(p->origts)); 240 printf("\torigts = %-.16g\n", NTP64asDOUBLE(message->origts));
244 printf("\trxts = %-.16g\n", NTP64asDOUBLE(p->rxts)); 241 printf("\trxts = %-.16g\n", NTP64asDOUBLE(message->rxts));
245 printf("\ttxts = %-.16g\n", NTP64asDOUBLE(p->txts)); 242 printf("\ttxts = %-.16g\n", NTP64asDOUBLE(message->txts));
246} 243}
247 244
248void setup_request(ntp_message *p) { 245void setup_request(ntp_message *message) {
249 memset(p, 0, sizeof(ntp_message)); 246 memset(message, 0, sizeof(ntp_message));
250 LI_SET(p->flags, LI_ALARM); 247 LI_SET(message->flags, LI_ALARM);
251 VN_SET(p->flags, 4); 248 VN_SET(message->flags, 4);
252 MODE_SET(p->flags, MODE_CLIENT); 249 MODE_SET(message->flags, MODE_CLIENT);
253 p->poll = 4; 250 message->poll = 4;
254 p->precision = (int8_t)0xfa; 251 message->precision = (int8_t)0xfa;
255 L16(p->rtdelay) = htons(1); 252 L16(message->rtdelay) = htons(1);
256 L16(p->rtdisp) = htons(1); 253 L16(message->rtdisp) = htons(1);
257 254
258 struct timeval t; 255 struct timeval t;
259 gettimeofday(&t, NULL); 256 gettimeofday(&t, NULL);
260 TVtoNTP64(t, p->txts); 257 TVtoNTP64(t, message->txts);
261} 258}
262 259
263/* select the "best" server from a list of servers, and return its index. 260/* select the "best" server from a list of servers, and return its index.
@@ -273,14 +270,16 @@ int best_offset_server(const ntp_server_results *slist, int nservers) {
273 * stratum 0 is for reference clocks so no NTP server should ever report 270 * stratum 0 is for reference clocks so no NTP server should ever report
274 * a stratum 0 */ 271 * a stratum 0 */
275 if (slist[cserver].stratum == 0) { 272 if (slist[cserver].stratum == 0) {
276 if (verbose) 273 if (verbose) {
277 printf("discarding peer %d: stratum=%d\n", cserver, slist[cserver].stratum); 274 printf("discarding peer %d: stratum=%d\n", cserver, slist[cserver].stratum);
275 }
278 continue; 276 continue;
279 } 277 }
280 /* Sort out servers with error flags */ 278 /* Sort out servers with error flags */
281 if (LI(slist[cserver].flags) == LI_ALARM) { 279 if (LI(slist[cserver].flags) == LI_ALARM) {
282 if (verbose) 280 if (verbose) {
283 printf("discarding peer %d: flags=%d\n", cserver, LI(slist[cserver].flags)); 281 printf("discarding peer %d: flags=%d\n", cserver, LI(slist[cserver].flags));
282 }
284 continue; 283 continue;
285 } 284 }
286 285
@@ -322,7 +321,7 @@ int best_offset_server(const ntp_server_results *slist, int nservers) {
322 * we don't waste time sitting around waiting for single packets. 321 * we don't waste time sitting around waiting for single packets.
323 * - we also "manually" handle resolving host names and connecting, because 322 * - we also "manually" handle resolving host names and connecting, because
324 * we have to do it in a way that our lazy macros don't handle currently :( */ 323 * we have to do it in a way that our lazy macros don't handle currently :( */
325double offset_request(const char *host, int *status) { 324double offset_request(const char *host, const char *port, mp_state_enum *status, int time_offset) {
326 /* setup hints to only return results from getaddrinfo that we'd like */ 325 /* setup hints to only return results from getaddrinfo that we'd like */
327 struct addrinfo hints; 326 struct addrinfo hints;
328 memset(&hints, 0, sizeof(struct addrinfo)); 327 memset(&hints, 0, sizeof(struct addrinfo));
@@ -331,39 +330,43 @@ double offset_request(const char *host, int *status) {
331 hints.ai_socktype = SOCK_DGRAM; 330 hints.ai_socktype = SOCK_DGRAM;
332 331
333 /* fill in ai with the list of hosts resolved by the host name */ 332 /* fill in ai with the list of hosts resolved by the host name */
334 struct addrinfo *ai = NULL; 333 struct addrinfo *addresses = NULL;
335 int ga_result = getaddrinfo(host, port, &hints, &ai); 334 int ga_result = getaddrinfo(host, port, &hints, &addresses);
336 if (ga_result != 0) { 335 if (ga_result != 0) {
337 die(STATE_UNKNOWN, "error getting address for %s: %s\n", host, gai_strerror(ga_result)); 336 die(STATE_UNKNOWN, "error getting address for %s: %s\n", host, gai_strerror(ga_result));
338 } 337 }
339 338
340 /* count the number of returned hosts, and allocate stuff accordingly */ 339 /* count the number of returned hosts, and allocate stuff accordingly */
341 int num_hosts = 0; 340 size_t num_hosts = 0;
342 for (struct addrinfo *ai_tmp = ai; ai_tmp != NULL; ai_tmp = ai_tmp->ai_next) { 341 for (struct addrinfo *ai_tmp = addresses; ai_tmp != NULL; ai_tmp = ai_tmp->ai_next) {
343 num_hosts++; 342 num_hosts++;
344 } 343 }
345 344
346 ntp_message *req = (ntp_message *)malloc(sizeof(ntp_message) * num_hosts); 345 ntp_message *req = (ntp_message *)malloc(sizeof(ntp_message) * num_hosts);
347 346
348 if (req == NULL) 347 if (req == NULL) {
349 die(STATE_UNKNOWN, "can not allocate ntp message array"); 348 die(STATE_UNKNOWN, "can not allocate ntp message array");
349 }
350 int *socklist = (int *)malloc(sizeof(int) * num_hosts); 350 int *socklist = (int *)malloc(sizeof(int) * num_hosts);
351 351
352 if (socklist == NULL) 352 if (socklist == NULL) {
353 die(STATE_UNKNOWN, "can not allocate socket array"); 353 die(STATE_UNKNOWN, "can not allocate socket array");
354 }
354 355
355 struct pollfd *ufds = (struct pollfd *)malloc(sizeof(struct pollfd) * num_hosts); 356 struct pollfd *ufds = (struct pollfd *)malloc(sizeof(struct pollfd) * num_hosts);
356 if (ufds == NULL) 357 if (ufds == NULL) {
357 die(STATE_UNKNOWN, "can not allocate socket array"); 358 die(STATE_UNKNOWN, "can not allocate socket array");
359 }
358 360
359 ntp_server_results *servers = (ntp_server_results *)malloc(sizeof(ntp_server_results) * num_hosts); 361 ntp_server_results *servers = (ntp_server_results *)malloc(sizeof(ntp_server_results) * num_hosts);
360 if (servers == NULL) 362 if (servers == NULL) {
361 die(STATE_UNKNOWN, "can not allocate server array"); 363 die(STATE_UNKNOWN, "can not allocate server array");
364 }
362 memset(servers, 0, sizeof(ntp_server_results) * num_hosts); 365 memset(servers, 0, sizeof(ntp_server_results) * num_hosts);
363 DBG(printf("Found %d peers to check\n", num_hosts)); 366 DBG(printf("Found %zu peers to check\n", num_hosts));
364 367
365 /* setup each socket for writing, and the corresponding struct pollfd */ 368 /* setup each socket for writing, and the corresponding struct pollfd */
366 struct addrinfo *ai_tmp = ai; 369 struct addrinfo *ai_tmp = addresses;
367 for (int i = 0; ai_tmp; i++) { 370 for (int i = 0; ai_tmp; i++) {
368 socklist[i] = socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP); 371 socklist[i] = socket(ai_tmp->ai_family, SOCK_DGRAM, IPPROTO_UDP);
369 if (socklist[i] == -1) { 372 if (socklist[i] == -1) {
@@ -389,7 +392,7 @@ double offset_request(const char *host, int *status) {
389 time_t start_ts = 0; 392 time_t start_ts = 0;
390 time_t now_time = 0; 393 time_t now_time = 0;
391 now_time = start_ts = time(NULL); 394 now_time = start_ts = time(NULL);
392 int servers_completed = 0; 395 size_t servers_completed = 0;
393 bool one_read = false; 396 bool one_read = false;
394 while (servers_completed < num_hosts && now_time - start_ts <= socket_timeout / 2) { 397 while (servers_completed < num_hosts && now_time - start_ts <= socket_timeout / 2) {
395 /* loop through each server and find each one which hasn't 398 /* loop through each server and find each one which hasn't
@@ -398,12 +401,14 @@ double offset_request(const char *host, int *status) {
398 * and update the "waiting" timestamp with the current time. */ 401 * and update the "waiting" timestamp with the current time. */
399 now_time = time(NULL); 402 now_time = time(NULL);
400 403
401 for (int i = 0; i < num_hosts; i++) { 404 for (size_t i = 0; i < num_hosts; i++) {
402 if (servers[i].waiting < now_time && servers[i].num_responses < AVG_NUM) { 405 if (servers[i].waiting < now_time && servers[i].num_responses < AVG_NUM) {
403 if (verbose && servers[i].waiting != 0) 406 if (verbose && servers[i].waiting != 0) {
404 printf("re-"); 407 printf("re-");
405 if (verbose) 408 }
406 printf("sending request to peer %d\n", i); 409 if (verbose) {
410 printf("sending request to peer %zu\n", i);
411 }
407 setup_request(&req[i]); 412 setup_request(&req[i]);
408 write(socklist[i], &req[i], sizeof(ntp_message)); 413 write(socklist[i], &req[i], sizeof(ntp_message));
409 servers[i].waiting = now_time; 414 servers[i].waiting = now_time;
@@ -419,10 +424,10 @@ double offset_request(const char *host, int *status) {
419 } 424 }
420 425
421 /* read from any sockets with pending data */ 426 /* read from any sockets with pending data */
422 for (int i = 0; servers_readable && i < num_hosts; i++) { 427 for (size_t i = 0; servers_readable && i < num_hosts; i++) {
423 if (ufds[i].revents & POLLIN && servers[i].num_responses < AVG_NUM) { 428 if (ufds[i].revents & POLLIN && servers[i].num_responses < AVG_NUM) {
424 if (verbose) { 429 if (verbose) {
425 printf("response from peer %d: ", i); 430 printf("response from peer %zu: ", i);
426 } 431 }
427 432
428 read(ufds[i].fd, &req[i], sizeof(ntp_message)); 433 read(ufds[i].fd, &req[i], sizeof(ntp_message));
@@ -442,14 +447,15 @@ double offset_request(const char *host, int *status) {
442 servers[i].flags = req[i].flags; 447 servers[i].flags = req[i].flags;
443 servers_readable--; 448 servers_readable--;
444 one_read = true; 449 one_read = true;
445 if (servers[i].num_responses == AVG_NUM) 450 if (servers[i].num_responses == AVG_NUM) {
446 servers_completed++; 451 servers_completed++;
452 }
447 } 453 }
448 } 454 }
449 /* lather, rinse, repeat. */ 455 /* lather, rinse, repeat. */
450 } 456 }
451 457
452 if (one_read == false) { 458 if (!one_read) {
453 die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n"); 459 die(STATE_CRITICAL, "NTP CRITICAL: No response from NTP server\n");
454 } 460 }
455 461
@@ -467,21 +473,22 @@ double offset_request(const char *host, int *status) {
467 } 473 }
468 474
469 /* cleanup */ 475 /* cleanup */
470 for (int j = 0; j < num_hosts; j++) { 476 for (size_t j = 0; j < num_hosts; j++) {
471 close(socklist[j]); 477 close(socklist[j]);
472 } 478 }
473 free(socklist); 479 free(socklist);
474 free(ufds); 480 free(ufds);
475 free(servers); 481 free(servers);
476 free(req); 482 free(req);
477 freeaddrinfo(ai); 483 freeaddrinfo(addresses);
478 484
479 if (verbose) 485 if (verbose) {
480 printf("overall average offset: %.10g\n", avg_offset); 486 printf("overall average offset: %.10g\n", avg_offset);
487 }
481 return avg_offset; 488 return avg_offset;
482} 489}
483 490
484int process_arguments(int argc, char **argv) { 491check_ntp_time_config_wrapper process_arguments(int argc, char **argv) {
485 static struct option longopts[] = {{"version", no_argument, 0, 'V'}, 492 static struct option longopts[] = {{"version", no_argument, 0, 'V'},
486 {"help", no_argument, 0, 'h'}, 493 {"help", no_argument, 0, 'h'},
487 {"verbose", no_argument, 0, 'v'}, 494 {"verbose", no_argument, 0, 'v'},
@@ -496,14 +503,24 @@ int process_arguments(int argc, char **argv) {
496 {"port", required_argument, 0, 'p'}, 503 {"port", required_argument, 0, 'p'},
497 {0, 0, 0, 0}}; 504 {0, 0, 0, 0}};
498 505
499 if (argc < 2) 506 if (argc < 2) {
500 usage("\n"); 507 usage("\n");
508 }
509
510 check_ntp_time_config_wrapper result = {
511 .errorcode = OK,
512 .config = check_ntp_time_config_init(),
513 };
514
515 char *owarn = "60";
516 char *ocrit = "120";
501 517
502 while (true) { 518 while (true) {
503 int option = 0; 519 int option = 0;
504 int option_char = getopt_long(argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option); 520 int option_char = getopt_long(argc, argv, "Vhv46qw:c:t:H:p:o:", longopts, &option);
505 if (option_char == -1 || option_char == EOF || option_char == 1) 521 if (option_char == -1 || option_char == EOF || option_char == 1) {
506 break; 522 break;
523 }
507 524
508 switch (option_char) { 525 switch (option_char) {
509 case 'h': 526 case 'h':
@@ -518,7 +535,7 @@ int process_arguments(int argc, char **argv) {
518 verbose++; 535 verbose++;
519 break; 536 break;
520 case 'q': 537 case 'q':
521 quiet = true; 538 result.config.quiet = true;
522 break; 539 break;
523 case 'w': 540 case 'w':
524 owarn = optarg; 541 owarn = optarg;
@@ -527,18 +544,19 @@ int process_arguments(int argc, char **argv) {
527 ocrit = optarg; 544 ocrit = optarg;
528 break; 545 break;
529 case 'H': 546 case 'H':
530 if (!is_host(optarg)) 547 if (!is_host(optarg)) {
531 usage2(_("Invalid hostname/address"), optarg); 548 usage2(_("Invalid hostname/address"), optarg);
532 server_address = strdup(optarg); 549 }
550 result.config.server_address = strdup(optarg);
533 break; 551 break;
534 case 'p': 552 case 'p':
535 port = strdup(optarg); 553 result.config.port = strdup(optarg);
536 break; 554 break;
537 case 't': 555 case 't':
538 socket_timeout = atoi(optarg); 556 socket_timeout = atoi(optarg);
539 break; 557 break;
540 case 'o': 558 case 'o':
541 time_offset = atoi(optarg); 559 result.config.time_offset = atoi(optarg);
542 break; 560 break;
543 case '4': 561 case '4':
544 address_family = AF_INET; 562 address_family = AF_INET;
@@ -557,14 +575,16 @@ int process_arguments(int argc, char **argv) {
557 } 575 }
558 } 576 }
559 577
560 if (server_address == NULL) { 578 if (result.config.server_address == NULL) {
561 usage4(_("Hostname was not supplied")); 579 usage4(_("Hostname was not supplied"));
562 } 580 }
563 581
564 return 0; 582 set_thresholds(&result.config.offset_thresholds, owarn, ocrit);
583
584 return result;
565} 585}
566 586
567char *perfd_offset(double offset) { 587char *perfd_offset(double offset, thresholds *offset_thresholds) {
568 return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true, offset_thresholds->critical->end, false, 0, false, 588 return fperfdata("offset", offset, "s", true, offset_thresholds->warning->end, true, offset_thresholds->critical->end, false, 0, false,
569 0); 589 0);
570} 590}
@@ -577,10 +597,13 @@ int main(int argc, char *argv[]) {
577 /* Parse extra opts if any */ 597 /* Parse extra opts if any */
578 argv = np_extra_opts(&argc, argv, progname); 598 argv = np_extra_opts(&argc, argv, progname);
579 599
580 if (process_arguments(argc, argv) == ERROR) 600 check_ntp_time_config_wrapper tmp_config = process_arguments(argc, argv);
601
602 if (tmp_config.errorcode == ERROR) {
581 usage4(_("Could not parse arguments")); 603 usage4(_("Could not parse arguments"));
604 }
582 605
583 set_thresholds(&offset_thresholds, owarn, ocrit); 606 const check_ntp_time_config config = tmp_config.config;
584 607
585 /* initialize alarm signal handling */ 608 /* initialize alarm signal handling */
586 signal(SIGALRM, socket_timeout_alarm_handler); 609 signal(SIGALRM, socket_timeout_alarm_handler);
@@ -588,13 +611,13 @@ int main(int argc, char *argv[]) {
588 /* set socket timeout */ 611 /* set socket timeout */
589 alarm(socket_timeout); 612 alarm(socket_timeout);
590 613
591 int offset_result = STATE_OK; 614 mp_state_enum offset_result = STATE_OK;
592 int result = STATE_OK; 615 mp_state_enum result = STATE_OK;
593 double offset = offset_request(server_address, &offset_result); 616 double offset = offset_request(config.server_address, config.port, &offset_result, config.time_offset);
594 if (offset_result == STATE_UNKNOWN) { 617 if (offset_result == STATE_UNKNOWN) {
595 result = ((!quiet) ? STATE_UNKNOWN : STATE_CRITICAL); 618 result = ((!config.quiet) ? STATE_UNKNOWN : STATE_CRITICAL);
596 } else { 619 } else {
597 result = get_status(fabs(offset), offset_thresholds); 620 result = get_status(fabs(offset), config.offset_thresholds);
598 } 621 }
599 622
600 char *result_line; 623 char *result_line;
@@ -619,13 +642,14 @@ int main(int argc, char *argv[]) {
619 xasprintf(&perfdata_line, ""); 642 xasprintf(&perfdata_line, "");
620 } else { 643 } else {
621 xasprintf(&result_line, "%s %s %.10g secs", result_line, _("Offset"), offset); 644 xasprintf(&result_line, "%s %s %.10g secs", result_line, _("Offset"), offset);
622 xasprintf(&perfdata_line, "%s", perfd_offset(offset)); 645 xasprintf(&perfdata_line, "%s", perfd_offset(offset, config.offset_thresholds));
623 } 646 }
624 printf("%s|%s\n", result_line, perfdata_line); 647 printf("%s|%s\n", result_line, perfdata_line);
625 648
626 if (server_address != NULL) 649 if (config.server_address != NULL) {
627 free(server_address); 650 free(config.server_address);
628 return result; 651 }
652 exit(result);
629} 653}
630 654
631void print_help(void) { 655void print_help(void) {
diff --git a/plugins/check_ntp_time.d/config.h b/plugins/check_ntp_time.d/config.h
new file mode 100644
index 00000000..99dabbbd
--- /dev/null
+++ b/plugins/check_ntp_time.d/config.h
@@ -0,0 +1,28 @@
1#pragma once
2
3#include "../../config.h"
4#include "thresholds.h"
5#include <stddef.h>
6
7typedef struct {
8 char *server_address;
9 char *port;
10
11 bool quiet;
12 int time_offset;
13
14 thresholds *offset_thresholds;
15} check_ntp_time_config;
16
17check_ntp_time_config check_ntp_time_config_init() {
18 check_ntp_time_config tmp = {
19 .server_address = NULL,
20 .port = "123",
21
22 .quiet = false,
23 .time_offset = 0,
24
25 .offset_thresholds = NULL,
26 };
27 return tmp;
28}
diff --git a/plugins/check_pgsql.c b/plugins/check_pgsql.c
index 6613634d..84305adb 100644
--- a/plugins/check_pgsql.c
+++ b/plugins/check_pgsql.c
@@ -28,6 +28,7 @@
28 * 28 *
29 *****************************************************************************/ 29 *****************************************************************************/
30 30
31#include "states.h"
31const char *progname = "check_pgsql"; 32const char *progname = "check_pgsql";
32const char *copyright = "1999-2024"; 33const char *copyright = "1999-2024";
33const char *email = "devel@monitoring-plugins.org"; 34const char *email = "devel@monitoring-plugins.org";
@@ -35,12 +36,13 @@ const char *email = "devel@monitoring-plugins.org";
35#include "common.h" 36#include "common.h"
36#include "utils.h" 37#include "utils.h"
37#include "utils_cmd.h" 38#include "utils_cmd.h"
39#include "check_pgsql.d/config.h"
40#include "thresholds.h"
38 41
39#include "netutils.h" 42#include "netutils.h"
40#include <libpq-fe.h> 43#include <libpq-fe.h>
41#include <pg_config_manual.h> 44#include <pg_config_manual.h>
42 45
43#define DEFAULT_DB "template1"
44#define DEFAULT_HOST "127.0.0.1" 46#define DEFAULT_HOST "127.0.0.1"
45 47
46/* return the PSQL server version as a 3-tuple */ 48/* return the PSQL server version as a 3-tuple */
@@ -53,33 +55,18 @@ const char *email = "devel@monitoring-plugins.org";
53#define PSQL_SOCKET3(host, port) \ 55#define PSQL_SOCKET3(host, port) \
54 ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, PSQL_IS_UNIX_DOMAIN_SOCKET(host) ? "/.s.PGSQL." : ":", port 56 ((NULL == (host)) || ('\0' == *(host))) ? DEFAULT_PGSOCKET_DIR : host, PSQL_IS_UNIX_DOMAIN_SOCKET(host) ? "/.s.PGSQL." : ":", port
55 57
56enum { 58typedef struct {
57 DEFAULT_PORT = 5432, 59 int errorcode;
58 DEFAULT_WARN = 2, 60 check_pgsql_config config;
59 DEFAULT_CRIT = 8 61} check_pgsql_config_wrapper;
60}; 62static check_pgsql_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
61 63
62static int process_arguments(int /*argc*/, char ** /*argv*/);
63static void print_help(void); 64static void print_help(void);
64static bool is_pg_logname(char * /*username*/); 65static bool is_pg_logname(char * /*username*/);
65static int do_query(PGconn * /*conn*/, char * /*query*/); 66static mp_state_enum do_query(PGconn * /*conn*/, char * /*query*/, const char /*pgqueryname*/[], thresholds * /*qthresholds*/,
67 char * /*query_warning*/, char * /*query_critical*/);
66void print_usage(void); 68void print_usage(void);
67 69
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; 70static int verbose = 0;
84 71
85#define OPTID_QUERYNAME -1000 72#define OPTID_QUERYNAME -1000
@@ -139,21 +126,19 @@ int main(int argc, char **argv) {
139 bindtextdomain(PACKAGE, LOCALEDIR); 126 bindtextdomain(PACKAGE, LOCALEDIR);
140 textdomain(PACKAGE); 127 textdomain(PACKAGE);
141 128
142 /* begin, by setting the parameters for a backend connection if the
143 * parameters are null, then the system will try to use reasonable
144 * defaults by looking up environment variables or, failing that,
145 * using hardwired constants */
146
147 pgoptions = NULL; /* special options to start up the backend server */
148 pgtty = NULL; /* debugging tty for the backend server */
149
150 /* Parse extra opts if any */ 129 /* Parse extra opts if any */
151 argv = np_extra_opts(&argc, argv, progname); 130 argv = np_extra_opts(&argc, argv, progname);
152 131
153 if (process_arguments(argc, argv) == ERROR) 132 check_pgsql_config_wrapper tmp_config = process_arguments(argc, argv);
133 if (tmp_config.errorcode == ERROR) {
154 usage4(_("Could not parse arguments")); 134 usage4(_("Could not parse arguments"));
155 if (verbose > 2) 135 }
136
137 const check_pgsql_config config = tmp_config.config;
138
139 if (verbose > 2) {
156 printf("Arguments initialized\n"); 140 printf("Arguments initialized\n");
141 }
157 142
158 /* Set signal handling and alarm */ 143 /* Set signal handling and alarm */
159 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) { 144 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
@@ -162,25 +147,32 @@ int main(int argc, char **argv) {
162 alarm(timeout_interval); 147 alarm(timeout_interval);
163 148
164 char *conninfo = NULL; 149 char *conninfo = NULL;
165 if (pgparams) 150 if (config.pgparams) {
166 asprintf(&conninfo, "%s ", pgparams); 151 asprintf(&conninfo, "%s ", config.pgparams);
167 152 }
168 asprintf(&conninfo, "%sdbname = '%s'", conninfo ? conninfo : "", dbName); 153
169 if (pghost) 154 asprintf(&conninfo, "%sdbname = '%s'", conninfo ? conninfo : "", config.dbName);
170 asprintf(&conninfo, "%s host = '%s'", conninfo, pghost); 155 if (config.pghost) {
171 if (pgport) 156 asprintf(&conninfo, "%s host = '%s'", conninfo, config.pghost);
172 asprintf(&conninfo, "%s port = '%s'", conninfo, pgport); 157 }
173 if (pgoptions) 158 if (config.pgport) {
174 asprintf(&conninfo, "%s options = '%s'", conninfo, pgoptions); 159 asprintf(&conninfo, "%s port = '%s'", conninfo, config.pgport);
160 }
161 if (config.pgoptions) {
162 asprintf(&conninfo, "%s options = '%s'", conninfo, config.pgoptions);
163 }
175 /* if (pgtty) -- ignored by PQconnectdb */ 164 /* if (pgtty) -- ignored by PQconnectdb */
176 if (pguser) 165 if (config.pguser) {
177 asprintf(&conninfo, "%s user = '%s'", conninfo, pguser); 166 asprintf(&conninfo, "%s user = '%s'", conninfo, config.pguser);
167 }
178 168
179 if (verbose) /* do not include password (see right below) in output */ 169 if (verbose) { /* do not include password (see right below) in output */
180 printf("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, pgpasswd ? " password = <hidden>" : ""); 170 printf("Connecting to PostgreSQL using conninfo: %s%s\n", conninfo, config.pgpasswd ? " password = <hidden>" : "");
171 }
181 172
182 if (pgpasswd) 173 if (config.pgpasswd) {
183 asprintf(&conninfo, "%s password = '%s'", conninfo, pgpasswd); 174 asprintf(&conninfo, "%s password = '%s'", conninfo, config.pgpasswd);
175 }
184 176
185 /* make a connection to the database */ 177 /* make a connection to the database */
186 struct timeval start_timeval; 178 struct timeval start_timeval;
@@ -194,24 +186,26 @@ int main(int argc, char **argv) {
194 end_timeval.tv_usec += 1000000; 186 end_timeval.tv_usec += 1000000;
195 } 187 }
196 double elapsed_time = 188 double elapsed_time =
197 (double)(end_timeval.tv_sec - start_timeval.tv_sec) + (double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0; 189 (double)(end_timeval.tv_sec - start_timeval.tv_sec) + ((double)(end_timeval.tv_usec - start_timeval.tv_usec) / 1000000.0);
198 190
199 if (verbose) 191 if (verbose) {
200 printf("Time elapsed: %f\n", elapsed_time); 192 printf("Time elapsed: %f\n", elapsed_time);
193 }
201 194
202 /* check to see that the backend connection was successfully made */ 195 /* check to see that the backend connection was successfully made */
203 if (verbose) 196 if (verbose) {
204 printf("Verifying connection\n"); 197 printf("Verifying connection\n");
198 }
205 if (PQstatus(conn) == CONNECTION_BAD) { 199 if (PQstatus(conn) == CONNECTION_BAD) {
206 printf(_("CRITICAL - no connection to '%s' (%s).\n"), dbName, PQerrorMessage(conn)); 200 printf(_("CRITICAL - no connection to '%s' (%s).\n"), config.dbName, PQerrorMessage(conn));
207 PQfinish(conn); 201 PQfinish(conn);
208 return STATE_CRITICAL; 202 return STATE_CRITICAL;
209 } 203 }
210 204
211 int status = STATE_UNKNOWN; 205 mp_state_enum status = STATE_UNKNOWN;
212 if (elapsed_time > tcrit) { 206 if (elapsed_time > config.tcrit) {
213 status = STATE_CRITICAL; 207 status = STATE_CRITICAL;
214 } else if (elapsed_time > twarn) { 208 } else if (elapsed_time > config.twarn) {
215 status = STATE_WARNING; 209 status = STATE_WARNING;
216 } else { 210 } else {
217 status = STATE_OK; 211 status = STATE_OK;
@@ -228,21 +222,23 @@ int main(int argc, char **argv) {
228 PQprotocolVersion(conn), PQbackendPID(conn)); 222 PQprotocolVersion(conn), PQbackendPID(conn));
229 } 223 }
230 224
231 printf(_(" %s - database %s (%f sec.)|%s\n"), state_text(status), dbName, elapsed_time, 225 printf(_(" %s - database %s (%f sec.)|%s\n"), state_text(status), config.dbName, elapsed_time,
232 fperfdata("time", elapsed_time, "s", !!(twarn > 0.0), twarn, !!(tcrit > 0.0), tcrit, true, 0, false, 0)); 226 fperfdata("time", elapsed_time, "s", (config.twarn > 0.0), config.twarn, (config.tcrit > 0.0), config.tcrit, true, 0, false, 0));
233 227
234 int query_status = STATE_UNKNOWN; 228 mp_state_enum query_status = STATE_UNKNOWN;
235 if (pgquery) 229 if (config.pgquery) {
236 query_status = do_query(conn, pgquery); 230 query_status = do_query(conn, config.pgquery, config.pgqueryname, config.qthresholds, config.query_warning, config.query_critical);
231 }
237 232
238 if (verbose) 233 if (verbose) {
239 printf("Closing connection\n"); 234 printf("Closing connection\n");
235 }
240 PQfinish(conn); 236 PQfinish(conn);
241 return (pgquery && query_status > status) ? query_status : status; 237 return (config.pgquery && query_status > status) ? query_status : status;
242} 238}
243 239
244/* process command-line arguments */ 240/* process command-line arguments */
245int process_arguments(int argc, char **argv) { 241check_pgsql_config_wrapper process_arguments(int argc, char **argv) {
246 static struct option longopts[] = {{"help", no_argument, 0, 'h'}, 242 static struct option longopts[] = {{"help", no_argument, 0, 'h'},
247 {"version", no_argument, 0, 'V'}, 243 {"version", no_argument, 0, 'V'},
248 {"timeout", required_argument, 0, 't'}, 244 {"timeout", required_argument, 0, 't'},
@@ -262,12 +258,18 @@ int process_arguments(int argc, char **argv) {
262 {"verbose", no_argument, 0, 'v'}, 258 {"verbose", no_argument, 0, 'v'},
263 {0, 0, 0, 0}}; 259 {0, 0, 0, 0}};
264 260
261 check_pgsql_config_wrapper result = {
262 .errorcode = OK,
263 .config = check_pgsql_config_init(),
264 };
265
265 while (true) { 266 while (true) {
266 int option = 0; 267 int option = 0;
267 int option_char = getopt_long(argc, argv, "hVt:c:w:H:P:d:l:p:a:o:q:C:W:v", longopts, &option); 268 int option_char = getopt_long(argc, argv, "hVt:c:w:H:P:d:l:p:a:o:q:C:W:v", longopts, &option);
268 269
269 if (option_char == EOF) 270 if (option_char == EOF) {
270 break; 271 break;
272 }
271 273
272 switch (option_char) { 274 switch (option_char) {
273 case '?': /* usage */ 275 case '?': /* usage */
@@ -279,68 +281,75 @@ int process_arguments(int argc, char **argv) {
279 print_revision(progname, NP_VERSION); 281 print_revision(progname, NP_VERSION);
280 exit(STATE_UNKNOWN); 282 exit(STATE_UNKNOWN);
281 case 't': /* timeout period */ 283 case 't': /* timeout period */
282 if (!is_integer(optarg)) 284 if (!is_integer(optarg)) {
283 usage2(_("Timeout interval must be a positive integer"), optarg); 285 usage2(_("Timeout interval must be a positive integer"), optarg);
284 else 286 } else {
285 timeout_interval = atoi(optarg); 287 timeout_interval = atoi(optarg);
288 }
286 break; 289 break;
287 case 'c': /* critical time threshold */ 290 case 'c': /* critical time threshold */
288 if (!is_nonnegative(optarg)) 291 if (!is_nonnegative(optarg)) {
289 usage2(_("Critical threshold must be a positive integer"), optarg); 292 usage2(_("Critical threshold must be a positive integer"), optarg);
290 else 293 } else {
291 tcrit = strtod(optarg, NULL); 294 result.config.tcrit = strtod(optarg, NULL);
295 }
292 break; 296 break;
293 case 'w': /* warning time threshold */ 297 case 'w': /* warning time threshold */
294 if (!is_nonnegative(optarg)) 298 if (!is_nonnegative(optarg)) {
295 usage2(_("Warning threshold must be a positive integer"), optarg); 299 usage2(_("Warning threshold must be a positive integer"), optarg);
296 else 300 } else {
297 twarn = strtod(optarg, NULL); 301 result.config.twarn = strtod(optarg, NULL);
302 }
298 break; 303 break;
299 case 'C': /* critical query threshold */ 304 case 'C': /* critical query threshold */
300 query_critical = optarg; 305 result.config.query_critical = optarg;
301 break; 306 break;
302 case 'W': /* warning query threshold */ 307 case 'W': /* warning query threshold */
303 query_warning = optarg; 308 result.config.query_warning = optarg;
304 break; 309 break;
305 case 'H': /* host */ 310 case 'H': /* host */
306 if ((*optarg != '/') && (!is_host(optarg))) 311 if ((*optarg != '/') && (!is_host(optarg))) {
307 usage2(_("Invalid hostname/address"), optarg); 312 usage2(_("Invalid hostname/address"), optarg);
308 else 313 } else {
309 pghost = optarg; 314 result.config.pghost = optarg;
315 }
310 break; 316 break;
311 case 'P': /* port */ 317 case 'P': /* port */
312 if (!is_integer(optarg)) 318 if (!is_integer(optarg)) {
313 usage2(_("Port must be a positive integer"), optarg); 319 usage2(_("Port must be a positive integer"), optarg);
314 else 320 } else {
315 pgport = optarg; 321 result.config.pgport = optarg;
322 }
316 break; 323 break;
317 case 'd': /* database name */ 324 case 'd': /* database name */
318 if (strlen(optarg) >= NAMEDATALEN) { 325 if (strlen(optarg) >= NAMEDATALEN) {
319 usage2(_("Database name exceeds the maximum length"), optarg); 326 usage2(_("Database name exceeds the maximum length"), optarg);
320 } 327 }
321 snprintf(dbName, NAMEDATALEN, "%s", optarg); 328 snprintf(result.config.dbName, NAMEDATALEN, "%s", optarg);
322 break; 329 break;
323 case 'l': /* login name */ 330 case 'l': /* login name */
324 if (!is_pg_logname(optarg)) 331 if (!is_pg_logname(optarg)) {
325 usage2(_("User name is not valid"), optarg); 332 usage2(_("User name is not valid"), optarg);
326 else 333 } else {
327 pguser = optarg; 334 result.config.pguser = optarg;
335 }
328 break; 336 break;
329 case 'p': /* authentication password */ 337 case 'p': /* authentication password */
330 case 'a': 338 case 'a':
331 pgpasswd = optarg; 339 result.config.pgpasswd = optarg;
332 break; 340 break;
333 case 'o': 341 case 'o':
334 if (pgparams) 342 if (result.config.pgparams) {
335 asprintf(&pgparams, "%s %s", pgparams, optarg); 343 asprintf(&result.config.pgparams, "%s %s", result.config.pgparams, optarg);
336 else 344 } else {
337 asprintf(&pgparams, "%s", optarg); 345 asprintf(&result.config.pgparams, "%s", optarg);
346 }
338 break; 347 break;
339 case 'q': 348 case 'q':
340 pgquery = optarg; 349 result.config.pgquery = optarg;
341 break; 350 break;
342 case OPTID_QUERYNAME: 351 case OPTID_QUERYNAME:
343 pgqueryname = optarg; 352 result.config.pgqueryname = optarg;
344 break; 353 break;
345 case 'v': 354 case 'v':
346 verbose++; 355 verbose++;
@@ -348,9 +357,9 @@ int process_arguments(int argc, char **argv) {
348 } 357 }
349 } 358 }
350 359
351 set_thresholds(&qthresholds, query_warning, query_critical); 360 set_thresholds(&result.config.qthresholds, result.config.query_warning, result.config.query_critical);
352 361
353 return OK; 362 return result;
354} 363}
355 364
356/** 365/**
@@ -378,8 +387,9 @@ should be added.</para>
378******************************************************************************/ 387******************************************************************************/
379 388
380bool is_pg_logname(char *username) { 389bool is_pg_logname(char *username) {
381 if (strlen(username) > NAMEDATALEN - 1) 390 if (strlen(username) > NAMEDATALEN - 1) {
382 return (false); 391 return (false);
392 }
383 return (true); 393 return (true);
384} 394}
385 395
@@ -394,7 +404,7 @@ bool is_pg_logname(char *username) {
394void print_help(void) { 404void print_help(void) {
395 char *myport; 405 char *myport;
396 406
397 xasprintf(&myport, "%d", DEFAULT_PORT); 407 xasprintf(&myport, "%d", 5432);
398 408
399 print_revision(progname, NP_VERSION); 409 print_revision(progname, NP_VERSION);
400 410
@@ -482,9 +492,11 @@ void print_usage(void) {
482 "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n"); 492 "[-q <query>] [-C <critical query range>] [-W <warning query range>]\n");
483} 493}
484 494
485int do_query(PGconn *conn, char *query) { 495mp_state_enum do_query(PGconn *conn, char *query, const char pgqueryname[], thresholds *qthresholds, char *query_warning,
486 if (verbose) 496 char *query_critical) {
497 if (verbose) {
487 printf("Executing SQL query \"%s\".\n", query); 498 printf("Executing SQL query \"%s\".\n", query);
499 }
488 PGresult *res = PQexec(conn, query); 500 PGresult *res = PQexec(conn, query);
489 501
490 if (PGRES_TUPLES_OK != PQresultStatus(res)) { 502 if (PGRES_TUPLES_OK != PQresultStatus(res)) {
@@ -510,8 +522,9 @@ int do_query(PGconn *conn, char *query) {
510 522
511 char *endptr = NULL; 523 char *endptr = NULL;
512 double value = strtod(val_str, &endptr); 524 double value = strtod(val_str, &endptr);
513 if (verbose) 525 if (verbose) {
514 printf("Query result: %f\n", value); 526 printf("Query result: %f\n", value);
527 }
515 528
516 if (endptr == val_str) { 529 if (endptr == val_str) {
517 printf("QUERY %s - %s: %s\n", _("CRITICAL"), _("Is not a numeric"), val_str); 530 printf("QUERY %s - %s: %s\n", _("CRITICAL"), _("Is not a numeric"), val_str);
@@ -519,11 +532,12 @@ int do_query(PGconn *conn, char *query) {
519 } 532 }
520 533
521 if ((endptr != NULL) && (*endptr != '\0')) { 534 if ((endptr != NULL) && (*endptr != '\0')) {
522 if (verbose) 535 if (verbose) {
523 printf("Garbage after value: %s.\n", endptr); 536 printf("Garbage after value: %s.\n", endptr);
537 }
524 } 538 }
525 539
526 int my_status = get_status(value, qthresholds); 540 mp_state_enum my_status = get_status(value, qthresholds);
527 printf("QUERY %s - ", (my_status == STATE_OK) ? _("OK") 541 printf("QUERY %s - ", (my_status == STATE_OK) ? _("OK")
528 : (my_status == STATE_WARNING) ? _("WARNING") 542 : (my_status == STATE_WARNING) ? _("WARNING")
529 : (my_status == STATE_CRITICAL) ? _("CRITICAL") 543 : (my_status == STATE_CRITICAL) ? _("CRITICAL")
diff --git a/plugins/check_pgsql.d/config.h b/plugins/check_pgsql.d/config.h
new file mode 100644
index 00000000..2d4b8b89
--- /dev/null
+++ b/plugins/check_pgsql.d/config.h
@@ -0,0 +1,61 @@
1#pragma once
2
3#include "../../config.h"
4#include "thresholds.h"
5#include <stddef.h>
6#include <pg_config_manual.h>
7
8#define DEFAULT_DB "template1"
9
10enum {
11 DEFAULT_WARN = 2,
12 DEFAULT_CRIT = 8,
13};
14
15typedef struct {
16 char *pghost; /* host name of the backend server */
17 char *pgport; /* port of the backend server */
18 char *pgoptions; /* special options to start up the backend server */
19 char *pgtty; /* debugging tty for the backend server */
20 char dbName[NAMEDATALEN];
21 char *pguser;
22 char *pgpasswd;
23 char *pgparams;
24 char *pgquery;
25 char *pgqueryname;
26
27 double twarn;
28 double tcrit;
29 thresholds *qthresholds;
30 char *query_warning;
31 char *query_critical;
32} check_pgsql_config;
33
34/* begin, by setting the parameters for a backend connection if the
35 * parameters are null, then the system will try to use reasonable
36 * defaults by looking up environment variables or, failing that,
37 * using hardwired constants
38 * this targets .pgoptions and .pgtty
39 */
40
41check_pgsql_config check_pgsql_config_init() {
42 check_pgsql_config tmp = {
43 .pghost = NULL,
44 .pgport = NULL,
45 .pgoptions = NULL,
46 .pgtty = NULL,
47 .dbName = DEFAULT_DB,
48 .pguser = NULL,
49 .pgpasswd = NULL,
50 .pgparams = NULL,
51 .pgquery = NULL,
52 .pgqueryname = NULL,
53
54 .twarn = (double)DEFAULT_WARN,
55 .tcrit = (double)DEFAULT_CRIT,
56 .qthresholds = NULL,
57 .query_warning = NULL,
58 .query_critical = NULL,
59 };
60 return tmp;
61}