CustomStartupRunner/main.cpp
2025-10-28 09:47:44 +05:30

109 lines
4.2 KiB
C++

#include <filesystem>
#include <fstream>
#include <chrono>
#include <format>
#include <QObject>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <iostream>
#include <sstream>
#include <QString>
#include <QCoreApplication>
#include <QProcess>
#include <unistd.h>
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<QProcess *> 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 << " with working dir: " << working_dir.toStdString() << "\n";
QProcess *proc = new QProcess();
QObject::connect(proc, &QProcess::started, [&, command, proc, working_dir] () {
log_file << "Started process: " << command << " with pid: " << QString::number(proc->processId()).toStdString() << " with working directory as: " << working_dir.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();
}