Merge pull request #7 from ldemouy/master

Create ServiceManager Class
This commit is contained in:
ldemouy
2016-01-19 14:44:42 -07:00
7 changed files with 465 additions and 81 deletions

View File

@@ -4,27 +4,29 @@ QT += core network
TARGET=sysadm
target.path = /usr/local/lib
DESTDIR= $$_PRO_FILE_PWD_
#DESTDIR= $$_PRO_FILE_PWD_
TEMPLATE = lib
LANGUAGE = C++
VERSION = 1.0.0
HEADERS += sysadm-global.h \
sysadm-general.h \
sysadm-lifepreserver.h \
sysadm-general.h \
sysadm-lifepreserver.h \
sysadm-network.h \
sysadm-firewall.h \
sysadm-update.h \
sysadm-usermanager.h
sysadm-firewall.h \
sysadm-servicemanager.h\
sysadm-update.h \
sysadm-usermanager.h
SOURCES += NetDevice.cpp \
sysadm-general.cpp \
sysadm-lifepreserver.cpp \
sysadm-network.cpp \
sysadm-firewall.cpp \
sysadm-update.cpp \
sysadm-usermanager.cpp
sysadm-general.cpp \
sysadm-lifepreserver.cpp \
sysadm-network.cpp \
sysadm-firewall.cpp \
sysadm-servicemanager.cpp \
sysadm-update.cpp \
sysadm-usermanager.cpp
include.path=/usr/local/include/
include.files=sysadm-*.h

View File

@@ -10,6 +10,20 @@
#include <algorithm>
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);
}
}

View File

@@ -8,6 +8,7 @@
#define PORTLOOKUP_H
#include <QtCore>
#include <tuple>
#include "sysadm-servicemanager.h"
namespace sysadm
{
struct PortInfo{
@@ -34,6 +35,11 @@ class Firewall
{
public:
///#section: ctors dtors
Firewall();
~Firewall();
///#endsection
///#section: port commands
/**
* @description Returns a structure containing information about the port
@@ -112,11 +118,6 @@ public:
void RestoreDefaults();
///#endsection
///#section: ctors dtors
Firewall();
~Firewall();
///#endsection
private:
void readServicesFile();
QStringList* portStrings;
@@ -125,7 +126,10 @@ private:
void LoadOpenPorts();
void SaveOpenPorts();
ServiceManager serviceManager;
Service firewallService;
};
}
#endif // PORTLOOKUP_H

View File

@@ -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<env.length(); i++){
if(!env[i].contains("=")){ continue; }
if(!env[i].contains("=")){ continue; }
PE.insert(env[i].section("=",0,0), env[i].section("=",1,100));
}
}
@@ -97,6 +97,137 @@ bool General::writeTextFile(QString filepath, QStringList contents, bool overwri
}
return ok;
}
QString General::getConfFileValue(QString fileName, QString Key, int occur )
{
int found = 1;
QFile file( fileName );
if ( ! file.open( QIODevice::ReadOnly ) ) {
return QString();
}
QTextStream stream( &file );
QString line;
while ( !stream.atEnd() )
{
line = stream.readLine(); // line of text excluding '\n'
line = line.section("#",0,0).trimmed(); //remove any comments
if(line.isEmpty()){ continue; }
int index = line.indexOf(Key, 0);
//qDebug() << "Line:" << line << index;
// If the KEY is not found at the start of the line, continue processing
if(index!=0)
continue;
if ( found == occur) {
line.remove(line.indexOf(Key, 0), Key.length());
// Remove any quotes
if ( line.indexOf('"') == 0 )
line = line.remove(0, 1);
if ( line.indexOf('"') != -1 )
line.truncate(line.indexOf('"'));
file.close();
return line;
} else {
found++;
}
}
file.close();
return QString();
}
bool General::setConfFileValue(QString fileName, QString oldKey, QString newKey, int occur )
{
// Lets the dev save a value into a specified config file.
// The occur value tells which occurance of "oldKey" to replace
// If occur is set to -1, it will remove any duplicates of "oldKey"
//copy the original file to create a temporary file for editing
QStringList args;
QString oFileTmp = fileName + ".tmp";
args << fileName << oFileTmp;
General::RunCommand("cp",args);
//Continue evaluating the temporary file
QStringList SavedFile;
int found = 1;
// Load the old file, find the oldKey, remove it and replace with newKey
QFile file( oFileTmp );
if ( ! file.open( QIODevice::ReadOnly ) )
return false;
QTextStream stream( &file );
QString line;
while ( !stream.atEnd() ) {
line = stream.readLine(); // line of text excluding '\n'
// Key is not found at all
if ( line.indexOf(oldKey, 0) == -1 ) {
SavedFile << line ;
continue;
}
// Found the key, but it is commented out, so don't worry about this line
if ( line.trimmed().indexOf("#", 0) == 0 ) {
SavedFile << line ;
continue;
}
// If the KEY is found, and we are just on wrong occurance, save it and continue to search
if ( occur != -1 && found != occur ) {
SavedFile << line ;
found++;
continue;
}
// If the KEY is found in the line and this matches the occurance that must be processed
if ( ! newKey.isEmpty() && found == occur )
{
SavedFile << newKey ;
newKey.clear();
found++;
continue;
}
// If the KEY is found and we just want one occurance of the key
if ( occur == -1 && ! newKey.isEmpty() ) {
SavedFile << newKey ;
newKey.clear();
found++;
continue;
}
}
file.close();
// Didn't find the key? Write it!
if ( ! newKey.isEmpty() )
SavedFile << newKey;
// Save the new file
QFile fileout( oFileTmp );
if ( ! fileout.open( QIODevice::WriteOnly ) )
return false;
QTextStream streamout( &fileout );
for (int i = 0; i < SavedFile.size(); ++i)
streamout << SavedFile.at(i) << "\n";
fileout.close();
//Have the temporary file with new changes overwrite the original file
args.clear();
args << oFileTmp << fileName;
General::RunCommand("mv",args);
return true;
}
//===========================
// SYSCTL ACCESS (might require root)

View File

@@ -13,25 +13,46 @@ namespace sysadm{
class General{
public:
//Non-event-blocking versions of QProcess::execute() or system()
//Note: environment changes should be listed as such: [<variable>=<value>]
// - 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: [<variable>=<value>]
// - 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
#endif

View File

@@ -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<Service> 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 (unsigned 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;
}
}
}
}

View File

@@ -0,0 +1,73 @@
#ifndef SERVICEMANAGER_H
#define SERVICEMANAGER_H
#include <QtCore>
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<Service> 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<Service> services;
void loadServices();
QString chroot;
QString ip;
};
}
#endif // SERVICEMANAGER_H