NCDUdevMonitor.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /**
  2. * @file NCDUdevMonitor.c
  3. * @author Ambroz Bizjak <ambrop7@gmail.com>
  4. *
  5. * @section LICENSE
  6. *
  7. * This file is part of BadVPN.
  8. *
  9. * BadVPN is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2
  11. * as published by the Free Software Foundation.
  12. *
  13. * BadVPN is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. */
  22. #include <stddef.h>
  23. #include <system/BLog.h>
  24. #include <udevmonitor/NCDUdevMonitor.h>
  25. #include <generated/blog_channel_NCDUdevMonitor.h>
  26. #define STDBUF_EXEC "/usr/bin/stdbuf"
  27. #define UDEVADM_EXEC "/sbin/udevadm"
  28. #define PARSER_BUF_SIZE 16384
  29. #define PARSER_MAX_PROPERTIES 256
  30. static void report_error (NCDUdevMonitor *o)
  31. {
  32. ASSERT(!o->process_running)
  33. ASSERT(!o->input_running)
  34. DEBUGERROR(&o->d_err, o->handler_error(o->user, (o->process_was_error || o->input_was_error)));
  35. }
  36. static void process_handler_terminated (NCDUdevMonitor *o, int normally, uint8_t normally_exit_status)
  37. {
  38. DebugObject_Access(&o->d_obj);
  39. ASSERT(o->process_running)
  40. BLog(BLOG_INFO, "process terminated");
  41. // set process not running (so we don't try to kill it)
  42. o->process_running = 0;
  43. // remember process error
  44. o->process_was_error = !(normally && normally_exit_status == 0);
  45. if (!o->input_running) {
  46. report_error(o);
  47. return;
  48. }
  49. }
  50. static void process_handler_closed (NCDUdevMonitor *o, int is_error)
  51. {
  52. DebugObject_Access(&o->d_obj);
  53. ASSERT(o->input_running)
  54. if (is_error) {
  55. BLog(BLOG_ERROR, "pipe error");
  56. } else {
  57. BLog(BLOG_INFO, "pipe closed");
  58. }
  59. // disconnect connector
  60. StreamRecvConnector_DisconnectInput(&o->connector);
  61. // set input not running
  62. o->input_running = 0;
  63. // remember input error
  64. o->input_was_error = is_error;
  65. if (!o->process_running) {
  66. report_error(o);
  67. return;
  68. }
  69. }
  70. static void parser_handler (NCDUdevMonitor *o)
  71. {
  72. DebugObject_Access(&o->d_obj);
  73. o->handler_event(o->user);
  74. return;
  75. }
  76. int NCDUdevMonitor_Init (NCDUdevMonitor *o, BReactor *reactor, BProcessManager *manager, int is_info_mode, void *user,
  77. NCDUdevMonitor_handler_event handler_event,
  78. NCDUdevMonitor_handler_error handler_error)
  79. {
  80. ASSERT(is_info_mode == 0 || is_info_mode == 1)
  81. // init arguments
  82. o->user = user;
  83. o->handler_event = handler_event;
  84. o->handler_error = handler_error;
  85. // construct arguments
  86. const char *argv_monitor[] = {STDBUF_EXEC, "-o", "L", UDEVADM_EXEC, "monitor", "--udev", "--property", NULL};
  87. const char *argv_info[] = {STDBUF_EXEC, "-o", "L", UDEVADM_EXEC, "info", "--query", "all", "--export-db", NULL};
  88. const char **argv = (is_info_mode ? argv_info : argv_monitor);
  89. // init process
  90. if (!BInputProcess_Init(&o->process, STDBUF_EXEC, (char **)argv, NULL, reactor, manager, o,
  91. (BInputProcess_handler_terminated)process_handler_terminated,
  92. (BInputProcess_handler_closed)process_handler_closed
  93. )) {
  94. BLog(BLOG_ERROR, "BInputProcess_Init failed");
  95. goto fail0;
  96. }
  97. // init connector
  98. StreamRecvConnector_Init(&o->connector, BReactor_PendingGroup(reactor));
  99. StreamRecvConnector_ConnectInput(&o->connector, BInputProcess_GetInput(&o->process));
  100. // init parser
  101. if (!NCDUdevMonitorParser_Init(&o->parser, StreamRecvConnector_GetOutput(&o->connector), PARSER_BUF_SIZE, PARSER_MAX_PROPERTIES,
  102. is_info_mode, BReactor_PendingGroup(reactor), o,
  103. (NCDUdevMonitorParser_handler)parser_handler
  104. )) {
  105. BLog(BLOG_ERROR, "NCDUdevMonitorParser_Init failed");
  106. goto fail1;
  107. }
  108. // set process running, input running
  109. o->process_running = 1;
  110. o->input_running = 1;
  111. DebugError_Init(&o->d_err, BReactor_PendingGroup(reactor));
  112. DebugObject_Init(&o->d_obj);
  113. return 1;
  114. fail1:
  115. StreamRecvConnector_Free(&o->connector);
  116. BInputProcess_Kill(&o->process);
  117. BInputProcess_Free(&o->process);
  118. fail0:
  119. return 0;
  120. }
  121. void NCDUdevMonitor_Free (NCDUdevMonitor *o)
  122. {
  123. DebugObject_Free(&o->d_obj);
  124. DebugError_Free(&o->d_err);
  125. // free parser
  126. NCDUdevMonitorParser_Free(&o->parser);
  127. // free connector
  128. StreamRecvConnector_Free(&o->connector);
  129. // kill process it it's running
  130. if (o->process_running) {
  131. BInputProcess_Kill(&o->process);
  132. }
  133. // free process
  134. BInputProcess_Free(&o->process);
  135. }
  136. void NCDUdevMonitor_Done (NCDUdevMonitor *o)
  137. {
  138. DebugObject_Access(&o->d_obj);
  139. DebugError_AssertNoError(&o->d_err);
  140. NCDUdevMonitorParser_AssertReady(&o->parser);
  141. NCDUdevMonitorParser_Done(&o->parser);
  142. }
  143. int NCDUdevMonitor_IsReadyEvent (NCDUdevMonitor *o)
  144. {
  145. DebugObject_Access(&o->d_obj);
  146. DebugError_AssertNoError(&o->d_err);
  147. NCDUdevMonitorParser_AssertReady(&o->parser);
  148. return NCDUdevMonitorParser_IsReadyEvent(&o->parser);
  149. }
  150. void NCDUdevMonitor_AssertReady (NCDUdevMonitor *o)
  151. {
  152. DebugObject_Access(&o->d_obj);
  153. DebugError_AssertNoError(&o->d_err);
  154. NCDUdevMonitorParser_AssertReady(&o->parser);
  155. }
  156. int NCDUdevMonitor_GetNumProperties (NCDUdevMonitor *o)
  157. {
  158. DebugObject_Access(&o->d_obj);
  159. DebugError_AssertNoError(&o->d_err);
  160. NCDUdevMonitorParser_AssertReady(&o->parser);
  161. return NCDUdevMonitorParser_GetNumProperties(&o->parser);
  162. }
  163. void NCDUdevMonitor_GetProperty (NCDUdevMonitor *o, int index, const char **name, const char **value)
  164. {
  165. DebugObject_Access(&o->d_obj);
  166. DebugError_AssertNoError(&o->d_err);
  167. NCDUdevMonitorParser_AssertReady(&o->parser);
  168. NCDUdevMonitorParser_GetProperty(&o->parser, index, name, value);
  169. }