* Copyright (C) 2024 Huawei Device Co., Ltd.
* Licensed 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 "host_shell_option.h"
namespace Hdc {
namespace HostShellOption {
bool FormatParametersToTlv(
const string ¶meters, const int startPos, string &formatOutput, string &errMsg, bool &hasCommand)
{
if (parameters.empty() || startPos >= parameters.size()) {
errMsg = "[E003007] Internal error: Invalid option parameters";
return false;
}
int argc = 0;
char **argv = Base::SplitCommandToArgs(parameters.c_str() + startPos, &argc);
if (argv == nullptr || argc <= 0) {
WRITE_LOG(LOG_FATAL, "Failed to split command to args");
errMsg = "[E003007] Internal error: Invalid option parameters";
return false;
}
bool ret = false;
TlvBuf tb(Base::REGISTERD_TAG_SET);
if (!ParameterToTlv(argv, argc, tb, errMsg)) {
ret = false;
} else if (!CopyToString(tb, formatOutput)) {
errMsg = "[E003009] Internal error: Invalid tlv buffer";
} else {
ret = true;
}
std::string tmp;
hasCommand = tb.FindTlv(TAG_SHELL_CMD, tmp);
delete[](reinterpret_cast<char *>(argv));
argv = nullptr;
return ret;
}
bool CopyToString(const TlvBuf &tlvBuf, string &output)
{
uint32_t bufSize = tlvBuf.GetBufSize();
if (bufSize <= 0) {
WRITE_LOG(LOG_FATAL, "tlvSize error, size is: %u", bufSize);
return false;
}
uint8_t* tlvs = new (std::nothrow) uint8_t[bufSize];
if (tlvs == nullptr) {
WRITE_LOG(LOG_FATAL, "failed to allocate tlvs memory");
return false;
}
bool ret = false;
if (tlvBuf.CopyToBuf(tlvs, bufSize)) {
output = string(reinterpret_cast<char *>(tlvs), bufSize);
ret = true;
} else {
WRITE_LOG(LOG_FATAL, "tlvs CopyToString failed");
}
delete[] tlvs;
tlvs = nullptr;
return ret;
}
bool ParameterToTlv(char **argv, int argc, TlvBuf &tlvBuf, string &errMsg)
{
int skipNext = 0;
const string cmdOptionBundle = "-b";
string shellCommand = "";
bool ret = false;
for (int i = 0; i < argc; i++) {
if (skipNext > 0) {
skipNext--;
continue;
}
if (std::strcmp(argv[i], cmdOptionBundle.c_str()) == 0) {
if (i + 1 >= argc) {
WRITE_LOG(LOG_FATAL, "empty bundle name");
errMsg = "[E003005] The parameter is missing, correct your input by referring below:\n"
"Usage: hdc shell [-b bundlename] [COMMAND...]";
break;
}
string bundlePath = argv[i + 1];
if (!TlvAppendParameter(TAG_SHELL_BUNDLE, bundlePath, errMsg, tlvBuf)) {
break;
} else {
ret = true;
skipNext++;
}
} else if (strlen(argv[i]) >= 1 && argv[i][0] == '-') {
WRITE_LOG(LOG_FATAL, "Unsupport shell option: %s", argv[i]);
errMsg = "[E003003] Unsupport shell option: " + std::string(argv[i]);
break;
} else {
shellCommand = ConstructShellCommand(argv, i, argc);
if (!TlvAppendParameter(TAG_SHELL_CMD, shellCommand, errMsg, tlvBuf)) {
break;
}
ret = true;
break;
}
}
return ret;
}
bool TlvAppendParameter(const uint32_t tag, const string &shellCommand, string &errMsg, TlvBuf &tlvBuf)
{
if (tag == TAG_SHELL_CMD && shellCommand.empty()) {
errMsg = "[E003002] Unsupport interactive shell command option";
return false;
}
if (tag == TAG_SHELL_BUNDLE && !Base::CheckBundleName(shellCommand)) {
errMsg = "[E003001] Invalid bundle name: " + shellCommand;
return false;
}
if (!tlvBuf.Append(tag, shellCommand.size(),
reinterpret_cast<uint8_t *>(const_cast<char *>(shellCommand.c_str())))) {
errMsg = "[E003008] Internal error: Failed to add value to TLV buffer";
return false;
}
return true;
}
string ConstructShellCommand(char **argv, const int startIndex, const int argc)
{
if (argv == nullptr || startIndex >= argc) {
return "";
}
string shellCommand;
for (int j = startIndex; j < argc; j++) {
shellCommand += argv[j];
if (j != argc - 1) {
shellCommand += " ";
}
}
return shellCommand;
}
}
}