From 9965bd5c49ff2f22d640d132ac343fdec97b3fb4 Mon Sep 17 00:00:00 2001 From: benmeyer Date: Mon, 30 Sep 2002 14:26:33 +0000 Subject: Initial commit --- diff --git a/noncore/net/networksetup/TODO b/noncore/net/networksetup/TODO new file mode 100644 index 0000000..9a1657a --- a/dev/null +++ b/noncore/net/networksetup/TODO @@ -0,0 +1 @@ +Fix DHCP obtained and expoired info diff --git a/noncore/net/networksetup/addservice.ui b/noncore/net/networksetup/addservice.ui new file mode 100644 index 0000000..929f4fb --- a/dev/null +++ b/noncore/net/networksetup/addservice.ui @@ -0,0 +1,154 @@ + +AddService + + QDialog + + name + AddService + + + geometry + + 0 + 0 + 245 + 268 + + + + caption + Add Network Service + + + + margin + 11 + + + spacing + 6 + + + QPushButton + + name + cancelButton + + + text + Cancel + + + + QPushButton + + name + addButton + + + text + Add + + + + QListView + + + text + Services + + + clickable + true + + + resizeable + true + + + + name + registeredServicesList + + + sizePolicy + + 7 + 3 + + + + minimumSize + + 0 + 75 + + + + + + name + Spacer12 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QLabel + + name + help + + + sizePolicy + + 5 + 4 + + + + text + LAN - TCP/IP +For Local-area network connections through PC_CARD network interfdace cards. + + + alignment + WordBreak|AlignTop|AlignLeft + + + vAlign + + + wordwrap + + + + + + + cancelButton + clicked() + AddService + reject() + + + addButton + clicked() + AddService + accept() + + + diff --git a/noncore/net/networksetup/addserviceimp.cpp b/noncore/net/networksetup/addserviceimp.cpp new file mode 100644 index 0000000..ac79d06 --- a/dev/null +++ b/noncore/net/networksetup/addserviceimp.cpp @@ -0,0 +1,26 @@ +#include "addserviceimp.h" +#include +#include +#include + +void AddServiceImp::addServices(QList list){ + list.setAutoDelete(true); + + for(uint i = 0; i < list.count(); i++){ + QString pluginFileName = ""; + QLibrary *lib = new QLibrary(pluginFileName); + void *functionPointer = lib->resolve("info"); + if( !functionPointer ){ + qDebug(QString("AddServiceImp: File: %1 is not a plugin, but though was.").arg(pluginFileName).latin1()); + delete lib; + break; + } + + // Try to get an info. + QString info = ((QString (*)()) functionPointer)(); + QListViewItem *newItem = new QListViewItem(registeredServicesList, info); + } +} + + +// addserviceimp.cpp diff --git a/noncore/net/networksetup/addserviceimp.h b/noncore/net/networksetup/addserviceimp.h new file mode 100644 index 0000000..7cacb97 --- a/dev/null +++ b/noncore/net/networksetup/addserviceimp.h @@ -0,0 +1,26 @@ +#ifndef ADDSERVICEIMP_H +#define ADDSERVICEIMP_H + +#include "addservice.h" +#include +#include + +class QListViewItem; + +class AddServiceImp : public AddService { + +Q_OBJECT + +public: + AddServiceImp(QWidget *parent=0, const char *name=0, WFlags f=0):AddService(parent, name, f){}; + void addServices(QList list); + +private: + QMap pluginInfo; + +}; + +#endif + +// addserviceimp.h + diff --git a/noncore/net/networksetup/defaultmodule.h b/noncore/net/networksetup/defaultmodule.h new file mode 100644 index 0000000..c7791d5 --- a/dev/null +++ b/noncore/net/networksetup/defaultmodule.h @@ -0,0 +1,26 @@ +#ifndef MODULE_H +#define MODULE_H + +#include "module.h" + +class QWidget; + +class DefaultModule : Module{ + +public: + DefaultModule(){}; + + virtual bool isOwner(Interface *i); + virtual QWidget *configure(); + virtual QWidget *information()}; + virtual QList getInterfaces(); + virtual QMap possibleNewInterfaces(); + virtual Interface *addNewInterface(QString name); + virtual bool remove(Interface* i); + +}; + +#endif + +// module.h + diff --git a/noncore/net/networksetup/interface.cpp b/noncore/net/networksetup/interface.cpp new file mode 100644 index 0000000..b9b09ad --- a/dev/null +++ b/noncore/net/networksetup/interface.cpp @@ -0,0 +1,236 @@ +#include "interface.h" +#include +#include +#include +#include + +#define IFCONFIG "/sbin/ifconfig" +#define HDCP_INFO_DIR "/etc/dhcpc" + +#include +#include + +Interface::Interface(QString name, bool newSatus): status(newSatus), attached(false), interfaceName(name), hardareName("Unknown"), moduleOwner("Default"), macAddress(""), ip("0.0.0.0"), broadcast(""), subnetMask("0.0.0.0"), dhcp(false){ + refresh(); +} + +/** + * Try to start the interface. + * @return bool true if successfull. + */ +bool Interface::start(){ + // check to see if we are already running. + if(status) + return false; + + int ret = system(QString("%1 %2 up").arg(IFCONFIG).arg(interfaceName).latin1()); + if(ret != 0) + return false; + + status = true; + refresh(); + return true; +} + +/** + * Try to stop the interface. + * @return bool true if successfull. + */ +bool Interface::stop(){ + // check to see if we are already stopped. + if(status == false) + return false; + + int ret = system(QString("%1 %2 down").arg(IFCONFIG).arg(interfaceName).latin1()); + if(ret != 0) + return false; + + status = true; + refresh(); + return true; +} +/** + * Try to restart the interface. + * @return bool true if successfull. + */ +bool Interface::restart(){ + return (stop() && start()); +} + +/** + * Try to refresh the information about the interface. + * First call ifconfig, then check the dhcp-info file + * @return bool true if successfull. + */ +bool Interface::refresh(){ + // See if we are up. + if(status == false){ + macAddress = ""; + ip = "0.0.0.0"; + subnetMask = "0.0.0.0"; + broadcast = ""; + dhcp = false; + dhcpServerIp = ""; + leaseObtained = ""; + leaseExpires = ""; + return true; + } + + QString fileName = QString("/tmp/%1_ifconfig_info").arg(interfaceName); + int ret = system(QString("%1 %2 > %3").arg(IFCONFIG).arg(interfaceName).arg(fileName).latin1()); + if(ret != 0){ + qDebug(QString("Interface: Ifconfig return value: %1, is not 0").arg(ret).latin1()); + return false; + } + + QFile file(fileName); + if (!file.open(IO_ReadOnly)){ + qDebug(QString("Interface: Can't open file: %1").arg(fileName).latin1()); + return false; + } + + // Set to the defaults + macAddress = ""; + ip = "0.0.0.0"; + subnetMask = "0.0.0.0"; + broadcast = ""; + + QTextStream stream( &file ); + QString line; + while ( !stream.eof() ) { + line = stream.readLine(); + if(line.contains("HWaddr")){ + int mac = line.find("HWaddr"); + macAddress = line.mid(mac+7, line.length()); + } + if(line.contains("inet addr")){ + int ipl = line.find("inet addr"); + int space = line.find(" ", ipl+10); + ip = line.mid(ipl+10, space-ipl-10); + } + if(line.contains("Mask")){ + int mask = line.find("Mask"); + subnetMask = line.mid(mask+5, line.length()); + } + if(line.contains("Bcast")){ + int mask = line.find("Bcast"); + int space = line.find(" ", mask+6); + broadcast = line.mid(mask+6, space-mask-6); + } + } + file.close(); + QFile::remove(fileName); + + // DHCP TESTING + // reset DHCP info + dhcpServerIp = ""; + leaseObtained = ""; + leaseExpires = ""; + dhcp = false; + + // See if we have + QString dhcpFile(QString(HDCP_INFO_DIR "/dhcpcd-%1.info").arg(interfaceName)); + // If there is no DHCP information then exit now with no errors. + if(!QFile::exists(dhcpFile)){ + return true; + } + + file.setName(dhcpFile); + if (!file.open(IO_ReadOnly)){ + qDebug(QString("Interface: Can't open file: %1").arg(dhcpFile).latin1()); + return false; + } + + // leaseTime and renewalTime and used if pid and deamon exe can be accessed. + int leaseTime = 0; + int renewalTime = 0; + + stream.setDevice( &file ); + while ( !stream.eof() ) { + line = stream.readLine(); + if(line.contains("DHCPSID=")) + dhcpServerIp = line.mid(8, line.length()); + if(line.contains("LEASETIME=")) + leaseTime = line.mid(10, line.length()).toInt(); + if(line.contains("RENEWALTIME=")) + renewalTime = line.mid(12, line.length()).toInt(); + } + file.close(); + //qDebug(QString("Interface: leaseTime: %1").arg(leaseTime).latin1()); + //qDebug(QString("Interface: renewalTime: %1").arg(renewalTime).latin1()); + + // Get the pid of the deamond + dhcpFile = (QString(HDCP_INFO_DIR "/dhcpcd-%1.pid").arg(interfaceName)); + file.setName(dhcpFile); + if (!file.open(IO_ReadOnly)){ + qDebug(QString("Interface: Can't open file: %1").arg(dhcpFile).latin1()); + return false; + } + + int pid = -1; + stream.setDevice( &file ); + while ( !stream.eof() ) { + line = stream.readLine(); + pid = line.toInt(); + } + file.close(); + + if( pid == -1){ + qDebug("Interface: Could not get pid of dhcpc deamon."); + return false; + } + + // Get the start running time of the deamon + fileName = (QString("/proc/%1/stat").arg(pid)); + file.setName(fileName); + stream.setDevice( &file ); + if (!file.open(IO_ReadOnly)){ + qDebug(QString("Interface: Can't open file: %1").arg(fileName).latin1()); + return false; + } + while ( !stream.eof() ) { + line = stream.readLine(); + } + file.close(); + long time = 0; + // Grab the start time + // pid com state ppid pgrp session tty_nr tpgid flags + int r = sscanf(line.latin1(), "%*d %*s %*c %*d %*d %*d %*d %*d %*u " + // minflt cminflt majflt cmajflt utime stime cutime cstime priority + "%*u %*u %*u %*u %*u %*u %*d %*d %*d " + // nice 0 itrealvalue starttime + "%*d %*d %*d %lu", (long*) &time); + time = time/100; + + QDateTime datetime(QDateTime::currentDateTime()); + + // Get the uptime of the computer. + QFile f("/proc/uptime"); + if ( f.open(IO_ReadOnly) ) { // file opened successfully + QTextStream t( &f ); // use a text stream + int sec = 0; + t >> sec; + datetime = datetime.addSecs((-1*sec)); + f.close(); + } + else{ + qDebug("Interface: Can't open /proc/uptime to retrive uptime."); + return false; + } + + datetime = datetime.addSecs(time); + //qDebug(QString("Interface: %1 %2").arg(datetime.toString()).arg(pid).latin1()); + + // Calculate the start and renew times + leaseObtained = datetime.toString(); + + // Calculate the start and renew times + datetime = datetime.addSecs(leaseTime); + leaseExpires = datetime.toString(); + + dhcp = true; + return true; +} + +// interface.cpp + diff --git a/noncore/net/networksetup/interface.h b/noncore/net/networksetup/interface.h new file mode 100644 index 0000000..1ad71eb --- a/dev/null +++ b/noncore/net/networksetup/interface.h @@ -0,0 +1,65 @@ +#ifndef INTERFACE_H +#define INTERFACE_H + +#include + +class Interface { + +public: + Interface(QString name = "unknown", bool status = false); + virtual ~Interface(){}; + + virtual bool getStatus(){ return status; }; + virtual void setStatus(bool newSatus){ status = newSatus; refresh(); }; + + virtual bool isAttached(){ return attached; }; + virtual void setAttached(bool isAttached=false){ attached = isAttached; }; + + virtual QString getInterfaceName(){ return interfaceName; }; + virtual void setInterfaceName(QString name="unknown"){ interfaceName = name; }; + + virtual QString getHardwareName(){ return hardareName; }; + virtual void setHardwareName(QString name="Unknown"){ hardareName = name; }; + + virtual QString getModuleOwner(){ return moduleOwner; }; + virtual void setModuleOwner(QString owner="Default"){ moduleOwner = owner; }; + + // inet information. + QString getMacAddress(){ return macAddress; }; + QString getIp(){ return ip; }; + QString getSubnetMask(){ return subnetMask; }; + QString getBroadcast(){ return broadcast; }; + bool isDhcp(){ return dhcp; }; + QString getDhcpServerIp(){ return dhcpServerIp; }; + QString getLeaseObtained(){ return leaseObtained; }; + QString getLeaseExpires(){ return leaseExpires; }; + + bool refresh(); + bool start(); + bool stop(); + bool restart(); + +private: + // Interface information + bool status; + bool attached; + QString interfaceName; + QString hardareName; + QString moduleOwner; + + // Network information + QString macAddress; + QString ip; + QString broadcast; + QString subnetMask; + bool dhcp; + QString dhcpServerIp; + QString leaseObtained; + QString leaseExpires; + +}; + +#endif + +// interface.h + diff --git a/noncore/net/networksetup/interfaceadvanced.ui b/noncore/net/networksetup/interfaceadvanced.ui new file mode 100644 index 0000000..8ef0b29 --- a/dev/null +++ b/noncore/net/networksetup/interfaceadvanced.ui @@ -0,0 +1,323 @@ + +InterfaceAdvanced + + QWidget + + name + InterfaceAdvanced + + + geometry + + 0 + 0 + 197 + 253 + + + + caption + Advanced Interface Information + + + + margin + 11 + + + spacing + 6 + + + QLabel + + name + TextLabel1 + + + text + MAC Address + + + + QLabel + + name + interfaceName + + + frameShape + Panel + + + frameShadow + Sunken + + + text + eth0 + + + + QLabel + + name + TextLabel3 + + + text + IP Address + + + + QLabel + + name + macAddressLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + 00:00:00:00:00:00 + + + + QLabel + + name + TextLabel7 + + + text + Interface + + + + QLabel + + name + TextLabel9 + + + text + Lease Expires + + + + QLabel + + name + leaseExpiresLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + + + + + QLabel + + name + leaseObtainedLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + + + + + QLabel + + name + TextLabel8 + + + text + Lease Obtained + + + + QLabel + + name + dhcpServerLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + 255.255.255.255 + + + + QLabel + + name + TextLabel6 + + + text + DHCP Server + + + + QLabel + + name + TextLabel4 + + + text + Subnet Mask + + + + QLabel + + name + ipAddressLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + 0.0.0.0 + + + + QLabel + + name + subnetMaskLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + 0.0.0.0 + + + + + name + Spacer2 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QLabel + + name + TextLabel2 + + + text + Broadcast + + + + QLabel + + name + broadcastLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + + Line + + name + Line2 + + + orientation + Horizontal + + + + + + + QWidget +
qwidget.h
+ + 100 + 100 + + 0 + + 7 + 7 + + image0 +
+
+ + + image0 + 789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523250004143a55a6b2e0026630c4f + + +
diff --git a/noncore/net/networksetup/interfaceedit.cpp b/noncore/net/networksetup/interfaceedit.cpp new file mode 100644 index 0000000..25599ef --- a/dev/null +++ b/noncore/net/networksetup/interfaceedit.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** Form implementation generated from reading ui file 'interfaceedit.ui' +** +** Created: Mon Sep 23 12:18:55 2002 +** by: The User Interface Compiler (uic) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ +#include "interfaceedit.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "qwidget.h" +#include +#include +#include +#include + +/* + * Constructs a InterfaceConfiguration which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + */ +InterfaceConfiguration::InterfaceConfiguration( QWidget* parent, const char* name, WFlags fl ) + : QWidget( parent, name, fl ) +{ + if ( !name ) + setName( "InterfaceConfiguration" ); + resize( 177, 306 ); + setCaption( tr( "Interface Configuration" ) ); + InterfaceConfigurationLayout = new QGridLayout( this ); + InterfaceConfigurationLayout->setSpacing( 6 ); + InterfaceConfigurationLayout->setMargin( 11 ); + + profile = new QComboBox( FALSE, this, "profile" ); + profile->insertItem( tr( "All" ) ); + + InterfaceConfigurationLayout->addWidget( profile, 2, 1 ); + + TextLabel1 = new QLabel( this, "TextLabel1" ); + TextLabel1->setText( tr( "Profile:" ) ); + + InterfaceConfigurationLayout->addWidget( TextLabel1, 2, 0 ); + + Line1 = new QFrame( this, "Line1" ); + Line1->setFrameStyle( QFrame::HLine | QFrame::Sunken ); + + InterfaceConfigurationLayout->addMultiCellWidget( Line1, 1, 1, 0, 1 ); + + CheckBox3 = new QCheckBox( this, "CheckBox3" ); + CheckBox3->setText( tr( "Automaticly bring up" ) ); + + InterfaceConfigurationLayout->addMultiCellWidget( CheckBox3, 0, 0, 0, 1 ); + + dhcpCheckBox = new QCheckBox( this, "dhcpCheckBox" ); + dhcpCheckBox->setText( tr( "DHCP" ) ); + + InterfaceConfigurationLayout->addMultiCellWidget( dhcpCheckBox, 3, 3, 0, 1 ); + + TextLabel3_3_2 = new QLabel( this, "TextLabel3_3_2" ); + TextLabel3_3_2->setText( tr( "Lease Hours" ) ); + + InterfaceConfigurationLayout->addWidget( TextLabel3_3_2, 4, 0 ); + + SpinBox1_2 = new QSpinBox( this, "SpinBox1_2" ); + SpinBox1_2->setMaxValue( 336 ); + SpinBox1_2->setMinValue( 1 ); + SpinBox1_2->setValue( 24 ); + + InterfaceConfigurationLayout->addWidget( SpinBox1_2, 4, 1 ); + QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding ); + InterfaceConfigurationLayout->addItem( spacer, 11, 1 ); + + TextLabel4 = new QLabel( this, "TextLabel4" ); + TextLabel4->setText( tr( "IP Address" ) ); + + InterfaceConfigurationLayout->addWidget( TextLabel4, 6, 0 ); + + ipAddressEdit = new QLineEdit( this, "ipAddressEdit" ); + + InterfaceConfigurationLayout->addWidget( ipAddressEdit, 6, 1 ); + + TextLabel5 = new QLabel( this, "TextLabel5" ); + TextLabel5->setText( tr( "Subnet Mask" ) ); + + InterfaceConfigurationLayout->addWidget( TextLabel5, 7, 0 ); + + firstDNSLineEdit = new QLineEdit( this, "firstDNSLineEdit" ); + + InterfaceConfigurationLayout->addWidget( firstDNSLineEdit, 9, 1 ); + + TextLabel3 = new QLabel( this, "TextLabel3" ); + TextLabel3->setText( tr( "Second DNS" ) ); + + InterfaceConfigurationLayout->addWidget( TextLabel3, 10, 0 ); + + subnetMaskEdit = new QLineEdit( this, "subnetMaskEdit" ); + + InterfaceConfigurationLayout->addWidget( subnetMaskEdit, 7, 1 ); + + gatewayEdit = new QLineEdit( this, "gatewayEdit" ); + + InterfaceConfigurationLayout->addWidget( gatewayEdit, 8, 1 ); + + TextLabel7 = new QLabel( this, "TextLabel7" ); + TextLabel7->setText( tr( "Gateway" ) ); + + InterfaceConfigurationLayout->addWidget( TextLabel7, 8, 0 ); + + TextLabel2 = new QLabel( this, "TextLabel2" ); + TextLabel2->setText( tr( "First DNS" ) ); + + InterfaceConfigurationLayout->addWidget( TextLabel2, 9, 0 ); + + secondDNSLineEdit = new QLineEdit( this, "secondDNSLineEdit" ); + + InterfaceConfigurationLayout->addWidget( secondDNSLineEdit, 10, 1 ); + + GroupBox2 = new QGroupBox( this, "GroupBox2" ); + GroupBox2->setTitle( tr( "Static Ip Configuration" ) ); + + InterfaceConfigurationLayout->addMultiCellWidget( GroupBox2, 5, 5, 0, 1 ); + + // signals and slots connections + connect( dhcpCheckBox, SIGNAL( toggled(bool) ), SpinBox1_2, SLOT( setEnabled(bool) ) ); + connect( dhcpCheckBox, SIGNAL( toggled(bool) ), GroupBox2, SLOT( setDisabled(bool) ) ); +} + +/* + * Destroys the object and frees any allocated resources + */ +InterfaceConfiguration::~InterfaceConfiguration() +{ + // no need to delete child widgets, Qt does it all for us +} + diff --git a/noncore/net/networksetup/interfaceedit.h b/noncore/net/networksetup/interfaceedit.h new file mode 100644 index 0000000..a65c030 --- a/dev/null +++ b/noncore/net/networksetup/interfaceedit.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** Form interface generated from reading ui file 'interfaceedit.ui' +** +** Created: Mon Sep 23 12:18:55 2002 +** by: The User Interface Compiler (uic) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ +#ifndef INTERFACECONFIGURATION_H +#define INTERFACECONFIGURATION_H + +#include +#include +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QCheckBox; +class QComboBox; +class QFrame; +class QGroupBox; +class QLabel; +class QLineEdit; +class QSpinBox; + +class InterfaceConfiguration : public QWidget +{ + Q_OBJECT + +public: + InterfaceConfiguration( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~InterfaceConfiguration(); + + QComboBox* profile; + QLabel* TextLabel1; + QFrame* Line1; + QCheckBox* CheckBox3; + QCheckBox* dhcpCheckBox; + QLabel* TextLabel3_3_2; + QSpinBox* SpinBox1_2; + QLabel* TextLabel4; + QLineEdit* ipAddressEdit; + QLabel* TextLabel5; + QLineEdit* firstDNSLineEdit; + QLabel* TextLabel3; + QLineEdit* subnetMaskEdit; + QLineEdit* gatewayEdit; + QLabel* TextLabel7; + QLabel* TextLabel2; + QLineEdit* secondDNSLineEdit; + QGroupBox* GroupBox2; + +protected: + QGridLayout* InterfaceConfigurationLayout; +}; + +#endif // INTERFACECONFIGURATION_H diff --git a/noncore/net/networksetup/interfaceinformation.ui b/noncore/net/networksetup/interfaceinformation.ui new file mode 100644 index 0000000..2a9b3fb --- a/dev/null +++ b/noncore/net/networksetup/interfaceinformation.ui @@ -0,0 +1,317 @@ + +InterfaceInformation + + QWidget + + name + InterfaceInformation + + + geometry + + 0 + 0 + 191 + 241 + + + + caption + Interface Information + + + + margin + 11 + + + spacing + 6 + + + QLayoutWidget + + name + Layout1 + + + + margin + 0 + + + spacing + 6 + + + QPushButton + + name + refreshButton + + + text + Refresh + + + + QPushButton + + name + stopButton + + + text + Stop + + + + QPushButton + + name + restartButton + + + text + Restart + + + + QPushButton + + name + startButton + + + text + Start + + + + + + Line + + name + Line1 + + + orientation + Horizontal + + + + + name + Spacer18 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QLayoutWidget + + name + Layout2 + + + + margin + 0 + + + spacing + 6 + + + + name + Spacer10 + + + orientation + Horizontal + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QPushButton + + name + advancedButton + + + text + View Advanced Information + + + + + + QLabel + + name + TextLabel22 + + + text + IP Address + + + + QLabel + + name + TextLabel23 + + + text + Subnet Mask + + + + QLabel + + name + TextLabel21 + + + text + MAC Address + + + + QLabel + + name + TextLabel24 + + + text + Broadcast + + + + QLabel + + name + subnetMaskLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + 0.0.0.0 + + + + QLabel + + name + macAddressLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + 00:00:00:00:00:00 + + + + QLabel + + name + broadcastLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + + + + + QLabel + + name + ipAddressLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + 0.0.0.0 + + + + + + + QWidget +
qwidget.h
+ + 100 + 100 + + 0 + + 7 + 7 + + image0 +
+
+ + + image0 + 789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758 + + +
diff --git a/noncore/net/networksetup/interfaceinformationimp.cpp b/noncore/net/networksetup/interfaceinformationimp.cpp new file mode 100644 index 0000000..e37e0f8 --- a/dev/null +++ b/noncore/net/networksetup/interfaceinformationimp.cpp @@ -0,0 +1,94 @@ +#include "interfaceinformationimp.h" +#include "interfaceadvanced.h" + +#include +#include +#include + +/** + * Constructor for the InterfaceInformationImp class. This class pretty much + * just display's information about the interface that is passed to it. + */ +InterfaceInformationImp::InterfaceInformationImp(QWidget *parent, const char *name, Interface *i, WFlags f):InterfaceInformation(parent, name, f){ + assert(i); + + interface = i; + updateInterface(); + connect(startButton, SIGNAL(clicked()), this, SLOT(start())); + connect(stopButton, SIGNAL(clicked()), this, SLOT(stop())); + connect(restartButton, SIGNAL(clicked()), this, SLOT(restart())); + connect(refreshButton, SIGNAL(clicked()), this, SLOT(refresh())); + connect(advancedButton, SIGNAL(clicked()), this, SLOT(advanced())); + +} + +void InterfaceInformationImp::updateInterface(){ + if(interface->getStatus()){ + startButton->setEnabled(false); + stopButton->setEnabled(true); + restartButton->setEnabled(true); + } + else{ + startButton->setEnabled(true); + stopButton->setEnabled(false); + restartButton->setEnabled(false); + } + macAddressLabel->setText(interface->getMacAddress()); + ipAddressLabel->setText(interface->getIp()); + subnetMaskLabel->setText(interface->getSubnetMask()); + broadcastLabel->setText(interface->getBroadcast()); +} + +/** + * Start the interface. Update the information if successfull + */ +void InterfaceInformationImp::start(){ + if(interface->start()){ + updateInterface(); + } +} + +/** + * Stop the interface. + */ +void InterfaceInformationImp::stop(){ + if(interface->stop()){ + updateInterface(); + } +} + +/*** + * Tell the interface to refresh its information. + **/ +void InterfaceInformationImp::refresh(){ + if(interface->refresh()) + updateInterface(); +} + +void InterfaceInformationImp::restart(){ + if(interface->restart()){ + updateInterface(); + } +} + + +/** + * Create the advanced widget. Fill it with the current interface's information. + * Display it. + */ +void InterfaceInformationImp::advanced(){ + InterfaceAdvanced *a = new InterfaceAdvanced(0, "InterfaceAdvanced"); + a->interfaceName->setText(interface->getInterfaceName()); + a->macAddressLabel->setText(interface->getMacAddress()); + a->ipAddressLabel->setText(interface->getIp()); + a->subnetMaskLabel->setText(interface->getSubnetMask()); + a->broadcastLabel->setText(interface->getBroadcast()); + a->dhcpServerLabel->setText(interface->getDhcpServerIp()); + a->leaseObtainedLabel->setText(interface->getLeaseObtained()); + a->leaseExpiresLabel->setText(interface->getLeaseExpires()); + a->showMaximized(); + a->show(); +} + +// infoimp.cpp + diff --git a/noncore/net/networksetup/interfaceinformationimp.h b/noncore/net/networksetup/interfaceinformationimp.h new file mode 100644 index 0000000..6fc2384 --- a/dev/null +++ b/noncore/net/networksetup/interfaceinformationimp.h @@ -0,0 +1,31 @@ +#ifndef INTERFACEINFORMATIONIMP_H +#define INTERFACEINFORMATIONIMP_H + +#include "interfaceinformation.h" +#include "interface.h" + +class InterfaceInformationImp : public InterfaceInformation { + +Q_OBJECT + +public: + InterfaceInformationImp(QWidget *parent=0, const char *name=0, Interface *i=0, WFlags f=0); + ~InterfaceInformationImp(){}; + +private slots: + void start(); + void stop(); + void refresh(); + void restart(); + void advanced(); + Interface *interface; + +private: + void updateInterface(); + +}; + +#endif + +// addserviceimp.h + diff --git a/noncore/net/networksetup/interfaces.cpp b/noncore/net/networksetup/interfaces.cpp new file mode 100644 index 0000000..b8a3e7f --- a/dev/null +++ b/noncore/net/networksetup/interfaces.cpp @@ -0,0 +1,513 @@ +#include "interfaces.h" + +#include +#include +#include + +#define AUTO "auto" +#define IFACE "iface" +#define MAPPING "mapping" + +/** + * Constructor. Reads in the interfaces file and then split the file up by + * the \n for interfaces variable. + * @param useInterfacesFile if an interface file other then the default is + * desired to be used it should be passed in. + */ +Interfaces::Interfaces(QString useInterfacesFile){ + acceptedFamily.append(INTERFACES_FAMILY_INET); + acceptedFamily.append(INTERFACES_FAMILY_IPX); + acceptedFamily.append(INTERFACES_FAMILY_INET6); + + interfacesFile = useInterfacesFile; + QFile file(interfacesFile); + if (!file.open(IO_ReadOnly)){ + qDebug(QString("Interfaces: Can't open file: %1 for reading.").arg(interfacesFile).latin1()); + currentIface = interfaces.end(); + currentMapping = interfaces.end(); + return; + } + QTextStream stream( &file ); + QString line; + while ( !stream.eof() ) { + line += stream.readLine(); + line += "\n"; + } + file.close(); + interfaces = QStringList::split("\n", line, true); + + currentIface = interfaces.end(); + currentMapping = interfaces.end(); +} + +/** + * Find out if interface is in an "auto" group or not. + * Report any duplicates such as eth0 being in two differnt auto's + * @param + * @return true is interface is in auto + */ +bool Interfaces::isAuto(QString interface){ + QStringList autoLines = interfaces.grep(QRegExp(AUTO)); + QStringList awi = autoLines.grep(QRegExp(interface)); + if(awi.count() > 1) + qDebug(QString("Interfaces: Found more then auto group with interface: %1.").arg(interface).latin1()); + if(awi.count() < 1) + return false; + return true; +} + +/** + * Attempt to set the auto option for interface to setAuto. + * @param interface the interface to set + * @param setAuto the value to set interface to. + * @return false if already set to setAuto. + * */ +bool Interfaces::setAuto(QString interface, bool setAuto){ + // Don't need to set it if it is already set. + if(isAuto(interface) == setAuto) + return false; + + bool changed = false; + for ( QStringList::Iterator it = interfaces.begin(); it != interfaces.end(); ++it ) { + if((*it).contains(AUTO)){ + //We know that they are not in any group so let add to this auto. + if(setAuto){ + (*it) = (*it) += " " + interface; + // Don't care to have such thins as: auto eth0 lo usb0 + (*it) = (*it).simplifyWhiteSpace(); + changed = true; + break; + } + else{ + if((*it).contains(interface)){ + (*it) = (*it).replace(QRegExp(interface), ""); + // clean up + QString line = (*it).simplifyWhiteSpace(); + line = line.replace(QRegExp(" "),""); + if(line == AUTO) + (*it) = ""; + changed = true; + // Don't break because we want to make sure we remove all cases. + } + } + } + } + if(changed == false){ + if(setAuto == true) + interfaces.append(QString(AUTO" %1").arg(interface)); + else{ + qDebug(QString("Interfaces: Can't set interface %1 auto to false sense it is already false.").arg(interface).latin1()); + } + } + return true; +} + +/** + * Set the current interface to interface. This needs to be done before you + * can call getFamily(), getMethod, and get/setOption(). + * @param interface the name of the interface to set. All whitespace is + * removed from the interface name. + * @return bool true if it is successfull. + */ +bool Interfaces::setInterface(QString interface){ + interface = interface.simplifyWhiteSpace(); + interface = interface.replace(QRegExp(" "), ""); + return setStanza(IFACE, interface, currentIface); +} + +/** + * A quick helper funtion to see if the current interface is set. + * @return bool true if set, false otherwise. + */ +bool Interfaces::isInterfaceSet(){ + return (currentIface != interfaces.end()); +} + +/** + * Add a new interface of with the settings - family and method + * @param interface the name of the interface to set. All whitespace is + * removed from the interface name. + * @param family the family of this interface inet or inet, ipx or inet6 + * Must of one of the families defined in interfaces.h + * @param method for the family. see interfaces man page for family methods. + * @return true if successfull. + */ +bool Interfaces::addInterface(QString interface, QString family, QString method){ + if(acceptedFamily.contains(family)==0) + return false; + interface = interface.simplifyWhiteSpace(); + interface = interface.replace(QRegExp(" "), ""); + interfaces.append(""); + interfaces.append(QString(IFACE " %1 %2 %3").arg(interface).arg(family).arg(method)); + return true; +} + +/** + * Remove the currently selected interface and all of its options. + * @return bool if successfull or not. + */ +bool Interfaces::removeInterface(){ + if(currentIface == interfaces.end()) + return false; + (*currentIface) = ""; + return removeAllInterfaceOptions(); +} + +/** + * Gets the hardware name of the interface that is currently selected. + * @return QString name of the hardware interface (eth0, usb2, wlan1...). + * @param error set to true if any error occurs, false otherwise. + */ +QString Interfaces::getInterfaceName(bool &error){ + if(currentIface == interfaces.end()){ + error = true; + return QString(); + } + QString line = (*currentIface); + line = line.mid(QString(IFACE).length() +1, line.length()); + line = line.simplifyWhiteSpace(); + int findSpace = line.find(" "); + if( findSpace < 0){ + error = true; + return QString(); + } + error = false; + return line.mid(0, findSpace); +} + +/** + * Gets the family name of the interface that is currently selected. + * @return QString name of the family (inet, inet6, ipx). + * @param error set to true if any error occurs, false otherwise. + */ +QString Interfaces::getInterfaceFamily(bool &error){ + QString name = getInterfaceName(error); + if(error){ + error = true; + return QString(); + } + QString line = (*currentIface); + line = line.mid(QString(IFACE).length() +1, line.length()); + line = line.mid(name.length()+1, line.length()); + line = line.simplifyWhiteSpace(); + int findSpace = line.find(" "); + if( findSpace < 0){ + error = true; + return QString(); + } + error = false; + return line.mid(0, findSpace); +} + +/** + * Gets the method of the interface that is currently selected. + * @return QString name of the method such as staic or dhcp. + * See the man page of interfaces for possible methods depending on the family. + * @param error set to true if any error occurs, false otherwise. + */ +QString Interfaces::getInterfaceMethod(bool &error){ + QString name = getInterfaceName(error); + if(error){ + error = true; + return QString(); + } + QString family = getInterfaceFamily(error); + if(error){ + error = true; + return QString(); + } + QString line = (*currentIface); + line = line.mid(QString(IFACE).length()+1, line.length()); + line = line.mid(name.length()+1, line.length()); + line = line.mid(family.length()+1, line.length()); + line = line.simplifyWhiteSpace(); + error = false; + return line; +} + +/** + * Sets the interface name to newName. + * @param newName the new name of the interface. All whitespace is removed. + * @return bool true if successfull. + */ +bool Interfaces::setInterfaceName(QString newName){ + if(currentIface == interfaces.end()) + return false; + newName = newName.simplifyWhiteSpace(); + newName = newName.replace(QRegExp(" "), ""); + bool returnValue = false; + (*currentIface) = QString("iface %1 %2 %3").arg(newName).arg(getInterfaceFamily(returnValue)).arg(getInterfaceMethod(returnValue)); + return !returnValue; +} + +/** + * Sets the interface family to newName. + * @param newName the new name of the interface. Must be one of the families + * defined in the interfaces.h file. + * @return bool true if successfull. + */ +bool Interfaces::setInterfaceFamily(QString newName){ + if(currentIface == interfaces.end()) + return false; + if(acceptedFamily.contains(newName)==0) + return false; + bool returnValue = false; + (*currentIface) = QString("iface %1 %2 %3").arg(getInterfaceName(returnValue)).arg(newName).arg(getInterfaceMethod(returnValue)); + return !returnValue; +} + +/** + * Sets the interface method to newName + * @param newName the new name of the interface + * @return bool true if successfull. + */ +bool Interfaces::setInterfaceMethod(QString newName){ + if(currentIface == interfaces.end()) + return false; + bool returnValue = false; + (*currentIface) = QString("iface %1 %2 %3").arg(getInterfaceName(returnValue)).arg(getInterfaceFamily(returnValue)).arg(newName); + return !returnValue; +} + +/** + * Get a value for an option in the currently selected interface. For example + * calling getInterfaceOption("address") on the following stanza would + * return 192.168.1.1. + * iface eth0 static + * address 192.168.1.1 + * @param option the options to get the value. + * @param error set to true if any error occurs, false otherwise. + * @return QString the options value. QString::null if error == true + */ +QString Interfaces::getInterfaceOption(QString option, bool &error){ + return getOption(currentIface, option, error); +} + +/** + * Set a value for an option in the currently selected interface. If option + * doesn't exist then it is added along with the value. If value is set to an + * empty string then option is removed. + * @param option the options to set the value. + * @param value the value that option should be set to. + * @param error set to true if any error occurs, false otherwise. + * @return QString the options value. QString::null if error == true + */ +bool Interfaces::setInterfaceOption(QString option, QString value){ + return setOption(currentIface, option, value); +} + +/** + * Removes all of the options from the currently selected interface. + * @return bool error if if successfull + */ +bool Interfaces::removeAllInterfaceOptions(){ + return removeAllOptions(currentIface); +} + +/** + * Set the current map to interface's map. This needs to be done before you + * can call addMapping(), set/getMap(), and get/setScript(). + * @param interface the name of the interface to set. All whitespace is + * removed from the interface name. + * @return bool true if it is successfull. + */ +bool Interfaces::setMapping(QString interface){ + interface = interface.simplifyWhiteSpace(); + interface = interface.replace(QRegExp(" "), ""); + return setStanza(MAPPING, interface, currentMapping); +} + +/** + * Adds a new Mapping to the interfaces file with interfaces. + * @param interface the name(s) of the interfaces to set to this mapping + */ +void Interfaces::addMapping(QString interfaces){ + interfaces.append(""); + interfaces.append(QString(MAPPING " %1").arg(interfaces)); +} + +/** + * Set a map option within a mapping. + * @param map map to use + * @param value value to go with map + * @return bool true if it is successfull. + */ +bool Interfaces::setMap(QString map, QString value){ + return setOption(currentMapping, map, value); +} + +/** + * Get a map value within a mapping. + * @param map map to get value of + * @param bool true if it is successfull. + * @return value that goes to the map + */ +QString Interfaces::getMap(QString map, bool &error){ + return getOption(currentMapping, map, error); +} + +/** + * Sets a script value of the current mapping to argument. + * @param argument the script name. + * @return true if successfull. + */ +bool Interfaces::setScript(QString argument){ + return setOption(currentMapping, "script", argument); +} + +/** + * @param error true if could not retrieve the current script argument. + * @return QString the argument of the script for the current mapping. + */ +QString Interfaces::getScript(bool &error){ + return getOption(currentMapping, "script", error); +} + +/** + * Helper function used to parse through the QStringList and put pointers in + * the correct place. + * @param stanza The stanza (auto, iface, mapping) to look for. + * @param option string that must be in the stanza's main line. + * @param interator interator to place at location of stanza if successfull. + * @return bool true if the stanza is found. + */ +bool Interfaces::setStanza(QString stanza, QString option, QStringList::Iterator &iterator){ + bool found = false; + iterator = interfaces.end(); + for ( QStringList::Iterator it = interfaces.begin(); it != interfaces.end(); ++it ) { + QString line = (*it).simplifyWhiteSpace(); + if(line.contains(stanza) && line.contains(option)){ + if(found == true){ + qDebug(QString("Interfaces: Found multiple stanza's for search: %1 %2").arg(stanza).arg(option).latin1()); + } + found = true; + iterator = it; + } + } + return !found; +} + +/** + * Sets a value of an option in a stanza + * @param start the start of the stanza + * @param option the option to use when setting value. + * @return bool true if successfull, false otherwise. + */ +bool Interfaces::setOption(QStringList::Iterator start, QString option, QString value){ + if(start == interfaces.end()) + return false; + + bool found = false; + for ( QStringList::Iterator it = start; it != interfaces.end(); ++it ) { + if(((*it).contains(IFACE) || (*it).contains(MAPPING) || (*it).contains(AUTO)) && it != start){ + if(!found && value != ""){ + // Got to the end of the stanza without finding it, so append it. + interfaces.insert(--it, QString("\t%1 %2").arg(option).arg(value)); + } + break; + } + if((*it).contains(option)){ + // Found it in stanza so replace it. + if(found) + qDebug(QString("Interfaces: Set Options found more then one value for option: %1 in stanza: %1").arg(option).arg((*start)).latin1()); + found = true; + if(value == "") + (*it) = ""; + else + (*it) = QString("\t%1 %2").arg(option).arg(value); + } + } + return true; +} + +/** + * Removes all options in a stanza + * @param start the start of the stanza + * @return bool true if successfull, false otherwise. + */ +bool Interfaces::removeAllOptions(QStringList::Iterator start){ + if(start == interfaces.end()) + return false; + + QStringList::Iterator it = start; + it = ++it; + for (it; it != interfaces.end(); ++it ) { + if(((*it).contains(IFACE) || (*it).contains(MAPPING) || (*it).contains(AUTO)) && it != start){ + break; + } + it = interfaces.remove(it); + it = --it; + } + // Leave a space between this interface and the next. + interfaces.insert(it, QString("")); + return true; +} + +/** + * Gets a value of an option in a stanza + * @param start the start of the stanza + * @param option the option to use when getting the value. + * @param bool true if errors false otherwise. + * @return QString the value of option QString::null() if error == true. + */ +QString Interfaces::getOption(QStringList::Iterator start, QString option, bool &error){ + if(start == interfaces.end()){ + error = false; + return QString(); + } + + QString value; + bool found = false; + for ( QStringList::Iterator it = start; it != interfaces.end(); ++it ) { + if(((*it).contains(IFACE) || (*it).contains(MAPPING) || (*it).contains(AUTO)) && it != start){ + break; + } + if((*it).contains(option)){ + if(found) + qDebug(QString("Interfaces: Get Options found more then one value: %1 for option: %2 in stanza %3").arg((*it)).arg(option).arg((*start)).latin1()); + found = true; + QString line = (*it).simplifyWhiteSpace(); + int space = line.find(" ", option.length()); + if(space != -1) + value = line.mid(space+1, line.length()); + else + qDebug(QString("Interfaces: Option %1 with no value").arg(option).latin1()); + } + } + error = !found; + return value; +} + +/** + * Write out the interfaces file to the file passed into the constructor. + * Removes any excess blank lines over 1 line long. + * @return bool true if successfull, false if not. + */ +bool Interfaces::write(){ + QFile::remove(interfacesFile); + QFile file(interfacesFile); + + if (!file.open(IO_ReadWrite)){ + qDebug(QString("Interfaces: Can't open file: %1 for writing.").arg(interfacesFile).latin1()); + return false; + } + QTextStream stream( &file ); + int whiteSpaceCount = 0; + for ( QStringList::Iterator it = interfaces.begin(); it != interfaces.end(); ++it ) { + QString line = (*it).simplifyWhiteSpace(); + line = line.replace(QRegExp(" "),""); + if(line.length() == 0) + whiteSpaceCount++; + else + whiteSpaceCount = 0; + if(whiteSpaceCount < 2){ + qDebug((*it).latin1()); + stream << (*it) << '\n'; + } + } + file.close(); + return true; +} + +// interfaces.cpp + diff --git a/noncore/net/networksetup/interfaces.h b/noncore/net/networksetup/interfaces.h new file mode 100644 index 0000000..2cc9689 --- a/dev/null +++ b/noncore/net/networksetup/interfaces.h @@ -0,0 +1,70 @@ +#ifndef INTERFACES_H +#define INTERFACES_H + +#include +#include + +#define INTERFACES_LOOPBACK "loopback" + +#define INTERFACES_FAMILY_INET "inet" +#define INTERFACES_FAMILY_IPX "ipx" +#define INTERFACES_FAMILY_INET6 "inet6" + +#define INTERFACES_METHOD_DHCP "dhcp" +#define INTERFACES_METHOD_STATIC "static" +#define INTERFACES_METHOD_PPP "ppp" + +/** + * This class provides a clean frontend for parsing the network interfaces file. + * It provides helper functions to minipulate the options within the file. + * See the interfaces man page for the syntax rules. + */ +class Interfaces { + +public: + Interfaces(QString useInterfacesFile = "/etc/network/interfaces"); + + bool isAuto(QString interface); + bool setAuto(QString interface, bool setAuto); + + bool removeInterface(); + bool addInterface(QString interface, QString family, QString method); + bool setInterface(QString interface); + bool isInterfaceSet(); + QString getInterfaceName(bool &error); + bool setInterfaceName(QString newName); + QString getInterfaceFamily(bool &error); + bool setInterfaceFamily(QString newName); + QString getInterfaceMethod(bool &error); + bool setInterfaceMethod(QString newName); + QString getInterfaceOption(QString option, bool &error); + bool setInterfaceOption(QString option, QString value); + bool removeAllInterfaceOptions(); + + bool setMapping(QString interface); + void addMapping(QString interfaces); + bool setMap(QString map, QString value); + QString getMap(QString map, bool &error); + bool setScript(QString); + QString getScript(bool &error); + + bool write(); + +private: + bool setStanza(QString stanza, QString option,QStringList::Iterator &iterator); + bool setOption(QStringList::Iterator start, QString option, QString value); + QString getOption(QStringList::Iterator start, QString option, bool &error); + bool removeAllOptions(QStringList::Iterator start); + + QString interfacesFile; + QStringList interfaces; + QStringList::Iterator currentIface; + QStringList::Iterator currentMapping; + + QStringList acceptedFamily; +}; + +#endif + +// interfaces + diff --git a/noncore/net/networksetup/interfacesetup.ui b/noncore/net/networksetup/interfacesetup.ui new file mode 100644 index 0000000..698422c --- a/dev/null +++ b/noncore/net/networksetup/interfacesetup.ui @@ -0,0 +1,274 @@ + +InterfaceSetup + + QDialog + + name + InterfaceSetup + + + geometry + + 0 + 0 + 193 + 310 + + + + caption + Interface Configuration + + + + margin + 11 + + + spacing + 6 + + + Line + + name + Line1 + + + orientation + Horizontal + + + + QLabel + + name + TextLabel4 + + + text + IP Address + + + + QCheckBox + + name + autoStart + + + text + Automaticly bring up + + + + QComboBox + + + text + All + + + + name + profileCombo + + + + QGroupBox + + name + staticGroupBox + + + enabled + false + + + title + Static Ip Configuration + + + + QLineEdit + + name + ipAddressEdit + + + + QLabel + + name + leaseHoursLabel + + + text + Requested Lease + + + + QCheckBox + + name + dhcpCheckBox + + + text + DHCP + + + checked + true + + + + QLabel + + name + TextLabel5 + + + text + Subnet Mask + + + + QLabel + + name + TextLabel1 + + + text + Profile: + + + + QSpinBox + + name + leaseTime + + + suffix + hours + + + maxValue + 336 + + + minValue + 1 + + + value + 24 + + + + + name + Spacer9 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QLineEdit + + name + secondDNSLineEdit + + + + QLabel + + name + TextLabel3 + + + text + Second DNS + + + + QLabel + + name + TextLabel2 + + + text + First DNS + + + + QLineEdit + + name + firstDNSLineEdit + + + + QLabel + + name + TextLabel1_2 + + + text + Gateway + + + + QLineEdit + + name + subnetMaskEdit + + + + QLineEdit + + name + gatewayEdit + + + + + + + dhcpCheckBox + toggled(bool) + leaseHoursLabel + setEnabled(bool) + + + dhcpCheckBox + toggled(bool) + leaseTime + setEnabled(bool) + + + dhcpCheckBox + toggled(bool) + staticGroupBox + setDisabled(bool) + + + diff --git a/noncore/net/networksetup/interfacesetupimp.cpp b/noncore/net/networksetup/interfacesetupimp.cpp new file mode 100644 index 0000000..6a8449d --- a/dev/null +++ b/noncore/net/networksetup/interfacesetupimp.cpp @@ -0,0 +1,147 @@ +#include "interfacesetupimp.h" +#include "interface.h" +#include "interfaces.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#define INTERFACE_FILE "/home/ben/interfaces" +#define DNSSCRIPT "interfacednsscript" + +/** + * Constuctor. Set up the connection and load the first profile. + */ +InterfaceSetupImp::InterfaceSetupImp(QWidget* parent, const char* name, Interface *i, bool modal, WFlags fl) : InterfaceSetup(parent, name, modal, fl){ + assert(i); + interface = i; + interfaces = new Interfaces(INTERFACE_FILE); + changeProfile(profileCombo->currentText()); + bool error = false; + if(interfaces->getInterfaceMethod(error) == INTERFACES_LOOPBACK){ + staticGroupBox->hide(); + dhcpCheckBox->hide(); + leaseTime->hide(); + leaseHoursLabel->hide(); + } + connect(profileCombo, SIGNAL(highlighted(const QString &)), this, SLOT(changeProfile(const QString &))); +} + +/** + * Save the current settings, then write out the interfaces file and close. + */ +void InterfaceSetupImp::accept(){ + if(!saveSettings()) + return; + interfaces->write(); + close(true); +} + +/** + * Save the settings for the current Interface. + * @return bool true if successfull, false otherwise + */ +bool InterfaceSetupImp::saveSettings(){ + // eh can't really do anything about it other then return. :-D + if(!interfaces->isInterfaceSet()) + return true; + + bool error = false; + // Loopback case + if(interfaces->getInterfaceMethod(error) == INTERFACES_LOOPBACK){ + interfaces->setAuto(interface->getInterfaceName(), autoStart->isChecked()); + return true; + } + + if(!dhcpCheckBox->isChecked() && (ipAddressEdit->text().isEmpty() || subnetMaskEdit->text().isEmpty() || firstDNSLineEdit->text().isEmpty())){ + QMessageBox::information(this, "Empy Fields.", "Please fill in address, subnet,\n gateway and the first dns entries.", "Ok"); + return false; + } + interfaces->removeAllInterfaceOptions(); + + // DHCP + if(dhcpCheckBox->isChecked()){ + interfaces->setInterfaceMethod(INTERFACES_METHOD_DHCP); + interfaces->setInterfaceOption("leasehours", QString("%1").arg(leaseTime->value())); + interfaces->setInterfaceOption("leasetime", QString("%1").arg(leaseTime->value()*60*60)); + } + else{ + interfaces->setInterfaceMethod("static"); + interfaces->setInterfaceOption("address", ipAddressEdit->text()); + interfaces->setInterfaceOption("netmask", subnetMaskEdit->text()); + interfaces->setInterfaceOption("gateway", gatewayEdit->text()); + QString dns = firstDNSLineEdit->text() + " " + secondDNSLineEdit->text(); + interfaces->setInterfaceOption("up "DNSSCRIPT" add ", dns); + interfaces->setInterfaceOption("down "DNSSCRIPT" remove ", dns); + } + + // IP Information + interfaces->setAuto(interface->getInterfaceName(), autoStart->isChecked()); + return true; +} + +/** + * The Profile has changed. + * @profile the new profile. + */ +void InterfaceSetupImp::changeProfile(const QString &profile){ + QString newInterfaceName; + if(profile.lower() == "all") + newInterfaceName = interface->getInterfaceName(); + else + newInterfaceName = interface->getInterfaceName() + "_" + profile; + if(newInterfaceName == currentInterfaceName) + return; + else{ + saveSettings(); + currentInterfaceName = newInterfaceName; + } + bool error = interfaces->setInterface(currentInterfaceName); + + // See if we have to make a interface. + if(error){ + qDebug("InterfaceSetupImp: Adding a new interface from profile change."); + interfaces->addInterface(currentInterfaceName, INTERFACES_FAMILY_INET, INTERFACES_METHOD_DHCP); + error = interfaces->setInterface(currentInterfaceName); + if(error){ + qDebug("InterfaceSetupImp: Added interface, but still can't set."); + return; + } + } + + //qDebug( currentInterfaceName.latin1() ); + // We must have a valid interface to get this far so read some settings. + + // DHCP + if(interfaces->getInterfaceMethod(error) == INTERFACES_METHOD_DHCP) + dhcpCheckBox->setChecked(true); + else + dhcpCheckBox->setChecked(false); + leaseTime->setValue(interfaces->getInterfaceOption("leasehours", error).toInt()); + if(error) + leaseTime->setValue(interfaces->getInterfaceOption("leasetime", error).toInt()/60/60); + if(error) + leaseTime->setValue(24); + + // IP Information + autoStart->setChecked(interfaces->isAuto(interface->getInterfaceName())); + QString dns = interfaces->getInterfaceOption("up interfacednsscript add", error); + if(dns.contains(" ")){ + firstDNSLineEdit->setText(dns.mid(0, dns.find(" "))); + secondDNSLineEdit->setText(dns.mid(dns.find(" ")+1, dns.length())); + } + ipAddressEdit->setText(interfaces->getInterfaceOption("address", error)); + subnetMaskEdit->setText(interfaces->getInterfaceOption("netmask", error)); + gatewayEdit->setText(interfaces->getInterfaceOption("gateway", error)); +} + + +// interfacesetup.cpp + diff --git a/noncore/net/networksetup/interfacesetupimp.h b/noncore/net/networksetup/interfacesetupimp.h new file mode 100644 index 0000000..6c34718 --- a/dev/null +++ b/noncore/net/networksetup/interfacesetupimp.h @@ -0,0 +1,30 @@ +#ifndef INTERFACESETUPIMP_H +#define INTERFACESETUPIMP_H + +#include "interfacesetup.h" + +class Interface; +class Interfaces; + +class InterfaceSetupImp : public InterfaceSetup { + Q_OBJECT + +public: + InterfaceSetupImp( QWidget* parent = 0, const char* name = 0, Interface *i=0, bool modal = FALSE, WFlags fl = 0); + +protected slots: + void accept(); + void changeProfile(const QString &profile); + +private: + bool saveSettings(); + Interfaces *interfaces; + Interface *interface; + QString currentInterfaceName; + +}; + +#endif + +// interfacesetupimp.h + diff --git a/noncore/net/networksetup/kprocctrl.cpp b/noncore/net/networksetup/kprocctrl.cpp new file mode 100644 index 0000000..cd8711a --- a/dev/null +++ b/noncore/net/networksetup/kprocctrl.cpp @@ -0,0 +1,267 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +// +// KPROCESSCONTROLLER -- A helper class for KProcess +// +// version 0.3.1, Jan, 8th 1997 +// +// (C) Christian Czezatke +// e9025461@student.tuwien.ac.at +// + +//#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include "kprocess.h" +#include "kprocctrl.h" + +KProcessController *KProcessController::theKProcessController = 0; + +struct sigaction KProcessController::oldChildHandlerData; +bool KProcessController::handlerSet = false; + +KProcessController::KProcessController() +{ + assert( theKProcessController == 0 ); + + if (0 > pipe(fd)) + printf(strerror(errno)); + + notifier = new QSocketNotifier(fd[0], QSocketNotifier::Read); + notifier->setEnabled(true); + QObject::connect(notifier, SIGNAL(activated(int)), + this, SLOT(slotDoHousekeeping(int))); + connect( &delayedChildrenCleanupTimer, SIGNAL( timeout()), + SLOT( delayedChildrenCleanup())); + + theKProcessController = this; + + setupHandlers(); +} + + +void KProcessController::setupHandlers() +{ + if( handlerSet ) + return; + struct sigaction act; + act.sa_handler=theSigCHLDHandler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGCHLD); + // Make sure we don't block this signal. gdb tends to do that :-( + sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0); + + act.sa_flags = SA_NOCLDSTOP; + + // CC: take care of SunOS which automatically restarts interrupted system + // calls (and thus does not have SA_RESTART) + +#ifdef SA_RESTART + act.sa_flags |= SA_RESTART; +#endif + + sigaction( SIGCHLD, &act, &oldChildHandlerData ); + + act.sa_handler=SIG_IGN; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGPIPE); + act.sa_flags = 0; + sigaction( SIGPIPE, &act, 0L); + handlerSet = true; +} + +void KProcessController::resetHandlers() +{ + if( !handlerSet ) + return; + sigaction( SIGCHLD, &oldChildHandlerData, 0 ); + // there should be no problem with SIGPIPE staying SIG_IGN + handlerSet = false; +} + +// block SIGCHLD handler, because it accesses processList +void KProcessController::addKProcess( KProcess* p ) +{ + sigset_t newset, oldset; + sigemptyset( &newset ); + sigaddset( &newset, SIGCHLD ); + sigprocmask( SIG_BLOCK, &newset, &oldset ); + processList.append( p ); + sigprocmask( SIG_SETMASK, &oldset, 0 ); +} + +void KProcessController::removeKProcess( KProcess* p ) +{ + sigset_t newset, oldset; + sigemptyset( &newset ); + sigaddset( &newset, SIGCHLD ); + sigprocmask( SIG_BLOCK, &newset, &oldset ); + processList.remove( p ); + sigprocmask( SIG_SETMASK, &oldset, 0 ); +} + +//using a struct which contains both the pid and the status makes it easier to write +//and read the data into the pipe +//especially this solves a problem which appeared on my box where slotDoHouseKeeping() received +//only 4 bytes (with some debug output around the write()'s it received all 8 bytes) +//don't know why this happened, but when writing all 8 bytes at once it works here, aleXXX +struct waitdata +{ + pid_t pid; + int status; +}; + +void KProcessController::theSigCHLDHandler(int arg) +{ + struct waitdata wd; +// int status; +// pid_t this_pid; + int saved_errno; + + saved_errno = errno; + // since waitpid and write change errno, we have to save it and restore it + // (Richard Stevens, Advanced programming in the Unix Environment) + + bool found = false; + if( theKProcessController != 0 ) { + // iterating the list doesn't perform any system call + for( QValueList::ConstIterator it = theKProcessController->processList.begin(); + it != theKProcessController->processList.end(); + ++it ) + { + if( !(*it)->isRunning()) + continue; + wd.pid = waitpid( (*it)->pid(), &wd.status, WNOHANG ); + if ( wd.pid > 0 ) { + ::write(theKProcessController->fd[1], &wd, sizeof(wd)); + found = true; + } + } + } + if( !found && oldChildHandlerData.sa_handler != SIG_IGN + && oldChildHandlerData.sa_handler != SIG_DFL ) + oldChildHandlerData.sa_handler( arg ); // call the old handler + // handle the rest + if( theKProcessController != 0 ) { + static const struct waitdata dwd = { 0, 0 }; // delayed waitpid() + ::write(theKProcessController->fd[1], &dwd, sizeof(dwd)); + } else { + int dummy; + while( waitpid( -1, &dummy, WNOHANG ) > 0 ) + ; + } + + errno = saved_errno; +} + + + +void KProcessController::slotDoHousekeeping(int ) +{ + unsigned int bytes_read = 0; + unsigned int errcnt=0; + // read pid and status from the pipe. + struct waitdata wd; + while ((bytes_read < sizeof(wd)) && (errcnt < 50)) { + int r = ::read(fd[0], ((char *)&wd) + bytes_read, sizeof(wd) - bytes_read); + if (r > 0) bytes_read += r; + else if (r < 0) errcnt++; + } + if (errcnt >= 50) { + fprintf(stderr, + "Error: Max. error count for pipe read " + "exceeded in KProcessController::slotDoHousekeeping\n"); + return; // it makes no sense to continue here! + } + if (bytes_read != sizeof(wd)) { + fprintf(stderr, + "Error: Could not read info from signal handler %d <> %d!\n", + bytes_read, sizeof(wd)); + return; // it makes no sense to continue here! + } + if (wd.pid==0) { // special case, see delayedChildrenCleanup() + delayedChildrenCleanupTimer.start( 1000, true ); + return; + } + + for( QValueList::ConstIterator it = processList.begin(); + it != processList.end(); + ++it ) { + KProcess* proc = *it; + if (proc->pid() == wd.pid) { + // process has exited, so do emit the respective events + if (proc->run_mode == KProcess::Block) { + // If the reads are done blocking then set the status in proc + // but do nothing else because KProcess will perform the other + // actions of processHasExited. + proc->status = wd.status; + proc->runs = false; + } else { + proc->processHasExited(wd.status); + } + return; + } + } +} + +// this is needed e.g. for popen(), which calls waitpid() checking +// for its forked child, if we did waitpid() directly in the SIGCHLD +// handler, popen()'s waitpid() call would fail +void KProcessController::delayedChildrenCleanup() +{ + struct waitdata wd; + while(( wd.pid = waitpid( -1, &wd.status, WNOHANG ) ) > 0 ) { + for( QValueList::ConstIterator it = processList.begin(); + it != processList.end(); + ++it ) + { + if( !(*it)->isRunning() || (*it)->pid() != wd.pid ) + continue; + // it's KProcess, handle it + ::write(fd[1], &wd, sizeof(wd)); + break; + } + } +} + +KProcessController::~KProcessController() +{ + assert( theKProcessController == this ); + resetHandlers(); + + notifier->setEnabled(false); + + close(fd[0]); + close(fd[1]); + + delete notifier; + theKProcessController = 0; +} + +//#include "kprocctrl.moc" diff --git a/noncore/net/networksetup/kprocctrl.h b/noncore/net/networksetup/kprocctrl.h new file mode 100644 index 0000000..ac82b9d --- a/dev/null +++ b/noncore/net/networksetup/kprocctrl.h @@ -0,0 +1,120 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +// +// KPROCESSCONTROLLER -- A helper class for KProcess +// +// version 0.3.1, Jan 8th 1997 +// +// (C) Christian Czezatke +// e9025461@student.tuwien.ac.at +// + +#ifndef __KPROCCTRL_H__ +#define __KPROCCTRL_H__ + +#include +#include + +#include "kprocess.h" + +class KProcessControllerPrivate; +class QSocketNotifier; + +/** + * @short Used internally by @ref KProcess + * @internal + * @author Christian Czezakte + * + * A class for internal use by KProcess only. -- Exactly one instance + * of this class is generated by the first instance of KProcess that is + * created (a pointer to it gets stored in @ref theKProcessController ). + * + * This class takes care of the actual (UN*X) signal handling. +*/ +class KProcessController : public QObject +{ + Q_OBJECT + +public: + KProcessController(); + ~KProcessController(); + //CC: WARNING! Destructor Not virtual (but you don't derive classes from this anyhow...) + +public: + + /** + * Only a single instance of this class is allowed at a time, + * and this static variable is used to track the one instance. + */ + static KProcessController *theKProcessController; + + /** + * Automatically called upon SIGCHLD. + * + * Normally you do not need to do anything with this function but + * if your application needs to disable SIGCHLD for some time for + * reasons beyond your control, you should call this function afterwards + * to make sure that no SIGCHLDs where missed. + */ + static void theSigCHLDHandler(int signal); + // handler for sigchld + + /** + * @internal + */ + static void setupHandlers(); + /** + * @internal + */ + static void resetHandlers(); + /** + * @internal + */ + void addKProcess( KProcess* ); + /** + * @internal + */ + void removeKProcess( KProcess* ); + public slots: + /** + * @internal + */ + void slotDoHousekeeping(int socket); + + private slots: + void delayedChildrenCleanup(); +private: + int fd[2]; + QSocketNotifier *notifier; + static struct sigaction oldChildHandlerData; + static bool handlerSet; + QValueList processList; + QTimer delayedChildrenCleanupTimer; + + // Disallow assignment and copy-construction + KProcessController( const KProcessController& ); + KProcessController& operator= ( const KProcessController& ); + + KProcessControllerPrivate *d; +}; + + + +#endif + diff --git a/noncore/net/networksetup/kprocess.cpp b/noncore/net/networksetup/kprocess.cpp new file mode 100644 index 0000000..193ec9b --- a/dev/null +++ b/noncore/net/networksetup/kprocess.cpp @@ -0,0 +1,919 @@ +/* + + $Id$ + + This file is part of the KDE libraries + Copyright (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + +// +// KPROCESS -- A class for handling child processes in KDE without +// having to take care of Un*x specific implementation details +// +// version 0.3.1, Jan 8th 1998 +// +// (C) Christian Czezatke +// e9025461@student.tuwien.ac.at +// +// Changes: +// +// March 2nd, 1998: Changed parameter list for KShellProcess: +// Arguments are now placed in a single string so that +// -c is passed to the shell +// to make the use of "operator<<" consistent with KProcess + +#include "kprocess.h" +#define _MAY_INCLUDE_KPROCESSCONTROLLER_ +#include "kprocctrl.h" + +//#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#ifdef HAVE_INITGROUPS +#include +#endif +#include + +#include +//#include + +///////////////////////////// +// public member functions // +///////////////////////////// + +class KProcessPrivate { +public: + KProcessPrivate() : useShell(false) { } + + bool useShell; + QMap env; + QString wd; + QCString shell; +}; + +#define Q_CHECK_PTR(a) + +KProcess::KProcess() + : QObject(), + run_mode(NotifyOnExit), + runs(false), + pid_(0), + status(0), + keepPrivs(false), + innot(0), + outnot(0), + errnot(0), + communication(NoCommunication), + input_data(0), + input_sent(0), + input_total(0), + d(0) +{ + if (0 == KProcessController::theKProcessController) { + (void) new KProcessController(); + Q_CHECK_PTR(KProcessController::theKProcessController); + } + + KProcessController::theKProcessController->addKProcess(this); + out[0] = out[1] = -1; + in[0] = in[1] = -1; + err[0] = err[1] = -1; +} + +void +KProcess::setEnvironment(const QString &name, const QString &value) +{ + if (!d) + d = new KProcessPrivate; + d->env.insert(name, value); +} + +void +KProcess::setWorkingDirectory(const QString &dir) +{ + if (!d) + d = new KProcessPrivate; + d->wd = dir; +} + +void +KProcess::setupEnvironment() +{ + if (d) + { + QMap::Iterator it; + for(it = d->env.begin(); it != d->env.end(); ++it) + setenv(QFile::encodeName(it.key()).data(), + QFile::encodeName(it.data()).data(), 1); + if (!d->wd.isEmpty()) + chdir(QFile::encodeName(d->wd).data()); + } +} + +void +KProcess::setRunPrivileged(bool keepPrivileges) +{ + keepPrivs = keepPrivileges; +} + +bool +KProcess::runPrivileged() const +{ + return keepPrivs; +} + + +KProcess::~KProcess() +{ + // destroying the KProcess instance sends a SIGKILL to the + // child process (if it is running) after removing it from the + // list of valid processes (if the process is not started as + // "DontCare") + + KProcessController::theKProcessController->removeKProcess(this); + // this must happen before we kill the child + // TODO: block the signal while removing the current process from the process list + + if (runs && (run_mode != DontCare)) + kill(SIGKILL); + + // Clean up open fd's and socket notifiers. + closeStdin(); + closeStdout(); + closeStderr(); + + // TODO: restore SIGCHLD and SIGPIPE handler if this is the last KProcess + delete d; +} + +void KProcess::detach() +{ + KProcessController::theKProcessController->removeKProcess(this); + + runs = false; + pid_ = 0; + + // Clean up open fd's and socket notifiers. + closeStdin(); + closeStdout(); + closeStderr(); +} + +bool KProcess::setExecutable(const QString& proc) +{ + if (runs) return false; + + if (proc.isEmpty()) return false; + + if (!arguments.isEmpty()) + arguments.remove(arguments.begin()); + arguments.prepend(QFile::encodeName(proc)); + + return true; +} + +KProcess &KProcess::operator<<(const QStringList& args) +{ + QStringList::ConstIterator it = args.begin(); + for ( ; it != args.end() ; ++it ) + arguments.append(QFile::encodeName(*it)); + return *this; +} + +KProcess &KProcess::operator<<(const QCString& arg) +{ + return operator<< (arg.data()); +} + +KProcess &KProcess::operator<<(const char* arg) +{ + arguments.append(arg); + return *this; +} + +KProcess &KProcess::operator<<(const QString& arg) +{ + arguments.append(QFile::encodeName(arg)); + return *this; +} + +void KProcess::clearArguments() +{ + arguments.clear(); +} + +bool KProcess::start(RunMode runmode, Communication comm) +{ + uint i; + uint n = arguments.count(); + char **arglist; + + if (runs || (0 == n)) { + return false; // cannot start a process that is already running + // or if no executable has been assigned + } + run_mode = runmode; + status = 0; + + QCString shellCmd; + if (d && d->useShell) + { + if (d->shell.isEmpty()) + { + //kdDebug() << "Could not find a valid shell\n" << endl; + return false; + } + + arglist = static_cast(malloc( (4)*sizeof(char *))); + for (i=0; i < n; i++) { + shellCmd += arguments[i]; + shellCmd += " "; // CC: to separate the arguments + } + + arglist[0] = d->shell.data(); + arglist[1] = (char *) "-c"; + arglist[2] = shellCmd.data(); + arglist[3] = 0; + } + else + { + arglist = static_cast(malloc( (n+1)*sizeof(char *))); + for (i=0; i < n; i++) + arglist[i] = arguments[i].data(); + arglist[n]= 0; + } + + setupCommunication(comm); + //) + //kdDebug() << "Could not setup Communication!\n"; + + // We do this in the parent because if we do it in the child process + // gdb gets confused when the application runs from gdb. + uid_t uid = getuid(); + gid_t gid = getgid(); +#ifdef HAVE_INITGROUPS + struct passwd *pw = getpwuid(uid); +#endif + + int fd[2]; + if (0 > pipe(fd)) + { + fd[0] = fd[1] = 0; // Pipe failed.. continue + } + + runs = true; + + QApplication::flushX(); + + // WABA: Note that we use fork() and not vfork() because + // vfork() has unclear semantics and is not standardized. + pid_ = fork(); + + if (0 == pid_) { + if (fd[0]) + close(fd[0]); + if (!runPrivileged()) + { + setgid(gid); +#if defined( HAVE_INITGROUPS) + if(pw) + initgroups(pw->pw_name, pw->pw_gid); +#endif + setuid(uid); + } + // The child process + commSetupDoneC(); + //) + //kdDebug() << "Could not finish comm setup in child!" << endl; + + setupEnvironment(); + + // Matthias + if (run_mode == DontCare) + setpgid(0,0); + // restore default SIGPIPE handler (Harri) + struct sigaction act; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGPIPE); + act.sa_handler = SIG_DFL; + act.sa_flags = 0; + sigaction(SIGPIPE, &act, 0L); + + // We set the close on exec flag. + // Closing of fd[1] indicates that the execvp succeeded! + if (fd[1]) + fcntl(fd[1], F_SETFD, FD_CLOEXEC); + execvp(arglist[0], arglist); + char resultByte = 1; + if (fd[1]) + write(fd[1], &resultByte, 1); + _exit(-1); + } else if (-1 == pid_) { + // forking failed + + runs = false; + free(arglist); + return false; + } else { + if (fd[1]) + close(fd[1]); + // the parent continues here + + // Discard any data for stdin that might still be there + input_data = 0; + + // Check whether client could be started. + if (fd[0]) for(;;) + { + char resultByte; + int n = ::read(fd[0], &resultByte, 1); + if (n == 1) + { + // Error + runs = false; + close(fd[0]); + free(arglist); + pid_ = 0; + return false; + } + if (n == -1) + { + if ((errno == ECHILD) || (errno == EINTR)) + continue; // Ignore + } + break; // success + } + if (fd[0]) + close(fd[0]); + + if (!commSetupDoneP()){} // finish communication socket setup for the parent + //kdDebug() << "Could not finish comm setup in parent!" << endl; + + if (run_mode == Block) { + commClose(); + + // The SIGCHLD handler of the process controller will catch + // the exit and set the status + while(runs) + { + KProcessController::theKProcessController-> + slotDoHousekeeping(0); + } + runs = FALSE; + emit processExited(this); + } + } + free(arglist); + return true; +} + + + +bool KProcess::kill(int signo) +{ + bool rv=false; + + if (0 != pid_) + rv= (-1 != ::kill(pid_, signo)); + // probably store errno somewhere... + return rv; +} + + + +bool KProcess::isRunning() const +{ + return runs; +} + + + +pid_t KProcess::pid() const +{ + return pid_; +} + + + +bool KProcess::normalExit() const +{ + int _status = status; + return (pid_ != 0) && (!runs) && (WIFEXITED((_status))); +} + + + +int KProcess::exitStatus() const +{ + int _status = status; + return WEXITSTATUS((_status)); +} + + + +bool KProcess::writeStdin(const char *buffer, int buflen) +{ + bool rv; + + // if there is still data pending, writing new data + // to stdout is not allowed (since it could also confuse + // kprocess... + if (0 != input_data) + return false; + + if (runs && (communication & Stdin)) { + input_data = buffer; + input_sent = 0; + input_total = buflen; + slotSendData(0); + innot->setEnabled(true); + rv = true; + } else + rv = false; + return rv; +} + +void KProcess::suspend() +{ + if ((communication & Stdout) && outnot) + outnot->setEnabled(false); +} + +void KProcess::resume() +{ + if ((communication & Stdout) && outnot) + outnot->setEnabled(true); +} + +bool KProcess::closeStdin() +{ + bool rv; + + if (communication & Stdin) { + communication = (Communication) (communication & ~Stdin); + delete innot; + innot = 0; + close(in[1]); + rv = true; + } else + rv = false; + return rv; +} + +bool KProcess::closeStdout() +{ + bool rv; + + if (communication & Stdout) { + communication = (Communication) (communication & ~Stdout); + delete outnot; + outnot = 0; + close(out[0]); + rv = true; + } else + rv = false; + return rv; +} + +bool KProcess::closeStderr() +{ + bool rv; + + if (communication & Stderr) { + communication = static_cast(communication & ~Stderr); + delete errnot; + errnot = 0; + close(err[0]); + rv = true; + } else + rv = false; + return rv; +} + + +///////////////////////////// +// protected slots // +///////////////////////////// + + + +void KProcess::slotChildOutput(int fdno) +{ + if (!childOutput(fdno)) + closeStdout(); +} + + +void KProcess::slotChildError(int fdno) +{ + if (!childError(fdno)) + closeStderr(); +} + + +void KProcess::slotSendData(int) +{ + if (input_sent == input_total) { + innot->setEnabled(false); + input_data = 0; + emit wroteStdin(this); + } else + input_sent += ::write(in[1], input_data+input_sent, input_total-input_sent); +} + + + +////////////////////////////// +// private member functions // +////////////////////////////// + + + +void KProcess::processHasExited(int state) +{ + if (runs) + { + runs = false; + status = state; + + commClose(); // cleanup communication sockets + + // also emit a signal if the process was run Blocking + if (DontCare != run_mode) + { + emit processExited(this); + } + } +} + + + +int KProcess::childOutput(int fdno) +{ + if (communication & NoRead) { + int len = -1; + emit receivedStdout(fdno, len); + errno = 0; // Make sure errno doesn't read "EAGAIN" + return len; + } + else + { + char buffer[1024]; + int len; + + len = ::read(fdno, buffer, 1024); + + if ( 0 < len) { + emit receivedStdout(this, buffer, len); + } + return len; + } +} + + + +int KProcess::childError(int fdno) +{ + char buffer[1024]; + int len; + + len = ::read(fdno, buffer, 1024); + + if ( 0 < len) + emit receivedStderr(this, buffer, len); + return len; +} + + + +int KProcess::setupCommunication(Communication comm) +{ + int ok; + + communication = comm; + + ok = 1; + if (comm & Stdin) + ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, in) >= 0; + + if (comm & Stdout) + ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, out) >= 0; + + if (comm & Stderr) + ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, err) >= 0; + + return ok; +} + + + +int KProcess::commSetupDoneP() +{ + int ok = 1; + + if (communication != NoCommunication) { + if (communication & Stdin) + close(in[0]); + if (communication & Stdout) + close(out[1]); + if (communication & Stderr) + close(err[1]); + + // Don't create socket notifiers and set the sockets non-blocking if + // blocking is requested. + if (run_mode == Block) return ok; + + if (communication & Stdin) { +// ok &= (-1 != fcntl(in[1], F_SETFL, O_NONBLOCK)); + innot = new QSocketNotifier(in[1], QSocketNotifier::Write, this); + Q_CHECK_PTR(innot); + innot->setEnabled(false); // will be enabled when data has to be sent + QObject::connect(innot, SIGNAL(activated(int)), + this, SLOT(slotSendData(int))); + } + + if (communication & Stdout) { +// ok &= (-1 != fcntl(out[0], F_SETFL, O_NONBLOCK)); + outnot = new QSocketNotifier(out[0], QSocketNotifier::Read, this); + Q_CHECK_PTR(outnot); + QObject::connect(outnot, SIGNAL(activated(int)), + this, SLOT(slotChildOutput(int))); + if (communication & NoRead) + suspend(); + } + + if (communication & Stderr) { +// ok &= (-1 != fcntl(err[0], F_SETFL, O_NONBLOCK)); + errnot = new QSocketNotifier(err[0], QSocketNotifier::Read, this ); + Q_CHECK_PTR(errnot); + QObject::connect(errnot, SIGNAL(activated(int)), + this, SLOT(slotChildError(int))); + } + } + return ok; +} + + + +int KProcess::commSetupDoneC() +{ + int ok = 1; + struct linger so; + memset(&so, 0, sizeof(so)); + + if (communication & Stdin) + close(in[1]); + if (communication & Stdout) + close(out[0]); + if (communication & Stderr) + close(err[0]); + + if (communication & Stdin) + ok &= dup2(in[0], STDIN_FILENO) != -1; + else { + int null_fd = open( "/dev/null", O_RDONLY ); + ok &= dup2( null_fd, STDIN_FILENO ) != -1; + close( null_fd ); + } + if (communication & Stdout) { + ok &= dup2(out[1], STDOUT_FILENO) != -1; + ok &= !setsockopt(out[1], SOL_SOCKET, SO_LINGER, (char*)&so, sizeof(so)); + } + else { + int null_fd = open( "/dev/null", O_WRONLY ); + ok &= dup2( null_fd, STDOUT_FILENO ) != -1; + close( null_fd ); + } + if (communication & Stderr) { + ok &= dup2(err[1], STDERR_FILENO) != -1; + ok &= !setsockopt(err[1], SOL_SOCKET, SO_LINGER, reinterpret_cast(&so), sizeof(so)); + } + else { + int null_fd = open( "/dev/null", O_WRONLY ); + ok &= dup2( null_fd, STDERR_FILENO ) != -1; + close( null_fd ); + } + return ok; +} + + + +void KProcess::commClose() +{ + if (NoCommunication != communication) { + bool b_in = (communication & Stdin); + bool b_out = (communication & Stdout); + bool b_err = (communication & Stderr); + if (b_in) + delete innot; + + if (b_out || b_err) { + // If both channels are being read we need to make sure that one socket buffer + // doesn't fill up whilst we are waiting for data on the other (causing a deadlock). + // Hence we need to use select. + + // Once one or other of the channels has reached EOF (or given an error) go back + // to the usual mechanism. + + int fds_ready = 1; + fd_set rfds; + + int max_fd = 0; + if (b_out) { + fcntl(out[0], F_SETFL, O_NONBLOCK); + if (out[0] > max_fd) + max_fd = out[0]; + delete outnot; + outnot = 0; + } + if (b_err) { + fcntl(err[0], F_SETFL, O_NONBLOCK); + if (err[0] > max_fd) + max_fd = err[0]; + delete errnot; + errnot = 0; + } + + + while (b_out || b_err) { + // * If the process is still running we block until we + // receive data. (p_timeout = 0, no timeout) + // * If the process has already exited, we only check + // the available data, we don't wait for more. + // (p_timeout = &timeout, timeout immediately) + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + struct timeval *p_timeout = runs ? 0 : &timeout; + + FD_ZERO(&rfds); + if (b_out) + FD_SET(out[0], &rfds); + + if (b_err) + FD_SET(err[0], &rfds); + + fds_ready = select(max_fd+1, &rfds, 0, 0, p_timeout); + if (fds_ready <= 0) break; + + if (b_out && FD_ISSET(out[0], &rfds)) { + int ret = 1; + while (ret > 0) ret = childOutput(out[0]); + if ((ret == -1 && errno != EAGAIN) || ret == 0) + b_out = false; + } + + if (b_err && FD_ISSET(err[0], &rfds)) { + int ret = 1; + while (ret > 0) ret = childError(err[0]); + if ((ret == -1 && errno != EAGAIN) || ret == 0) + b_err = false; + } + } + } + + if (b_in) { + communication = (Communication) (communication & ~Stdin); + close(in[1]); + } + if (b_out) { + communication = (Communication) (communication & ~Stdout); + close(out[0]); + } + if (b_err) { + communication = (Communication) (communication & ~Stderr); + close(err[0]); + } + } +} + +void KProcess::setUseShell(bool useShell, const char *shell) +{ + if (!d) + d = new KProcessPrivate; + d->useShell = useShell; + d->shell = shell; + if (d->shell.isEmpty()) + d->shell = searchShell(); +} + +QString KProcess::quote(const QString &arg) +{ + QString res = arg; + res.replace(QRegExp(QString::fromLatin1("\'")), + QString::fromLatin1("'\"'\"'")); + res.prepend('\''); + res.append('\''); + return res; +} + +QCString KProcess::searchShell() +{ + QCString tmpShell = QCString(getenv("SHELL")).stripWhiteSpace(); + if (!isExecutable(tmpShell)) + { + tmpShell = "/bin/sh"; + } + + return tmpShell; +} + +bool KProcess::isExecutable(const QCString &filename) +{ + struct stat fileinfo; + + if (filename.isEmpty()) return false; + + // CC: we've got a valid filename, now let's see whether we can execute that file + + if (-1 == stat(filename.data(), &fileinfo)) return false; + // CC: return false if the file does not exist + + // CC: anyway, we cannot execute directories, block/character devices, fifos or sockets + if ( (S_ISDIR(fileinfo.st_mode)) || + (S_ISCHR(fileinfo.st_mode)) || + (S_ISBLK(fileinfo.st_mode)) || +#ifdef S_ISSOCK + // CC: SYSVR4 systems don't have that macro + (S_ISSOCK(fileinfo.st_mode)) || +#endif + (S_ISFIFO(fileinfo.st_mode)) || + (S_ISDIR(fileinfo.st_mode)) ) { + return false; + } + + // CC: now check for permission to execute the file + if (access(filename.data(), X_OK) != 0) return false; + + // CC: we've passed all the tests... + return true; +} + +void KProcess::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + + +/////////////////////////// +// CC: Class KShellProcess +/////////////////////////// + +KShellProcess::KShellProcess(const char *shellname): + KProcess() +{ + setUseShell(true, shellname); +} + + +KShellProcess::~KShellProcess() { +} + +QString KShellProcess::quote(const QString &arg) +{ + return KProcess::quote(arg); +} + +bool KShellProcess::start(RunMode runmode, Communication comm) +{ + return KProcess::start(runmode, comm); +} + +void KShellProcess::virtual_hook( int id, void* data ) +{ KProcess::virtual_hook( id, data ); } + +//#include "kprocess.moc" diff --git a/noncore/net/networksetup/kprocess.h b/noncore/net/networksetup/kprocess.h new file mode 100644 index 0000000..e70f7e7 --- a/dev/null +++ b/noncore/net/networksetup/kprocess.h @@ -0,0 +1,804 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +// +// KPROCESS -- A class for handling child processes in KDE without +// having to take care of Un*x specific implementation details +// +// version 0.3.1, Jan 8th 1998 +// +// (C) Christian Czezatke +// e9025461@student.tuwien.ac.at +// + +#ifndef __kprocess_h__ +#define __kprocess_h__ + +#include // for pid_t +#include +#include +#include +#include +#include +#include + +class QSocketNotifier; +class KProcessPrivate; + +/** + * Child process invocation, monitoring and control. + * + * @sect General usage and features + * + *This class allows a KDE application to start child processes without having + *to worry about UN*X signal handling issues and zombie process reaping. + * + *@see KProcIO + * + *Basically, this class distinguishes three different ways of running + *child processes: + * + *@li KProcess::DontCare -- The child process is invoked and both the child + *process and the parent process continue concurrently. + * + *Starting a DontCare child process means that the application is + *not interested in any notification to determine whether the + *child process has already exited or not. + * + *@li KProcess::NotifyOnExit -- The child process is invoked and both the + *child and the parent process run concurrently. + * + *When the child process exits, the KProcess instance + *corresponding to it emits the Qt signal @ref processExited(). + * + *Since this signal is @em not emitted from within a UN*X + *signal handler, arbitrary function calls can be made. + * + *Be aware: When the KProcess objects gets destructed, the child + *process will be killed if it is still running! + *This means in particular, that you cannot use a KProcess on the stack + *with KProcess::NotifyOnExit. + * + *@li KProcess::Block -- The child process starts and the parent process + *is suspended until the child process exits. (@em Really not recommended + *for programs with a GUI.) + * + *KProcess also provides several functions for determining the exit status + *and the pid of the child process it represents. + * + *Furthermore it is possible to supply command-line arguments to the process + *in a clean fashion (no null -- terminated stringlists and such...) + * + *A small usage example: + *
+ *KProcess *proc = new KProcess;
+ *
+ **proc << "my_executable";
+ **proc << "These" << "are" << "the" << "command" << "line" << "args";
+ *QApplication::connect(proc, SIGNAL(processExited(KProcess *)),
+ *                      pointer_to_my_object, SLOT(my_objects_slot(KProcess *)));
+ *proc->start();
+ *
+ * + *This will start "my_executable" with the commandline arguments "These"... + * + *When the child process exits, the respective Qt signal will be emitted. + * + *@sect Communication with the child process + * + *KProcess supports communication with the child process through + *stdin/stdout/stderr. + * + *The following functions are provided for getting data from the child + *process or sending data to the child's stdin (For more information, + *have a look at the documentation of each function): + * + *@li bool @ref writeStdin(char *buffer, int buflen); + *@li -- Transmit data to the child process's stdin. + * + *@li bool @ref closeStdin(); + *@li -- Closes the child process's stdin (which causes it to see an feof(stdin)). + *Returns false if you try to close stdin for a process that has been started + *without a communication channel to stdin. + * + *@li bool @ref closeStdout(); + *@li -- Closes the child process's stdout. + *Returns false if you try to close stdout for a process that has been started + *without a communication channel to stdout. + * + *@li bool @ref closeStderr(); + *@li -- Closes the child process's stderr. + *Returns false if you try to close stderr for a process that has been started + *without a communication channel to stderr. + * + * + *@sect QT signals: + * + *@li void @ref receivedStdout(KProcess *proc, char *buffer, int buflen); + *@li void @ref receivedStderr(KProcess *proc, char *buffer, int buflen); + *@li -- Indicates that new data has arrived from either the + *child process's stdout or stderr. + * + *@li void @ref wroteStdin(KProcess *proc); + *@li -- Indicates that all data that has been sent to the child process + *by a prior call to @ref writeStdin() has actually been transmitted to the + *client . + * + *@author Christian Czezakte e9025461@student.tuwien.ac.at + * + * + **/ +class KProcess : public QObject +{ + Q_OBJECT + +public: + + /** + * Modes in which the communication channel can be opened. + * + * If communication for more than one channel is required, + * the values have to be or'ed together, for example to get + * communication with stdout as well as with stdin, you would + * specify @p Stdin @p | @p Stdout + * + * If @p NoRead is specified in conjunction with @p Stdout, + * no data is actually read from @p Stdout but only + * the signal @ref childOutput(int fd) is emitted. + */ + enum Communication { NoCommunication = 0, Stdin = 1, Stdout = 2, Stderr = 4, + AllOutput = 6, All = 7, + NoRead }; + + /** + * Run-modes for a child process. + */ + enum RunMode { + /** + * The application does not receive notifications from the subprocess when + * it is finished or aborted. + */ + DontCare, + /** + * The application is notified when the subprocess dies. + */ + NotifyOnExit, + /** + * The application is suspended until the started process is finished. + */ + Block }; + + /** + * Constructor + */ + KProcess(); + + /** + *Destructor: + * + * If the process is running when the destructor for this class + * is called, the child process is killed with a SIGKILL, but + * only if the run mode is not of type @p DontCare. + * Processes started as @p DontCare keep running anyway. + */ + virtual ~KProcess(); + + /** + @deprecated + + The use of this function is now deprecated. -- Please use the + "operator<<" instead of "setExecutable". + + Sets the executable to be started with this KProcess object. + Returns false if the process is currently running (in that + case the executable remains unchanged.) + + @see operator<< + + */ + bool setExecutable(const QString& proc); + + + /** + * Sets the executable and the command line argument list for this process. + * + * For example, doing an "ls -l /usr/local/bin" can be achieved by: + *
+   *  KProcess p;
+   *  ...
+   *  p << "ls" << "-l" << "/usr/local/bin"
+   *  
+ * + **/ + KProcess &operator<<(const QString& arg); + /** + * Similar to previous method, takes a char *, supposed to be in locale 8 bit already. + */ + KProcess &operator<<(const char * arg); + /** + * Similar to previous method, takes a QCString, supposed to be in locale 8 bit already. + */ + KProcess &operator<<(const QCString & arg); + + /** + * Sets the executable and the command line argument list for this process, + * in a single method call, or add a list of arguments. + **/ + KProcess &operator<<(const QStringList& args); + + /** + * Clear a command line argument list that has been set by using + * the "operator<<". + */ + void clearArguments(); + + /** + * Starts the process. + * For a detailed description of the + * various run modes and communication semantics, have a look at the + * general description of the KProcess class. + * + * The following problems could cause this function to + * return false: + * + * @li The process is already running. + * @li The command line argument list is empty. + * @li The starting of the process failed (could not fork). + * @li The executable was not found. + * + * @param comm Specifies which communication links should be + * established to the child process (stdin/stdout/stderr). By default, + * no communication takes place and the respective communication + * signals will never get emitted. + * + * @return true on success, false on error + * (see above for error conditions) + **/ + virtual bool start(RunMode runmode = NotifyOnExit, + Communication comm = NoCommunication); + + /** + * Stop the process (by sending it a signal). + * + * @param signo The signal to send. The default is SIGTERM. + * @return @p true if the signal was delivered successfully. + */ + virtual bool kill(int signo = SIGTERM); + + /** + @return @p true if the process is (still) considered to be running + */ + bool isRunning() const; + + /** Returns the process id of the process. + * + * If it is called after + * the process has exited, it returns the process id of the last + * child process that was created by this instance of KProcess. + * + * Calling it before any child process has been started by this + * KProcess instance causes pid() to return 0. + **/ + pid_t pid() const; + + /** + * Use pid(). + * @deprecated + */ + pid_t getPid() const { return pid(); } + + /** + * Suspend processing of data from stdout of the child process. + */ + void suspend(); + + /** + * Resume processing of data from stdout of the child process. + */ + void resume(); + + /** + * @return @p true if the process has already finished and has exited + * "voluntarily", ie: it has not been killed by a signal. + * + * Note that you should check @ref KProcess::exitStatus() to determine + * whether the process completed its task successful or not. + */ + bool normalExit() const; + + /** + * Returns the exit status of the process. + * + * Please use + * @ref KProcess::normalExit() to check whether the process has exited + * cleanly (i.e., @ref KProcess::normalExit() returns @p true) before calling + * this function because if the process did not exit normally, + * it does not have a valid exit status. + */ + int exitStatus() const; + + + /** + * Transmit data to the child process's stdin. + * + * KProcess::writeStdin may return false in the following cases: + * + * @li The process is not currently running. + * + * @li Communication to stdin has not been requested in the @ref start() call. + * + * @li Transmission of data to the child process by a previous call to + * @ref writeStdin() is still in progress. + * + * Please note that the data is sent to the client asynchronously, + * so when this function returns, the data might not have been + * processed by the child process. + * + * If all the data has been sent to the client, the signal + * @ref wroteStdin() will be emitted. + * + * Please note that you must not free "buffer" or call @ref writeStdin() + * again until either a @ref wroteStdin() signal indicates that the + * data has been sent or a @ref processHasExited() signal shows that + * the child process is no longer alive... + **/ + bool writeStdin(const char *buffer, int buflen); + + /** + * This causes the stdin file descriptor of the child process to be + * closed indicating an "EOF" to the child. + * + * @return @p false if no communication to the process's stdin + * had been specified in the call to @ref start(). + */ + bool closeStdin(); + + /** + * This causes the stdout file descriptor of the child process to be + * closed. + * + * @return @p false if no communication to the process's stdout + * had been specified in the call to @ref start(). + */ + bool closeStdout(); + + /** + * This causes the stderr file descriptor of the child process to be + * closed. + * + * @return @p false if no communication to the process's stderr + * had been specified in the call to @ref start(). + */ + bool closeStderr(); + + /** + * Lets you see what your arguments are for debugging. + */ + + const QValueList &args() { return arguments; } + + /** + * Controls whether the started process should drop any + * setuid/segid privileges or whether it should keep them + * + * The default is @p false : drop privileges + */ + void setRunPrivileged(bool keepPrivileges); + + /** + * Returns whether the started process will drop any + * setuid/segid privileges or whether it will keep them + */ + bool runPrivileged() const; + + /** + * Modifies the environment of the process to be started. + * This function must be called before starting the process. + */ + void setEnvironment(const QString &name, const QString &value); + + /** + * Changes the current working directory (CWD) of the process + * to be started. + * This function must be called before starting the process. + */ + void setWorkingDirectory(const QString &dir); + + /** + * Specify whether to start the command via a shell or directly. + * The default is to start the command directly. + * If @p useShell is true @p shell will be used as shell, or + * if shell is empty, the standard shell is used. + * @p quote A flag indicating whether to quote the arguments. + * + * When using a shell, the caller should make sure that all filenames etc. + * are properly quoted when passed as argument. + * @see quote() + */ + void setUseShell(bool useShell, const char *shell = 0); + + /** + * This function can be used to quote an argument string such that + * the shell processes it properly. This is e. g. necessary for + * user-provided file names which may contain spaces or quotes. + * It also prevents expansion of wild cards and environment variables. + */ + static QString quote(const QString &arg); + + /** + * Detaches KProcess from child process. All communication is closed. + * No exit notification is emitted any more for the child process. + * Deleting the KProcess will no longer kill the child process. + * Note that the current process remains the parent process of the + * child process. + */ + void detach(); + + + +signals: + + /** + * Emitted after the process has terminated when + * the process was run in the @p NotifyOnExit (==default option to + * @ref start()) or the @ref Block mode. + **/ + void processExited(KProcess *proc); + + + /** + * Emitted, when output from the child process has + * been received on stdout. + * + * To actually get + * these signals, the respective communication link (stdout/stderr) + * has to be turned on in @ref start(). + * + * @param buffer The data received. + * @param buflen The number of bytes that are available. + * + * You should copy the information contained in @p buffer to your private + * data structures before returning from this slot. + **/ + void receivedStdout(KProcess *proc, char *buffer, int buflen); + + /** + * Emitted when output from the child process has + * been received on stdout. + * + * To actually get these signals, the respective communications link + * (stdout/stderr) has to be turned on in @ref start() and the + * @p NoRead flag should have been passed. + * + * You will need to explicitly call resume() after your call to start() + * to begin processing data from the child process's stdout. This is + * to ensure that this signal is not emitted when no one is connected + * to it, otherwise this signal will not be emitted. + * + * The data still has to be read from file descriptor @p fd. + **/ + void receivedStdout(int fd, int &len); + + + /** + * Emitted, when output from the child process has + * been received on stderr. + * To actually get + * these signals, the respective communication link (stdout/stderr) + * has to be turned on in @ref start(). + * + * @param buffer The data received. + * @param buflen The number of bytes that are available. + * + * You should copy the information contained in @p buffer to your private + * data structures before returning from this slot. + */ + void receivedStderr(KProcess *proc, char *buffer, int buflen); + + /** + * Emitted after all the data that has been + * specified by a prior call to @ref writeStdin() has actually been + * written to the child process. + **/ + void wroteStdin(KProcess *proc); + + +protected slots: + + /** + * This slot gets activated when data from the child's stdout arrives. + * It usually calls "childOutput" + */ + void slotChildOutput(int fdno); + + /** + * This slot gets activated when data from the child's stderr arrives. + * It usually calls "childError" + */ + void slotChildError(int fdno); + /* + Slot functions for capturing stdout and stderr of the child + */ + + /** + * Called when another bulk of data can be sent to the child's + * stdin. If there is no more data to be sent to stdin currently + * available, this function must disable the QSocketNotifier "innot". + */ + void slotSendData(int dummy); + +protected: + + /** + * Sets up the environment according to the data passed via + * setEnvironment(...) + */ + void setupEnvironment(); + + /** + * The list of the process' command line arguments. The first entry + * in this list is the executable itself. + */ + QValueList arguments; + /** + * How to run the process (Block, NotifyOnExit, DontCare). You should + * not modify this data member directly from derived classes. + */ + RunMode run_mode; + /** + * true if the process is currently running. You should not + * modify this data member directly from derived classes. For + * reading the value of this data member, please use "isRunning()" + * since "runs" will probably be made private in later versions + * of KProcess. + */ + bool runs; + + /** + * The PID of the currently running process (see "getPid()"). + * You should not modify this data member in derived classes. + * Please use "getPid()" instead of directly accessing this + * member function since it will probably be made private in + * later versions of KProcess. + */ + pid_t pid_; + + /** + * The process' exit status as returned by "waitpid". You should not + * modify the value of this data member from derived classes. You should + * rather use @ref exitStatus than accessing this data member directly + * since it will probably be made private in further versions of + * KProcess. + */ + int status; + + + /** + * See setRunPrivileged() + */ + bool keepPrivs; + + /* + Functions for setting up the sockets for communication. + setupCommunication + -- is called from "start" before "fork"ing. + commSetupDoneP + -- completes communication socket setup in the parent + commSetupDoneC + -- completes communication setup in the child process + commClose + -- frees all allocated communication resources in the parent + after the process has exited + */ + + /** + * This function is called from "KProcess::start" right before a "fork" takes + * place. According to + * the "comm" parameter this function has to initialize the "in", "out" and + * "err" data member of KProcess. + * + * This function should return 0 if setting the needed communication channels + * was successful. + * + * The default implementation is to create UNIX STREAM sockets for the communication, + * but you could overload this function and establish a TCP/IP communication for + * network communication, for example. + */ + virtual int setupCommunication(Communication comm); + + /** + * Called right after a (successful) fork on the parent side. This function + * will usually do some communications cleanup, like closing the reading end + * of the "stdin" communication channel. + * + * Furthermore, it must also create the QSocketNotifiers "innot", "outnot" and + * "errnot" and connect their Qt slots to the respective KProcess member functions. + * + * For a more detailed explanation, it is best to have a look at the default + * implementation of "setupCommunication" in kprocess.cpp. + */ + virtual int commSetupDoneP(); + + /** + * Called right after a (successful) fork, but before an "exec" on the child + * process' side. It usually just closes the unused communication ends of + * "in", "out" and "err" (like the writing end of the "in" communication + * channel. + */ + virtual int commSetupDoneC(); + + + /** + * Immediately called after a process has exited. This function normally + * calls commClose to close all open communication channels to this + * process and emits the "processExited" signal (if the process was + * not running in the "DontCare" mode). + */ + virtual void processHasExited(int state); + + /** + * Should clean up the communication links to the child after it has + * exited. Should be called from "processHasExited". + */ + virtual void commClose(); + + + /** + * the socket descriptors for stdin/stdout/stderr. + */ + int out[2]; + int in[2]; + int err[2]; + + /** + * The socket notifiers for the above socket descriptors. + */ + QSocketNotifier *innot; + QSocketNotifier *outnot; + QSocketNotifier *errnot; + + /** + * Lists the communication links that are activated for the child + * process. Should not be modified from derived classes. + */ + Communication communication; + + /** + * Called by "slotChildOutput" this function copies data arriving from the + * child process's stdout to the respective buffer and emits the signal + * "@ref receivedStderr". + */ + int childOutput(int fdno); + + /** + * Called by "slotChildOutput" this function copies data arriving from the + * child process's stdout to the respective buffer and emits the signal + * "@ref receivedStderr" + */ + int childError(int fdno); + + // information about the data that has to be sent to the child: + + const char *input_data; // the buffer holding the data + int input_sent; // # of bytes already transmitted + int input_total; // total length of input_data + + /** + * @ref KProcessController is a friend of KProcess because it has to have + * access to various data members. + */ + friend class KProcessController; + + +private: + /** + * Searches for a valid shell. + * Here is the algorithm used for finding an executable shell: + * + * @li Try the executable pointed to by the "SHELL" environment + * variable with white spaces stripped off + * + * @li If your process runs with uid != euid or gid != egid, a shell + * not listed in /etc/shells will not used. + * + * @li If no valid shell could be found, "/bin/sh" is used as a last resort. + */ + QCString searchShell(); + + /** + * Used by @ref searchShell in order to find out whether the shell found + * is actually executable at all. + */ + bool isExecutable(const QCString &filename); + + // Disallow assignment and copy-construction + KProcess( const KProcess& ); + KProcess& operator= ( const KProcess& ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KProcessPrivate *d; +}; + +class KShellProcessPrivate; + +/** +* @obsolete +* +* This class is obsolete. Use KProcess and KProcess::setUseShell(true) +* instead. +* +* @short A class derived from @ref KProcess to start child +* processes through a shell. +* @author Christian Czezakte +* @version $Id$ +*/ +class KShellProcess: public KProcess +{ + Q_OBJECT + +public: + + /** + * Constructor + * + * By specifying the name of a shell (like "/bin/bash") you can override + * the mechanism for finding a valid shell as described in KProcess::searchShell() + */ + KShellProcess(const char *shellname=0); + + /** + * Destructor. + */ + ~KShellProcess(); + + /** + * Starts up the process. -- For a detailed description + * have a look at the "start" member function and the detailed + * description of @ref KProcess . + */ + virtual bool start(RunMode runmode = NotifyOnExit, + Communication comm = NoCommunication); + + /** + * This function can be used to quote an argument string such that + * the shell processes it properly. This is e. g. necessary for + * user-provided file names which may contain spaces or quotes. + * It also prevents expansion of wild cards and environment variables. + */ + static QString quote(const QString &arg); + +private: + + QCString shell; + + // Disallow assignment and copy-construction + KShellProcess( const KShellProcess& ); + KShellProcess& operator= ( const KShellProcess& ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KShellProcessPrivate *d; +}; + + + +#endif + diff --git a/noncore/net/networksetup/main.cpp b/noncore/net/networksetup/main.cpp new file mode 100644 index 0000000..52cb92b --- a/dev/null +++ b/noncore/net/networksetup/main.cpp @@ -0,0 +1,13 @@ +#include "mainwindowimp.h" +#include + +int main(int argc, char **argv) +{ + QPEApplication app(argc, argv); + MainWindowImp window; + window.showMaximized(); + return app.exec(); +} + +// main.cpp + diff --git a/noncore/net/networksetup/mainwindow.ui b/noncore/net/networksetup/mainwindow.ui new file mode 100644 index 0000000..b8c0675 --- a/dev/null +++ b/noncore/net/networksetup/mainwindow.ui @@ -0,0 +1,321 @@ + +MainWindow + + QWidget + + name + MainWindow + + + geometry + + 0 + 0 + 222 + 289 + + + + caption + Network Setup + + + + margin + 0 + + + spacing + 6 + + + QTabWidget + + name + tabWidget + + + layoutMargin + + + QWidget + + name + Widget3 + + + title + Interfaces + + + + margin + 0 + + + spacing + 6 + + + QListView + + + text + i + + + clickable + true + + + resizeable + true + + + + + text + t + + + clickable + true + + + resizeable + true + + + + + text + Name + + + clickable + true + + + resizeable + true + + + + name + serviceList + + + allColumnsShowFocus + true + + + + QLayoutWidget + + name + Layout2 + + + layoutMargin + + + + margin + 5 + + + spacing + 6 + + + QPushButton + + name + addServiceButton + + + text + &Add + + + + QPushButton + + name + informationServiceButton + + + text + &Information + + + + QPushButton + + name + configureServiceButton + + + text + &Configure + + + + QPushButton + + name + removeServiceButton + + + text + &Remove + + + + + + + + QWidget + + name + tab + + + title + Profiles + + + + margin + 11 + + + spacing + 6 + + + QLabel + + name + TextLabel3 + + + text + Change Profile To + + + + QLabel + + name + TextLabel1 + + + text + Current Profile + + + + QLabel + + name + TextLabel2 + + + frameShape + Panel + + + frameShadow + Sunken + + + text + All + + + + QComboBox + + + text + All + + + + name + ComboBox10 + + + + QPushButton + + name + removeProfileButton + + + text + &Remove + + + + QPushButton + + name + newProfileButton + + + text + &New + + + + + name + Spacer16 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + + + + + QWidget +
qwidget.h
+ + 100 + 100 + + 0 + + 7 + 7 + + image0 +
+
+ + + image0 + 789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758 + + +
diff --git a/noncore/net/networksetup/mainwindowimp.cpp b/noncore/net/networksetup/mainwindowimp.cpp new file mode 100644 index 0000000..3c13143 --- a/dev/null +++ b/noncore/net/networksetup/mainwindowimp.cpp @@ -0,0 +1,308 @@ +#include "mainwindowimp.h" +#include "addserviceimp.h" +#include "interfaceinformationimp.h" +#include "interfacesetupimp.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +// For library loading. +#include + +#define TEMP_ALL "/tmp/ifconfig-a" +#define TEMP_UP "/tmp/ifconfig" + +#define NO_SELECT_ERROR_AND_RETURN { \ + QMessageBox::information(this, "Error","Please select an interface.", "Ok"); \ + return; \ +} + +MainWindowImp::MainWindowImp(QWidget *parent, const char *name) : MainWindow(parent, name, true) { + connect(addServiceButton, SIGNAL(clicked()), this, SLOT(addClicked())); + connect(removeServiceButton, SIGNAL(clicked()), this, SLOT(removeClicked())); + connect(informationServiceButton, SIGNAL(clicked()), this, SLOT(informationClicked())); + connect(configureServiceButton, SIGNAL(clicked()), this, SLOT(configureClicked())); + // Make sure we have a plugin directory to scan. + QString DirStr = QDir::homeDirPath() + "/.networksetup/" ; + QDir pluginDir( DirStr ); + pluginDir.mkdir( DirStr ); + pluginDir.mkdir( ( DirStr + "plugins/" ) ); + QString path = DirStr + "plugins"; + pluginDir.setPath(path); + if(!pluginDir.exists()){ + qDebug(QString("MainWindowImp: ERROR: %1 %2").arg(__FILE__).arg(__LINE__).latin1()); + return; + } + + // Load any saved services. + loadModules(path); + getInterfaceList(); + serviceList->header()->hide(); +} + +/** + * Deconstructor. Unload libraries and save. + */ +MainWindowImp::~MainWindowImp(){ +} + +void MainWindowImp::loadModules(QString path){ +} + +/** + * Attempt to load a function and resolve a function. + * @param pluginFileName - the name of the file in which to attempt to load + * @param resolveString - function pointer to resolve + * @return pointer to the function with name resolveString or NULL + */ +Module* MainWindowImp::loadPlugin(QString pluginFileName, QString resolveString){ + //qDebug(pluginFileName.latin1()); + QLibrary *lib = new QLibrary(pluginFileName); + void *functionPointer = lib->resolve(resolveString); + if( !functionPointer ){ + qDebug(QString("MainWindowImp: File: %1 is not a plugin, but though was.").arg(pluginFileName).latin1()); + delete lib; + return NULL; + } + + // Try to get an object. + Module *object = ((Module* (*)()) functionPointer)(); + if(object == NULL){ + qDebug("MainWindowImp: Couldn't create object, but did load library!"); + delete lib; + return NULL; + } + + // Store for reference + libraries.insert(object, lib); + return object; +} + +/* +QList MainWindowImp::retrieveUnloadedPluginList(){ + QString DirStr = QDir::homeDirPath() + "/.networksetup/" ; + QString path = DirStr + "plugins"; + QDir d(path); + d.setFilter( QDir::Files | QDir::Hidden ); + + QMap::Iterator libraryIt; + QList rlist; + rlist.setAutoDelete(false); + + const QFileInfoList *list = d.entryInfoList(); + QFileInfoListIterator it( *list ); + QFileInfo *fi; + while ( (fi=it.current()) ) { + if(fi->fileName().contains(".so")){ + for( libraryIt = libraries.begin(); libraryIt != libraries.end(); ++libraryIt ) + if((path + "/" + fi->fileName()) != (libraryIt.data())->library()){ + QString *s = new QString(path + "/" + fi->fileName()); + rlist.append(s); + } + } + ++it; + } + return rlist; +} +*/ + +/** + * The Add button was clicked. Bring up the add dialog and if OK is hit + * load the plugin and append it to the list + */ +void MainWindowImp::addClicked(){ + // Now that we have a list of all of the protocals, list them. + { + QMessageBox::information(this, "No Modules", "Nothing to add.", "Ok"); + return; + } + AddServiceImp service(this, "AddService", true); + service.showMaximized(); + service.exec(); +} + +/** + * Prompt the user to see if they really want to do this. + * If they do then remove from the list and unload. + */ +void MainWindowImp::removeClicked(){ + QListViewItem *item = serviceList->currentItem(); + if(item == NULL) NO_SELECT_ERROR_AND_RETURN + + if(modules.find(interfaceItems[item]) == modules.end()){ + QMessageBox::information(this, "Can't remove interface.", "Interface is built in.", "Ok"); + } + else{ + // Try to remove. + } + +} + +/** + * See if there is a configuration for the selected protocal. + * Prompt with errors. + */ +void MainWindowImp::configureClicked(){ + QListViewItem *item = serviceList->currentItem(); + if(item == NULL) NO_SELECT_ERROR_AND_RETURN + + if(modules.find(interfaceItems[item]) == modules.end()){ + InterfaceSetupImp *conf = new InterfaceSetupImp(0, "InterfaceConfiguration", interfaceItems[item]); + conf->showMaximized(); + conf->show(); + } + else{ + InterfaceSetupImp *conf = new InterfaceSetupImp(this, "InterfaceConfiguration"); + conf->show(); + } +} + +/** + * Pull up the information about the selected interface + * Report an error + */ +void MainWindowImp::informationClicked(){ + QListViewItem *item = serviceList->currentItem(); + if(item == NULL)NO_SELECT_ERROR_AND_RETURN + + if(modules.find(interfaceItems[item]) == modules.end()){ + InterfaceInformationImp *i = new InterfaceInformationImp(0, "InterfaceInformationImp", interfaceItems[item]); + i->showMaximized(); + i->show(); + } + else{ + QTabWidget *t = new QTabWidget(this, "InterfaceInformationTAB"); + InterfaceInformationImp *i = new InterfaceInformationImp(t, "TCPIPInformation", interfaceItems[item], true); + t->insertTab(i, "TCP/IP"); + t->show(); + } +} + +/** + * Aquire the list of active interfaces from ifconfig + * Call ifconfig and ifconfig -a + */ +void MainWindowImp::getInterfaceList(){ + KShellProcess *processAll = new KShellProcess(); + *processAll << "/sbin/ifconfig" << "-a" << " > " TEMP_ALL; + connect(processAll, SIGNAL(processExited(KProcess *)), + this, SLOT(jobDone(KProcess *))); + threads.insert(processAll, TEMP_ALL); + processAll->start(KShellProcess::NotifyOnExit); + + KShellProcess *process = new KShellProcess(); + *process << "/sbin/ifconfig" << " > " TEMP_UP; + connect(process, SIGNAL(processExited(KProcess *)), + this, SLOT(jobDone(KProcess *))); + threads.insert(process, TEMP_UP); + process->start(KShellProcess::NotifyOnExit); +} + +void MainWindowImp::jobDone(KProcess *process){ + QString fileName = threads[process]; + threads.remove(process); + delete process; + + QFile file(fileName); + if (!file.open(IO_ReadOnly)){ + qDebug(QString("MainWindowImp: Can't open file: %1").arg(fileName).latin1()); + return; + } + + QTextStream stream( &file ); + QString line; + while ( !stream.eof() ) { + line = stream.readLine(); + int space = line.find(" "); + if(space > 1){ + // We have found an interface + QString interfaceName = line.mid(0, space); + Interface *i; + // See if we already have it + if(interfaceNames.find(interfaceName) == interfaceNames.end()){ + if(fileName == TEMP_ALL) + i = new Interface(interfaceName, false); + else + i = new Interface(interfaceName, true); + } + else{ + i = interfaceNames[interfaceName]; + if(fileName != TEMP_ALL) + i->setStatus(true); + } + + i->setAttached(true); + i->setInterfaceName(interfaceName); + + QString hardName = "Ethernet"; + int hardwareName = line.find("Link encap:"); + int macAddress = line.find("HWaddr"); + if(macAddress == -1) + macAddress = line.length(); + if(hardwareName != -1) + i->setHardwareName(line.mid(hardwareName+11, macAddress-(hardwareName+11))); + // We have found an interface + //qDebug(QString("MainWindowImp: Found Interface: %1").arg(line).latin1()); + interfaceNames.insert(i->getInterfaceName(), i); + updateInterface(i); + } + } + file.close(); + QFile::remove(fileName); +} + +void MainWindowImp::updateInterface(Interface *i){ + QListViewItem *item = NULL; + + // See if we already have it + if(items.find(i) == items.end()){ + item = new QListViewItem(serviceList, "", "", ""); + // See if you can't find a module owner for this interface + //EmployeeMap::Iterator it; + //for( it = map.begin(); it != map.end(); ++it ) + // printf( "%s, %s earns %d\n", it.key().latin1(), it.data().name().latin1(), it.data().salary() ); + + items.insert(i, item); + interfaceItems.insert(item, i); + } + else + item = items[i]; + + QString statusImage = "down"; + if(i->getStatus()) + statusImage = "up"; + QPixmap status = (Resource::loadPixmap(statusImage)); + item->setPixmap(0, status); + + QString typeName = "lan"; + if(i->getHardwareName().contains("Local Loopback")) + typeName = "lo"; + QPixmap type = (Resource::loadPixmap(typeName)); + item->setPixmap(1, type); + + item->setText(2, i->getHardwareName()); + +} + +void MainWindowImp::addProfile(){ + +} + +void MainWindowImp::removeProfile(){ + +} + +// mainwindowimp.cpp + diff --git a/noncore/net/networksetup/mainwindowimp.h b/noncore/net/networksetup/mainwindowimp.h new file mode 100644 index 0000000..95ec2a1 --- a/dev/null +++ b/noncore/net/networksetup/mainwindowimp.h @@ -0,0 +1,53 @@ +#ifndef MAINWINOWIMP_H +#define MAINWINOWIMP_H + +#include "mainwindow.h" +#include "module.h" +#include "interface.h" +#include "kprocess.h" +#include + +class QLibrary; + +class MainWindowImp : public MainWindow { + Q_OBJECT + +public: + MainWindowImp(QWidget *parent=0, const char *name=0); + ~MainWindowImp(); + +private slots: + void addClicked(); + void removeClicked(); + void configureClicked(); + void informationClicked(); + + void jobDone(KProcess *process); + void getInterfaceList(); + + void addProfile(); + void removeProfile(); + + void updateInterface(Interface *i); + +private: + void loadModules(QString path); + + Module* loadPlugin(QString pluginFileName, + QString resolveString = "create_plugin"); + + // For our local list of names + QMap interfaceNames; + + QMap libraries; + QMap modules; + QMap items; + QMap interfaceItems; + + QMap threads; +}; + +#endif + +// mainwindowimp.h + diff --git a/noncore/net/networksetup/module.h b/noncore/net/networksetup/module.h new file mode 100644 index 0000000..f146d8c --- a/dev/null +++ b/noncore/net/networksetup/module.h @@ -0,0 +1,33 @@ +#ifndef MODULE_H +#define MODULE_H + +#include +#include +#include +#include "interface.h" + +class QWidget; + +class Module : QObject{ + +signals: + void updateInterface(Interface *i); + +public: + Module(){}; + + virtual bool isOwner(Interface *){ return false; }; + virtual QWidget *configure(){ return NULL; } ; + virtual QWidget *information(){ return NULL; }; + virtual QList getInterfaces() = 0; + virtual QMap possibleNewInterfaces() = 0; + virtual Interface *addNewInterface(QString name) = 0; + virtual bool remove(Interface* i) = 0; + + +}; + +#endif + +// module.h + diff --git a/noncore/net/networksetup/networksetup.pro b/noncore/net/networksetup/networksetup.pro new file mode 100644 index 0000000..7d9918b --- a/dev/null +++ b/noncore/net/networksetup/networksetup.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +CONFIG = qt warn_on debug +#CONFIG = qt warn_on release +HEADERS = mainwindowimp.h addserviceimp.h interface.h interfaceinformationimp.h interfacesetupimp.h interfaces.h defaultmodule.h kprocctrl.h module.h kprocess.h +SOURCES = main.cpp mainwindowimp.cpp addserviceimp.cpp interface.cpp interfaceinformationimp.cpp interfacesetupimp.cpp kprocctrl.cpp kprocess.cpp interfaces.cpp +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe +INTERFACES = mainwindow.ui addservice.ui interfaceinformation.ui interfaceadvanced.ui interfacesetup.ui +TARGET = networksetup diff --git a/noncore/net/networksetup/systemadvanced.ui b/noncore/net/networksetup/systemadvanced.ui new file mode 100644 index 0000000..6ea192c --- a/dev/null +++ b/noncore/net/networksetup/systemadvanced.ui @@ -0,0 +1,443 @@ + +SystemNetworking + + QWidget + + name + SystemNetworking + + + geometry + + 0 + 0 + 222 + 289 + + + + caption + System Networking + + + + margin + 0 + + + spacing + 6 + + + QTabWidget + + name + tabWidget + + + layoutMargin + + + QWidget + + name + tab + + + title + DNS + + + + margin + 11 + + + spacing + 6 + + + QLabel + + name + TextLabel6 + + + text + Hostname + + + + QLabel + + name + TextLabel5 + + + text + DNS + + + alignment + AlignTop|AlignLeft + + + vAlign + + + + QListBox + + name + ListBox5 + + + + QLineEdit + + name + LineEdit7 + + + + QLabel + + name + TextLabel7 + + + text + Hosts + + + + QLabel + + name + TextLabel9 + + + text + List here.... + + + + QPushButton + + name + PushButton15 + + + text + &Add + + + + QPushButton + + name + PushButton16 + + + text + &Delete + + + + + name + Spacer14 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + QWidget + + name + tab + + + title + Routing + + + + margin + 11 + + + spacing + 6 + + + QListView + + + text + Destination + + + clickable + true + + + resizeable + true + + + + + text + Gateway + + + clickable + true + + + resizeable + true + + + + + text + Genmask + + + clickable + true + + + resizeable + true + + + + + text + Flags + + + clickable + true + + + resizeable + true + + + + + text + Metric + + + clickable + true + + + resizeable + true + + + + + text + Ref + + + clickable + true + + + resizeable + true + + + + + text + Use + + + clickable + true + + + resizeable + true + + + + + text + Iface + + + clickable + true + + + resizeable + true + + + + + text + 192.168.1.0 + + + text + * + + + text + 255.255.255.0 + + + text + U + + + text + 0 + + + text + 0 + + + text + 0 + + + text + eth0 + + + pixmap + + + + pixmap + + + + pixmap + + + + pixmap + + + + pixmap + + + + pixmap + + + + pixmap + + + + pixmap + + + + + name + ListView4 + + + + QPushButton + + name + PushButton17 + + + text + &Add + + + + QPushButton + + name + PushButton18 + + + text + Remove + + + + + name + Spacer15 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + + + + + QWidget +
qwidget.h
+ + 100 + 100 + + 0 + + 7 + 7 + + image0 +
+
+ + + image0 + 789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758 + + +
diff --git a/noncore/settings/networksettings/TODO b/noncore/settings/networksettings/TODO new file mode 100644 index 0000000..9a1657a --- a/dev/null +++ b/noncore/settings/networksettings/TODO @@ -0,0 +1 @@ +Fix DHCP obtained and expoired info diff --git a/noncore/settings/networksettings/addservice.ui b/noncore/settings/networksettings/addservice.ui new file mode 100644 index 0000000..929f4fb --- a/dev/null +++ b/noncore/settings/networksettings/addservice.ui @@ -0,0 +1,154 @@ + +AddService + + QDialog + + name + AddService + + + geometry + + 0 + 0 + 245 + 268 + + + + caption + Add Network Service + + + + margin + 11 + + + spacing + 6 + + + QPushButton + + name + cancelButton + + + text + Cancel + + + + QPushButton + + name + addButton + + + text + Add + + + + QListView + + + text + Services + + + clickable + true + + + resizeable + true + + + + name + registeredServicesList + + + sizePolicy + + 7 + 3 + + + + minimumSize + + 0 + 75 + + + + + + name + Spacer12 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QLabel + + name + help + + + sizePolicy + + 5 + 4 + + + + text + LAN - TCP/IP +For Local-area network connections through PC_CARD network interfdace cards. + + + alignment + WordBreak|AlignTop|AlignLeft + + + vAlign + + + wordwrap + + + + + + + cancelButton + clicked() + AddService + reject() + + + addButton + clicked() + AddService + accept() + + + diff --git a/noncore/settings/networksettings/addserviceimp.cpp b/noncore/settings/networksettings/addserviceimp.cpp new file mode 100644 index 0000000..ac79d06 --- a/dev/null +++ b/noncore/settings/networksettings/addserviceimp.cpp @@ -0,0 +1,26 @@ +#include "addserviceimp.h" +#include +#include +#include + +void AddServiceImp::addServices(QList list){ + list.setAutoDelete(true); + + for(uint i = 0; i < list.count(); i++){ + QString pluginFileName = ""; + QLibrary *lib = new QLibrary(pluginFileName); + void *functionPointer = lib->resolve("info"); + if( !functionPointer ){ + qDebug(QString("AddServiceImp: File: %1 is not a plugin, but though was.").arg(pluginFileName).latin1()); + delete lib; + break; + } + + // Try to get an info. + QString info = ((QString (*)()) functionPointer)(); + QListViewItem *newItem = new QListViewItem(registeredServicesList, info); + } +} + + +// addserviceimp.cpp diff --git a/noncore/settings/networksettings/addserviceimp.h b/noncore/settings/networksettings/addserviceimp.h new file mode 100644 index 0000000..7cacb97 --- a/dev/null +++ b/noncore/settings/networksettings/addserviceimp.h @@ -0,0 +1,26 @@ +#ifndef ADDSERVICEIMP_H +#define ADDSERVICEIMP_H + +#include "addservice.h" +#include +#include + +class QListViewItem; + +class AddServiceImp : public AddService { + +Q_OBJECT + +public: + AddServiceImp(QWidget *parent=0, const char *name=0, WFlags f=0):AddService(parent, name, f){}; + void addServices(QList list); + +private: + QMap pluginInfo; + +}; + +#endif + +// addserviceimp.h + diff --git a/noncore/settings/networksettings/defaultmodule.h b/noncore/settings/networksettings/defaultmodule.h new file mode 100644 index 0000000..c7791d5 --- a/dev/null +++ b/noncore/settings/networksettings/defaultmodule.h @@ -0,0 +1,26 @@ +#ifndef MODULE_H +#define MODULE_H + +#include "module.h" + +class QWidget; + +class DefaultModule : Module{ + +public: + DefaultModule(){}; + + virtual bool isOwner(Interface *i); + virtual QWidget *configure(); + virtual QWidget *information()}; + virtual QList getInterfaces(); + virtual QMap possibleNewInterfaces(); + virtual Interface *addNewInterface(QString name); + virtual bool remove(Interface* i); + +}; + +#endif + +// module.h + diff --git a/noncore/settings/networksettings/interface.cpp b/noncore/settings/networksettings/interface.cpp new file mode 100644 index 0000000..b9b09ad --- a/dev/null +++ b/noncore/settings/networksettings/interface.cpp @@ -0,0 +1,236 @@ +#include "interface.h" +#include +#include +#include +#include + +#define IFCONFIG "/sbin/ifconfig" +#define HDCP_INFO_DIR "/etc/dhcpc" + +#include +#include + +Interface::Interface(QString name, bool newSatus): status(newSatus), attached(false), interfaceName(name), hardareName("Unknown"), moduleOwner("Default"), macAddress(""), ip("0.0.0.0"), broadcast(""), subnetMask("0.0.0.0"), dhcp(false){ + refresh(); +} + +/** + * Try to start the interface. + * @return bool true if successfull. + */ +bool Interface::start(){ + // check to see if we are already running. + if(status) + return false; + + int ret = system(QString("%1 %2 up").arg(IFCONFIG).arg(interfaceName).latin1()); + if(ret != 0) + return false; + + status = true; + refresh(); + return true; +} + +/** + * Try to stop the interface. + * @return bool true if successfull. + */ +bool Interface::stop(){ + // check to see if we are already stopped. + if(status == false) + return false; + + int ret = system(QString("%1 %2 down").arg(IFCONFIG).arg(interfaceName).latin1()); + if(ret != 0) + return false; + + status = true; + refresh(); + return true; +} +/** + * Try to restart the interface. + * @return bool true if successfull. + */ +bool Interface::restart(){ + return (stop() && start()); +} + +/** + * Try to refresh the information about the interface. + * First call ifconfig, then check the dhcp-info file + * @return bool true if successfull. + */ +bool Interface::refresh(){ + // See if we are up. + if(status == false){ + macAddress = ""; + ip = "0.0.0.0"; + subnetMask = "0.0.0.0"; + broadcast = ""; + dhcp = false; + dhcpServerIp = ""; + leaseObtained = ""; + leaseExpires = ""; + return true; + } + + QString fileName = QString("/tmp/%1_ifconfig_info").arg(interfaceName); + int ret = system(QString("%1 %2 > %3").arg(IFCONFIG).arg(interfaceName).arg(fileName).latin1()); + if(ret != 0){ + qDebug(QString("Interface: Ifconfig return value: %1, is not 0").arg(ret).latin1()); + return false; + } + + QFile file(fileName); + if (!file.open(IO_ReadOnly)){ + qDebug(QString("Interface: Can't open file: %1").arg(fileName).latin1()); + return false; + } + + // Set to the defaults + macAddress = ""; + ip = "0.0.0.0"; + subnetMask = "0.0.0.0"; + broadcast = ""; + + QTextStream stream( &file ); + QString line; + while ( !stream.eof() ) { + line = stream.readLine(); + if(line.contains("HWaddr")){ + int mac = line.find("HWaddr"); + macAddress = line.mid(mac+7, line.length()); + } + if(line.contains("inet addr")){ + int ipl = line.find("inet addr"); + int space = line.find(" ", ipl+10); + ip = line.mid(ipl+10, space-ipl-10); + } + if(line.contains("Mask")){ + int mask = line.find("Mask"); + subnetMask = line.mid(mask+5, line.length()); + } + if(line.contains("Bcast")){ + int mask = line.find("Bcast"); + int space = line.find(" ", mask+6); + broadcast = line.mid(mask+6, space-mask-6); + } + } + file.close(); + QFile::remove(fileName); + + // DHCP TESTING + // reset DHCP info + dhcpServerIp = ""; + leaseObtained = ""; + leaseExpires = ""; + dhcp = false; + + // See if we have + QString dhcpFile(QString(HDCP_INFO_DIR "/dhcpcd-%1.info").arg(interfaceName)); + // If there is no DHCP information then exit now with no errors. + if(!QFile::exists(dhcpFile)){ + return true; + } + + file.setName(dhcpFile); + if (!file.open(IO_ReadOnly)){ + qDebug(QString("Interface: Can't open file: %1").arg(dhcpFile).latin1()); + return false; + } + + // leaseTime and renewalTime and used if pid and deamon exe can be accessed. + int leaseTime = 0; + int renewalTime = 0; + + stream.setDevice( &file ); + while ( !stream.eof() ) { + line = stream.readLine(); + if(line.contains("DHCPSID=")) + dhcpServerIp = line.mid(8, line.length()); + if(line.contains("LEASETIME=")) + leaseTime = line.mid(10, line.length()).toInt(); + if(line.contains("RENEWALTIME=")) + renewalTime = line.mid(12, line.length()).toInt(); + } + file.close(); + //qDebug(QString("Interface: leaseTime: %1").arg(leaseTime).latin1()); + //qDebug(QString("Interface: renewalTime: %1").arg(renewalTime).latin1()); + + // Get the pid of the deamond + dhcpFile = (QString(HDCP_INFO_DIR "/dhcpcd-%1.pid").arg(interfaceName)); + file.setName(dhcpFile); + if (!file.open(IO_ReadOnly)){ + qDebug(QString("Interface: Can't open file: %1").arg(dhcpFile).latin1()); + return false; + } + + int pid = -1; + stream.setDevice( &file ); + while ( !stream.eof() ) { + line = stream.readLine(); + pid = line.toInt(); + } + file.close(); + + if( pid == -1){ + qDebug("Interface: Could not get pid of dhcpc deamon."); + return false; + } + + // Get the start running time of the deamon + fileName = (QString("/proc/%1/stat").arg(pid)); + file.setName(fileName); + stream.setDevice( &file ); + if (!file.open(IO_ReadOnly)){ + qDebug(QString("Interface: Can't open file: %1").arg(fileName).latin1()); + return false; + } + while ( !stream.eof() ) { + line = stream.readLine(); + } + file.close(); + long time = 0; + // Grab the start time + // pid com state ppid pgrp session tty_nr tpgid flags + int r = sscanf(line.latin1(), "%*d %*s %*c %*d %*d %*d %*d %*d %*u " + // minflt cminflt majflt cmajflt utime stime cutime cstime priority + "%*u %*u %*u %*u %*u %*u %*d %*d %*d " + // nice 0 itrealvalue starttime + "%*d %*d %*d %lu", (long*) &time); + time = time/100; + + QDateTime datetime(QDateTime::currentDateTime()); + + // Get the uptime of the computer. + QFile f("/proc/uptime"); + if ( f.open(IO_ReadOnly) ) { // file opened successfully + QTextStream t( &f ); // use a text stream + int sec = 0; + t >> sec; + datetime = datetime.addSecs((-1*sec)); + f.close(); + } + else{ + qDebug("Interface: Can't open /proc/uptime to retrive uptime."); + return false; + } + + datetime = datetime.addSecs(time); + //qDebug(QString("Interface: %1 %2").arg(datetime.toString()).arg(pid).latin1()); + + // Calculate the start and renew times + leaseObtained = datetime.toString(); + + // Calculate the start and renew times + datetime = datetime.addSecs(leaseTime); + leaseExpires = datetime.toString(); + + dhcp = true; + return true; +} + +// interface.cpp + diff --git a/noncore/settings/networksettings/interface.h b/noncore/settings/networksettings/interface.h new file mode 100644 index 0000000..1ad71eb --- a/dev/null +++ b/noncore/settings/networksettings/interface.h @@ -0,0 +1,65 @@ +#ifndef INTERFACE_H +#define INTERFACE_H + +#include + +class Interface { + +public: + Interface(QString name = "unknown", bool status = false); + virtual ~Interface(){}; + + virtual bool getStatus(){ return status; }; + virtual void setStatus(bool newSatus){ status = newSatus; refresh(); }; + + virtual bool isAttached(){ return attached; }; + virtual void setAttached(bool isAttached=false){ attached = isAttached; }; + + virtual QString getInterfaceName(){ return interfaceName; }; + virtual void setInterfaceName(QString name="unknown"){ interfaceName = name; }; + + virtual QString getHardwareName(){ return hardareName; }; + virtual void setHardwareName(QString name="Unknown"){ hardareName = name; }; + + virtual QString getModuleOwner(){ return moduleOwner; }; + virtual void setModuleOwner(QString owner="Default"){ moduleOwner = owner; }; + + // inet information. + QString getMacAddress(){ return macAddress; }; + QString getIp(){ return ip; }; + QString getSubnetMask(){ return subnetMask; }; + QString getBroadcast(){ return broadcast; }; + bool isDhcp(){ return dhcp; }; + QString getDhcpServerIp(){ return dhcpServerIp; }; + QString getLeaseObtained(){ return leaseObtained; }; + QString getLeaseExpires(){ return leaseExpires; }; + + bool refresh(); + bool start(); + bool stop(); + bool restart(); + +private: + // Interface information + bool status; + bool attached; + QString interfaceName; + QString hardareName; + QString moduleOwner; + + // Network information + QString macAddress; + QString ip; + QString broadcast; + QString subnetMask; + bool dhcp; + QString dhcpServerIp; + QString leaseObtained; + QString leaseExpires; + +}; + +#endif + +// interface.h + diff --git a/noncore/settings/networksettings/interfaceadvanced.ui b/noncore/settings/networksettings/interfaceadvanced.ui new file mode 100644 index 0000000..8ef0b29 --- a/dev/null +++ b/noncore/settings/networksettings/interfaceadvanced.ui @@ -0,0 +1,323 @@ + +InterfaceAdvanced + + QWidget + + name + InterfaceAdvanced + + + geometry + + 0 + 0 + 197 + 253 + + + + caption + Advanced Interface Information + + + + margin + 11 + + + spacing + 6 + + + QLabel + + name + TextLabel1 + + + text + MAC Address + + + + QLabel + + name + interfaceName + + + frameShape + Panel + + + frameShadow + Sunken + + + text + eth0 + + + + QLabel + + name + TextLabel3 + + + text + IP Address + + + + QLabel + + name + macAddressLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + 00:00:00:00:00:00 + + + + QLabel + + name + TextLabel7 + + + text + Interface + + + + QLabel + + name + TextLabel9 + + + text + Lease Expires + + + + QLabel + + name + leaseExpiresLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + + + + + QLabel + + name + leaseObtainedLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + + + + + QLabel + + name + TextLabel8 + + + text + Lease Obtained + + + + QLabel + + name + dhcpServerLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + 255.255.255.255 + + + + QLabel + + name + TextLabel6 + + + text + DHCP Server + + + + QLabel + + name + TextLabel4 + + + text + Subnet Mask + + + + QLabel + + name + ipAddressLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + 0.0.0.0 + + + + QLabel + + name + subnetMaskLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + 0.0.0.0 + + + + + name + Spacer2 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QLabel + + name + TextLabel2 + + + text + Broadcast + + + + QLabel + + name + broadcastLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + + Line + + name + Line2 + + + orientation + Horizontal + + + + + + + QWidget +
qwidget.h
+ + 100 + 100 + + 0 + + 7 + 7 + + image0 +
+
+ + + image0 + 789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523250004143a55a6b2e0026630c4f + + +
diff --git a/noncore/settings/networksettings/interfaceedit.cpp b/noncore/settings/networksettings/interfaceedit.cpp new file mode 100644 index 0000000..25599ef --- a/dev/null +++ b/noncore/settings/networksettings/interfaceedit.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** Form implementation generated from reading ui file 'interfaceedit.ui' +** +** Created: Mon Sep 23 12:18:55 2002 +** by: The User Interface Compiler (uic) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ +#include "interfaceedit.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "qwidget.h" +#include +#include +#include +#include + +/* + * Constructs a InterfaceConfiguration which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + */ +InterfaceConfiguration::InterfaceConfiguration( QWidget* parent, const char* name, WFlags fl ) + : QWidget( parent, name, fl ) +{ + if ( !name ) + setName( "InterfaceConfiguration" ); + resize( 177, 306 ); + setCaption( tr( "Interface Configuration" ) ); + InterfaceConfigurationLayout = new QGridLayout( this ); + InterfaceConfigurationLayout->setSpacing( 6 ); + InterfaceConfigurationLayout->setMargin( 11 ); + + profile = new QComboBox( FALSE, this, "profile" ); + profile->insertItem( tr( "All" ) ); + + InterfaceConfigurationLayout->addWidget( profile, 2, 1 ); + + TextLabel1 = new QLabel( this, "TextLabel1" ); + TextLabel1->setText( tr( "Profile:" ) ); + + InterfaceConfigurationLayout->addWidget( TextLabel1, 2, 0 ); + + Line1 = new QFrame( this, "Line1" ); + Line1->setFrameStyle( QFrame::HLine | QFrame::Sunken ); + + InterfaceConfigurationLayout->addMultiCellWidget( Line1, 1, 1, 0, 1 ); + + CheckBox3 = new QCheckBox( this, "CheckBox3" ); + CheckBox3->setText( tr( "Automaticly bring up" ) ); + + InterfaceConfigurationLayout->addMultiCellWidget( CheckBox3, 0, 0, 0, 1 ); + + dhcpCheckBox = new QCheckBox( this, "dhcpCheckBox" ); + dhcpCheckBox->setText( tr( "DHCP" ) ); + + InterfaceConfigurationLayout->addMultiCellWidget( dhcpCheckBox, 3, 3, 0, 1 ); + + TextLabel3_3_2 = new QLabel( this, "TextLabel3_3_2" ); + TextLabel3_3_2->setText( tr( "Lease Hours" ) ); + + InterfaceConfigurationLayout->addWidget( TextLabel3_3_2, 4, 0 ); + + SpinBox1_2 = new QSpinBox( this, "SpinBox1_2" ); + SpinBox1_2->setMaxValue( 336 ); + SpinBox1_2->setMinValue( 1 ); + SpinBox1_2->setValue( 24 ); + + InterfaceConfigurationLayout->addWidget( SpinBox1_2, 4, 1 ); + QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding ); + InterfaceConfigurationLayout->addItem( spacer, 11, 1 ); + + TextLabel4 = new QLabel( this, "TextLabel4" ); + TextLabel4->setText( tr( "IP Address" ) ); + + InterfaceConfigurationLayout->addWidget( TextLabel4, 6, 0 ); + + ipAddressEdit = new QLineEdit( this, "ipAddressEdit" ); + + InterfaceConfigurationLayout->addWidget( ipAddressEdit, 6, 1 ); + + TextLabel5 = new QLabel( this, "TextLabel5" ); + TextLabel5->setText( tr( "Subnet Mask" ) ); + + InterfaceConfigurationLayout->addWidget( TextLabel5, 7, 0 ); + + firstDNSLineEdit = new QLineEdit( this, "firstDNSLineEdit" ); + + InterfaceConfigurationLayout->addWidget( firstDNSLineEdit, 9, 1 ); + + TextLabel3 = new QLabel( this, "TextLabel3" ); + TextLabel3->setText( tr( "Second DNS" ) ); + + InterfaceConfigurationLayout->addWidget( TextLabel3, 10, 0 ); + + subnetMaskEdit = new QLineEdit( this, "subnetMaskEdit" ); + + InterfaceConfigurationLayout->addWidget( subnetMaskEdit, 7, 1 ); + + gatewayEdit = new QLineEdit( this, "gatewayEdit" ); + + InterfaceConfigurationLayout->addWidget( gatewayEdit, 8, 1 ); + + TextLabel7 = new QLabel( this, "TextLabel7" ); + TextLabel7->setText( tr( "Gateway" ) ); + + InterfaceConfigurationLayout->addWidget( TextLabel7, 8, 0 ); + + TextLabel2 = new QLabel( this, "TextLabel2" ); + TextLabel2->setText( tr( "First DNS" ) ); + + InterfaceConfigurationLayout->addWidget( TextLabel2, 9, 0 ); + + secondDNSLineEdit = new QLineEdit( this, "secondDNSLineEdit" ); + + InterfaceConfigurationLayout->addWidget( secondDNSLineEdit, 10, 1 ); + + GroupBox2 = new QGroupBox( this, "GroupBox2" ); + GroupBox2->setTitle( tr( "Static Ip Configuration" ) ); + + InterfaceConfigurationLayout->addMultiCellWidget( GroupBox2, 5, 5, 0, 1 ); + + // signals and slots connections + connect( dhcpCheckBox, SIGNAL( toggled(bool) ), SpinBox1_2, SLOT( setEnabled(bool) ) ); + connect( dhcpCheckBox, SIGNAL( toggled(bool) ), GroupBox2, SLOT( setDisabled(bool) ) ); +} + +/* + * Destroys the object and frees any allocated resources + */ +InterfaceConfiguration::~InterfaceConfiguration() +{ + // no need to delete child widgets, Qt does it all for us +} + diff --git a/noncore/settings/networksettings/interfaceedit.h b/noncore/settings/networksettings/interfaceedit.h new file mode 100644 index 0000000..a65c030 --- a/dev/null +++ b/noncore/settings/networksettings/interfaceedit.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** Form interface generated from reading ui file 'interfaceedit.ui' +** +** Created: Mon Sep 23 12:18:55 2002 +** by: The User Interface Compiler (uic) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ +#ifndef INTERFACECONFIGURATION_H +#define INTERFACECONFIGURATION_H + +#include +#include +class QVBoxLayout; +class QHBoxLayout; +class QGridLayout; +class QCheckBox; +class QComboBox; +class QFrame; +class QGroupBox; +class QLabel; +class QLineEdit; +class QSpinBox; + +class InterfaceConfiguration : public QWidget +{ + Q_OBJECT + +public: + InterfaceConfiguration( QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~InterfaceConfiguration(); + + QComboBox* profile; + QLabel* TextLabel1; + QFrame* Line1; + QCheckBox* CheckBox3; + QCheckBox* dhcpCheckBox; + QLabel* TextLabel3_3_2; + QSpinBox* SpinBox1_2; + QLabel* TextLabel4; + QLineEdit* ipAddressEdit; + QLabel* TextLabel5; + QLineEdit* firstDNSLineEdit; + QLabel* TextLabel3; + QLineEdit* subnetMaskEdit; + QLineEdit* gatewayEdit; + QLabel* TextLabel7; + QLabel* TextLabel2; + QLineEdit* secondDNSLineEdit; + QGroupBox* GroupBox2; + +protected: + QGridLayout* InterfaceConfigurationLayout; +}; + +#endif // INTERFACECONFIGURATION_H diff --git a/noncore/settings/networksettings/interfaceinformation.ui b/noncore/settings/networksettings/interfaceinformation.ui new file mode 100644 index 0000000..2a9b3fb --- a/dev/null +++ b/noncore/settings/networksettings/interfaceinformation.ui @@ -0,0 +1,317 @@ + +InterfaceInformation + + QWidget + + name + InterfaceInformation + + + geometry + + 0 + 0 + 191 + 241 + + + + caption + Interface Information + + + + margin + 11 + + + spacing + 6 + + + QLayoutWidget + + name + Layout1 + + + + margin + 0 + + + spacing + 6 + + + QPushButton + + name + refreshButton + + + text + Refresh + + + + QPushButton + + name + stopButton + + + text + Stop + + + + QPushButton + + name + restartButton + + + text + Restart + + + + QPushButton + + name + startButton + + + text + Start + + + + + + Line + + name + Line1 + + + orientation + Horizontal + + + + + name + Spacer18 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QLayoutWidget + + name + Layout2 + + + + margin + 0 + + + spacing + 6 + + + + name + Spacer10 + + + orientation + Horizontal + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QPushButton + + name + advancedButton + + + text + View Advanced Information + + + + + + QLabel + + name + TextLabel22 + + + text + IP Address + + + + QLabel + + name + TextLabel23 + + + text + Subnet Mask + + + + QLabel + + name + TextLabel21 + + + text + MAC Address + + + + QLabel + + name + TextLabel24 + + + text + Broadcast + + + + QLabel + + name + subnetMaskLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + 0.0.0.0 + + + + QLabel + + name + macAddressLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + 00:00:00:00:00:00 + + + + QLabel + + name + broadcastLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + + + + + QLabel + + name + ipAddressLabel + + + frameShape + Panel + + + frameShadow + Sunken + + + text + 0.0.0.0 + + + + + + + QWidget +
qwidget.h
+ + 100 + 100 + + 0 + + 7 + 7 + + image0 +
+
+ + + image0 + 789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758 + + +
diff --git a/noncore/settings/networksettings/interfaceinformationimp.cpp b/noncore/settings/networksettings/interfaceinformationimp.cpp new file mode 100644 index 0000000..e37e0f8 --- a/dev/null +++ b/noncore/settings/networksettings/interfaceinformationimp.cpp @@ -0,0 +1,94 @@ +#include "interfaceinformationimp.h" +#include "interfaceadvanced.h" + +#include +#include +#include + +/** + * Constructor for the InterfaceInformationImp class. This class pretty much + * just display's information about the interface that is passed to it. + */ +InterfaceInformationImp::InterfaceInformationImp(QWidget *parent, const char *name, Interface *i, WFlags f):InterfaceInformation(parent, name, f){ + assert(i); + + interface = i; + updateInterface(); + connect(startButton, SIGNAL(clicked()), this, SLOT(start())); + connect(stopButton, SIGNAL(clicked()), this, SLOT(stop())); + connect(restartButton, SIGNAL(clicked()), this, SLOT(restart())); + connect(refreshButton, SIGNAL(clicked()), this, SLOT(refresh())); + connect(advancedButton, SIGNAL(clicked()), this, SLOT(advanced())); + +} + +void InterfaceInformationImp::updateInterface(){ + if(interface->getStatus()){ + startButton->setEnabled(false); + stopButton->setEnabled(true); + restartButton->setEnabled(true); + } + else{ + startButton->setEnabled(true); + stopButton->setEnabled(false); + restartButton->setEnabled(false); + } + macAddressLabel->setText(interface->getMacAddress()); + ipAddressLabel->setText(interface->getIp()); + subnetMaskLabel->setText(interface->getSubnetMask()); + broadcastLabel->setText(interface->getBroadcast()); +} + +/** + * Start the interface. Update the information if successfull + */ +void InterfaceInformationImp::start(){ + if(interface->start()){ + updateInterface(); + } +} + +/** + * Stop the interface. + */ +void InterfaceInformationImp::stop(){ + if(interface->stop()){ + updateInterface(); + } +} + +/*** + * Tell the interface to refresh its information. + **/ +void InterfaceInformationImp::refresh(){ + if(interface->refresh()) + updateInterface(); +} + +void InterfaceInformationImp::restart(){ + if(interface->restart()){ + updateInterface(); + } +} + + +/** + * Create the advanced widget. Fill it with the current interface's information. + * Display it. + */ +void InterfaceInformationImp::advanced(){ + InterfaceAdvanced *a = new InterfaceAdvanced(0, "InterfaceAdvanced"); + a->interfaceName->setText(interface->getInterfaceName()); + a->macAddressLabel->setText(interface->getMacAddress()); + a->ipAddressLabel->setText(interface->getIp()); + a->subnetMaskLabel->setText(interface->getSubnetMask()); + a->broadcastLabel->setText(interface->getBroadcast()); + a->dhcpServerLabel->setText(interface->getDhcpServerIp()); + a->leaseObtainedLabel->setText(interface->getLeaseObtained()); + a->leaseExpiresLabel->setText(interface->getLeaseExpires()); + a->showMaximized(); + a->show(); +} + +// infoimp.cpp + diff --git a/noncore/settings/networksettings/interfaceinformationimp.h b/noncore/settings/networksettings/interfaceinformationimp.h new file mode 100644 index 0000000..6fc2384 --- a/dev/null +++ b/noncore/settings/networksettings/interfaceinformationimp.h @@ -0,0 +1,31 @@ +#ifndef INTERFACEINFORMATIONIMP_H +#define INTERFACEINFORMATIONIMP_H + +#include "interfaceinformation.h" +#include "interface.h" + +class InterfaceInformationImp : public InterfaceInformation { + +Q_OBJECT + +public: + InterfaceInformationImp(QWidget *parent=0, const char *name=0, Interface *i=0, WFlags f=0); + ~InterfaceInformationImp(){}; + +private slots: + void start(); + void stop(); + void refresh(); + void restart(); + void advanced(); + Interface *interface; + +private: + void updateInterface(); + +}; + +#endif + +// addserviceimp.h + diff --git a/noncore/settings/networksettings/interfaces.cpp b/noncore/settings/networksettings/interfaces.cpp new file mode 100644 index 0000000..b8a3e7f --- a/dev/null +++ b/noncore/settings/networksettings/interfaces.cpp @@ -0,0 +1,513 @@ +#include "interfaces.h" + +#include +#include +#include + +#define AUTO "auto" +#define IFACE "iface" +#define MAPPING "mapping" + +/** + * Constructor. Reads in the interfaces file and then split the file up by + * the \n for interfaces variable. + * @param useInterfacesFile if an interface file other then the default is + * desired to be used it should be passed in. + */ +Interfaces::Interfaces(QString useInterfacesFile){ + acceptedFamily.append(INTERFACES_FAMILY_INET); + acceptedFamily.append(INTERFACES_FAMILY_IPX); + acceptedFamily.append(INTERFACES_FAMILY_INET6); + + interfacesFile = useInterfacesFile; + QFile file(interfacesFile); + if (!file.open(IO_ReadOnly)){ + qDebug(QString("Interfaces: Can't open file: %1 for reading.").arg(interfacesFile).latin1()); + currentIface = interfaces.end(); + currentMapping = interfaces.end(); + return; + } + QTextStream stream( &file ); + QString line; + while ( !stream.eof() ) { + line += stream.readLine(); + line += "\n"; + } + file.close(); + interfaces = QStringList::split("\n", line, true); + + currentIface = interfaces.end(); + currentMapping = interfaces.end(); +} + +/** + * Find out if interface is in an "auto" group or not. + * Report any duplicates such as eth0 being in two differnt auto's + * @param + * @return true is interface is in auto + */ +bool Interfaces::isAuto(QString interface){ + QStringList autoLines = interfaces.grep(QRegExp(AUTO)); + QStringList awi = autoLines.grep(QRegExp(interface)); + if(awi.count() > 1) + qDebug(QString("Interfaces: Found more then auto group with interface: %1.").arg(interface).latin1()); + if(awi.count() < 1) + return false; + return true; +} + +/** + * Attempt to set the auto option for interface to setAuto. + * @param interface the interface to set + * @param setAuto the value to set interface to. + * @return false if already set to setAuto. + * */ +bool Interfaces::setAuto(QString interface, bool setAuto){ + // Don't need to set it if it is already set. + if(isAuto(interface) == setAuto) + return false; + + bool changed = false; + for ( QStringList::Iterator it = interfaces.begin(); it != interfaces.end(); ++it ) { + if((*it).contains(AUTO)){ + //We know that they are not in any group so let add to this auto. + if(setAuto){ + (*it) = (*it) += " " + interface; + // Don't care to have such thins as: auto eth0 lo usb0 + (*it) = (*it).simplifyWhiteSpace(); + changed = true; + break; + } + else{ + if((*it).contains(interface)){ + (*it) = (*it).replace(QRegExp(interface), ""); + // clean up + QString line = (*it).simplifyWhiteSpace(); + line = line.replace(QRegExp(" "),""); + if(line == AUTO) + (*it) = ""; + changed = true; + // Don't break because we want to make sure we remove all cases. + } + } + } + } + if(changed == false){ + if(setAuto == true) + interfaces.append(QString(AUTO" %1").arg(interface)); + else{ + qDebug(QString("Interfaces: Can't set interface %1 auto to false sense it is already false.").arg(interface).latin1()); + } + } + return true; +} + +/** + * Set the current interface to interface. This needs to be done before you + * can call getFamily(), getMethod, and get/setOption(). + * @param interface the name of the interface to set. All whitespace is + * removed from the interface name. + * @return bool true if it is successfull. + */ +bool Interfaces::setInterface(QString interface){ + interface = interface.simplifyWhiteSpace(); + interface = interface.replace(QRegExp(" "), ""); + return setStanza(IFACE, interface, currentIface); +} + +/** + * A quick helper funtion to see if the current interface is set. + * @return bool true if set, false otherwise. + */ +bool Interfaces::isInterfaceSet(){ + return (currentIface != interfaces.end()); +} + +/** + * Add a new interface of with the settings - family and method + * @param interface the name of the interface to set. All whitespace is + * removed from the interface name. + * @param family the family of this interface inet or inet, ipx or inet6 + * Must of one of the families defined in interfaces.h + * @param method for the family. see interfaces man page for family methods. + * @return true if successfull. + */ +bool Interfaces::addInterface(QString interface, QString family, QString method){ + if(acceptedFamily.contains(family)==0) + return false; + interface = interface.simplifyWhiteSpace(); + interface = interface.replace(QRegExp(" "), ""); + interfaces.append(""); + interfaces.append(QString(IFACE " %1 %2 %3").arg(interface).arg(family).arg(method)); + return true; +} + +/** + * Remove the currently selected interface and all of its options. + * @return bool if successfull or not. + */ +bool Interfaces::removeInterface(){ + if(currentIface == interfaces.end()) + return false; + (*currentIface) = ""; + return removeAllInterfaceOptions(); +} + +/** + * Gets the hardware name of the interface that is currently selected. + * @return QString name of the hardware interface (eth0, usb2, wlan1...). + * @param error set to true if any error occurs, false otherwise. + */ +QString Interfaces::getInterfaceName(bool &error){ + if(currentIface == interfaces.end()){ + error = true; + return QString(); + } + QString line = (*currentIface); + line = line.mid(QString(IFACE).length() +1, line.length()); + line = line.simplifyWhiteSpace(); + int findSpace = line.find(" "); + if( findSpace < 0){ + error = true; + return QString(); + } + error = false; + return line.mid(0, findSpace); +} + +/** + * Gets the family name of the interface that is currently selected. + * @return QString name of the family (inet, inet6, ipx). + * @param error set to true if any error occurs, false otherwise. + */ +QString Interfaces::getInterfaceFamily(bool &error){ + QString name = getInterfaceName(error); + if(error){ + error = true; + return QString(); + } + QString line = (*currentIface); + line = line.mid(QString(IFACE).length() +1, line.length()); + line = line.mid(name.length()+1, line.length()); + line = line.simplifyWhiteSpace(); + int findSpace = line.find(" "); + if( findSpace < 0){ + error = true; + return QString(); + } + error = false; + return line.mid(0, findSpace); +} + +/** + * Gets the method of the interface that is currently selected. + * @return QString name of the method such as staic or dhcp. + * See the man page of interfaces for possible methods depending on the family. + * @param error set to true if any error occurs, false otherwise. + */ +QString Interfaces::getInterfaceMethod(bool &error){ + QString name = getInterfaceName(error); + if(error){ + error = true; + return QString(); + } + QString family = getInterfaceFamily(error); + if(error){ + error = true; + return QString(); + } + QString line = (*currentIface); + line = line.mid(QString(IFACE).length()+1, line.length()); + line = line.mid(name.length()+1, line.length()); + line = line.mid(family.length()+1, line.length()); + line = line.simplifyWhiteSpace(); + error = false; + return line; +} + +/** + * Sets the interface name to newName. + * @param newName the new name of the interface. All whitespace is removed. + * @return bool true if successfull. + */ +bool Interfaces::setInterfaceName(QString newName){ + if(currentIface == interfaces.end()) + return false; + newName = newName.simplifyWhiteSpace(); + newName = newName.replace(QRegExp(" "), ""); + bool returnValue = false; + (*currentIface) = QString("iface %1 %2 %3").arg(newName).arg(getInterfaceFamily(returnValue)).arg(getInterfaceMethod(returnValue)); + return !returnValue; +} + +/** + * Sets the interface family to newName. + * @param newName the new name of the interface. Must be one of the families + * defined in the interfaces.h file. + * @return bool true if successfull. + */ +bool Interfaces::setInterfaceFamily(QString newName){ + if(currentIface == interfaces.end()) + return false; + if(acceptedFamily.contains(newName)==0) + return false; + bool returnValue = false; + (*currentIface) = QString("iface %1 %2 %3").arg(getInterfaceName(returnValue)).arg(newName).arg(getInterfaceMethod(returnValue)); + return !returnValue; +} + +/** + * Sets the interface method to newName + * @param newName the new name of the interface + * @return bool true if successfull. + */ +bool Interfaces::setInterfaceMethod(QString newName){ + if(currentIface == interfaces.end()) + return false; + bool returnValue = false; + (*currentIface) = QString("iface %1 %2 %3").arg(getInterfaceName(returnValue)).arg(getInterfaceFamily(returnValue)).arg(newName); + return !returnValue; +} + +/** + * Get a value for an option in the currently selected interface. For example + * calling getInterfaceOption("address") on the following stanza would + * return 192.168.1.1. + * iface eth0 static + * address 192.168.1.1 + * @param option the options to get the value. + * @param error set to true if any error occurs, false otherwise. + * @return QString the options value. QString::null if error == true + */ +QString Interfaces::getInterfaceOption(QString option, bool &error){ + return getOption(currentIface, option, error); +} + +/** + * Set a value for an option in the currently selected interface. If option + * doesn't exist then it is added along with the value. If value is set to an + * empty string then option is removed. + * @param option the options to set the value. + * @param value the value that option should be set to. + * @param error set to true if any error occurs, false otherwise. + * @return QString the options value. QString::null if error == true + */ +bool Interfaces::setInterfaceOption(QString option, QString value){ + return setOption(currentIface, option, value); +} + +/** + * Removes all of the options from the currently selected interface. + * @return bool error if if successfull + */ +bool Interfaces::removeAllInterfaceOptions(){ + return removeAllOptions(currentIface); +} + +/** + * Set the current map to interface's map. This needs to be done before you + * can call addMapping(), set/getMap(), and get/setScript(). + * @param interface the name of the interface to set. All whitespace is + * removed from the interface name. + * @return bool true if it is successfull. + */ +bool Interfaces::setMapping(QString interface){ + interface = interface.simplifyWhiteSpace(); + interface = interface.replace(QRegExp(" "), ""); + return setStanza(MAPPING, interface, currentMapping); +} + +/** + * Adds a new Mapping to the interfaces file with interfaces. + * @param interface the name(s) of the interfaces to set to this mapping + */ +void Interfaces::addMapping(QString interfaces){ + interfaces.append(""); + interfaces.append(QString(MAPPING " %1").arg(interfaces)); +} + +/** + * Set a map option within a mapping. + * @param map map to use + * @param value value to go with map + * @return bool true if it is successfull. + */ +bool Interfaces::setMap(QString map, QString value){ + return setOption(currentMapping, map, value); +} + +/** + * Get a map value within a mapping. + * @param map map to get value of + * @param bool true if it is successfull. + * @return value that goes to the map + */ +QString Interfaces::getMap(QString map, bool &error){ + return getOption(currentMapping, map, error); +} + +/** + * Sets a script value of the current mapping to argument. + * @param argument the script name. + * @return true if successfull. + */ +bool Interfaces::setScript(QString argument){ + return setOption(currentMapping, "script", argument); +} + +/** + * @param error true if could not retrieve the current script argument. + * @return QString the argument of the script for the current mapping. + */ +QString Interfaces::getScript(bool &error){ + return getOption(currentMapping, "script", error); +} + +/** + * Helper function used to parse through the QStringList and put pointers in + * the correct place. + * @param stanza The stanza (auto, iface, mapping) to look for. + * @param option string that must be in the stanza's main line. + * @param interator interator to place at location of stanza if successfull. + * @return bool true if the stanza is found. + */ +bool Interfaces::setStanza(QString stanza, QString option, QStringList::Iterator &iterator){ + bool found = false; + iterator = interfaces.end(); + for ( QStringList::Iterator it = interfaces.begin(); it != interfaces.end(); ++it ) { + QString line = (*it).simplifyWhiteSpace(); + if(line.contains(stanza) && line.contains(option)){ + if(found == true){ + qDebug(QString("Interfaces: Found multiple stanza's for search: %1 %2").arg(stanza).arg(option).latin1()); + } + found = true; + iterator = it; + } + } + return !found; +} + +/** + * Sets a value of an option in a stanza + * @param start the start of the stanza + * @param option the option to use when setting value. + * @return bool true if successfull, false otherwise. + */ +bool Interfaces::setOption(QStringList::Iterator start, QString option, QString value){ + if(start == interfaces.end()) + return false; + + bool found = false; + for ( QStringList::Iterator it = start; it != interfaces.end(); ++it ) { + if(((*it).contains(IFACE) || (*it).contains(MAPPING) || (*it).contains(AUTO)) && it != start){ + if(!found && value != ""){ + // Got to the end of the stanza without finding it, so append it. + interfaces.insert(--it, QString("\t%1 %2").arg(option).arg(value)); + } + break; + } + if((*it).contains(option)){ + // Found it in stanza so replace it. + if(found) + qDebug(QString("Interfaces: Set Options found more then one value for option: %1 in stanza: %1").arg(option).arg((*start)).latin1()); + found = true; + if(value == "") + (*it) = ""; + else + (*it) = QString("\t%1 %2").arg(option).arg(value); + } + } + return true; +} + +/** + * Removes all options in a stanza + * @param start the start of the stanza + * @return bool true if successfull, false otherwise. + */ +bool Interfaces::removeAllOptions(QStringList::Iterator start){ + if(start == interfaces.end()) + return false; + + QStringList::Iterator it = start; + it = ++it; + for (it; it != interfaces.end(); ++it ) { + if(((*it).contains(IFACE) || (*it).contains(MAPPING) || (*it).contains(AUTO)) && it != start){ + break; + } + it = interfaces.remove(it); + it = --it; + } + // Leave a space between this interface and the next. + interfaces.insert(it, QString("")); + return true; +} + +/** + * Gets a value of an option in a stanza + * @param start the start of the stanza + * @param option the option to use when getting the value. + * @param bool true if errors false otherwise. + * @return QString the value of option QString::null() if error == true. + */ +QString Interfaces::getOption(QStringList::Iterator start, QString option, bool &error){ + if(start == interfaces.end()){ + error = false; + return QString(); + } + + QString value; + bool found = false; + for ( QStringList::Iterator it = start; it != interfaces.end(); ++it ) { + if(((*it).contains(IFACE) || (*it).contains(MAPPING) || (*it).contains(AUTO)) && it != start){ + break; + } + if((*it).contains(option)){ + if(found) + qDebug(QString("Interfaces: Get Options found more then one value: %1 for option: %2 in stanza %3").arg((*it)).arg(option).arg((*start)).latin1()); + found = true; + QString line = (*it).simplifyWhiteSpace(); + int space = line.find(" ", option.length()); + if(space != -1) + value = line.mid(space+1, line.length()); + else + qDebug(QString("Interfaces: Option %1 with no value").arg(option).latin1()); + } + } + error = !found; + return value; +} + +/** + * Write out the interfaces file to the file passed into the constructor. + * Removes any excess blank lines over 1 line long. + * @return bool true if successfull, false if not. + */ +bool Interfaces::write(){ + QFile::remove(interfacesFile); + QFile file(interfacesFile); + + if (!file.open(IO_ReadWrite)){ + qDebug(QString("Interfaces: Can't open file: %1 for writing.").arg(interfacesFile).latin1()); + return false; + } + QTextStream stream( &file ); + int whiteSpaceCount = 0; + for ( QStringList::Iterator it = interfaces.begin(); it != interfaces.end(); ++it ) { + QString line = (*it).simplifyWhiteSpace(); + line = line.replace(QRegExp(" "),""); + if(line.length() == 0) + whiteSpaceCount++; + else + whiteSpaceCount = 0; + if(whiteSpaceCount < 2){ + qDebug((*it).latin1()); + stream << (*it) << '\n'; + } + } + file.close(); + return true; +} + +// interfaces.cpp + diff --git a/noncore/settings/networksettings/interfaces.h b/noncore/settings/networksettings/interfaces.h new file mode 100644 index 0000000..2cc9689 --- a/dev/null +++ b/noncore/settings/networksettings/interfaces.h @@ -0,0 +1,70 @@ +#ifndef INTERFACES_H +#define INTERFACES_H + +#include +#include + +#define INTERFACES_LOOPBACK "loopback" + +#define INTERFACES_FAMILY_INET "inet" +#define INTERFACES_FAMILY_IPX "ipx" +#define INTERFACES_FAMILY_INET6 "inet6" + +#define INTERFACES_METHOD_DHCP "dhcp" +#define INTERFACES_METHOD_STATIC "static" +#define INTERFACES_METHOD_PPP "ppp" + +/** + * This class provides a clean frontend for parsing the network interfaces file. + * It provides helper functions to minipulate the options within the file. + * See the interfaces man page for the syntax rules. + */ +class Interfaces { + +public: + Interfaces(QString useInterfacesFile = "/etc/network/interfaces"); + + bool isAuto(QString interface); + bool setAuto(QString interface, bool setAuto); + + bool removeInterface(); + bool addInterface(QString interface, QString family, QString method); + bool setInterface(QString interface); + bool isInterfaceSet(); + QString getInterfaceName(bool &error); + bool setInterfaceName(QString newName); + QString getInterfaceFamily(bool &error); + bool setInterfaceFamily(QString newName); + QString getInterfaceMethod(bool &error); + bool setInterfaceMethod(QString newName); + QString getInterfaceOption(QString option, bool &error); + bool setInterfaceOption(QString option, QString value); + bool removeAllInterfaceOptions(); + + bool setMapping(QString interface); + void addMapping(QString interfaces); + bool setMap(QString map, QString value); + QString getMap(QString map, bool &error); + bool setScript(QString); + QString getScript(bool &error); + + bool write(); + +private: + bool setStanza(QString stanza, QString option,QStringList::Iterator &iterator); + bool setOption(QStringList::Iterator start, QString option, QString value); + QString getOption(QStringList::Iterator start, QString option, bool &error); + bool removeAllOptions(QStringList::Iterator start); + + QString interfacesFile; + QStringList interfaces; + QStringList::Iterator currentIface; + QStringList::Iterator currentMapping; + + QStringList acceptedFamily; +}; + +#endif + +// interfaces + diff --git a/noncore/settings/networksettings/interfacesetup.ui b/noncore/settings/networksettings/interfacesetup.ui new file mode 100644 index 0000000..698422c --- a/dev/null +++ b/noncore/settings/networksettings/interfacesetup.ui @@ -0,0 +1,274 @@ + +InterfaceSetup + + QDialog + + name + InterfaceSetup + + + geometry + + 0 + 0 + 193 + 310 + + + + caption + Interface Configuration + + + + margin + 11 + + + spacing + 6 + + + Line + + name + Line1 + + + orientation + Horizontal + + + + QLabel + + name + TextLabel4 + + + text + IP Address + + + + QCheckBox + + name + autoStart + + + text + Automaticly bring up + + + + QComboBox + + + text + All + + + + name + profileCombo + + + + QGroupBox + + name + staticGroupBox + + + enabled + false + + + title + Static Ip Configuration + + + + QLineEdit + + name + ipAddressEdit + + + + QLabel + + name + leaseHoursLabel + + + text + Requested Lease + + + + QCheckBox + + name + dhcpCheckBox + + + text + DHCP + + + checked + true + + + + QLabel + + name + TextLabel5 + + + text + Subnet Mask + + + + QLabel + + name + TextLabel1 + + + text + Profile: + + + + QSpinBox + + name + leaseTime + + + suffix + hours + + + maxValue + 336 + + + minValue + 1 + + + value + 24 + + + + + name + Spacer9 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + QLineEdit + + name + secondDNSLineEdit + + + + QLabel + + name + TextLabel3 + + + text + Second DNS + + + + QLabel + + name + TextLabel2 + + + text + First DNS + + + + QLineEdit + + name + firstDNSLineEdit + + + + QLabel + + name + TextLabel1_2 + + + text + Gateway + + + + QLineEdit + + name + subnetMaskEdit + + + + QLineEdit + + name + gatewayEdit + + + + + + + dhcpCheckBox + toggled(bool) + leaseHoursLabel + setEnabled(bool) + + + dhcpCheckBox + toggled(bool) + leaseTime + setEnabled(bool) + + + dhcpCheckBox + toggled(bool) + staticGroupBox + setDisabled(bool) + + + diff --git a/noncore/settings/networksettings/interfacesetupimp.cpp b/noncore/settings/networksettings/interfacesetupimp.cpp new file mode 100644 index 0000000..6a8449d --- a/dev/null +++ b/noncore/settings/networksettings/interfacesetupimp.cpp @@ -0,0 +1,147 @@ +#include "interfacesetupimp.h" +#include "interface.h" +#include "interfaces.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include + +#define INTERFACE_FILE "/home/ben/interfaces" +#define DNSSCRIPT "interfacednsscript" + +/** + * Constuctor. Set up the connection and load the first profile. + */ +InterfaceSetupImp::InterfaceSetupImp(QWidget* parent, const char* name, Interface *i, bool modal, WFlags fl) : InterfaceSetup(parent, name, modal, fl){ + assert(i); + interface = i; + interfaces = new Interfaces(INTERFACE_FILE); + changeProfile(profileCombo->currentText()); + bool error = false; + if(interfaces->getInterfaceMethod(error) == INTERFACES_LOOPBACK){ + staticGroupBox->hide(); + dhcpCheckBox->hide(); + leaseTime->hide(); + leaseHoursLabel->hide(); + } + connect(profileCombo, SIGNAL(highlighted(const QString &)), this, SLOT(changeProfile(const QString &))); +} + +/** + * Save the current settings, then write out the interfaces file and close. + */ +void InterfaceSetupImp::accept(){ + if(!saveSettings()) + return; + interfaces->write(); + close(true); +} + +/** + * Save the settings for the current Interface. + * @return bool true if successfull, false otherwise + */ +bool InterfaceSetupImp::saveSettings(){ + // eh can't really do anything about it other then return. :-D + if(!interfaces->isInterfaceSet()) + return true; + + bool error = false; + // Loopback case + if(interfaces->getInterfaceMethod(error) == INTERFACES_LOOPBACK){ + interfaces->setAuto(interface->getInterfaceName(), autoStart->isChecked()); + return true; + } + + if(!dhcpCheckBox->isChecked() && (ipAddressEdit->text().isEmpty() || subnetMaskEdit->text().isEmpty() || firstDNSLineEdit->text().isEmpty())){ + QMessageBox::information(this, "Empy Fields.", "Please fill in address, subnet,\n gateway and the first dns entries.", "Ok"); + return false; + } + interfaces->removeAllInterfaceOptions(); + + // DHCP + if(dhcpCheckBox->isChecked()){ + interfaces->setInterfaceMethod(INTERFACES_METHOD_DHCP); + interfaces->setInterfaceOption("leasehours", QString("%1").arg(leaseTime->value())); + interfaces->setInterfaceOption("leasetime", QString("%1").arg(leaseTime->value()*60*60)); + } + else{ + interfaces->setInterfaceMethod("static"); + interfaces->setInterfaceOption("address", ipAddressEdit->text()); + interfaces->setInterfaceOption("netmask", subnetMaskEdit->text()); + interfaces->setInterfaceOption("gateway", gatewayEdit->text()); + QString dns = firstDNSLineEdit->text() + " " + secondDNSLineEdit->text(); + interfaces->setInterfaceOption("up "DNSSCRIPT" add ", dns); + interfaces->setInterfaceOption("down "DNSSCRIPT" remove ", dns); + } + + // IP Information + interfaces->setAuto(interface->getInterfaceName(), autoStart->isChecked()); + return true; +} + +/** + * The Profile has changed. + * @profile the new profile. + */ +void InterfaceSetupImp::changeProfile(const QString &profile){ + QString newInterfaceName; + if(profile.lower() == "all") + newInterfaceName = interface->getInterfaceName(); + else + newInterfaceName = interface->getInterfaceName() + "_" + profile; + if(newInterfaceName == currentInterfaceName) + return; + else{ + saveSettings(); + currentInterfaceName = newInterfaceName; + } + bool error = interfaces->setInterface(currentInterfaceName); + + // See if we have to make a interface. + if(error){ + qDebug("InterfaceSetupImp: Adding a new interface from profile change."); + interfaces->addInterface(currentInterfaceName, INTERFACES_FAMILY_INET, INTERFACES_METHOD_DHCP); + error = interfaces->setInterface(currentInterfaceName); + if(error){ + qDebug("InterfaceSetupImp: Added interface, but still can't set."); + return; + } + } + + //qDebug( currentInterfaceName.latin1() ); + // We must have a valid interface to get this far so read some settings. + + // DHCP + if(interfaces->getInterfaceMethod(error) == INTERFACES_METHOD_DHCP) + dhcpCheckBox->setChecked(true); + else + dhcpCheckBox->setChecked(false); + leaseTime->setValue(interfaces->getInterfaceOption("leasehours", error).toInt()); + if(error) + leaseTime->setValue(interfaces->getInterfaceOption("leasetime", error).toInt()/60/60); + if(error) + leaseTime->setValue(24); + + // IP Information + autoStart->setChecked(interfaces->isAuto(interface->getInterfaceName())); + QString dns = interfaces->getInterfaceOption("up interfacednsscript add", error); + if(dns.contains(" ")){ + firstDNSLineEdit->setText(dns.mid(0, dns.find(" "))); + secondDNSLineEdit->setText(dns.mid(dns.find(" ")+1, dns.length())); + } + ipAddressEdit->setText(interfaces->getInterfaceOption("address", error)); + subnetMaskEdit->setText(interfaces->getInterfaceOption("netmask", error)); + gatewayEdit->setText(interfaces->getInterfaceOption("gateway", error)); +} + + +// interfacesetup.cpp + diff --git a/noncore/settings/networksettings/interfacesetupimp.h b/noncore/settings/networksettings/interfacesetupimp.h new file mode 100644 index 0000000..6c34718 --- a/dev/null +++ b/noncore/settings/networksettings/interfacesetupimp.h @@ -0,0 +1,30 @@ +#ifndef INTERFACESETUPIMP_H +#define INTERFACESETUPIMP_H + +#include "interfacesetup.h" + +class Interface; +class Interfaces; + +class InterfaceSetupImp : public InterfaceSetup { + Q_OBJECT + +public: + InterfaceSetupImp( QWidget* parent = 0, const char* name = 0, Interface *i=0, bool modal = FALSE, WFlags fl = 0); + +protected slots: + void accept(); + void changeProfile(const QString &profile); + +private: + bool saveSettings(); + Interfaces *interfaces; + Interface *interface; + QString currentInterfaceName; + +}; + +#endif + +// interfacesetupimp.h + diff --git a/noncore/settings/networksettings/kprocctrl.cpp b/noncore/settings/networksettings/kprocctrl.cpp new file mode 100644 index 0000000..cd8711a --- a/dev/null +++ b/noncore/settings/networksettings/kprocctrl.cpp @@ -0,0 +1,267 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +// +// KPROCESSCONTROLLER -- A helper class for KProcess +// +// version 0.3.1, Jan, 8th 1997 +// +// (C) Christian Czezatke +// e9025461@student.tuwien.ac.at +// + +//#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include "kprocess.h" +#include "kprocctrl.h" + +KProcessController *KProcessController::theKProcessController = 0; + +struct sigaction KProcessController::oldChildHandlerData; +bool KProcessController::handlerSet = false; + +KProcessController::KProcessController() +{ + assert( theKProcessController == 0 ); + + if (0 > pipe(fd)) + printf(strerror(errno)); + + notifier = new QSocketNotifier(fd[0], QSocketNotifier::Read); + notifier->setEnabled(true); + QObject::connect(notifier, SIGNAL(activated(int)), + this, SLOT(slotDoHousekeeping(int))); + connect( &delayedChildrenCleanupTimer, SIGNAL( timeout()), + SLOT( delayedChildrenCleanup())); + + theKProcessController = this; + + setupHandlers(); +} + + +void KProcessController::setupHandlers() +{ + if( handlerSet ) + return; + struct sigaction act; + act.sa_handler=theSigCHLDHandler; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGCHLD); + // Make sure we don't block this signal. gdb tends to do that :-( + sigprocmask(SIG_UNBLOCK, &(act.sa_mask), 0); + + act.sa_flags = SA_NOCLDSTOP; + + // CC: take care of SunOS which automatically restarts interrupted system + // calls (and thus does not have SA_RESTART) + +#ifdef SA_RESTART + act.sa_flags |= SA_RESTART; +#endif + + sigaction( SIGCHLD, &act, &oldChildHandlerData ); + + act.sa_handler=SIG_IGN; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGPIPE); + act.sa_flags = 0; + sigaction( SIGPIPE, &act, 0L); + handlerSet = true; +} + +void KProcessController::resetHandlers() +{ + if( !handlerSet ) + return; + sigaction( SIGCHLD, &oldChildHandlerData, 0 ); + // there should be no problem with SIGPIPE staying SIG_IGN + handlerSet = false; +} + +// block SIGCHLD handler, because it accesses processList +void KProcessController::addKProcess( KProcess* p ) +{ + sigset_t newset, oldset; + sigemptyset( &newset ); + sigaddset( &newset, SIGCHLD ); + sigprocmask( SIG_BLOCK, &newset, &oldset ); + processList.append( p ); + sigprocmask( SIG_SETMASK, &oldset, 0 ); +} + +void KProcessController::removeKProcess( KProcess* p ) +{ + sigset_t newset, oldset; + sigemptyset( &newset ); + sigaddset( &newset, SIGCHLD ); + sigprocmask( SIG_BLOCK, &newset, &oldset ); + processList.remove( p ); + sigprocmask( SIG_SETMASK, &oldset, 0 ); +} + +//using a struct which contains both the pid and the status makes it easier to write +//and read the data into the pipe +//especially this solves a problem which appeared on my box where slotDoHouseKeeping() received +//only 4 bytes (with some debug output around the write()'s it received all 8 bytes) +//don't know why this happened, but when writing all 8 bytes at once it works here, aleXXX +struct waitdata +{ + pid_t pid; + int status; +}; + +void KProcessController::theSigCHLDHandler(int arg) +{ + struct waitdata wd; +// int status; +// pid_t this_pid; + int saved_errno; + + saved_errno = errno; + // since waitpid and write change errno, we have to save it and restore it + // (Richard Stevens, Advanced programming in the Unix Environment) + + bool found = false; + if( theKProcessController != 0 ) { + // iterating the list doesn't perform any system call + for( QValueList::ConstIterator it = theKProcessController->processList.begin(); + it != theKProcessController->processList.end(); + ++it ) + { + if( !(*it)->isRunning()) + continue; + wd.pid = waitpid( (*it)->pid(), &wd.status, WNOHANG ); + if ( wd.pid > 0 ) { + ::write(theKProcessController->fd[1], &wd, sizeof(wd)); + found = true; + } + } + } + if( !found && oldChildHandlerData.sa_handler != SIG_IGN + && oldChildHandlerData.sa_handler != SIG_DFL ) + oldChildHandlerData.sa_handler( arg ); // call the old handler + // handle the rest + if( theKProcessController != 0 ) { + static const struct waitdata dwd = { 0, 0 }; // delayed waitpid() + ::write(theKProcessController->fd[1], &dwd, sizeof(dwd)); + } else { + int dummy; + while( waitpid( -1, &dummy, WNOHANG ) > 0 ) + ; + } + + errno = saved_errno; +} + + + +void KProcessController::slotDoHousekeeping(int ) +{ + unsigned int bytes_read = 0; + unsigned int errcnt=0; + // read pid and status from the pipe. + struct waitdata wd; + while ((bytes_read < sizeof(wd)) && (errcnt < 50)) { + int r = ::read(fd[0], ((char *)&wd) + bytes_read, sizeof(wd) - bytes_read); + if (r > 0) bytes_read += r; + else if (r < 0) errcnt++; + } + if (errcnt >= 50) { + fprintf(stderr, + "Error: Max. error count for pipe read " + "exceeded in KProcessController::slotDoHousekeeping\n"); + return; // it makes no sense to continue here! + } + if (bytes_read != sizeof(wd)) { + fprintf(stderr, + "Error: Could not read info from signal handler %d <> %d!\n", + bytes_read, sizeof(wd)); + return; // it makes no sense to continue here! + } + if (wd.pid==0) { // special case, see delayedChildrenCleanup() + delayedChildrenCleanupTimer.start( 1000, true ); + return; + } + + for( QValueList::ConstIterator it = processList.begin(); + it != processList.end(); + ++it ) { + KProcess* proc = *it; + if (proc->pid() == wd.pid) { + // process has exited, so do emit the respective events + if (proc->run_mode == KProcess::Block) { + // If the reads are done blocking then set the status in proc + // but do nothing else because KProcess will perform the other + // actions of processHasExited. + proc->status = wd.status; + proc->runs = false; + } else { + proc->processHasExited(wd.status); + } + return; + } + } +} + +// this is needed e.g. for popen(), which calls waitpid() checking +// for its forked child, if we did waitpid() directly in the SIGCHLD +// handler, popen()'s waitpid() call would fail +void KProcessController::delayedChildrenCleanup() +{ + struct waitdata wd; + while(( wd.pid = waitpid( -1, &wd.status, WNOHANG ) ) > 0 ) { + for( QValueList::ConstIterator it = processList.begin(); + it != processList.end(); + ++it ) + { + if( !(*it)->isRunning() || (*it)->pid() != wd.pid ) + continue; + // it's KProcess, handle it + ::write(fd[1], &wd, sizeof(wd)); + break; + } + } +} + +KProcessController::~KProcessController() +{ + assert( theKProcessController == this ); + resetHandlers(); + + notifier->setEnabled(false); + + close(fd[0]); + close(fd[1]); + + delete notifier; + theKProcessController = 0; +} + +//#include "kprocctrl.moc" diff --git a/noncore/settings/networksettings/kprocctrl.h b/noncore/settings/networksettings/kprocctrl.h new file mode 100644 index 0000000..ac82b9d --- a/dev/null +++ b/noncore/settings/networksettings/kprocctrl.h @@ -0,0 +1,120 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +// +// KPROCESSCONTROLLER -- A helper class for KProcess +// +// version 0.3.1, Jan 8th 1997 +// +// (C) Christian Czezatke +// e9025461@student.tuwien.ac.at +// + +#ifndef __KPROCCTRL_H__ +#define __KPROCCTRL_H__ + +#include +#include + +#include "kprocess.h" + +class KProcessControllerPrivate; +class QSocketNotifier; + +/** + * @short Used internally by @ref KProcess + * @internal + * @author Christian Czezakte + * + * A class for internal use by KProcess only. -- Exactly one instance + * of this class is generated by the first instance of KProcess that is + * created (a pointer to it gets stored in @ref theKProcessController ). + * + * This class takes care of the actual (UN*X) signal handling. +*/ +class KProcessController : public QObject +{ + Q_OBJECT + +public: + KProcessController(); + ~KProcessController(); + //CC: WARNING! Destructor Not virtual (but you don't derive classes from this anyhow...) + +public: + + /** + * Only a single instance of this class is allowed at a time, + * and this static variable is used to track the one instance. + */ + static KProcessController *theKProcessController; + + /** + * Automatically called upon SIGCHLD. + * + * Normally you do not need to do anything with this function but + * if your application needs to disable SIGCHLD for some time for + * reasons beyond your control, you should call this function afterwards + * to make sure that no SIGCHLDs where missed. + */ + static void theSigCHLDHandler(int signal); + // handler for sigchld + + /** + * @internal + */ + static void setupHandlers(); + /** + * @internal + */ + static void resetHandlers(); + /** + * @internal + */ + void addKProcess( KProcess* ); + /** + * @internal + */ + void removeKProcess( KProcess* ); + public slots: + /** + * @internal + */ + void slotDoHousekeeping(int socket); + + private slots: + void delayedChildrenCleanup(); +private: + int fd[2]; + QSocketNotifier *notifier; + static struct sigaction oldChildHandlerData; + static bool handlerSet; + QValueList processList; + QTimer delayedChildrenCleanupTimer; + + // Disallow assignment and copy-construction + KProcessController( const KProcessController& ); + KProcessController& operator= ( const KProcessController& ); + + KProcessControllerPrivate *d; +}; + + + +#endif + diff --git a/noncore/settings/networksettings/kprocess.cpp b/noncore/settings/networksettings/kprocess.cpp new file mode 100644 index 0000000..193ec9b --- a/dev/null +++ b/noncore/settings/networksettings/kprocess.cpp @@ -0,0 +1,919 @@ +/* + + $Id$ + + This file is part of the KDE libraries + Copyright (C) 1997 Christian Czezatke (e9025461@student.tuwien.ac.at) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + + +// +// KPROCESS -- A class for handling child processes in KDE without +// having to take care of Un*x specific implementation details +// +// version 0.3.1, Jan 8th 1998 +// +// (C) Christian Czezatke +// e9025461@student.tuwien.ac.at +// +// Changes: +// +// March 2nd, 1998: Changed parameter list for KShellProcess: +// Arguments are now placed in a single string so that +// -c is passed to the shell +// to make the use of "operator<<" consistent with KProcess + +#include "kprocess.h" +#define _MAY_INCLUDE_KPROCESSCONTROLLER_ +#include "kprocctrl.h" + +//#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#ifdef HAVE_INITGROUPS +#include +#endif +#include + +#include +//#include + +///////////////////////////// +// public member functions // +///////////////////////////// + +class KProcessPrivate { +public: + KProcessPrivate() : useShell(false) { } + + bool useShell; + QMap env; + QString wd; + QCString shell; +}; + +#define Q_CHECK_PTR(a) + +KProcess::KProcess() + : QObject(), + run_mode(NotifyOnExit), + runs(false), + pid_(0), + status(0), + keepPrivs(false), + innot(0), + outnot(0), + errnot(0), + communication(NoCommunication), + input_data(0), + input_sent(0), + input_total(0), + d(0) +{ + if (0 == KProcessController::theKProcessController) { + (void) new KProcessController(); + Q_CHECK_PTR(KProcessController::theKProcessController); + } + + KProcessController::theKProcessController->addKProcess(this); + out[0] = out[1] = -1; + in[0] = in[1] = -1; + err[0] = err[1] = -1; +} + +void +KProcess::setEnvironment(const QString &name, const QString &value) +{ + if (!d) + d = new KProcessPrivate; + d->env.insert(name, value); +} + +void +KProcess::setWorkingDirectory(const QString &dir) +{ + if (!d) + d = new KProcessPrivate; + d->wd = dir; +} + +void +KProcess::setupEnvironment() +{ + if (d) + { + QMap::Iterator it; + for(it = d->env.begin(); it != d->env.end(); ++it) + setenv(QFile::encodeName(it.key()).data(), + QFile::encodeName(it.data()).data(), 1); + if (!d->wd.isEmpty()) + chdir(QFile::encodeName(d->wd).data()); + } +} + +void +KProcess::setRunPrivileged(bool keepPrivileges) +{ + keepPrivs = keepPrivileges; +} + +bool +KProcess::runPrivileged() const +{ + return keepPrivs; +} + + +KProcess::~KProcess() +{ + // destroying the KProcess instance sends a SIGKILL to the + // child process (if it is running) after removing it from the + // list of valid processes (if the process is not started as + // "DontCare") + + KProcessController::theKProcessController->removeKProcess(this); + // this must happen before we kill the child + // TODO: block the signal while removing the current process from the process list + + if (runs && (run_mode != DontCare)) + kill(SIGKILL); + + // Clean up open fd's and socket notifiers. + closeStdin(); + closeStdout(); + closeStderr(); + + // TODO: restore SIGCHLD and SIGPIPE handler if this is the last KProcess + delete d; +} + +void KProcess::detach() +{ + KProcessController::theKProcessController->removeKProcess(this); + + runs = false; + pid_ = 0; + + // Clean up open fd's and socket notifiers. + closeStdin(); + closeStdout(); + closeStderr(); +} + +bool KProcess::setExecutable(const QString& proc) +{ + if (runs) return false; + + if (proc.isEmpty()) return false; + + if (!arguments.isEmpty()) + arguments.remove(arguments.begin()); + arguments.prepend(QFile::encodeName(proc)); + + return true; +} + +KProcess &KProcess::operator<<(const QStringList& args) +{ + QStringList::ConstIterator it = args.begin(); + for ( ; it != args.end() ; ++it ) + arguments.append(QFile::encodeName(*it)); + return *this; +} + +KProcess &KProcess::operator<<(const QCString& arg) +{ + return operator<< (arg.data()); +} + +KProcess &KProcess::operator<<(const char* arg) +{ + arguments.append(arg); + return *this; +} + +KProcess &KProcess::operator<<(const QString& arg) +{ + arguments.append(QFile::encodeName(arg)); + return *this; +} + +void KProcess::clearArguments() +{ + arguments.clear(); +} + +bool KProcess::start(RunMode runmode, Communication comm) +{ + uint i; + uint n = arguments.count(); + char **arglist; + + if (runs || (0 == n)) { + return false; // cannot start a process that is already running + // or if no executable has been assigned + } + run_mode = runmode; + status = 0; + + QCString shellCmd; + if (d && d->useShell) + { + if (d->shell.isEmpty()) + { + //kdDebug() << "Could not find a valid shell\n" << endl; + return false; + } + + arglist = static_cast(malloc( (4)*sizeof(char *))); + for (i=0; i < n; i++) { + shellCmd += arguments[i]; + shellCmd += " "; // CC: to separate the arguments + } + + arglist[0] = d->shell.data(); + arglist[1] = (char *) "-c"; + arglist[2] = shellCmd.data(); + arglist[3] = 0; + } + else + { + arglist = static_cast(malloc( (n+1)*sizeof(char *))); + for (i=0; i < n; i++) + arglist[i] = arguments[i].data(); + arglist[n]= 0; + } + + setupCommunication(comm); + //) + //kdDebug() << "Could not setup Communication!\n"; + + // We do this in the parent because if we do it in the child process + // gdb gets confused when the application runs from gdb. + uid_t uid = getuid(); + gid_t gid = getgid(); +#ifdef HAVE_INITGROUPS + struct passwd *pw = getpwuid(uid); +#endif + + int fd[2]; + if (0 > pipe(fd)) + { + fd[0] = fd[1] = 0; // Pipe failed.. continue + } + + runs = true; + + QApplication::flushX(); + + // WABA: Note that we use fork() and not vfork() because + // vfork() has unclear semantics and is not standardized. + pid_ = fork(); + + if (0 == pid_) { + if (fd[0]) + close(fd[0]); + if (!runPrivileged()) + { + setgid(gid); +#if defined( HAVE_INITGROUPS) + if(pw) + initgroups(pw->pw_name, pw->pw_gid); +#endif + setuid(uid); + } + // The child process + commSetupDoneC(); + //) + //kdDebug() << "Could not finish comm setup in child!" << endl; + + setupEnvironment(); + + // Matthias + if (run_mode == DontCare) + setpgid(0,0); + // restore default SIGPIPE handler (Harri) + struct sigaction act; + sigemptyset(&(act.sa_mask)); + sigaddset(&(act.sa_mask), SIGPIPE); + act.sa_handler = SIG_DFL; + act.sa_flags = 0; + sigaction(SIGPIPE, &act, 0L); + + // We set the close on exec flag. + // Closing of fd[1] indicates that the execvp succeeded! + if (fd[1]) + fcntl(fd[1], F_SETFD, FD_CLOEXEC); + execvp(arglist[0], arglist); + char resultByte = 1; + if (fd[1]) + write(fd[1], &resultByte, 1); + _exit(-1); + } else if (-1 == pid_) { + // forking failed + + runs = false; + free(arglist); + return false; + } else { + if (fd[1]) + close(fd[1]); + // the parent continues here + + // Discard any data for stdin that might still be there + input_data = 0; + + // Check whether client could be started. + if (fd[0]) for(;;) + { + char resultByte; + int n = ::read(fd[0], &resultByte, 1); + if (n == 1) + { + // Error + runs = false; + close(fd[0]); + free(arglist); + pid_ = 0; + return false; + } + if (n == -1) + { + if ((errno == ECHILD) || (errno == EINTR)) + continue; // Ignore + } + break; // success + } + if (fd[0]) + close(fd[0]); + + if (!commSetupDoneP()){} // finish communication socket setup for the parent + //kdDebug() << "Could not finish comm setup in parent!" << endl; + + if (run_mode == Block) { + commClose(); + + // The SIGCHLD handler of the process controller will catch + // the exit and set the status + while(runs) + { + KProcessController::theKProcessController-> + slotDoHousekeeping(0); + } + runs = FALSE; + emit processExited(this); + } + } + free(arglist); + return true; +} + + + +bool KProcess::kill(int signo) +{ + bool rv=false; + + if (0 != pid_) + rv= (-1 != ::kill(pid_, signo)); + // probably store errno somewhere... + return rv; +} + + + +bool KProcess::isRunning() const +{ + return runs; +} + + + +pid_t KProcess::pid() const +{ + return pid_; +} + + + +bool KProcess::normalExit() const +{ + int _status = status; + return (pid_ != 0) && (!runs) && (WIFEXITED((_status))); +} + + + +int KProcess::exitStatus() const +{ + int _status = status; + return WEXITSTATUS((_status)); +} + + + +bool KProcess::writeStdin(const char *buffer, int buflen) +{ + bool rv; + + // if there is still data pending, writing new data + // to stdout is not allowed (since it could also confuse + // kprocess... + if (0 != input_data) + return false; + + if (runs && (communication & Stdin)) { + input_data = buffer; + input_sent = 0; + input_total = buflen; + slotSendData(0); + innot->setEnabled(true); + rv = true; + } else + rv = false; + return rv; +} + +void KProcess::suspend() +{ + if ((communication & Stdout) && outnot) + outnot->setEnabled(false); +} + +void KProcess::resume() +{ + if ((communication & Stdout) && outnot) + outnot->setEnabled(true); +} + +bool KProcess::closeStdin() +{ + bool rv; + + if (communication & Stdin) { + communication = (Communication) (communication & ~Stdin); + delete innot; + innot = 0; + close(in[1]); + rv = true; + } else + rv = false; + return rv; +} + +bool KProcess::closeStdout() +{ + bool rv; + + if (communication & Stdout) { + communication = (Communication) (communication & ~Stdout); + delete outnot; + outnot = 0; + close(out[0]); + rv = true; + } else + rv = false; + return rv; +} + +bool KProcess::closeStderr() +{ + bool rv; + + if (communication & Stderr) { + communication = static_cast(communication & ~Stderr); + delete errnot; + errnot = 0; + close(err[0]); + rv = true; + } else + rv = false; + return rv; +} + + +///////////////////////////// +// protected slots // +///////////////////////////// + + + +void KProcess::slotChildOutput(int fdno) +{ + if (!childOutput(fdno)) + closeStdout(); +} + + +void KProcess::slotChildError(int fdno) +{ + if (!childError(fdno)) + closeStderr(); +} + + +void KProcess::slotSendData(int) +{ + if (input_sent == input_total) { + innot->setEnabled(false); + input_data = 0; + emit wroteStdin(this); + } else + input_sent += ::write(in[1], input_data+input_sent, input_total-input_sent); +} + + + +////////////////////////////// +// private member functions // +////////////////////////////// + + + +void KProcess::processHasExited(int state) +{ + if (runs) + { + runs = false; + status = state; + + commClose(); // cleanup communication sockets + + // also emit a signal if the process was run Blocking + if (DontCare != run_mode) + { + emit processExited(this); + } + } +} + + + +int KProcess::childOutput(int fdno) +{ + if (communication & NoRead) { + int len = -1; + emit receivedStdout(fdno, len); + errno = 0; // Make sure errno doesn't read "EAGAIN" + return len; + } + else + { + char buffer[1024]; + int len; + + len = ::read(fdno, buffer, 1024); + + if ( 0 < len) { + emit receivedStdout(this, buffer, len); + } + return len; + } +} + + + +int KProcess::childError(int fdno) +{ + char buffer[1024]; + int len; + + len = ::read(fdno, buffer, 1024); + + if ( 0 < len) + emit receivedStderr(this, buffer, len); + return len; +} + + + +int KProcess::setupCommunication(Communication comm) +{ + int ok; + + communication = comm; + + ok = 1; + if (comm & Stdin) + ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, in) >= 0; + + if (comm & Stdout) + ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, out) >= 0; + + if (comm & Stderr) + ok &= socketpair(AF_UNIX, SOCK_STREAM, 0, err) >= 0; + + return ok; +} + + + +int KProcess::commSetupDoneP() +{ + int ok = 1; + + if (communication != NoCommunication) { + if (communication & Stdin) + close(in[0]); + if (communication & Stdout) + close(out[1]); + if (communication & Stderr) + close(err[1]); + + // Don't create socket notifiers and set the sockets non-blocking if + // blocking is requested. + if (run_mode == Block) return ok; + + if (communication & Stdin) { +// ok &= (-1 != fcntl(in[1], F_SETFL, O_NONBLOCK)); + innot = new QSocketNotifier(in[1], QSocketNotifier::Write, this); + Q_CHECK_PTR(innot); + innot->setEnabled(false); // will be enabled when data has to be sent + QObject::connect(innot, SIGNAL(activated(int)), + this, SLOT(slotSendData(int))); + } + + if (communication & Stdout) { +// ok &= (-1 != fcntl(out[0], F_SETFL, O_NONBLOCK)); + outnot = new QSocketNotifier(out[0], QSocketNotifier::Read, this); + Q_CHECK_PTR(outnot); + QObject::connect(outnot, SIGNAL(activated(int)), + this, SLOT(slotChildOutput(int))); + if (communication & NoRead) + suspend(); + } + + if (communication & Stderr) { +// ok &= (-1 != fcntl(err[0], F_SETFL, O_NONBLOCK)); + errnot = new QSocketNotifier(err[0], QSocketNotifier::Read, this ); + Q_CHECK_PTR(errnot); + QObject::connect(errnot, SIGNAL(activated(int)), + this, SLOT(slotChildError(int))); + } + } + return ok; +} + + + +int KProcess::commSetupDoneC() +{ + int ok = 1; + struct linger so; + memset(&so, 0, sizeof(so)); + + if (communication & Stdin) + close(in[1]); + if (communication & Stdout) + close(out[0]); + if (communication & Stderr) + close(err[0]); + + if (communication & Stdin) + ok &= dup2(in[0], STDIN_FILENO) != -1; + else { + int null_fd = open( "/dev/null", O_RDONLY ); + ok &= dup2( null_fd, STDIN_FILENO ) != -1; + close( null_fd ); + } + if (communication & Stdout) { + ok &= dup2(out[1], STDOUT_FILENO) != -1; + ok &= !setsockopt(out[1], SOL_SOCKET, SO_LINGER, (char*)&so, sizeof(so)); + } + else { + int null_fd = open( "/dev/null", O_WRONLY ); + ok &= dup2( null_fd, STDOUT_FILENO ) != -1; + close( null_fd ); + } + if (communication & Stderr) { + ok &= dup2(err[1], STDERR_FILENO) != -1; + ok &= !setsockopt(err[1], SOL_SOCKET, SO_LINGER, reinterpret_cast(&so), sizeof(so)); + } + else { + int null_fd = open( "/dev/null", O_WRONLY ); + ok &= dup2( null_fd, STDERR_FILENO ) != -1; + close( null_fd ); + } + return ok; +} + + + +void KProcess::commClose() +{ + if (NoCommunication != communication) { + bool b_in = (communication & Stdin); + bool b_out = (communication & Stdout); + bool b_err = (communication & Stderr); + if (b_in) + delete innot; + + if (b_out || b_err) { + // If both channels are being read we need to make sure that one socket buffer + // doesn't fill up whilst we are waiting for data on the other (causing a deadlock). + // Hence we need to use select. + + // Once one or other of the channels has reached EOF (or given an error) go back + // to the usual mechanism. + + int fds_ready = 1; + fd_set rfds; + + int max_fd = 0; + if (b_out) { + fcntl(out[0], F_SETFL, O_NONBLOCK); + if (out[0] > max_fd) + max_fd = out[0]; + delete outnot; + outnot = 0; + } + if (b_err) { + fcntl(err[0], F_SETFL, O_NONBLOCK); + if (err[0] > max_fd) + max_fd = err[0]; + delete errnot; + errnot = 0; + } + + + while (b_out || b_err) { + // * If the process is still running we block until we + // receive data. (p_timeout = 0, no timeout) + // * If the process has already exited, we only check + // the available data, we don't wait for more. + // (p_timeout = &timeout, timeout immediately) + struct timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + struct timeval *p_timeout = runs ? 0 : &timeout; + + FD_ZERO(&rfds); + if (b_out) + FD_SET(out[0], &rfds); + + if (b_err) + FD_SET(err[0], &rfds); + + fds_ready = select(max_fd+1, &rfds, 0, 0, p_timeout); + if (fds_ready <= 0) break; + + if (b_out && FD_ISSET(out[0], &rfds)) { + int ret = 1; + while (ret > 0) ret = childOutput(out[0]); + if ((ret == -1 && errno != EAGAIN) || ret == 0) + b_out = false; + } + + if (b_err && FD_ISSET(err[0], &rfds)) { + int ret = 1; + while (ret > 0) ret = childError(err[0]); + if ((ret == -1 && errno != EAGAIN) || ret == 0) + b_err = false; + } + } + } + + if (b_in) { + communication = (Communication) (communication & ~Stdin); + close(in[1]); + } + if (b_out) { + communication = (Communication) (communication & ~Stdout); + close(out[0]); + } + if (b_err) { + communication = (Communication) (communication & ~Stderr); + close(err[0]); + } + } +} + +void KProcess::setUseShell(bool useShell, const char *shell) +{ + if (!d) + d = new KProcessPrivate; + d->useShell = useShell; + d->shell = shell; + if (d->shell.isEmpty()) + d->shell = searchShell(); +} + +QString KProcess::quote(const QString &arg) +{ + QString res = arg; + res.replace(QRegExp(QString::fromLatin1("\'")), + QString::fromLatin1("'\"'\"'")); + res.prepend('\''); + res.append('\''); + return res; +} + +QCString KProcess::searchShell() +{ + QCString tmpShell = QCString(getenv("SHELL")).stripWhiteSpace(); + if (!isExecutable(tmpShell)) + { + tmpShell = "/bin/sh"; + } + + return tmpShell; +} + +bool KProcess::isExecutable(const QCString &filename) +{ + struct stat fileinfo; + + if (filename.isEmpty()) return false; + + // CC: we've got a valid filename, now let's see whether we can execute that file + + if (-1 == stat(filename.data(), &fileinfo)) return false; + // CC: return false if the file does not exist + + // CC: anyway, we cannot execute directories, block/character devices, fifos or sockets + if ( (S_ISDIR(fileinfo.st_mode)) || + (S_ISCHR(fileinfo.st_mode)) || + (S_ISBLK(fileinfo.st_mode)) || +#ifdef S_ISSOCK + // CC: SYSVR4 systems don't have that macro + (S_ISSOCK(fileinfo.st_mode)) || +#endif + (S_ISFIFO(fileinfo.st_mode)) || + (S_ISDIR(fileinfo.st_mode)) ) { + return false; + } + + // CC: now check for permission to execute the file + if (access(filename.data(), X_OK) != 0) return false; + + // CC: we've passed all the tests... + return true; +} + +void KProcess::virtual_hook( int, void* ) +{ /*BASE::virtual_hook( id, data );*/ } + + +/////////////////////////// +// CC: Class KShellProcess +/////////////////////////// + +KShellProcess::KShellProcess(const char *shellname): + KProcess() +{ + setUseShell(true, shellname); +} + + +KShellProcess::~KShellProcess() { +} + +QString KShellProcess::quote(const QString &arg) +{ + return KProcess::quote(arg); +} + +bool KShellProcess::start(RunMode runmode, Communication comm) +{ + return KProcess::start(runmode, comm); +} + +void KShellProcess::virtual_hook( int id, void* data ) +{ KProcess::virtual_hook( id, data ); } + +//#include "kprocess.moc" diff --git a/noncore/settings/networksettings/kprocess.h b/noncore/settings/networksettings/kprocess.h new file mode 100644 index 0000000..e70f7e7 --- a/dev/null +++ b/noncore/settings/networksettings/kprocess.h @@ -0,0 +1,804 @@ +/* This file is part of the KDE libraries + Copyright (C) 1997 Christian Czezakte (e9025461@student.tuwien.ac.at) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ +// +// KPROCESS -- A class for handling child processes in KDE without +// having to take care of Un*x specific implementation details +// +// version 0.3.1, Jan 8th 1998 +// +// (C) Christian Czezatke +// e9025461@student.tuwien.ac.at +// + +#ifndef __kprocess_h__ +#define __kprocess_h__ + +#include // for pid_t +#include +#include +#include +#include +#include +#include + +class QSocketNotifier; +class KProcessPrivate; + +/** + * Child process invocation, monitoring and control. + * + * @sect General usage and features + * + *This class allows a KDE application to start child processes without having + *to worry about UN*X signal handling issues and zombie process reaping. + * + *@see KProcIO + * + *Basically, this class distinguishes three different ways of running + *child processes: + * + *@li KProcess::DontCare -- The child process is invoked and both the child + *process and the parent process continue concurrently. + * + *Starting a DontCare child process means that the application is + *not interested in any notification to determine whether the + *child process has already exited or not. + * + *@li KProcess::NotifyOnExit -- The child process is invoked and both the + *child and the parent process run concurrently. + * + *When the child process exits, the KProcess instance + *corresponding to it emits the Qt signal @ref processExited(). + * + *Since this signal is @em not emitted from within a UN*X + *signal handler, arbitrary function calls can be made. + * + *Be aware: When the KProcess objects gets destructed, the child + *process will be killed if it is still running! + *This means in particular, that you cannot use a KProcess on the stack + *with KProcess::NotifyOnExit. + * + *@li KProcess::Block -- The child process starts and the parent process + *is suspended until the child process exits. (@em Really not recommended + *for programs with a GUI.) + * + *KProcess also provides several functions for determining the exit status + *and the pid of the child process it represents. + * + *Furthermore it is possible to supply command-line arguments to the process + *in a clean fashion (no null -- terminated stringlists and such...) + * + *A small usage example: + *
+ *KProcess *proc = new KProcess;
+ *
+ **proc << "my_executable";
+ **proc << "These" << "are" << "the" << "command" << "line" << "args";
+ *QApplication::connect(proc, SIGNAL(processExited(KProcess *)),
+ *                      pointer_to_my_object, SLOT(my_objects_slot(KProcess *)));
+ *proc->start();
+ *
+ * + *This will start "my_executable" with the commandline arguments "These"... + * + *When the child process exits, the respective Qt signal will be emitted. + * + *@sect Communication with the child process + * + *KProcess supports communication with the child process through + *stdin/stdout/stderr. + * + *The following functions are provided for getting data from the child + *process or sending data to the child's stdin (For more information, + *have a look at the documentation of each function): + * + *@li bool @ref writeStdin(char *buffer, int buflen); + *@li -- Transmit data to the child process's stdin. + * + *@li bool @ref closeStdin(); + *@li -- Closes the child process's stdin (which causes it to see an feof(stdin)). + *Returns false if you try to close stdin for a process that has been started + *without a communication channel to stdin. + * + *@li bool @ref closeStdout(); + *@li -- Closes the child process's stdout. + *Returns false if you try to close stdout for a process that has been started + *without a communication channel to stdout. + * + *@li bool @ref closeStderr(); + *@li -- Closes the child process's stderr. + *Returns false if you try to close stderr for a process that has been started + *without a communication channel to stderr. + * + * + *@sect QT signals: + * + *@li void @ref receivedStdout(KProcess *proc, char *buffer, int buflen); + *@li void @ref receivedStderr(KProcess *proc, char *buffer, int buflen); + *@li -- Indicates that new data has arrived from either the + *child process's stdout or stderr. + * + *@li void @ref wroteStdin(KProcess *proc); + *@li -- Indicates that all data that has been sent to the child process + *by a prior call to @ref writeStdin() has actually been transmitted to the + *client . + * + *@author Christian Czezakte e9025461@student.tuwien.ac.at + * + * + **/ +class KProcess : public QObject +{ + Q_OBJECT + +public: + + /** + * Modes in which the communication channel can be opened. + * + * If communication for more than one channel is required, + * the values have to be or'ed together, for example to get + * communication with stdout as well as with stdin, you would + * specify @p Stdin @p | @p Stdout + * + * If @p NoRead is specified in conjunction with @p Stdout, + * no data is actually read from @p Stdout but only + * the signal @ref childOutput(int fd) is emitted. + */ + enum Communication { NoCommunication = 0, Stdin = 1, Stdout = 2, Stderr = 4, + AllOutput = 6, All = 7, + NoRead }; + + /** + * Run-modes for a child process. + */ + enum RunMode { + /** + * The application does not receive notifications from the subprocess when + * it is finished or aborted. + */ + DontCare, + /** + * The application is notified when the subprocess dies. + */ + NotifyOnExit, + /** + * The application is suspended until the started process is finished. + */ + Block }; + + /** + * Constructor + */ + KProcess(); + + /** + *Destructor: + * + * If the process is running when the destructor for this class + * is called, the child process is killed with a SIGKILL, but + * only if the run mode is not of type @p DontCare. + * Processes started as @p DontCare keep running anyway. + */ + virtual ~KProcess(); + + /** + @deprecated + + The use of this function is now deprecated. -- Please use the + "operator<<" instead of "setExecutable". + + Sets the executable to be started with this KProcess object. + Returns false if the process is currently running (in that + case the executable remains unchanged.) + + @see operator<< + + */ + bool setExecutable(const QString& proc); + + + /** + * Sets the executable and the command line argument list for this process. + * + * For example, doing an "ls -l /usr/local/bin" can be achieved by: + *
+   *  KProcess p;
+   *  ...
+   *  p << "ls" << "-l" << "/usr/local/bin"
+   *  
+ * + **/ + KProcess &operator<<(const QString& arg); + /** + * Similar to previous method, takes a char *, supposed to be in locale 8 bit already. + */ + KProcess &operator<<(const char * arg); + /** + * Similar to previous method, takes a QCString, supposed to be in locale 8 bit already. + */ + KProcess &operator<<(const QCString & arg); + + /** + * Sets the executable and the command line argument list for this process, + * in a single method call, or add a list of arguments. + **/ + KProcess &operator<<(const QStringList& args); + + /** + * Clear a command line argument list that has been set by using + * the "operator<<". + */ + void clearArguments(); + + /** + * Starts the process. + * For a detailed description of the + * various run modes and communication semantics, have a look at the + * general description of the KProcess class. + * + * The following problems could cause this function to + * return false: + * + * @li The process is already running. + * @li The command line argument list is empty. + * @li The starting of the process failed (could not fork). + * @li The executable was not found. + * + * @param comm Specifies which communication links should be + * established to the child process (stdin/stdout/stderr). By default, + * no communication takes place and the respective communication + * signals will never get emitted. + * + * @return true on success, false on error + * (see above for error conditions) + **/ + virtual bool start(RunMode runmode = NotifyOnExit, + Communication comm = NoCommunication); + + /** + * Stop the process (by sending it a signal). + * + * @param signo The signal to send. The default is SIGTERM. + * @return @p true if the signal was delivered successfully. + */ + virtual bool kill(int signo = SIGTERM); + + /** + @return @p true if the process is (still) considered to be running + */ + bool isRunning() const; + + /** Returns the process id of the process. + * + * If it is called after + * the process has exited, it returns the process id of the last + * child process that was created by this instance of KProcess. + * + * Calling it before any child process has been started by this + * KProcess instance causes pid() to return 0. + **/ + pid_t pid() const; + + /** + * Use pid(). + * @deprecated + */ + pid_t getPid() const { return pid(); } + + /** + * Suspend processing of data from stdout of the child process. + */ + void suspend(); + + /** + * Resume processing of data from stdout of the child process. + */ + void resume(); + + /** + * @return @p true if the process has already finished and has exited + * "voluntarily", ie: it has not been killed by a signal. + * + * Note that you should check @ref KProcess::exitStatus() to determine + * whether the process completed its task successful or not. + */ + bool normalExit() const; + + /** + * Returns the exit status of the process. + * + * Please use + * @ref KProcess::normalExit() to check whether the process has exited + * cleanly (i.e., @ref KProcess::normalExit() returns @p true) before calling + * this function because if the process did not exit normally, + * it does not have a valid exit status. + */ + int exitStatus() const; + + + /** + * Transmit data to the child process's stdin. + * + * KProcess::writeStdin may return false in the following cases: + * + * @li The process is not currently running. + * + * @li Communication to stdin has not been requested in the @ref start() call. + * + * @li Transmission of data to the child process by a previous call to + * @ref writeStdin() is still in progress. + * + * Please note that the data is sent to the client asynchronously, + * so when this function returns, the data might not have been + * processed by the child process. + * + * If all the data has been sent to the client, the signal + * @ref wroteStdin() will be emitted. + * + * Please note that you must not free "buffer" or call @ref writeStdin() + * again until either a @ref wroteStdin() signal indicates that the + * data has been sent or a @ref processHasExited() signal shows that + * the child process is no longer alive... + **/ + bool writeStdin(const char *buffer, int buflen); + + /** + * This causes the stdin file descriptor of the child process to be + * closed indicating an "EOF" to the child. + * + * @return @p false if no communication to the process's stdin + * had been specified in the call to @ref start(). + */ + bool closeStdin(); + + /** + * This causes the stdout file descriptor of the child process to be + * closed. + * + * @return @p false if no communication to the process's stdout + * had been specified in the call to @ref start(). + */ + bool closeStdout(); + + /** + * This causes the stderr file descriptor of the child process to be + * closed. + * + * @return @p false if no communication to the process's stderr + * had been specified in the call to @ref start(). + */ + bool closeStderr(); + + /** + * Lets you see what your arguments are for debugging. + */ + + const QValueList &args() { return arguments; } + + /** + * Controls whether the started process should drop any + * setuid/segid privileges or whether it should keep them + * + * The default is @p false : drop privileges + */ + void setRunPrivileged(bool keepPrivileges); + + /** + * Returns whether the started process will drop any + * setuid/segid privileges or whether it will keep them + */ + bool runPrivileged() const; + + /** + * Modifies the environment of the process to be started. + * This function must be called before starting the process. + */ + void setEnvironment(const QString &name, const QString &value); + + /** + * Changes the current working directory (CWD) of the process + * to be started. + * This function must be called before starting the process. + */ + void setWorkingDirectory(const QString &dir); + + /** + * Specify whether to start the command via a shell or directly. + * The default is to start the command directly. + * If @p useShell is true @p shell will be used as shell, or + * if shell is empty, the standard shell is used. + * @p quote A flag indicating whether to quote the arguments. + * + * When using a shell, the caller should make sure that all filenames etc. + * are properly quoted when passed as argument. + * @see quote() + */ + void setUseShell(bool useShell, const char *shell = 0); + + /** + * This function can be used to quote an argument string such that + * the shell processes it properly. This is e. g. necessary for + * user-provided file names which may contain spaces or quotes. + * It also prevents expansion of wild cards and environment variables. + */ + static QString quote(const QString &arg); + + /** + * Detaches KProcess from child process. All communication is closed. + * No exit notification is emitted any more for the child process. + * Deleting the KProcess will no longer kill the child process. + * Note that the current process remains the parent process of the + * child process. + */ + void detach(); + + + +signals: + + /** + * Emitted after the process has terminated when + * the process was run in the @p NotifyOnExit (==default option to + * @ref start()) or the @ref Block mode. + **/ + void processExited(KProcess *proc); + + + /** + * Emitted, when output from the child process has + * been received on stdout. + * + * To actually get + * these signals, the respective communication link (stdout/stderr) + * has to be turned on in @ref start(). + * + * @param buffer The data received. + * @param buflen The number of bytes that are available. + * + * You should copy the information contained in @p buffer to your private + * data structures before returning from this slot. + **/ + void receivedStdout(KProcess *proc, char *buffer, int buflen); + + /** + * Emitted when output from the child process has + * been received on stdout. + * + * To actually get these signals, the respective communications link + * (stdout/stderr) has to be turned on in @ref start() and the + * @p NoRead flag should have been passed. + * + * You will need to explicitly call resume() after your call to start() + * to begin processing data from the child process's stdout. This is + * to ensure that this signal is not emitted when no one is connected + * to it, otherwise this signal will not be emitted. + * + * The data still has to be read from file descriptor @p fd. + **/ + void receivedStdout(int fd, int &len); + + + /** + * Emitted, when output from the child process has + * been received on stderr. + * To actually get + * these signals, the respective communication link (stdout/stderr) + * has to be turned on in @ref start(). + * + * @param buffer The data received. + * @param buflen The number of bytes that are available. + * + * You should copy the information contained in @p buffer to your private + * data structures before returning from this slot. + */ + void receivedStderr(KProcess *proc, char *buffer, int buflen); + + /** + * Emitted after all the data that has been + * specified by a prior call to @ref writeStdin() has actually been + * written to the child process. + **/ + void wroteStdin(KProcess *proc); + + +protected slots: + + /** + * This slot gets activated when data from the child's stdout arrives. + * It usually calls "childOutput" + */ + void slotChildOutput(int fdno); + + /** + * This slot gets activated when data from the child's stderr arrives. + * It usually calls "childError" + */ + void slotChildError(int fdno); + /* + Slot functions for capturing stdout and stderr of the child + */ + + /** + * Called when another bulk of data can be sent to the child's + * stdin. If there is no more data to be sent to stdin currently + * available, this function must disable the QSocketNotifier "innot". + */ + void slotSendData(int dummy); + +protected: + + /** + * Sets up the environment according to the data passed via + * setEnvironment(...) + */ + void setupEnvironment(); + + /** + * The list of the process' command line arguments. The first entry + * in this list is the executable itself. + */ + QValueList arguments; + /** + * How to run the process (Block, NotifyOnExit, DontCare). You should + * not modify this data member directly from derived classes. + */ + RunMode run_mode; + /** + * true if the process is currently running. You should not + * modify this data member directly from derived classes. For + * reading the value of this data member, please use "isRunning()" + * since "runs" will probably be made private in later versions + * of KProcess. + */ + bool runs; + + /** + * The PID of the currently running process (see "getPid()"). + * You should not modify this data member in derived classes. + * Please use "getPid()" instead of directly accessing this + * member function since it will probably be made private in + * later versions of KProcess. + */ + pid_t pid_; + + /** + * The process' exit status as returned by "waitpid". You should not + * modify the value of this data member from derived classes. You should + * rather use @ref exitStatus than accessing this data member directly + * since it will probably be made private in further versions of + * KProcess. + */ + int status; + + + /** + * See setRunPrivileged() + */ + bool keepPrivs; + + /* + Functions for setting up the sockets for communication. + setupCommunication + -- is called from "start" before "fork"ing. + commSetupDoneP + -- completes communication socket setup in the parent + commSetupDoneC + -- completes communication setup in the child process + commClose + -- frees all allocated communication resources in the parent + after the process has exited + */ + + /** + * This function is called from "KProcess::start" right before a "fork" takes + * place. According to + * the "comm" parameter this function has to initialize the "in", "out" and + * "err" data member of KProcess. + * + * This function should return 0 if setting the needed communication channels + * was successful. + * + * The default implementation is to create UNIX STREAM sockets for the communication, + * but you could overload this function and establish a TCP/IP communication for + * network communication, for example. + */ + virtual int setupCommunication(Communication comm); + + /** + * Called right after a (successful) fork on the parent side. This function + * will usually do some communications cleanup, like closing the reading end + * of the "stdin" communication channel. + * + * Furthermore, it must also create the QSocketNotifiers "innot", "outnot" and + * "errnot" and connect their Qt slots to the respective KProcess member functions. + * + * For a more detailed explanation, it is best to have a look at the default + * implementation of "setupCommunication" in kprocess.cpp. + */ + virtual int commSetupDoneP(); + + /** + * Called right after a (successful) fork, but before an "exec" on the child + * process' side. It usually just closes the unused communication ends of + * "in", "out" and "err" (like the writing end of the "in" communication + * channel. + */ + virtual int commSetupDoneC(); + + + /** + * Immediately called after a process has exited. This function normally + * calls commClose to close all open communication channels to this + * process and emits the "processExited" signal (if the process was + * not running in the "DontCare" mode). + */ + virtual void processHasExited(int state); + + /** + * Should clean up the communication links to the child after it has + * exited. Should be called from "processHasExited". + */ + virtual void commClose(); + + + /** + * the socket descriptors for stdin/stdout/stderr. + */ + int out[2]; + int in[2]; + int err[2]; + + /** + * The socket notifiers for the above socket descriptors. + */ + QSocketNotifier *innot; + QSocketNotifier *outnot; + QSocketNotifier *errnot; + + /** + * Lists the communication links that are activated for the child + * process. Should not be modified from derived classes. + */ + Communication communication; + + /** + * Called by "slotChildOutput" this function copies data arriving from the + * child process's stdout to the respective buffer and emits the signal + * "@ref receivedStderr". + */ + int childOutput(int fdno); + + /** + * Called by "slotChildOutput" this function copies data arriving from the + * child process's stdout to the respective buffer and emits the signal + * "@ref receivedStderr" + */ + int childError(int fdno); + + // information about the data that has to be sent to the child: + + const char *input_data; // the buffer holding the data + int input_sent; // # of bytes already transmitted + int input_total; // total length of input_data + + /** + * @ref KProcessController is a friend of KProcess because it has to have + * access to various data members. + */ + friend class KProcessController; + + +private: + /** + * Searches for a valid shell. + * Here is the algorithm used for finding an executable shell: + * + * @li Try the executable pointed to by the "SHELL" environment + * variable with white spaces stripped off + * + * @li If your process runs with uid != euid or gid != egid, a shell + * not listed in /etc/shells will not used. + * + * @li If no valid shell could be found, "/bin/sh" is used as a last resort. + */ + QCString searchShell(); + + /** + * Used by @ref searchShell in order to find out whether the shell found + * is actually executable at all. + */ + bool isExecutable(const QCString &filename); + + // Disallow assignment and copy-construction + KProcess( const KProcess& ); + KProcess& operator= ( const KProcess& ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KProcessPrivate *d; +}; + +class KShellProcessPrivate; + +/** +* @obsolete +* +* This class is obsolete. Use KProcess and KProcess::setUseShell(true) +* instead. +* +* @short A class derived from @ref KProcess to start child +* processes through a shell. +* @author Christian Czezakte +* @version $Id$ +*/ +class KShellProcess: public KProcess +{ + Q_OBJECT + +public: + + /** + * Constructor + * + * By specifying the name of a shell (like "/bin/bash") you can override + * the mechanism for finding a valid shell as described in KProcess::searchShell() + */ + KShellProcess(const char *shellname=0); + + /** + * Destructor. + */ + ~KShellProcess(); + + /** + * Starts up the process. -- For a detailed description + * have a look at the "start" member function and the detailed + * description of @ref KProcess . + */ + virtual bool start(RunMode runmode = NotifyOnExit, + Communication comm = NoCommunication); + + /** + * This function can be used to quote an argument string such that + * the shell processes it properly. This is e. g. necessary for + * user-provided file names which may contain spaces or quotes. + * It also prevents expansion of wild cards and environment variables. + */ + static QString quote(const QString &arg); + +private: + + QCString shell; + + // Disallow assignment and copy-construction + KShellProcess( const KShellProcess& ); + KShellProcess& operator= ( const KShellProcess& ); + +protected: + virtual void virtual_hook( int id, void* data ); +private: + KShellProcessPrivate *d; +}; + + + +#endif + diff --git a/noncore/settings/networksettings/main.cpp b/noncore/settings/networksettings/main.cpp new file mode 100644 index 0000000..52cb92b --- a/dev/null +++ b/noncore/settings/networksettings/main.cpp @@ -0,0 +1,13 @@ +#include "mainwindowimp.h" +#include + +int main(int argc, char **argv) +{ + QPEApplication app(argc, argv); + MainWindowImp window; + window.showMaximized(); + return app.exec(); +} + +// main.cpp + diff --git a/noncore/settings/networksettings/mainwindow.ui b/noncore/settings/networksettings/mainwindow.ui new file mode 100644 index 0000000..b8c0675 --- a/dev/null +++ b/noncore/settings/networksettings/mainwindow.ui @@ -0,0 +1,321 @@ + +MainWindow + + QWidget + + name + MainWindow + + + geometry + + 0 + 0 + 222 + 289 + + + + caption + Network Setup + + + + margin + 0 + + + spacing + 6 + + + QTabWidget + + name + tabWidget + + + layoutMargin + + + QWidget + + name + Widget3 + + + title + Interfaces + + + + margin + 0 + + + spacing + 6 + + + QListView + + + text + i + + + clickable + true + + + resizeable + true + + + + + text + t + + + clickable + true + + + resizeable + true + + + + + text + Name + + + clickable + true + + + resizeable + true + + + + name + serviceList + + + allColumnsShowFocus + true + + + + QLayoutWidget + + name + Layout2 + + + layoutMargin + + + + margin + 5 + + + spacing + 6 + + + QPushButton + + name + addServiceButton + + + text + &Add + + + + QPushButton + + name + informationServiceButton + + + text + &Information + + + + QPushButton + + name + configureServiceButton + + + text + &Configure + + + + QPushButton + + name + removeServiceButton + + + text + &Remove + + + + + + + + QWidget + + name + tab + + + title + Profiles + + + + margin + 11 + + + spacing + 6 + + + QLabel + + name + TextLabel3 + + + text + Change Profile To + + + + QLabel + + name + TextLabel1 + + + text + Current Profile + + + + QLabel + + name + TextLabel2 + + + frameShape + Panel + + + frameShadow + Sunken + + + text + All + + + + QComboBox + + + text + All + + + + name + ComboBox10 + + + + QPushButton + + name + removeProfileButton + + + text + &Remove + + + + QPushButton + + name + newProfileButton + + + text + &New + + + + + name + Spacer16 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + + + + + QWidget +
qwidget.h
+ + 100 + 100 + + 0 + + 7 + 7 + + image0 +
+
+ + + image0 + 789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758 + + +
diff --git a/noncore/settings/networksettings/mainwindowimp.cpp b/noncore/settings/networksettings/mainwindowimp.cpp new file mode 100644 index 0000000..3c13143 --- a/dev/null +++ b/noncore/settings/networksettings/mainwindowimp.cpp @@ -0,0 +1,308 @@ +#include "mainwindowimp.h" +#include "addserviceimp.h" +#include "interfaceinformationimp.h" +#include "interfacesetupimp.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +// For library loading. +#include + +#define TEMP_ALL "/tmp/ifconfig-a" +#define TEMP_UP "/tmp/ifconfig" + +#define NO_SELECT_ERROR_AND_RETURN { \ + QMessageBox::information(this, "Error","Please select an interface.", "Ok"); \ + return; \ +} + +MainWindowImp::MainWindowImp(QWidget *parent, const char *name) : MainWindow(parent, name, true) { + connect(addServiceButton, SIGNAL(clicked()), this, SLOT(addClicked())); + connect(removeServiceButton, SIGNAL(clicked()), this, SLOT(removeClicked())); + connect(informationServiceButton, SIGNAL(clicked()), this, SLOT(informationClicked())); + connect(configureServiceButton, SIGNAL(clicked()), this, SLOT(configureClicked())); + // Make sure we have a plugin directory to scan. + QString DirStr = QDir::homeDirPath() + "/.networksetup/" ; + QDir pluginDir( DirStr ); + pluginDir.mkdir( DirStr ); + pluginDir.mkdir( ( DirStr + "plugins/" ) ); + QString path = DirStr + "plugins"; + pluginDir.setPath(path); + if(!pluginDir.exists()){ + qDebug(QString("MainWindowImp: ERROR: %1 %2").arg(__FILE__).arg(__LINE__).latin1()); + return; + } + + // Load any saved services. + loadModules(path); + getInterfaceList(); + serviceList->header()->hide(); +} + +/** + * Deconstructor. Unload libraries and save. + */ +MainWindowImp::~MainWindowImp(){ +} + +void MainWindowImp::loadModules(QString path){ +} + +/** + * Attempt to load a function and resolve a function. + * @param pluginFileName - the name of the file in which to attempt to load + * @param resolveString - function pointer to resolve + * @return pointer to the function with name resolveString or NULL + */ +Module* MainWindowImp::loadPlugin(QString pluginFileName, QString resolveString){ + //qDebug(pluginFileName.latin1()); + QLibrary *lib = new QLibrary(pluginFileName); + void *functionPointer = lib->resolve(resolveString); + if( !functionPointer ){ + qDebug(QString("MainWindowImp: File: %1 is not a plugin, but though was.").arg(pluginFileName).latin1()); + delete lib; + return NULL; + } + + // Try to get an object. + Module *object = ((Module* (*)()) functionPointer)(); + if(object == NULL){ + qDebug("MainWindowImp: Couldn't create object, but did load library!"); + delete lib; + return NULL; + } + + // Store for reference + libraries.insert(object, lib); + return object; +} + +/* +QList MainWindowImp::retrieveUnloadedPluginList(){ + QString DirStr = QDir::homeDirPath() + "/.networksetup/" ; + QString path = DirStr + "plugins"; + QDir d(path); + d.setFilter( QDir::Files | QDir::Hidden ); + + QMap::Iterator libraryIt; + QList rlist; + rlist.setAutoDelete(false); + + const QFileInfoList *list = d.entryInfoList(); + QFileInfoListIterator it( *list ); + QFileInfo *fi; + while ( (fi=it.current()) ) { + if(fi->fileName().contains(".so")){ + for( libraryIt = libraries.begin(); libraryIt != libraries.end(); ++libraryIt ) + if((path + "/" + fi->fileName()) != (libraryIt.data())->library()){ + QString *s = new QString(path + "/" + fi->fileName()); + rlist.append(s); + } + } + ++it; + } + return rlist; +} +*/ + +/** + * The Add button was clicked. Bring up the add dialog and if OK is hit + * load the plugin and append it to the list + */ +void MainWindowImp::addClicked(){ + // Now that we have a list of all of the protocals, list them. + { + QMessageBox::information(this, "No Modules", "Nothing to add.", "Ok"); + return; + } + AddServiceImp service(this, "AddService", true); + service.showMaximized(); + service.exec(); +} + +/** + * Prompt the user to see if they really want to do this. + * If they do then remove from the list and unload. + */ +void MainWindowImp::removeClicked(){ + QListViewItem *item = serviceList->currentItem(); + if(item == NULL) NO_SELECT_ERROR_AND_RETURN + + if(modules.find(interfaceItems[item]) == modules.end()){ + QMessageBox::information(this, "Can't remove interface.", "Interface is built in.", "Ok"); + } + else{ + // Try to remove. + } + +} + +/** + * See if there is a configuration for the selected protocal. + * Prompt with errors. + */ +void MainWindowImp::configureClicked(){ + QListViewItem *item = serviceList->currentItem(); + if(item == NULL) NO_SELECT_ERROR_AND_RETURN + + if(modules.find(interfaceItems[item]) == modules.end()){ + InterfaceSetupImp *conf = new InterfaceSetupImp(0, "InterfaceConfiguration", interfaceItems[item]); + conf->showMaximized(); + conf->show(); + } + else{ + InterfaceSetupImp *conf = new InterfaceSetupImp(this, "InterfaceConfiguration"); + conf->show(); + } +} + +/** + * Pull up the information about the selected interface + * Report an error + */ +void MainWindowImp::informationClicked(){ + QListViewItem *item = serviceList->currentItem(); + if(item == NULL)NO_SELECT_ERROR_AND_RETURN + + if(modules.find(interfaceItems[item]) == modules.end()){ + InterfaceInformationImp *i = new InterfaceInformationImp(0, "InterfaceInformationImp", interfaceItems[item]); + i->showMaximized(); + i->show(); + } + else{ + QTabWidget *t = new QTabWidget(this, "InterfaceInformationTAB"); + InterfaceInformationImp *i = new InterfaceInformationImp(t, "TCPIPInformation", interfaceItems[item], true); + t->insertTab(i, "TCP/IP"); + t->show(); + } +} + +/** + * Aquire the list of active interfaces from ifconfig + * Call ifconfig and ifconfig -a + */ +void MainWindowImp::getInterfaceList(){ + KShellProcess *processAll = new KShellProcess(); + *processAll << "/sbin/ifconfig" << "-a" << " > " TEMP_ALL; + connect(processAll, SIGNAL(processExited(KProcess *)), + this, SLOT(jobDone(KProcess *))); + threads.insert(processAll, TEMP_ALL); + processAll->start(KShellProcess::NotifyOnExit); + + KShellProcess *process = new KShellProcess(); + *process << "/sbin/ifconfig" << " > " TEMP_UP; + connect(process, SIGNAL(processExited(KProcess *)), + this, SLOT(jobDone(KProcess *))); + threads.insert(process, TEMP_UP); + process->start(KShellProcess::NotifyOnExit); +} + +void MainWindowImp::jobDone(KProcess *process){ + QString fileName = threads[process]; + threads.remove(process); + delete process; + + QFile file(fileName); + if (!file.open(IO_ReadOnly)){ + qDebug(QString("MainWindowImp: Can't open file: %1").arg(fileName).latin1()); + return; + } + + QTextStream stream( &file ); + QString line; + while ( !stream.eof() ) { + line = stream.readLine(); + int space = line.find(" "); + if(space > 1){ + // We have found an interface + QString interfaceName = line.mid(0, space); + Interface *i; + // See if we already have it + if(interfaceNames.find(interfaceName) == interfaceNames.end()){ + if(fileName == TEMP_ALL) + i = new Interface(interfaceName, false); + else + i = new Interface(interfaceName, true); + } + else{ + i = interfaceNames[interfaceName]; + if(fileName != TEMP_ALL) + i->setStatus(true); + } + + i->setAttached(true); + i->setInterfaceName(interfaceName); + + QString hardName = "Ethernet"; + int hardwareName = line.find("Link encap:"); + int macAddress = line.find("HWaddr"); + if(macAddress == -1) + macAddress = line.length(); + if(hardwareName != -1) + i->setHardwareName(line.mid(hardwareName+11, macAddress-(hardwareName+11))); + // We have found an interface + //qDebug(QString("MainWindowImp: Found Interface: %1").arg(line).latin1()); + interfaceNames.insert(i->getInterfaceName(), i); + updateInterface(i); + } + } + file.close(); + QFile::remove(fileName); +} + +void MainWindowImp::updateInterface(Interface *i){ + QListViewItem *item = NULL; + + // See if we already have it + if(items.find(i) == items.end()){ + item = new QListViewItem(serviceList, "", "", ""); + // See if you can't find a module owner for this interface + //EmployeeMap::Iterator it; + //for( it = map.begin(); it != map.end(); ++it ) + // printf( "%s, %s earns %d\n", it.key().latin1(), it.data().name().latin1(), it.data().salary() ); + + items.insert(i, item); + interfaceItems.insert(item, i); + } + else + item = items[i]; + + QString statusImage = "down"; + if(i->getStatus()) + statusImage = "up"; + QPixmap status = (Resource::loadPixmap(statusImage)); + item->setPixmap(0, status); + + QString typeName = "lan"; + if(i->getHardwareName().contains("Local Loopback")) + typeName = "lo"; + QPixmap type = (Resource::loadPixmap(typeName)); + item->setPixmap(1, type); + + item->setText(2, i->getHardwareName()); + +} + +void MainWindowImp::addProfile(){ + +} + +void MainWindowImp::removeProfile(){ + +} + +// mainwindowimp.cpp + diff --git a/noncore/settings/networksettings/mainwindowimp.h b/noncore/settings/networksettings/mainwindowimp.h new file mode 100644 index 0000000..95ec2a1 --- a/dev/null +++ b/noncore/settings/networksettings/mainwindowimp.h @@ -0,0 +1,53 @@ +#ifndef MAINWINOWIMP_H +#define MAINWINOWIMP_H + +#include "mainwindow.h" +#include "module.h" +#include "interface.h" +#include "kprocess.h" +#include + +class QLibrary; + +class MainWindowImp : public MainWindow { + Q_OBJECT + +public: + MainWindowImp(QWidget *parent=0, const char *name=0); + ~MainWindowImp(); + +private slots: + void addClicked(); + void removeClicked(); + void configureClicked(); + void informationClicked(); + + void jobDone(KProcess *process); + void getInterfaceList(); + + void addProfile(); + void removeProfile(); + + void updateInterface(Interface *i); + +private: + void loadModules(QString path); + + Module* loadPlugin(QString pluginFileName, + QString resolveString = "create_plugin"); + + // For our local list of names + QMap interfaceNames; + + QMap libraries; + QMap modules; + QMap items; + QMap interfaceItems; + + QMap threads; +}; + +#endif + +// mainwindowimp.h + diff --git a/noncore/settings/networksettings/module.h b/noncore/settings/networksettings/module.h new file mode 100644 index 0000000..f146d8c --- a/dev/null +++ b/noncore/settings/networksettings/module.h @@ -0,0 +1,33 @@ +#ifndef MODULE_H +#define MODULE_H + +#include +#include +#include +#include "interface.h" + +class QWidget; + +class Module : QObject{ + +signals: + void updateInterface(Interface *i); + +public: + Module(){}; + + virtual bool isOwner(Interface *){ return false; }; + virtual QWidget *configure(){ return NULL; } ; + virtual QWidget *information(){ return NULL; }; + virtual QList getInterfaces() = 0; + virtual QMap possibleNewInterfaces() = 0; + virtual Interface *addNewInterface(QString name) = 0; + virtual bool remove(Interface* i) = 0; + + +}; + +#endif + +// module.h + diff --git a/noncore/settings/networksettings/networksetup.pro b/noncore/settings/networksettings/networksetup.pro new file mode 100644 index 0000000..7d9918b --- a/dev/null +++ b/noncore/settings/networksettings/networksetup.pro @@ -0,0 +1,10 @@ +TEMPLATE = app +CONFIG = qt warn_on debug +#CONFIG = qt warn_on release +HEADERS = mainwindowimp.h addserviceimp.h interface.h interfaceinformationimp.h interfacesetupimp.h interfaces.h defaultmodule.h kprocctrl.h module.h kprocess.h +SOURCES = main.cpp mainwindowimp.cpp addserviceimp.cpp interface.cpp interfaceinformationimp.cpp interfacesetupimp.cpp kprocctrl.cpp kprocess.cpp interfaces.cpp +INCLUDEPATH += $(QPEDIR)/include +DEPENDPATH += $(QPEDIR)/include +LIBS += -lqpe +INTERFACES = mainwindow.ui addservice.ui interfaceinformation.ui interfaceadvanced.ui interfacesetup.ui +TARGET = networksetup diff --git a/noncore/settings/networksettings/systemadvanced.ui b/noncore/settings/networksettings/systemadvanced.ui new file mode 100644 index 0000000..6ea192c --- a/dev/null +++ b/noncore/settings/networksettings/systemadvanced.ui @@ -0,0 +1,443 @@ + +SystemNetworking + + QWidget + + name + SystemNetworking + + + geometry + + 0 + 0 + 222 + 289 + + + + caption + System Networking + + + + margin + 0 + + + spacing + 6 + + + QTabWidget + + name + tabWidget + + + layoutMargin + + + QWidget + + name + tab + + + title + DNS + + + + margin + 11 + + + spacing + 6 + + + QLabel + + name + TextLabel6 + + + text + Hostname + + + + QLabel + + name + TextLabel5 + + + text + DNS + + + alignment + AlignTop|AlignLeft + + + vAlign + + + + QListBox + + name + ListBox5 + + + + QLineEdit + + name + LineEdit7 + + + + QLabel + + name + TextLabel7 + + + text + Hosts + + + + QLabel + + name + TextLabel9 + + + text + List here.... + + + + QPushButton + + name + PushButton15 + + + text + &Add + + + + QPushButton + + name + PushButton16 + + + text + &Delete + + + + + name + Spacer14 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + QWidget + + name + tab + + + title + Routing + + + + margin + 11 + + + spacing + 6 + + + QListView + + + text + Destination + + + clickable + true + + + resizeable + true + + + + + text + Gateway + + + clickable + true + + + resizeable + true + + + + + text + Genmask + + + clickable + true + + + resizeable + true + + + + + text + Flags + + + clickable + true + + + resizeable + true + + + + + text + Metric + + + clickable + true + + + resizeable + true + + + + + text + Ref + + + clickable + true + + + resizeable + true + + + + + text + Use + + + clickable + true + + + resizeable + true + + + + + text + Iface + + + clickable + true + + + resizeable + true + + + + + text + 192.168.1.0 + + + text + * + + + text + 255.255.255.0 + + + text + U + + + text + 0 + + + text + 0 + + + text + 0 + + + text + eth0 + + + pixmap + + + + pixmap + + + + pixmap + + + + pixmap + + + + pixmap + + + + pixmap + + + + pixmap + + + + pixmap + + + + + name + ListView4 + + + + QPushButton + + name + PushButton17 + + + text + &Add + + + + QPushButton + + name + PushButton18 + + + text + Remove + + + + + name + Spacer15 + + + orientation + Vertical + + + sizeType + Expanding + + + sizeHint + + 20 + 20 + + + + + + + + + + + QWidget +
qwidget.h
+ + 100 + 100 + + 0 + + 7 + 7 + + image0 +
+
+ + + image0 + 789c6dd2c10ac2300c00d07bbf2234b7229d1be245fc04c5a3201e4615f430059d0711ff5ddb2e6bb236ec90eed134cb5a19d8ef36602af5ecdbfeeac05dda0798d3abebde87e3faa374d3807fa0d633a52d38d8de6f679fe33fc776e196f53cd010188256a3600a292882096246517815ca99884606e18044a3a40d91824820924265a7923a2e8bcd05f33db1173e002913175f2a6be6d3294871a2d95fa00e8a94ee017b69d339d90df1e77c57ea072ede6758 + + +
-- cgit v0.9.0.2