Code

867fe41e251938a8abed79d20289583c0ee0a2b9
[nagiosplug.git] / plugins / check_apt.c
1 /******************************************************************************
2  * check_apt.c: check for available updates in apt package management systems
3  * original author: sean finney <seanius@seanius.net> 
4  *                  (with some common bits stolen from check_nagios.c)
5  ******************************************************************************
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  GNU General Public License for more details.
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  $Id$
22  
23 ******************************************************************************/
25 const char *progname = "check_apt";
26 const char *revision = "$Revision$";
27 const char *copyright = "2006";
28 const char *email = "nagiosplug-devel@lists.sourceforge.net";
30 #include "common.h"
31 #include "runcmd.h"
32 #include "utils.h"
34 #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"
36 #define APTGET_UPDATE "/usr/bin/apt-get -q update"
38 int process_arguments(int, char **);
39 void print_help(void);
40 void print_usage(void);
42 int run_update(void);
43 int run_upgrade(int *pkgcount);
45 static int verbose = 0;
46 static int do_update = 0;
47 static int dist_upgrade = 0;
48 static int stderr_warning = 0;
49 static int exec_warning = 0;
51 int main (int argc, char **argv) {
52         int result=STATE_UNKNOWN, packages_available=0;
54         if (process_arguments(argc, argv) == ERROR)
55                 usage_va(_("Could not parse arguments"));
57         /* Set signal handling and alarm timeout */
58         if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
59                 usage_va(_("Cannot catch SIGALRM"));
60         }
62         /* handle timeouts gracefully... */
63         alarm (timeout_interval);
65         /* if they want to run apt-get update first... */
66         if(do_update) result = run_update();
68         /* apt-get upgrade */
69         result = max_state(result, run_upgrade(&packages_available));
71         if(stderr_warning){
72                 fprintf(stderr, "warning, output detected on stderr. ");
73                 fprintf(stderr, "re-run with -v for more information.\n");
74         }
76         if(packages_available > 0){
77                 result = max_state(result, STATE_WARNING);
78         } else {
79                 result = max_state(result, STATE_OK);
80         }
82         printf("APT %s: %d packages available for %s.%s%s%s\n", 
83                state_text(result),
84                packages_available,
85                (dist_upgrade)?"dist-upgrade":"upgrade",
86                (stderr_warning)?" (warnings detected)":"",
87                (stderr_warning && exec_warning)?",":"",
88                (exec_warning)?" (errors detected)":""
89                );
91         return result;
92 }
94 /* process command-line arguments */
95 int process_arguments (int argc, char **argv) {
96         int c;
98         static struct option longopts[] = {
99                 {"version", no_argument, 0, 'V'},
100                 {"help", no_argument, 0, 'h'},
101                 {"verbose", no_argument, 0, 'v'},
102                 {"timeout", required_argument, 0, 't'},
103                 {"update", no_argument, 0, 'u'},
104                 {"dist-upgrade", no_argument, 0, 'd'},
105                 {0, 0, 0, 0}
106         };
108         while(1) {
109                 c = getopt_long(argc, argv, "hVvt:ud", longopts, NULL);
111                 if(c == -1 || c == EOF || c == 1) break;
113                 switch(c) {
114                 case 'h':                                                                       /* help */
115                         print_help();
116                         exit(STATE_OK);
117                 case 'V':                                                                       /* version */
118                         print_revision(progname, revision);
119                         exit(STATE_OK);
120                 case 'v':
121                         verbose++;
122                         break;
123                 case 't':
124                         timeout_interval=atoi(optarg);
125                         break;
126                 case 'd':
127                         dist_upgrade=1;
128                         break;
129                 case 'u':
130                         do_update=1;
131                         break;
132                 default:
133                         /* print short usage statement if args not parsable */
134                         usage_va(_("Unknown argument - %s"), optarg);
135                 }
136         }
138         return OK;
142 /* informative help message */
143 void print_help(void){
144         print_revision(progname, revision);
145         printf(_(COPYRIGHT), copyright, email);
146         printf(_("\
147 This plugin checks for software updates on systems that use\n\
148 package management systems based on the apt-get(8) command\n\
149 found in Debian GNU/Linux\n\
150 \n\n"));
151         print_usage();
152         printf(_(UT_HELP_VRSN));
153         printf(_(UT_TIMEOUT), timeout_interval);
154         printf(_("\n\
155  -d, --dist-upgrade\n\
156    Perform a dist-upgrade instead of normal upgrade.\n\n\
157 The following options require root privileges and should be used with care: \
158 \n\n"));
159         printf(_("\
160  -u, --update\n\
161    First perform an 'apt-get update' (note: you may also need to use -t)\
162 \n\n"));
165 /* simple usage heading */
166 void print_usage(void){
167         printf ("Usage: %s [-du] [-t timeout]\n", progname);
170 /* run an apt-get upgrade */
171 int run_upgrade(int *pkgcount){
172         int i=0, result=STATE_UNKNOWN, pc=0;
173         struct output chld_out, chld_err;
175         /* run the upgrade */
176         if(dist_upgrade==0){
177                 result = np_runcmd(APTGET_UPGRADE, &chld_out, &chld_err, 0);
178         } else {
179                 result = np_runcmd(APTGET_DISTUPGRADE, &chld_out, &chld_err, 0);
180         }
181         /* apt-get only changes exit status if there is an internal error */
182         if(result != 0){
183                 exec_warning=1;
184                 result = STATE_UNKNOWN;
185                 fprintf(stderr, "'%s' exited with non-zero status.\n%s\n",
186                     APTGET_UPGRADE,
187                     "Run again with -v for more info.");
188         }
190         /* parse the output, which should only consist of lines like
191          *
192          * Inst package ....
193          * Conf package ....
194          *
195          * so we'll filter based on "Inst".  If we ever want to do
196          */
197         for(i = 0; i < chld_out.lines; i++) {
198                 if(strncmp(chld_out.line[i], "Inst", 4)==0){
199                         if(verbose){
200                                 printf("%s\n", chld_out.line[i]);
201                         }
202                         pc++;
203                 }
204         }
205         *pkgcount=pc;
207         /* If we get anything on stderr, at least set warning */
208         if(chld_err.buflen){
209                 stderr_warning=1;
210                 result = max_state(result, STATE_WARNING);
211                 if(verbose){
212                         for(i = 0; i < chld_err.lines; i++) {
213                                 printf("%s\n", chld_err.line[i]);
214                         }
215                 }
216         }
217         return result;
220 /* run an apt-get update (needs root) */
221 int run_update(void){
222         int i=0, result=STATE_UNKNOWN;
223         struct output chld_out, chld_err;
225         /* run the upgrade */
226         result = np_runcmd(APTGET_UPDATE, &chld_out, &chld_err, 0);
227         /* apt-get only changes exit status if there is an internal error */
228         if(result != 0){
229                 exec_warning=1;
230                 result = STATE_UNKNOWN;
231                 fprintf(stderr, "'%s' exited with non-zero status.\n",
232                         APTGET_UPDATE);
233         }
235         if(verbose){
236                 for(i = 0; i < chld_out.lines; i++) {
237                         printf("%s\n", chld_out.line[i]);
238                 }
239         }
241         /* If we get anything on stderr, at least set warning */
242         if(chld_err.buflen){
243                 stderr_warning=1;
244                 result = max_state(result, STATE_WARNING);
245                 if(verbose){
246                         for(i = 0; i < chld_err.lines; i++) {
247                                 printf("%s\n", chld_err.line[i]);
248                         }
249                 }
250         }
251         return result;