diff options
Diffstat (limited to 'plugins/check_apt.c')
-rw-r--r-- | plugins/check_apt.c | 100 |
1 files changed, 88 insertions, 12 deletions
diff --git a/plugins/check_apt.c b/plugins/check_apt.c index 07622c2f..d7be5750 100644 --- a/plugins/check_apt.c +++ b/plugins/check_apt.c | |||
@@ -66,13 +66,19 @@ char* construct_cmdline(upgrade_type u, const char *opts); | |||
66 | /* run an apt-get update */ | 66 | /* run an apt-get update */ |
67 | int run_update(void); | 67 | int run_update(void); |
68 | /* run an apt-get upgrade */ | 68 | /* run an apt-get upgrade */ |
69 | int run_upgrade(int *pkgcount, int *secpkgcount); | 69 | int run_upgrade(int *pkgcount, int *secpkgcount, char ***pkglist, char ***secpkglist); |
70 | /* add another clause to a regexp */ | 70 | /* add another clause to a regexp */ |
71 | char* add_to_regexp(char *expr, const char *next); | 71 | char* add_to_regexp(char *expr, const char *next); |
72 | /* extract package name from Inst line */ | ||
73 | char* pkg_name(char *line); | ||
74 | /* string comparison function for qsort */ | ||
75 | int cmpstringp(const void *p1, const void *p2); | ||
72 | 76 | ||
73 | /* configuration variables */ | 77 | /* configuration variables */ |
74 | static int verbose = 0; /* -v */ | 78 | static int verbose = 0; /* -v */ |
79 | static int list = 0; /* list packages available for upgrade */ | ||
75 | static int do_update = 0; /* whether to call apt-get update */ | 80 | static int do_update = 0; /* whether to call apt-get update */ |
81 | static int only_critical = 0; /* whether to warn about non-critical updates */ | ||
76 | static upgrade_type upgrade = UPGRADE; /* which type of upgrade to do */ | 82 | static upgrade_type upgrade = UPGRADE; /* which type of upgrade to do */ |
77 | static char *upgrade_opts = NULL; /* options to override defaults for upgrade */ | 83 | static char *upgrade_opts = NULL; /* options to override defaults for upgrade */ |
78 | static char *update_opts = NULL; /* options to override defaults for update */ | 84 | static char *update_opts = NULL; /* options to override defaults for update */ |
@@ -80,13 +86,16 @@ static char *do_include = NULL; /* regexp to only include certain packages */ | |||
80 | static char *do_exclude = NULL; /* regexp to only exclude certain packages */ | 86 | static char *do_exclude = NULL; /* regexp to only exclude certain packages */ |
81 | static char *do_critical = NULL; /* regexp specifying critical packages */ | 87 | static char *do_critical = NULL; /* regexp specifying critical packages */ |
82 | static char *input_filename = NULL; /* input filename for testing */ | 88 | static char *input_filename = NULL; /* input filename for testing */ |
89 | /* number of packages available for upgrade to return WARNING status */ | ||
90 | static int packages_warning = 1; | ||
83 | 91 | ||
84 | /* other global variables */ | 92 | /* other global variables */ |
85 | static int stderr_warning = 0; /* if a cmd issued output on stderr */ | 93 | static int stderr_warning = 0; /* if a cmd issued output on stderr */ |
86 | static int exec_warning = 0; /* if a cmd exited non-zero */ | 94 | static int exec_warning = 0; /* if a cmd exited non-zero */ |
87 | 95 | ||
88 | int main (int argc, char **argv) { | 96 | int main (int argc, char **argv) { |
89 | int result=STATE_UNKNOWN, packages_available=0, sec_count=0; | 97 | int result=STATE_UNKNOWN, packages_available=0, sec_count=0, i=0; |
98 | char **packages_list=NULL, **secpackages_list=NULL; | ||
90 | 99 | ||
91 | /* Parse extra opts if any */ | 100 | /* Parse extra opts if any */ |
92 | argv=np_extra_opts(&argc, argv, progname); | 101 | argv=np_extra_opts(&argc, argv, progname); |
@@ -106,11 +115,11 @@ int main (int argc, char **argv) { | |||
106 | if(do_update) result = run_update(); | 115 | if(do_update) result = run_update(); |
107 | 116 | ||
108 | /* apt-get upgrade */ | 117 | /* apt-get upgrade */ |
109 | result = max_state(result, run_upgrade(&packages_available, &sec_count)); | 118 | result = max_state(result, run_upgrade(&packages_available, &sec_count, &packages_list, &secpackages_list)); |
110 | 119 | ||
111 | if(sec_count > 0){ | 120 | if(sec_count > 0){ |
112 | result = max_state(result, STATE_CRITICAL); | 121 | result = max_state(result, STATE_CRITICAL); |
113 | } else if(packages_available > 0){ | 122 | } else if(packages_available >= packages_warning && only_critical == 0){ |
114 | result = max_state(result, STATE_WARNING); | 123 | result = max_state(result, STATE_WARNING); |
115 | } else if(result > STATE_UNKNOWN){ | 124 | } else if(result > STATE_UNKNOWN){ |
116 | result = STATE_UNKNOWN; | 125 | result = STATE_UNKNOWN; |
@@ -129,6 +138,18 @@ int main (int argc, char **argv) { | |||
129 | sec_count | 138 | sec_count |
130 | ); | 139 | ); |
131 | 140 | ||
141 | if(list) { | ||
142 | qsort(secpackages_list, sec_count, sizeof(char*), cmpstringp); | ||
143 | qsort(packages_list, packages_available-sec_count, sizeof(char*), cmpstringp); | ||
144 | |||
145 | for(i = 0; i < sec_count; i++) | ||
146 | printf("%s (security)\n", secpackages_list[i]); | ||
147 | if (only_critical == 0) { | ||
148 | for(i = 0; i < packages_available - sec_count; i++) | ||
149 | printf("%s\n", packages_list[i]); | ||
150 | } | ||
151 | } | ||
152 | |||
132 | return result; | 153 | return result; |
133 | } | 154 | } |
134 | 155 | ||
@@ -145,25 +166,28 @@ int process_arguments (int argc, char **argv) { | |||
145 | {"upgrade", optional_argument, 0, 'U'}, | 166 | {"upgrade", optional_argument, 0, 'U'}, |
146 | {"no-upgrade", no_argument, 0, 'n'}, | 167 | {"no-upgrade", no_argument, 0, 'n'}, |
147 | {"dist-upgrade", optional_argument, 0, 'd'}, | 168 | {"dist-upgrade", optional_argument, 0, 'd'}, |
169 | {"list", no_argument, 0, 'l'}, | ||
148 | {"include", required_argument, 0, 'i'}, | 170 | {"include", required_argument, 0, 'i'}, |
149 | {"exclude", required_argument, 0, 'e'}, | 171 | {"exclude", required_argument, 0, 'e'}, |
150 | {"critical", required_argument, 0, 'c'}, | 172 | {"critical", required_argument, 0, 'c'}, |
173 | {"only-critical", no_argument, 0, 'o'}, | ||
151 | {"input-file", required_argument, 0, INPUT_FILE_OPT}, | 174 | {"input-file", required_argument, 0, INPUT_FILE_OPT}, |
175 | {"packages-warning", required_argument, 0, 'w'}, | ||
152 | {0, 0, 0, 0} | 176 | {0, 0, 0, 0} |
153 | }; | 177 | }; |
154 | 178 | ||
155 | while(1) { | 179 | while(1) { |
156 | c = getopt_long(argc, argv, "hVvt:u::U::d::ni:e:c:", longopts, NULL); | 180 | c = getopt_long(argc, argv, "hVvt:u::U::d::nli:e:c:ow:", longopts, NULL); |
157 | 181 | ||
158 | if(c == -1 || c == EOF || c == 1) break; | 182 | if(c == -1 || c == EOF || c == 1) break; |
159 | 183 | ||
160 | switch(c) { | 184 | switch(c) { |
161 | case 'h': | 185 | case 'h': |
162 | print_help(); | 186 | print_help(); |
163 | exit(STATE_OK); | 187 | exit(STATE_UNKNOWN); |
164 | case 'V': | 188 | case 'V': |
165 | print_revision(progname, NP_VERSION); | 189 | print_revision(progname, NP_VERSION); |
166 | exit(STATE_OK); | 190 | exit(STATE_UNKNOWN); |
167 | case 'v': | 191 | case 'v': |
168 | verbose++; | 192 | verbose++; |
169 | break; | 193 | break; |
@@ -194,6 +218,9 @@ int process_arguments (int argc, char **argv) { | |||
194 | if(update_opts==NULL) die(STATE_UNKNOWN, "strdup failed"); | 218 | if(update_opts==NULL) die(STATE_UNKNOWN, "strdup failed"); |
195 | } | 219 | } |
196 | break; | 220 | break; |
221 | case 'l': | ||
222 | list=1; | ||
223 | break; | ||
197 | case 'i': | 224 | case 'i': |
198 | do_include=add_to_regexp(do_include, optarg); | 225 | do_include=add_to_regexp(do_include, optarg); |
199 | break; | 226 | break; |
@@ -203,9 +230,15 @@ int process_arguments (int argc, char **argv) { | |||
203 | case 'c': | 230 | case 'c': |
204 | do_critical=add_to_regexp(do_critical, optarg); | 231 | do_critical=add_to_regexp(do_critical, optarg); |
205 | break; | 232 | break; |
233 | case 'o': | ||
234 | only_critical=1; | ||
235 | break; | ||
206 | case INPUT_FILE_OPT: | 236 | case INPUT_FILE_OPT: |
207 | input_filename = optarg; | 237 | input_filename = optarg; |
208 | break; | 238 | break; |
239 | case 'w': | ||
240 | packages_warning = atoi(optarg); | ||
241 | break; | ||
209 | default: | 242 | default: |
210 | /* print short usage statement if args not parsable */ | 243 | /* print short usage statement if args not parsable */ |
211 | usage5(); | 244 | usage5(); |
@@ -217,14 +250,14 @@ int process_arguments (int argc, char **argv) { | |||
217 | 250 | ||
218 | 251 | ||
219 | /* run an apt-get upgrade */ | 252 | /* run an apt-get upgrade */ |
220 | int run_upgrade(int *pkgcount, int *secpkgcount){ | 253 | int run_upgrade(int *pkgcount, int *secpkgcount, char ***pkglist, char ***secpkglist){ |
221 | int i=0, result=STATE_UNKNOWN, regres=0, pc=0, spc=0; | 254 | int i=0, result=STATE_UNKNOWN, regres=0, pc=0, spc=0; |
222 | struct output chld_out, chld_err; | 255 | struct output chld_out, chld_err; |
223 | regex_t ireg, ereg, sreg; | 256 | regex_t ireg, ereg, sreg; |
224 | char *cmdline=NULL, rerrbuf[64]; | 257 | char *cmdline=NULL, rerrbuf[64]; |
225 | 258 | ||
226 | /* initialize ereg as it is possible it is printed while uninitialized */ | 259 | /* initialize ereg as it is possible it is printed while uninitialized */ |
227 | memset(&ereg, "\0", sizeof(ereg.buffer)); | 260 | memset(&ereg, '\0', sizeof(ereg.buffer)); |
228 | 261 | ||
229 | if(upgrade==NO_UPGRADE) return STATE_OK; | 262 | if(upgrade==NO_UPGRADE) return STATE_OK; |
230 | 263 | ||
@@ -273,6 +306,11 @@ int run_upgrade(int *pkgcount, int *secpkgcount){ | |||
273 | cmdline); | 306 | cmdline); |
274 | } | 307 | } |
275 | 308 | ||
309 | *pkglist=malloc(sizeof(char *) * chld_out.lines); | ||
310 | if(!pkglist) die(STATE_UNKNOWN, "malloc failed!\n"); | ||
311 | *secpkglist=malloc(sizeof(char *) * chld_out.lines); | ||
312 | if(!secpkglist) die(STATE_UNKNOWN, "malloc failed!\n"); | ||
313 | |||
276 | /* parse the output, which should only consist of lines like | 314 | /* parse the output, which should only consist of lines like |
277 | * | 315 | * |
278 | * Inst package .... | 316 | * Inst package .... |
@@ -297,6 +335,9 @@ int run_upgrade(int *pkgcount, int *secpkgcount){ | |||
297 | if(regexec(&sreg, chld_out.line[i], 0, NULL, 0)==0){ | 335 | if(regexec(&sreg, chld_out.line[i], 0, NULL, 0)==0){ |
298 | spc++; | 336 | spc++; |
299 | if(verbose) printf("*"); | 337 | if(verbose) printf("*"); |
338 | (*secpkglist)[spc-1] = pkg_name(chld_out.line[i]); | ||
339 | } else { | ||
340 | (*pkglist)[pc-spc-1] = pkg_name(chld_out.line[i]); | ||
300 | } | 341 | } |
301 | if(verbose){ | 342 | if(verbose){ |
302 | printf("*%s\n", chld_out.line[i]); | 343 | printf("*%s\n", chld_out.line[i]); |
@@ -363,6 +404,31 @@ int run_update(void){ | |||
363 | return result; | 404 | return result; |
364 | } | 405 | } |
365 | 406 | ||
407 | char* pkg_name(char *line){ | ||
408 | char *start=NULL, *space=NULL, *pkg=NULL; | ||
409 | int len=0; | ||
410 | |||
411 | start = line + strlen(PKGINST_PREFIX); | ||
412 | len = strlen(start); | ||
413 | |||
414 | space = index(start, ' '); | ||
415 | if(space!=NULL){ | ||
416 | len = space - start; | ||
417 | } | ||
418 | |||
419 | pkg=malloc(sizeof(char)*(len+1)); | ||
420 | if(!pkg) die(STATE_UNKNOWN, "malloc failed!\n"); | ||
421 | |||
422 | strncpy(pkg, start, len); | ||
423 | pkg[len]='\0'; | ||
424 | |||
425 | return pkg; | ||
426 | } | ||
427 | |||
428 | int cmpstringp(const void *p1, const void *p2){ | ||
429 | return strcmp(* (char * const *) p1, * (char * const *) p2); | ||
430 | } | ||
431 | |||
366 | char* add_to_regexp(char *expr, const char *next){ | 432 | char* add_to_regexp(char *expr, const char *next){ |
367 | char *re=NULL; | 433 | char *re=NULL; |
368 | 434 | ||
@@ -445,8 +511,11 @@ print_help (void) | |||
445 | printf (" %s\n", "-d, --dist-upgrade=OPTS"); | 511 | printf (" %s\n", "-d, --dist-upgrade=OPTS"); |
446 | printf (" %s\n", _("Perform a dist-upgrade instead of normal upgrade. Like with -U OPTS")); | 512 | printf (" %s\n", _("Perform a dist-upgrade instead of normal upgrade. Like with -U OPTS")); |
447 | printf (" %s\n", _("can be provided to override the default options.")); | 513 | printf (" %s\n", _("can be provided to override the default options.")); |
448 | printf (" %s\n", " -n, --no-upgrade"); | 514 | printf (" %s\n", "-n, --no-upgrade"); |
449 | printf (" %s\n", _("Do not run the upgrade. Probably not useful (without -u at least).")); | 515 | printf (" %s\n", _("Do not run the upgrade. Probably not useful (without -u at least).")); |
516 | printf (" %s\n", "-l, --list"); | ||
517 | printf (" %s\n", _("List packages available for upgrade. Packages are printed sorted by")); | ||
518 | printf (" %s\n", _("name with security packages listed first.")); | ||
450 | printf (" %s\n", "-i, --include=REGEXP"); | 519 | printf (" %s\n", "-i, --include=REGEXP"); |
451 | printf (" %s\n", _("Include only packages matching REGEXP. Can be specified multiple times")); | 520 | printf (" %s\n", _("Include only packages matching REGEXP. Can be specified multiple times")); |
452 | printf (" %s\n", _("the values will be combined together. Any packages matching this list")); | 521 | printf (" %s\n", _("the values will be combined together. Any packages matching this list")); |
@@ -463,7 +532,14 @@ print_help (void) | |||
463 | printf (" %s\n", _("upgrades for Debian and Ubuntu:")); | 532 | printf (" %s\n", _("upgrades for Debian and Ubuntu:")); |
464 | printf (" \t\%s\n", SECURITY_RE); | 533 | printf (" \t\%s\n", SECURITY_RE); |
465 | printf (" %s\n", _("Note that the package must first match the include list before its")); | 534 | printf (" %s\n", _("Note that the package must first match the include list before its")); |
466 | printf (" %s\n\n", _("information is compared against the critical list.")); | 535 | printf (" %s\n", _("information is compared against the critical list.")); |
536 | printf (" %s\n", "-o, --only-critical"); | ||
537 | printf (" %s\n", _("Only warn about upgrades matching the critical list. The total number")); | ||
538 | printf (" %s\n", _("of upgrades will be printed, but any non-critical upgrades will not cause")); | ||
539 | printf (" %s\n", _("the plugin to return WARNING status.")); | ||
540 | printf (" %s\n", "-w, --packages-warning"); | ||
541 | printf (" %s\n", _("Minumum number of packages available for upgrade to return WARNING status.")); | ||
542 | printf (" %s\n\n", _("Default is 1 package.")); | ||
467 | 543 | ||
468 | printf ("%s\n\n", _("The following options require root privileges and should be used with care:")); | 544 | printf ("%s\n\n", _("The following options require root privileges and should be used with care:")); |
469 | printf (" %s\n", "-u, --update=OPTS"); | 545 | printf (" %s\n", "-u, --update=OPTS"); |
@@ -481,5 +557,5 @@ void | |||
481 | print_usage(void) | 557 | print_usage(void) |
482 | { | 558 | { |
483 | printf ("%s\n", _("Usage:")); | 559 | printf ("%s\n", _("Usage:")); |
484 | printf ("%s [[-d|-u|-U]opts] [-n] [-t timeout]\n", progname); | 560 | printf ("%s [[-d|-u|-U]opts] [-n] [-l] [-t timeout] [-w packages-warning]\n", progname); |
485 | } | 561 | } |