summaryrefslogtreecommitdiffstats
path: root/plugins/check_apt.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_apt.c')
-rw-r--r--plugins/check_apt.c100
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 */
67int run_update(void); 67int run_update(void);
68/* run an apt-get upgrade */ 68/* run an apt-get upgrade */
69int run_upgrade(int *pkgcount, int *secpkgcount); 69int run_upgrade(int *pkgcount, int *secpkgcount, char ***pkglist, char ***secpkglist);
70/* add another clause to a regexp */ 70/* add another clause to a regexp */
71char* add_to_regexp(char *expr, const char *next); 71char* add_to_regexp(char *expr, const char *next);
72/* extract package name from Inst line */
73char* pkg_name(char *line);
74/* string comparison function for qsort */
75int cmpstringp(const void *p1, const void *p2);
72 76
73/* configuration variables */ 77/* configuration variables */
74static int verbose = 0; /* -v */ 78static int verbose = 0; /* -v */
79static int list = 0; /* list packages available for upgrade */
75static int do_update = 0; /* whether to call apt-get update */ 80static int do_update = 0; /* whether to call apt-get update */
81static int only_critical = 0; /* whether to warn about non-critical updates */
76static upgrade_type upgrade = UPGRADE; /* which type of upgrade to do */ 82static upgrade_type upgrade = UPGRADE; /* which type of upgrade to do */
77static char *upgrade_opts = NULL; /* options to override defaults for upgrade */ 83static char *upgrade_opts = NULL; /* options to override defaults for upgrade */
78static char *update_opts = NULL; /* options to override defaults for update */ 84static 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 */
80static char *do_exclude = NULL; /* regexp to only exclude certain packages */ 86static char *do_exclude = NULL; /* regexp to only exclude certain packages */
81static char *do_critical = NULL; /* regexp specifying critical packages */ 87static char *do_critical = NULL; /* regexp specifying critical packages */
82static char *input_filename = NULL; /* input filename for testing */ 88static char *input_filename = NULL; /* input filename for testing */
89/* number of packages available for upgrade to return WARNING status */
90static int packages_warning = 1;
83 91
84/* other global variables */ 92/* other global variables */
85static int stderr_warning = 0; /* if a cmd issued output on stderr */ 93static int stderr_warning = 0; /* if a cmd issued output on stderr */
86static int exec_warning = 0; /* if a cmd exited non-zero */ 94static int exec_warning = 0; /* if a cmd exited non-zero */
87 95
88int main (int argc, char **argv) { 96int 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 */
220int run_upgrade(int *pkgcount, int *secpkgcount){ 253int 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
407char* 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
428int cmpstringp(const void *p1, const void *p2){
429 return strcmp(* (char * const *) p1, * (char * const *) p2);
430}
431
366char* add_to_regexp(char *expr, const char *next){ 432char* 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
481print_usage(void) 557print_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}