From a66d4b9bcc6df6580b04c4b9f6c389d68d79ec8b Mon Sep 17 00:00:00 2001 From: Luke De Mouy Date: Mon, 18 Jan 2016 16:27:21 -0700 Subject: [PATCH 1/5] Create the ServiceManager Class that has the following functionality: *Start/Stop/Restart a Service *Enable/Disable a Service *Get the List of services *Get a specific service token Pull in two functions from pcbsd-utils into sysadm-general: GetConfFileValue SetConfFileValue which are used to modify /etc/rc.conf --- src/library/library.pro | 6 +- src/library/sysadm-general.cpp | 133 +++++++++++++++++++- src/library/sysadm-general.h | 59 ++++++--- src/library/sysadm-servicemanager.cpp | 172 ++++++++++++++++++++++++++ src/library/sysadm-servicemanager.h | 73 +++++++++++ 5 files changed, 421 insertions(+), 22 deletions(-) create mode 100644 src/library/sysadm-servicemanager.cpp create mode 100644 src/library/sysadm-servicemanager.h diff --git a/src/library/library.pro b/src/library/library.pro index c08f0aa..dca294a 100644 --- a/src/library/library.pro +++ b/src/library/library.pro @@ -15,14 +15,16 @@ HEADERS += sysadm-global.h \ sysadm-lifepreserver.h \ sysadm-network.h \ sysadm-firewall.h \ - sysadm-usermanager.h + sysadm-usermanager.h \ + sysadm-servicemanager.h SOURCES += sysadm-general.cpp \ sysadm-lifepreserver.cpp \ sysadm-network.cpp \ NetDevice.cpp \ sysadm-firewall.cpp \ - sysadm-usermanager.cpp + sysadm-usermanager.cpp \ + sysadm-servicemanager.cpp include.path=/usr/local/include/ include.files=sysadm-*.h diff --git a/src/library/sysadm-general.cpp b/src/library/sysadm-general.cpp index 9e0cb40..3a2b812 100644 --- a/src/library/sysadm-general.cpp +++ b/src/library/sysadm-general.cpp @@ -23,7 +23,7 @@ QString General::RunCommand(bool &success, QString command, QStringList argument QProcessEnvironment PE = QProcessEnvironment::systemEnvironment(); if(!env.isEmpty()){ for(int i=0; i=] - // - Both success/log of output - static QString RunCommand(bool &success, QString command, QStringList arguments = QStringList(), QString workdir = "", QStringList env = QStringList() ); - // - Log output only - static QString RunCommand(QString command, QStringList arguments = QStringList(), QString workdir = "", QStringList env = QStringList() ); - // - success output only - static bool RunQuickCommand(QString command, QStringList arguments = QStringList(), QString workdir = "", QStringList env = QStringList() ); - - //File Access Functions - static QStringList readTextFile(QString filename); - static bool writeTextFile(QString filename, QStringList contents, bool overwrite = true); - - //Retrieve a text-based sysctl - static QString sysctl(QString var); - //Retrieve a number-based sysctl - static long long sysctlAsInt(QString var); + //Non-event-blocking versions of QProcess::execute() or system() + //Note: environment changes should be listed as such: [=] + // - Both success/log of output + static QString RunCommand(bool &success, QString command, QStringList arguments = QStringList(), QString workdir = "", QStringList env = QStringList() ); + // - Log output only + static QString RunCommand(QString command, QStringList arguments = QStringList(), QString workdir = "", QStringList env = QStringList() ); + // - success output only + static bool RunQuickCommand(QString command, QStringList arguments = QStringList(), QString workdir = "", QStringList env = QStringList() ); + + //File Access Functions + static QStringList readTextFile(QString filename); + static bool writeTextFile(QString filename, QStringList contents, bool overwrite = true); + + /** + * @brief getConfFileValue get the value associated with a key in a config file + * @param fileName the file to read from + * @param Key the key to look for + * @param occur which occurance of the key to return, 1 = the first occurance + * @return the value associated with the key + */ + static QString getConfFileValue( QString fileName, QString Key, int occur =1); + + /** + * @brief setConfFileValue set a value in a config file + * @param fileName the file to write to + * @param oldKey the key to look for + * @param newKey the new key with it's value + * @param occur which occurance in a file to write the key to, if set to -1 it removes all duplicates + * @return success or failure to write the key + */ + static bool setConfFileValue( QString fileName, QString oldKey, QString newKey, int occur = -1 ); + + + //Retrieve a text-based sysctl + static QString sysctl(QString var); + //Retrieve a number-based sysctl + static long long sysctlAsInt(QString var); + }; - + } //end of pcbsd namespace -#endif \ No newline at end of file +#endif diff --git a/src/library/sysadm-servicemanager.cpp b/src/library/sysadm-servicemanager.cpp new file mode 100644 index 0000000..9cbff06 --- /dev/null +++ b/src/library/sysadm-servicemanager.cpp @@ -0,0 +1,172 @@ +#include "sysadm-servicemanager.h" +#include "sysadm-general.h" +using namespace sysadm; +ServiceManager::ServiceManager(QString chroot, QString ip) +{ + this->chroot = chroot; + this->ip = ip; + loadServices(); +} + +Service ServiceManager::GetService(QString serviceName) +{ + for(Service service : services) + { + if(service.Name == serviceName) + return service; + } + return Service(); +} + +QVector ServiceManager::GetServices() +{ + return services; +} + +void ServiceManager::Start(Service service) +{ + // Start the process + QString prog; + QStringList args; + + if ( chroot.isEmpty() ) { + prog = "service"; + args << service.Directory; + args << "start"; + } else { + prog = "warden"; + args << "chroot" << ip << "service" << service.Directory << "start"; + } + General::RunCommand(prog,args); +} + +void ServiceManager::Stop(Service service) +{ + // Start the process + QString prog; + QStringList args; + + if ( chroot.isEmpty() ) { + prog = "service"; + args << service.Directory; + args << "stop"; + } else { + prog = "warden"; + args << "chroot" << ip << "service" << service.Directory << "stop"; + } + General::RunCommand(prog,args); +} + +void ServiceManager::Restart(Service service) +{ + QString prog; + QStringList args; + + if ( chroot.isEmpty() ) { + prog = "service"; + args << service.Directory; + args << "restart"; + } else { + prog = "warden"; + args << "chroot" << ip << "service" << service.Directory << "restart"; + } + General::RunCommand(prog,args); +} + +void ServiceManager::Enable(Service service) +{ + General:: setConfFileValue( chroot + "/etc/rc.conf", service.Tag, service.Tag + "=\"YES\"", -1); +} + +void ServiceManager::Disable(Service service) +{ + General:: setConfFileValue( chroot + "/etc/rc.conf", service.Tag, service.Tag + "=\"NO\"", -1); +} + +void ServiceManager::loadServices() +{ + QString tmp; + bool valid; + Service service; + + QStringList stringDirs; + stringDirs << chroot + "/etc/rc.d" << chroot + "/usr/local/etc/rc.d"; + + for ( QString dir: stringDirs) + { + + QDir directory( dir ); + + directory.setFilter( QDir::Files ); + directory.setSorting( QDir::Name ); + + if ( directory.count() == 0 ) + return; + + for ( int i = 0; i < directory.count(); i++ ) + { + service = Service(); + + QFile file( dir + "/" + directory[i] ); + if ( file.open( QIODevice::ReadOnly ) ) + { + valid=false; + service.Directory=directory[i]; + QTextStream stream( &file ); + stream.setCodec("UTF-8"); + QString line; + while ( !stream.atEnd() ) + { + line = stream.readLine(); // line of text excluding '\n' + + if ( line.indexOf("name=") == 0) + { + valid=true; + tmp = line.replace("name=", ""); + service.Name = tmp.replace('"', ""); + } + if ( line.indexOf("rcvar=") == 0) + { + if ( tmp.isEmpty() ) + continue; + + tmp = line.replace("rcvar=", ""); + tmp = tmp.replace('"', ""); + tmp = tmp.replace("'", ""); + tmp = tmp.replace("`", ""); + tmp = tmp.replace("$(set_rcvar)", ""); + tmp = tmp.replace("$set_rcvar", ""); + tmp = tmp.replace("set_rcvar", ""); + tmp = tmp.replace("${name}", ""); + tmp = tmp.replace("_enable", ""); + tmp = tmp.replace(" ", ""); + + if (tmp.isEmpty()) + service.Tag = service.Name + "_enable"; + else + service.Tag = tmp; + + if ( service.Tag.indexOf("_enable") == -1 ) + service.Tag=service.Tag + "_enable"; + break; + } + } + file.close(); + + if ( !valid || service.Tag.isEmpty() ) + continue; + + QString cDir = dir; + if ( ! chroot.isEmpty() ) + cDir.replace(chroot, ""); + if ( service.Tag.indexOf("$") == 0 ) + service.Tag = service.Directory + "_enable"; + if ( service.Name.indexOf("$") == 0 ) + service.Name = service.Directory; + + services << service; + qDebug() << "Added Service:" << cDir << service.Directory << service.Name << service.Tag; + } + } + } +} diff --git a/src/library/sysadm-servicemanager.h b/src/library/sysadm-servicemanager.h new file mode 100644 index 0000000..6b70d06 --- /dev/null +++ b/src/library/sysadm-servicemanager.h @@ -0,0 +1,73 @@ +#ifndef SERVICEMANAGER_H +#define SERVICEMANAGER_H +#include +namespace sysadm{ +struct Service{ + Service() + { + Name = ""; + Tag = ""; + Directory = ""; + } + + QString Name; + QString Tag; + QString Directory; +}; + +class ServiceManager +{ +public: + /** + * @brief ServiceManager constructor for service manager + * @param chroot if we're using a chroot, the chroot to use + * @param ip if we're in a jail the ip to use + */ + ServiceManager(QString chroot = "", QString ip = ""); + + /** + * @brief GetService gets a service by it's name + * @param serviceName the name of the service to get, use the name that would be stored in Service.Name + * @return the service with the service name, if the service is not found it returns a blank Service + */ + Service GetService(QString serviceName); + /** + * @brief GetServices getter for the vector of services + * @return returns the vector of services on the system + */ + QVector GetServices(); + + /** + * @brief Start starts a service + * @param service the service to start + */ + void Start(Service service); + /** + * @brief Stop stops a service + * @param service the service to stop + */ + void Stop(Service service); + /** + * @brief Restart restarts a service + * @param service the service to restart + */ + void Restart(Service service); + + /** + * @brief Enable enable a service + * @param service the service to enable + */ + void Enable(Service service); + /** + * @brief Disable disable a service + * @param service the service to disable + */ + void Disable(Service service); +private: + QVector services; + void loadServices(); + QString chroot; + QString ip; +}; +} +#endif // SERVICEMANAGER_H From 28eab2e2ef1a0f1d41267ac67af4a435515b7816 Mon Sep 17 00:00:00 2001 From: Luke De Mouy Date: Mon, 18 Jan 2016 16:29:01 -0700 Subject: [PATCH 2/5] switch the Firewall class over to using the ServiceManager --- src/library/sysadm-firewall.cpp | 67 ++++++++++++--------------------- src/library/sysadm-firewall.h | 6 ++- 2 files changed, 29 insertions(+), 44 deletions(-) diff --git a/src/library/sysadm-firewall.cpp b/src/library/sysadm-firewall.cpp index 13317ae..837aa6a 100644 --- a/src/library/sysadm-firewall.cpp +++ b/src/library/sysadm-firewall.cpp @@ -10,6 +10,20 @@ #include using namespace sysadm; + +Firewall::Firewall() +{ + readServicesFile(); + LoadOpenPorts(); + + firewallService = serviceManager.GetService("ipfw"); +} + +Firewall::~Firewall() +{ + delete portStrings; +} + PortInfo Firewall::LookUpPort(int port, QString type) { //Make sure that the port is valid @@ -74,7 +88,7 @@ PortInfo Firewall::LookUpPort(int port, QString type) returnValue.Description = description; } } - + return returnValue; } @@ -122,52 +136,30 @@ bool Firewall::IsRunning() void Firewall::Start() { - Enable(); - - QStringList args; - args << "start"; - General::RunCommand("/etc/rc.d/ipfw",args); + serviceManager.Enable(firewallService); + serviceManager.Start(firewallService); } void Firewall::Stop() { - Enable(); - QStringList args; - args << "stop"; - General::RunCommand("/etc/rc.d/ipfw",args); + serviceManager.Enable(firewallService); + serviceManager.Stop(firewallService); } void Firewall::Restart() { - Enable(); - - QStringList args; - args << "restart"; - General::RunCommand("/etc/rc.d/ipfw",args); + serviceManager.Enable(firewallService); + serviceManager.Restart(firewallService); } void Firewall::Enable() { - //check if rc.conf has firewall_enable="YES" - QStringList rcConf = General::readTextFile("/etc/rc.conf"); - if (rcConf.filter("firewall_enabled=\"YES\"").size() == 0) - { - rcConf.removeAll("firewall_enable=\"NO\""); - rcConf.append("firewall_enabled=\"YES\""); - General::writeTextFile("/etc/rc.conf",rcConf); - } + serviceManager.Enable(firewallService); } void Firewall::Disable() { - //check if rc.conf has firewall_enable="NO" - QStringList rcConf = General::readTextFile("/etc/rc.conf"); - if (rcConf.filter("firewall_enabled=\"NO\"").size() == 0) - { - rcConf.removeAll("firewall_enable=\"YES\""); - rcConf.append("firewall_enabled=\"NO\""); - General::writeTextFile("/etc/rc.conf",rcConf); - } + serviceManager.Disable(firewallService); } void Firewall::RestoreDefaults() @@ -201,17 +193,6 @@ void Firewall::RestoreDefaults() LoadOpenPorts(); } -Firewall::Firewall() -{ - readServicesFile(); - LoadOpenPorts(); -} - -Firewall::~Firewall() -{ - delete portStrings; -} - void Firewall::readServicesFile() { portStrings = new QStringList(); @@ -280,4 +261,4 @@ void Firewall::SaveOpenPorts() General::RunCommand("sh",args); } } - + diff --git a/src/library/sysadm-firewall.h b/src/library/sysadm-firewall.h index beb48c0..7d9663c 100644 --- a/src/library/sysadm-firewall.h +++ b/src/library/sysadm-firewall.h @@ -8,6 +8,7 @@ #define PORTLOOKUP_H #include #include +#include "sysadm-servicemanager.h" namespace sysadm { struct PortInfo{ @@ -125,7 +126,10 @@ private: void LoadOpenPorts(); void SaveOpenPorts(); + + ServiceManager serviceManager; + Service firewallService; }; } #endif // PORTLOOKUP_H - + From 71ef5fb49da1ef1a081621cd2463d7319cfdc009 Mon Sep 17 00:00:00 2001 From: Luke De Mouy Date: Mon, 18 Jan 2016 16:30:03 -0700 Subject: [PATCH 3/5] Move Ctors/Dtors to top of class as is normal --- src/library/sysadm-firewall.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/library/sysadm-firewall.h b/src/library/sysadm-firewall.h index 7d9663c..d0360e8 100644 --- a/src/library/sysadm-firewall.h +++ b/src/library/sysadm-firewall.h @@ -35,6 +35,11 @@ class Firewall { public: + ///#section: ctors dtors + Firewall(); + ~Firewall(); + ///#endsection + ///#section: port commands /** * @description Returns a structure containing information about the port @@ -113,11 +118,6 @@ public: void RestoreDefaults(); ///#endsection - ///#section: ctors dtors - Firewall(); - ~Firewall(); - ///#endsection - private: void readServicesFile(); QStringList* portStrings; From 8930ed8a01c29e0745391849f285b18b5513a12b Mon Sep 17 00:00:00 2001 From: Luke De Mouy Date: Mon, 18 Jan 2016 16:37:20 -0700 Subject: [PATCH 4/5] put unsigned back in to get rid of the warning about conversion between int and uint --- src/library/sysadm-servicemanager.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/library/sysadm-servicemanager.cpp b/src/library/sysadm-servicemanager.cpp index 9cbff06..7aad73a 100644 --- a/src/library/sysadm-servicemanager.cpp +++ b/src/library/sysadm-servicemanager.cpp @@ -75,12 +75,12 @@ void ServiceManager::Restart(Service service) void ServiceManager::Enable(Service service) { - General:: setConfFileValue( chroot + "/etc/rc.conf", service.Tag, service.Tag + "=\"YES\"", -1); + General::setConfFileValue( chroot + "/etc/rc.conf", service.Tag, service.Tag + "=\"YES\"", -1); } void ServiceManager::Disable(Service service) { - General:: setConfFileValue( chroot + "/etc/rc.conf", service.Tag, service.Tag + "=\"NO\"", -1); + General::setConfFileValue( chroot + "/etc/rc.conf", service.Tag, service.Tag + "=\"NO\"", -1); } void ServiceManager::loadServices() @@ -103,7 +103,7 @@ void ServiceManager::loadServices() if ( directory.count() == 0 ) return; - for ( int i = 0; i < directory.count(); i++ ) + for (unsigned int i = 0; i < directory.count(); i++ ) { service = Service(); From b54191a87df4159e7d6f3c5a39f6f00bf93534a1 Mon Sep 17 00:00:00 2001 From: Luke De Mouy Date: Mon, 18 Jan 2016 16:43:18 -0700 Subject: [PATCH 5/5] turn off the debug statement about services that are loaded --- src/library/sysadm-servicemanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/sysadm-servicemanager.cpp b/src/library/sysadm-servicemanager.cpp index 7aad73a..0a12acd 100644 --- a/src/library/sysadm-servicemanager.cpp +++ b/src/library/sysadm-servicemanager.cpp @@ -165,7 +165,7 @@ void ServiceManager::loadServices() service.Name = service.Directory; services << service; - qDebug() << "Added Service:" << cDir << service.Directory << service.Name << service.Tag; + //qDebug() << "Added Service:" << cDir << service.Directory << service.Name << service.Tag; } } }