diff --git a/main.cpp b/main.cpp index bda8c0e..26927ad 100644 --- a/main.cpp +++ b/main.cpp @@ -16,6 +16,9 @@ *****************************************************************************/ #include +#include +#include +#include #include #include "mayu.h" @@ -28,11 +31,28 @@ int main(int argc, char *argv[]) QStringList arguments = a.arguments(); arguments.removeAt(0); + mayuMode a_mode = mayuMode::Ping; + for (int i = arguments.length(); i > 0; i--) { + const QString &argument = arguments.at(i-1); + if (argument == "-p" || argument == "--ping") { + a_mode = mayuMode::Ping; + arguments.removeAt(i-1); + } + else if (argument == "-r" || argument == "--resolve") { + a_mode = mayuMode::Resolve; + arguments.removeAt(i-1); + } + } + if (arguments.length() >= 2) { mayu a_mayu(arguments.at(0), arguments.at(1)); + a_mayu.setMayuMode(a_mode); a_mayu.work(); return a_mayu.getResult(); } + else { + QTextStream(stdout) << "Usage: " << a.arguments().at(0) << " [-p ping]" << " [-r resolve]" << " input.txt" << " output.json" << endl; + } return 0; } diff --git a/mayu.cpp b/mayu.cpp index 94fe964..96de91e 100644 --- a/mayu.cpp +++ b/mayu.cpp @@ -26,20 +26,29 @@ #include using namespace std; +#ifdef MAYU_UNIX extern "C" { #include "oping.h" } +#endif -mayu::mayu(const QString &hostsFile, const QString &jsonFile, int tries, QObject *parent) : QObject(parent) +mayu::mayu(const QString &hostsFile, const QString &jsonFile, QObject *parent) : QObject(parent) { p_return = -1; - p_tries = tries; + p_timeout = 2.5; + p_tries = 4; + p_mayuMode = mayuMode::Ping; if (!hostsFile.isEmpty()) setHostsFile(hostsFile); if (!jsonFile.isEmpty()) setJsonFile(jsonFile); } +void mayu::setMayuMode(mayuMode mode) +{ + p_mayuMode = mode; +} + void mayu::setHostsFile(const QString &fileName) { p_hostsFile = fileName; @@ -57,11 +66,21 @@ void mayu::setJsonFile(const QString &fileName) p_jsonFile = fileName; } -void mayu::setMaxTries(int tries) +void mayu::setPingTimeout(double timeout) +{ + p_timeout = timeout; +} + +void mayu::setPingTries(int tries) { p_tries = tries; } +mayuMode mayu::getMayuMode() +{ + return p_mayuMode; +} + const QString mayu::getHostsFile() { return p_hostsFile; @@ -77,7 +96,12 @@ const QString mayu::getJsonFile() return p_jsonFile; } -int mayu::getMaxTries() +double mayu::getPingTimeout() +{ + return p_timeout; +} + +int mayu::getPingTries() { return p_tries; } @@ -87,21 +111,18 @@ int mayu::getResult() return p_return; } +#ifdef MAYU_UNIX double mayu::ping(const QString &host, int tries, double timeout) { double latency; pingobj_t *pingObj; pingobj_iter_t *pingIter; if ((pingObj = ping_construct()) == NULL) { -#ifdef E_DEBUG - qDebug() << "Ping construction failed"; -#endif + QTextStream(stderr) << "Ping construction failed " << endl; return -1; } if (ping_setopt(pingObj, PING_OPT_TIMEOUT, (void*)(&timeout)) < 0) { -#ifdef E_DEBUG - qDebug() << "Setting timeout to" << timeout << "have failed"; -#endif + QTextStream(stderr) << "Setting timeout to" << timeout << " have failed" << endl; ping_destroy(pingObj); return -1; } @@ -148,9 +169,7 @@ double mayu::ping(const QString &host, int tries, double timeout) int curTry = 0; while (!hostUp && curTry != tries) { if (ping_send(pingObj) < 0) { -#ifdef E_DEBUG - qDebug() << "Pinging host" << host << " has failed"; -#endif + QTextStream(stderr) << "Pinging host " << host << " has failed" << endl; ping_destroy(pingObj); return -1; } @@ -165,7 +184,7 @@ double mayu::ping(const QString &host, int tries, double timeout) char hostname[100]; len = 100; ping_iterator_get_info(pingIter, PING_INFO_HOSTNAME, hostname, &len); - qDebug() << hostname << latency << pingSuccess; + QTextStream(stdout) << "Host: " << hostname << " Ping: " << latency << "ms" << " Status: " << (pingSuccess ? "true" : "false") << endl; #endif } if (pingSuccess) { @@ -178,14 +197,44 @@ double mayu::ping(const QString &host, int tries, double timeout) return latency; return -1; } +#endif + +const QList mayu::resolve(const QString &host) +{ + QList resultList; + QList hostAddresses = QHostInfo::fromName(host).addresses(); + if (hostAddresses.length() >= 1) { + for (const QHostAddress &hostAddress : hostAddresses) { +#ifdef E_DEBUG + qDebug() << "Hostname" << host << "found and resolved" << hostAddress.toString(); +#endif + mayuResult m_result; + m_result.host = host; + m_result.result = hostAddress.toString(); + resultList += m_result; + } + } + else { +#ifdef E_DEBUG + qDebug() << "Hostname" << host << "not found"; +#endif + mayuResult m_result; + m_result.host = host; + m_result.result = "-1"; + resultList += m_result; + } + return resultList; +} void mayu::parse_hosts() { p_hostsList.clear(); - if (!dropPrivileges()) { +#ifdef PRIVILEGE_DROP_REQUIRED + if (!p_dropPrivileges()) { p_return = 2; return; } +#endif QFile hostsFile(p_hostsFile); if (hostsFile.open(QFile::ReadOnly)) { const QList hostsArray = hostsFile.readAll().split('\n'); @@ -210,57 +259,104 @@ void mayu::parse_hosts() } else { - qCritical() << "Failed read hosts from" << p_hostsFile; + QTextStream(stderr) << "Failed read hosts from " << p_hostsFile << endl; } - if (!regainPrivileges()) { +#ifdef PRIVILEGE_DROP_REQUIRED + if (!p_regainPrivileges()) { p_return = 3; return; } +#endif +} + +void mayu::p_saveWork(QJsonObject jsonObject) +{ + QJsonDocument jsonDocument; + jsonDocument.setObject(jsonObject); + QByteArray jsonArray = jsonDocument.toJson(); +#ifdef PRIVILEGE_DROP_REQUIRED + if (!p_dropPrivileges()) { + p_return = 2; + return; + } +#endif + QSaveFile jsonFile(p_jsonFile); + if (jsonFile.open(QSaveFile::WriteOnly)) { + jsonFile.write(jsonArray); + if (!jsonFile.commit()) { + QTextStream(stderr) << "Failed save result to " << p_jsonFile << " because file can't be saved!" << endl; + p_return = 1; + } + } + else { + QTextStream(stderr) << "Failed save result to " << p_jsonFile << " because file can't be opened!" << endl; + p_return = 1; + } +#ifdef PRIVILEGE_DROP_REQUIRED + if (!p_regainPrivileges()) { + p_return = 3; + return; + } +#endif + p_return = 0; } void mayu::work() +{ + switch(p_mayuMode) { + case mayuMode::Ping: +#ifdef MAYU_UNIX + p_workPing(); +#else + QTextStream(stderr) << "Mayu doesn't support pinging on your Operating System!" << endl; +#endif + break; + case mayuMode::Resolve: + p_workResolve(); + break; + } +} + +#ifdef MAYU_UNIX +void mayu::p_workPing() { if (!p_hostsParsed) parse_hosts(); QJsonObject jsonObject; const QStringList hostsList = getHosts(); for (const QString &host : hostsList) { - double result = ping(host, p_tries); + double result = ping(host, p_tries, p_timeout); jsonObject[host] = result; } - QJsonDocument jsonDocument; - jsonDocument.setObject(jsonObject); - QByteArray jsonArray = jsonDocument.toJson(); - if (!dropPrivileges()) { - p_return = 2; - return; - } - QSaveFile jsonFile(p_jsonFile); - if (jsonFile.open(QSaveFile::WriteOnly)) { - jsonFile.write(jsonArray); - if (!jsonFile.commit()) { - qCritical() << "Failed save result to" << p_jsonFile << "because file can't be saved!"; - p_return = 1; + p_saveWork(jsonObject); +} +#endif + +void mayu::p_workResolve() +{ + if (!p_hostsParsed) + parse_hosts(); + QJsonObject jsonObject; + const QStringList hostsList = getHosts(); + for (const QString &host : hostsList) { + const QList resultList = resolve(host); + QJsonArray arrayList; + for (const mayuResult &result : resultList) { + arrayList += result.result; } + jsonObject[host] = arrayList; } - else { - qCritical() << "Failed save result to" << p_jsonFile << "because file can't be opened!"; - p_return = 1; - } - if (!regainPrivileges()) { - p_return = 3; - return; - } - p_return = 0; + p_saveWork(jsonObject); } -bool mayu::dropPrivileges() +#ifdef PRIVILEGE_DROP_REQUIRED +bool mayu::p_dropPrivileges() { #if _POSIX_SAVED_IDS p_uid = geteuid(); int status = seteuid(getuid()); if (status != 0) { - qCritical() << "Dropping of privileges has failed!"; + QTextStream(stderr) << "Dropping of privileges has failed!" << endl; return false; } return true; @@ -269,12 +365,12 @@ bool mayu::dropPrivileges() #endif } -bool mayu::regainPrivileges() +bool mayu::p_regainPrivileges() { #if _POSIX_SAVED_IDS int status = seteuid(p_uid); if (status != 0) { - qCritical() << "Regaining of privileges has failed!"; + QTextStream(stderr) << "Regaining of privileges has failed!" << endl; return false; } return true; @@ -282,3 +378,4 @@ bool mayu::regainPrivileges() return false; #endif } +#endif diff --git a/mayu.h b/mayu.h index 79a23fe..9ac3c27 100644 --- a/mayu.h +++ b/mayu.h @@ -21,38 +21,64 @@ #include #include #include +#include #include +#include + +enum class mayuMode : int{Ping = 0, Resolve = 1}; +struct mayuResult { + QString host; + QString result; +}; class mayu : public QObject { Q_OBJECT public: - explicit mayu(const QString &hostsFile = QString(), const QString &jsonFile = QString(), int tries = 4, QObject *parent = nullptr); + explicit mayu(const QString &hostsFile = QString(), const QString &jsonFile = QString(), QObject *parent = nullptr); + void setMayuMode(mayuMode mode); void setHostsFile(const QString &fileName); void setHosts(const QStringList &hostsList); void setJsonFile(const QString &fileName); - void setMaxTries(int tries); + void setPingTimeout(double timeout); + void setPingTries(int tries); + mayuMode getMayuMode(); const QString getHostsFile(); const QStringList getHosts(); const QString getJsonFile(); - int getMaxTries(); + double getPingTimeout(); + int getPingTries(); int getResult(); +#ifdef MAYU_UNIX static double ping(const QString &host, int tries, double timeout = 2.5); +#endif + static const QList resolve(const QString &host); public slots: void parse_hosts(); void work(); private: - bool dropPrivileges(); - bool regainPrivileges(); +#ifdef PRIVILEGE_DROP_REQUIRED + bool p_dropPrivileges(); + bool p_regainPrivileges(); +#endif + void p_saveWork(QJsonObject jsonObject); +#ifdef MAYU_UNIX + void p_workPing(); +#endif + void p_workResolve(); QStringList p_hostsList; QString p_hostsFile; QString p_jsonFile; + mayuMode p_mayuMode; bool p_hostsParsed; + double p_timeout; int p_return; int p_tries; +#ifdef PRIVILEGE_DROP_REQUIRED uid_t p_uid; +#endif }; #endif // MAYU_H diff --git a/mayu.pro b/mayu.pro index 1a2a1c4..accb72a 100644 --- a/mayu.pro +++ b/mayu.pro @@ -18,7 +18,9 @@ QT -= gui QT += network -LIBS += -loping +unix: DEFINES += PRIVILEGE_DROP_REQUIRED +unix: DEFINES += MAYU_UNIX +unix: LIBS += -loping CONFIG += c++11 console CONFIG -= app_bundle