Remove the old library directory from the sysadm source tree

This commit is contained in:
Ken Moore
2016-02-01 12:33:28 -05:00
parent 1146b14917
commit 6aeb05b825
21 changed files with 0 additions and 3637 deletions

View File

@@ -1,325 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
// Note: This was almost entirely written by Tim McCormick in 2009 for
// the first PC-BSD library, and copied here by Ken Moore in 2015
//===========================================
#include "sysadm-network.h"
#include "sysadm-general.h"
#include "sysadm-global.h"
using namespace sysadm;
//====================
// STATIC LISTING FUNCTION
//====================
QStringList NetDevice::listNetDevices(){
QStringList result;
struct ifaddrs *ifap;
getifaddrs(&ifap);
char ifName[IFNAMSIZ];
//Probe the system for each device (one at a time)
while (ifap != NULL){
strncpy(ifName, ifap->ifa_name, IFNAMSIZ);
if (result.contains(ifName) == 0) result += ifName;
ifap = ifap->ifa_next;
}
//Close the
freeifaddrs(ifap);
return result;
}
//=====================
// CLASS FUNCTIONS
//=====================
//Get the name of the device (taking off any numbers)
QString NetDevice::devName(){
uint pos = name.indexOf(QRegExp("[0-9]+$"));
QString result = name;
result.truncate(pos);
return result;
}
//Return just the number of the device (removing the name)
uint NetDevice::devNum(){
uint pos = name.indexOf(QRegExp("[0-9]+$"));
return name.mid(pos).toInt();
}
//Fetch the IP and return it as a QString
QString NetDevice::ipAsString(){
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, name.toLocal8Bit(), IFNAMSIZ);
int s = socket(PF_INET, SOCK_DGRAM, 0);
ioctl(s, SIOCGIFADDR, &ifr);
struct in_addr in = ((sockaddr_in *) &ifr.ifr_addr)->sin_addr;
return QString(inet_ntoa(in));
}
//Fetch the IPv6 and return it as a QString
QString NetDevice::ipv6AsString(){
//Get the sockaddr for the device
struct sockaddr *sadd = 0;
struct ifaddrs *addrs;
if( 0!=getifaddrs( &addrs ) ){ qDebug() << "Could not get addrs"; return ""; }
while(sadd==0 && addrs!=0){
if( QString(addrs->ifa_name)==name && addrs->ifa_addr->sa_family==AF_INET6){
//Found device (with IPv6 address)
sadd = addrs->ifa_addr;
break;
}else{
//Move to the next device
addrs = addrs->ifa_next;
}
}
free(addrs);
if(sadd==0){ qDebug() << "No socket address found"; return ""; }
//Now get the IPv6 address in string form
char straddr[INET6_ADDRSTRLEN];
int err = getnameinfo(sadd, sadd->sa_len, straddr, sizeof(straddr),NULL, 0, NI_NUMERICHOST);
if(err!=0){
qDebug() << "getnameinfo error:" << gai_strerror(err);
return "";
}else{
return QString(straddr);
}
}
//Fetch the netmask and return it as a QString
QString NetDevice::netmaskAsString(){
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, name.toLocal8Bit(), IFNAMSIZ);
int s = socket(PF_INET, SOCK_DGRAM, 0);
ioctl(s, SIOCGIFNETMASK, &ifr);
struct in_addr in = ((sockaddr_in *) &ifr.ifr_addr)->sin_addr;
return QString(inet_ntoa(in));
}
//Returns the description string for the device
QString NetDevice::desc(){
return General::sysctl("dev." + devName() + "." + QString::number(devNum()) + ".%desc");
}
//Fetch the mac address as a QString
QString NetDevice::macAsString(){
int mib[6];
size_t len;
char *buf;
struct sockaddr_dl *sdl;
char *ptr;
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
mib[3] = AF_LINK;
mib[4] = NET_RT_IFLIST;
mib[5] = if_nametoindex(name.toLocal8Bit());
//First find the size of the return, so we can adjust buf accordingly
sysctl(mib, 6, NULL, &len, NULL, 0);
buf = (char *) malloc(len);
sysctl(mib, 6, buf, &len, NULL, 0);
sdl = (sockaddr_dl *)(((if_msghdr *)buf)+1);
ptr = (char *) LLADDR(sdl);
QString mac;
for (uint i=0; i < 6; i++){
mac += QString::number(*(ptr+i), 16).right(2).rightJustified(2, '0');
if(i<5){ mac += ":"; }
}
return mac;
}
//Get the status of the device (active, associated, etc...)
QString NetDevice::mediaStatusAsString(){
struct ifmediareq ifm;
memset(&ifm, 0, sizeof(struct ifmediareq));
strncpy(ifm.ifm_name, name.toLocal8Bit(), IFNAMSIZ);
int s = socket(AF_INET, SOCK_DGRAM, 0);
ioctl(s, SIOCGIFMEDIA, &ifm);
QString status;
switch (IFM_TYPE(ifm.ifm_active)){
case IFM_FDDI:
case IFM_TOKEN:
if (ifm.ifm_status & IFM_ACTIVE) status = "inserted";
else status = "no ring";
break;
case IFM_IEEE80211:
if (ifm.ifm_status & IFM_ACTIVE) status = "associated";
else status = "no carrier";
break;
default:
if (ifm.ifm_status & IFM_ACTIVE) status = "active";
else status = "no carrier";
}
return status;
}
QString NetDevice::gatewayAsString(){
QString info = General::RunCommand("nice netstat -n -r").split("\n").filter(name).filter("default").join("\n");
if(info.isEmpty()){ return ""; }
//Pull the gateway out of the first line (<default> <gateway>)
info = info.replace("\t"," ").section("\n",0,0).simplified(); //ensure proper parsing
return info.section(" ",1,1);
}
//Check if a device is wireless or not
bool NetDevice::isWireless(){
struct ifmediareq ifm;
memset(&ifm, 0, sizeof(struct ifmediareq));
strncpy(ifm.ifm_name, name.toLocal8Bit(), IFNAMSIZ);
int s = socket(AF_INET, SOCK_DGRAM, 0);
ioctl(s, SIOCGIFMEDIA, &ifm);
return IFM_TYPE(ifm.ifm_active) == IFM_IEEE80211;
}
//Get the parent device (if this is a wireless wlan)
QString NetDevice::getWifiParent(){
if(!name.contains("wlan")){ return ""; }
return General::sysctl("net.wlan." + QString::number(this->devNum()) + ".%parent");
}
//See if the device is setup to use DHCP
bool NetDevice::usesDHCP(){
//The system does not keep track of how the device's address was assigned
// so the closest we can get to this is to see if the system is setup to use
// DHCP on startup (in /etc/rc.conf) (Ken Moore - 6/24/15)
return !Network::readRcConf().filter(name).filter("DHCP").isEmpty();
}
//See if the device is currently in use
bool NetDevice::isUp(){
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
strncpy(ifr.ifr_name, name.toLocal8Bit(), IFNAMSIZ);
int s = socket(AF_INET, SOCK_DGRAM, 0);
ioctl(s, SIOCGIFFLAGS, &ifr);
return (ifr.ifr_flags & IFF_UP) ? 1 : 0;
}
//Determine the number of packets received by the device
long NetDevice::packetsRx(){
int mib[6];
size_t len;
char *buf;
struct if_msghdr *ifm;
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
mib[3] = AF_LINK;
mib[4] = NET_RT_IFLIST;
mib[5] = if_nametoindex(name.toLocal8Bit());
//First find the size of the return, so we can adjust buf accordingly
sysctl(mib, 6, NULL, &len, NULL, 0);
buf = (char *) malloc(len);
sysctl(mib, 6, buf, &len, NULL, 0);
ifm = (if_msghdr *) buf;
return ifm->ifm_data.ifi_ipackets;
}
//Determine the number of packets transmitted by the device
long NetDevice::packetsTx(){
int mib[6];
size_t len;
char *buf;
struct if_msghdr *ifm;
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
mib[3] = AF_LINK;
mib[4] = NET_RT_IFLIST;
mib[5] = if_nametoindex(name.toLocal8Bit());
//First find the size of the return, so we can adjust buf accordingly
sysctl(mib, 6, NULL, &len, NULL, 0);
buf = (char *) malloc(len);
sysctl(mib, 6, buf, &len, NULL, 0);
ifm = (if_msghdr *) buf;
return ifm->ifm_data.ifi_opackets;
}
//Determine the number of errors received
long NetDevice::errorsRx(){
int mib[6];
size_t len;
char *buf;
struct if_msghdr *ifm;
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
mib[3] = AF_LINK;
mib[4] = NET_RT_IFLIST;
mib[5] = if_nametoindex(name.toLocal8Bit());
//First find the size of the return, so we can adjust buf accordingly
sysctl(mib, 6, NULL, &len, NULL, 0);
buf = (char *) malloc(len);
sysctl(mib, 6, buf, &len, NULL, 0);
ifm = (if_msghdr *) buf;
return ifm->ifm_data.ifi_ierrors;
}
//Determine the number of errors transmitted
long NetDevice::errorsTx(){
int mib[6];
size_t len;
char *buf;
struct if_msghdr *ifm;
mib[0] = CTL_NET;
mib[1] = AF_ROUTE;
mib[2] = 0;
mib[3] = AF_LINK;
mib[4] = NET_RT_IFLIST;
mib[5] = if_nametoindex(name.toLocal8Bit());
//First find the size of the return, so we can adjust buf accordingly
sysctl(mib, 6, NULL, &len, NULL, 0);
buf = (char *) malloc(len);
sysctl(mib, 6, buf, &len, NULL, 0);
ifm = (if_msghdr *) buf;
return ifm->ifm_data.ifi_oerrors;
}
//=========================
// SETTING FUNCTIONS (requires root)
//=========================
void NetDevice::setUp(bool up){
//This only sets it up/down for the current session - does not change usage on next boot
General::RunCommand("ifconfig "+name+" "+ (up ? "up": "down") );
}

View File

@@ -1,40 +0,0 @@
CONFIG += c++11
QT += core network
TARGET=sysadm
target.path = /usr/local/lib
#DESTDIR= $$_PRO_FILE_PWD_
TEMPLATE = lib
LANGUAGE = C++
VERSION = 1.0.0
HEADERS += sysadm-global.h \
sysadm-general.h \
sysadm-iocage.h \
sysadm-lifepreserver.h \
sysadm-network.h \
sysadm-firewall.h \
sysadm-servicemanager.h\
sysadm-systeminfo.h\
sysadm-update.h \
sysadm-usermanager.h
SOURCES += NetDevice.cpp \
sysadm-general.cpp \
sysadm-iocage.cpp \
sysadm-lifepreserver.cpp \
sysadm-network.cpp \
sysadm-firewall.cpp \
sysadm-servicemanager.cpp \
sysadm-systeminfo.cpp \
sysadm-update.cpp \
sysadm-usermanager.cpp
include.path=/usr/local/include/
include.files=sysadm-*.h
INSTALLS += target include
QMAKE_LIBDIR = /usr/local/lib/qt5 /usr/local/lib

