lsbloader.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. * This program is free software; you can redistribute it and/or modify
  3. * it under the terms of the GNU General Public License as published by
  4. * the Free Software Foundation; version 2 of the License
  5. *
  6. * This program is distributed in the hope that it will be useful,
  7. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. * GNU General Public License for more details.
  10. *
  11. * You should have received a copy of the GNU General Public License
  12. * along with this program; if not, write to the Free Software
  13. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  14. *
  15. * Copyright (C) 2012 John Crispin <blogic@openwrt.org>
  16. */
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #define __USE_GNU
  20. #include <string.h>
  21. #include <regex.h>
  22. #include <glob.h>
  23. #include <libubox/list.h>
  24. #include <libubox/blobmsg_json.h>
  25. #include "libubus.h"
  26. struct initd {
  27. struct list_head list;
  28. char *name;
  29. char *exec;
  30. char *desc;
  31. char *tpl;
  32. char **deps;
  33. int start;
  34. int stop;
  35. };
  36. static LIST_HEAD(initds);
  37. static regex_t pat_provides, pat_require, pat_start, pat_stop, pat_desc, pat_exec, pat_tpl;
  38. static struct ubus_context *ctx;
  39. static struct blob_buf b;
  40. static uint32_t service;
  41. static void initd_free(struct initd *i)
  42. {
  43. if (i->name)
  44. free(i->name);
  45. if (i->exec)
  46. free(i->exec);
  47. if (i->desc)
  48. free(i->desc);
  49. if (i->tpl)
  50. free(i->tpl);
  51. }
  52. static int initd_parse(const char *file)
  53. {
  54. FILE *fp;
  55. struct initd *i;
  56. regmatch_t matches[2];
  57. char buffer[1024];
  58. ssize_t len;
  59. fp = fopen(file, "r");
  60. if (!fp) {
  61. fprintf(stderr, "failed to open %s\n", file);
  62. return -1;
  63. }
  64. len = fread(buffer, 1, sizeof(buffer) - 1, fp);
  65. fclose(fp);
  66. if (len < 1) {
  67. fprintf(stderr, "failed to read from %s\n", file);
  68. return -1;
  69. }
  70. buffer[len] = '\0';
  71. i = calloc(1, sizeof(struct initd));
  72. if (!i) {
  73. fprintf(stderr, "failed to alloc initd struct\n");
  74. return -1;
  75. }
  76. if (!regexec(&pat_provides, buffer, 2, matches, 0))
  77. i->name = strndup(buffer + matches[1].rm_so, (size_t)matches[1].rm_eo - matches[1].rm_so);
  78. if (!regexec(&pat_exec, buffer, 2, matches, 0))
  79. i->exec = strndup(buffer + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
  80. if (!regexec(&pat_desc, buffer, 2, matches, 0))
  81. i->desc = strndup(buffer + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
  82. if (!regexec(&pat_tpl, buffer, 2, matches, 0))
  83. i->tpl = strndup(buffer + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
  84. if (!regexec(&pat_start, buffer, 2, matches, 0))
  85. i->start += atoi(buffer + matches[1].rm_so);
  86. if (!regexec(&pat_stop, buffer, 2, matches, 0))
  87. i->stop += atoi(buffer + matches[1].rm_so);
  88. if (i->name && i->exec)
  89. list_add(&i->list, &initds);
  90. else
  91. initd_free(i);
  92. return 0;
  93. }
  94. static void initd_init(void)
  95. {
  96. int gl_flags = GLOB_NOESCAPE | GLOB_MARK;
  97. glob_t gl;
  98. regcomp(&pat_provides, "# Provides:[ \t]*([a-zA-Z0-9]+)", REG_EXTENDED);
  99. regcomp(&pat_require, "# Required-Start:[ \t]*([a-zA-Z0-9 ]+)", REG_EXTENDED);
  100. regcomp(&pat_start, "# Default-Start:[ \t]*([0-9])", REG_EXTENDED);
  101. regcomp(&pat_stop, "# Default-Stop:[ \t]*([0-9])", REG_EXTENDED);
  102. regcomp(&pat_desc, "# Description:[ \t]*([a-zA-Z0-9 ]+)", REG_EXTENDED);
  103. regcomp(&pat_exec, "# X-Exec:[ \t]*([a-zA-Z0-9/ ]+)", REG_EXTENDED);
  104. regcomp(&pat_tpl, "# X-Template:[ \t]*([a-zA-Z0-9/.]+)", REG_EXTENDED);
  105. if (glob("/etc/rc.d/P*", gl_flags, NULL, &gl) >= 0) {
  106. int j;
  107. for (j = 0; j < gl.gl_pathc; j++)
  108. initd_parse(gl.gl_pathv[j]);
  109. }
  110. globfree(&gl);
  111. regfree(&pat_provides);
  112. regfree(&pat_require);
  113. regfree(&pat_start);
  114. regfree(&pat_stop);
  115. regfree(&pat_desc);
  116. regfree(&pat_exec);
  117. regfree(&pat_tpl);
  118. }
  119. static int init_services(void)
  120. {
  121. struct initd *i;
  122. void *instances, *instance, *command;
  123. list_for_each_entry(i, &initds, list) {
  124. char *t;
  125. blob_buf_init(&b, 0);
  126. blobmsg_add_string(&b, "name", i->name);
  127. instances = blobmsg_open_table(&b, "instances");
  128. instance = blobmsg_open_table(&b, "instance");
  129. command = blobmsg_open_array(&b, "command");
  130. t = strtok(i->exec, " ");
  131. while (t) {
  132. blobmsg_add_string(&b, NULL, t);
  133. t = strtok(NULL, " ");
  134. }
  135. blobmsg_close_array(&b, command);
  136. blobmsg_close_table(&b, instance);
  137. blobmsg_close_table(&b, instances);
  138. ubus_invoke(ctx, service, "add", b.head, NULL, 0, 1000);
  139. }
  140. return 0;
  141. }
  142. int main(int argc, char **argv)
  143. {
  144. int ret;
  145. initd_init();
  146. if (list_empty(&initds))
  147. return 0;
  148. ctx = ubus_connect(NULL);
  149. if (!ctx) {
  150. fprintf(stderr, "Failed to connect to ubus\n");
  151. return -1;
  152. }
  153. ret = ubus_lookup_id(ctx, "service", &service);
  154. if (ret) {
  155. fprintf(stderr, "Failed to find service object: %s\n", ubus_strerror(ret));
  156. return -1;
  157. }
  158. return init_services();
  159. }