check_apt.c 6.7 KB

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