View File

@@ -1,264 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
#include "sysadm-firewall.h"
#include "sysadm-general.h"
#include <QtCore>
#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
if (port < 0 || port > 65535)
{
PortInfo returnValue;
returnValue.Port = -1;
returnValue.Description = "Port out of bounds";
return returnValue;
}
//Check to see if things have been initialized
if(portStrings == NULL)
readServicesFile();
PortInfo returnValue;
//the port number is valid so set it
returnValue.Port = port;
//make sure that the portType is cased in lower to match the service file and
//then store it in the returnValue, since there isn't a huge point in checking
//the validitiy of the type since /etc/services lists more than udp/tcp
type = type.toLower();
returnValue.Type = type;
//Check to see if it's a recommended port
returnValue.Recommended = false;
for(int recommendedPort : recommendedPorts)
{
if (port == recommendedPort)
{
returnValue.Recommended = true;
}
}
//Check to see if the port number is listed. The format in the file
// is portname/portType. ex.: 22/tcp
QStringList portList = portStrings->filter(QString::number(port) + "/" + type);
if(portList.size() > 0)
{
//grab the first one, there may be duplicates due to colliding ports in the /etc/services file
//but those are listed after the declaration for what the port officially should be used for
QString line = portList.at(0);
//Split across spaces since it's whitespace delimited
QStringList lineList = line.split(' ');
//the keyword associated with the port is the first element in a line
returnValue.Keyword = lineList.at(0);
//if the size of the list is less than 3 then there is no description
if(lineList.size() > 2)
{
QString description = lineList.at(2);
//String the description back together from the end of the list
for(int i = 3; i < lineList.size(); i++)
{
description += " " + lineList.at(i);
}
returnValue.Description = description;
}
}
return returnValue;
}
void Firewall::OpenPort(int port, QString type)
{
openports.append(LookUpPort(port,type));
SaveOpenPorts();
}
void Firewall::OpenPort(QVector<PortInfo> ports)
{
for(PortInfo port : ports)
{
openports.append(port);
}
SaveOpenPorts();
}
void Firewall::ClosePort(int port, QString type)
{
openports.removeAll(LookUpPort(port,type));
SaveOpenPorts();
}
void Firewall::ClosePort(QVector<PortInfo> ports)
{
for(PortInfo port : ports)
{
openports.removeAll(port);
}
SaveOpenPorts();
}
QVector<PortInfo> Firewall::OpenPorts()
{
return openports;
}
bool Firewall::IsRunning()
{
return General::sysctlAsInt("net.inet.ip.fw.enable") == 1;
}
void Firewall::Start()
{
serviceManager.Enable(firewallService);
serviceManager.Start(firewallService);
}
void Firewall::Stop()
{
serviceManager.Enable(firewallService);
serviceManager.Stop(firewallService);
}
void Firewall::Restart()
{
serviceManager.Enable(firewallService);
serviceManager.Restart(firewallService);
}
void Firewall::Enable()
{
serviceManager.Enable(firewallService);
}
void Firewall::Disable()
{
serviceManager.Disable(firewallService);
}
void Firewall::RestoreDefaults()
{
const QString ipfwrules = "/etc/ipfw.rules";
const QString ipfwrulesprevious = ipfwrules + ".previous";
const QString ipfwopenports = "/etc/ipfw.openports";
const QString ipfwopenportsprevious = ipfwopenports + ".previous";
//QFile has a rename command that acts like move, however it won't
//clobber a file if it already exists, so we have to check if there
//already is a .previous and if so delete it before moving the file
//to .previous
//move the files out of the way
if(QFile::exists(ipfwrulesprevious))
QFile::remove(ipfwrulesprevious);
QFile::rename(ipfwrules,ipfwrulesprevious);
if(QFile::exists(ipfwopenportsprevious))
QFile::remove(ipfwopenportsprevious);
QFile::rename(ipfwopenports,ipfwopenportsprevious);
//refresh/restart the rules files
QStringList args;
args << "/usr/local/share/pcbsd/scripts/reset-firewall";
General::RunCommand("sh",args);
LoadOpenPorts();
}
void Firewall::readServicesFile()
{
portStrings = new QStringList();
// /etc/services contains a file that lists the various port numbers
// and their descriptions
QFile* services = new QFile("/etc/services");
services->open(QFile::ReadOnly);
while(!services->atEnd())
{
QString line = services->readLine();
//jump down past the comments
if(line[0] == '#' || line.simplified().isEmpty())
continue;
//remove all of the extraneous whitespace in the line
line = line.simplified();
portStrings->append(line);
}
services->close();
delete services;
}
void Firewall::LoadOpenPorts()
{
openports.clear();
QFile file("/etc/ipfw.openports");
if( file.open(QIODevice::ReadOnly) ){
QTextStream in(&file);
while( !in.atEnd() ){
QString line = in.readLine();
if(line.startsWith("#") || line.simplified().isEmpty()){ continue; }
//File format: "<type> <port>" (nice and simple)
openports.append(LookUpPort(line.section(" ",1,1).toInt(),line.section(" ",0,0)));
}
file.close();
}
//order them in ascending order by port then port type
std::sort(openports.begin(),openports.end());
}
void Firewall::SaveOpenPorts()
{
//Convert to file format
std::sort(openports.begin(), openports.end()); //make sure they are still sorted by port
QStringList fileout;
for(PortInfo port : openports){
fileout.append("#" + port.Keyword + ": " + port.Description + "\n" +
port.Type +" "+QString::number(port.Port));
}
//Always make sure that the file always ends with a newline
if(!fileout.isEmpty()){ fileout << ""; }
//Save to file
QFile file("/etc/ipfw.openports");
if( file.open(QIODevice::WriteOnly | QIODevice::Truncate) ){
QTextStream out(&file);
out << fileout.join("\n");
file.close();
}
//Re-load/start rules (just in case - it is a smart script)
if(IsRunning())
{
QStringList args;
args << "/usr/local/share/pcbsd/scripts/reset-firewall";
General::RunCommand("sh",args);
}
}

View File

@@ -1,135 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
#ifndef PORTLOOKUP_H
#define PORTLOOKUP_H
#include <QtCore>
#include <tuple>
#include "sysadm-servicemanager.h"
namespace sysadm
{
struct PortInfo{
int Port;
QString Type;
QString Keyword;
QString Description;
bool Recommended;
friend bool operator<(const PortInfo lhs, const PortInfo rhs){
return std::tie(lhs.Port,lhs.Type) < std::tie(rhs.Port,rhs.Type);
}
friend bool operator>(const PortInfo lhs, const PortInfo rhs)
{ return rhs < lhs;}
friend bool operator==(const PortInfo lhs, const PortInfo rhs)
{
return lhs.Port == rhs.Port && lhs.Type == rhs.Type;
}
friend bool operator !=(const PortInfo lhs, const PortInfo rhs)
{ return !(lhs == rhs);}
};
const static QVector<int> recommendedPorts = {22, 80};
class Firewall
{
public:
///#section: ctors dtors
Firewall();
~Firewall();
///#endsection
///#section: port commands
/**
* @description Returns a structure containing information about the port
* including its port type, keyword, description, and whether it's a
* recommended port
*
* @param number a port number between 0 and 2^16 - 1
* @param type specify whether the port is tdp, udp, etc
*
* @ErrorConditions Port Number is set to -1 and a description of the error is stored in the description variable
*/
PortInfo LookUpPort(int number, QString type);
/**
* @brief Opens a port
* @param number a port number between 0 and 2^16 -1
* @param type specify whether the port is tdp, udp, etc
*/
void OpenPort(int number, QString type);
/**
* @brief Opens a set of ports
* @param ports a vector of ports to open
*/
void OpenPort(QVector<PortInfo> ports);
/**
* @brief ClosePort closes a port
* @param number a port number between 0 and 2^16 -1
* @param type specify whether the port is tdp, udp, etc
*/
void ClosePort(int number, QString type);
/**
* @brief ClosePort closes a set of ports
* @param ports a vector of ports to close
*/
void ClosePort(QVector<PortInfo> ports);
/**
* @brief finds a list of ports that are open gets the info about them
* and returns them
* @return a QVector of the open ports
*/
QVector<PortInfo> OpenPorts();
///#endsection
///#section: firewall commands
/**
* @brief Checks to see if the firewall is running
* @return true if the firewall is running, false if not
*/
bool IsRunning();
/**
* @brief Starts the firewall
*/
void Start();
/**
* @brief Stops the firewall
*/
void Stop();
/**
* @brief Restarts the firewall
*/
void Restart();
/**
* @brief Enables the firewall in rc.conf, Start() will automatically enable the firewall
*/
void Enable();
/**
* @brief Disables the firewall in rc.conf use after Stop() to completely disable
*/
void Disable();
/**
* @brief Restores the Default Configuration
*/
void RestoreDefaults();
///#endsection
private:
void readServicesFile();
QStringList* portStrings;
QVector<PortInfo> openports;
void LoadOpenPorts();
void SaveOpenPorts();
ServiceManager serviceManager;
Service firewallService;
};
}
#endif // PORTLOOKUP_H

View File

