utils.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. /*****************************************************************************
  2. *
  3. * utils.c
  4. *
  5. * Library of useful functions for plugins
  6. *
  7. * Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net)
  8. * Copyright (c) 2006 Nagios Plugin Development Team
  9. * License: GPL
  10. *
  11. * $Revision$
  12. * $Date$
  13. ****************************************************************************/
  14. #define LOCAL_TIMEOUT_ALARM_HANDLER
  15. #include "common.h"
  16. #include "utils.h"
  17. #include "utils_base.h"
  18. #include <stdarg.h>
  19. #include <limits.h>
  20. #include <arpa/inet.h>
  21. extern void print_usage (void);
  22. extern const char *progname;
  23. #define STRLEN 64
  24. #define TXTBLK 128
  25. /* **************************************************************************
  26. * max_state(STATE_x, STATE_y)
  27. * compares STATE_x to STATE_y and returns result based on the following
  28. * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
  29. *
  30. * Note that numerically the above does not hold
  31. ****************************************************************************/
  32. int
  33. max_state (int a, int b)
  34. {
  35. if (a == STATE_CRITICAL || b == STATE_CRITICAL)
  36. return STATE_CRITICAL;
  37. else if (a == STATE_WARNING || b == STATE_WARNING)
  38. return STATE_WARNING;
  39. else if (a == STATE_OK || b == STATE_OK)
  40. return STATE_OK;
  41. else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
  42. return STATE_UNKNOWN;
  43. else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
  44. return STATE_DEPENDENT;
  45. else
  46. return max (a, b);
  47. }
  48. void usage (const char *msg)
  49. {
  50. printf ("%s\n", msg);
  51. print_usage ();
  52. exit (STATE_UNKNOWN);
  53. }
  54. void usage_va (const char *fmt, ...)
  55. {
  56. va_list ap;
  57. printf("%s: ", progname);
  58. va_start(ap, fmt);
  59. vprintf(fmt, ap);
  60. va_end(ap);
  61. printf("\n");
  62. exit (STATE_UNKNOWN);
  63. }
  64. void usage2(const char *msg, const char *arg)
  65. {
  66. printf ("%s: %s - %s\n", progname, msg, arg?arg:"(null)" );
  67. print_usage ();
  68. exit (STATE_UNKNOWN);
  69. }
  70. void
  71. usage3 (const char *msg, int arg)
  72. {
  73. printf ("%s: %s - %c\n", progname, msg, arg);
  74. print_usage();
  75. exit (STATE_UNKNOWN);
  76. }
  77. void
  78. usage4 (const char *msg)
  79. {
  80. printf ("%s: %s\n", progname, msg);
  81. print_usage();
  82. exit (STATE_UNKNOWN);
  83. }
  84. void
  85. usage5 (void)
  86. {
  87. print_usage();
  88. exit (STATE_UNKNOWN);
  89. }
  90. char *
  91. clean_revstring (const char *revstring)
  92. {
  93. char plugin_revision[STRLEN];
  94. plugin_revision[0] = 'v';
  95. if (sscanf (revstring,"$Revision: %[0-9.]", plugin_revision + 1) == 1)
  96. return strscpy (NULL, plugin_revision);
  97. else
  98. return strscpy (NULL, "N/A");
  99. }
  100. void
  101. print_revision (const char *command_name, const char *revision_string)
  102. {
  103. char plugin_revision[STRLEN];
  104. printf ("%s %s (%s %s)\n",
  105. command_name, clean_revstring(revision_string), PACKAGE, VERSION);
  106. }
  107. const char *
  108. state_text (int result)
  109. {
  110. switch (result) {
  111. case STATE_OK:
  112. return "OK";
  113. case STATE_WARNING:
  114. return "WARNING";
  115. case STATE_CRITICAL:
  116. return "CRITICAL";
  117. case STATE_DEPENDENT:
  118. return "DEPENDENT";
  119. default:
  120. return "UNKNOWN";
  121. }
  122. }
  123. void
  124. timeout_alarm_handler (int signo)
  125. {
  126. if (signo == SIGALRM) {
  127. printf (_("CRITICAL - Plugin timed out after %d seconds\n"),
  128. timeout_interval);
  129. exit (STATE_CRITICAL);
  130. }
  131. }
  132. int
  133. is_numeric (char *number)
  134. {
  135. char tmp[1];
  136. float x;
  137. if (!number)
  138. return FALSE;
  139. else if (sscanf (number, "%f%c", &x, tmp) == 1)
  140. return TRUE;
  141. else
  142. return FALSE;
  143. }
  144. int
  145. is_positive (char *number)
  146. {
  147. if (is_numeric (number) && atof (number) > 0.0)
  148. return TRUE;
  149. else
  150. return FALSE;
  151. }
  152. int
  153. is_negative (char *number)
  154. {
  155. if (is_numeric (number) && atof (number) < 0.0)
  156. return TRUE;
  157. else
  158. return FALSE;
  159. }
  160. int
  161. is_nonnegative (char *number)
  162. {
  163. if (is_numeric (number) && atof (number) >= 0.0)
  164. return TRUE;
  165. else
  166. return FALSE;
  167. }
  168. int
  169. is_percentage (char *number)
  170. {
  171. int x;
  172. if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
  173. return TRUE;
  174. else
  175. return FALSE;
  176. }
  177. int
  178. is_integer (char *number)
  179. {
  180. long int n;
  181. if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
  182. return FALSE;
  183. n = strtol (number, NULL, 10);
  184. if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
  185. return TRUE;
  186. else
  187. return FALSE;
  188. }
  189. int
  190. is_intpos (char *number)
  191. {
  192. if (is_integer (number) && atoi (number) > 0)
  193. return TRUE;
  194. else
  195. return FALSE;
  196. }
  197. int
  198. is_intneg (char *number)
  199. {
  200. if (is_integer (number) && atoi (number) < 0)
  201. return TRUE;
  202. else
  203. return FALSE;
  204. }
  205. int
  206. is_intnonneg (char *number)
  207. {
  208. if (is_integer (number) && atoi (number) >= 0)
  209. return TRUE;
  210. else
  211. return FALSE;
  212. }
  213. int
  214. is_intpercent (char *number)
  215. {
  216. int i;
  217. if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
  218. return TRUE;
  219. else
  220. return FALSE;
  221. }
  222. int
  223. is_option (char *str)
  224. {
  225. if (!str)
  226. return FALSE;
  227. else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
  228. return TRUE;
  229. else
  230. return FALSE;
  231. }
  232. #ifdef NEED_GETTIMEOFDAY
  233. int
  234. gettimeofday (struct timeval *tv, struct timezone *tz)
  235. {
  236. tv->tv_usec = 0;
  237. tv->tv_sec = (long) time ((time_t) 0);
  238. }
  239. #endif
  240. double
  241. delta_time (struct timeval tv)
  242. {
  243. struct timeval now;
  244. gettimeofday (&now, NULL);
  245. return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
  246. }
  247. long
  248. deltime (struct timeval tv)
  249. {
  250. struct timeval now;
  251. gettimeofday (&now, NULL);
  252. return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec;
  253. }
  254. void
  255. strip (char *buffer)
  256. {
  257. size_t x;
  258. int i;
  259. for (x = strlen (buffer); x >= 1; x--) {
  260. i = x - 1;
  261. if (buffer[i] == ' ' ||
  262. buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
  263. buffer[i] = '\0';
  264. else
  265. break;
  266. }
  267. return;
  268. }
  269. /******************************************************************************
  270. *
  271. * Copies one string to another. Any previously existing data in
  272. * the destination string is lost.
  273. *
  274. * Example:
  275. *
  276. * char *str=NULL;
  277. * str = strscpy("This is a line of text with no trailing newline");
  278. *
  279. *****************************************************************************/
  280. char *
  281. strscpy (char *dest, const char *src)
  282. {
  283. if (src == NULL)
  284. return NULL;
  285. asprintf (&dest, "%s", src);
  286. return dest;
  287. }
  288. /******************************************************************************
  289. *
  290. * Returns a pointer to the next line of a multiline string buffer
  291. *
  292. * Given a pointer string, find the text following the next sequence
  293. * of \r and \n characters. This has the effect of skipping blank
  294. * lines as well
  295. *
  296. * Example:
  297. *
  298. * Given text as follows:
  299. *
  300. * ==============================
  301. * This
  302. * is
  303. * a
  304. *
  305. * multiline string buffer
  306. * ==============================
  307. *
  308. * int i=0;
  309. * char *str=NULL;
  310. * char *ptr=NULL;
  311. * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
  312. * ptr = str;
  313. * while (ptr) {
  314. * printf("%d %s",i++,firstword(ptr));
  315. * ptr = strnl(ptr);
  316. * }
  317. *
  318. * Produces the following:
  319. *
  320. * 1 This
  321. * 2 is
  322. * 3 a
  323. * 4 multiline
  324. *
  325. * NOTE: The 'firstword()' function is conceptual only and does not
  326. * exist in this package.
  327. *
  328. * NOTE: Although the second 'ptr' variable is not strictly needed in
  329. * this example, it is good practice with these utilities. Once
  330. * the * pointer is advance in this manner, it may no longer be
  331. * handled with * realloc(). So at the end of the code fragment
  332. * above, * strscpy(str,"foo") work perfectly fine, but
  333. * strscpy(ptr,"foo") will * cause the the program to crash with
  334. * a segmentation fault.
  335. *
  336. *****************************************************************************/
  337. char *
  338. strnl (char *str)
  339. {
  340. size_t len;
  341. if (str == NULL)
  342. return NULL;
  343. str = strpbrk (str, "\r\n");
  344. if (str == NULL)
  345. return NULL;
  346. len = strspn (str, "\r\n");
  347. if (str[len] == '\0')
  348. return NULL;
  349. str += len;
  350. if (strlen (str) == 0)
  351. return NULL;
  352. return str;
  353. }
  354. /******************************************************************************
  355. *
  356. * Like strscpy, except only the portion of the source string up to
  357. * the provided delimiter is copied.
  358. *
  359. * Example:
  360. *
  361. * str = strpcpy(str,"This is a line of text with no trailing newline","x");
  362. * printf("%s\n",str);
  363. *
  364. * Produces:
  365. *
  366. *This is a line of te
  367. *
  368. *****************************************************************************/
  369. char *
  370. strpcpy (char *dest, const char *src, const char *str)
  371. {
  372. size_t len;
  373. if (src)
  374. len = strcspn (src, str);
  375. else
  376. return NULL;
  377. if (dest == NULL || strlen (dest) < len)
  378. dest = realloc (dest, len + 1);
  379. if (dest == NULL)
  380. die (STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
  381. strncpy (dest, src, len);
  382. dest[len] = '\0';
  383. return dest;
  384. }
  385. /******************************************************************************
  386. *
  387. * Like strscat, except only the portion of the source string up to
  388. * the provided delimiter is copied.
  389. *
  390. * str = strpcpy(str,"This is a line of text with no trailing newline","x");
  391. * str = strpcat(str,"This is a line of text with no trailing newline","x");
  392. * printf("%s\n",str);
  393. *
  394. *This is a line of texThis is a line of tex
  395. *
  396. *****************************************************************************/
  397. char *
  398. strpcat (char *dest, const char *src, const char *str)
  399. {
  400. size_t len, l2;
  401. if (dest)
  402. len = strlen (dest);
  403. else
  404. len = 0;
  405. if (src) {
  406. l2 = strcspn (src, str);
  407. }
  408. else {
  409. return dest;
  410. }
  411. dest = realloc (dest, len + l2 + 1);
  412. if (dest == NULL)
  413. die (STATE_UNKNOWN, _("failed malloc in strscat\n"));
  414. strncpy (dest + len, src, l2);
  415. dest[len + l2] = '\0';
  416. return dest;
  417. }
  418. /******************************************************************************
  419. *
  420. * Print perfdata in a standard format
  421. *
  422. ******************************************************************************/
  423. char *perfdata (const char *label,
  424. long int val,
  425. const char *uom,
  426. int warnp,
  427. long int warn,
  428. int critp,
  429. long int crit,
  430. int minp,
  431. long int minv,
  432. int maxp,
  433. long int maxv)
  434. {
  435. char *data = NULL;
  436. if (strpbrk (label, "'= "))
  437. asprintf (&data, "'%s'=%ld%s;", label, val, uom);
  438. else
  439. asprintf (&data, "%s=%ld%s;", label, val, uom);
  440. if (warnp)
  441. asprintf (&data, "%s%ld;", data, warn);
  442. else
  443. asprintf (&data, "%s;", data);
  444. if (critp)
  445. asprintf (&data, "%s%ld;", data, crit);
  446. else
  447. asprintf (&data, "%s;", data);
  448. if (minp)
  449. asprintf (&data, "%s%ld", data, minv);
  450. if (maxp)
  451. asprintf (&data, "%s;%ld", data, maxv);
  452. return data;
  453. }
  454. char *fperfdata (const char *label,
  455. double val,
  456. const char *uom,
  457. int warnp,
  458. double warn,
  459. int critp,
  460. double crit,
  461. int minp,
  462. double minv,
  463. int maxp,
  464. double maxv)
  465. {
  466. char *data = NULL;
  467. if (strpbrk (label, "'= "))
  468. asprintf (&data, "'%s'=", label);
  469. else
  470. asprintf (&data, "%s=", label);
  471. asprintf (&data, "%s%f", data, val);
  472. asprintf (&data, "%s%s;", data, uom);
  473. if (warnp)
  474. asprintf (&data, "%s%f", data, warn);
  475. asprintf (&data, "%s;", data);
  476. if (critp)
  477. asprintf (&data, "%s%f", data, crit);
  478. asprintf (&data, "%s;", data);
  479. if (minp)
  480. asprintf (&data, "%s%f", data, minv);
  481. if (maxp) {
  482. asprintf (&data, "%s;", data);
  483. asprintf (&data, "%s%f", data, maxv);
  484. }
  485. return data;
  486. }