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
);
179 close(c
->opipe
.fd
.fd
);
180 close(c
->epipe
.fd
.fd
);
182 ustream_poll(&c
->opipe
.stream
);
183 ustream_poll(&c
->epipe
.stream
);
187 rpc_exec_ipipe_write_cb(struct ustream
*s
, int bytes
)
189 struct rpc_exec_context
*c
=
190 container_of(s
, struct rpc_exec_context
, ipipe
.stream
);
192 if (c
->stdin_cb(s
, c
->priv
) <= 0)
194 ustream_free(&c
->ipipe
.stream
);
195 close(c
->ipipe
.fd
.fd
);
200 rpc_exec_opipe_read_cb(struct ustream
*s
, int bytes
)
204 struct rpc_exec_context
*c
=
205 container_of(s
, struct rpc_exec_context
, opipe
.stream
);
210 buf
= ustream_get_read_buf(s
, &len
);
215 rv
= c
->stdout_cb(&c
->blob
, buf
, len
, c
->priv
);
220 ustream_consume(s
, rv
);
223 else if (ustream_read_buf_full(s
))
225 rpc_exec_reply(c
, UBUS_STATUS_NOT_SUPPORTED
);
230 rpc_exec_epipe_read_cb(struct ustream
*s
, int bytes
)
234 struct rpc_exec_context
*c
=
235 container_of(s
, struct rpc_exec_context
, epipe
.stream
);
240 buf
= ustream_get_read_buf(s
, &len
);
245 rv
= c
->stderr_cb(&c
->blob
, buf
, len
, c
->priv
);
250 ustream_consume(s
, rv
);
253 else if (ustream_read_buf_full(s
))
255 rpc_exec_reply(c
, UBUS_STATUS_NOT_SUPPORTED
);
260 rpc_exec_opipe_state_cb(struct ustream
*s
)
262 struct rpc_exec_context
*c
=
263 container_of(s
, struct rpc_exec_context
, opipe
.stream
);
265 if (c
->opipe
.stream
.eof
&& c
->epipe
.stream
.eof
)
266 rpc_exec_reply(c
, UBUS_STATUS_OK
);
270 rpc_exec_epipe_state_cb(struct ustream
*s
)
272 struct rpc_exec_context
*c
=
273 container_of(s
, struct rpc_exec_context
, epipe
.stream
);
275 if (c
->opipe
.stream
.eof
&& c
->epipe
.stream
.eof
)
276 rpc_exec_reply(c
, UBUS_STATUS_OK
);
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
)
292 struct rpc_exec_context
*c
;
294 cmd
= rpc_exec_lookup(args
[0]);
297 return UBUS_STATUS_NOT_FOUND
;
299 c
= malloc(sizeof(*c
));
302 return UBUS_STATUS_UNKNOWN_ERROR
;
313 switch ((pid
= fork()))
316 return rpc_errno_status();
332 if (execv(cmd
, (char * const *)args
))
333 return rpc_errno_status();
336 memset(c
, 0, sizeof(*c
));
337 blob_buf_init(&c
->blob
, 0);
345 ustream_declare_read(c
->opipe
, opipe
[0], opipe
);
346 ustream_declare_read(c
->epipe
, epipe
[0], epipe
);
348 c
->process
.pid
= pid
;
349 c
->process
.cb
= rpc_exec_process_cb
;
350 uloop_process_add(&c
->process
);
352 c
->timeout
.cb
= rpc_exec_timeout_cb
;
353 uloop_timeout_set(&c
->timeout
, RPC_EXEC_MAX_RUNTIME
);
357 ustream_declare_write(c
->ipipe
, ipipe
[1], ipipe
);
358 rpc_exec_ipipe_write_cb(&c
->ipipe
.stream
, 0);
370 ubus_defer_request(ctx
, req
, &c
->request
);
373 return UBUS_STATUS_OK
;
384 return rpc_errno_status();