1 /*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "host_shell_option.h"
17
18 namespace Hdc {
19 namespace HostShellOption {
FormatParametersToTlv(const string & parameters,const int startPos,string & formatOutput,string & errMsg)20 bool FormatParametersToTlv(const string ¶meters, const int startPos, string &formatOutput, string &errMsg)
21 {
22 if (parameters.empty() || startPos >= parameters.size()) {
23 errMsg = "[E003007] Internal error: Invalid option parameters";
24 return false;
25 }
26 int argc = 0;
27 char **argv = Base::SplitCommandToArgs(parameters.c_str() + startPos, &argc);
28 if (argv == nullptr || argc <= 0) {
29 WRITE_LOG(LOG_FATAL, "Failed to split command to args");
30 errMsg = "[E003007] Internal error: Invalid option parameters";
31 return false;
32 }
33 bool ret = false;
34 TlvBuf tb(Base::REGISTERD_TAG_SET);
35 if (!ParameterToTlv(argv, argc, tb, errMsg)) {
36 ret = false;
37 } else if (!CopyToString(tb, formatOutput)) {
38 errMsg = "[E003009] Internal error: Invalid tlv buffer";
39 } else {
40 ret = true;
41 }
42 delete[](reinterpret_cast<char *>(argv));
43 argv = nullptr;
44 return ret;
45 }
46
CopyToString(const TlvBuf & tlvBuf,string & output)47 bool CopyToString(const TlvBuf &tlvBuf, string &output)
48 {
49 uint32_t bufSize = tlvBuf.GetBufSize();
50 if (bufSize <= 0) {
51 WRITE_LOG(LOG_FATAL, "tlvSize error, size is: %u", bufSize);
52 return false;
53 }
54 uint8_t* tlvs = new uint8_t[bufSize];
55 if (tlvs == nullptr) {
56 WRITE_LOG(LOG_FATAL, "failed to allocate tlvs memory");
57 return false;
58 }
59 bool ret = false;
60 if (tlvBuf.CopyToBuf(tlvs, bufSize)) {
61 output = string(reinterpret_cast<char *>(tlvs), bufSize);
62 ret = true;
63 } else {
64 WRITE_LOG(LOG_FATAL, "tlvs CopyToString failed");
65 }
66 delete[] tlvs;
67 tlvs = nullptr;
68 return ret;
69 }
70
ParameterToTlv(char ** argv,int argc,TlvBuf & tlvBuf,string & errMsg)71 bool ParameterToTlv(char **argv, int argc, TlvBuf &tlvBuf, string &errMsg)
72 {
73 int skipNext = 0;
74 const string cmdOptionBundle = "-b";
75 string shellCommand = "";
76 bool ret = false;
77 for (int i = 0; i < argc; i++) {
78 if (skipNext > 0) {
79 skipNext--;
80 continue;
81 }
82 if (std::strcmp(argv[i], cmdOptionBundle.c_str()) == 0) {
83 if (i + 1 >= argc) {
84 WRITE_LOG(LOG_FATAL, "empty bundle name");
85 errMsg = "[E003005] The parameter is missing, correct your input by referring below:\n"
86 "Usage: hdc shell [-b bundlename] [COMMAND...]";
87 break;
88 }
89 string bundlePath = argv[i + 1];
90 if (!TlvAppendParameter(TAG_SHELL_BUNDLE, bundlePath, errMsg, tlvBuf)) {
91 break;
92 } else {
93 skipNext++; // skip the next parameter
94 }
95 } else if (strlen(argv[i]) >= 1 && argv[i][0] == '-') {
96 WRITE_LOG(LOG_FATAL, "Unsupport shell option: %s", argv[i]);
97 errMsg = "[E003003] Unsupport shell option: " + std::string(argv[i]);
98 break;
99 } else {
100 shellCommand = ConstructShellCommand(argv, i, argc);
101 if (!TlvAppendParameter(TAG_SHELL_CMD, shellCommand, errMsg, tlvBuf)) {
102 break;
103 }
104 ret = true;
105 break;
106 }
107 }
108 if (errMsg.empty() && shellCommand.empty()) {
109 errMsg = "[E003002] Unsupport interactive shell command option";
110 }
111 return ret;
112 }
113
TlvAppendParameter(const uint32_t tag,const string & shellCommand,string & errMsg,TlvBuf & tlvBuf)114 bool TlvAppendParameter(const uint32_t tag, const string &shellCommand, string &errMsg, TlvBuf &tlvBuf)
115 {
116 if (tag == TAG_SHELL_CMD && shellCommand.empty()) {
117 errMsg = "[E003002] Unsupport interactive shell command option";
118 return false;
119 }
120 if (tag == TAG_SHELL_BUNDLE && !Base::CheckBundleName(shellCommand)) {
121 errMsg = "[E003001] Invalid bundle name: " + shellCommand;
122 return false;
123 }
124 if (!tlvBuf.Append(tag, shellCommand.size(),
125 reinterpret_cast<uint8_t *>(const_cast<char *>(shellCommand.c_str())))) {
126 errMsg = "[E003008] Internal error: Failed to add value to TLV buffer";
127 return false;
128 }
129 return true;
130 }
131
ConstructShellCommand(char ** argv,const int startIndex,const int argc)132 string ConstructShellCommand(char **argv, const int startIndex, const int argc)
133 {
134 if (argv == nullptr || startIndex >= argc) {
135 return "";
136 }
137 string shellCommand;
138 for (int j = startIndex; j < argc; j++) {
139 shellCommand += argv[j];
140 if (j != argc - 1) {
141 shellCommand += " ";
142 }
143 }
144 return shellCommand;
145 }
146 }
147 }
148