diff --git a/Opkg/message_handler.cpp b/Opkg/message_handler.cpp new file mode 100755 index 0000000..996bd2f --- /dev/null +++ b/Opkg/message_handler.cpp @@ -0,0 +1,97 @@ +#include "message_handler.h" + +#include +#include +#include +#include +#include + + +static char const *DBG_NAME[] = { "DBG ", "WARN ", "CRIT ", "FATAL", "INFO " }; +static bool installedMsgHandler = false; +static int debugLevel = LOG_NOTICE; + +int getDebugLevel() { return debugLevel; } +void setDebugLevel(int newDebugLevel) { + debugLevel = newDebugLevel; +} + +bool messageHandlerInstalled() { + return installedMsgHandler; +} + +QtMessageHandler atbInstallMessageHandler(QtMessageHandler handler) { + installedMsgHandler = (handler != 0); + static QtMessageHandler prevHandler = nullptr; + if (handler) { + prevHandler = qInstallMessageHandler(handler); + return prevHandler; + } else { + return qInstallMessageHandler(prevHandler); + } +} + +/// +/// \brief Print message according to given debug level. +/// +/// \note Install this function using qInstallMsgHandler(). +/// +/// int main(int argc, char **argv) { +/// installMsgHandler(atbDebugOutput); +/// QApplication app(argc, argv); +/// ... +/// return app.exec(); +/// } +/// +#if (QT_VERSION > QT_VERSION_CHECK(5, 0, 0) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) +void atbDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { + Q_UNUSED(context); + QString const localMsg = QString(DBG_NAME[type]) + msg.toLocal8Bit(); + + switch (debugLevel) { + case LOG_DEBUG: { // debug-level message + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } break; + case LOG_INFO: { // informational message + if (type != QtDebugMsg) { + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } + } break; + case LOG_NOTICE: { // normal, but significant, condition + if (type != QtDebugMsg) { + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } + } break; + case LOG_WARNING: { // warning conditions + if (type != QtInfoMsg && type != QtDebugMsg) { + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } + } break; + case LOG_ERR: { // error conditions + if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) { + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } + } break; + case LOG_CRIT: { // critical conditions + if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) { + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } + } break; + case LOG_ALERT: { // action must be taken immediately + if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) { + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } + } break; + case LOG_EMERG: { // system is unusable + if (type != QtInfoMsg && type != QtDebugMsg && type != QtWarningMsg) { + syslog(LOG_DEBUG, "%s", localMsg.toStdString().c_str()); + } + } break; + default: { + //fprintf(stderr, "%s No ErrorLevel defined! %s\n", + // datetime.toStdString().c_str(), msg.toStdString().c_str()); + } + } +} +#endif + diff --git a/Opkg/message_handler.h b/Opkg/message_handler.h new file mode 100755 index 0000000..98c4d7e --- /dev/null +++ b/Opkg/message_handler.h @@ -0,0 +1,23 @@ +#ifndef MESSAGE_HANDLER_H_INCLUDED +#define MESSAGE_HANDLER_H_INCLUDED + +#include +#ifdef __linux__ +#include +#endif + +int getDebugLevel(); +void setDebugLevel(int newDebugLevel); + +bool messageHandlerInstalled(); +QtMessageHandler atbInstallMessageHandler(QtMessageHandler handler); + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +// typedef void (*QtMessageHandler)(QtMsgType, const char *); +void atbDebugOutput(QtMsgType type, const char *msg); +#elif QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +// typedef void (*QtMessageHandler)(QtMsgType, const QMessageLogContext &, const QString &); +void atbDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg); +#endif + +#endif // MESSAGE_HANDLER_H_INCLUDED diff --git a/Opkg/opkg_command.cpp b/Opkg/opkg_command.cpp new file mode 100644 index 0000000..3103b8b --- /dev/null +++ b/Opkg/opkg_command.cpp @@ -0,0 +1,176 @@ +#include "opkg_command.h" + +#include "command.h" +#include "utils_internal.h" +using namespace internal; + +#include +#include +#include +#include + +OpkgCommand::OpkgCommand(bool noaction, QString const &opkg_commands_filename) + : m_noaction(noaction) + , m_opkg_commands_filename(opkg_commands_filename) { + cleanUpOpkgCache(); + execCommandsInternal(); +} + +bool OpkgCommand::readCommands() { + QFile opkgFile(QDir::cleanPath(m_opkg_commands_dir + QDir::separator() + m_opkg_commands_filename)); + if (!opkgFile.exists()) { + qCritical() << __func__ << ":" << __LINE__ + << opkgFile.fileName() << "does not exists"; + return false; + } + + m_commands.clear(); + + if (opkgFile.open(QIODevice::ReadOnly)) { + QTextStream in(&opkgFile); + while (!in.atEnd()) { + QString line = in.readLine(); + // TODO: "^\\s*[#]{0,}$" : empty line or comment line starting with # + static const QRegularExpression comment("^\\s*[#].*$"); + static const QRegularExpression emptyLine("^\\s*$"); + if (line.indexOf(emptyLine, 0) == -1 && + line.indexOf(comment, 0) == -1) { + QString const &commandLine = line.trimmed(); + if (!commandLine.isEmpty()) { + m_commands << commandLine; + } + } + } + } else { + qCritical() << __func__ << ":" << __LINE__ + << "error opening" << opkgFile.fileName(); + } + + return m_commands.size() > 0; +} + +bool OpkgCommand::execCommandsInternal() { + if (readCommands()) { + // command lines are located between markers: ... + // they are later removed when used by the update-tool. + qCritical().noquote() << ""; + QListIterator it(m_commands); + while (it.hasNext()) { + QString command = it.next(); + QStringList cmdAndOptions = command.split(u' ', QString::SkipEmptyParts); + if (cmdAndOptions.size() > 0) { + QString const &cmd = cmdAndOptions.takeFirst(); + if (m_noaction) { + if (cmd.contains("opkg")) { + cmdAndOptions.prepend("--noaction"); + } else continue; // only opkg has the --noaction option + } + QStringList const &options = cmdAndOptions; + if (exec(cmd, options)) { + qCritical().noquote() << cmd << options.join(" ") << "ok" << ""; + } else { + qCritical().noquote() << cmd << options.join(" ") << "FAIL" << ""; + } + } + } + return true; + } + return false; + +} + +bool OpkgCommand::execCommands() { + if (readCommands()) { + QListIterator it(m_commands); + while (it.hasNext()) { + QString command = it.next(); + QStringList cmdAndOptions = command.split(u' ', QString::SkipEmptyParts); + if (cmdAndOptions.size() > 0) { + QString const &cmd = cmdAndOptions.takeFirst(); + if (m_noaction) { + cmdAndOptions.prepend("--noaction"); + } + QStringList const &options = cmdAndOptions; + if (exec(cmd, options)) { + qCritical().noquote() << cmd << options.join(" "); + } else { + qCritical().noquote() << cmd << options.join(" ") << "FAIL"; + return false; + } + } + } + return true; + } + return false; + +#if 0 + + QFile opkgFile(QDir::cleanPath(m_opkg_commands_dir + QDir::separator() + m_opkg_commands_filename)); + if (!opkgFile.exists()) { + qCritical() << __func__ << ":" << __LINE__ + << opkgFile.fileName() << "does not exists"; + return false; + } + + if (opkgFile.open(QIODevice::ReadOnly)) { + QTextStream in(&opkgFile); + while (!in.atEnd()) { + QString line = in.readLine(); + // TODO: "^\\s*[#]{0,}$" : empty line or comment line starting with # + static const QRegularExpression comment("^\\s*[#].*$"); + static const QRegularExpression emptyLine("^\\s*$"); + if (line.indexOf(emptyLine, 0) == -1 && + line.indexOf(comment, 0) == -1) { + QString const &commandLine = line.trimmed(); + if (!commandLine.isEmpty()) { + QStringList cmdAndOptions = commandLine.split(u' ', QString::SkipEmptyParts); + if (cmdAndOptions.size() > 0) { + QString const &cmd = cmdAndOptions.takeFirst(); + if (m_noaction) { + cmdAndOptions.prepend("--noaction"); + } + QStringList const &options = cmdAndOptions; + if (exec(cmd, options)) { + qCritical().noquote() << cmd << options.join(" ") << "ok"; + } else { + qCritical().noquote() << cmd << options.join(" ") << "FAIL"; + } + } else { + continue; + } + } + } + } + return true; + } else { + qCritical() << __func__ << ":" << __LINE__ + << "error opening" << opkgFile.fileName(); + } + + return false; +#endif +} + +bool OpkgCommand::exec(QString const &cmd, QStringList const &options, + int start_timeout, int finish_timeout) { + bool const verbose = false; + return Command(cmd, options, "/tmp", verbose, start_timeout, finish_timeout).exec(); +} + +bool OpkgCommand::cleanUpOpkgCache() { + bool removedFiles = true; + QDir dir("/var/cache/opkg/"); + if (dir.exists()) { + dir.setNameFilters(QStringList() << ".gz" << ".ipk"); + dir.setFilter(QDir::Files); + foreach(QString dirFile, dir.entryList()) { + removedFiles &= dir.remove(dirFile); + } + } + + if (removedFiles == false) { + qCritical() << "some errors while cleaning up opkg-cache"; + } + + return removedFiles; +} diff --git a/Opkg/opkg_command.h b/Opkg/opkg_command.h new file mode 100644 index 0000000..486162e --- /dev/null +++ b/Opkg/opkg_command.h @@ -0,0 +1,29 @@ +#ifndef OPKG_COMMND_H_INCLUDED +#define OPKG_COMMND_H_INCLUDED + +#include + +class OpkgCommand { + QString const m_opkg_commands_dir{"/etc/psa_update/"}; + bool m_noaction; + QString m_opkg_commands_filename; + QStringList m_commands; + + bool execCommands(); + bool execCommandsInternal(); + bool cleanUpOpkgCache(); + +public: + OpkgCommand(bool noaction = false, + QString const &opkg_commands_file_name="opkg_commands"); + + bool exec(QString const &cmd, QStringList const &options, + int start_timeout = 100000, int finish_timeout = 100000); + + QStringList commands() { return m_commands; } + QStringList const &commands() const { return m_commands; } + + bool readCommands(); +}; + +#endif // OPKG_COMMND_H_INCLUDED