@@ -1,250 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#include "sysadm-general.h"
//PLEASE: Keep the functions in the same order as listed in pcbsd-general.h
#include "sysadm-global.h"
using namespace sysadm;
//=================
// RunCommand() variations
//=================
//Note: environment changes should be listed as such: <variable>=<value>
//Return CLI output (and success/failure)
QString General::RunCommand(bool &success, QString command, QStringList arguments, QString workdir, QStringList env){
QProcess proc;
proc.setProcessChannelMode(QProcess::MergedChannels); //need output
//First setup the process environment as necessary
QProcessEnvironment PE = QProcessEnvironment::systemEnvironment();
if(!env.isEmpty()){
for(int i=0; i<env.length(); i++){
if(!env[i].contains("=")){ continue; }
PE.insert(env[i].section("=",0,0), env[i].section("=",1,100));
}
}
proc.setProcessEnvironment(PE);
//if a working directory is specified, check it and use it
if(!workdir.isEmpty()){
proc.setWorkingDirectory(workdir);
}
//Now run the command (with any optional arguments)
if(arguments.isEmpty()){ proc.start(command); }
else{ proc.start(command, arguments); }
//Wait for the process to finish (but don't block the event loop)
while( !proc.waitForFinished(500) ){ QCoreApplication::processEvents(); }
success = (proc.exitCode()==0); //return success/failure
return QString(proc.readAllStandardOutput());
}
QString General::RunCommand(QString command, QStringList arguments, QString workdir, QStringList env){
//Overloaded simplification for text-only output
bool junk = false;
return General::RunCommand(junk,command,arguments,workdir,env);
}
bool General::RunQuickCommand(QString command, QStringList arguments,QString workdir, QStringList env){
//Overloaded simplification for success-only output
bool success = false;
General::RunCommand(success, command, arguments, workdir, env);
return success;
}
//=================
// TEXT FILE INTERACTION
//=================
QStringList General::readTextFile(QString filepath){
QStringList out;
QFile file(filepath);
if(file.open(QIODevice::Text | QIODevice::ReadOnly)){
QTextStream in(&file);
while(!in.atEnd()){
out << in.readLine();
}
file.close();
}
return out;
}
bool General::writeTextFile(QString filepath, QStringList contents, bool overwrite){
//Simplification for user directory
if(filepath.startsWith("~")){ filepath = filepath.replace(0,1,QDir::homePath()); }
QFile file(filepath);
//Check existance/validity
if(file.exists() && !overwrite){ return false; }
if(!file.exists()){
//See if we need to create the parent directory as well
QDir dir = QFileInfo(filepath).dir(); //get the parent directory
if(!dir.exists()){
if(!dir.mkpath(dir.absolutePath())){ return false; } //could not create parent directory
}
}
//Make sure that something is there to be written
// - to delete a file, use QFile::remove() instead of this function
if(contents.isEmpty()){ contents << "\n"; }
else if(contents.last().isEmpty()){ contents << "\n"; }
//Now save the contents to the file
bool ok = false;
if( file.open(QIODevice::WriteOnly | QIODevice::Truncate) ){
QTextStream out(&file);
out << contents.join("\n");
file.close();
ok = true;
}
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)
//===========================
//Retrieve a text-based sysctl
QString General::sysctl(QString var){
char result[1000];
size_t len = sizeof(result);
sysctlbyname(var.toLocal8Bit(), result, &len, NULL, 0);
result[len] = '\0';
return QString(result);
}
//Retrieve a number-based sysctl
long long General::sysctlAsInt(QString var){
long long result = 0;
size_t len = sizeof(result);
sysctlbyname(var.toLocal8Bit(), &result, &len, NULL, 0);
return result;
}

View File

