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 136 if (c->finish_cb) 137 rv = c->finish_cb(&c->blob, c->stat, c->priv); 138 139 if (rv == UBUS_STATUS_OK) 140 ubus_send_reply(c->context, &c->request, c->blob.head); 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 goto fail_fork; 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_fork: 376 close(epipe[0]); 377 close(epipe[1]); 378 379 fail_epipe: 380 close(opipe[0]); 381 close(opipe[1]); 382 383 fail_opipe: 384 close(ipipe[0]); 385 close(ipipe[1]); 386 387 fail_ipipe: 388 free(c); 389 return rpc_errno_status(); 390 } 391
This page was automatically generated by LXR 0.3.1. • OpenWrt