sysvars.c 8.1 KB

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