@@ -1,58 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#ifndef __PCBSD_LIB_UTILS_GENERAL_H
#define __PCBSD_LIB_UTILS_GENERAL_H
#include "sysadm-global.h"
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);
/**
* @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

View File

@@ -1,39 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#ifndef __PCBSD_LIB_UTILS_GENERAL_INCLUDES_H
#define __PCBSD_LIB_UTILS_GENERAL_INCLUDES_H
//Qt Includes
#include <QCoreApplication>
#include <QDateTime>
#include <QDir>
#include <QDebug>
#include <QFile>
#include <QJsonObject>
#include <QJsonValue>
#include <QProcess>
#include <QString>
#include <QStringList>
#include <QTextStream>
//FreeBSD Includes
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <net/if_media.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <netdb.h> //from "man getnetent" (network entries)
#endif

View File

@@ -1,101 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#include "sysadm-general.h"
#include "sysadm-iocage.h"
#include "sysadm-global.h"
using namespace sysadm;
//PLEASE: Keep the functions in the same order as listed in pcbsd-general.h
// Return all the default iocage settings
QJsonObject Iocage::getDefaultSettings() {
QJsonObject retObject;
QStringList output = General::RunCommand("iocage defaults").split("\n");
QJsonObject vals;
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("JID") != -1 )
continue;
if ( output.at(i).isEmpty() )
break;
QString key = output.at(i).simplified().section("=", 0, 0);
QString value = output.at(i).simplified().section("=", 1, 1);
vals.insert(key, value);
}
retObject.insert("defaults", vals);
return retObject;
}
// List the jails on the box
QJsonObject Iocage::getJailSettings(QJsonObject jsin) {
QJsonObject retObject;
QStringList keys = jsin.keys();
if (! keys.contains("jail") ) {
retObject.insert("error", "Missing required keys");
return retObject;
}
// Get the key values
QString jail = jsin.value("jail").toString();
QStringList output = General::RunCommand("iocage get all " + jail).split("\n");
QJsonObject vals;
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("JID") != -1 )
continue;
if ( output.at(i).isEmpty() )
break;
QString key = output.at(i).simplified().section(":", 0, 0);
QString value = output.at(i).simplified().section(":", 1, 1);
vals.insert(key, value);
}
retObject.insert(jail, vals);
return retObject;
}
// List the jails on the box
QJsonObject Iocage::listJails() {
QJsonObject retObject;
QStringList output = General::RunCommand("iocage list").split("\n");
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("JID") != -1 )
continue;
if ( output.at(i).isEmpty() )
break;
QJsonObject jail;
QString line = output.at(i).simplified();
QString uuid = line.section(" ", 1, 1);
jail.insert("jid", line.section(" ", 0, 0));
jail.insert("boot", line.section(" ", 2, 2));
jail.insert("state", line.section(" ", 3, 3));
jail.insert("tag", line.section(" ", 4, 4));
jail.insert("type", line.section(" ", 5, 5));
retObject.insert(uuid, jail);
}
return retObject;
}

View File

@@ -1,24 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#ifndef __PCBSD_LIB_UTILS_IOCAGE_H
#define __PCBSD_LIB_UTILS_IOCAGE_H
#include <QJsonObject>
#include "sysadm-global.h"
namespace sysadm{
class Iocage{
public:
static QJsonObject getDefaultSettings();
static QJsonObject getJailSettings(QJsonObject);
static QJsonObject listJails();
};
} //end of pcbsd namespace
#endif

View File

@@ -1,665 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#include "sysadm-general.h"
#include "sysadm-lifepreserver.h"
#include "sysadm-global.h"
using namespace sysadm;
//PLEASE: Keep the functions in the same order as listed in pcbsd-general.h
// Add a new replication target
QJsonObject LifePreserver::addReplication(QJsonObject jsin) {
QJsonObject retObject;
QString host, user, port, password, ldataset, rdataset, frequency;
QStringList keys = jsin.keys();
if (! keys.contains("host")
|| ! keys.contains("user")
|| ! keys.contains("port")
|| ! keys.contains("password")
|| ! keys.contains("dataset")
|| ! keys.contains("remotedataset")
|| ! keys.contains("frequency") ) {
retObject.insert("error", "Missing required keys");
return retObject;
}
// Get the key values
host = jsin.value("host").toString();
user = jsin.value("user").toString();
port = jsin.value("port").toString();
password = jsin.value("password").toString();
ldataset = jsin.value("dataset").toString();
rdataset = jsin.value("remotedataset").toString();
frequency = jsin.value("frequency").toString();
// Make sure we have the dataset / snap key(s)
if ( host.isEmpty()
|| user.isEmpty()
|| port.isEmpty()
|| password.isEmpty()
|| ldataset.isEmpty()
|| rdataset.isEmpty()
|| frequency.isEmpty() ) {
retObject.insert("error", "Empty dataset or snap keys ");
return retObject;
}
// Run the command with the SSHPASS env variable set
QStringList output;
output = General::RunCommand("lpreserver", QStringList() << "replicate" << "add"
<< host
<< user
<< port
<< ldataset
<< rdataset
<< frequency, "", QStringList() << "SSHPASS=" + password ).split("\n");
// Check for any errors
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("ERROR:") != -1 ) {
retObject.insert("error", output.at(i));
return retObject;
}
}
// Got to the end, return the good json
QJsonObject values;
values.insert("host", host);
values.insert("user", user);
values.insert("port", port);
values.insert("ldataset", ldataset);
values.insert("rdataset", rdataset);
values.insert("frequency", frequency);
return values;
}
// Re-init the LP replication target
QJsonObject LifePreserver::initReplication(QJsonObject jsin) {
QJsonObject retObject;
QString dset, rhost;
QStringList keys = jsin.keys();
if(! keys.contains("dataset") || ! keys.contains("host")){
retObject.insert("error", "Missing dataset or host key");
return retObject;
}
// Check which pool we are looking at
dset = jsin.value("dataset").toString();
rhost = jsin.value("host").toString();
// Make sure we have the pool key
if ( dset.isEmpty() || rhost.isEmpty()) {
retObject.insert("error", "Missing dataset or host key");
return retObject;
}
// TODO - This command can take a LONG TIME. Find a way to queue / background it and return an event
// via websockets later, or block here and return when finished if this is REST
QStringList output = General::RunCommand("lpreserver replicate init " + dset + " " + rhost).split("\n");
// Check for any errors
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("ERROR:") != -1 ) {
retObject.insert("error", output.at(i));
return retObject;
}
}
QJsonObject values;
values.insert("dataset", dset);
values.insert("host", rhost);
return values;
}
// Build list of scheduled cron snapshot jobs
QJsonObject LifePreserver::listCron() {
QJsonObject retObject;
QStringList output = General::RunCommand("lpreserver listcron").split("\n");
QList<QStringList> snaps;
// Parse the output
bool inSnapSection = false;
bool inScrubSection = false;
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("-----------------") != -1 ) {
inSnapSection = true;
continue;
}
if (!inSnapSection)
continue;
if ( output.at(i).indexOf("Pools scheduled for scrub") != -1 ) {
inScrubSection = true;
continue;
}
if ( output.at(i).isEmpty() || output.at(i).indexOf("-----------------") != -1 )
continue;
if ( inSnapSection && ! inScrubSection ) {
// Breakdown this cron job
QString pool = output.at(i).section("-", 0, 0).simplified();
QString freq = output.at(i).section("-", 1, 1).simplified();
QString keep = output.at(i).section("-", 2, 2).simplified().replace("total: ", "");
QJsonObject values;
values.insert("schedule", freq);
values.insert("keep", keep);
retObject.insert(pool, values);
} else if (inSnapSection && inScrubSection ) {
// Add a cron scrub
QString pool = output.at(i).section("-", 0, 0).simplified();
QString freq = output.at(i).section("-", 1, 1).simplified().replace(" ", "");
qDebug() << "Found scrub:" << pool << freq;
QJsonObject values;
QStringList keys = retObject.keys();
if( keys.contains(pool)){
// We have an existing pool object, add it
values = retObject[pool].toObject();
retObject.remove(pool);
values.insert("scrub", freq);
retObject.insert(pool, values);
} else {
// Add a new pool object with the scrub
values.insert("scrub", freq);
retObject.insert(pool, values);
}
}
}
return retObject;
}
// Return a list of replication targets
QJsonObject LifePreserver::listReplication() {
QJsonObject retObject;
QStringList output = General::RunCommand("lpreserver replicate list").split("\n");
QStringList setitems;
QString tmpkey;
QRegExp sep("\\s+");
// Parse the output
bool inSection = false;
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("-----------------") != -1 ) {
inSection = true;
continue;
}
if (!inSection)
continue;
if ( output.at(i).isEmpty() || output.at(i).indexOf("-----------------") != -1 )
break;
// Breakdown the settings
QJsonObject values;
tmpkey = "";
QString dset, rdset, user, host, port, parseline, time;
dset = output.at(i).section(sep, 0, 0).simplified();
parseline = output.at(i).section(sep, 2, 2).simplified();
user = parseline.section("@", 0, 0);
host = parseline.section("@", 1, 1).section("[", 0, 0);
port = parseline.section("@", 1, 1).section("[", 1, 1).section("]", 0, 0);
rdset = parseline.section(":", 1, 1);
time = output.at(i).section(sep, 4, 4).simplified();
values.insert("dataset", dset);
values.insert("user", user);
values.insert("port", port);
values.insert("host", host);
values.insert("rdset", rdset);
values.insert("frequency", time);
retObject.insert(dset + "->" + host, values);
}
return retObject;
}
// Return a list of snapshots on a particular pool / dataset
QJsonObject LifePreserver::listSnap(QJsonObject jsin) {
QJsonObject retObject;
QString pool;
QStringList keys = jsin.keys();
if(! keys.contains("pool")){
retObject.insert("error", "Missing pool key");
return retObject;
}
// Check which pool we are looking at
pool = jsin.value("pool").toString();
// Make sure we have the pool key
if ( pool.isEmpty() ) {
retObject.insert("error", "Missing pool key");
return retObject;
}
QStringList output = General::RunCommand("lpreserver listsnap " + pool ).split("\n");
QList<QStringList> snaps;
QStringList snapitems;
QRegExp sep("\\s+");
// Parse the output
bool inSection = false;
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("-----------------") != -1 ) {
inSection = true;
continue;
}
if (!inSection)
continue;
if ( output.at(i).isEmpty() || output.at(i).indexOf("-----------------") != -1 )
break;
// Breakdown this snapshot
snapitems.clear();
snapitems << output.at(i).section(sep, 0, 0).simplified();
snapitems << output.at(i).section(sep, 1, -1).simplified();
QJsonObject values;
values.insert("comment", snapitems.at(1));
retObject.insert(snapitems.at(0), values);
}
return retObject;
}
// Remove a replication task
QJsonObject LifePreserver::removeReplication(QJsonObject jsin) {
QJsonObject retObject;
QString dataset, host;
QStringList keys = jsin.keys();
if(! keys.contains("dataset") || ! keys.contains("host")){
retObject.insert("error", "Requires dataset and host keys");
return retObject;
}
// Get the dataset / host
dataset = jsin.value("dataset").toString();
host = jsin.value("host").toString();
// Make sure we have the dataset / host key(s)
if ( dataset.isEmpty() || host.isEmpty() ) {
retObject.insert("error", "Empty dataset or host keys ");
return retObject;
}
QStringList output;
output = General::RunCommand("lpreserver replicate remove " + dataset + " " + host).split("\n");
// Check for any errors
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("ERROR:") != -1 ) {
retObject.insert("error", output.at(i));
return retObject;
}
}
// Got to the end, return the good json
QJsonObject values;
values.insert("dataset", dataset);
values.insert("host", host);
return values;
}
// Remove a snapshot
QJsonObject LifePreserver::removeSnapshot(QJsonObject jsin) {
QJsonObject retObject;
QString dataset, snap;
QStringList keys = jsin.keys();
if(! keys.contains("dataset") || ! keys.contains("snap")){
retObject.insert("error", "Requires dataset and snap keys");
return retObject;
}
// Get the dataset / snap
dataset = jsin.value("dataset").toString();
snap = jsin.value("snap").toString();
// Make sure we have the dataset / snap key(s)
if ( dataset.isEmpty() || snap.isEmpty() ) {
retObject.insert("error", "Empty dataset or snap keys ");
return retObject;
}
QStringList output;
output = General::RunCommand("lpreserver rmsnap " + dataset + " " + snap).split("\n");
// Check for any errors
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("ERROR:") != -1 ) {
retObject.insert("error", output.at(i));
return retObject;
}
}
// Got to the end, return the good json
QJsonObject values;
values.insert("dataset", dataset);
values.insert("snap", snap);
return values;
}
// Run a replication task
QJsonObject LifePreserver::runReplication(QJsonObject jsin) {
QJsonObject retObject;
QString dataset, host;
QStringList keys = jsin.keys();
if(! keys.contains("dataset") || ! keys.contains("host")){
retObject.insert("error", "Requires dataset and host keys");
return retObject;
}
// Get the dataset / host
dataset = jsin.value("dataset").toString();
host = jsin.value("host").toString();
// Make sure we have the dataset / host key(s)
if ( dataset.isEmpty() || host.isEmpty() ) {
retObject.insert("error", "Empty dataset or host keys ");
return retObject;
}
QStringList output;
output = General::RunCommand("lpreserver replicate run " + dataset + " " + host).split("\n");
// Check for any errors
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("ERROR:") != -1 ) {
retObject.insert("error", output.at(i));
return retObject;
}
}
// Got to the end, return the good json
QJsonObject values;
values.insert("dataset", dataset);
values.insert("host", host);
return values;
}
// Revert to a snapshot
QJsonObject LifePreserver::revertSnapshot(QJsonObject jsin) {
QJsonObject retObject;
QString dataset, snap;
QStringList keys = jsin.keys();
if(! keys.contains("dataset") || ! keys.contains("snap")){
retObject.insert("error", "Requires dataset and snap keys");
return retObject;
}
// Get the dataset / snap
dataset = jsin.value("dataset").toString();
snap = jsin.value("snap").toString();
// Make sure we have the dataset / snap key(s)
if ( dataset.isEmpty() || snap.isEmpty() ) {
retObject.insert("error", "Empty dataset or snap keys ");
return retObject;
}
QStringList output;
output = General::RunCommand("lpreserver revertsnap " + dataset + " " + snap).split("\n");
// Check for any errors
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("ERROR:") != -1 ) {
retObject.insert("error", output.at(i));
return retObject;
}
}
// Got to the end, return the good json
QJsonObject values;
values.insert("dataset", dataset);
values.insert("snap", snap);
return values;
}
// Save system-wide settings
QJsonObject LifePreserver::saveSettings(QJsonObject jsin) {
QJsonObject retObject;
QString warn, email, emailopts, recursive;
QStringList keys = jsin.keys();
if(! keys.contains("duwarn") && ! keys.contains("email") && ! keys.contains("emailopts") && !keys.contains("recursive")){
retObject.insert("error", "Requires duwarn, email, emailopts or recursive to be set!");
return retObject;
}
QJsonObject values;
QStringList output;
// Get the settings
if ( keys.contains("duwarn") ) {
warn = jsin.value("duwarn").toString();
output = General::RunCommand("lpreserver set duwarn " + warn).split("\n");
// Check for any errors
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("ERROR:") != -1 ) {
retObject.insert("error", output.at(i));
return retObject;
}
}
values.insert("duwarn", warn);
}
if ( keys.contains("email") ) {
email = jsin.value("email").toString();
output = General::RunCommand("lpreserver set email " + email).split("\n");
// Check for any errors
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("ERROR:") != -1 ) {
retObject.insert("error", output.at(i));
return retObject;
}
}
values.insert("email", email);
}
if ( keys.contains("emailopts") ) {
emailopts = jsin.value("emailopts").toString();
output = General::RunCommand("lpreserver set emailopts " + emailopts.toUpper()).split("\n");
// Check for any errors
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("ERROR:") != -1 ) {
retObject.insert("error", output.at(i));
return retObject;
}
}
values.insert("emailopts", emailopts);
}
if ( keys.contains("recursive") ) {
recursive = jsin.value("recursive").toString();
QString recset = "ON";
if ( recursive.toUpper() == "FALSE" )
recset = "OFF";
output = General::RunCommand("lpreserver set recursive " + recset).split("\n");
// Check for any errors
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("ERROR:") != -1 ) {
retObject.insert("error", output.at(i));
return retObject;
}
}
values.insert("recursive", recursive);
}
return values;
}
// Schedule a new scrub routine
QJsonObject LifePreserver::scheduleScrub(QJsonObject jsin) {
QJsonObject retObject;
QString pool, frequency;
QStringList keys = jsin.keys();
if(! keys.contains("pool") || ! keys.contains("frequency")){
retObject.insert("error", "Requires pool and frequency keys");
return retObject;
}
// Check which pool we are looking at
pool = jsin.value("pool").toString();
frequency = jsin.value("frequency").toString();
// Make sure we have the pool / frequency / keep key(s)
if ( pool.isEmpty() || frequency.isEmpty() ) {
retObject.insert("error", "Empty pool or frequency keys ");
return retObject;
}
QStringList output;
if ( frequency == "none" )
output = General::RunCommand("lpreserver cronscrub " + pool + " stop " + frequency).split("\n");
else
output = General::RunCommand("lpreserver cronscrub " + pool + " start " + frequency).split("\n");
// Check for any errors
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("ERROR:") != -1 ) {
retObject.insert("error", output.at(i));
return retObject;
}
}
// Got to the end, return the good json
QJsonObject values;
values.insert("pool", pool);
values.insert("frequency", frequency);
return values;
}
// Schedule a new snapshot routine
QJsonObject LifePreserver::scheduleSnapshot(QJsonObject jsin) {
QJsonObject retObject;
QString pool, frequency, keep;
QStringList keys = jsin.keys();
if(! keys.contains("pool") || ! keys.contains("frequency") || ! keys.contains("keep")){
retObject.insert("error", "Requires pool, frequency and keep keys");
return retObject;
}
// Check which pool we are looking at
pool = jsin.value("pool").toString();
frequency = jsin.value("frequency").toString();
keep = jsin.value("keep").toString();
// Make sure we have the pool / frequency / keep key(s)
if ( pool.isEmpty() || frequency.isEmpty() || keep.isEmpty() ) {
retObject.insert("error", "Empty pool, frequency and keep keys ");
return retObject;
}
QStringList output;
if ( frequency == "none" )
output = General::RunCommand("lpreserver cronsnap " + pool + " stop " ).split("\n");
else
output = General::RunCommand("lpreserver cronsnap " + pool + " start " + frequency + " " + keep ).split("\n");
// Check for any errors
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("ERROR:") != -1 ) {
retObject.insert("error", output.at(i));
return retObject;
}
}
// Got to the end, return the good json
QJsonObject values;
values.insert("pool", pool);
values.insert("frequency", frequency);
values.insert("keep", keep);
return values;
}
// Return a list of settings for life-preserver
QJsonObject LifePreserver::settings() {
QJsonObject retObject;
QStringList output = General::RunCommand("lpreserver get").split("\n");
QStringList setitems;
QString tmpkey;
QRegExp sep("\\s+");
// Parse the output
bool inSection = false;
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("-----------------") != -1 ) {
inSection = true;
continue;
}
if (!inSection)
continue;
if ( output.at(i).isEmpty() || output.at(i).indexOf("-----------------") != -1 )
break;
// Breakdown the setting we got
tmpkey = "";
setitems.clear();
setitems << output.at(i).section(":", 0, 0).simplified();
setitems << output.at(i).section(":", 1, 1).simplified();
if ( setitems.at(0) == "Recursive mode" )
tmpkey = "recursive";
if ( setitems.at(0) == "E-mail notifications" )
tmpkey = "email";
if ( setitems.at(0) == "E-mail addresses" )
tmpkey = "emailaddress";
if ( setitems.at(0) == "Disk space warn at" )
tmpkey = "diskwarn";
// Unknown key we dont support?
if ( tmpkey.isEmpty() )
continue;
retObject.insert(tmpkey, setitems.at(1));
}
return retObject;
}

View File

@@ -1,34 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#ifndef __PCBSD_LIB_UTILS_LIFEPRESERVER_H
#define __PCBSD_LIB_UTILS_LIFEPRESERVER_H
#include <QJsonObject>
#include "sysadm-global.h"
namespace sysadm{
class LifePreserver{
public:
static QJsonObject addReplication(QJsonObject jsin);
static QJsonObject initReplication(QJsonObject jsin);
static QJsonObject listCron();
static QJsonObject listReplication();
static QJsonObject listSnap(QJsonObject jsin);
static QJsonObject removeReplication(QJsonObject jsin);
static QJsonObject removeSnapshot(QJsonObject jsin);
static QJsonObject revertSnapshot(QJsonObject jsin);
static QJsonObject runReplication(QJsonObject jsin);
static QJsonObject saveSettings(QJsonObject jsin);
static QJsonObject scheduleSnapshot(QJsonObject jsin);
static QJsonObject scheduleScrub(QJsonObject jsin);
static QJsonObject settings();
};
} //end of pcbsd namespace
#endif

View File

@@ -1,129 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#include "sysadm-network.h"
//PLEASE: Keep the functions in the same order as listed in pcbsd-network.h
#include "sysadm-general.h"
using namespace sysadm;
//=====================
// NETWORK FUNCTIONS
//=====================
/*QList<NetworkEntry> Network::listNetworkEntries(){
QList<NetworkEntry> out;
netent *entry = getnetent();
while(entry!=0){
//Copy over this data into the output structure
NetworkEntry tmp;
tmp.name = QString::fromLocal8Bit(entry->n_name);
for(int i=0; entry->n_aliases[i] != 0; i++){
tmp.aliases << QString::fromLocal8Bit(entry->n_aliases[i]);
}
tmp.netnum = entry->n_net;
out << tmp;
//Now load the next entry
entry = getnetent();
}
endnetent(); //make sure to close the file since we are finished reading it
return out;
}*/
//---------------------------------------
QStringList Network::readRcConf(){
static QStringList contents = QStringList();
static QDateTime lastread;
if(!lastread.isValid() || contents.isEmpty() || (QFileInfo("/etc/rc.conf").lastModified()> lastread) ){
lastread = QDateTime::currentDateTime();
contents = General::readTextFile("/etc/rc.conf");
}
return contents;
}
//---------------------------------------
NetDevSettings Network::deviceRCSettings(QString dev){
QStringList info = Network::readRcConf().filter(dev);
//Setup the default structure/values
NetDevSettings set;
set.device = dev;
set.wifihost = set.useDHCP = set.wifisecurity = false;
if(info.isEmpty()){ return set; } //no settings
//Now load any info associated with this device
for(int i=0; i<info.length(); i++){
QString var = info[i].section("=",0,0).simplified();
QString val = info[i].section("=",1,100).simplified();
if(val.startsWith("\"")){ val = val.remove(1); }
if(val.endsWith("\"")){ val.chop(1); }
val.prepend(" "); val.append(" "); //just to make additional parsing easier later - each "variable" should have whitespace on both sides
if( (var=="vlans_"+dev) || (var=="wlans_"+dev) ){
set.asDevice = val;
}else if(var==("ifconfig_"+dev)){
QStringList vals = val.split(" ",QString::SkipEmptyParts);
//This is the main settings line: lots of things to look for:
if(!val.contains("DHCP")){
//Look for the static networking values
set.useDHCP = false;
if(val.contains(" netmask ")){ set.staticNetmask = val.section(" netmask ",1,1).section(" ",0,0); }
if(val.contains(" gateway ")){ set.staticGateway = val.section(" gateway ",1,1).section(" ",0,0); }
if(val.contains(" inet ")){ set.staticIPv4 = val.section(" inet ",1,1).section(" ",0,0); }
if(val.contains(" inet6 ")){ set.staticIPv6 = val.section(" inet6 ",1,1).section(" ",0,0); }
/*if(set.staticIPv4.isEmpty() || set.staticIPv6.isEmpty()){
//IPv4/6 address can sometimes not have the "inet(6)" identifier - look through the first few values as well
QStringList vals = val.split(" ",QString::SkipEmptyParts);
for(int v=0; v<vals.length(); v++){
}
}*/
}else{ set.useDHCP=true; } //end of DHCP check
//Wifi Checks
if(vals.contains("WPA")){ set.wifisecurity=true; }
} //end variable checks
} //end loop over rc.conf lines
return set;
}
//---------------------------------------
/*NetDevSettings Network::deviceIfconfigSettings(QString dev){
QString info = General::RunCommand("ifconfig "+dev);
NetDevSettings set;
if(info.isEmpty() || info.contains("interface "+dev+"does not exist")){ return set; } //empty stucture
//Now parse all the available info from ifconfig
info = info.replace("\t"," ").replace("\n"," ").simplified(); //ensure that whitespace is used for parsing
//if(info.contains("inet ")){ set.staticIPv4 = info.section("inet ",1,1).section(" ",0,0); }
//if(info.contains("inet6 ")){ set.staticIPv6 = info.section("inet6 ",1,1).section("%",0,0); }
set.device = dev;
if(info.contains(" ether ")){ set.etherMac = info.section(" ether ",1,1).section(" ",0,0); }
if(info.contains(" ssid ")){ set.wifiSSID = info.section(" ssid ",1,1).section(" ",0,0); }
if(info.contains(" bssid ")){ set.wifiBSSID = info.section(" bssid ",1,1).section(" ",0,0); }
if(info.contains(" country ")){ set.wifiCountry = info.section(" country ",1,1).section(" ",0,0); }
if(info.contains(" channel ")){ set.wifiChannel = info.section(" channel ",1,1).section(" ",0,0); }
return set;
}*/
//=====================
// NETWORK-ROOT FUNCTIONS
//=====================
/*bool NetworkRoot::saveNetworkEntry(NetworkEntry data){
netent *entry = getnetbyname(data.name.toLocal8Bit());
if(entry==0){
//This entry does not exist yet - need to add it
return false; //not implemented yet - add it to /etc/networks?
}else{
//This entry already exists, update it
endnetent(); //Make sure to close the file when finished
return false; //not implemented yet
}
}*/
//--------------------------------------
bool NetworkRoot::saveRCSettings(NetDevSettings){
return false;
}
//--------------------------------------
bool NetworkRoot::setIfconfigSettings(NetDevSettings){
return false;
}

