2 * rpcd - UBUS RPC server
4 * Copyright (C) 2013-2014 Jo-Philipp Wich <jow@openwrt.org>
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.
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.
29 #include <rpcd/exec.h>
32 rpc_errno_status(void)
37 return UBUS_STATUS_PERMISSION_DENIED
;
40 return UBUS_STATUS_INVALID_ARGUMENT
;
43 return UBUS_STATUS_NOT_FOUND
;
46 return UBUS_STATUS_INVALID_ARGUMENT
;
49 return UBUS_STATUS_UNKNOWN_ERROR
;
54 rpc_exec_lookup(const char *cmd
)
57 int plen
= 0, clen
= strlen(cmd
) + 1;
59 static char path
[PATH_MAX
];
61 if (!stat(cmd
, &s
) && S_ISREG(s
.st_mode
))
64 search
= getenv("PATH");
67 search
= "/bin:/usr/bin:/sbin:/usr/sbin";
73 if (*p
!= ':' && *p
!= '\0')
78 if ((plen
+ clen
) >= sizeof(path
))
81 strncpy(path
, search
, plen
);
82 sprintf(path
+ plen
, "/%s", cmd
);
84 if (!stat(path
, &s
) && S_ISREG(s
.st_mode
))
96 rpc_ustream_to_blobmsg(struct blob_buf
*blob
, struct ustream
*s
,
102 if ((len
= ustream_pending_data(s
, false)) > 0)
104 wbuf
= blobmsg_alloc_string_buffer(blob
, name
, len
+ 1);
109 ustream_for_each_read_buffer(s
, rbuf
, len
)
111 memcpy(wbuf
, rbuf
, len
);
116 blobmsg_add_string_buffer(blob
);
121 rpc_exec_reply(struct rpc_exec_context
*c
, int rv
)
123 uloop_timeout_cancel(&c
->timeout
);
124 uloop_process_delete(&c
->process
);
126 if (rv
== UBUS_STATUS_OK
)
128 if (!c
->stdout_cb
&& !c
->stderr_cb
&& !c
->finish_cb
)
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");
136 rv
= c
->finish_cb(&c
->blob
, c
->stat
, c
->priv
);
138 if (rv
== UBUS_STATUS_OK
)
139 ubus_send_reply(c
->context
, &c
->request
, c
->blob
.head
);
142 ubus_complete_deferred_request(c
->context
, &c
->request
, rv
);
144 blob_buf_free(&c
->blob
);
146 ustream_free(&c
->opipe
.stream
);
147 ustream_free(&c
->epipe
.stream
);
149 close(c
->opipe
.fd
.fd
);
150 close(c
->epipe
.fd
.fd
);
159 rpc_exec_timeout_cb(struct uloop_timeout
*t
)
161 struct rpc_exec_context
*c
=
162 container_of(t
, struct rpc_exec_context
, timeout
);
164 kill(c
->process
.pid
, SIGKILL
);
165 rpc_exec_reply(c
, UBUS_STATUS_TIMEOUT
);
169 rpc_exec_process_cb(struct uloop_process
*p
, int stat
)
171 struct rpc_exec_context
*c
=
172 container_of(p
, struct rpc_exec_context
, process
);
176 ustream_poll(&c
->opipe
.stream
);
177 ustream_poll(&c
->epipe
.stream
);
181 rpc_exec_ipipe_write_cb(struct ustream
*s
, int bytes
)
183 struct rpc_exec_context
*c
=
184 container_of(s
, struct rpc_exec_context
, ipipe
.stream
);
186 if (c
->stdin_cb(s
, c
->priv
) <= 0)
188 ustream_free(&c
->ipipe
.stream
);
189 close(c
->ipipe
.fd
.fd
);
194 rpc_exec_opipe_read_cb(struct ustream
*s
, int bytes
)
198 struct rpc_exec_context
*c
=
199 container_of(s
, struct rpc_exec_context
, opipe
.stream
);
204 buf
= ustream_get_read_buf(s
, &len
);
209 rv
= c
->stdout_cb(&c
->blob
, buf
, len
, c
->priv
);
214 ustream_consume(s
, rv
);
217 else if (ustream_read_buf_full(s
))
219 rpc_exec_reply(c
, UBUS_STATUS_NOT_SUPPORTED
);
224 rpc_exec_epipe_read_cb(struct ustream
*s
, int bytes
)
228 struct rpc_exec_context
*c
=
229 container_of(s
, struct rpc_exec_context
, epipe
.stream
);
234 buf
= ustream_get_read_buf(s
, &len
);
239 rv
= c
->stderr_cb(&c
->blob
, buf
, len
, c
->priv
);
244 ustream_consume(s
, rv
);
247 else if (ustream_read_buf_full(s
))
249 rpc_exec_reply(c
, UBUS_STATUS_NOT_SUPPORTED
);
254 rpc_exec_opipe_state_cb(struct ustream
*s
)
256 struct rpc_exec_context
*c
=
257 container_of(s
, struct rpc_exec_context
, opipe
.stream
);
259 if (c
->opipe
.stream
.eof
&& c
->epipe
.stream
.eof
)
260 rpc_exec_reply(c
, UBUS_STATUS_OK
);
264 rpc_exec_epipe_state_cb(struct ustream
*s
)
266 struct rpc_exec_context
*c
=
267 container_of(s
, struct rpc_exec_context
, epipe
.stream
);
269 if (c
->opipe
.stream
.eof
&& c
->epipe
.stream
.eof
)
270 rpc_exec_reply(c
, UBUS_STATUS_OK
);
274 rpc_exec(const char **args
, rpc_exec_write_cb_t in
,
275 rpc_exec_read_cb_t out
, rpc_exec_read_cb_t err
,
276 rpc_exec_done_cb_t end
, void *priv
, struct ubus_context
*ctx
,
277 struct ubus_request_data
*req
)
286 struct rpc_exec_context
*c
;
288 cmd
= rpc_exec_lookup(args
[0]);
291 return UBUS_STATUS_NOT_FOUND
;
293 c
= malloc(sizeof(*c
));
296 return UBUS_STATUS_UNKNOWN_ERROR
;
307 switch ((pid
= fork()))
310 return rpc_errno_status();
326 if (execv(cmd
, (char * const *)args
))
327 return rpc_errno_status();
330 memset(c
, 0, sizeof(*c
));
331 blob_buf_init(&c
->blob
, 0);
339 ustream_declare_read(c
->opipe
, opipe
[0], opipe
);
340 ustream_declare_read(c
->epipe
, epipe
[0], epipe
);
342 c
->process
.pid
= pid
;
343 c
->process
.cb
= rpc_exec_process_cb
;
344 uloop_process_add(&c
->process
);
346 c
->timeout
.cb
= rpc_exec_timeout_cb
;
347 uloop_timeout_set(&c
->timeout
, RPC_EXEC_MAX_RUNTIME
);
351 ustream_declare_write(c
->ipipe
, ipipe
[1], ipipe
);
352 rpc_exec_ipipe_write_cb(&c
->ipipe
.stream
, 0);
364 ubus_defer_request(ctx
, req
, &c
->request
);
367 return UBUS_STATUS_OK
;
378 return rpc_errno_status();