#include #include #include #include #include #include #include #include #include #include #include #include #include #include char *get_current_time() { const auto now = std::chrono::system_clock::now(); const std::time_t t_c = std::chrono::system_clock::to_time_t(now); return std::ctime(&t_c); } int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); if(!std::filesystem::exists("/home/ud/logs/")) { std::filesystem::create_directory("/home/ud/logs"); } std::fstream log_file("/home/ud/logs/StartUpRunner.log", std::fstream::app); if(!log_file.is_open()) { log_file.open("/home/ud/logs/StartUpRunner.log", std::fstream::out); } log_file << "-------- Starting app: " << get_current_time(); log_file << "Current path: " << std::filesystem::current_path() << "\n"; if(!std::filesystem::exists("startup_apps.json")) { log_file << "startup_apps.json not found exiting.\n"; log_file.flush(); log_file.close(); exit(-1); } std::string data = ""; std::string t_data = ""; std::fstream json_file; json_file.open("startup_apps.json", std::fstream::in); if(!json_file.is_open()) { std::cout << "Why is the startup_apps.json file not open?" << std::endl; return -1; } std::stringstream test; test << json_file.rdbuf(); json_file.close(); QByteArray arr_data = QByteArray::fromStdString(test.str()); QJsonArray top = QJsonDocument::fromJson(arr_data).array(); std::vector active_process_list; for(auto i: top) { auto object = i.toObject(); std::string name = object["app_name"].toString().toStdString(); std::string args = ""; QStringList sargs; for(auto k: object["app_args"].toArray()) { args += k.toString().toStdString(); sargs << k.toString(); } QString mode = object["mode"].toString("wait"); QString working_dir = object["working_dir"].toString("/home/ud/StartUpApps/"); std::string file_name = std::filesystem::path(name).stem().string(); std::string log_file_name = std::format("/home/ud/logs/{}.log", file_name); bool create_log_file = object["create_log"].toBool(); std::string command; if(create_log_file) command = std::format("{} {} > {}", name, args, log_file_name); else command = std::format("{} {}", name, args); log_file << "Running: " << command << "\n"; QProcess *proc = new QProcess(); QObject::connect(proc, &QProcess::started, [&, command, proc] () { log_file << "Started process: " << command << " with pid: " << QString::number(proc->processId()).toStdString() << std::endl; }); if (mode == "wait") { QObject::connect(proc, &QProcess::finished, [&, command, proc] (int exitcode, QProcess::ExitStatus status) { auto process = proc; if(status == QProcess::NormalExit) log_file << "Process: " << command << " with pid: " << QString::number(proc->processId()).toStdString() << std::endl << " exited with exit code: " << exitcode << std::endl; else log_file << "Process: " << command << " with pid: " << QString::number(proc->processId()).toStdString() << std::endl << " CRASHED with exit code: " << exitcode << std::endl; auto it = std::find(active_process_list.begin(), active_process_list.end(), process); active_process_list.erase(it); if(active_process_list.size() == 0) { log_file << "-------- All processes finished." << std::endl; log_file.flush(); log_file.close(); app.exit(0); } }); active_process_list.push_back(proc); } if(!working_dir.isEmpty()) proc->setWorkingDirectory(working_dir); proc->setStandardOutputFile(QString::fromStdString(log_file_name)); proc->setProgram(QString::fromStdString(name)); proc->setArguments(sargs); if(mode == "wait") proc->start(QString::fromStdString(name), sargs); else proc->startDetached(QString::fromStdString(name), sargs); } return app.exec(); }