View File

@@ -1,98 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#ifndef __PCBSD_LIB_UTILS_NETWORK_H
#define __PCBSD_LIB_UTILS_NETWORK_H
#include "sysadm-global.h"
namespace sysadm{
//General purpose enumeration of network encryption types
enum NetCrypt {UNKNOWN, NONE, WEP, WPA1, WPA2, WPAE};
//Data structure for network entries ("/etc/networks" entries for example)
struct NetworkEntry{
QString name;
QStringList aliases;
unsigned int netnum;
};
//Data structure for rc.conf settings
struct NetDevSettings{
QString device; //the device these settings correspond with (usually unset if there was an error)
QString asDevice; //associated device (Example: wifi device -> wlan<num> device)
//Wifi settings
QString wifiCountry, wifiSSID, wifiBSSID, wifiChannel;
bool wifihost;
bool wifisecurity; //always recommended for wifi settings - otherwise can't connect to secure access points
//Addressing
bool useDHCP;
QString staticIPv4, staticNetmask, staticIPv6; //assumes DHCP if none are set
QString staticGateway;
};
//General data class for network devices
// Note: Sources in NetDevice.cpp
class NetDevice{
private:
QString name;
public:
NetDevice(QString devName){ name = devName; }
QString device(){ return name; } //full device name (wlan0)
QString devName(); //name only (wlan)
uint devNum(); //number only (0)
QString ipAsString();
QString ipv6AsString();
QString netmaskAsString();
QString desc();
QString macAsString();
//QString mediaTypeAsString();
QString mediaStatusAsString();
QString gatewayAsString();
bool isWireless();
QString getWifiParent();
bool usesDHCP();
bool isUp();
long packetsRx();
long packetsTx();
long errorsRx();
long errorsTx();
//Setting Functions (to make changes - requires root)
void setUp(bool up); //Turn device on/off (temporary - not saved globally)
//Generic listing of devices
static QStringList listNetDevices(); //probe the system for all network devices
};
//General data structure for wifi access points (local or available)
struct NetWifi{
NetCrypt encryption;
QString BSSID, SSID;
};
//The general-purpose class that any user/app can utilitize
class Network{
public:
//static QList<NetworkEntry> listNetworkEntries();
static QStringList readRcConf(); //use this when reading /etc/rc.conf for network stuff - prevents opening the file repeatedly
static NetDevSettings deviceRCSettings(QString dev); //settings in rc.conf (bootup)
//static NetDevSettings deviceIfconfigSettings(QString dev); //settings currently running
};
//The class that requires overarching root permissions (usually for changes to system)
class NetworkRoot{
public:
//static bool saveNetworkEntry(NetworkEntry); //**Not implemented yet**
static bool saveRCSettings(NetDevSettings); //rc.conf settings (bootup)
static bool setIfconfigSettings(NetDevSettings); //ifconfig settings (temporary session)
};
} //end of pcbsd namespace
#endif

View File

@@ -1,172 +0,0 @@
#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

@@ -1,73 +0,0 @@
#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

View File

