This is an automated email from the ASF dual-hosted git repository. ccollins pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 4d37e68313f9dbae9f5abd6cc695372b57f58fdc Author: Christopher Collins <ccoll...@apache.org> AuthorDate: Fri May 10 18:59:39 2019 -0700 sys/shell: shell-newtmgr bridge Implement a new newtmgr command: `shell exec`. This command allows shell commands to be executed via newtmgr. --- mgmt/mgmt/include/mgmt/mgmt.h | 1 + sys/shell/pkg.yml | 3 + sys/shell/src/shell_bridge.c | 109 ++++++++++++++++++++++++++++++++++ sys/shell/src/shell_bridge_streamer.c | 81 +++++++++++++++++++++++++ sys/shell/syscfg.yml | 16 +++++ 5 files changed, 210 insertions(+) diff --git a/mgmt/mgmt/include/mgmt/mgmt.h b/mgmt/mgmt/include/mgmt/mgmt.h index 427be1d..179d67f 100644 --- a/mgmt/mgmt/include/mgmt/mgmt.h +++ b/mgmt/mgmt/include/mgmt/mgmt.h @@ -58,6 +58,7 @@ extern "C" { #define MGMT_GROUP_ID_SPLIT (6) #define MGMT_GROUP_ID_RUN (7) #define MGMT_GROUP_ID_FS (8) +#define MGMT_GROUP_ID_SHELL (9) #define MGMT_GROUP_ID_PERUSER (64) /** diff --git a/sys/shell/pkg.yml b/sys/shell/pkg.yml index cf009a8..dee374f 100644 --- a/sys/shell/pkg.yml +++ b/sys/shell/pkg.yml @@ -33,6 +33,9 @@ pkg.deps.SHELL_NEWTMGR: - "@apache-mynewt-core/encoding/base64" - "@apache-mynewt-core/util/crc" +pkg.deps.SHELL_BRIDGE: + - "@apache-mynewt-core/encoding/tinycbor" + pkg.req_apis: - console diff --git a/sys/shell/src/shell_bridge.c b/sys/shell/src/shell_bridge.c new file mode 100644 index 0000000..f1ca335 --- /dev/null +++ b/sys/shell/src/shell_bridge.c @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "os/mynewt.h" + +#if MYNEWT_VAL(SHELL_BRIDGE) + +#include "mgmt/mgmt.h" +#include "cborattr/cborattr.h" +#include "streamer/streamer.h" +#include "tinycbor/cbor_mbuf_writer.h" +#include "shell_priv.h" + +static struct mgmt_group shell_bridge_group; + +static int shell_bridge_exec(struct mgmt_cbuf *cb); + +static struct mgmt_handler shell_bridge_group_handlers[] = { + [SHELL_NMGR_OP_EXEC] = { NULL, shell_bridge_exec }, +}; + +/** + * Handler for the `shell exec` newtmgr command. + */ +static int +shell_bridge_exec(struct mgmt_cbuf *cb) +{ + char line[MYNEWT_VAL(SHELL_BRIDGE_MAX_IN_LEN)]; + char *argv[MYNEWT_VAL(SHELL_CMD_ARGC_MAX)]; + struct shell_bridge_streamer sbs; + CborEncoder str_encoder; + CborError err; + int argc; + int rc; + + const struct cbor_attr_t attrs[] = { + { + .attribute = "argv", + .type = CborAttrArrayType, + .addr.array = { + .element_type = CborAttrTextStringType, + .arr.strings.ptrs = argv, + .arr.strings.store = line, + .arr.strings.storelen = sizeof line, + .count = &argc, + .maxlen = sizeof argv / sizeof argv[0], + }, + }, + { 0 }, + }; + + err = cbor_read_object(&cb->it, attrs); + if (err != 0) { + return MGMT_ERR_EINVAL; + } + + /* Key="o"; value=<command-output> */ + err |= cbor_encode_text_stringz(&cb->encoder, "o"); + err |= cbor_encoder_create_indef_text_string(&cb->encoder, &str_encoder); + + shell_bridge_streamer_new(&sbs, &str_encoder); + rc = shell_exec(argc, argv, &sbs.streamer); + + err |= cbor_encoder_close_container(&cb->encoder, &str_encoder); + + /* Key="rc"; value=<status> */ + err |= cbor_encode_text_stringz(&cb->encoder, "rc"); + err |= cbor_encode_int(&cb->encoder, rc); + + if (err != 0) { + return MGMT_ERR_ENOMEM; + } + + return 0; +} + +int +shell_bridge_init(void) +{ + int rc; + + MGMT_GROUP_SET_HANDLERS(&shell_bridge_group, shell_bridge_group_handlers); + shell_bridge_group.mg_group_id = MGMT_GROUP_ID_SHELL; + + rc = mgmt_group_register(&shell_bridge_group); + if (rc) { + return rc; + } + + return 0; +} + +#endif diff --git a/sys/shell/src/shell_bridge_streamer.c b/sys/shell/src/shell_bridge_streamer.c new file mode 100644 index 0000000..d9df4dd --- /dev/null +++ b/sys/shell/src/shell_bridge_streamer.c @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include "os/mynewt.h" + +#if MYNEWT_VAL(SHELL_BRIDGE) + +#include "tinycbor/cbor.h" +#include "shell_priv.h" + +static int +shell_bridge_streamer_write(struct streamer *streamer, + const void *src, size_t len) +{ + struct shell_bridge_streamer *sbs; + int err; + + sbs = (struct shell_bridge_streamer *)streamer; + + /* Encode the data as a CBOR text string. */ + err = cbor_encode_text_string(sbs->str_encoder, src, len); + if (err != 0) { + return SYS_ENOMEM; + } + + return 0; +} + +static int +shell_bridge_streamer_vprintf(struct streamer *streamer, + const char *fmt, va_list ap) +{ + char buf[MYNEWT_VAL(SHELL_BRIDGE_PRINTF_LEN)]; + int num_chars; + int rc; + + num_chars = vsnprintf(buf, sizeof buf, fmt, ap); + if (num_chars > sizeof buf - 1) { + num_chars = sizeof buf - 1; + } + + rc = shell_bridge_streamer_write(streamer, buf, num_chars); + if (rc != 0) { + return rc; + } + + return num_chars; +} + +static const struct streamer_cfg shell_bridge_streamer_cfg = { + .write_cb = shell_bridge_streamer_write, + .vprintf_cb = shell_bridge_streamer_vprintf, +}; + +void +shell_bridge_streamer_new(struct shell_bridge_streamer *sbs, + struct CborEncoder *str_encoder) +{ + *sbs = (struct shell_bridge_streamer) { + .streamer.cfg = &shell_bridge_streamer_cfg, + .str_encoder = str_encoder, + }; +} + +#endif diff --git a/sys/shell/syscfg.yml b/sys/shell/syscfg.yml index 1f416bc..638f968 100644 --- a/sys/shell/syscfg.yml +++ b/sys/shell/syscfg.yml @@ -74,6 +74,22 @@ syscfg.defs: write 2, read/write 3 (default) value: 3 + SHELL_BRIDGE: + description: > + Enables the `shell exec` newtmgr command; executes shell commands + via newtmgr. + value: 0 + SHELL_BRIDGE_MAX_IN_LEN: + description: > + Maximum combined length of arguments passed to the `shell exec` + newtmgr command. + value: 128 + SHELL_BRIDGE_PRINTF_LEN: + description: > + Maximum number of characters that can be streamed by a single + printf call during processing of the `shell exec` newtmgr command. + value: 128 + ## duplicated from boot/boot_serial BOOT_SERIAL_NVREG_MAGIC: description: >