1/*
2 * Copyright (c) 2022 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 <cstdio>
17#include <sys/stat.h>
18
19#include "app_manager.h"
20#include "component_manager.h"
21#include "exception_manager.h"
22#include "multimode_manager.h"
23#include "report.h"
24#include "scene_delegate.h"
25#include "string_ex.h"
26#include "tree_manager.h"
27#include "wukong_define.h"
28#include "wukong_logger.h"
29#include "wukong_shell_command.h"
30#include "wukong_util.h"
31#include "parameters.h"
32
33using namespace OHOS::WuKong;
34
35static const unsigned int NUMBER_TWO = 2;
36
37static bool FreeSingtion()
38{
39    AppManager::DestroyInstance();
40    ComponentManager::DestroyInstance();
41    ExceptionManager::DestroyInstance();
42    MultimodeManager::DestroyInstance();
43    Report::DestroyInstance();
44    SceneDelegate::DestroyInstance();
45    TreeManager::DestroyInstance();
46    WuKongUtil::DestroyInstance();
47    return true;
48}
49
50static void WuKongMutexFile()
51{
52    int fileExist = access("/dev/shm", F_OK);
53    if (fileExist == 0) {
54        DEBUG_LOG("File exist. Now create wukong test mutex.");
55    } else {
56        const int wuKongGm = mkdir("/dev/shm", 0777);
57        DEBUG_LOG("File create. Now create wukong test mutex.");
58        if (wuKongGm == -1) {
59            DEBUG_LOG("Error creating directory!");
60        }
61    }
62}
63
64static void InitSemaphore(NamedSemaphore& sem, const int count)
65{
66    bool res = sem.Open();
67    if (!res) {
68        WuKongMutexFile();
69        res = sem.Create();
70    }
71    if (res) {
72        DEBUG_LOG("Open Semaphore success");
73        int value = sem.GetValue();
74        if (value > count) {
75            DEBUG_LOG_STR("the semaphore value is invalid (%d), and reopen Semaphore", value);
76            res = sem.Create();
77            if (!res) {
78                ERROR_LOG("create sem failed");
79                return;
80            }
81        } else {
82            DEBUG_LOG_STR("Semaphore Value: (%d)", value);
83        }
84    }
85    sem.Close();
86}
87
88static bool IsRunning(NamedSemaphore& sem)
89{
90    bool result = false;
91    sem.Open();
92    // the wukong pidof buffer size.
93    const int bufferSize = 32;
94    int value = sem.GetValue();
95    TRACK_LOG_STR("Semaphore Is Open: (%d)", value);
96    if (value <= 0) {
97        FILE* fp = nullptr;
98        fp = popen("pidof wukong", "r");
99        TRACK_LOG("Run pidof wukong");
100        if (fp == nullptr) {
101            ERROR_LOG("popen function failed");
102            return true;
103        }
104        char pid[bufferSize] = {0};
105        if (fgets(pid, bufferSize - 1, fp) != nullptr) {
106            std::string pidStr(pid);
107            pidStr = OHOS::ReplaceStr(pidStr, "\n", " ");
108            TRACK_LOG_STR("Wukong Pid: (%s)", pidStr.c_str());
109            std::vector<std::string> strs;
110            OHOS::SplitStr(pidStr, " ", strs);
111            for (auto i : strs) {
112                DEBUG_LOG_STR("Pid: (%s)", i.c_str());
113            }
114            if (strs.size() >= NUMBER_TWO) {
115                result = true;
116            } else {
117                sem.Create();
118                result = false;
119            }
120        } else {
121            result = true;
122        }
123        pclose(fp);
124    }
125    return result;
126}
127
128int main(int argc, char* argv[])
129{
130    if (!OHOS::system::GetBoolParameter("const.security.developermode.state", true)) {
131        std::cout << "Not a development mode state, please check device mode." << std::endl;
132        return 0;
133    }
134    std::shared_ptr<WuKongLogger> WuKonglogger = WuKongLogger::GetInstance();
135    // first start logger
136    WuKonglogger->SetLevel(LOG_LEVEL_INFO);
137    bool isStop = false;
138    for (int index = argc - 1; index >= 1; index--) {
139        std::string arg = argv[index];
140        if (arg == "--track") {
141            argv[index][0] = '\0';
142            WuKonglogger->SetLevel(LOG_LEVEL_TRACK);
143        }
144        if (arg == "--debug") {
145            argv[index][0] = '\0';
146            WuKonglogger->SetLevel(LOG_LEVEL_DEBUG);
147        }
148        if (arg == "stop") {
149            isStop = true;
150        }
151    }
152    if (!WuKonglogger->Start()) {
153        return 1;
154    }
155    NamedSemaphore semRun(SEMPHORE_RUN_NAME, 1);
156    InitSemaphore(semRun, 1);
157    NamedSemaphore semStop(SEMPHORE_STOP_NAME, 1);
158    InitSemaphore(semStop, 1);
159    WuKongShellCommand cmd(argc, argv);
160    if (isStop) {
161        std::cout << cmd.ExecCommand();
162    } else {
163        if (IsRunning(semRun)) {
164            ERROR_LOG("error: wukong has running, allow one program run.");
165        } else {
166            semRun.Open();
167            semRun.Wait();
168            std::cout << cmd.ExecCommand();
169            semRun.Post();
170            semRun.Close();
171        }
172    }
173    FreeSingtion();
174    WuKonglogger->Stop();
175    std::cout << "exit main" << std::endl;
176    return 0;
177}
178