@@ -1,251 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#include "sysadm-general.h"
#include "sysadm-systeminfo.h"
#include "sysadm-global.h"
using namespace sysadm;
//PLEASE: Keep the functions in the same order as listed in pcbsd-general.h
//Battery Availability
QJsonObject SysInfo::batteryInfo(){
QJsonObject retObject;
bool ok;
int val = General::RunCommand("apm -l").toInt(&ok);
if ( ok && (val >= 0 && val <= 100) ) {
retObject.insert("battery", "true");
} else {
retObject.insert("battery", "false");
return retObject;
}
// We have a battery, return info about it
//Battery Charge Level
QString tmp;
tmp.setNum(val);
retObject.insert("level", tmp);
//Battery Charging State
int state = General::RunCommand("apm -a").toInt(&ok);
if ( ok && state == 0 )
retObject.insert("status", "offline");
else if ( ok && state == 1 )
retObject.insert("status", "charging");
else if ( ok && state == 2 )
retObject.insert("status", "backup");
else
retObject.insert("status", "unknown");
int timeleft = General::RunCommand("apm -t").toInt(&ok);
if ( ok ) {
tmp.setNum(timeleft);
retObject.insert("timeleft", tmp);
} else {
retObject.insert("timeleft", "-1");
}
return retObject;
}
// KPM 1-21-2016
// This needs to be looked at, I'm not 100% sure it is returning correct busy %
// We probably want to supply more info as well, such as user,nice,system,interrupt,idle
QJsonObject SysInfo::cpuPercentage() {
QJsonObject retObject;
QString tmp;
//Calculate the percentage based on the kernel information directly - no extra utilities
QStringList result = General::RunCommand("sysctl -n kern.cp_times").split(" ");
static QStringList last = QStringList();
if(last.isEmpty()){
//need two ticks before it works properly
sleep(1);
last = result;
result = General::RunCommand("sysctl -n kern.cp_times").split(" ");
}
double tot = 0;
double roundtot;
int cpnum = 0;
for(int i=4; i<result.length(); i+=5){
//The values come in blocks of 5 per CPU: [user,nice,system,interrupt,idle]
cpnum++; //the number of CPU's accounted for (to average out at the end)
//qDebug() <<"CPU:" << cpnum;
long sum = 0;
//Adjust/all the data to correspond to diffs from the previous check
for(int j=0; j<5; j++){
QString tmp = result[i-j];
result[i-j] = QString::number(result[i-j].toLong()-last[i-j].toLong());
//need the difference between last run and this one
sum += result[i-j].toLong();
last[i-j] = tmp; //make sure to keep the original value around for the next run
}
QJsonObject vals;
roundtot = 100.0L - ( (100.0L*result[i].toLong())/sum );
tmp.setNum(qRound(roundtot));
vals.insert("busy", tmp );
tmp.setNum(cpnum);
retObject.insert("cpu" + tmp, vals);
//Calculate the percentage used for this CPU (100% - IDLE%)
tot += 100.0L - ( (100.0L*result[i].toLong())/sum ); //remember IDLE is the last of the five values per CPU
}
// Add the total busy %
tmp.setNum(qRound(tot/cpnum));
retObject.insert("busytotal", tmp);
return retObject;
}
QJsonObject SysInfo::cpuTemps() {
// Make sure coretemp is loaded
if ( General::RunCommand("kldstat").indexOf("coretemp") == -1 )
General::RunCommand("kldload coretemp");
QJsonObject retObject;
QStringList temps;
temps = General::RunCommand("sysctl -ai").split("\n").filter(".temperature:");
temps.sort();
for(int i=0; i<temps.length(); i++){
if(temps[i].contains(".acpi.") || temps[i].contains(".cpu")){
retObject.insert(temps[i].section(":", 0, 0).section(".", 1,2).replace(".", "").simplified(), temps[i].section(":", 1,5).simplified());
}else{
//non CPU temperature - skip it
temps.removeAt(i); i--;
}
}
return retObject;
}
// ==== ExternalDevicePaths() ====
QJsonObject SysInfo::externalDevicePaths() {
QJsonObject retObject;
//Returns: QStringList[<type>::::<filesystem>::::<path>]
//Note: <type> = [USB, HDRIVE, DVD, SDCARD, UNKNOWN]
QStringList devs = General::RunCommand("mount").split("\n");
//Now check the output
for(int i=0; i<devs.length(); i++){
if(devs[i].startsWith("/dev/")){
devs[i].replace("\t"," ");
QString type = devs[i].section(" on ",0,0);
type.remove("/dev/");
//Determine the type of hardware device based on the dev node
if(type.startsWith("da")){ type = "USB"; }
else if(type.startsWith("ada")){ type = "HDRIVE"; }
else if(type.startsWith("mmsd")){ type = "SDCARD"; }
else if(type.startsWith("cd")||type.startsWith("acd")){ type="DVD"; }
else{ type = "UNKNOWN"; }
//Now put the device in the proper output format
QString filesystem = devs[i].section("(",1,1).section(",",0,0);
QString path = devs[i].section(" on ",1,50).section("(",0,0).simplified();
QJsonObject vals;
vals.insert("type",type);
vals.insert("filesystem",filesystem);
vals.insert("path",path);
retObject.insert(devs[i].section(" ", 0, 0), vals);
}else{
//invalid device - remove it from the list
devs.removeAt(i);
i--;
}
}
// Return the devices / mounts
return retObject;
}
// Return information about memory
QJsonObject SysInfo::memoryStats() {
QJsonObject retObject;
QString tmp;
long pageSize;
bool ok;
// Get the page size
tmp = General::RunCommand("sysctl -n vm.stats.vm.v_page_size").simplified();
tmp.toLong(&ok);
if ( ok )
pageSize = tmp.toLong();
else
return retObject;
// Get the free size
tmp = General::RunCommand("sysctl -n vm.stats.vm.v_free_count").simplified();
tmp.toLong(&ok);
if ( ok )
retObject.insert("free", tmp.setNum((tmp.toLong() * pageSize) / 1024 / 1024));
// Get the inactive size
tmp = General::RunCommand("sysctl -n vm.stats.vm.v_inactive_count").simplified();
tmp.toLong(&ok);
if ( ok )
retObject.insert("inactive", tmp.setNum((tmp.toLong() * pageSize) / 1024 / 1024));
// Get the cache size
tmp = General::RunCommand("sysctl -n vm.stats.vm.v_cache_count").simplified();
tmp.toLong(&ok);
if ( ok )
retObject.insert("cache", tmp.setNum((tmp.toLong() * pageSize) / 1024 / 1024));
// Get the wired size
tmp = General::RunCommand("sysctl -n vm.stats.vm.v_wire_count").simplified();
tmp.toLong(&ok);
if ( ok )
retObject.insert("wired", tmp.setNum((tmp.toLong() * pageSize) / 1024 / 1024));
// Get the active size
tmp = General::RunCommand("sysctl -n vm.stats.vm.v_active_count").simplified();
tmp.toLong(&ok);
if ( ok )
retObject.insert("active", tmp.setNum((tmp.toLong() * pageSize) / 1024 / 1024));
return retObject;
}
// Return a bunch of various system information
QJsonObject SysInfo::systemInfo() {
QJsonObject retObject;
QString arch = General::RunCommand("uname -m").simplified();
retObject.insert("arch", arch);
QString sysver = General::RunCommand("freebsd-version").simplified();
retObject.insert("systemversion", sysver);
QString kernver = General::RunCommand("uname -r").simplified();
retObject.insert("kernelversion", kernver);
QString kernident = General::RunCommand("uname -i").simplified();
retObject.insert("kernelident", kernident);
QString host = General::RunCommand("hostname").simplified();
retObject.insert("hostname", host);
QString uptime = General::RunCommand("uptime").simplified().section(" ", 1, 4).simplified().replace(",", "");
retObject.insert("uptime", uptime);
QString cputype = General::RunCommand("sysctl -n hw.model").simplified();
retObject.insert("cputype", cputype);
QString cpucores = General::RunCommand("sysctl -n kern.smp.cpus").simplified();
retObject.insert("cpucores", cpucores);
bool ok;
QString tmp;
QString totalmem = General::RunCommand("sysctl -n hw.realmem").simplified();
totalmem.toLong(&ok);
if ( ok ) {
retObject.insert("totalmem", tmp.setNum(totalmem.toLong() / 1024 / 1024));
}
return retObject;
}

View File

@@ -1,27 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#ifndef __PCBSD_LIB_UTILS_SYSINFO_H
#define __PCBSD_LIB_UTILS_SYSINFO_H
#include <QJsonObject>
#include "sysadm-global.h"
namespace sysadm{
class SysInfo{
public:
static QJsonObject batteryInfo();
static QJsonObject cpuPercentage();
static QJsonObject cpuTemps();
static QJsonObject externalDevicePaths();
static QJsonObject memoryStats();
static QJsonObject systemInfo();
};
} //end of pcbsd namespace
#endif

View File

@@ -1,151 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#include <QUuid>
#include "sysadm-general.h"
#include "sysadm-update.h"
#include "sysadm-global.h"
using namespace sysadm;
//PLEASE: Keep the functions in the same order as listed in pcbsd-general.h
// Return a list of updates available
QJsonObject Update::checkUpdates() {
QJsonObject retObject;
QStringList output = General::RunCommand("pc-updatemanager check").split("\n");
QString nameval;
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("Your system is up to date!") != -1 )
{
retObject.insert("status", "noupdates");
return retObject;
}
if ( output.at(i).indexOf("NAME: ") != -1 )
nameval = output.at(i).section(" ", 1, 1);
if ( output.at(i).indexOf("TYPE: SECURITYUPDATE") != -1 ) {
QJsonObject itemvals;
itemvals.insert("name", nameval);
retObject.insert("security", itemvals);
}
if ( output.at(i).indexOf("TYPE: SYSTEMUPDATE") != -1 ) {
QJsonObject itemvals;
itemvals.insert("name", nameval);
if ( output.size() > ( i + 1) )
itemvals.insert("tag", output.at(i+1).section(" ", 1, 1));
if ( output.size() > ( i + 2) )
itemvals.insert("version", output.at(i+2).section(" ", 1, 1));
retObject.insert("majorupgrade", itemvals);
}
if ( output.at(i).indexOf("TYPE: PATCH") != -1 ) {
QJsonObject itemvals;
itemvals.insert("name", nameval);
if ( output.size() > ( i + 1) )
itemvals.insert("tag", output.at(i+1).section(" ", 1, 1));
if ( output.size() > ( i + 2) )
itemvals.insert("details", output.at(i+2).section(" ", 1, 1));
if ( output.size() > ( i + 3) )
itemvals.insert("date", output.at(i+3).section(" ", 1, 1));
if ( output.size() > ( i + 4) )
itemvals.insert("size", output.at(i+4).section(" ", 1, 1));
retObject.insert("patch", itemvals);
}
if ( output.at(i).indexOf("TYPE: PKGUPDATE") != -1 ) {
QJsonObject itemvals;
itemvals.insert("name", nameval);
retObject.insert("packageupdate", itemvals);
}
}
// Update status that we have updates
retObject.insert("status", "updatesavailable");
return retObject;
}
// List available branches we can switch to
QJsonObject Update::listBranches() {
QJsonObject retObject;
QStringList output = General::RunCommand("pc-updatemanager branches").split("\n");
bool inSection = false;
for ( int i = 0; i < output.size(); i++)
{
if ( output.at(i).indexOf("-----------------") != -1 ) {
inSection = true;
continue;
}
if (!inSection)
continue;
if ( output.at(i).isEmpty() )
break;
QString tmp = output.at(i).section(" ", 0, 0);
QString tmp2 = output.at(i).section(" ", 1, 1);
if ( tmp2 == "*" )
retObject.insert(tmp, "active");
else
retObject.insert(tmp, "available");
}
return retObject;
}
// Kickoff an update process
QJsonObject Update::startUpdate(QJsonObject jsin) {
QJsonObject retObject;
QStringList keys = jsin.keys();
if (! keys.contains("target") ) {
retObject.insert("error", "Missing required key 'target'");
return retObject;
}
// Save the target
QString target;
target = jsin.value("target").toString();
QString flags;
if ( target == "chbranch" ) {
if (! keys.contains("branch") ) {
retObject.insert("error", "Missing required key 'branch'");
return retObject;
}
flags = "chbranch " + jsin.value("branch").toString();
} else if ( target == "pkgupdate" ) {
flags = "pkgupdate";
} else if ( target == "fbsdupdate" ) {
flags = "fbsdupdate";
} else if ( target == "fbsdupdatepkgs" ) {
flags = "fbsdupdatepkgs";
} else if ( target == "standalone" ) {
if (! keys.contains("tag") ) {
retObject.insert("error", "Missing required key 'tag'");
return retObject;
}
flags = "install " + jsin.value("tag").toString();
} else {
// Ruh-roh
retObject.insert("error", "Unknown target key: " + target);
return retObject;
}
// Create a unique ID for this queued action
QString ID = QUuid::createUuid().toString();
//DISPATCHER::queueProcess(ID, "pc-updatemanager " + flags).split("\n");
// Return some details to user that the action was queued
retObject.insert("command", "pc-updatemanger " + flags);
retObject.insert("comment", "Task Queued");
retObject.insert("queueid", ID);
return retObject;
}

