utils.c 11 KB

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