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