View File

@@ -1,24 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#ifndef __PCBSD_LIB_UTILS_UPDATER_H
#define __PCBSD_LIB_UTILS_UPDATER_H
#include <QJsonObject>
#include "sysadm-global.h"
namespace sysadm{
class Update{
public:
static QJsonObject checkUpdates();
static QJsonObject listBranches();
static QJsonObject startUpdate(QJsonObject);
};
} //end of pcbsd namespace
#endif

View File

@@ -1,546 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#include "sysadm-usermanager.h"
#include "sysadm-general.h"
using namespace sysadm;
UserManager::UserManager(QString chroot)
{
this->chroot = chroot;
loadUsers();
loadGroups();
loadShells();
}
void UserManager::NewUser(QString fullName, QString userName, QString password, QString home, QString shell, int uid, int gid, bool encrypt)
{
User user;
user.UserName = userName;
user.FullName = fullName;
user.HomeFolder = (home.isEmpty())?"/usr/home/"+userName : home;
user.Shell = shell;
//Add User
qDebug() << "Adding user " << userName;
// Create the zfs dataset associated with the home directory
if ( chroot.isEmpty() )
{
QStringList args;
args.append(user.HomeFolder);
General::RunCommand("/usr/local/share/pcbsd/scripts/mkzfsdir.sh",args);
}
QStringList args;
if ( ! chroot.isEmpty() ) //if chroot is not empty the command starts with chroot instead of pw
args << chroot << "pw"; //and thus we have to add it as an argument
args << "useradd"; //create a user
args << userName; //with this userName
args << "-c"; //sets the comment field
args << "\""+ fullName+"\""; //with the full name of the user
args << "-m"; //create the user's home directory
if(!home.isEmpty())
{
args << "-d"; //set the home directory to
args << home; //this
}
args << "-s"; //set the user's shell
args << shell; //to this
if(gid != -1)
{
args << "-g"; //set the group id to
args << QString::number(gid); //this
}
if(uid != -1)
{
args << "-u"; //set the user id to
args << QString::number(uid); //this
}
args << "-G"; //additionally add the user to
args << "operator"; //the operator's group
if ( ! chroot.isEmpty() ) //if we're operating with a chroot call
General::RunCommand("chroot", args);
else //otherwise
General::RunCommand("pw", args);
ChangeUserPassword(user,password);
//enable flash for the user
if ( chroot.isEmpty() ) { //if we're not in a chroot
qDebug() << "Enabling Flash Plugin for " << userName;
args.clear();
args << userName; //run command as this user
args << "-c"; //with the command
args << "\"flashpluginctl on\""; //turn on flashpluginctl
General::RunCommand("su",args);
}
//if we're going to PersonaCrypt the home directory
if(encrypt)
initPCDevice(user,home,password);
//reloads the groups and users so that the internal model is consistent
loadUsers();
loadGroups();
}
void UserManager::DeleteUser(User user)
{
//Delete User
qDebug() << "Deleting user " << user.UserName;
//remove the dataset associated with the home folder
QStringList args;
args << user.HomeFolder;
General::RunCommand("/usr/local/share/pcbsd/scripts/rmzfsdir.sh",args);
//delete the user and their home directory
args.clear();
if ( ! chroot.isEmpty() ) //if we're in a chroot we need to use chroot before pw
args << chroot << "pw";
args << "userdel"; //delete a user
args << user.UserName; //this user
args << "-r"; //remove the contents of the user's home directory
if ( ! chroot.isEmpty() )
General::RunCommand("chroot", args);
else
General::RunCommand("pw", args);
loadUsers();
loadGroups();
}
const QVector<User> UserManager::GetUsers()
{
return users;
}
const User UserManager::GetUser(int id)
{
for(User user: users)
{
if(user.ID == id)
return user;
}
return User();
}
const User UserManager::GetUser(QString userName)
{
for(User user: users)
{
if(user.UserName == userName)
return user;
}
return User();
}
void UserManager::ChangeUserPassword(User user, QString newPassword)
{
//Don't Change the password of a user with an encrypted Home directory
if( !QFile::exists("/var/db/personacrypt/"+user.UserName+".key") ){ return; }
//Create a temporary file to store the password in
QTemporaryFile nfile("/tmp/.XXXXXXXX");
if ( nfile.open() )
{
QTextStream stream( &nfile );
stream << newPassword;
nfile.close();
}
//set the user password
QStringList args;
args.append(nfile.fileName()); //the temp file holding the password
args.append("|"); //which we're going to pipe to the stdin of
if ( ! chroot.isEmpty() ) //if we're in a chroot
{
args << "chroot"; //a chroot
args << chroot; //located here
}
args << "pw"; //change users
args << "usermod"; //where we're going to modify a user
args << user.UserName;//this user
args << "-h"; //set the user's password
args << "0"; //using stdin
General::RunCommand("cat",args);
//remove the temp file holding the password
nfile.remove();
}
void UserManager::ChangeUserShell(User user, QString shell)
{
if(shells.contains(shell))
{
qDebug("Shell found");
QStringList args;
args << "usermod"; // modify the user
args << "-n"; //specify a user name
args << user.UserName; //for this user
args << "-s"; //set the shell to
args << shell; //this shell
General::RunCommand("pw",args);
}
else
qDebug("Shell not found");
loadUsers();
}
void UserManager::ChangeUserFullName(User user, QString newName)
{
QStringList args;
args << "usermod"; //modify the user
args << user.UserName; //for this user
args << "-c"; //change the gecos field to
args << newName; //this name
General::RunCommand("pw",args);
loadUsers();
}
void UserManager::AddUserToGroup(User user, Group group)
{
QStringList args;
args << "groupmod"; //modify a group
args << "-n"; //modify for a group
args << group.Name;//this group
args << "-m";//by adding a member
args << user.UserName; //this user
General::RunCommand("pw",args);
loadGroups();
}
void UserManager::RemoveUserFromGroup(User user, Group group)
{
QStringList args;
args << "groupmod"; //modify a group
args << "-n"; //modify for a group
args << group.Name; //this group
args << "-d"; //by removing a user
args << user.UserName ; //this user
General::RunCommand("pw", args);
loadGroups();
}
void UserManager::NewGroup(QString name, QStringList members)
{
QStringList args;
qDebug() << "Adding group " << name;
if ( ! chroot.isEmpty() ) //if we're in a chroot need to add chroot before pw
args << chroot << "pw";
args << "groupadd"; //create a new group
args << name; // with this name
args << "-M"; //with this list of users
args << members.join(","); //these guys
if ( ! chroot.isEmpty() ) //if we're in a chroot
General::RunCommand("chroot", args);
else
General::RunCommand("pw", args);
loadGroups();
}
void UserManager::DeleteGroup(Group group)
{
QStringList args;
qDebug() << "Deleting group " << group.Name;
if ( ! chroot.isEmpty() ) //if we're in a chroot need to add chroot before pw
args << chroot << "pw";
args << "groupdel"; //delete a group
args << group.Name; //of this name
if ( ! chroot.isEmpty() ) //if we're in a chroot
General::RunCommand("chroot", args);
else
General::RunCommand("pw", args);
loadGroups();
}
const QVector<Group> UserManager::GetGroups()
{
return groups;
}
const Group UserManager::getGroup(int id)
{
for(Group group : groups)
{
if(group.ID == id)
return group;
}
return Group();
}
const Group UserManager::getGroup(QString name)
{
for(Group group : groups)
{
if(group.Name == name)
return group;
}
return Group();
}
const QStringList UserManager::GetShells()
{
return shells;
}
void UserManager::loadUsers()
{
users.clear();
QStringList userStrings;
QStringList args;
if(!chroot.isEmpty())
{
args << chroot;
args << "pw";
}
args << "usershow";
args << "-a";
if(chroot.isEmpty())
userStrings = General::RunCommand("pw",args).split("\n");
else
userStrings = General::RunCommand("chroot",args).split("\n");
//remove the empty string at the end
userStrings.removeLast();
for(QString line : userStrings)
{
User user;
user.UserName = line.section(":",0,0);
user.ID = line.section(":",2,2).toInt();
user.GroupID = line.section(":",3,3).toInt();
user.HomeFolder = line.section(":",8,8);
user.Shell = line.section(":",9,9);
user.FullName = line.section(":",7,7);
users.append(user);
}
}
void UserManager::loadGroups()
{
groups.clear();
QStringList groupStrings;
QStringList args;
if(!chroot.isEmpty())
{
args << chroot;
args << "pw";
}
args << "groupshow";
args << "-a";
if(chroot.isEmpty())
groupStrings = General::RunCommand("pw",args).split("\n");
else
groupStrings = General::RunCommand("chroot",args).split("\n");
//remove the empty string at the end
groupStrings.removeLast();
for(QString line : groupStrings)
{
Group group;
group.Name = line.section(":",0,0);
group.ID = line.section(":",2,2).toInt();
QString memberString = line.section(":",3,3);
group.Members = memberString.split(",");
groups.append(group);
}
}
void UserManager::loadShells()
{
shells.clear();
QFile shellFile(chroot + "/etc/shells");
if ( shellFile.open(QIODevice::ReadOnly) ) {
QTextStream stream(&shellFile);
stream.setCodec("UTF-8");
QString line;
while ( !stream.atEnd() ) {
line = stream.readLine();
if ( !line.startsWith("#") && !line.isEmpty() ) { //Make sure it isn't a comment or blank
shells.append(line);
}
}
} else {
//Unable to open file error
qWarning("Error! Unable to open /etc/shells");
}
// Add /sbin/nologin as well
shells.append("/sbin/nologin");
}
void UserManager::importPCKey(User user, QString filename){
//Double check that the key does not exist (button should have been hidden earlier if invalid)
if( QFile::exists("/var/db/personacrypt/"+user.UserName+".key") ){ return; }
//if the location is empty cancel
if(filename.isEmpty()){ return; }
//Now run the import command
QStringList args;
args << "import";
args << "\""+filename + "\"";
if( 0 == General::RunCommand("personacrypt",args) ){
//Success
qDebug("The key file was imported successfully.");
}else{
//Failure
qWarning("The key file could not be imported. Please ensure you are using a valid file.");
}
}
void UserManager::exportPCKey(User user, QString filename){
//Double check that the key exists (button should have been hidden earlier if invalid)
if( !QFile::exists("/var/db/personacrypt/"+user.UserName+".key") ){ return; }
if(filename.isEmpty()){ return; } //cancelled
if( !filename.endsWith(".key") ){ filename.append(".key"); }
//Now get/save the key file
QStringList args;
args << "export";
args << "\"" + user.UserName + "\"";
QString key = General::RunCommand("personacrypt",args);
QFile file(filename);
if( !file.open(QIODevice::WriteOnly | QIODevice::Truncate) ){
//Could not open output file
qWarning() <<"Output file could not be opened:\n\n" << filename;
return;
}
QTextStream out(&file);
out << key;
file.close();
qDebug() << "The PersonaCrypt key has been saved successfully: \n\n" << filename;
}
void UserManager::disablePCKey(User user){
//Double check that the key exists (button should have been hidden earlier if invalid)
if( !QFile::exists("/var/db/personacrypt/"+user.UserName+".key") ){ return; }
if( QFile::remove("/var/db/personacrypt/"+user.UserName+".key") ){
//Success
qDebug("The PersonaCrypt user key has been disabled." );
}else{
//Failure (should almost never happen, since this utility runs as root and just needs to delete a file)
qDebug("The PersonaCrypt user key could not be removed. Do you have the proper permissions?" );
}
}
void UserManager::disableAndCopyPCKey(User user, QString password){
QStringList args;
args << "list";
QStringList cusers = General::RunCommand("personacrypt",args).split("\n");
bool available = false;
for(int i=0; i<cusers.length(); i++){
if(cusers[i].section(" on ",0,0) == user.UserName){ available = true; break; } //disk is connected to the system
}
if(!available){
//Warn the user that they need to plug in their USB stick first
qWarning("PersonaCrypt Device Not Found, Please ensure that your PersonaCrypt device is connected to the system and try again.");
return;
}
if(password.isEmpty()){ return; } //cancelled
//Save the password to a temporary file
QTemporaryFile tmpfile("/tmp/.XXXXXXXXXXXXXXXXXXXX");
if( !tmpfile.open() ){ return; } //could not create a temporary file (extremely rare)
QTextStream out(&tmpfile);
out << password;
tmpfile.close();
//Now run the PersonaCrypt command
args.clear();
args << "remove";
args << "\"" + user.UserName + "\"";
args << "\"" + tmpfile.fileName() + "\"";
if(0 == General::RunCommand("personacrypt",args) ){
//Success
qDebug("Success; The data for this user has been merged onto the system and the system key has been disabled");
}else{
//Failure
qWarning("Failure; The PersonaCrypt user data could not be merged onto the system. Invalid Password?" );
}
}
void UserManager::initPCDevice(User user, QString home, QString password)
{
//Double check that the key does not exist (button should have been hidden earlier if invalid)
if( QFile::exists("/var/db/personacrypt/" + user.UserName + ".key") ){ return; }
//Prompt for the user to select a device
QStringList args;
args << "list";
args << "-r";
QStringList devlist = General::RunCommand("personacrypt",args).split("\n");
for(int i=0; i<devlist.length(); i++){
//qDebug() << "Devlist:" << devlist[i];
if(devlist[i].isEmpty() || devlist[i].startsWith("gpart:"))
{
devlist.removeAt(i);
i--;
}
}
if(devlist.isEmpty() || devlist.join("").simplified().isEmpty()){
qWarning("No Devices Found; Please connect a removable device and try again");
return;
}
args.clear();
args << "-h";
args << user.HomeFolder;
bool ok = false;
QString space = General::RunCommand("df -h "+home).split("\n").filter(home).join("");
space.replace("\t"," ");
space = space.section(" ",2,2,QString::SectionSkipEmpty);
if(!ok || home.isEmpty()){ return; }
home = home.section(":",0,0); //only need the raw device
//Save the password to a temporary file (for input to personacrypt)
QTemporaryFile tmpfile("/tmp/.XXXXXXXXXXXXXXX");
if(!tmpfile.open()){
//Error: could not open a temporary file
qWarning("Error; Could not create a temporary file for personacrypt");
return;
}
QTextStream out(&tmpfile);
out << password;
tmpfile.close();
//Now start the process of setting up the device
bool success = false;
args.clear();
args << "init";
args << "\""+user.UserName + "\"";
args << "\"" + tmpfile.fileName() + "\"";
args << home;
QStringList output = General::RunCommand(success,"personacrypt",args).split("\n");
if(success){
//Success
qDebug("Success; The PersonaCrypt device was successfully initialized");
}else{
//Failure - make sure the key was not created before the failure
if(QFile::exists("/var/db/personacrypt/"+user.UserName+".key")){
QFile::remove("/var/db/personacrypt/"+user.UserName+".key");
}
//Now show the error message with the log
qWarning("Failure; The PersonaCrypt device could not be initialized");
}
}

