3 * Copyright (c) 2020 Project CHIP Authors
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include <core/CHIPCore.h>
20 #include <ChipShellCollection.h>
22 #if CONFIG_DEVICE_LAYER
23 #include <platform/CHIPDeviceLayer.h>
26 #if CHIP_ENABLE_OPENTHREAD
30 #include <lib/shell/shell.h>
31 #include <lib/support/CHIPArgParser.hpp>
32 #include <lib/support/CHIPMem.h>
33 #include <lib/support/CodeUtils.h>
34 #include <platform/ThreadStackManager.h>
36 #if CHIP_TARGET_STYLE_EMBEDDED
37 #include <openthread/cli.h>
38 #include <openthread/instance.h>
39 #include <openthread/ip6.h>
40 #include <openthread/link.h>
41 #include <openthread/thread.h>
43 #include <sys/types.h>
49 using namespace chip::Shell;
50 using namespace chip::Platform;
51 using namespace chip::DeviceLayer;
52 using namespace chip::Logging;
53 using namespace chip::ArgParser;
55 static chip::Shell::Shell sShellOtcliSubcommands;
57 int cmd_otcli_help_iterator(shell_command_t * command, void * arg)
59 streamer_printf(streamer_get(), " %-15s %s\n\r", command->cmd_name, command->cmd_help);
63 int cmd_otcli_help(int argc, char ** argv)
65 sShellOtcliSubcommands.ForEachCommand(cmd_otcli_help_iterator, nullptr);
69 #if CHIP_TARGET_STYLE_EMBEDDED
71 int cmd_otcli_dispatch(int argc, char ** argv)
73 CHIP_ERROR error = CHIP_NO_ERROR;
75 // From OT CLI internal lib, kMaxLineLength = 128
76 #define kMaxLineLength 128
77 char buff[kMaxLineLength] = { 0 };
78 char * buff_ptr = buff;
81 VerifyOrExit(argc > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
83 for (i = 0; i < argc; i++)
85 size_t arg_len = strlen(argv[i]);
87 /* Make sure that the next argument won't overflow the buffer */
88 VerifyOrExit(buff_ptr + arg_len < buff + kMaxLineLength, error = CHIP_ERROR_BUFFER_TOO_SMALL);
90 strncpy(buff_ptr, argv[i], arg_len);
93 /* Make sure that there is enough buffer for a space char */
94 if (buff_ptr + sizeof(char) < buff + kMaxLineLength)
96 strncpy(buff_ptr, " ", sizeof(char));
102 otCliConsoleInputLine(buff, buff_ptr - buff);
107 #elif CHIP_TARGET_STYLE_UNIX
109 int cmd_otcli_dispatch(int argc, char ** argv)
111 CHIP_ERROR error = CHIP_NO_ERROR;
114 uid_t euid = geteuid();
115 char ctl_command[] = "/usr/local/sbin/ot-ctl";
120 streamer_printf(streamer_get(), "Error otcli: requires running chip-shell as sudo\n\r");
121 error = CHIP_ERROR_INCORRECT_STATE;
125 VerifyOrExit(argc > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
127 // Fork and execute the command.
129 VerifyOrExit(pid != -1, error = CHIP_ERROR_INCORRECT_STATE);
133 // Child process to execute the command with provided arguments
134 --argv; // Restore access to entry [0] containing the command;
135 argv[0] = ctl_command;
136 if (execvp(ctl_command, argv) < 0)
138 streamer_printf(streamer_get(), "Error exec %s: %s\n", ctl_command, strerror(errno));
144 // Parent process to wait on child.
147 error = (status) ? CHIP_ERROR_INCORRECT_STATE : CHIP_NO_ERROR;
154 #endif // CHIP_TARGET_STYLE_UNIX
156 static const shell_command_t cmds_otcli_root = { &cmd_otcli_dispatch, "otcli", "Dispatch OpenThread CLI command" };
158 #if CHIP_TARGET_STYLE_EMBEDDED
159 static int OnOtCliOutput(const char * aBuf, uint16_t aBufLength, void * aContext)
161 return streamer_write(streamer_get(), aBuf, aBufLength);
165 #endif // CHIP_ENABLE_OPENTHREAD
167 void cmd_otcli_init()
169 #if CHIP_ENABLE_OPENTHREAD
170 #if CHIP_TARGET_STYLE_EMBEDDED
171 otCliConsoleInit(otInstanceInitSingle(), &OnOtCliOutput, NULL);
174 // Register the root otcli command with the top-level shell.
175 shell_register(&cmds_otcli_root, 1);
176 #endif // CHIP_ENABLE_OPENTHREAD