sysvars.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. #include "common.h"
  2. #include "sysvars.h"
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdio.h>
  6. #include <time.h>
  7. bool sysvar_print_updates;
  8. #ifndef DEBUG
  9. # ifdef ON_FPGA
  10. # define DEBUG 0
  11. # else
  12. # define DEBUG sysvar_print_updates
  13. # endif
  14. #endif
  15. static const char *sysvar_bool_tostr(sysvar_t from, char *buf)
  16. {
  17. buf[0] = '0' + from.v_bool;
  18. buf[1] = '\0';
  19. return buf;
  20. }
  21. static bool sysvar_bool_fromstr(sysvar_t *to, const char *from)
  22. {
  23. char c = from[0] | 0x20;
  24. switch (c) {
  25. case '1':
  26. case 't':
  27. case 'y':
  28. case 'j':
  29. case 's':
  30. to->v_bool = true;
  31. return true;
  32. case ' ': /* Blank or null */
  33. case '0':
  34. case 'f':
  35. case 'n':
  36. to->v_bool = false;
  37. return true;
  38. default:
  39. return false;
  40. }
  41. }
  42. const struct sysvar_ops sysvar_bool_ops = {
  43. .tostr = sysvar_bool_tostr,
  44. .fromstr = sysvar_bool_fromstr,
  45. .buflen = BOOL_BUFLEN
  46. };
  47. static const char *sysvar_int_tostr(sysvar_t from, char *buf)
  48. {
  49. snprintf(buf, INT_BUFLEN, "%ld", from.v_int);
  50. return buf;
  51. }
  52. static bool sysvar_int_fromstr(sysvar_t *to, const char *from)
  53. {
  54. char *ep;
  55. long v = strtol(from, &ep, 0);
  56. if (ep == from || *ep)
  57. return false;
  58. to->v_int = v;
  59. return true;
  60. }
  61. const struct sysvar_ops sysvar_int_ops = {
  62. .tostr = sysvar_int_tostr,
  63. .fromstr = sysvar_int_fromstr,
  64. .buflen = INT_BUFLEN
  65. };
  66. static const char *sysvar_uint_tostr(sysvar_t from, char *buf)
  67. {
  68. snprintf(buf, UINT_BUFLEN, "%lu", from.v_uint);
  69. return buf;
  70. }
  71. static bool sysvar_uint_fromstr(sysvar_t *to, const char *from)
  72. {
  73. char *ep;
  74. unsigned long v = strtoul(from, &ep, 0);
  75. if (ep == from || *ep)
  76. return false;
  77. to->v_uint = v;
  78. return true;
  79. }
  80. const struct sysvar_ops sysvar_uint_ops = {
  81. .tostr = sysvar_uint_tostr,
  82. .fromstr = sysvar_uint_fromstr,
  83. .buflen = UINT_BUFLEN
  84. };
  85. static const char *sysvar_str_tostr(sysvar_t from, char *buf)
  86. {
  87. (void)buf;
  88. return from.v_str;
  89. }
  90. static bool sysvar_str_fromstr(sysvar_t *to, const char *from)
  91. {
  92. char *ns;
  93. if (!from) {
  94. ns = NULL;
  95. } else {
  96. ns = strdup(from);
  97. if (!ns)
  98. return false;
  99. }
  100. to->v_str = ns;
  101. return true;
  102. }
  103. static bool sysvar_str_set(sysvar_t *to, sysvar_t from)
  104. {
  105. return sysvar_str_fromstr(to, from.v_str);
  106. }
  107. static size_t sysvar_str_datasize(sysvar_t val)
  108. {
  109. return (val.v_str ? strlen(val.v_str) : 0) + 1;
  110. }
  111. const struct sysvar_ops sysvar_str_ops = {
  112. .set = sysvar_str_set,
  113. .tostr = sysvar_str_tostr,
  114. .fromstr = sysvar_str_fromstr,
  115. .datasize = sysvar_str_datasize
  116. };
  117. static void sysvar_tz_update(sysvar_t val, bool isset)
  118. {
  119. if (isset)
  120. setenv("TZ", val.v_tz, 1);
  121. else
  122. unsetenv("TZ");
  123. tzset();
  124. }
  125. const struct sysvar_ops sysvar_tz_ops = {
  126. .set = sysvar_str_set,
  127. .tostr = sysvar_str_tostr,
  128. .fromstr = sysvar_str_fromstr,
  129. .update = sysvar_tz_update,
  130. .datasize = sysvar_str_datasize
  131. };
  132. static const char *sysvar_ip_tostr(sysvar_t from, char *buf)
  133. {
  134. union ip_bytes {
  135. uint8_t b[4];
  136. uint32_t l;
  137. } ip;
  138. ip.l = from.v_ip;
  139. snprintf(buf, IP_BUFLEN,
  140. "%u.%u.%u.%u", ip.b[0], ip.b[1], ip.b[2], ip.b[3]);
  141. return buf;
  142. }
  143. static bool sysvar_ip_fromstr(sysvar_t *to, const char *str)
  144. {
  145. union ip_bytes {
  146. uint8_t b[4];
  147. uint32_t l;
  148. } ip;
  149. ip.l = 0;
  150. for (int i = 0; i < 4; i++) {
  151. char *ep;
  152. unsigned long v = strtoul(str, &ep, 10);
  153. if (ep == str || *ep != (i == 3) ? '\0' : '.' || v > 255)
  154. return false;
  155. str = ep + 1;
  156. ip.b[i] = v;
  157. }
  158. to->v_ip = ip.l;
  159. return true;
  160. }
  161. const struct sysvar_ops sysvar_ip_ops = {
  162. .tostr = sysvar_ip_tostr,
  163. .fromstr = sysvar_ip_fromstr,
  164. .buflen = IP_BUFLEN
  165. };
  166. static bool sysvar_mac_set(sysvar_t *to, sysvar_t from)
  167. {
  168. uint8_t *buf;
  169. if (!from.v_mac) {
  170. buf = NULL;
  171. } else {
  172. buf = malloc(6);
  173. if (!buf)
  174. return false;
  175. memcpy(buf, from.v_mac, 6);
  176. }
  177. to->v_mac = buf;
  178. return true;
  179. }
  180. static const char *sysvar_mac_tostr(sysvar_t from, char *buf)
  181. {
  182. const uint8_t *m = from.v_mac;
  183. if (!m)
  184. return NULL;
  185. snprintf(buf, MAC_BUFLEN, "%02x:%02x:%02x:%02x:%02x:%02x",
  186. m[0], m[1], m[2], m[3], m[4], m[5]);
  187. return buf;
  188. }
  189. static bool sysvar_mac_fromstr(sysvar_t *to, const char *str)
  190. {
  191. sysvar_t from;
  192. uint8_t m[6];
  193. if (!str) {
  194. from.v_mac = NULL;
  195. } else {
  196. for (int i = 0; i < 6; i++) {
  197. char *ep;
  198. unsigned long v = strtoul(str, &ep, 16);
  199. if (ep == str || *ep != (i == 5) ? '\0' : ':' || v > 255)
  200. return false;
  201. str = ep + 1;
  202. m[i] = v;
  203. }
  204. from.v_mac = m;
  205. }
  206. return sysvar_mac_set(to, from);
  207. }
  208. static size_t sysvar_mac_datasize(sysvar_t val)
  209. {
  210. (void)val;
  211. return 6;
  212. }
  213. const struct sysvar_ops sysvar_mac_ops = {
  214. .set = sysvar_mac_set,
  215. .tostr = sysvar_mac_tostr,
  216. .fromstr = sysvar_mac_fromstr,
  217. .buflen = MAC_BUFLEN,
  218. .datasize = sysvar_mac_datasize
  219. };
  220. /* --- Generic getters/setters --- */
  221. /* Contains the lowest numbered sysvar changed; or sysvar_count if nothing */
  222. enum sysvar_enum sysvar_changed;
  223. sysvar_t getvar(size_t var)
  224. {
  225. if (var >= (size_t)sysvar_count)
  226. return sysvar_defval[sysvar_null];
  227. return sysvar_val[var];
  228. }
  229. static bool do_setvar(size_t var, sysvar_t val, bool is_set)
  230. {
  231. const struct sysvar_ops *type = sysvar_types[var];
  232. sysvar_t *to = &sysvar_val[var];
  233. void *free_ptr = NULL;
  234. if (type->datasize)
  235. free_ptr = to->v_ptr;
  236. if (DEBUG) {
  237. char tostr_buf[SYSVAR_BUFLEN];
  238. printf("%ssetvar %zu %s <- %s\n", is_set ? "" : "un",
  239. var, sysvar_name[var],
  240. notempty(type->tostr(val, tostr_buf)));
  241. }
  242. if (!type->set || (type->datasize && !val.v_ptr)) {
  243. sysvar_val[var] = val;
  244. } else {
  245. if (!type->set(to, val))
  246. return false;
  247. }
  248. if (free_ptr)
  249. free(free_ptr);
  250. if (var < (size_t)sysvar_changed)
  251. sysvar_changed = (enum sysvar_enum)var;
  252. sysvar_isset[var] = is_set;
  253. if (type->update)
  254. type->update(*to, is_set);
  255. return true;
  256. }
  257. bool setvar(size_t var, sysvar_t val)
  258. {
  259. if (var >= (size_t)sysvar_count)
  260. return false;
  261. return do_setvar(var, val, true);
  262. }
  263. bool unsetvar(size_t var)
  264. {
  265. if (var >= (size_t)sysvar_count)
  266. return false;
  267. return do_setvar(var, sysvar_defval[var], false);
  268. }
  269. /* --- Getters/setters converting to/from strings --- */
  270. const char *getvar_tostr(size_t var)
  271. {
  272. static char buf[SYSVAR_BUFLEN];
  273. return getvar_tostr_r(var, buf);
  274. }
  275. const char *getvar_tostr_r(size_t var, char *buf)
  276. {
  277. if (var >= (size_t)sysvar_count)
  278. return NULL;
  279. const struct sysvar_ops *type = sysvar_types[var];
  280. /* A tostr method is required */
  281. return type->tostr(sysvar_val[var], buf);
  282. }
  283. bool setvar_fromstr(size_t var, const char *str)
  284. {
  285. if (var >= (size_t)sysvar_count)
  286. return NULL;
  287. if (!str)
  288. return unsetvar(var);
  289. const struct sysvar_ops *type = sysvar_types[var];
  290. sysvar_t *to = &sysvar_val[var];
  291. void *free_ptr = NULL;
  292. if (type->datasize)
  293. free_ptr = to->v_ptr;
  294. if (DEBUG) {
  295. printf("setvar_fromstr %zu %s <- %s\n", var, sysvar_name[var], str);
  296. }
  297. /* A fromstr method is required */
  298. if (!type->fromstr(to, str))
  299. return false;
  300. if (free_ptr)
  301. free(free_ptr);
  302. if (var < (size_t)sysvar_changed)
  303. sysvar_changed = (enum sysvar_enum)var;
  304. sysvar_isset[var] = true;
  305. if (type->update)
  306. type->update(*to, true);
  307. return true;
  308. }
  309. /* --- Find the index of a specific variable --- */
  310. static int string_ptr_compare(const void *a, const void *b)
  311. {
  312. const char * const *aa = a;
  313. const char * const *bb = b;
  314. return strcmp(*aa, *bb);
  315. }
  316. size_t sysvar_find(size_t ns, const char *name)
  317. {
  318. if (ns >= (size_t)sysvar_nscount)
  319. return 0;
  320. const sysvar_ns_t *nsi = &sysvar_ns[ns];
  321. const char * const *varname;
  322. const size_t count = nsi[1].first - nsi->first;
  323. varname = bsearch(&name, sysvar_name + nsi->first,
  324. count, sizeof *sysvar_name,
  325. string_ptr_compare);
  326. if (!varname)
  327. return 0;
  328. return varname - sysvar_name;
  329. }
  330. /* --- Initialization/reset to defaults --- */
  331. void sysvar_reset(size_t ns)
  332. {
  333. if (ns >= (size_t)sysvar_nscount)
  334. return;
  335. bool print_updates = sysvar_print_updates;
  336. enum sysvar_enum i;
  337. for (i = sysvar_ns[ns].first; i < sysvar_ns[ns+1].first; i++)
  338. unsetvar(i);
  339. sysvar_print_updates = print_updates;
  340. if (sysvar_changed < i)
  341. sysvar_changed = i;
  342. }
  343. void sysvar_init(void)
  344. {
  345. sysvar_print_updates = false;
  346. for (enum sysvar_enum i = sysvar_null+1; i < sysvar_count; i++)
  347. unsetvar(i);
  348. sysvar_changed = sysvar_count;
  349. }