View File

@@ -1,231 +0,0 @@
//===========================================
// PC-BSD source code
// Copyright (c) 2015, PC-BSD Software/iXsystems
// Available under the 3-clause BSD license
// See the LICENSE file for full details
//===========================================
#ifndef USERMANAGER_H
#define USERMANAGER_H
#include<QtCore>
namespace sysadm{
class User
{
public:
User()
{
FullName = "";
UserName = "";
ID = -1;
HomeFolder = "";
Shell = "";
GroupID = -1;
Encrypted = false;
}
QString FullName;
QString UserName;
int ID;
QString HomeFolder;
QString Shell;
int GroupID;
bool Encrypted;
friend bool operator<(const User lhs, const User rhs){
return std::tie(lhs.ID,lhs.UserName) < std::tie(rhs.ID,rhs.UserName);
}
friend bool operator>(const User lhs, const User rhs)
{ return rhs < lhs;}
friend bool operator==(const User lhs, const User rhs)
{
return lhs.ID == rhs.ID && lhs.UserName == rhs.UserName;
}
friend bool operator !=(const User lhs, const User rhs)
{ return !(lhs == rhs);}
};
class Group
{
public:
Group()
{
ID = -1;
Name = "";
Members = QStringList();
}
int ID;
QString Name;
//While the object model would be more "correct" if
//Users were to be a Vector of User pointers, it's
//expensive to wire up and we don't really gain anything
//from doing so
QStringList Members;
};
class UserManager
{
public:
UserManager(QString chroot = "");
//#section user actions
/**
* @brief NewUser Create a new user
* @param fullName The full name of the user
* @param userName The username of the user
* @param password The user's password
* @param home the location of the home directory
* @param shell the user's shell, defaults to /bin/tcsh
* @param uid the user id of the user
* @param gid the group id of the user
* @param encrypt whether to personaCrypt the User's home directory
*/
void NewUser(QString fullName, QString userName, QString password, QString home = "", QString shell = "/bin/tcsh", int uid = -1, int gid = -1, bool encrypt=false);
/**
* @brief DeleteUser Deletes a user
* @param user the user to delete
*/
void DeleteUser(User user);
/**
* @brief GetUsers getter for the users vector
* @return a QVector<Users> that is a copy of the current state
* do not modify it, instead call functions on this class to change
* things and then get another copy of the vector
*/
const QVector<User> GetUsers();
/**
* @brief GetUser get a particular user by their UID
* @param id the UID of the user to get
* @return the user with the UID specified, if not found
* returns a blank User
*/
const User GetUser(int id);
/**
* @brief GetUser get a particular user by their UID
* @param userName the username of the user to get
* @return the user with the user name specified, if not found
* returns a blank User
*/
const User GetUser(QString userName);
/**
* @brief ChangeUserPassword changes the specified user's password
* @param user the user to change the password of
* @param newPassword the new password
*/
void ChangeUserPassword(User user, QString newPassword);
/**
* @brief ChangeUserShell change a specified user's shell
* @param user the user to change the shell for
* @param shell the shell to change to, note that if the shell
* is not in the shells list then it does nothing
*/
void ChangeUserShell(User user, QString shell);
/**
* @brief ChangeUserFullName change the gecos field of a user to a new name
* @param user the user to change the name of
* @param newName the name to change to
*/
void ChangeUserFullName(User user, QString newName);
//#endsection
//#section group actions
/**
* @brief AddUserToGroup add the specified user to the specified group
* @param user the user to add to the group
* @param group the group to add the user to
*/
void AddUserToGroup(User user, Group group);
/**
* @brief RemoveUserFromGroup removes the specified user from the specified group
* @param user the user to remove from the group
* @param group the group to remove the user from
*/
void RemoveUserFromGroup(User user, Group group);
/**
* @brief NewGroup creates a new group
* @param name the name of the new group
* @param Users a list of users to add to the group
*/
void NewGroup(QString name, QStringList Users = QStringList());
/**
* @brief DeleteGroup delete a specified group
* @param group the group to delete
*/
void DeleteGroup(Group group);
/**
* @brief GetGroups get the internal list of groups
* @return a QVector<Group> that is a copy of the current state
* do not modify it, instead call functions on this class to change
* things and then get another copy of the vector
*/
const QVector<Group> GetGroups();
/**
* @brief getGroup get a specified group by their gid
* @param id the gid of the group to get
* @return the group with the specified gid
*/
const Group getGroup(int id);
/**
* @brief getGroup get a specified group by their name
* @param name the name of the group to get
* @return the group with the specified name
*/
const Group getGroup(QString name);
//#endsection
/**
* @brief GetShells the list of shells that are currently installed on the system
* @return a QStringList of shells on the system
*/
const QStringList GetShells();
/**
* @brief initPCDevice Initiate PersonaCrypt for the user
* @param user the user to initiate PersonaCrypt for
* @param home the location of the home directory
* @param password the password of the user
*/
void initPCDevice(User user, QString home, QString password);
/**
* @brief importPCKey Import a PersonaCrypt Key
* @param user the user to import the key for
* @param filename the location of the key
*/
void importPCKey(User user, QString filename);
/**
* @brief exportPCKey Export a PersonaCrypt Key
* @param user the user to export the key for
* @param filename the file to export to
*/
void exportPCKey(User user, QString filename);
/**
* @brief disablePCKey Disables a PersonaCrypt key
* @param user the user to diable PersonaCrypt for
*/
void disablePCKey(User user);
/**
* @brief disableAndCopyPCKey Disable a PersonaCrypt Key
* @param user for this user
* @param password password for the PersonaCrypt
*/
void disableAndCopyPCKey(User user, QString password);
private:
QVector<User> users;
QVector<Group> groups;
QStringList shells;
QString chroot;
//loads the users from /etc/passwd
void loadUsers();
//load the groups from /etc/group
void loadGroups();
//load the shells from /etc/shells
void loadShells();
};
}
#endif // USERMANAGER_H