diff options
| author | M. Sean Finney <seanius@users.sourceforge.net> | 2006-03-23 22:58:38 +0000 |
|---|---|---|
| committer | M. Sean Finney <seanius@users.sourceforge.net> | 2006-03-23 22:58:38 +0000 |
| commit | 19d76b3fb60aea7470b7bd03485669a531456d7a (patch) | |
| tree | 8d60862a87f59bba6cfa6ab572926571992d74c6 | |
| parent | ada5f2fe02f4171e82ff7adc39d5f46dda40e4b1 (diff) | |
| download | monitoring-plugins-19d76b3fb60aea7470b7bd03485669a531456d7a.tar.gz | |
- addition of include/exclude option for package names in check_apt,
using POSIX regexp support.
- various commenting and tidying of code/logic/output.
- still haven't committed the Makefile.am/configure.in stuff.
git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@1352 f882894a-f735-0410-b71e-b25c423dba1c
| -rw-r--r-- | plugins/check_apt.c | 148 |
1 files changed, 117 insertions, 31 deletions
diff --git a/plugins/check_apt.c b/plugins/check_apt.c index 867fe41e..3fdee5d3 100644 --- a/plugins/check_apt.c +++ b/plugins/check_apt.c | |||
| @@ -30,23 +30,36 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; | |||
| 30 | #include "common.h" | 30 | #include "common.h" |
| 31 | #include "runcmd.h" | 31 | #include "runcmd.h" |
| 32 | #include "utils.h" | 32 | #include "utils.h" |
| 33 | #include <regex.h> | ||
| 33 | 34 | ||
| 35 | /* for now define the various apt calls as constants. this may need | ||
| 36 | * to change later. */ | ||
| 34 | #define APTGET_UPGRADE "/usr/bin/apt-get -o 'Debug::NoLocking=true' -s -qq upgrade" | 37 | #define APTGET_UPGRADE "/usr/bin/apt-get -o 'Debug::NoLocking=true' -s -qq upgrade" |
| 35 | #define APTGET_DISTUPGRADE "/usr/bin/apt-get -o 'Debug::NoLocking=true' -s -qq dist-upgrade" | 38 | #define APTGET_DISTUPGRADE "/usr/bin/apt-get -o 'Debug::NoLocking=true' -s -qq dist-upgrade" |
| 36 | #define APTGET_UPDATE "/usr/bin/apt-get -q update" | 39 | #define APTGET_UPDATE "/usr/bin/apt-get -q update" |
| 37 | 40 | ||
| 41 | /* some standard functions */ | ||
| 38 | int process_arguments(int, char **); | 42 | int process_arguments(int, char **); |
| 39 | void print_help(void); | 43 | void print_help(void); |
| 40 | void print_usage(void); | 44 | void print_usage(void); |
| 41 | 45 | ||
| 46 | /* run an apt-get update */ | ||
| 42 | int run_update(void); | 47 | int run_update(void); |
| 48 | /* run an apt-get upgrade */ | ||
| 43 | int run_upgrade(int *pkgcount); | 49 | int run_upgrade(int *pkgcount); |
| 50 | /* add another clause to a regexp */ | ||
| 51 | char* add_to_regexp(char *expr, const char *next); | ||
| 52 | |||
| 53 | /* configuration variables */ | ||
| 54 | static int verbose = 0; /* -v */ | ||
| 55 | static int do_update = 0; /* whether to call apt-get update */ | ||
| 56 | static int dist_upgrade = 0; /* whether to call apt-get dist-upgrade */ | ||
| 57 | static char* do_include = NULL; /* regexp to only include certain packages */ | ||
| 58 | static char* do_exclude = NULL; /* regexp to only exclude certain packages */ | ||
| 44 | 59 | ||
| 45 | static int verbose = 0; | 60 | /* other global variables */ |
| 46 | static int do_update = 0; | 61 | static int stderr_warning = 0; /* if a cmd issued output on stderr */ |
| 47 | static int dist_upgrade = 0; | 62 | static int exec_warning = 0; /* if a cmd exited non-zero */ |
| 48 | static int stderr_warning = 0; | ||
| 49 | static int exec_warning = 0; | ||
| 50 | 63 | ||
| 51 | int main (int argc, char **argv) { | 64 | int main (int argc, char **argv) { |
| 52 | int result=STATE_UNKNOWN, packages_available=0; | 65 | int result=STATE_UNKNOWN, packages_available=0; |
| @@ -68,24 +81,20 @@ int main (int argc, char **argv) { | |||
| 68 | /* apt-get upgrade */ | 81 | /* apt-get upgrade */ |
| 69 | result = max_state(result, run_upgrade(&packages_available)); | 82 | result = max_state(result, run_upgrade(&packages_available)); |
| 70 | 83 | ||
| 71 | if(stderr_warning){ | ||
| 72 | fprintf(stderr, "warning, output detected on stderr. "); | ||
| 73 | fprintf(stderr, "re-run with -v for more information.\n"); | ||
| 74 | } | ||
| 75 | |||
| 76 | if(packages_available > 0){ | 84 | if(packages_available > 0){ |
| 77 | result = max_state(result, STATE_WARNING); | 85 | result = max_state(result, STATE_WARNING); |
| 78 | } else { | 86 | } else { |
| 79 | result = max_state(result, STATE_OK); | 87 | result = max_state(result, STATE_OK); |
| 80 | } | 88 | } |
| 81 | 89 | ||
| 82 | printf("APT %s: %d packages available for %s.%s%s%s\n", | 90 | printf("APT %s: %d packages available for %s.%s%s%s%s\n", |
| 83 | state_text(result), | 91 | state_text(result), |
| 84 | packages_available, | 92 | packages_available, |
| 85 | (dist_upgrade)?"dist-upgrade":"upgrade", | 93 | (dist_upgrade)?"dist-upgrade":"upgrade", |
| 86 | (stderr_warning)?" (warnings detected)":"", | 94 | (stderr_warning)?" warnings detected":"", |
| 87 | (stderr_warning && exec_warning)?",":"", | 95 | (stderr_warning && exec_warning)?",":"", |
| 88 | (exec_warning)?" (errors detected)":"" | 96 | (exec_warning)?" errors detected":"", |
| 97 | (stderr_warning||exec_warning)?". run with -v for information.":"" | ||
| 89 | ); | 98 | ); |
| 90 | 99 | ||
| 91 | return result; | 100 | return result; |
| @@ -102,19 +111,21 @@ int process_arguments (int argc, char **argv) { | |||
| 102 | {"timeout", required_argument, 0, 't'}, | 111 | {"timeout", required_argument, 0, 't'}, |
| 103 | {"update", no_argument, 0, 'u'}, | 112 | {"update", no_argument, 0, 'u'}, |
| 104 | {"dist-upgrade", no_argument, 0, 'd'}, | 113 | {"dist-upgrade", no_argument, 0, 'd'}, |
| 114 | {"include", no_argument, 0, 'i'}, | ||
| 115 | {"exclude", no_argument, 0, 'e'}, | ||
| 105 | {0, 0, 0, 0} | 116 | {0, 0, 0, 0} |
| 106 | }; | 117 | }; |
| 107 | 118 | ||
| 108 | while(1) { | 119 | while(1) { |
| 109 | c = getopt_long(argc, argv, "hVvt:ud", longopts, NULL); | 120 | c = getopt_long(argc, argv, "hVvt:udi:e:", longopts, NULL); |
| 110 | 121 | ||
| 111 | if(c == -1 || c == EOF || c == 1) break; | 122 | if(c == -1 || c == EOF || c == 1) break; |
| 112 | 123 | ||
| 113 | switch(c) { | 124 | switch(c) { |
| 114 | case 'h': /* help */ | 125 | case 'h': |
| 115 | print_help(); | 126 | print_help(); |
| 116 | exit(STATE_OK); | 127 | exit(STATE_OK); |
| 117 | case 'V': /* version */ | 128 | case 'V': |
| 118 | print_revision(progname, revision); | 129 | print_revision(progname, revision); |
| 119 | exit(STATE_OK); | 130 | exit(STATE_OK); |
| 120 | case 'v': | 131 | case 'v': |
| @@ -129,6 +140,12 @@ int process_arguments (int argc, char **argv) { | |||
| 129 | case 'u': | 140 | case 'u': |
| 130 | do_update=1; | 141 | do_update=1; |
| 131 | break; | 142 | break; |
| 143 | case 'i': | ||
| 144 | do_include=add_to_regexp(do_include, optarg); | ||
| 145 | break; | ||
| 146 | case 'e': | ||
| 147 | do_exclude=add_to_regexp(do_exclude, optarg); | ||
| 148 | break; | ||
| 132 | default: | 149 | default: |
| 133 | /* print short usage statement if args not parsable */ | 150 | /* print short usage statement if args not parsable */ |
| 134 | usage_va(_("Unknown argument - %s"), optarg); | 151 | usage_va(_("Unknown argument - %s"), optarg); |
| @@ -153,7 +170,15 @@ found in Debian GNU/Linux\n\ | |||
| 153 | printf(_(UT_TIMEOUT), timeout_interval); | 170 | printf(_(UT_TIMEOUT), timeout_interval); |
| 154 | printf(_("\n\ | 171 | printf(_("\n\ |
| 155 | -d, --dist-upgrade\n\ | 172 | -d, --dist-upgrade\n\ |
| 156 | Perform a dist-upgrade instead of normal upgrade.\n\n\ | 173 | Perform a dist-upgrade instead of normal upgrade.\n\ |
| 174 | -i, --include=REGEXP\n\ | ||
| 175 | Include only packages matching REGEXP. Can be specified multiple times;\n\ | ||
| 176 | the values will be combined together. Default is to include all packages.\n\ | ||
| 177 | -e, --exclude=REGEXP\n\ | ||
| 178 | Exclude packages matching REGEXP from the list of packages that would\n\ | ||
| 179 | otherwise be excluded. Can be specified multiple times; the values\n\ | ||
| 180 | will be combined together. Default is to exclude no packages.\n\n")); | ||
| 181 | printf(_("\ | ||
| 157 | The following options require root privileges and should be used with care: \ | 182 | The following options require root privileges and should be used with care: \ |
| 158 | \n\n")); | 183 | \n\n")); |
| 159 | printf(_("\ | 184 | printf(_("\ |
| @@ -169,8 +194,37 @@ void print_usage(void){ | |||
| 169 | 194 | ||
| 170 | /* run an apt-get upgrade */ | 195 | /* run an apt-get upgrade */ |
| 171 | int run_upgrade(int *pkgcount){ | 196 | int run_upgrade(int *pkgcount){ |
| 172 | int i=0, result=STATE_UNKNOWN, pc=0; | 197 | int i=0, result=STATE_UNKNOWN, regres=0, pc=0; |
| 173 | struct output chld_out, chld_err; | 198 | struct output chld_out, chld_err; |
| 199 | regex_t ireg, ereg; | ||
| 200 | char rerrbuf[64]; | ||
| 201 | const char *default_include_expr="^Inst"; | ||
| 202 | |||
| 203 | /* compile the regexps */ | ||
| 204 | if(do_include!=NULL){ | ||
| 205 | regres=regcomp(&ireg, do_include, REG_EXTENDED); | ||
| 206 | if(regres!=0) { | ||
| 207 | regerror(regres, &ireg, rerrbuf, 64); | ||
| 208 | die(STATE_UNKNOWN, "%s: Error compiling regexp: %s", | ||
| 209 | progname, rerrbuf); | ||
| 210 | } | ||
| 211 | } else { | ||
| 212 | regres=regcomp(&ireg, default_include_expr, REG_EXTENDED); | ||
| 213 | if(regres!=0) { | ||
| 214 | regerror(regres, &ireg, rerrbuf, 64); | ||
| 215 | die(STATE_UNKNOWN, "%s: Error compiling regexp: %s", | ||
| 216 | progname, rerrbuf); | ||
| 217 | } | ||
| 218 | } | ||
| 219 | if(do_exclude!=NULL){ | ||
| 220 | regres=regcomp(&ereg, do_exclude, REG_EXTENDED); | ||
| 221 | if(regres!=0) { | ||
| 222 | regerror(regres, &ereg, rerrbuf, 64); | ||
| 223 | die(STATE_UNKNOWN, "%s: Error compiling regexp: %s", | ||
| 224 | progname, rerrbuf); | ||
| 225 | } | ||
| 226 | } | ||
| 227 | |||
| 174 | 228 | ||
| 175 | /* run the upgrade */ | 229 | /* run the upgrade */ |
| 176 | if(dist_upgrade==0){ | 230 | if(dist_upgrade==0){ |
| @@ -178,13 +232,14 @@ int run_upgrade(int *pkgcount){ | |||
| 178 | } else { | 232 | } else { |
| 179 | result = np_runcmd(APTGET_DISTUPGRADE, &chld_out, &chld_err, 0); | 233 | result = np_runcmd(APTGET_DISTUPGRADE, &chld_out, &chld_err, 0); |
| 180 | } | 234 | } |
| 181 | /* apt-get only changes exit status if there is an internal error */ | 235 | /* apt-get upgrade only changes exit status if there is an |
| 236 | * internal error when run in dry-run mode. therefore we will | ||
| 237 | * treat such an error as UNKNOWN */ | ||
| 182 | if(result != 0){ | 238 | if(result != 0){ |
| 183 | exec_warning=1; | 239 | exec_warning=1; |
| 184 | result = STATE_UNKNOWN; | 240 | result = STATE_UNKNOWN; |
| 185 | fprintf(stderr, "'%s' exited with non-zero status.\n%s\n", | 241 | fprintf(stderr, "'%s' exited with non-zero status.\n", |
| 186 | APTGET_UPGRADE, | 242 | APTGET_UPGRADE); |
| 187 | "Run again with -v for more info."); | ||
| 188 | } | 243 | } |
| 189 | 244 | ||
| 190 | /* parse the output, which should only consist of lines like | 245 | /* parse the output, which should only consist of lines like |
| @@ -192,14 +247,25 @@ int run_upgrade(int *pkgcount){ | |||
| 192 | * Inst package .... | 247 | * Inst package .... |
| 193 | * Conf package .... | 248 | * Conf package .... |
| 194 | * | 249 | * |
| 195 | * so we'll filter based on "Inst". If we ever want to do | 250 | * so we'll filter based on "Inst" for the time being. later |
| 251 | * we may need to switch to the --print-uris output format, | ||
| 252 | * in which case the logic here will slightly change. | ||
| 196 | */ | 253 | */ |
| 197 | for(i = 0; i < chld_out.lines; i++) { | 254 | for(i = 0; i < chld_out.lines; i++) { |
| 198 | if(strncmp(chld_out.line[i], "Inst", 4)==0){ | 255 | if(verbose){ |
| 199 | if(verbose){ | 256 | printf("%s\n", chld_out.line[i]); |
| 200 | printf("%s\n", chld_out.line[i]); | 257 | } |
| 258 | /* if it is a package we care about */ | ||
| 259 | if(regexec(&ireg, chld_out.line[i], 0, NULL, 0)==0){ | ||
| 260 | /* if we're not excluding, or it's not in the | ||
| 261 | * list of stuff to exclude */ | ||
| 262 | if(do_exclude==NULL || | ||
| 263 | regexec(&ereg, chld_out.line[i], 0, NULL, 0)!=0){ | ||
| 264 | pc++; | ||
| 265 | if(verbose){ | ||
| 266 | printf("*%s\n", chld_out.line[i]); | ||
| 267 | } | ||
| 201 | } | 268 | } |
| 202 | pc++; | ||
| 203 | } | 269 | } |
| 204 | } | 270 | } |
| 205 | *pkgcount=pc; | 271 | *pkgcount=pc; |
| @@ -210,7 +276,7 @@ int run_upgrade(int *pkgcount){ | |||
| 210 | result = max_state(result, STATE_WARNING); | 276 | result = max_state(result, STATE_WARNING); |
| 211 | if(verbose){ | 277 | if(verbose){ |
| 212 | for(i = 0; i < chld_err.lines; i++) { | 278 | for(i = 0; i < chld_err.lines; i++) { |
| 213 | printf("%s\n", chld_err.line[i]); | 279 | fprintf(stderr, "%s\n", chld_err.line[i]); |
| 214 | } | 280 | } |
| 215 | } | 281 | } |
| 216 | } | 282 | } |
| @@ -224,10 +290,12 @@ int run_update(void){ | |||
| 224 | 290 | ||
| 225 | /* run the upgrade */ | 291 | /* run the upgrade */ |
| 226 | result = np_runcmd(APTGET_UPDATE, &chld_out, &chld_err, 0); | 292 | result = np_runcmd(APTGET_UPDATE, &chld_out, &chld_err, 0); |
| 227 | /* apt-get only changes exit status if there is an internal error */ | 293 | /* apt-get update changes exit status if it can't fetch packages. |
| 294 | * since we were explicitly asked to do so, this is treated as | ||
| 295 | * a critical error. */ | ||
| 228 | if(result != 0){ | 296 | if(result != 0){ |
| 229 | exec_warning=1; | 297 | exec_warning=1; |
| 230 | result = STATE_UNKNOWN; | 298 | result = STATE_CRITICAL; |
| 231 | fprintf(stderr, "'%s' exited with non-zero status.\n", | 299 | fprintf(stderr, "'%s' exited with non-zero status.\n", |
| 232 | APTGET_UPDATE); | 300 | APTGET_UPDATE); |
| 233 | } | 301 | } |
| @@ -244,9 +312,27 @@ int run_update(void){ | |||
| 244 | result = max_state(result, STATE_WARNING); | 312 | result = max_state(result, STATE_WARNING); |
| 245 | if(verbose){ | 313 | if(verbose){ |
| 246 | for(i = 0; i < chld_err.lines; i++) { | 314 | for(i = 0; i < chld_err.lines; i++) { |
| 247 | printf("%s\n", chld_err.line[i]); | 315 | fprintf(stderr, "%s\n", chld_err.line[i]); |
| 248 | } | 316 | } |
| 249 | } | 317 | } |
| 250 | } | 318 | } |
| 251 | return result; | 319 | return result; |
| 252 | } | 320 | } |
| 321 | |||
| 322 | char* add_to_regexp(char *expr, const char *next){ | ||
| 323 | char *re=NULL; | ||
| 324 | |||
| 325 | if(expr==NULL){ | ||
| 326 | re=malloc(sizeof(char)*(strlen("^Inst () ")+strlen(next)+1)); | ||
| 327 | if(!re) die(STATE_UNKNOWN, "malloc failed!\n"); | ||
| 328 | sprintf(re, "^Inst (%s) ", next); | ||
| 329 | } else { | ||
| 330 | /* resize it, adding an extra char for the new '|' separator */ | ||
| 331 | re=realloc(expr, sizeof(char)*strlen(expr)+1+strlen(next)+1); | ||
| 332 | if(!re) die(STATE_UNKNOWN, "realloc failed!\n"); | ||
| 333 | /* append it starting at ')' in the old re */ | ||
| 334 | sprintf((char*)(re+strlen(re)-2), "|%s) ", next); | ||
| 335 | } | ||
| 336 | |||
| 337 | return re; | ||
| 338 | } | ||
