Code

another round of localization cleaning
[nagiosplug.git] / plugins / check_swap.c
1 /******************************************************************************
2 *
3 * Nagios check_disk plugin
4 *
5 * License: GPL
6 * Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
7 * Copyright (c) 2000-2006 nagios-plugins team
8 *
9 * Last Modified: $Date$
10 *
11 * Description:
12 *
13 * This file contains the check_disk plugin
14 *
15 * License Information:
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 *
31 * $Id$
32 *
33 *****************************************************************************/
35 const char *progname = "check_swap";
36 const char *revision = "$Revision$";
37 const char *copyright = "2000-2006";
38 const char *email = "nagiosplug-devel@lists.sourceforge.net";
40 #include "common.h"
41 #include "popen.h"
42 #include "utils.h"
44 int check_swap (int usp, float free_swap_mb);
45 int process_arguments (int argc, char **argv);
46 int validate_arguments (void);
47 void print_usage (void);
48 void print_help (void);
50 int warn_percent = 0;
51 int crit_percent = 0;
52 float warn_size_bytes = 0;
53 float crit_size_bytes= 0;
54 int verbose;
55 int allswaps;
57 int
58 main (int argc, char **argv)
59 {
60         int percent_used, percent;
61         float total_swap_mb = 0, used_swap_mb = 0, free_swap_mb = 0;
62         float dsktotal_mb = 0, dskused_mb = 0, dskfree_mb = 0, tmp_mb = 0;
63         int result = STATE_UNKNOWN;
64         char input_buffer[MAX_INPUT_BUFFER];
65 #ifdef HAVE_PROC_MEMINFO
66         FILE *fp;
67 #else
68         int conv_factor = SWAP_CONVERSION;
69 # ifdef HAVE_SWAP
70         char *temp_buffer;
71         char *swap_command;
72         char *swap_format;
73 # else
74 #  ifdef HAVE_DECL_SWAPCTL
75         int i=0, nswaps=0, swapctl_res=0;
76 #   ifdef CHECK_SWAP_SWAPCTL_SVR4
77         swaptbl_t *tbl=NULL;
78         swapent_t *ent=NULL;
79 #   else
80 #    ifdef CHECK_SWAP_SWAPCTL_BSD
81         struct swapent *ent;
82 #    endif /* CHECK_SWAP_SWAPCTL_BSD */
83 #   endif /* CHECK_SWAP_SWAPCTL_SVR4 */
84 #  endif /* HAVE_DECL_SWAPCTL */
85 # endif
86 #endif
87         char str[32];
88         char *status;
90         setlocale (LC_ALL, "");
91         bindtextdomain (PACKAGE, LOCALEDIR);
92         textdomain (PACKAGE);
94         status = strdup ("");
96         if (process_arguments (argc, argv) == ERROR)
97                 usage4 (_("Could not parse arguments"));
99 #ifdef HAVE_PROC_MEMINFO
100         if (verbose >= 3) {
101                 printf("Reading PROC_MEMINFO at %s\n", PROC_MEMINFO);
102         }
103         fp = fopen (PROC_MEMINFO, "r");
104         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
105                 if (sscanf (input_buffer, "%*[S]%*[w]%*[a]%*[p]%*[:] %f %f %f", &dsktotal_mb, &dskused_mb, &dskfree_mb) == 3) {
106                         dsktotal_mb = dsktotal_mb / 1048576;    /* Apply conversion */
107                         dskused_mb = dskused_mb / 1048576;
108                         dskfree_mb = dskfree_mb / 1048576;
109                         total_swap_mb += dsktotal_mb;
110                         used_swap_mb += dskused_mb;
111                         free_swap_mb += dskfree_mb;
112                         if (allswaps) {
113                                 if (dsktotal_mb == 0)
114                                         percent=100.0;
115                                 else
116                                         percent = 100 * (((double) dskused_mb) / ((double) dsktotal_mb));
117                                 result = max_state (result, check_swap (percent, dskfree_mb));
118                                 if (verbose)
119                                         asprintf (&status, "%s [%.0f (%d%%)]", status, dskfree_mb, 100 - percent);
120                         }
121                 }
122                 else if (sscanf (input_buffer, "%*[S]%*[w]%*[a]%*[p]%[TotalFre]%*[:] %f %*[k]%*[B]", str, &tmp_mb)) {
123                         if (verbose >= 3) {
124                                 printf("Got %s with %f\n", str, tmp_mb);
125                         }
126                         /* I think this part is always in Kb, so convert to mb */
127                         if (strcmp ("Total", str) == 0) {
128                                 dsktotal_mb = tmp_mb / 1024;
129                         }
130                         else if (strcmp ("Free", str) == 0) {
131                                 dskfree_mb = tmp_mb / 1024;
132                         }
133                 }
134         }
135         fclose(fp);
136         dskused_mb = dsktotal_mb - dskfree_mb;
137         total_swap_mb = dsktotal_mb;
138         used_swap_mb = dskused_mb;
139         free_swap_mb = dskfree_mb;
140 #else
141 # ifdef HAVE_SWAP
142         asprintf(&swap_command, "%s", SWAP_COMMAND);
143         asprintf(&swap_format, "%s", SWAP_FORMAT);
145 /* These override the command used if a summary (and thus ! allswaps) is required */
146 /* The summary flag returns more accurate information about swap usage on these OSes */
147 #  ifdef _AIX
148         if (!allswaps) {
149                 asprintf(&swap_command, "%s", "/usr/sbin/lsps -s");
150                 asprintf(&swap_format, "%s", "%f%*s %f");
151                 conv_factor = 1;
152         }
153 #  endif
155         if (verbose >= 2)
156                 printf (_("Command: %s\n"), swap_command);
157         if (verbose >= 3)
158                 printf (_("Format: %s\n"), swap_format);
160         child_process = spopen (swap_command);
161         if (child_process == NULL) {
162                 printf (_("Could not open pipe: %s\n"), swap_command);
163                 return STATE_UNKNOWN;
164         }
166         child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
167         if (child_stderr == NULL)
168                 printf (_("Could not open stderr for %s\n"), swap_command);
170         sprintf (str, "%s", "");
171         /* read 1st line */
172         fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
173         if (strcmp (swap_format, "") == 0) {
174                 temp_buffer = strtok (input_buffer, " \n");
175                 while (temp_buffer) {
176                         if (strstr (temp_buffer, "blocks"))
177                                 sprintf (str, "%s %s", str, "%f");
178                         else if (strstr (temp_buffer, "dskfree"))
179                                 sprintf (str, "%s %s", str, "%f");
180                         else
181                                 sprintf (str, "%s %s", str, "%*s");
182                         temp_buffer = strtok (NULL, " \n");
183                 }
184         }
186 /* If different swap command is used for summary switch, need to read format differently */
187 #  ifdef _AIX
188         if (!allswaps) {
189                 fgets(input_buffer, MAX_INPUT_BUFFER - 1, child_process);       /* Ignore first line */
190                 sscanf (input_buffer, swap_format, &total_swap_mb, &used_swap_mb);
191                 free_swap_mb = total_swap_mb * (100 - used_swap_mb) /100;
192                 used_swap_mb = total_swap_mb - free_swap_mb;
193                 if (verbose >= 3)
194                         printf (_("total=%.0f, used=%.0f, free=%.0f\n"), total_swap_mb, used_swap_mb, free_swap_mb);
195         } else {
196 #  endif
197                 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
198                         sscanf (input_buffer, swap_format, &dsktotal_mb, &dskfree_mb);
200                         dsktotal_mb = dsktotal_mb / conv_factor;
201                         /* AIX lists percent used, so this converts to dskfree in MBs */
202 #  ifdef _AIX
203                         dskfree_mb = dsktotal_mb * (100 - dskfree_mb) / 100;
204 #  else
205                         dskfree_mb = dskfree_mb / conv_factor;
206 #  endif
207                         if (verbose >= 3)
208                                 printf (_("total=%.0f, free=%.0f\n"), dsktotal_mb, dskfree_mb);
210                         dskused_mb = dsktotal_mb - dskfree_mb;
211                         total_swap_mb += dsktotal_mb;
212                         used_swap_mb += dskused_mb;
213                         free_swap_mb += dskfree_mb;
214                         if (allswaps) {
215                                 percent = 100 * (((double) dskused_mb) / ((double) dsktotal_mb));
216                                 result = max_state (result, check_swap (percent, dskfree_mb));
217                                 if (verbose)
218                                         asprintf (&status, "%s [%.0f (%d%%)]", status, dskfree_mb, 100 - percent);
219                         }
220                 }
221 #  ifdef _AIX
222         }
223 #  endif
225         /* If we get anything on STDERR, at least set warning */
226         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
227                 result = max_state (result, STATE_WARNING);
229         /* close stderr */
230         (void) fclose (child_stderr);
232         /* close the pipe */
233         if (spclose (child_process))
234                 result = max_state (result, STATE_WARNING);
235 # else
236 #  ifdef CHECK_SWAP_SWAPCTL_SVR4
238         /* get the number of active swap devices */
239         nswaps=swapctl(SC_GETNSWP, NULL);
241         /* initialize swap table + entries */
242         tbl=(swaptbl_t*)malloc(sizeof(swaptbl_t)+(sizeof(swapent_t)*nswaps));
243         memset(tbl, 0, sizeof(swaptbl_t)+(sizeof(swapent_t)*nswaps));
244         tbl->swt_n=nswaps;
245         for(i=0;i<nswaps;i++){
246                 ent=&tbl->swt_ent[i];
247                 ent->ste_path=(char*)malloc(sizeof(char)*MAXPATHLEN);
248         }
250         /* and now, tally 'em up */
251         swapctl_res=swapctl(SC_LIST, tbl);
252         if(swapctl_res < 0){
253                 perror(_("swapctl failed: "));
254                 result = STATE_WARNING;
255         }
257         for(i=0;i<nswaps;i++){
258                 dsktotal_mb = (float) tbl->swt_ent[i].ste_pages / SWAP_CONVERSION;
259                 dskfree_mb = (float) tbl->swt_ent[i].ste_free /  SWAP_CONVERSION;
260                 dskused_mb = ( dsktotal_mb - dskfree_mb );
262                 if (verbose >= 3)
263                         printf ("dsktotal_mb=%.0f dskfree_mb=%.0f dskused_mb=%.0f\n", dsktotal_mb, dskfree_mb, dskused_mb);
265                 if(allswaps && dsktotal_mb > 0){
266                         percent = 100 * (((double) dskused_mb) / ((double) dsktotal_mb));
267                         result = max_state (result, check_swap (percent, dskfree_mb));
268                         if (verbose) {
269                                 asprintf (&status, "%s [%.0f (%d%%)]", status, dskfree_mb, 100 - percent);
270                         }
271                 }
273                 total_swap_mb += dsktotal_mb;
274                 free_swap_mb += dskfree_mb;
275                 used_swap_mb += dskused_mb;
276         }
278         /* and clean up after ourselves */
279         for(i=0;i<nswaps;i++){
280                 free(tbl->swt_ent[i].ste_path);
281         }
282         free(tbl);
283 #  else
284 #   ifdef CHECK_SWAP_SWAPCTL_BSD
286         /* get the number of active swap devices */
287         nswaps=swapctl(SWAP_NSWAP, NULL, 0);
289         /* initialize swap table + entries */
290         ent=(struct swapent*)malloc(sizeof(struct swapent)*nswaps);
292         /* and now, tally 'em up */
293         swapctl_res=swapctl(SWAP_STATS, ent, nswaps);
294         if(swapctl_res < 0){
295                 perror(_("swapctl failed: "));
296                 result = STATE_WARNING;
297         }
299         for(i=0;i<nswaps;i++){
300                 dsktotal_mb = (float) ent[i].se_nblks / conv_factor;
301                 dskused_mb = (float) ent[i].se_inuse / conv_factor;
302                 dskfree_mb = ( dsktotal_mb - dskused_mb );
304                 if(allswaps && dsktotal_mb > 0){
305                         percent = 100 * (((double) dskused_mb) / ((double) dsktotal_mb));
306                         result = max_state (result, check_swap (percent, dskfree_mb));
307                         if (verbose) {
308                                 asprintf (&status, "%s [%.0f (%d%%)]", status, dskfree_mb, 100 - percent);
309                         }
310                 }
312                 total_swap_mb += dsktotal_mb;
313                 free_swap_mb += dskfree_mb;
314                 used_swap_mb += dskused_mb;
315         }
317         /* and clean up after ourselves */
318         free(ent);
320 #   endif /* CHECK_SWAP_SWAPCTL_BSD */
321 #  endif /* CHECK_SWAP_SWAPCTL_SVR4 */
322 # endif /* HAVE_SWAP */
323 #endif /* HAVE_PROC_MEMINFO */
325         /* if total_swap_mb == 0, let's not divide by 0 */
326         if(total_swap_mb) {
327                 percent_used = 100 * ((double) used_swap_mb) / ((double) total_swap_mb);
328         } else {
329                 percent_used = 0;
330         }
332         result = max_state (result, check_swap (percent_used, free_swap_mb));
333         printf (_("SWAP %s - %d%% free (%d MB out of %d MB) %s|"),
334                         state_text (result),
335                         (100 - percent_used), (int) free_swap_mb, (int) total_swap_mb, status);
337         puts (perfdata ("swap", (long) free_swap_mb, "MB",
338                         TRUE, (long) max (warn_size_bytes/(1024 * 1024), warn_percent/100.0*total_swap_mb),
339                         TRUE, (long) max (crit_size_bytes/(1024 * 1024), crit_percent/100.0*total_swap_mb),
340                         TRUE, 0,
341                         TRUE, (long) total_swap_mb));
343         return result;
348 int
349 check_swap (int usp, float free_swap_mb)
351         int result = STATE_UNKNOWN;
352         float free_swap = free_swap_mb * (1024 * 1024);         /* Convert back to bytes as warn and crit specified in bytes */
353         if (usp >= 0 && crit_percent != 0 && usp >= (100.0 - crit_percent))
354                 result = STATE_CRITICAL;
355         else if (crit_size_bytes > 0 && free_swap <= crit_size_bytes)
356                 result = STATE_CRITICAL;
357         else if (usp >= 0 && warn_percent != 0 && usp >= (100.0 - warn_percent))
358                 result = STATE_WARNING;
359         else if (warn_size_bytes > 0 && free_swap <= warn_size_bytes)
360                 result = STATE_WARNING;
361         else if (usp >= 0.0)
362                 result = STATE_OK;
363         return result;
368 /* process command-line arguments */
369 int
370 process_arguments (int argc, char **argv)
372         int c = 0;  /* option character */
374         int option = 0;
375         static struct option longopts[] = {
376                 {"warning", required_argument, 0, 'w'},
377                 {"critical", required_argument, 0, 'c'},
378                 {"allswaps", no_argument, 0, 'a'},
379                 {"verbose", no_argument, 0, 'v'},
380                 {"version", no_argument, 0, 'V'},
381                 {"help", no_argument, 0, 'h'},
382                 {0, 0, 0, 0}
383         };
385         if (argc < 2)
386                 return ERROR;
388         while (1) {
389                 c = getopt_long (argc, argv, "+?Vvhac:w:", longopts, &option);
391                 if (c == -1 || c == EOF)
392                         break;
394                 switch (c) {
395                 case 'w':                                                                       /* warning size threshold */
396                         if (is_intnonneg (optarg)) {
397                                 warn_size_bytes = (float) atoi (optarg);
398                                 break;
399                         }
400                         else if (strstr (optarg, ",") &&
401                                                          strstr (optarg, "%") &&
402                                                          sscanf (optarg, "%f,%d%%", &warn_size_bytes, &warn_percent) == 2) {
403                                 warn_size_bytes = floorf(warn_size_bytes);
404                                 break;
405                         }
406                         else if (strstr (optarg, "%") &&
407                                                          sscanf (optarg, "%d%%", &warn_percent) == 1) {
408                                 break;
409                         }
410                         else {
411                                 usage4 (_("Warning threshold must be integer or percentage!"));
412                         }
413                 case 'c':                                                                       /* critical size threshold */
414                         if (is_intnonneg (optarg)) {
415                                 crit_size_bytes = (float) atoi (optarg);
416                                 break;
417                         }
418                         else if (strstr (optarg, ",") &&
419                                                          strstr (optarg, "%") &&
420                                                          sscanf (optarg, "%f,%d%%", &crit_size_bytes, &crit_percent) == 2) {
421                                 crit_size_bytes = floorf(crit_size_bytes);
422                                 break;
423                         }
424                         else if (strstr (optarg, "%") &&
425                                                          sscanf (optarg, "%d%%", &crit_percent) == 1) {
426                                 break;
427                         }
428                         else {
429                                 usage4 (_("Critical threshold must be integer or percentage!"));
430                         }
431                 case 'a':                                                                       /* all swap */
432                         allswaps = TRUE;
433                         break;
434                 case 'v':                                                                       /* verbose */
435                         verbose++;
436                         break;
437                 case 'V':                                                                       /* version */
438                         print_revision (progname, revision);
439                         exit (STATE_OK);
440                 case 'h':                                                                       /* help */
441                         print_help ();
442                         exit (STATE_OK);
443                 case '?':                                                                       /* error */
444                         usage2 (_("Unknown argument"), optarg);
445                 }
446         }
448         c = optind;
449         if (c == argc)
450                 return validate_arguments ();
451         if (warn_percent == 0 && is_intnonneg (argv[c]))
452                 warn_percent = atoi (argv[c++]);
454         if (c == argc)
455                 return validate_arguments ();
456         if (crit_percent == 0 && is_intnonneg (argv[c]))
457                 crit_percent = atoi (argv[c++]);
459         if (c == argc)
460                 return validate_arguments ();
461         if (warn_size_bytes == 0 && is_intnonneg (argv[c]))
462                 warn_size_bytes = (float) atoi (argv[c++]);
464         if (c == argc)
465                 return validate_arguments ();
466         if (crit_size_bytes == 0 && is_intnonneg (argv[c]))
467                 crit_size_bytes = (float) atoi (argv[c++]);
469         return validate_arguments ();
474 int
475 validate_arguments (void)
477         if (warn_percent == 0 && crit_percent == 0 && warn_size_bytes == 0
478                         && crit_size_bytes == 0) {
479                 return ERROR;
480         }
481         else if (warn_percent < crit_percent) {
482                 usage4 
483                         (_("Warning percentage should be more than critical percentage"));
484         }
485         else if (warn_size_bytes < crit_size_bytes) {
486                 usage4
487                         (_("Warning free space should be more than critical free space"));
488         }
489         return OK;
494 void
495 print_help (void)
497         print_revision (progname, revision);
499         printf (_(COPYRIGHT), copyright, email);
501         printf ("%s\n", _("Check swap space on local machine."));
503   printf ("\n\n");
504   
505         print_usage ();
507         printf (_(UT_HELP_VRSN));
509         printf (" %s\n", "-w, --warning=INTEGER");
510   printf ("    %s\n", _("Exit with WARNING status if less than INTEGER bytes of swap space are free"));
511   printf (" %s\n", "-w, --warning=PERCENT%%");
512   printf ("    %s\n", _("Exit with WARNING status if less than PERCENT of swap space is free"));
513   printf (" %s\n", "-c, --critical=INTEGER");
514   printf ("    %s\n", _("Exit with CRITICAL status if less than INTEGER bytes of swap space are free"));
515   printf (" %s\n", "-c, --critical=PERCENT%%");
516   printf ("    %s\n", _("Exit with CRITCAL status if less than PERCENT of swap space is free"));
517   printf (" %s\n", "-a, --allswaps");
518   printf ("    %s\n", _("Conduct comparisons for all swap partitions, one by one"));
519   printf (" %s\n", "-v, --verbose");
520   printf ("    %s\n", _("Verbose output. Up to 3 levels"));
521         printf ("\n");
522   printf ("%s\n", _("Notes:"));
523   printf (" %s\n", _("On AIX, if -a is specified, uses lsps -a, otherwise uses lsps -s.\n"));
525         printf (_(UT_SUPPORT));
530 void
531 print_usage (void)
533         printf (_("Usage:"));
534   printf ("%s [-av] -w <percent_free>%% -c <percent_free>%%\n",progname);
535   printf ("%s [-av] -w <bytes_free> -c <bytes_free>\n", progname);