BadVPN – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 /**
2 * @file NCDUdevMonitor.c
3 * @author Ambroz Bizjak <ambrop7@gmail.com>
4 *
5 * @section LICENSE
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the
15 * names of its contributors may be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29  
30 #include <stddef.h>
31  
32 #include <base/BLog.h>
33 #include <misc/find_program.h>
34  
35 #include <udevmonitor/NCDUdevMonitor.h>
36  
37 #include <generated/blog_channel_NCDUdevMonitor.h>
38  
39 #define PARSER_BUF_SIZE 16384
40 #define PARSER_MAX_PROPERTIES 256
41  
42 static void report_error (NCDUdevMonitor *o)
43 {
44 ASSERT(!o->process_running)
45 ASSERT(!o->input_running)
46  
47 DEBUGERROR(&o->d_err, o->handler_error(o->user, (o->process_was_error || o->input_was_error)));
48 }
49  
50 static void process_handler_terminated (NCDUdevMonitor *o, int normally, uint8_t normally_exit_status)
51 {
52 DebugObject_Access(&o->d_obj);
53 ASSERT(o->process_running)
54  
55 BLog(BLOG_INFO, "process terminated");
56  
57 // set process not running (so we don't try to kill it)
58 o->process_running = 0;
59  
60 // remember process error
61 o->process_was_error = !(normally && normally_exit_status == 0);
62  
63 if (!o->input_running) {
64 report_error(o);
65 return;
66 }
67 }
68  
69 static void process_handler_closed (NCDUdevMonitor *o, int is_error)
70 {
71 DebugObject_Access(&o->d_obj);
72 ASSERT(o->input_running)
73  
74 if (is_error) {
75 BLog(BLOG_ERROR, "pipe error");
76 } else {
77 BLog(BLOG_INFO, "pipe closed");
78 }
79  
80 // disconnect connector
81 StreamRecvConnector_DisconnectInput(&o->connector);
82  
83 // set input not running
84 o->input_running = 0;
85  
86 // remember input error
87 o->input_was_error = is_error;
88  
89 if (!o->process_running) {
90 report_error(o);
91 return;
92 }
93 }
94  
95 static void parser_handler (NCDUdevMonitor *o)
96 {
97 DebugObject_Access(&o->d_obj);
98  
99 o->handler_event(o->user);
100 return;
101 }
102  
103 int NCDUdevMonitor_Init (NCDUdevMonitor *o, BReactor *reactor, BProcessManager *manager, int mode, void *user,
104 NCDUdevMonitor_handler_event handler_event,
105 NCDUdevMonitor_handler_error handler_error)
106 {
107 ASSERT(mode == NCDUDEVMONITOR_MODE_MONITOR_UDEV || mode == NCDUDEVMONITOR_MODE_INFO || mode == NCDUDEVMONITOR_MODE_MONITOR_KERNEL)
108  
109 // init arguments
110 o->user = user;
111 o->handler_event = handler_event;
112 o->handler_error = handler_error;
113  
114 // find programs
115 char *stdbuf_exec = badvpn_find_program("stdbuf");
116 char *udevadm_exec = badvpn_find_program("udevadm");
117 if (!stdbuf_exec) {
118 BLog(BLOG_ERROR, "failed to find stdbuf program");
119 goto fail0;
120 }
121 if (!udevadm_exec) {
122 BLog(BLOG_ERROR, "failed to find udevadm program");
123 goto fail0;
124 }
125  
126 // construct arguments
127 const char *argv_monitor_udev[] = {stdbuf_exec, "-o", "L", udevadm_exec, "monitor", "--udev", "--environment", NULL};
128 const char *argv_monitor_kernel[] = {stdbuf_exec, "-o", "L", udevadm_exec, "monitor", "--kernel", "--environment", NULL};
129 const char *argv_info[] = {stdbuf_exec, "-o", "L", udevadm_exec, "info", "--query", "all", "--export-db", NULL};
130  
131 // choose arguments based on mode
132 const char **argv = NULL; // to remove warning
133 switch (mode) {
134 case NCDUDEVMONITOR_MODE_MONITOR_UDEV: argv = argv_monitor_udev; break;
135 case NCDUDEVMONITOR_MODE_INFO: argv = argv_info; break;
136 case NCDUDEVMONITOR_MODE_MONITOR_KERNEL: argv = argv_monitor_kernel; break;
137 default: ASSERT(0);
138 }
139  
140 // init process
141 if (!BInputProcess_Init(&o->process, reactor, manager, o,
142 (BInputProcess_handler_terminated)process_handler_terminated,
143 (BInputProcess_handler_closed)process_handler_closed
144 )) {
145 BLog(BLOG_ERROR, "BInputProcess_Init failed");
146 goto fail0;
147 }
148  
149 // init connector
150 StreamRecvConnector_Init(&o->connector, BReactor_PendingGroup(reactor));
151 StreamRecvConnector_ConnectInput(&o->connector, BInputProcess_GetInput(&o->process));
152  
153 // init parser
154 if (!NCDUdevMonitorParser_Init(&o->parser, StreamRecvConnector_GetOutput(&o->connector), PARSER_BUF_SIZE, PARSER_MAX_PROPERTIES,
155 (mode == NCDUDEVMONITOR_MODE_INFO), BReactor_PendingGroup(reactor), o,
156 (NCDUdevMonitorParser_handler)parser_handler
157 )) {
158 BLog(BLOG_ERROR, "NCDUdevMonitorParser_Init failed");
159 goto fail1;
160 }
161  
162 // start process
163 if (!BInputProcess_Start(&o->process, stdbuf_exec, (char **)argv, NULL)) {
164 BLog(BLOG_ERROR, "BInputProcess_Start failed");
165 goto fail2;
166 }
167  
168 // set process running, input running
169 o->process_running = 1;
170 o->input_running = 1;
171  
172 free(udevadm_exec);
173 free(stdbuf_exec);
174  
175 DebugError_Init(&o->d_err, BReactor_PendingGroup(reactor));
176 DebugObject_Init(&o->d_obj);
177 return 1;
178  
179 fail2:
180 NCDUdevMonitorParser_Free(&o->parser);
181 fail1:
182 StreamRecvConnector_Free(&o->connector);
183 BInputProcess_Free(&o->process);
184 fail0:
185 free(udevadm_exec);
186 free(stdbuf_exec);
187 return 0;
188 }
189  
190 void NCDUdevMonitor_Free (NCDUdevMonitor *o)
191 {
192 DebugObject_Free(&o->d_obj);
193 DebugError_Free(&o->d_err);
194  
195 // free parser
196 NCDUdevMonitorParser_Free(&o->parser);
197  
198 // free connector
199 StreamRecvConnector_Free(&o->connector);
200  
201 // kill process it it's running
202 if (o->process_running) {
203 BInputProcess_Kill(&o->process);
204 }
205  
206 // free process
207 BInputProcess_Free(&o->process);
208 }
209  
210 void NCDUdevMonitor_Done (NCDUdevMonitor *o)
211 {
212 DebugObject_Access(&o->d_obj);
213 DebugError_AssertNoError(&o->d_err);
214 NCDUdevMonitorParser_AssertReady(&o->parser);
215  
216 NCDUdevMonitorParser_Done(&o->parser);
217 }
218  
219 int NCDUdevMonitor_IsReadyEvent (NCDUdevMonitor *o)
220 {
221 DebugObject_Access(&o->d_obj);
222 DebugError_AssertNoError(&o->d_err);
223 NCDUdevMonitorParser_AssertReady(&o->parser);
224  
225 return NCDUdevMonitorParser_IsReadyEvent(&o->parser);
226 }
227 void NCDUdevMonitor_AssertReady (NCDUdevMonitor *o)
228 {
229 DebugObject_Access(&o->d_obj);
230 DebugError_AssertNoError(&o->d_err);
231 NCDUdevMonitorParser_AssertReady(&o->parser);
232 }
233  
234 int NCDUdevMonitor_GetNumProperties (NCDUdevMonitor *o)
235 {
236 DebugObject_Access(&o->d_obj);
237 DebugError_AssertNoError(&o->d_err);
238 NCDUdevMonitorParser_AssertReady(&o->parser);
239  
240 return NCDUdevMonitorParser_GetNumProperties(&o->parser);
241 }
242  
243 void NCDUdevMonitor_GetProperty (NCDUdevMonitor *o, int index, const char **name, const char **value)
244 {
245 DebugObject_Access(&o->d_obj);
246 DebugError_AssertNoError(&o->d_err);
247 NCDUdevMonitorParser_AssertReady(&o->parser);
248  
249 NCDUdevMonitorParser_GetProperty(&o->parser, index, name, value);
250 }