treewide: rename exec_timeout to rpc_exec_timeout
[project/rpcd.git] / exec.c
1 /*
2 * rpcd - UBUS RPC server
3 *
4 * Copyright (C) 2013-2014 Jo-Philipp Wich <jow@openwrt.org>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <fcntl.h>
20 #include <errno.h>
21 #include <unistd.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <limits.h>
25 #include <dirent.h>
26 #include <sys/stat.h>
27 #include <sys/wait.h>
28
29 #include <rpcd/exec.h>
30
31 static int
32 rpc_errno_status(void)
33 {
34 switch (errno)
35 {
36 case EACCES:
37 return UBUS_STATUS_PERMISSION_DENIED;
38
39 case ENOTDIR:
40 return UBUS_STATUS_INVALID_ARGUMENT;
41
42 case ENOENT:
43 return UBUS_STATUS_NOT_FOUND;
44
45 case EINVAL:
46 return UBUS_STATUS_INVALID_ARGUMENT;
47
48 default:
49 return UBUS_STATUS_UNKNOWN_ERROR;
50 }
51 }
52
53 const char *
54 rpc_exec_lookup(const char *cmd)
55 {
56 struct stat s;
57 int plen = 0, clen = strlen(cmd) + 1;
58 char *search, *p;
59 static char path[PATH_MAX];
60
61 if (!stat(cmd, &s) && S_ISREG(s.st_mode))
62 return cmd;
63
64 search = getenv("PATH");
65
66 if (!search)
67 search = "/bin:/usr/bin:/sbin:/usr/sbin";
68
69 p = search;
70
71 do
72 {
73 if (*p != ':' && *p != '\0')
74 continue;
75
76 plen = p - search;
77
78 if ((plen + clen) >= sizeof(path))
79 continue;
80
81 strncpy(path, search, plen);
82 sprintf(path + plen, "/%s", cmd);
83
84 if (!stat(path, &s) && S_ISREG(s.st_mode))
85 return path;
86
87 search = p + 1;
88 }
89 while (*p++);
90
91 return NULL;
92 }
93
94
95 static void
96 rpc_ustream_to_blobmsg(struct blob_buf *blob, struct ustream *s,
97 const char *name)
98 {
99 int len;
100 char *rbuf, *wbuf;
101
102 if ((len = ustream_pending_data(s, false)) > 0)
103 {
104 wbuf = blobmsg_alloc_string_buffer(blob, name, len + 1);
105
106 if (!wbuf)
107 return;
108
109 ustream_for_each_read_buffer(s, rbuf, len)
110 {
111 memcpy(wbuf, rbuf, len);
112 wbuf += len;
113 }
114
115 *wbuf = 0;
116 blobmsg_add_string_buffer(blob);
117 }
118 }
119
120 static void
121 rpc_exec_reply(struct rpc_exec_context *c, int rv)
122 {
123 uloop_timeout_cancel(&c->timeout);
124 uloop_process_delete(&c->process);
125
126 if (rv == UBUS_STATUS_OK)
127 {
128 if (!c->stdout_cb && !c->stderr_cb && !c->finish_cb)
129 {
130 blobmsg_add_u32(&c->blob, "code", WEXITSTATUS(c->stat));
131 rpc_ustream_to_blobmsg(&c->blob, &c->opipe.stream, "stdout");
132 rpc_ustream_to_blobmsg(&c->blob, &c->epipe.stream, "stderr");
133 }
134
135 if (c->finish_cb)
136 rv = c->finish_cb(&c->blob, c->stat, c->priv);
137
138 if (rv == UBUS_STATUS_OK)
139 ubus_send_reply(c->context, &c->request, c->blob.head);
140 }
141
142 ubus_complete_deferred_request(c->context, &c->request, rv);
143
144 blob_buf_free(&c->blob);
145
146 ustream_free(&c->opipe.stream);
147 ustream_free(&c->epipe.stream);
148
149 close(c->opipe.fd.fd);
150 close(c->epipe.fd.fd);
151
152 if (c->priv)
153 free(c->priv);
154
155 free(c);
156 }
157
158 static void
159 rpc_exec_timeout_cb(struct uloop_timeout *t)
160 {
161 struct rpc_exec_context *c =
162 container_of(t, struct rpc_exec_context, timeout);
163
164 kill(c->process.pid, SIGKILL);
165 rpc_exec_reply(c, UBUS_STATUS_TIMEOUT);
166 }
167
168 static void
169 rpc_exec_process_cb(struct uloop_process *p, int stat)
170 {
171 struct rpc_exec_context *c =
172 container_of(p, struct rpc_exec_context, process);
173
174 c->stat = stat;
175
176 ustream_poll(&c->opipe.stream);
177 ustream_poll(&c->epipe.stream);
178
179 close(c->opipe.fd.fd);
180 close(c->epipe.fd.fd);
181
182 ustream_poll(&c->opipe.stream);
183 ustream_poll(&c->epipe.stream);
184 }
185
186 static void
187 rpc_exec_ipipe_write_cb(struct ustream *s, int bytes)
188 {
189 struct rpc_exec_context *c =
190 container_of(s, struct rpc_exec_context, ipipe.stream);
191
192 if (c->stdin_cb(s, c->priv) <= 0)
193 {
194 ustream_free(&c->ipipe.stream);
195 close(c->ipipe.fd.fd);
196 }
197 }
198
199 static void
200 rpc_exec_opipe_read_cb(struct ustream *s, int bytes)
201 {
202 int len, rv;
203 char *buf;
204 struct rpc_exec_context *c =
205 container_of(s, struct rpc_exec_context, opipe.stream);
206
207 if (c->stdout_cb)
208 {
209 do {
210 buf = ustream_get_read_buf(s, &len);
211
212 if (!buf || !len)
213 break;
214
215 rv = c->stdout_cb(&c->blob, buf, len, c->priv);
216
217 if (rv <= 0)
218 break;
219
220 ustream_consume(s, rv);
221 } while(1);
222 }
223 else if (ustream_read_buf_full(s))
224 {
225 rpc_exec_reply(c, UBUS_STATUS_NOT_SUPPORTED);
226 }
227 }
228
229 static void
230 rpc_exec_epipe_read_cb(struct ustream *s, int bytes)
231 {
232 int len, rv;
233 char *buf;
234 struct rpc_exec_context *c =
235 container_of(s, struct rpc_exec_context, epipe.stream);
236
237 if (c->stderr_cb)
238 {
239 do {
240 buf = ustream_get_read_buf(s, &len);
241
242 if (!buf || !len)
243 break;
244
245 rv = c->stderr_cb(&c->blob, buf, len, c->priv);
246
247 if (rv <= 0)
248 break;
249
250 ustream_consume(s, rv);
251 } while(1);
252 }
253 else if (ustream_read_buf_full(s))
254 {
255 rpc_exec_reply(c, UBUS_STATUS_NOT_SUPPORTED);
256 }
257 }
258
259 static void
260 rpc_exec_opipe_state_cb(struct ustream *s)
261 {
262 struct rpc_exec_context *c =
263 container_of(s, struct rpc_exec_context, opipe.stream);
264
265 if (c->opipe.stream.eof && c->epipe.stream.eof)
266 rpc_exec_reply(c, UBUS_STATUS_OK);
267 }
268
269 static void
270 rpc_exec_epipe_state_cb(struct ustream *s)
271 {
272 struct rpc_exec_context *c =
273 container_of(s, struct rpc_exec_context, epipe.stream);
274
275 if (c->opipe.stream.eof && c->epipe.stream.eof)
276 rpc_exec_reply(c, UBUS_STATUS_OK);
277 }
278
279 int
280 rpc_exec(const char **args, rpc_exec_write_cb_t in,
281 rpc_exec_read_cb_t out, rpc_exec_read_cb_t err,
282 rpc_exec_done_cb_t end, void *priv, struct ubus_context *ctx,
283 struct ubus_request_data *req)
284 {
285 pid_t pid;
286
287 int ipipe[2];
288 int opipe[2];
289 int epipe[2];
290
291 const char *cmd;
292 struct rpc_exec_context *c;
293
294 cmd = rpc_exec_lookup(args[0]);
295
296 if (!cmd)
297 return UBUS_STATUS_NOT_FOUND;
298
299 c = malloc(sizeof(*c));
300
301 if (!c)
302 return UBUS_STATUS_UNKNOWN_ERROR;
303
304 if (pipe(ipipe))
305 goto fail_ipipe;
306
307 if (pipe(opipe))
308 goto fail_opipe;
309
310 if (pipe(epipe))
311 goto fail_epipe;
312
313 switch ((pid = fork()))
314 {
315 case -1:
316 return rpc_errno_status();
317
318 case 0:
319 uloop_done();
320
321 dup2(ipipe[0], 0);
322 dup2(opipe[1], 1);
323 dup2(epipe[1], 2);
324
325 close(ipipe[0]);
326 close(ipipe[1]);
327 close(opipe[0]);
328 close(opipe[1]);
329 close(epipe[0]);
330 close(epipe[1]);
331
332 if (execv(cmd, (char * const *)args))
333 return rpc_errno_status();
334
335 default:
336 memset(c, 0, sizeof(*c));
337 blob_buf_init(&c->blob, 0);
338
339 c->stdin_cb = in;
340 c->stdout_cb = out;
341 c->stderr_cb = err;
342 c->finish_cb = end;
343 c->priv = priv;
344
345 ustream_declare_read(c->opipe, opipe[0], opipe);
346 ustream_declare_read(c->epipe, epipe[0], epipe);
347
348 c->process.pid = pid;
349 c->process.cb = rpc_exec_process_cb;
350 uloop_process_add(&c->process);
351
352 c->timeout.cb = rpc_exec_timeout_cb;
353 uloop_timeout_set(&c->timeout, rpc_exec_timeout);
354
355 if (c->stdin_cb)
356 {
357 ustream_declare_write(c->ipipe, ipipe[1], ipipe);
358 rpc_exec_ipipe_write_cb(&c->ipipe.stream, 0);
359 }
360 else
361 {
362 close(ipipe[1]);
363 }
364
365 close(ipipe[0]);
366 close(opipe[1]);
367 close(epipe[1]);
368
369 c->context = ctx;
370 ubus_defer_request(ctx, req, &c->request);
371 }
372
373 return UBUS_STATUS_OK;
374
375 fail_epipe:
376 close(opipe[0]);
377 close(opipe[1]);
378
379 fail_opipe:
380 close(ipipe[0]);
381 close(ipipe[1]);
382
383 fail_ipipe:
384 return rpc_errno_status();
385 }