kdb.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5. #include <assert.h>
  6. #include <dlfcn.h>
  7. #include <faux/str.h>
  8. #include <faux/list.h>
  9. #include <klish/khelper.h>
  10. #include <klish/kscheme.h>
  11. #include <klish/kdb.h>
  12. struct kdb_s {
  13. char *name;
  14. char *sofile;
  15. char *options;
  16. uint8_t major;
  17. uint8_t minor;
  18. void *dlhan; // dlopen() handler
  19. void *init_fn;
  20. void *fini_fn;
  21. void *load_fn;
  22. void *deploy_fn;
  23. void *udata; // User data
  24. };
  25. // Simple methods
  26. // Name
  27. KGET_STR(db, name);
  28. // ID
  29. KGET_STR(db, id);
  30. KSET_STR(db, id);
  31. // File
  32. KGET_STR(db, file);
  33. KSET_STR(db, file);
  34. // Conf
  35. KGET_STR(db, conf);
  36. KSET_STR(db, conf);
  37. // Version major number
  38. KGET(db, uint8_t, major);
  39. KSET(db, uint8_t, major);
  40. // Version minor number
  41. KGET(db, uint8_t, minor);
  42. KSET(db, uint8_t, minor);
  43. // User data
  44. KGET(db, void *, udata);
  45. KSET(db, void *, udata);
  46. // COMMAND list
  47. static KCMP_NESTED(db, sym, name);
  48. static KCMP_NESTED_BY_KEY(db, sym, name);
  49. KADD_NESTED(db, sym);
  50. KFIND_NESTED(db, sym);
  51. KNESTED_LEN(db, sym);
  52. KNESTED_ITER(db, sym);
  53. KNESTED_EACH(db, sym);
  54. kdb_t *kdb_new(const char *name)
  55. {
  56. kdb_t *db = NULL;
  57. if (faux_str_is_empty(name))
  58. return NULL;
  59. db = faux_zmalloc(sizeof(*db));
  60. assert(db);
  61. if (!db)
  62. return NULL;
  63. // Initialize
  64. db->name = faux_str_dup(name);
  65. db->id = NULL;
  66. db->file = NULL;
  67. db->conf = NULL;
  68. db->major = 0;
  69. db->minor = 0;
  70. db->dlhan = NULL;
  71. db->init_fn = NULL;
  72. db->fini_fn = NULL;
  73. db->udata = NULL;
  74. // SYM list
  75. db->syms = faux_list_new(FAUX_LIST_SORTED, FAUX_LIST_UNIQUE,
  76. kdb_sym_compare, kdb_sym_kcompare,
  77. (void (*)(void *))ksym_free);
  78. assert(db->syms);
  79. return db;
  80. }
  81. void kdb_free(kdb_t *db)
  82. {
  83. if (!db)
  84. return;
  85. faux_str_free(db->name);
  86. faux_str_free(db->id);
  87. faux_str_free(db->file);
  88. faux_str_free(db->conf);
  89. faux_list_free(db->syms);
  90. if (db->dlhan)
  91. dlclose(db->dlhan);
  92. faux_free(db);
  93. }
  94. bool_t kdb_load(kdb_t *db)
  95. {
  96. char *file_name = NULL;
  97. char *init_name = NULL;
  98. char *fini_name = NULL;
  99. char *major_name = NULL;
  100. char *minor_name = NULL;
  101. int flag = RTLD_NOW | RTLD_LOCAL;
  102. const char *id = NULL;
  103. bool_t retcode = BOOL_FALSE;
  104. uint8_t *ver = NULL;
  105. assert(db);
  106. if (!db)
  107. return BOOL_FALSE;
  108. if (kdb_id(db))
  109. id = kdb_id(db);
  110. else
  111. id = kdb_name(db);
  112. // Shared object file name
  113. if (kdb_file(db))
  114. file_name = faux_str_dup(kdb_file(db));
  115. else
  116. file_name = faux_str_sprintf(Kdb_SONAME_FMT, id);
  117. // Symbol names
  118. major_name = faux_str_sprintf(Kdb_MAJOR_FMT, id);
  119. minor_name = faux_str_sprintf(Kdb_MINOR_FMT, id);
  120. init_name = faux_str_sprintf(Kdb_INIT_FMT, id);
  121. fini_name = faux_str_sprintf(Kdb_FINI_FMT, id);
  122. // Open shared object
  123. db->dlhan = dlopen(file_name, flag);
  124. if (!db->dlhan) {
  125. // fprintf(stderr, "Error: Can't open db \"%s\": %s\n",
  126. // this->name, dlerror());
  127. goto err;
  128. }
  129. // Get db version
  130. ver = (uint8_t *)dlsym(db->dlhan, major_name);
  131. if (!ver)
  132. goto err;
  133. kdb_set_major(db, *ver);
  134. ver = (uint8_t *)dlsym(db->dlhan, minor_name);
  135. if (!ver)
  136. goto err;
  137. kdb_set_minor(db, *ver);
  138. // Get db init function
  139. db->init_fn = dlsym(db->dlhan, init_name);
  140. if (!db->init_fn) {
  141. // fprintf(stderr, "Error: Can't get db \"%s\" init function: %s\n",
  142. // this->name, dlerror());
  143. goto err;
  144. }
  145. // Get db fini function
  146. db->fini_fn = dlsym(db->dlhan, fini_name);
  147. retcode = BOOL_TRUE;
  148. err:
  149. faux_str_free(file_name);
  150. faux_str_free(major_name);
  151. faux_str_free(minor_name);
  152. faux_str_free(init_name);
  153. faux_str_free(fini_name);
  154. if (!retcode && db->dlhan)
  155. dlclose(db->dlhan);
  156. return retcode;
  157. }