utils.c 11 KB

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