14 files changed, 174 insertions, 54 deletions
diff --git a/noncore/settings/networksettings2/activateprofileGUI.ui b/noncore/settings/networksettings2/activateprofileGUI.ui index 12ab051..861ce96 100644 --- a/noncore/settings/networksettings2/activateprofileGUI.ui +++ b/noncore/settings/networksettings2/activateprofileGUI.ui @@ -1,85 +1,110 @@ <!DOCTYPE UI><UI> <class>ActivateProfileGUI</class> <widget> <class>QDialog</class> <property stdset="1"> <name>name</name> <cstring>ActivateProfileGUI</cstring> </property> <property stdset="1"> <name>geometry</name> <rect> <x>0</x> <y>0</y> - <width>231</width> + <width>219</width> <height>121</height> </rect> </property> <property stdset="1"> <name>caption</name> <string>Activate Network</string> </property> <property> <name>layoutMargin</name> </property> <property> <name>layoutSpacing</name> </property> <vbox> <property stdset="1"> <name>margin</name> <number>2</number> </property> <property stdset="1"> <name>spacing</name> <number>2</number> </property> <widget> <class>QLayoutWidget</class> <property stdset="1"> <name>name</name> <cstring>Layout2</cstring> </property> + <property> + <name>layoutSpacing</name> + </property> <hbox> <property stdset="1"> <name>margin</name> <number>0</number> </property> <property stdset="1"> <name>spacing</name> - <number>6</number> + <number>0</number> </property> <widget> <class>QLabel</class> <property stdset="1"> <name>name</name> <cstring>TextLabel1</cstring> </property> <property stdset="1"> + <name>sizePolicy</name> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>1</vsizetype> + </sizepolicy> + </property> + <property stdset="1"> <name>text</name> <string>Select profile to activate for </string> </property> </widget> <widget> <class>QLabel</class> <property stdset="1"> <name>name</name> <cstring>DeviceName_LBL</cstring> </property> <property stdset="1"> + <name>sizePolicy</name> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>1</vsizetype> + </sizepolicy> + </property> + <property stdset="1"> <name>text</name> <string>TextLabel2</string> </property> </widget> </hbox> </widget> <widget> <class>QListBox</class> <property stdset="1"> <name>name</name> <cstring>Profiles_LB</cstring> </property> </widget> </vbox> </widget> +<connections> + <connection> + <sender>Profiles_LB</sender> + <signal>doubleClicked(QListBoxItem*)</signal> + <receiver>ActivateProfileGUI</receiver> + <slot>accept()</slot> + </connection> +</connections> </UI> diff --git a/noncore/settings/networksettings2/activatevpn.cpp b/noncore/settings/networksettings2/activatevpn.cpp index b75e623..768a031 100644 --- a/noncore/settings/networksettings2/activatevpn.cpp +++ b/noncore/settings/networksettings2/activatevpn.cpp @@ -1,47 +1,48 @@ #include <qlistview.h> #include <qheader.h> #include <resources.h> #include "activatevpn.h" class MyCheckListItem : public QCheckListItem { public : MyCheckListItem( NodeCollection * N, QListView * V ); NodeCollection * NC; }; MyCheckListItem::MyCheckListItem( NodeCollection * N, QListView * V ): QCheckListItem( V, N->name() ) { NC = N; } -ActivateVPN::ActivateVPN( void ) : +ActivateVPN::ActivateVPN( const QString & I ) : ActivateVPNGUI( 0, 0, TRUE ), NSD() { QCheckListItem * CI; VPN_LV->clear(); VPN_LV->header()->hide(); + // find all connections that want to be triggered by this interface for( QDictIterator<NodeCollection> it(NSResources->connections()); it.current(); ++it ) { - if( it.current()->triggeredBy( "vpn" ) ) { + if( it.current()->triggeredBy( I ) ) { CI = new MyCheckListItem( it.current(), VPN_LV ); } } } ActivateVPN::~ActivateVPN( void ) { } void ActivateVPN::SLOT_ChangedVPNSetting( QListViewItem * I ) { MyCheckListItem * MI = (MyCheckListItem *)I; printf( "%s : %d\n", MI->text(0).latin1(), MI->isOn() ); } diff --git a/noncore/settings/networksettings2/activatevpn.h b/noncore/settings/networksettings2/activatevpn.h index 5794757..49a940b 100644 --- a/noncore/settings/networksettings2/activatevpn.h +++ b/noncore/settings/networksettings2/activatevpn.h @@ -1,20 +1,20 @@ #include "activatevpnGUI.h" #include "nsdata.h" class ActivateVPN : public ActivateVPNGUI { Q_OBJECT public : - ActivateVPN( void ); + ActivateVPN( const QString & Interface ); ~ActivateVPN( void ); public slots : void SLOT_ChangedVPNSetting( QListViewItem * ); private : NetworkSettingsData NSD; }; diff --git a/noncore/settings/networksettings2/main.cpp b/noncore/settings/networksettings2/main.cpp index 973b4b7..2243826 100644 --- a/noncore/settings/networksettings2/main.cpp +++ b/noncore/settings/networksettings2/main.cpp @@ -1,163 +1,179 @@ #include "nsdata.h" #include "activateprofile.h" #include "activatevpn.h" #include "networksettings.h" #include <opie2/odebug.h> #include <qpe/qpeapplication.h> #include <opie2/oapplicationfactory.h> using namespace Opie::Core; #ifdef GONE OPIE_EXPORT_APP( OApplicationFactory<NetworkSettings> ) #else // just standard GUI #define ACT_GUI 0 // used by interfaces to request for allow of up/down #define ACT_REQUEST 1 // regenerate config files #define ACT_REGEN 2 // used by interfaces to request user prompt #define ACT_PROMPT 3 -// used by interfaces to trigger VPN -#define ACT_VPN 4 +// used by interfaces to trigger VPN prompting +#define ACT_TRIGGERVPN 4 // activate opietooth #define ACT_OT 5 +// prompt for VPN networks +#define ACT_PROMPTVPN 6 // include Opietooth GUI #include <opietooth2/Opietooth.h> using namespace Opietooth2; #include <qpushbutton.h> #include <qlayout.h> #include <qframe.h> #include <qlabel.h> int main( int argc, char * argv[] ) { int rv = 0; int Action = ACT_GUI; // could be overruled by -qws QApplication::Type GuiType = QApplication::GuiClient; QPEApplication * TheApp; for ( int i = 1; i < argc; i ++ ) { int rmv; rmv = 0; if( strcmp( argv[i], "--regen" ) == 0 ) { Action = ACT_REGEN; GuiType = QApplication::Tty; rmv = 1; } else if( strcmp( argv[i], "--prompt" ) == 0 ) { Action = ACT_PROMPT; rmv = 1; } else if( strcmp( argv[i], "--triggervpn" ) == 0 ) { - Action = ACT_VPN; + GuiType = QApplication::Tty; + Action = ACT_TRIGGERVPN; + rmv = 1; + } else if( strcmp( argv[i], "--promptvpn" ) == 0 ) { + Action = ACT_PROMPTVPN; rmv = 1; } else if( strcmp( argv[i], "--opietooth" ) == 0 ) { Action = ACT_OT; rmv = 1; } if( rmv ) { memmove( argv+i, argv+i+rmv, sizeof( char * ) * (argc-i-rmv) ); i --; argc -= rmv; } } if( strstr( argv[0], "-request" ) ) { // called from system to request something GuiType = QApplication::Tty; Action = ACT_REQUEST; Log(("Request : %s\n", argv[1] )); } else if( strstr( argv[0], "-opietooth" ) ) { Action = ACT_OT; } // Start Qt // because QPEApplication does not handle GuiType well if( GuiType == QApplication::Tty ) { // this cast is NOT correct but we do not use // TheApp anymore ... TheApp = (QPEApplication *)new QApplication( argc, argv, GuiType ); } else { TheApp = new QPEApplication( argc, argv, GuiType ); } // init qt with app widget switch( Action ) { case ACT_REQUEST : { NetworkSettingsData NS; if( NS.canStart( argv[1] ) ) { + QStringList SL; + SL << QPEApplication::qpeDir() + "bin/networksettings2" + << "--prompt" + << argv[1]; + // exec synchronous -> blocks + NSResources->system().execAsUser( SL, 1 ); + } + } + break; + case ACT_TRIGGERVPN : + { NetworkSettingsData NS; + if( NS.couldBeTriggered( argv[1] ) ) { + // there are VPNS that can be triggered QStringList S; - S << QPEApplication::qpeDir() + "/bin/networksettings2"; - S << "networksettings2"; - S << "--prompt"; + S << QPEApplication::qpeDir() + "bin/networksettings2"; + S << "--promptvpn"; S << argv[1]; NSResources->system().execAsUser( S ); - Log(("FAILED %s-cNN-allowed\n", argv[1] )); - // if we come here , failed - printf( "%s-cNN-disallowed", argv[1] ); } } break; case ACT_REGEN : { NetworkSettingsData NS; QString S= NS.generateSettings(); // regen returns 0 if OK rv = ( S.isEmpty() ) ? 0 : 1; } break; case ACT_PROMPT : { ActivateProfile AP(argv[1]); if( AP.exec() == QDialog::Accepted ) { - Log(("%s-c%ld-allowed\n", - argv[1], AP.selectedProfile() )); - printf( "%s-c%ld-allowed", argv[1], AP.selectedProfile() ); + Log(("allow profile %ld for %s\n", + AP.selectedProfile(), argv[1] )); + printf( "A%ld%s\n", AP.selectedProfile(), argv[1] ); } else { - Log(("%s-c%NN-disallowed\n", argv[1] )); - printf( "%s-cNN-disallowed", argv[1] ); + Log(("disallow %s\n", argv[1] )); + printf( "D-%s\n", argv[1] ); } } break; - case ACT_VPN : - { ActivateVPN AVPN; + case ACT_PROMPTVPN : + { ActivateVPN AVPN( argv[1] ); + Log(("Trigger vpns on interface %s\n", argv[1] )); AVPN.exec(); } break; case ACT_GUI : case ACT_OT : { QWidget * W; if( Action == ACT_OT ) { W = new OTMain( 0 ); } else { W = new NetworkSettings(0); } TheApp->setMainWidget( W ); W->show(); W->showMaximized(); rv = TheApp->exec(); delete W; } break; } LogClose(); return rv; } #endif // main.cpp diff --git a/noncore/settings/networksettings2/network/network_NNI.cpp b/noncore/settings/networksettings2/network/network_NNI.cpp index 78e6545..34dac54 100644 --- a/noncore/settings/networksettings2/network/network_NNI.cpp +++ b/noncore/settings/networksettings2/network/network_NNI.cpp @@ -1,217 +1,218 @@ #include <system.h> #include <netnode.h> #include "networkedit.h" #include "network_NNI.h" #include "network_NN.h" ANetwork::ANetwork( NetworkNetNode * PNN ) : ANetNodeInstance( PNN ) { Data.UseDHCP = 1; Data.IPAddress = ""; Data.NetMask = ""; Data.Broadcast = ""; Data.Gateway = ""; Data.DNS1 = ""; Data.DNS2 = ""; Data.SendHostname = 0; Data.Hostname = ""; Data.PreUp_SL.clear(); Data.PreDown_SL.clear(); Data.PostUp_SL.clear(); Data.PostDown_SL.clear(); GUI = 0; RT = 0; } void ANetwork::setSpecificAttribute( QString & A, QString & V ) { if( A == "usedhcp" ) { Data.UseDHCP = (V == "yes"); } else if( A == "sendhostname" ) { Data.SendHostname = (V=="yes"); } else if( A == "hostname" ) { Data.Hostname = V; } else if( A == "ipaddress" ) { Data.IPAddress = V; } else if( A == "netmask" ) { Data.NetMask = V; } else if( A == "broadcast" ) { Data.Broadcast = V; } else if( A == "gateway" ) { Data.Gateway = V; } else if( A == "dns1" ) { Data.DNS1 = V; } else if( A == "dns2" ) { Data.DNS2 = V; } else if( A == "preup" ) { Data.PreUp_SL.append( V ); } else if( A == "predown" ) { Data.PreDown_SL.append( V ); } else if( A == "postup" ) { Data.PostUp_SL.append( V ); } else if( A == "postdown" ) { Data.PostDown_SL.append( V ); } } void ANetwork::saveSpecificAttribute( QTextStream & TS ) { TS << "usedhcp=" << ((Data.UseDHCP) ? "yes" : "no") << endl; TS << "sendhostname=" << ((Data.SendHostname) ? "yes" : "no") << endl; TS << "hostname=" << Data.Hostname << endl; TS << "ipaddress=" << Data.IPAddress << endl; TS << "netmask=" << Data.NetMask << endl; TS << "broadcast=" << Data.Broadcast << endl; TS << "gateway=" << Data.Gateway << endl; TS << "dns1=" << Data.DNS1 << endl; TS << "dns2=" << Data.DNS2 << endl; for ( QStringList::Iterator it = Data.PreUp_SL.begin(); it != Data.PreUp_SL.end(); ++it ) { TS << "preup=" << quote(*it) << endl; } for ( QStringList::Iterator it = Data.PreDown_SL.begin(); it != Data.PreDown_SL.end(); ++it ) { TS << "predown=" << quote(*it) << endl; } for ( QStringList::Iterator it = Data.PostUp_SL.begin(); it != Data.PostUp_SL.end(); ++it ) { TS << "postup=" << quote(*it) << endl; } for ( QStringList::Iterator it = Data.PostDown_SL.begin(); it != Data.PostDown_SL.end(); ++it ) { TS << "postdown=" << quote(*it) << endl; } } QWidget * ANetwork::edit( QWidget * parent ) { GUI = new NetworkEdit( parent ); GUI->showData( Data ); return GUI; } QString ANetwork::acceptable( void ) { return ( GUI ) ? GUI->acceptable( ) : QString(); } void ANetwork::commit( void ) { if( GUI && GUI->commit( Data ) ) setModified( 1 ); } bool ANetwork::hasDataForFile( SystemFile & S ) { return S.name() == "interfaces"; } short ANetwork::generateFile( SystemFile &SF, long DevNr ) { short rvl, rvd ; QString NIC = runtime()->device()->netNode()->nodeClass()->genNic( DevNr ); rvl = 1; if( SF.name() == "interfaces" ) { Log(("Generate Network for %s\n", SF.name().latin1() )); // we can safely call from here since device item is deeper if( Data.UseDHCP ) { SF << "iface " - << NIC - << "-c" + << "A" << connection()->number() - << "-allowed inet dhcp" + << NIC + << " inet dhcp" << endl; SF << " up echo \"" << NIC << "\" > /tmp/profile-" << connection()->number() << ".up" << endl; if( Data.SendHostname ) { SF << " hostname " << Data.Hostname << endl; } SF << " down rm -f /tmp/profile-" << connection()->number() << ".up" << endl; } else { SF << "iface " - << NIC << "-c" + << "A" << connection()->number() - << "-allowed inet static" + << NIC + << " inet static" << endl; SF << " up echo \"" << NIC << "\" > /tmp/profile-" << connection()->number() << ".up" << endl; SF << " down rm -f /tmp/profile-" << connection()->number() << ".up" << endl; SF << " address " << Data.IPAddress << endl; SF << " broadcast " << Data.Broadcast << endl; SF << " netmask " << Data.NetMask << endl; // derive network address = IPAddress & netmask { QString NW; QStringList ipal = QStringList::split( '.', Data.IPAddress ); QStringList nmal = QStringList::split( '.', Data.NetMask ); NW = QString( "%1.%2.%3.%4" ). arg( ipal[0].toShort() & nmal[0].toShort() ). arg( ipal[1].toShort() & nmal[1].toShort() ). arg( ipal[2].toShort() & nmal[2].toShort() ). arg( ipal[3].toShort() & nmal[3].toShort() ); SF << " network " << NW << endl; } } for ( QStringList::Iterator it = Data.PreUp_SL.begin(); it != Data.PreUp_SL.end(); ++it ) { SF << " pre-up " << (*it) << endl; } for ( QStringList::Iterator it = Data.PostUp_SL.begin(); it != Data.PostUp_SL.end(); ++it ) { SF << " up " << (*it) << endl; } for ( QStringList::Iterator it = Data.PreDown_SL.begin(); it != Data.PreDown_SL.end(); ++it ) { SF << " down " << (*it) << endl; } for ( QStringList::Iterator it = Data.PostDown_SL.begin(); it != Data.PostDown_SL.end(); ++it ) { SF << " post-down " << (*it) << endl; } rvl = 0; } // embed other info in it rvd = connection()->getToplevel()->generateFileEmbedded( SF, DevNr ); return (rvd == 2 || rvl == 2 ) ? 2 : (rvd == 0 || rvl == 0 ) ? 0 : 1; } diff --git a/noncore/settings/networksettings2/network/networkrun.cpp b/noncore/settings/networksettings2/network/networkrun.cpp index 2c93d9d..74467ad 100644 --- a/noncore/settings/networksettings2/network/networkrun.cpp +++ b/noncore/settings/networksettings2/network/networkrun.cpp @@ -1,50 +1,51 @@ #include <system.h> #include <netnode.h> #include <resources.h> #include "networkrun.h" State_t NetworkRun::detectState( void ) { InterfaceInfo * II = nodeCollection()->assignedInterface(); - Log(( "Interface %p : %d\n", II, (II) ? II->IsUp : 0 )); + Log(( "Interface %p %p : %d\n", II, nodeCollection(), (II) ? II->IsUp : 0 )); if( II && II->IsUp ) { // device has assigned interface return IsUp; } // had no interface or interface is no longer up -> release nodeCollection()->assignInterface( 0 ); return Unknown; } QString NetworkRun::setMyState( NodeCollection * NC, Action_t A, bool ) { // we handle UP and DOWN InterfaceInfo * II = NC->assignedInterface(); if( ! II ) { Log(( "no interface assigned." )); return QString(); } QStringList SL; if( A == Up ) { // we can bring UP if lower level is available SL << "ifup"; } else if( A == Down ) { SL << "ifdown"; } else { return QString(); } - SL << QString().sprintf( "%s=%s-c%d-allowed", - II->Name.latin1(), II->Name.latin1(), - nodeCollection()->number() ); + SL << QString().sprintf( "%s=A%ld%s", + II->Name.latin1(), + nodeCollection()->number(), + II->Name.latin1() ); if( ! NSResources->system().runAsRoot( SL ) ) { return QString("Cannot call %1").arg(SL.join(" ")); } return QString(); } diff --git a/noncore/settings/networksettings2/networksettings2/resources.cpp b/noncore/settings/networksettings2/networksettings2/resources.cpp index 3479abb..b81dcaa 100644 --- a/noncore/settings/networksettings2/networksettings2/resources.cpp +++ b/noncore/settings/networksettings2/networksettings2/resources.cpp @@ -1,479 +1,481 @@ #include <unistd.h> #include <errno.h> #include <fcntl.h> #include <pwd.h> #include <qpixmap.h> #include <qdir.h> #include <qmessagebox.h> #include <qpe/qlibrary.h> #include <qpe/qpeapplication.h> #include <opie2/odebug.h> #include <opie2/opluginloader.h> #include <qtopia/resource.h> #include "netnode.h" #include "resources.h" #include "netnodeinterface.h" #define PLUGINDIR "plugins/networksettings2" #define ICONDIR "/pics/networksettings2/" // single resources instance TheNSResources * _NSResources = 0; TheNSResources::TheNSResources( void ) : NodeTypeNameMap(), ConnectionsMap(), DanglingConnectionsMap() { _NSResources = this; detectCurrentUser(); // load available netnodes Plugins = 0; findAvailableNetNodes(); // compile provides and needs lists { const char ** NeedsRun; QDictIterator<ANetNode> OuterIt( AllNodeTypes ); bool Done; for ( ; OuterIt.current(); ++OuterIt ) { // find needs list ANetNode::NetNodeList * NNLP = new ANetNode::NetNodeList; ANetNode::NetNodeList & NNL = *(NNLP); // must iterate this way to avoid duplication pointers for ( QDictIterator<ANetNode> InnerIt( AllNodeTypes ); InnerIt.current(); ++InnerIt ) { if( InnerIt.current() == OuterIt.current() ) // avoid recursive continue; const char ** Provides = InnerIt.current()->provides(); NeedsRun = OuterIt.current()->needs(); for( ; *NeedsRun; NeedsRun ++ ) { const char ** PRun; PRun = Provides; for( ; *PRun; PRun ++ ) { if( strcmp( *PRun, *NeedsRun ) == 0 ) { // inner provides what outer needs NNL.resize( NNL.size() + 1 ); NNL[NNL.size()-1] = InnerIt.current(); Done = 1; // break from 2 loops break; } } } } OuterIt.current()->setAlternatives( NNLP ); } } // define built in Node types to Description map addNodeType( "device", tr( "Network Device" ), tr( "<p>Devices that can handle IP packets</p>" ) ); addNodeType( "line", tr( "Character device" ), tr( "<p>Devices that can handle single bytes</p>" ) ); addNodeType( "connection", tr( "IP Connection" ), tr( "<p>Nodes that provide working IP connections</p>" ) ); addNodeType( "fullsetup", tr( "Connection Profile" ), tr( "<p>Fully configured connection profile</p>" ) ); addNodeType( "GPRS", tr( "Connection to GPRS device" ), tr( "<p>Connection to a GPRS capable device</p>" ) ); // get access to the system TheSystem = new System(); } TheNSResources::~TheNSResources( void ) { if( Plugins ) { delete Plugins; delete PluginManager; } delete TheSystem; } void TheNSResources::addNodeType( const QString & ID, const QString & Name, const QString & Descr ) { if( NodeTypeNameMap[ID].isEmpty() ) { NodeTypeNameMap.insert( ID, Name ); NodeTypeDescriptionMap.insert( ID, Descr ); } } void TheNSResources::addSystemFile( const QString & ID, const QString & P, bool KDI ) { if( ! SystemFiles.find( ID ) ) { // new system file SystemFiles.insert( ID, new SystemFile( ID, P, KDI ) ); } // else existed } void TheNSResources::busy( bool ) { /* if( B ) { ShowWait->show(); qApp->process } else { ShowWait->hide(); } */ } void TheNSResources::findAvailableNetNodes( void ){ Plugins = new OPluginLoader( "networksettings2" ); Plugins->setAutoDelete( true ); PluginManager = new OPluginManager( Plugins ); PluginManager->load(); if( Plugins->isInSafeMode() ) { QMessageBox::information( 0, tr( "Today Error"), tr( "<qt>The plugin '%1' caused Today to crash." " It could be that the plugin is not properly" " installed.<br>Today tries to continue loading" " plugins.</qt>" ) .arg( PluginManager->crashedPlugin().name())); } // Get All Plugins OPluginLoader::List allplugins = Plugins->filtered(); QString lang = ::getenv("LANG"); for( OPluginLoader::List::Iterator it = allplugins.begin(); it != allplugins.end(); ++it ) { // check if this plugin supports the proper interface NetNodeInterface * interface = Plugins->load<NetNodeInterface>( *it, IID_NetworkSettings2 ); if( ! interface ) { Log(( "Plugin %s from %s does not support proper interface\n", (*it).name().latin1(), (*it).path().latin1() )); continue; } // add the nodes in this plugin to the dictionary { QList<ANetNode> PNN; interface->create_plugin( PNN ); if( PNN.isEmpty() ) { Log(( "Plugin %s from %s does offer any nodes\n", (*it).name().latin1(), (*it).path().latin1() )); delete interface; continue; } // merge this node with global node for( QListIterator<ANetNode> it(PNN); it.current(); ++it ) { AllNodeTypes.insert( it.current()->name(), it.current() ); } } // load the translation QTranslator *trans = new QTranslator(qApp); QString fn = QPEApplication::qpeDir()+ "/i18n/"+lang+"/"+ (*it).name() + ".qm"; if( trans->load( fn ) ) qApp->installTranslator( trans ); else delete trans; } } // used to find unique connection number int TheNSResources::assignConnectionNumber( void ) { bool found = 1; for( int trial = 0; ; trial ++ ) { found = 1; for( QDictIterator<NodeCollection> it(ConnectionsMap); it.current(); ++it ) { if( it.current()->number() == trial ) { found = 0; break; } } if( found ) { Log(("Assign profile number %d\n", trial )); return trial; } } } QPixmap TheNSResources::getPixmap( const QString & QS ) { QPixmap P; QString S("networksettings2/"); S += QS; P = Resource::loadPixmap( S ); if( P.isNull() ) { Log(( "Cannot load %s\n", S.latin1() )); } return ( P.isNull() ) ? QPixmap() : P; } QString TheNSResources::tr( const char * s ) { return qApp->translate( "resource", s ); } const QString & TheNSResources::netNode2Name( const char * s ) { return NodeTypeNameMap[s]; } const QString & TheNSResources::netNode2Description( const char * s ) { return NodeTypeDescriptionMap[s]; } void TheNSResources::addConnection( NodeCollection * NC, bool Dangling ) { ANetNodeInstance * NNI; + Log(( "Add Connection %s, Dangling %d\n", + NC->name().latin1(), Dangling )); if( Dangling ) { DanglingConnectionsMap.insert( NC->name(), NC ); } else { ConnectionsMap.insert( NC->name(), NC ); } // add (new) nodes to NodeList for( QListIterator<ANetNodeInstance> it(*NC); it.current(); ++it ) { NNI = it.current(); if( findNodeInstance( NNI->name() ) == 0 ) { // new item addNodeInstance( NNI ); } } } void TheNSResources::removeConnection( const QString & N ) { NodeCollection * NC = findConnection( N ); if( ! NC ) return; // delete netnodes in this connection ANetNodeInstance * NNI; for( NNI = NC->first(); NNI != 0; NNI = NC->next() ) { removeNodeInstance( NNI->name() ); } if( ConnectionsMap.find( N ) ) { ConnectionsMap.remove( N ); } else { DanglingConnectionsMap.remove( N ); } } // dangling connections are filtered out NodeCollection * TheNSResources::findConnection( const QString & S ) { return ConnectionsMap[ S ]; } NodeCollection * TheNSResources::getConnection( int nr ) { for( QDictIterator<NodeCollection> it(ConnectionsMap); it.current(); ++it ) { if( it.current()->number() == nr ) { return it.current(); } } return 0; } /* void TheNSResources::renumberConnections( void ) { Name2Connection_t & M = NSResources->connections(); NodeCollection * NC; // for all connections NodeCollection::resetMaxNr(); for( QDictIterator<NodeCollection> it(M); it.current(); ++it ) { NC = it.current(); NC->setNumber( NC->maxConnectionNumber()+1 ); NC->setModified( 1 ); } } */ typedef struct EnvVars { char * Name; int Len; } EnvVar_t; #define AnEV(x) x, sizeof(x)-1 static EnvVar_t EV[] = { AnEV( "HOME" ), AnEV( "LOGNAME" ), AnEV( "USER" ), AnEV( "LD_LIBRARY_PATH" ), AnEV( "PATH" ), AnEV( "QTDIR" ), AnEV( "OPIEDIR" ), AnEV( "SHELL" ), { NULL, 0 } }; void TheNSResources::detectCurrentUser( void ) { // find current running qpe QString QPEEnvFile = ""; CurrentUser.UserName = ""; CurrentUser.HomeDir = ""; if( getenv( "OPIEDIR" ) == 0 ) { // nothing known { // open proc dir and find all dirs in it QRegExp R("[0-9]+"); QDir ProcDir( "/proc" ); QFileInfo FI; QStringList EL = ProcDir.entryList( QDir::Dirs ); // print it out for ( QStringList::Iterator it = EL.begin(); it != EL.end(); ++it ) { if( R.match( (*it) ) >= 0 ) { QString S = ProcDir.path()+"/"+ (*it); S.append( "/exe" ); FI.setFile( S ); // get the link S = FI.readLink(); if( S.right( 8 ) == "/bin/qpe" ) { // found running qpe QPEEnvFile.sprintf( ProcDir.path()+ "/" + (*it) + "/environ" ); break; } } } } if( QPEEnvFile.isEmpty() ) { // could not find qpe Log(("Could not find qpe\n" )); return; } // FI now contains path ProcDir to the cmd dir { char * Buf = 0; char TB[1024]; long BufSize = 0; int fd; int rd; fd = open( QPEEnvFile.latin1(), O_RDONLY ); if( fd < 0 ) { Log(("Could not open %s : %d\n", QPEEnvFile.latin1(), errno )); return; } while( (rd = read( fd, TB, sizeof(TB) ) ) > 0 ) { Buf = (char *)realloc( Buf, BufSize+rd ); memcpy( Buf+BufSize, TB, rd ); BufSize += rd; } char * Data = Buf; char * DataEnd = Data+BufSize-1; // get env items out of list while( Data < DataEnd ) { EnvVar_t * Run = EV; while( Run->Name ) { if( strncmp( Data, Run->Name, Run->Len ) == 0 && Data[Run->Len] == '=' ) { CurrentUser.EnvList.resize( CurrentUser.EnvList.size()+1 ); CurrentUser.EnvList[CurrentUser.EnvList.size()-1] = strdup( Data ); if( strcmp( Run->Name, "OPIEDIR" ) == 0 ) { // put OPIEDIR in env putenv( CurrentUser.EnvList[CurrentUser.EnvList.size()-1] ); } else if( strcmp( Run->Name, "HOME" ) == 0 ) { CurrentUser.HomeDir = Data+5; } else if( strcmp( Run->Name, "LOGNAME" ) == 0 ) { CurrentUser.UserName = Data+8; } break; } Run ++; } Data += strlen( Data )+1; } free( Buf ); if( ! CurrentUser.UserName.isEmpty() ) { // find user info struct passwd pwd; struct passwd * pwdres; if( getpwnam_r( CurrentUser.UserName.latin1(), &pwd, TB, sizeof(TB), &pwdres ) || pwdres == 0 ) { Log(("Could not determine user %s : %d\n", CurrentUser.UserName.latin1(), errno )); return; } CurrentUser.Uid = pwd.pw_uid; CurrentUser.Gid = pwd.pw_gid; } else{ CurrentUser.Uid = CurrentUser.Gid = -1; } } } else { char * X; QString S; EnvVar_t * Run = EV; while( Run->Name ) { if( ( X = getenv( Run->Name ) ) ) { Log(( "Env : %s = %s\n", Run->Name, X )); S.sprintf( "%s=%s", Run->Name, X ); CurrentUser.EnvList.resize( CurrentUser.EnvList.size()+1 ); CurrentUser.EnvList[CurrentUser.EnvList.size()-1] = strdup( S.latin1() ); if( strcmp( Run->Name, "LOGNAME" ) == 0 ) { CurrentUser.UserName = X; } else if( strcmp( Run->Name, "HOME" ) == 0 ) { CurrentUser.HomeDir = X; } // regulare env var } else { Log(("Could not determine %s\n", Run->Name )); } Run ++; } CurrentUser.Uid = getuid(); CurrentUser.Gid = getgid(); } } diff --git a/noncore/settings/networksettings2/networksettings2/resources.h b/noncore/settings/networksettings2/networksettings2/resources.h index b27cda1..51c4250 100644 --- a/noncore/settings/networksettings2/networksettings2/resources.h +++ b/noncore/settings/networksettings2/networksettings2/resources.h @@ -1,153 +1,153 @@ #ifndef __RESOURCES__H #define __RESOURCES__H #include <qstring.h> #include <qdict.h> #include <qmap.h> #include <qlist.h> #include "netnode.h" #include "systemfile.h" #include "system.h" class QLibrary; class QPixmap; class ANetNode; class ANetNodeInstance; namespace Opie { namespace Core { class OPluginLoader; class OPluginManager; } } typedef void (*GetNetNodeListFt_t)(QList<ANetNode>& PNN ); class CurrentQPEUser { public : CurrentQPEUser() : UserName(), HomeDir(), EnvList() {} inline bool known( void ) { return ! HomeDir.isEmpty() && ! UserName.isEmpty(); } QString UserName; QString HomeDir; int Uid; int Gid; QArray<char *> EnvList; }; typedef QDict<ANetNode> Name2NetNode_t; typedef QDict<ANetNodeInstance > Name2Instance_t; typedef QDict<NodeCollection> Name2Connection_t; typedef QDict<SystemFile> Name2SystemFile_t; class TheNSResources { public : TheNSResources( void ); ~TheNSResources( ); // give busy feedback void busy( bool B ); System & system() { return *TheSystem; } int assignConnectionNumber(void); QPixmap getPixmap( const QString & Name ); Name2NetNode_t & netNodes( void ) { return AllNodeTypes; } bool netNodeExists( const QString & X ) { return AllNodeTypes.find(X)!=0; } ANetNode * findNetNode( const QString & N ) { return AllNodeTypes.find(N); } // define new plugin (=node) void addNodeType( const QString & ID, const QString & LongName, const QString & Description ); Name2SystemFile_t & systemFiles( void ) { return SystemFiles; } void addSystemFile( const QString & ID, const QString & P, bool KDI ); ANetNodeInstance * createNodeInstance( const QString & S ) { ANetNode * NN = findNetNode( S ); Log(( "Find node type %s : %p\n", S.latin1(), NN )); if( NN == 0 ) // type of this instance not found return 0; ANetNodeInstance * NNI = NN->createInstance(); NNI->initialize(); return NNI; } Name2Instance_t & netNodeInstances( void ) { return AllNodes; } void addNodeInstance( ANetNodeInstance * I ) { AllNodes.insert( I->name(), I ); } void removeNodeInstance( const QString & N ) { AllNodes.remove( N );} ANetNodeInstance * findNodeInstance( const QString & S ) { return AllNodes[S]; } const QString & netNode2Name( const char * Type ); const QString & netNode2Description( const char * Type ); void addConnection( NodeCollection * NC, bool Dangling ); void removeConnection( const QString & N ); NodeCollection * findConnection( const QString & N ); NodeCollection * getConnection( int nr ); Name2Connection_t & connections( void ) { return ConnectionsMap; } Name2Connection_t & danglingConnections( void ) - { return ConnectionsMap; } + { return DanglingConnectionsMap; } inline bool userKnown( void ) { return CurrentUser.known(); } CurrentQPEUser & currentUser( void ) { return CurrentUser; } private : void detectCurrentUser( void ); QString tr( const char * path ); void findAvailableNetNodes( void ); QMap< QString, QString> NodeTypeNameMap; QMap< QString, QString> NodeTypeDescriptionMap; // list of connections that are valid Name2Connection_t ConnectionsMap; // list of connection configurations that are not valid // e.g. because plugins are missing Name2Connection_t DanglingConnectionsMap; System * TheSystem; Name2SystemFile_t SystemFiles; // all node type classes Name2NetNode_t AllNodeTypes; // all nodes Name2Instance_t AllNodes; CurrentQPEUser CurrentUser; Opie::Core::OPluginLoader * Plugins; Opie::Core::OPluginManager * PluginManager; }; extern TheNSResources * _NSResources; #define NSResources _NSResources #endif diff --git a/noncore/settings/networksettings2/networksettings2/system.cpp b/noncore/settings/networksettings2/networksettings2/system.cpp index f027d35..a290f08 100644 --- a/noncore/settings/networksettings2/networksettings2/system.cpp +++ b/noncore/settings/networksettings2/networksettings2/system.cpp @@ -1,587 +1,603 @@ #include <sys/types.h> #include <sys/wait.h> #include <net/if.h> #include <net/if_arp.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <errno.h> #include <unistd.h> #include <opie2/oprocess.h> #include <qdir.h> #include <qregexp.h> #include <qstringlist.h> #include <qfile.h> #include <qtextstream.h> #include <qapplication.h> #include "resources.h" #include "system.h" #define PROCNETDEV "/proc/net/dev" #ifndef ARPHRD_IEEE80211 #define ARPHRD_IEEE80211 801 #endif static char Dig2Hex[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; // get HIGH nibble of byte #define HN(x) Dig2Hex[(((x)&0xf0)>>4)] // get LOW nibble of byte #define LN(x) Dig2Hex[((x)&0x0f)] System::System( void ) : QObject(), ProbedInterfaces() { ProcDevNet = 0; } System::~System( void ) { if( ProcDevNet ) delete ProcDevNet; } QDict<InterfaceInfo> & System::interfaces( void ) { if( ProbedInterfaces.count() == 0 ) { probeInterfaces(); } return ProbedInterfaces; } int System::runAsRoot( QStringList & S, MyProcess * Prc ) { char * usr = getenv("USER"); if( S.count() == 0 ) { - // loophole to start shell + // close loophole to start shell return 8888; } if( usr == 0 || strcmp( usr, "root" ) ) { // unknown or non-root user -> use SUDO S.prepend( "sudo" ); } if( getenv( "NS2TESTMODE" ) ) { odebug << "TESTMODE !!! execute " << S.join( " ") << oendl; } else { MyProcess * P; if( Prc ) { P = Prc; } else { P = new MyProcess(); emit processEvent( tr("Command : ") + S.join( " " ) ); connect( P, SIGNAL( stdoutLine( const QString & ) ), this, SIGNAL( stdoutLine( const QString & ) ) ); connect( P, SIGNAL( stderrLine( const QString & ) ), this, SIGNAL( stderrLine( const QString & ) ) ); connect( P, SIGNAL(processExited(MyProcess*) ), this, SLOT (SLOT_ProcessExited(MyProcess*) ) ); } P->process() << S; Log(("Executing %s\n", S.join( " " ).latin1() )); if( ! P->process().start( OProcess::DontCare, OProcess::AllOutput ) ) { odebug << "Error starting " << S << oendl; if( ! Prc ) delete P; // error starting app return 0; } odebug << "Started " << S << oendl; } // all is fine return 1; } -int System::execAsUser( QStringList & SL ) { +int System::execAsUser( QStringList & SL, bool Synchronous ) { MyProcess * P = new MyProcess(); CurrentQPEUser CU = NSResources->currentUser(); char * usr = getenv("USER"); - if( strcmp( usr, "root" ) == 0 ) { + if( usr == 0 || + strcmp( usr, "root" ) == 0 ) { // find user running qpe if( CU.UserName.isEmpty() ) { // if we come here, the exec was not successfull Log(("User not known \n" )); return 0; } } // now we are ready to exec the requested command setuid( CU.Uid ); setgid( CU.Gid ); for( unsigned int i = 0 ; i < CU.EnvList.count() ; i ++ ) { QString X; QStringList SL; X = CU.EnvList[i]; SL = QStringList::split( "=", X ); P->process().setEnvironment( SL[0], SL[1] ); } P->process() << SL; emit processEvent( tr("Command : ") + SL.join( " " ) ); Log(("Executing as user %s : %s\n", CU.UserName.latin1(), SL.join( " " ).latin1() )); - int rv = ( P->process().start( OProcess::DontCare, - OProcess::NoCommunication ) ); + P->setEchoMode( Synchronous ); + + bool rv = P->process().start( + (Synchronous) ? OProcess::Block : + OProcess::DontCare, + (Synchronous) ? OProcess::AllOutput : + OProcess::NoCommunication ); delete P; - if( rv ) { + if( ! rv ) { // if we come here, the exec was not successfull Log(("Could not exec : %d\n", errno )); } - return ! rv; + return rv; } void System::SLOT_ProcessExited( MyProcess * P ) { QString R; for( QValueListConstIterator<QCString> it = P->process().args().begin(); it != P->process().args().end(); ++it ) { R += (*it); R += " "; } R += "Returned with " + QString().setNum( P->process().exitStatus() ); emit processEvent( R ); delete P; } void System::refreshStatistics( InterfaceInfo & I ) { if( ! ProcDevNet ) { return; } // cannot seek on dev ProcDevNet->close(); ProcDevNet->open( IO_ReadOnly ); QString line; QTextStream procTs(ProcDevNet); QStringList SL; int loc = -1; int version; procTs.readLine(); line = procTs.readLine(); // get version if( line.find("compressed") ) version = 3; else if( line.find( "bytes" ) ) version = 2; else version = 1; while((line = procTs.readLine().simplifyWhiteSpace()) != QString::null) { if( (loc = line.find(":") ) == -1) { continue; } if( I.Name != line.left(loc) ) continue; // tokenize SL = QStringList::split( ' ', line, FALSE ); // update data switch( version ) { case 1 : I.RcvBytes = SL[1]; I.RcvErrors = SL[3]; I.RcvDropped = SL[4]; I.SndBytes = SL[6]; I.SndErrors = SL[8]; I.SndDropped = SL[9]; I.Collisions = SL[11]; break; case 2 : I.RcvBytes = SL[1]; I.RcvErrors = SL[3]; I.RcvDropped = SL[4]; I.SndBytes = SL[7]; I.SndErrors = SL[9]; I.SndDropped = SL[10]; I.Collisions = SL[12]; break; case 3 : I.RcvBytes = SL[1]; I.RcvErrors = SL[3]; I.RcvDropped = SL[4]; I.SndBytes = SL[9]; I.SndErrors = SL[11]; I.SndDropped = SL[12]; I.Collisions = SL[14]; break; } break; } } // // THIS UPDATES THE LIST -> INTERFACES ARE NOT DELETED BUT // FLAGGED AS ! 'IsUp' IF NO LONGER PRESENT // void System::probeInterfaces( void ) { // probe interfaces int sockfd; // get list of all interfaces struct ifreq ifrs; InterfaceInfo * IFI; // flag all as 'down' for( QDictIterator<InterfaceInfo> it( ProbedInterfaces ); it.current(); ++it ) { it.current()->IsUp = 0; } sockfd = socket(PF_INET, SOCK_DGRAM, 0); if(sockfd == -1) { odebug << "Cannot open INET socket " << errno << " " << strerror( errno ) << oendl; return; } // read interfaces from /proc/dev/net // SIOCGIFCONF does not return ALL interfaces ???!? ProcDevNet = new QFile(PROCNETDEV); if( ! ProcDevNet->open(IO_ReadOnly) ) { odebug << "Cannot open " << PROCNETDEV << " " << errno << " " << strerror( errno ) << oendl; delete ProcDevNet; ProcDevNet =0; ::close( sockfd ); return; } QString line; QString NicName; QTextStream procTs(ProcDevNet); int loc = -1; procTs.readLine(); // eat a line procTs.readLine(); // eat a line while((line = procTs.readLine().simplifyWhiteSpace()) != QString::null) { if((loc = line.find(":")) == -1) { continue; } NicName = line.left(loc); // set name for ioctl strcpy( ifrs.ifr_name, NicName.latin1() ); if ( ! ( IFI = ProbedInterfaces.find( NicName ) ) ) { // new nic Log(("New NIC found : %s\n", NicName.latin1())); IFI = new InterfaceInfo; IFI->Name = line.left(loc); IFI->Collection = 0; ProbedInterfaces.insert( IFI->Name, IFI ); // get dynamic info if( ioctl(sockfd, SIOCGIFFLAGS, &ifrs) >= 0 ) { IFI->IsPointToPoint = ((ifrs.ifr_flags & IFF_POINTOPOINT) == IFF_POINTOPOINT); } else { IFI->IsPointToPoint = 0; } // settings that never change IFI->DstAddress = ""; if( IFI->IsPointToPoint ) { if( ioctl(sockfd, SIOCGIFDSTADDR, &ifrs) >= 0 ) { IFI->DstAddress = inet_ntoa(((struct sockaddr_in*)&ifrs.ifr_dstaddr)->sin_addr); } } IFI->CardType = 999999; IFI->MACAddress = ""; if( ioctl(sockfd, SIOCGIFHWADDR, &ifrs) >= 0 ) { Log(("Family for NIC %s : %d\n", IFI->Name.latin1(), ifrs.ifr_hwaddr.sa_family )); IFI->CardType = ifrs.ifr_hwaddr.sa_family; switch( ifrs.ifr_hwaddr.sa_family ) { case ARPHRD_ETHER : // regular MAC address // valid address -> convert to regular ::: format // length = 6 bytes = 12 DIGITS -> 6 : IFI->MACAddress.sprintf( "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c", HN( ifrs.ifr_hwaddr.sa_data[0] ), LN( ifrs.ifr_hwaddr.sa_data[0] ), HN( ifrs.ifr_hwaddr.sa_data[1] ), LN( ifrs.ifr_hwaddr.sa_data[1] ), HN( ifrs.ifr_hwaddr.sa_data[2] ), LN( ifrs.ifr_hwaddr.sa_data[2] ), HN( ifrs.ifr_hwaddr.sa_data[3] ), LN( ifrs.ifr_hwaddr.sa_data[3] ), HN( ifrs.ifr_hwaddr.sa_data[4] ), LN( ifrs.ifr_hwaddr.sa_data[4] ), HN( ifrs.ifr_hwaddr.sa_data[5] ), LN( ifrs.ifr_hwaddr.sa_data[5] ) ); break; #ifdef ARPHRD_IEEE1394 case ARPHRD_IEEE1394 : // Firewire Eth address IFI->MACAddress.sprintf( "%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-%c%c-00-00", HN( ifrs.ifr_hwaddr.sa_data[0] ), LN( ifrs.ifr_hwaddr.sa_data[0] ), HN( ifrs.ifr_hwaddr.sa_data[1] ), LN( ifrs.ifr_hwaddr.sa_data[1] ), HN( ifrs.ifr_hwaddr.sa_data[2] ), LN( ifrs.ifr_hwaddr.sa_data[2] ), HN( ifrs.ifr_hwaddr.sa_data[3] ), LN( ifrs.ifr_hwaddr.sa_data[3] ), HN( ifrs.ifr_hwaddr.sa_data[4] ), LN( ifrs.ifr_hwaddr.sa_data[4] ), HN( ifrs.ifr_hwaddr.sa_data[5] ), LN( ifrs.ifr_hwaddr.sa_data[5] ), HN( ifrs.ifr_hwaddr.sa_data[6] ), LN( ifrs.ifr_hwaddr.sa_data[6] ), HN( ifrs.ifr_hwaddr.sa_data[7] ), LN( ifrs.ifr_hwaddr.sa_data[7] ), HN( ifrs.ifr_hwaddr.sa_data[8] ), LN( ifrs.ifr_hwaddr.sa_data[8] ), HN( ifrs.ifr_hwaddr.sa_data[9] ), LN( ifrs.ifr_hwaddr.sa_data[9] ), HN( ifrs.ifr_hwaddr.sa_data[10] ), LN( ifrs.ifr_hwaddr.sa_data[10] ), HN( ifrs.ifr_hwaddr.sa_data[11] ), LN( ifrs.ifr_hwaddr.sa_data[11] ), HN( ifrs.ifr_hwaddr.sa_data[12] ), LN( ifrs.ifr_hwaddr.sa_data[12] ), HN( ifrs.ifr_hwaddr.sa_data[13] ), LN( ifrs.ifr_hwaddr.sa_data[13] ) ); break; #endif case ARPHRD_PPP : // PPP break; case ARPHRD_IEEE80211 : // WLAN break; case ARPHRD_IRDA : // IRDA break; } } } else // else already probed before -> just update Log(("Redetected NIC %s\n", NicName.latin1())); // get dynamic info if( ioctl(sockfd, SIOCGIFFLAGS, &ifrs) >= 0 ) { IFI->IsUp = ((ifrs.ifr_flags & IFF_UP) == IFF_UP); IFI->HasMulticast = ((ifrs.ifr_flags & IFF_MULTICAST) == IFF_MULTICAST); } else { IFI->IsUp = 0; IFI->HasMulticast = 0; } if( ioctl(sockfd, SIOCGIFADDR, &ifrs) >= 0 ) { IFI->Address = inet_ntoa(((struct sockaddr_in*)&ifrs.ifr_addr)->sin_addr); } else { IFI->Address = ""; IFI->IsUp = 0; } if( ioctl(sockfd, SIOCGIFBRDADDR, &ifrs) >= 0 ) { IFI->BCastAddress = inet_ntoa(((struct sockaddr_in*)&ifrs.ifr_broadaddr)->sin_addr); } else { IFI->BCastAddress = ""; } if( ioctl(sockfd, SIOCGIFNETMASK, &ifrs) >= 0 ) { IFI->Netmask = inet_ntoa(((struct sockaddr_in*)&ifrs.ifr_netmask)->sin_addr); } else { IFI->Netmask = ""; } Log(("NIC %s UP ? %d\n", NicName.latin1(), IFI->IsUp )); } ::close( sockfd ); } InterfaceInfo * System::findInterface( const QString & N ) { InterfaceInfo * Run; // has PAN connection UP interface ? for( QDictIterator<InterfaceInfo> It(ProbedInterfaces); It.current(); ++It ) { Run = It.current(); if( N == Run->Name ) { // this PAN connection is up return Run; } } return 0; } #include <stdarg.h> static FILE * logf = 0; void VLog( char * Format, ... ) { va_list l; va_start(l, Format ); if( logf == (FILE *)0 ) { QString S = getenv("NS2LOG"); if( S == "stderr" ) { logf = stderr; } else if( S.isEmpty() ) { logf = fopen( "/tmp/ns2log", "a" ); } else { logf = fopen( S, "a" ); } if( ! logf ) { fprintf( stderr, "Cannot open logfile %s : %d\n", S.latin1(), errno ); logf = (FILE *)1; } else { fprintf( logf, "____ OPEN LOGFILE ____\n"); } } if( (unsigned long)logf > 1 ) { vfprintf( logf, Format, l ); } va_end( l ); fflush( logf ); } void LogClose( void ) { if( (long)logf > 1 ) { fprintf( logf, "____ CLOSE LOGFILE ____\n"); if( logf != stderr ) { fclose( logf ); } logf = 0; } } QString removeSpaces( const QString & X ) { QString Y; Y = X.simplifyWhiteSpace(); Y.replace( QRegExp(" "), "_" ); odebug << X << " **" << Y << "**" << oendl; return Y; } // // // // // MyProcess::MyProcess() : QObject(), StdoutBuffer(), StderrBuffer() { P = new OProcess(); connect( P, SIGNAL( receivedStdout(Opie::Core::OProcess*, char*, int ) ), this, SLOT( SLOT_Stdout(Opie::Core::OProcess*,char*,int) ) ); connect( P, SIGNAL( receivedStderr(Opie::Core::OProcess*, char*, int ) ), this, SLOT( SLOT_Stderr(Opie::Core::OProcess*,char*,int) ) ); connect( P, SIGNAL( processExited(Opie::Core::OProcess*) ), this, SLOT( SLOT_ProcessExited(Opie::Core::OProcess*) ) ); } MyProcess::~MyProcess() { delete P; } void MyProcess::SLOT_Stdout( Opie::Core::OProcess * , char * Buf, int len ) { + if( EchoMode ) { + write( 1, Buf, len ); + return; + } + char * LB = (char *)alloca( len + 1 ); memcpy( LB, Buf, len ); LB[len] = '\0'; // now input is zero terminated StdoutBuffer += LB; odebug << "Received " << len << " bytes on stdout" << oendl; // see if we have some lines (allow empty lines) QStringList SL = QStringList::split( "\n", StdoutBuffer, TRUE ); for( unsigned int i = 0; i < SL.count()-1; i ++ ) { Log(( "Stdout : \"%s\"\n", SL[i].latin1() ) ); emit stdoutLine( SL[i] ); } // last line is rest StdoutBuffer = SL[ SL.count()-1 ]; } void MyProcess::SLOT_Stderr( Opie::Core::OProcess * , char * Buf, int len ) { + if( EchoMode ) { + write( 2, Buf, len ); + return; + } + char * LB = (char *)alloca( len + 1 ); memcpy( LB, Buf, len ); LB[len] = '\0'; // now input is zero terminated StderrBuffer += LB; odebug << "Received " << len << " bytes on stderr" << oendl; // see if we have some lines (allow empty lines) QStringList SL = QStringList::split( "\n", StderrBuffer, TRUE ); for( unsigned int i = 0; i < SL.count()-1; i ++ ) { Log(( "Stderr : \"%s\"\n", SL[i].latin1() ) ); emit stderrLine( SL[i] ); } // last line is rest StderrBuffer = SL[ SL.count()-1 ]; } void MyProcess::SLOT_ProcessExited( Opie::Core::OProcess * ) { emit processExited( this ); } diff --git a/noncore/settings/networksettings2/networksettings2/system.h b/noncore/settings/networksettings2/networksettings2/system.h index f7a7274..ebee0d5 100644 --- a/noncore/settings/networksettings2/networksettings2/system.h +++ b/noncore/settings/networksettings2/networksettings2/system.h @@ -1,134 +1,140 @@ #ifndef __SYSTEM__H #define __SYSTEM__H #include <qstring.h> #include <opie2/oprocess.h> using namespace Opie::Core; // for hardware types #include <net/if_arp.h> #include <qdict.h> #include <qobject.h> #include <stdio.h> class NodeCollection; class ANetNodeInstance; class QFile; class MyProcess : public QObject { Q_OBJECT public : MyProcess(); ~MyProcess(); inline OProcess & process() { return *P; } + inline void setEchoMode( bool M ) { + EchoMode = M; + } + public slots : void SLOT_Stdout( Opie::Core::OProcess * P, char *, int ); void SLOT_Stderr( Opie::Core::OProcess * P, char *, int ); void SLOT_ProcessExited( Opie::Core::OProcess * P); signals : void stdoutLine( const QString & ); void stderrLine( const QString & ); void processExited( MyProcess * ); private : QString StdoutBuffer; QString StderrBuffer; OProcess * P; + // output all output to my output + bool EchoMode; }; class InterfaceInfo { public : InterfaceInfo() : Name(), MACAddress(), BCastAddress(), Netmask(), DstAddress() { } NodeCollection * assignedConnection() { return Collection; } void assignConnection( NodeCollection * NNI ) { Collection = NNI; } NodeCollection * Collection; // connection taking care of me QString Name; // name of interface int CardType; // type of card QString MACAddress; // MAC address QString Address; // IP Address QString BCastAddress; // Broadcast Address QString Netmask; // Netmask QString DstAddress; // Peer address (if P-t-P) bool IsUp; // interface is UP bool HasMulticast; // Supports Multicast bool IsPointToPoint; // IsPointToPoint card QString RcvBytes; QString SndBytes; QString RcvErrors; QString SndErrors; QString RcvDropped; QString SndDropped; QString Collisions; }; class System : public QObject { Q_OBJECT public : System( void ); ~System( void ); QDict<InterfaceInfo> & interfaces( void ); InterfaceInfo * interface( const QString& N ) { return interfaces()[N]; } // exec command as root int runAsRoot( QStringList & S, MyProcess * Prc = 0 ); // exec command as user - int execAsUser( QStringList & Cmd ); + int execAsUser( QStringList & Cmd, bool Synchronous = 0 ); // refresh stats for this interface void refreshStatistics( InterfaceInfo & ); // reloads interfaces void probeInterfaces( void ); InterfaceInfo * findInterface( const QString & DevName ); private slots : void SLOT_ProcessExited( MyProcess * ); signals : void stdoutLine( const QString & ); void stderrLine( const QString & ); void processEvent( const QString & ); private : QDict<InterfaceInfo> ProbedInterfaces; FILE * OutputOfCmd; QFile * ProcDevNet; }; #endif diff --git a/noncore/settings/networksettings2/networksettings2/systemfile.cpp b/noncore/settings/networksettings2/networksettings2/systemfile.cpp index 1b1988e..0314765 100644 --- a/noncore/settings/networksettings2/networksettings2/systemfile.cpp +++ b/noncore/settings/networksettings2/networksettings2/systemfile.cpp @@ -1,235 +1,234 @@ #include <stdio.h> #include <qpe/qpeapplication.h> #include <qfileinfo.h> #include <qmessagebox.h> #include <qfile.h> #include <qtextstream.h> #include "resources.h" #include "systemfile.h" #define TEMPLATEDIR "NS2templates/" QString TemplDir; SystemFile::SystemFile( const QString & N, const QString & P, bool KDI ){ Name = N; Path = P; InAppend = 0; F = 0; // get template info { QString S; QFileInfo FI; // find location of templates TemplDir = QPEApplication::qpeDir() + "etc/" + TEMPLATEDIR; FI.setFile( TemplDir ); if( ! FI.isDir() ) { // try current dir TemplDir = "./" TEMPLATEDIR; FI.setFile( TemplDir ); if( ! FI.isDir() ) { hasPreSection = hasPostSection = hasPreNodeSection = hasPostNodeSection = hasPreDeviceSection = hasPostDeviceSection = 0; return; } } // have found location S = TemplDir + Name + "/presection"; FI.setFile( S ); hasPreSection = ( FI.exists() && FI.isReadable() ); S = TemplDir + Name + "/postsection"; FI.setFile( S ); hasPostSection = ( FI.exists() && FI.isReadable() ); S = TemplDir + Name + "/prenodesection"; FI.setFile( S ); hasPreNodeSection = ( FI.exists() && FI.isReadable() ); S = TemplDir + Name + "/postnodesection"; FI.setFile( S ); hasPostNodeSection = ( FI.exists() && FI.isReadable() ); S = TemplDir + Name + "/predevicesection"; FI.setFile( S ); hasPreDeviceSection = ( FI.exists() && FI.isReadable() ); S = TemplDir + Name + "/postdevicesection"; FI.setFile( S ); hasPostDeviceSection = ( FI.exists() && FI.isReadable() ); } KnowsDeviceInstances = KDI; } SystemFile::SystemFile( const QString & N, bool KDI ){ Name = N; Path = ""; InAppend = 0; F =0; KnowsDeviceInstances = KDI; hasPreSection = hasPostSection = hasPreNodeSection = hasPostNodeSection = hasPreDeviceSection = hasPostDeviceSection = 0; } SystemFile::~SystemFile( void ) { close(); } bool SystemFile::open( void ) { QString Prefix = getenv( "NS2OUTPUTTO" ); if( Prefix != "stderr" /* && Name != "interfaces" */ ) { // generate files where the need to be if( F ) { F->close(); delete F; } F = new QFile( Prefix + Path + ((InAppend)?"":"bup") ); Log(( "Open systemfile %s\n", F->name().latin1() )); if( ! F->open( ((InAppend)?IO_Append : 0 ) | IO_WriteOnly ) ) { return 0; } } else { if( ! F ) { odebug << "!!!!!!!!!!!!!!!!!! " << oendl; odebug << "!!!! TESTMODE !!!!" << oendl; odebug << "!!!!!!!!!!!!!!!!!! " << oendl; odebug << "!!!!" << oendl; odebug << "!!!! GENERATE " << Path << oendl; if( InAppend ) { odebug << "!!!! In APPEND mode" << oendl; } odebug << "!!!!" << oendl; odebug << "!!!!!!!!!!!!!!!!!!" << oendl; F = new QFile(); F->open( IO_WriteOnly, stderr ); } } setDevice( F ); return 1; } bool SystemFile::close( void ) { if( ! F || ! F->isOpen() ) { return 1 ; } QString Prefix = getenv( "NS2OUTPUTTO" ); if( Prefix == "stderr" ) { return 1; } QString OldP = Prefix + Path + "bup"; F->close(); delete F; F = 0; if( ! InAppend ) { - odebug << "Rename " << OldP << " to " << Path << oendl; return ( rename( OldP.latin1(), Path.latin1() ) >= 0 ); } return 1; } bool SystemFile::preSection( void ) { if( hasPreSection ) { QFile Fl( TemplDir + Name + "/presection" ); if( ! Fl.open( IO_ReadOnly ) ) return 0; // error // copy file to this file F->writeBlock( Fl.readAll() ); } return 1; } bool SystemFile::postSection( void ) { if( hasPostSection ) { QFile Fl( TemplDir + Name + "/postsection" ); if( ! Fl.open( IO_ReadOnly ) ) return 0; // error // copy file to this file F->writeBlock( Fl.readAll() ); } return 1; } bool SystemFile::preNodeSection( ANetNodeInstance * NNI, long ) { if( hasPreNodeSection ) { QFile Fl( TemplDir + Name + "/prenodesection" ); if( ! Fl.open( IO_ReadOnly ) ) return 0; // error QTextStream TX( &Fl ); QString Out; QString S = TX.readLine(); while( ! TX.eof() ) { Out = S. arg(NNI->nodeClass()->name()); (*this) << Out << endl; S = TX.readLine(); } } return 1; } bool SystemFile::postNodeSection( ANetNodeInstance * NNI, long ) { if( hasPostNodeSection ) { QFile Fl( TemplDir + Name + "/postnodesection" ); if( ! Fl.open( IO_ReadOnly ) ) return 0; // error QTextStream TX( &Fl ); QString Out; QString S = TX.readLine(); while( ! TX.eof() ) { Out = S. arg(NNI->name()); (*this) << Out << endl; S = TX.readLine(); } } return 1; } bool SystemFile::preDeviceSection( ANetNode * NN ) { if( hasPreDeviceSection ) { QFile Fl( TemplDir + Name + "/predevicesection" ); if( ! Fl.open( IO_ReadOnly ) ) return 0; // error QTextStream TX( &Fl ); QString Out; QString S = TX.readLine(); while( ! TX.eof() ) { Out = S.arg(NN->name()); (*this) << Out << endl; S = TX.readLine(); } } return 1; } bool SystemFile::postDeviceSection( ANetNode * NN ) { if( hasPostDeviceSection ) { QFile Fl( TemplDir + Name + "/postdevicesection" ); if( ! Fl.open( IO_ReadOnly ) ) return 0; // error QTextStream TX( &Fl ); QString Out; QString S = TX.readLine(); while( ! TX.eof() ) { Out = S.arg(NN->name()); (*this) << Out << endl; S = TX.readLine(); } } return 1; } diff --git a/noncore/settings/networksettings2/nsdata.cpp b/noncore/settings/networksettings2/nsdata.cpp index d76353a..39031ed 100644 --- a/noncore/settings/networksettings2/nsdata.cpp +++ b/noncore/settings/networksettings2/nsdata.cpp @@ -1,743 +1,787 @@ #include <stdlib.h> #include <opie2/odebug.h> #include <qpe/qpeapplication.h> #include <qtextstream.h> #include <qdir.h> #include <qfile.h> #include <qfileinfo.h> #include "nsdata.h" #include <netnode.h> #include <resources.h> static QString CfgFile; NetworkSettingsData::NetworkSettingsData( void ) { // init global resources structure new TheNSResources(); if( ! NSResources->userKnown() ) { Log(( "Cannot detect qpe user HOME=\"%s\" USER=\"%s\"\n", NSResources->currentUser().HomeDir.latin1(), NSResources->currentUser().UserName.latin1() )); return; } CfgFile.sprintf( "%s/Settings/NS2.conf", NSResources->currentUser().HomeDir.latin1() ); Log(( "Cfg from %s\n", CfgFile.latin1() )); // load settings loadSettings(); // assign interfaces by scanning /tmp/profile-%s.Up files { QDir D( "/tmp" ); QFile * F = new QFile; int profilenr; QString interfacename; QTextStream TS ( F ); QStringList SL = D.entryList( "profile-*.up"); Log(( "System reports %d interfaces. Found %d up\n", NSResources->system().interfaces().count(), SL.count() )); for ( QStringList::Iterator it = SL.begin(); it != SL.end(); ++it ) { profilenr = atol( (*it).mid( 8 ).latin1() ); // read the interface store int 'up' F->setName( D.path() + "/" + (*it) ); if( F->open( IO_ReadOnly ) ) { NodeCollection * NC; interfacename = TS.readLine(); F->close(); Log(( "Assign interface %s to Profile nr %d\n", interfacename.latin1(), profilenr )); NC = NSResources->getConnection( profilenr ); if( NC ) { NC->assignInterface( NSResources->system().findInterface( interfacename ) ); + Log(( "Assign interface %p\n", + NC->assignedInterface() )); } else { Log(( "Profile nr %d no longer defined\n", profilenr )); } } } } } // saving is done by caller NetworkSettingsData::~NetworkSettingsData( void ) { delete NSResources; } void NetworkSettingsData::loadSettings( void ) { QString Line, S; QString Attr, Value; long idx; QFile F( CfgFile ); QTextStream TS( &F ); ForceModified = 0; do { if( ! F.open(IO_ReadOnly) ) break; /* load the file -> FORMAT : [NETNODETYPE] Entries ... <EMPTYLINE> [connection] Name=Name Node=Name <EMPTYLINE> */ while( ! TS.atEnd() ) { S = Line = TS.readLine(); if ( S.isEmpty() || S[0] != '[' ) continue; S = S.mid( 1, S.length()-2 ); if( ! NSResources ) { continue; } if( S == "connection" ) { // load connections -> collections of nodes bool Dangling; NodeCollection * NC = new NodeCollection( TS, Dangling ); NSResources->addConnection( NC, Dangling ); } else { ANetNode * NN = 0; ANetNodeInstance* NNI = 0; if( S.startsWith( "nodetype " ) ) { S = S.mid( 9, S.length()-9 ); S = deQuote(S); // try to find netnode NN = NSResources->findNetNode( S ); } else { // try to find instance NNI = NSResources->createNodeInstance( S ); } if( NN == 0 && NNI == 0 ) { LeftOvers.append( Line ); do { Line = TS.readLine(); // store even delimiter LeftOvers.append( Line ); } while ( ! Line.isEmpty() ); //next section continue; } // read entries of this section do { S = Line = TS.readLine(); if( S.isEmpty() ) { // empty line break; } idx = S.find( '=' ); if( idx > 0 ) { Attr = S.left( idx ); Value = S.mid( idx+1, S.length() ); } else { Value=""; Attr = S; } Value.stripWhiteSpace(); Attr.stripWhiteSpace(); Attr.lower(); // dequote Attr Value = deQuote(Value); if( NN ) { // set the attribute NN->setAttribute( Attr, Value ); } else { // set the attribute NNI->setAttribute( Attr, Value ); } } while( 1 ); if( NNI ) { // loading from file -> exists Log( ( "NodeInstance %s : %p\n", NNI->name(), NNI )); NNI->setNew( FALSE ); NSResources->addNodeInstance( NNI ); } if( NN ) { Log( ( "Node %s : %p\n", NN->name(), NN ) ); } } } } while( 0 ); } QString NetworkSettingsData::saveSettings( void ) { QString ErrS = ""; if( ! isModified() ) return ErrS; QString S; QFile F( CfgFile + ".bup" ); Log( ( "Saving settings to %s\n", CfgFile.latin1() )); if( ! F.open( IO_WriteOnly | IO_Truncate ) ) { ErrS = qApp->translate( "NetworkSettings", "<p>Could not save setup to \"%1\" !</p>" ). arg(CfgFile); // problem return ErrS; } QTextStream TS( &F ); // save global configs for( QDictIterator<ANetNode> it( NSResources->netNodes() ); it.current(); ++it ) { TS << "[nodetype " << quote( QString( it.current()->name() ) ) << "]" << endl; it.current()->saveAttributes( TS ); TS << endl; } // save leftovers for ( QStringList::Iterator it = LeftOvers.begin(); it != LeftOvers.end(); ++it ) { TS << (*it) << endl; } // save all netnode instances { ANetNodeInstance * NNI; for( QDictIterator<ANetNodeInstance> nit( NSResources->netNodeInstances()); nit.current(); ++nit ) { // header NNI = nit.current(); TS << '[' << QString(NNI->nodeClass()->name()) << ']' << endl; NNI->saveAttributes( TS ); TS << endl; } } // good connections { Name2Connection_t & M = NSResources->connections(); // for all connections for( QDictIterator<NodeCollection> it(M); it.current(); ++it ) { TS << "[connection]" << endl; it.current()->save(TS); } } // save dangling connections { Name2Connection_t & M = NSResources->danglingConnections(); // for all connections for( QDictIterator<NodeCollection> it(M); it.current(); ++it ) { TS << "[connection]" << endl; it.current()->save(TS); } } QDir D("."); D.rename( CfgFile + ".bup", CfgFile ); // // proper files AND system files regenerated // for( QDictIterator<NodeCollection> it(NSResources->connections()); it.current(); ++it ) { it.current()->setModified( 0 ); } return ErrS; } QString NetworkSettingsData::generateSettings( void ) { QString S = ""; Name2SystemFile_t & SFM = NSResources->systemFiles(); Name2Connection_t & M = NSResources->connections(); NodeCollection * NC; ANetNodeInstance * NNI; ANetNodeInstance * FirstWithData; RuntimeInfo * CurDev; ANetNode * NN, * CurDevNN = 0; long NoOfDevs; long DevCtStart; bool needToGenerate; // regenerate system files Log( ( "Generating settings from %s\n", CfgFile.latin1() )); for( QDictIterator<ANetNode> nnit( NSResources->netNodes() ); nnit.current(); ++nnit ) { bool FirstItem = 1; bool Generated = 0; CurDevNN = nnit.current(); { QStringList SL; SL = CurDevNN->properFiles(); for ( QStringList::Iterator it = SL.begin(); it != SL.end(); ++it ) { Generated = 0; FirstItem = 1; // iterate over NNI's of this class for( QDictIterator<ANetNodeInstance> nniit( NSResources->netNodeInstances() ); nniit.current(); ++nniit ) { if( nniit.current()->nodeClass() != CurDevNN ) // different class continue; // open proper file { SystemFile SF( (*it) ); if( ! CurDevNN->openFile( SF, nniit.current()) ) { // cannot open S = qApp->translate( "NetworkSettings", "<p>Cannot open proper file \"%1\" for node \"%2\"</p>" ). arg( (*it) ).arg( CurDevNN->name() ); return S; } if( ! SF.open() ) { S = qApp->translate( "NetworkSettings", "<p>Cannot open proper file \"%1\" for node \"%2\"</p>" ). arg( (*it) ).arg( CurDevNN->name() ); return S; } // preamble on first if( FirstItem ) { if( CurDevNN->generatePreamble( SF ) == 2 ) { S = qApp->translate( "NetworkSettings", "<p>Error in section \"preamble\" for proper file \"%1\" and node \"%2\"</p>" ). arg( (*it) ). arg( CurDevNN->name() ); return S; } } FirstItem = 0; Generated = 1; // item specific if( nniit.current()->generateFile( SF, -1 ) == 2 ) { S = qApp->translate( "NetworkSettings", "<p>Error in section for node \"%1\" for proper file \"%2\" and node class \"%3\"</p>" ). arg( nniit.current()->name() ). arg( (*it) ). arg( CurDevNN->name() ); return S; } } } if( Generated ) { SystemFile SF( (*it) ); if( CurDevNN->openFile( SF, 0 ) && ! SF.path().isEmpty() ) { if( ! SF.open() ) { S = qApp->translate( "NetworkSettings", "<p>Cannot open proper file \"%1\" for node \"%2\"</p>" ). arg( (*it) ).arg( CurDevNN->name() ); return S; } if( CurDevNN->generatePostamble( SF ) == 2 ) { S = qApp->translate( "NetworkSettings", "<p>Error in section \"postamble\" for proper file \"%1\" and node \"%2\"</p>" ). arg( (*it) ). arg( CurDevNN->name() ); return S; } } // no postamble } } } } // // generate all registered files // for( QDictIterator<SystemFile> sfit(SFM); sfit.current(); ++sfit ) { SystemFile * SF; SF = sfit.current(); // reset all for( QDictIterator<ANetNode> nnit( NSResources->netNodes() ); nnit.current(); ++nnit ) { nnit.current()->setDone(0); } for( QDictIterator<ANetNodeInstance> nniit( NSResources->netNodeInstances() ); nniit.current(); ++nniit ) { nniit.current()->setDone(0); } for( QDictIterator<NodeCollection> ncit(M); ncit.current(); ++ncit ) { ncit.current()->setDone(0); } Log( ( "Generating system file %s\n", SF->name().latin1() )); needToGenerate = 0; // are there netnodes that have instances and need // to write data in this system file ? for( QDictIterator<ANetNode> nnit( NSResources->netNodes() ); ! needToGenerate && nnit.current(); ++nnit ) { NN = nnit.current(); if( NN->hasDataForFile( *SF ) ) { // netnode can have data // are there instances of this node ? for( QDictIterator<ANetNodeInstance> nniit( NSResources->netNodeInstances() ); ! needToGenerate && nniit.current(); ++nniit ) { if( nniit.current()->nodeClass() == NN ) { // yes Log(("Node %s has data\n", nniit.current()->name() )); needToGenerate = 1; break; } } } } if( ! needToGenerate ) { // no instances found that might need to write data // in this systemfile Log(("No nodes for systemfile %s\n", SF->name().latin1() )); continue; } // ok generate this system file if( ! SF->open() ) { S = qApp->translate( "NetworkSettings", "<p>Cannot open system file \"%1\"</p>" ). arg( SF->name() ); return S; } // global presection for this system file if( ! SF->preSection() ) { S = qApp->translate( "NetworkSettings", "<p>Error in section \"Preamble\" for file \"%1\"</p>" ). arg( SF->name() ); return S; } // find connections that want to write to this file for( QDictIterator<NodeCollection> ncit(M); ncit.current(); ++ncit ) { NC = ncit.current(); if( NC->done() ) { // already done continue; } if( ! NC->hasDataForFile( *SF ) ) { // no data continue; } Log(("Generating %s for connection %s\n", SF->name().latin1(), NC->name().latin1() )); // find highest item that wants to write data to this file FirstWithData = NC->firstWithDataForFile( *SF ); // find device on which this connection works CurDev = NC->device(); // class of that node CurDevNN = CurDev->netNode()->nodeClass(); if( ! FirstWithData->nodeClass()->done() ) { // generate fixed part if( ! SF->preDeviceSection( CurDevNN ) ) { S = qApp->translate( "NetworkSettings", "<p>Error in section \"Pre-Device\" for file \"%1\"</p>" ). arg( SF->name() ); return S; } if( FirstWithData->nodeClass()->generateFile( *SF, FirstWithData, -2 ) == 2 ) { S = qApp->translate( "NetworkSettings", "<p>Error in section \"Common\" for file \"%1\" and node \"%2\"</p>" ). arg( SF->name() ). arg( CurDevNN->name() ); return S; } FirstWithData->nodeClass()->setDone( 1 ); Log(( "Systemfile %s for node instance %s is done\n", SF->name().latin1(), FirstWithData->name() )); } NoOfDevs = 0; DevCtStart = -1; if( SF->knowsDeviceInstances() ) { DevCtStart = 0; NoOfDevs = CurDevNN->instanceCount(); } if( ! CurDev->netNode()->nodeClass()->done() ) { // first time this device is handled // generate common device specific part for( int i = DevCtStart; i < NoOfDevs ; i ++ ) { if( FirstWithData->nodeClass()->generateFile( *SF, CurDev->netNode(), i ) == 2 ) { S = qApp->translate( "NetworkSettings", "<p>Error in section \"Device\" for file \"%1\" and node \"%2\"</p>" ). arg( SF->name() ). arg( CurDevNN->name() ); return S; } } CurDev->netNode()->nodeClass()->setDone( 1 ); Log(( "Systemfile %s for Nodeclass %s is done\n", SF->name().latin1(), CurDev->netNode()->nodeClass()->name() )); } // generate profile specific info // for all nodeconnections that work on the same device for( QDictIterator<NodeCollection> ncit2(M); ncit2.current(); ++ncit2 ) { if( ncit2.current()->device() != CurDev ) { // different device continue; } Log(("Connection %s of family %s\n", ncit2.current()->name().latin1(), CurDev->name() )); // generate NNI = ncit2.current()->firstWithDataForFile( *SF ); for( int i = DevCtStart; i < NoOfDevs ; i ++ ) { if( ! SF->preNodeSection( NNI, i ) ) { S = qApp->translate( "NetworkSettings", "<p>Error in \"Pre-Node Part\" for file \"%1\" and node \"%2\"</p>" ). arg( SF->name() ). arg( CurDevNN->name() ); return S; } switch( NNI->generateFile( *SF, i ) ) { case 0 : (*SF) << endl; break; case 1 : break; case 2 : S = qApp->translate( "NetworkSettings", "<p>Error in section \"Node\" for file \"%1\" and node \"%2\"</p>" ). arg( SF->name() ). arg( CurDevNN->name() ); return S; } if( ! SF->postNodeSection( NNI, i ) ) { S = qApp->translate( "NetworkSettings", "<p>Error in \"Post-Node Part\" for file \"%1\" and node \"%2\"</p>" ). arg( SF->name() ). arg( CurDevNN->name() ); return S; } } ncit2.current()->setDone( 1 ); } } if( ! SF->postDeviceSection( CurDevNN ) ) { S = qApp->translate( "NetworkSettings", "<p>Error in section \"Post-Device\" for file \"%1\" and node \"%2\"</p>" ). arg( SF->name() ). arg( CurDevNN->name() ); return S; } if( ! SF->postSection() ) { S = qApp->translate( "NetworkSettings", "<p>Error in section \"Closure\" for file \"%1\"</p>" ). arg( SF->name() ); return S; } // end of file SF->close(); } return S; } -QList<NodeCollection> NetworkSettingsData::collectPossible( const char * Interface ) { +QList<NodeCollection> NetworkSettingsData::collectPossible( + const QString & Interface ) { // collect connections that can work on top of this interface NodeCollection * NC; QList<NodeCollection> PossibleConnections; Name2Connection_t & M = NSResources->connections(); // for all connections for( QDictIterator<NodeCollection> it(M); it.current(); ++it ) { NC = it.current(); // check if this profile handles the requested interface if( NC->handlesInterface( Interface ) && // if different Intf. - NC->state() != Disabled && // if not enabled + NC->state() != Disabled && // if enabled NC->state() != IsUp // if already used ) { - Log( ( "Append %s for %s\n", NC->name().latin1(), Interface)); + Log( ( "Append %s for %s\n", + NC->name().latin1(), Interface.latin1() )); PossibleConnections.append( NC ); } } return PossibleConnections; } /* Called by the system to see if interface can be brought UP if allowed, echo Interface-allowed else Interface-disallowed */ -bool NetworkSettingsData::canStart( const char * Interface ) { +bool NetworkSettingsData::canStart( const QString & Interface ) { // load situation NodeCollection * NC = 0; QList<NodeCollection> PossibleConnections; PossibleConnections = collectPossible( Interface ); Log( ( "for %s : Possiblilies %d\n", - Interface, PossibleConnections.count() )); + Interface.latin1(), PossibleConnections.count() )); switch( PossibleConnections.count() ) { case 0 : // no connections break; case 1 : // one connection NC = PossibleConnections.first(); break; default : // need to ask user ? return 1; } if( NC ) { switch( NC->state() ) { case Unchecked : case Unknown : case Unavailable : case Disabled : // this profile does not allow interface to be UP // -> try others break; case Off : // try to UP the device { QString S= NC->setState( Activate ); if( ! S.isEmpty() ) { // could not bring device Online -> try other alters - Log(( "%s-c%d-disallowed : %s\n", - Interface, NC->number(), S.latin1() )); + Log(( "disallow %ld for %s : %s\n", + NC->number(), Interface.latin1(), S.latin1() )); break; } // interface assigned } // FT case Available : case IsUp : // also called for 'ifdown' // device is ready -> done - Log(( "%s-c%d-allowed\n", Interface, NC->number() )); - printf( "%s-c%d-allowed\n", Interface, NC->number() ); + Log(( "allow %ld for %s\n", NC->number(), Interface.latin1())); + printf( "A%ld%s\n", NC->number(), Interface.latin1() ); return 0; } } // if we come here no alternatives are possible - Log(( "%s-cnn-disallowed\n", Interface )); - printf( "%s-cnn-disallowed\n", Interface ); + Log(( "disallow %s\n", Interface.latin1())); + printf( "D-%s\n", Interface.latin1() ); return 0; } bool NetworkSettingsData::isModified( void ) { if( ForceModified ) return 1; for( QDictIterator<NodeCollection> it(NSResources->connections()); it.current(); ++it ) { if( it.current()->isModified() ) { return 1; } } return 0; } + +bool NetworkSettingsData::couldBeTriggered( const QString & Interface ) { + // load situation + QList<NodeCollection> PossibleTriggered; + + PossibleTriggered = collectTriggered( Interface ); + + Log( ( "for %s : Possiblilies %d\n", + Interface.latin1(), PossibleTriggered.count() )); + + return ( PossibleTriggered.count() ) ? 1 : 0; +} + +QList<NodeCollection> NetworkSettingsData::collectTriggered( + const QString & Interface ) { + + // collect connections that could be triggered by this interface + NodeCollection * NC; + QList<NodeCollection> PossibleTriggered; + + // for all connections + Name2Connection_t & M = NSResources->connections(); + + for( QDictIterator<NodeCollection> it(M); + it.current(); + ++it ) { + NC = it.current(); + // check if this profile handles the requested interface + if( NC->triggeredBy( Interface ) && // if different Intf. + NC->state() != Disabled && // if enabled + NC->state() != IsUp // if already used + ) { + Log( ( "Append %s for %s\n", + NC->name().latin1(), Interface.latin1() )); + PossibleTriggered.append( NC ); + } + } + return PossibleTriggered; +} + diff --git a/noncore/settings/networksettings2/nsdata.h b/noncore/settings/networksettings2/nsdata.h index a0ae7d1..5791c1e 100644 --- a/noncore/settings/networksettings2/nsdata.h +++ b/noncore/settings/networksettings2/nsdata.h @@ -1,34 +1,38 @@ #ifndef __NSDATA_H #define __NSDATA_H #include <netnode.h> class NetworkSettingsData { public : NetworkSettingsData( void ); ~NetworkSettingsData( void ); void loadSettings( void ); QString saveSettings( void ); QString generateSettings( void ); bool isModified( void ); inline void setModified( bool M ) { ForceModified = M; } - QList<NodeCollection> collectPossible( const char * Interface ); + QList<NodeCollection> collectPossible( const QString & Interface ); // return TRUE if we need gui to decide - bool canStart( const char * Interface ); + bool canStart( const QString & Interface ); + // return TRUE if there are vpns that could be triggered + // by this interface + bool couldBeTriggered( const QString & Interface ); private : + QList<NodeCollection> collectTriggered( const QString &Interface ); bool ForceModified; // collect strings in config file nobody wants QStringList LeftOvers; }; #endif diff --git a/noncore/settings/networksettings2/profile/profile_NNI.cpp b/noncore/settings/networksettings2/profile/profile_NNI.cpp index a1e1254..fc2d809 100644 --- a/noncore/settings/networksettings2/profile/profile_NNI.cpp +++ b/noncore/settings/networksettings2/profile/profile_NNI.cpp @@ -1,76 +1,81 @@ +#include <qpe/qpeapplication.h> #include <opie2/odebug.h> #include "profileedit.h" #include "profile_NNI.h" #include "profile_NN.h" AProfile::AProfile( ProfileNetNode * PNN ) : ANetNodeInstance( PNN ) { Data.Automatic = 1; Data.Confirm = 0; Data.Description = ""; Data.Disabled = 0; Data.TriggerVPN = 0; GUI = 0; RT = 0; } void AProfile::setSpecificAttribute( QString & Attr, QString & Value ) { if ( Attr == "automatic" ) { Data.Automatic = (Value=="yes"); } else if ( Attr == "preconfirm" ) { Data.Confirm = (Value=="yes"); } else if ( Attr == "disabled" ) { Data.Disabled = (Value=="yes"); } else if ( Attr == "triggervpn" ) { Data.TriggerVPN = (Value=="yes"); } else if ( Attr == "description" ) { Data.Description = Value; } } void AProfile::saveSpecificAttribute( QTextStream & TS ) { TS << "automatic=" << ((Data.Automatic) ? "yes" : "no") << endl; TS << "preconfirm=" << ((Data.Confirm) ? "yes" : "no") << endl; TS << "disabled=" << ((Data.Disabled) ? "yes" : "no") << endl; TS << "triggervpn=" << ((Data.TriggerVPN) ? "yes" : "no") << endl; TS << "description=" << Data.Description << endl; } QWidget * AProfile::edit( QWidget * parent ) { GUI = new ProfileEdit( parent, this ); GUI->showData( Data ); return GUI; } QString AProfile::acceptable( void ) { return ( GUI ) ? GUI->acceptable( ) : QString(); } void AProfile::commit( void ) { if( GUI && GUI->commit( Data ) ) setModified( 1 ); } short AProfile::generateFileEmbedded( SystemFile & SF, long DevNr ) { short rvl, rvd; rvl = 1; if( SF.name() == "interfaces" ) { Log(("Generate Profile for %s\n", SF.name().latin1() )); if( Data.TriggerVPN ) { // this profile triggers VPN -> insert trigger - SF << " up networksettings2 --triggervpn" + SF << " up " + << QPEApplication::qpeDir() + << "bin/networksettings2 --triggervpn " + << runtime()->device()->netNode()->nodeClass()->genNic( DevNr ) + << " || true" << endl; rvl = 0; } } rvd = ANetNodeInstance::generateFileEmbedded( SF, DevNr ); return (rvd == 2 || rvl == 2 ) ? 2 : (rvd == 0 || rvl == 0 ) ? 0 : 1; } |