1 /*
2  * Copyright (c) 2021-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 "injection_tools_help_func.h"
17 
18 #include <getopt.h>
19 
20 #include <algorithm>
21 #include <iostream>
22 #include <string>
23 
24 #include <unistd.h>
25 
26 #undef MMI_LOG_TAG
27 #define MMI_LOG_TAG "InjectionToolsHelpFunc"
28 
29 namespace OHOS {
30 namespace MMI {
31 namespace {
32 constexpr int32_t SEND_EVENT_ARGV_COUNTS { 6 };
33 constexpr int32_t JSON_ARGV_COUNTS { 3 };
34 constexpr int32_t HELP_ARGV_COUNTS { 2 };
35 constexpr int32_t SHORT_OPTION_LENGTH { 2 };
36 } // namespace
37 
CheckInjectionCommand(int32_t argc,char ** argv)38 bool InjectionToolsHelpFunc::CheckInjectionCommand(int32_t argc, char **argv)
39 {
40     CALL_DEBUG_ENTER;
41     int32_t c = -1;
42     if (!SelectOptions(argc, argv, c)) {
43         MMI_HILOGE("Select option failed");
44         return false;
45     }
46     switch (c) {
47         case 'S': {
48             if (!SendEventOption(argc, argv)) {
49                 MMI_HILOGE("SendEvent option failed");
50                 return false;
51             }
52             break;
53         }
54         case 'J': {
55             if (!JsonOption(argc, argv)) {
56                 MMI_HILOGE("Json option failed");
57                 return false;
58             }
59             break;
60         }
61         case '?': {
62             if (!HelpOption(argc, argv)) {
63                 MMI_HILOGE("Help option failed");
64                 return false;
65             }
66             break;
67         }
68         default: {
69             std::cout << "invalid command" << std::endl;
70             return false;
71         }
72     }
73     return true;
74 }
75 
SelectOptions(int32_t argc,char ** argv,int32_t & opt)76 bool InjectionToolsHelpFunc::SelectOptions(int32_t argc, char **argv, int32_t &opt)
77 {
78     CALL_DEBUG_ENTER;
79     if (argc < SHORT_OPTION_LENGTH) {
80         std::cout << "Please enter options or parameters" << std::endl;
81         return false;
82     }
83     struct option longOptions[] = {
84         {"sendevent", no_argument, nullptr, 'S'},
85         {"json", no_argument, nullptr, 'J'},
86         {"help", no_argument, nullptr, '?'},
87         {nullptr, 0, nullptr, 0}
88     };
89     std::string inputOptions = argv[optind];
90     if (inputOptions.find('-') == inputOptions.npos) {
91         for (uint32_t i = 0; i < sizeof(longOptions) / sizeof(struct option) - 1; ++i) {
92             if (longOptions[i].name == inputOptions) {
93                 opt = longOptions[i].val;
94                 optind++;
95                 break;
96             }
97         }
98     } else if ((inputOptions.length() != SHORT_OPTION_LENGTH) && (inputOptions[inputOptions.find('-') + 1] != '-')) {
99         std::cout << "More than one short option is not supported" << std::endl;
100         return false;
101     } else {
102         int32_t optionIndex = 0;
103         opt = getopt_long(argc, argv, "SJ?", longOptions, &optionIndex);
104     }
105     if (opt == -1) {
106         std::cout << "Nonstandard input parameters" << std::endl;
107         return false;
108     }
109     return true;
110 }
111 
SendEventOption(int32_t argc,char ** argv)112 bool InjectionToolsHelpFunc::SendEventOption(int32_t argc, char **argv)
113 {
114     CALL_DEBUG_ENTER;
115     if (argc != SEND_EVENT_ARGV_COUNTS) {
116         std::cout << "Wrong number of input parameters" << std::endl;
117         return false;
118     }
119     std::string deviceNode = argv[optind];
120     if (deviceNode.empty()) {
121         std::cout << "Device node does not exist: " << deviceNode.c_str() << std::endl;
122         return false;
123     }
124     char realPath[PATH_MAX] = {};
125     if (realpath(deviceNode.c_str(), realPath) == nullptr) {
126         std::cout << "Device node path is error, path: " << deviceNode.c_str() << std::endl;
127         return false;
128     }
129     while (++optind < argc) {
130         std::string deviceInfo = argv[optind];
131         if (!IsNumberic(deviceInfo)) {
132             std::cout << "Parameter is error, element: " << deviceInfo.c_str() << std::endl;
133             return false;
134         }
135     }
136     SetArgvs(argc, argv, "sendevent");
137     return true;
138 }
139 
JsonOption(int32_t argc,char ** argv)140 bool InjectionToolsHelpFunc::JsonOption(int32_t argc, char **argv)
141 {
142     CALL_DEBUG_ENTER;
143     if (argc < JSON_ARGV_COUNTS) {
144         std::cout << "Wrong number of input parameters" << std::endl;
145         return false;
146     }
147     const std::string jsonFile = argv[optind];
148     std::string jsonBuf = ReadJsonFile(jsonFile);
149     if (jsonBuf.empty()) {
150         return false;
151     }
152     SetArgvs(argc, argv, "json");
153     return true;
154 }
155 
HelpOption(int32_t argc,char ** argv)156 bool InjectionToolsHelpFunc::HelpOption(int32_t argc, char **argv)
157 {
158     CALL_DEBUG_ENTER;
159     if (argc != HELP_ARGV_COUNTS) {
160         std::cout << "Wrong number of input parameters" << std::endl;
161         return false;
162     }
163     SetArgvs(argc, argv, "help");
164     return true;
165 }
166 
IsNumberic(const std::string & str)167 bool InjectionToolsHelpFunc::IsNumberic(const std::string &str)
168 {
169     return !str.empty() && std::all_of(str.begin(), str.end(), ::isdigit);
170 }
171 
SetArgvs(int32_t argc,char ** argv,const std::string & str)172 void InjectionToolsHelpFunc::SetArgvs(int32_t argc, char **argv, const std::string &str)
173 {
174     injectArgvs_.clear();
175     injectArgvs_.push_back(str);
176     for (int32_t i = SHORT_OPTION_LENGTH; i < argc; ++i) {
177         injectArgvs_.push_back(argv[i]);
178     }
179 }
180 
GetArgvs() const181 std::vector<std::string> InjectionToolsHelpFunc::GetArgvs() const
182 {
183     return injectArgvs_;
184 }
185 
ShowUsage()186 void InjectionToolsHelpFunc::ShowUsage()
187 {
188     std::cout << "Usage: mmi-event-injection <option> <command> <arg>..." << std::endl;
189     std::cout << "The option are:                                       " << std::endl;
190     std::cout << "commands for sendevent:                               " << std::endl;
191     std::cout << "                                 -inject the original event to the device node" << std::endl;
192     std::cout << "-S <device_node> <type> <code> <value>                " << std::endl;
193     std::cout << "--sendevent <device_node> <type> <code> <value>       " << std::endl;
194     std::cout << "sendevent <device_node> <type> <code> <value>         " << std::endl;
195     std::cout << "commands for json:                                    " << std::endl;
196     std::cout << "  -Inject a json file that writes all action information to the virtual device" << std::endl;
197     std::cout << "-J <file_name>   --json <file_name>   josn <file_name>" << std::endl;
198     std::cout << "-?  --help  help                                      " << std::endl;
199 }
200 } // namespace MMI
201 } // namespace OHOS
202