util.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. #define _GNU_SOURCE
  2. #include "util.h"
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <assert.h>
  7. #include "includes.h"
  8. #include "xalloc.h"
  9. #include <unistd.h>
  10. #include <sched.h>
  11. #include <pthread.h>
  12. #include <sys/types.h>
  13. #include <pwd.h>
  14. #define MAX_SPLITS 128
  15. int max_int(int a, int b) {
  16. if (a >= b) {
  17. return a;
  18. }
  19. return b;
  20. }
  21. void split_string(char* in, int *len, char***results)
  22. {
  23. char** fields = xcalloc(MAX_SPLITS, sizeof(char*));
  24. int retvlen = 0;
  25. char *currloc = in;
  26. // parse csv into a set of strings
  27. while (1) {
  28. assert(retvlen < MAX_SPLITS);
  29. size_t len = strcspn(currloc, ", ");
  30. if (len == 0) {
  31. currloc++;
  32. } else {
  33. char *new = xmalloc(len+1);
  34. strncpy(new, currloc, len);
  35. new[len] = '\0';
  36. fields[retvlen++] = new;
  37. assert(fields[retvlen-1]);
  38. }
  39. if (len == strlen(currloc)) {
  40. break;
  41. }
  42. currloc += len;
  43. }
  44. *results = fields;
  45. *len = retvlen;
  46. }
  47. void fprintw(FILE *f, char *s, size_t w)
  48. {
  49. if (strlen(s) <= w) {
  50. fprintf(f, "%s", s);
  51. return;
  52. }
  53. // process each line individually in order to
  54. // respect existing line breaks in string.
  55. char *news = strdup(s);
  56. char *pch = strtok(news, "\n");
  57. while (pch) {
  58. if (strlen(pch) <= w) {
  59. printf("%s\n", pch);
  60. pch = strtok(NULL, "\n");
  61. continue;
  62. }
  63. char *t = pch;
  64. while (strlen(t)) {
  65. size_t numchars = 0; //number of chars to print
  66. char *tmp = t;
  67. while (1) {
  68. size_t new = strcspn(tmp, " ") + 1;
  69. if (new == strlen(tmp) || new > w) {
  70. // there are no spaces in the string, so, just
  71. // print the entire thing on one line;
  72. numchars += new;
  73. break;
  74. } else if (numchars + new > w) {
  75. // if we added any more, we'd be over w chars so
  76. // time to print the line and move on to the next.
  77. break;
  78. } else {
  79. tmp += (size_t) new;
  80. numchars += new;
  81. }
  82. }
  83. fprintf(f, "%.*s\n", (int) numchars, t);
  84. t += (size_t) numchars;
  85. if (t > pch + (size_t)strlen(pch)) {
  86. break;
  87. }
  88. }
  89. pch = strtok(NULL, "\n");
  90. }
  91. free(news);
  92. }
  93. // pretty print elapsed (or estimated) number of seconds
  94. void time_string(uint32_t time, int est, char *buf, size_t len)
  95. {
  96. int y = time / 31556736;
  97. int d = (time % 31556736) / 86400;
  98. int h = (time % 86400) / 3600;
  99. int m = (time % 3600) / 60;
  100. int s = time % 60;
  101. if (est) {
  102. if (y > 0) {
  103. snprintf(buf, len, "%d years", y);
  104. } else if (d > 9) {
  105. snprintf(buf, len, "%dd", d);
  106. } else if (d > 0) {
  107. snprintf(buf, len, "%dd%02dh", d, h);
  108. } else if (h > 9) {
  109. snprintf(buf, len, "%dh", h);
  110. } else if (h > 0) {
  111. snprintf(buf, len, "%dh%02dm", h, m);
  112. } else if (m > 9) {
  113. snprintf(buf, len, "%dm", m);
  114. } else if (m > 0) {
  115. snprintf(buf, len, "%dm%02ds", m, s);
  116. } else {
  117. snprintf(buf, len, "%ds", s);
  118. }
  119. } else {
  120. if (d > 0) {
  121. snprintf(buf, len, "%dd%d:%02d:%02d", d, h, m, s);
  122. } else if (h > 0) {
  123. snprintf(buf, len, "%d:%02d:%02d", h, m, s);
  124. } else {
  125. snprintf(buf, len, "%d:%02d", m, s);
  126. }
  127. }
  128. }
  129. // pretty print quantities
  130. void number_string(uint32_t n, char *buf, size_t len)
  131. {
  132. int figs = 0;
  133. if (n < 1000) {
  134. snprintf(buf, len, "%u ", n);
  135. } else if (n < 1000000) {
  136. if (n < 10000) {
  137. figs = 2;
  138. } else if (n < 100000) {
  139. figs = 1;
  140. }
  141. snprintf(buf, len, "%0.*f K", figs, (float)n/1000.);
  142. } else {
  143. if (figs < 10000000) {
  144. figs = 2;
  145. } else if (figs < 100000000) {
  146. figs = 1;
  147. }
  148. snprintf(buf, len, "%0.*f M", figs, (float)n/1000000.);
  149. }
  150. }
  151. int parse_mac(macaddr_t *out, char *in)
  152. {
  153. if (strlen(in) < MAC_ADDR_LEN*3-1)
  154. return 0;
  155. char octet[4];
  156. octet[2] = '\0';
  157. for (int i=0; i < MAC_ADDR_LEN; i++) {
  158. if (i < MAC_ADDR_LEN-1 && in[i*3+2] != ':') {
  159. return 0;
  160. }
  161. strncpy(octet, &in[i*3], 2);
  162. char *err = NULL;
  163. long b = strtol(octet, &err, 16);
  164. if (err && *err != '\0') {
  165. return 0;
  166. }
  167. out[i] = b & 0xFF;
  168. }
  169. return 1;
  170. }
  171. int check_range(int v, int min, int max)
  172. {
  173. if (v < min || v > max) {
  174. return EXIT_FAILURE;
  175. }
  176. return EXIT_SUCCESS;
  177. }
  178. int file_exists(char *name)
  179. {
  180. FILE *file = fopen(name, "r");
  181. if (!file)
  182. return 0;
  183. fclose(file);
  184. return 1;
  185. }
  186. #if defined(__APPLE__)
  187. #include <uuid/uuid.h>
  188. #endif
  189. int drop_privs()
  190. {
  191. struct passwd *pw;
  192. if (geteuid() != 0) {
  193. /* Not root */
  194. return EXIT_SUCCESS;
  195. }
  196. if ((pw = getpwnam("nobody")) != NULL) {
  197. if (setuid(pw->pw_uid) == 0) {
  198. return EXIT_SUCCESS; // success
  199. }
  200. }
  201. return EXIT_FAILURE;
  202. }
  203. #if defined(__APPLE__)
  204. #include <mach/thread_act.h>
  205. int set_cpu(uint32_t core)
  206. {
  207. mach_port_t tid = pthread_mach_thread_np(pthread_self());
  208. struct thread_affinity_policy policy;
  209. policy.affinity_tag = core;
  210. kern_return_t ret = thread_policy_set(tid,THREAD_AFFINITY_POLICY,
  211. (thread_policy_t) &policy,THREAD_AFFINITY_POLICY_COUNT);
  212. if (ret != KERN_SUCCESS) {
  213. return EXIT_FAILURE;
  214. }
  215. return EXIT_SUCCESS;
  216. }
  217. #else
  218. #if defined(__FreeBSD__) || defined(__NetBSD__)
  219. #include <sys/param.h>
  220. #include <sys/cpuset.h>
  221. #define cpu_set_t cpuset_t
  222. #endif
  223. int set_cpu(uint32_t core)
  224. {
  225. cpu_set_t cpuset;
  226. CPU_ZERO(&cpuset);
  227. CPU_SET(core, &cpuset);
  228. if (pthread_setaffinity_np(pthread_self(),
  229. sizeof(cpu_set_t), &cpuset) != 0) {
  230. return EXIT_FAILURE;
  231. }
  232. return EXIT_SUCCESS;
  233. }
  234. #endif