11 files changed, 270 insertions, 36 deletions
diff --git a/noncore/settings/networksettings2/activateprofile.cpp b/noncore/settings/networksettings2/activateprofile.cpp index ba726bb..e4064e3 100644 --- a/noncore/settings/networksettings2/activateprofile.cpp +++ b/noncore/settings/networksettings2/activateprofile.cpp @@ -1,29 +1,31 @@ #include <qlistbox.h> +#include <qlabel.h> #include "activateprofile.h" ActivateProfile::ActivateProfile( const char * Interface ) : ActivateProfileGUI( 0, 0, TRUE ), NSD() { Possible = NSD.collectPossible( Interface ); + DeviceName_LBL->setText( Interface ); Profiles_LB->clear(); for( NodeCollection * NC = Possible.first(); NC; NC = Possible.next() ) { Profiles_LB->insertItem( NC->devicePixmap(), NC->name() ); } } ActivateProfile::~ActivateProfile( void ) { } long ActivateProfile::selectedProfile( void ) { for( unsigned int i = 0 ; i < Profiles_LB->count(); i ++ ) { if( Profiles_LB->isSelected(i) ) { return Possible.at(i)->number(); } } return -1; } diff --git a/noncore/settings/networksettings2/activateprofileGUI.ui b/noncore/settings/networksettings2/activateprofileGUI.ui index 296e044..12ab051 100644 --- a/noncore/settings/networksettings2/activateprofileGUI.ui +++ b/noncore/settings/networksettings2/activateprofileGUI.ui @@ -1,85 +1,85 @@ <!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> <height>121</height> </rect> </property> <property stdset="1"> <name>caption</name> - <string>Activate Profile</string> + <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> <hbox> <property stdset="1"> <name>margin</name> <number>0</number> </property> <property stdset="1"> <name>spacing</name> <number>6</number> </property> <widget> <class>QLabel</class> <property stdset="1"> <name>name</name> <cstring>TextLabel1</cstring> </property> <property stdset="1"> <name>text</name> - <string>Select profile for device :</string> + <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>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> </UI> diff --git a/noncore/settings/networksettings2/main.cpp b/noncore/settings/networksettings2/main.cpp index 7ec26a7..e2c00f6 100644 --- a/noncore/settings/networksettings2/main.cpp +++ b/noncore/settings/networksettings2/main.cpp @@ -1,119 +1,132 @@ #include "nsdata.h" #include "activateprofile.h" #include "networksettings.h" + #include <qpe/qpeapplication.h> #include <opie/oapplicationfactory.h> #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 int main( int argc, char * argv[] ) { int rv = 0; int Action = ACT_GUI; // could be overruled by -qws QApplication::Type GuiType = QApplication::GuiClient; #ifdef _WS_QWS_ QPEApplication * TheApp; #else QApplication * TheApp; #endif 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; } 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; } // Start Qt #ifdef _WS_QWS_ // 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 ); } #else TheApp = new QApplication( argc, argv, GuiType ); #endif // init qt with app widget switch( Action ) { case ACT_REQUEST : { NetworkSettingsData NS; - NS.canStart( argv[1] ); + if( NS.canStart( argv[1] ) ) { + QString S; + S.sprintf( QPEApplication::qpeDir()+ + "/bin/networksettings2" ); + char * MyArgv[4]; + MyArgv[0] = "networksettings2"; + MyArgv[1] = "--prompt"; + MyArgv[2] = argv[1]; + MyArgv[3] = NULL; + NSResources->system().execAsUser( S, MyArgv ); + // if we come here , failed + printf( "%s-cNN-disallowed", argv[1] ); + } } break; case ACT_REGEN : { NetworkSettingsData NS; // regen returns 0 if OK rv = (NS.regenerate()) ? 1 : 0; } break; case ACT_PROMPT : { ActivateProfile AP(argv[1]); if( AP.exec() == QDialog::Accepted ) { printf( "%s-c%ld-allowed", argv[1], AP.selectedProfile() ); } else { printf( "%s-cNN-disallowed", argv[1] ); } } break; case ACT_GUI : { QWidget * W = new NetworkSettings(0); TheApp->setMainWidget( W ); W->show(); #ifdef _WS_QWS_ W->showMaximized(); #else W->resize( W->sizeHint() ); #endif rv = TheApp->exec(); delete W; } break; } return rv; } #endif // main.cpp diff --git a/noncore/settings/networksettings2/network/network_NNI.cpp b/noncore/settings/networksettings2/network/network_NNI.cpp index 054385a..3e368a2 100644 --- a/noncore/settings/networksettings2/network/network_NNI.cpp +++ b/noncore/settings/networksettings2/network/network_NNI.cpp @@ -64,105 +64,126 @@ void ANetwork::saveSpecificAttribute( QTextStream & TS ) { 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::hasDataFor( const QString & S ) { return S == "interfaces"; } bool ANetwork::generateDataForCommonFile( SystemFile & S, long DevNr ) { QString NIC = runtime()->device()->netNode()->nodeClass()->genNic( DevNr ); if( S.name() == "interfaces" ) { // we can safely call from here since device item is deeper if( Data.UseDHCP ) { - S << "iface " << NIC << "-c" << connection()->number() << - "-allowed inet dhcp" << endl; - S << " up echo \"" << NIC << "\" > /tmp/profile-" << connection()->number() << - ".up" << Data.IPAddress << endl; + S << "iface " + << NIC + << "-c" + << connection()->number() + << "-allowed inet dhcp" + << endl; + S << " up echo \"" + << NIC + << "\" > /tmp/profile-" + << connection()->number() + << ".up" + << endl; if( Data.SendHostname ) { - S << " hostname "<< Data.Hostname << endl; + S << " hostname " + << Data.Hostname + << endl; } - S << " down rm -f /tmp/profile-" << connection()->number() << - ".up" << Data.IPAddress << endl; + S << " down rm -f /tmp/profile-" + << connection()->number() + << ".up" + << endl; } else { - S << "iface " << NIC << "-c" << connection()->number() << - "-allowed inet static" << endl; - S << " up echo \"" << NIC << "\" > /tmp/profile-" << connection()->number() << - ".up" << Data.IPAddress << endl; - S << " down rm -f /tmp/profile-" << connection()->number() << - ".up" << Data.IPAddress << endl; + S << "iface " + << NIC << "-c" + << connection()->number() + << "-allowed inet static" + << endl; + S << " up echo \"" + << NIC + << "\" > /tmp/profile-" + << connection()->number() + << ".up" + << endl; + S << " down rm -f /tmp/profile-" + << connection()->number() + << ".up" + << endl; S << " address " << Data.IPAddress << endl; S << " broadcast " << Data.Broadcast << endl; S << " 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() ); S << " network " << NW << endl; } } for ( QStringList::Iterator it = Data.PreUp_SL.begin(); it != Data.PreUp_SL.end(); ++it ) { S << " pre-up " << (*it) << endl; } for ( QStringList::Iterator it = Data.PostUp_SL.begin(); it != Data.PostUp_SL.end(); ++it ) { S << " up " << (*it) << endl; } for ( QStringList::Iterator it = Data.PreDown_SL.begin(); it != Data.PreDown_SL.end(); ++it ) { S << " down " << (*it) << endl; } for ( QStringList::Iterator it = Data.PostDown_SL.begin(); it != Data.PostDown_SL.end(); ++it ) { S << " post-down " << (*it) << endl; } } return 0; } diff --git a/noncore/settings/networksettings2/network/networkrun.cpp b/noncore/settings/networksettings2/network/networkrun.cpp index ddb9a5f..c19235a 100644 --- a/noncore/settings/networksettings2/network/networkrun.cpp +++ b/noncore/settings/networksettings2/network/networkrun.cpp @@ -1,66 +1,66 @@ #include <system.h> #include <asdevice.h> #include "networkrun.h" void NetworkRun::detectState( NodeCollection * NC ) { RuntimeInfo * RI = netNode()->nextNode()->runtime(); AsDevice * Next = RI->asDevice(); InterfaceInfo * II = Next->assignedInterface(); if( II ) { // device has assigned interface NC->setCurrentState( (( II->IsUp ) ? IsUp : Available) ); return; } // has no interface -> delegate RI->detectState( NC ); } bool NetworkRun::setState( NodeCollection * NC, Action_t A ) { // we handle UP and DOWN RuntimeInfo * RI = netNode()->nextNode()->runtime(); AsDevice * Next = RI->asDevice(); InterfaceInfo * II = Next->assignedInterface(); if( A == Up ) { // we can bring UP if lower level is available if( NC->currentState() == Available ) { QString S; S.sprintf( "ifup %s=%s-c%d-allowed", II->Name.latin1(), II->Name.latin1(), connection()->number() ); - NSResources->system().execute( S ); + NSResources->system().runAsRoot( S ); } return 1; } else if( A == Down ) { if( NC->currentState() == IsUp ) { QString S; S.sprintf( "ifdown %s=%s-c%d-allowed", II->Name.latin1(), II->Name.latin1(), connection()->number() ); - NSResources->system().execute( S ); + NSResources->system().runAsRoot( S ); } return 1; } // delegate return RI->setState( NC, A ); } bool NetworkRun::canSetState( State_t Curr, Action_t A ) { // we handle UP and DOWN RuntimeInfo * RI = netNode()->nextNode()->runtime(); if( A == Up ) { return ( Curr == Available ); } else if( A == Down ) { return ( Curr == IsUp ); } // delegate return RI->canSetState( Curr, A ); } bool NetworkRun::handlesInterface( const QString & S ) { // donno -> pass deeper return netNode()->nextNode()->runtime()->handlesInterface(S); } diff --git a/noncore/settings/networksettings2/networksettings2/resources.cpp b/noncore/settings/networksettings2/networksettings2/resources.cpp index 0301361..e6ce2b7 100644 --- a/noncore/settings/networksettings2/networksettings2/resources.cpp +++ b/noncore/settings/networksettings2/networksettings2/resources.cpp @@ -1,125 +1,131 @@ +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> +#include <pwd.h> #include <qpixmap.h> +#include <qdir.h> #include <qpe/qlibrary.h> #include <qpe/qpeapplication.h> -#include <qdir.h> #include <opie2/odebug.h> #include <qtopia/resource.h> #include "netnode.h" #include "resources.h" #define PLUGINDIR "plugins/networksettings2" #define ICONDIR "/pics/networksettings2/" // single resources instance TheNSResources * _NSResources = 0; TheNSResources::TheNSResources( void ) : NodeTypeNameMap(), ConnectionsMap() { _NSResources = this; // load available netnodes findAvailableNetNodes(QPEApplication::qpeDir() + PLUGINDIR ); // compile provides and needs lists { const char ** NeedsRun; QDictIterator<NetNode_t> 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<NetNode_t> InnerIt( AllNodeTypes ); InnerIt.current(); ++InnerIt ) { if( InnerIt.current() == OuterIt.current() ) // avoid recursive continue; const char * Provides = InnerIt.current()->NetNode->provides(); NeedsRun = OuterIt.current()->NetNode->needs(); for( ; *NeedsRun; NeedsRun ++ ) { if( strcmp( Provides, *NeedsRun ) == 0 ) { // inner provides what outer needs NNL.resize( NNL.size() + 1 ); NNL[NNL.size()-1] = InnerIt.current()->NetNode; Done = 1; // break from 2 loops break; } } } OuterIt.current()->NetNode->setAlternatives( NNLP ); } } // define Node types to Description map NodeTypeNameMap.insert( "device", tr( "Network Device" ) ); NodeTypeNameMap.insert( "line", tr( "Character device" ) ); NodeTypeNameMap.insert( "connection", tr( "IP Connection" ) ); NodeTypeNameMap.insert( "fullsetup", tr( "Connection Profile" ) ); NodeTypeDescriptionMap.insert( "device", tr( "<p>Devices that can handle IP packets</p>" ) ); NodeTypeDescriptionMap.insert( "line", tr( "<p>Devices that can handle single bytes</p>" ) ); NodeTypeDescriptionMap.insert( "connection", tr( "<p>Nodes that provide working IP connections</p>" ) ); NodeTypeDescriptionMap.insert( "fullsetup", tr( "<p>Fully configured connection profile</p>" ) ); // define system files addSystemFile( new SystemFile( "interfaces", "./interfaces" ) ); // get access to the system TheSystem = new System(); + + detectCurrentUser(); } TheNSResources::~TheNSResources( void ) { delete TheSystem; } /** * Load all modules that are found in the path * @param path a directory that is scaned for any plugins that can be loaded * and attempts to load them */ void TheNSResources::findAvailableNetNodes(const QString &path){ QDir d(path); if(!d.exists()) return; QString lang = ::getenv("LANG"); // Don't want sym links d.setFilter( QDir::Files | QDir::NoSymLinks ); const QFileInfoList *list = d.entryInfoList(); QFileInfoListIterator it( *list ); QFileInfo *fi; while ( (fi=it.current()) ) { if( fi->fileName().contains(".so")){ /* if loaded install translation */ if( loadNetNode(path + "/" + fi->fileName()) ) { QTranslator *trans = new QTranslator(qApp); QString fn = QPEApplication::qpeDir()+ "/i18n/"+lang+"/"+ fi->fileName().left( fi->fileName().find(".") )+ ".qm"; if( trans->load( fn ) ) qApp->installTranslator( trans ); else delete trans; } } ++it; } } /** * Attempt to load a function and resolve a function. @@ -187,48 +193,177 @@ const QString & TheNSResources::netNode2Description( const char * s ) { } void TheNSResources::addConnection( NodeCollection * NC ) { ANetNodeInstance * NNI; ConnectionsMap.insert( NC->name(), NC ); // add (new) nodes to NodeList for( QListIterator<ANetNodeInstance> it(*NC); it.current(); ++it ) { NNI = it.current(); if( findNodeInstance( NNI->nodeName() ) == 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->nodeName() ); } ConnectionsMap.remove( N ); } NodeCollection * TheNSResources::findConnection( const QString & S ) { return ConnectionsMap[ S ]; } 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=" ), -> SPECIAL + // AnEV( "LOGNAME=" ), -> SPECIAL + 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 = ""; + + // open proc dir and find all dirs in it + { QRegExp R("[0-9]+"); + QDir ProcDir( "/proc" ); + QString QPELoc = QPEApplication::qpeDir() + "bin/qpe"; + 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 linke + S = FI.readLink(); + if( S == QPELoc ) { + // found running qpe + QPEEnvFile.sprintf( ProcDir.path()+ "/" + (*it) + "/environ" ); + break; + } + } + } + } + + if( QPEEnvFile.isEmpty() ) { + // could not find qpe + fprintf( stderr, "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 ) { + fprintf( stderr, "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 ) { + if( strncmp( Data, "LOGNAME=", 8 ) == 0 ) { + CurrentUser.UserName = Data+8; + CurrentUser.EnvList.resize( CurrentUser.EnvList.size()+1 ); + CurrentUser.EnvList[CurrentUser.EnvList.size()-1] = + strdup( Data ); + } else if( strncmp( Data, "HOME=", 5 ) == 0 ) { + CurrentUser.HomeDir = Data+5; + CurrentUser.EnvList.resize( CurrentUser.EnvList.size()+1 ); + CurrentUser.EnvList[CurrentUser.EnvList.size()-1] = + strdup( Data ); + } else { + EnvVar_t * Run = EV; + while( Run->Name ) { + if( strncmp( Data, Run->Name, Run->Len ) == 0 ) { + CurrentUser.EnvList.resize( CurrentUser.EnvList.size()+1 ); + CurrentUser.EnvList[CurrentUser.EnvList.size()-1] = + strdup( Data ); + 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 ) { + fprintf( stderr, "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; + } + } +} diff --git a/noncore/settings/networksettings2/networksettings2/resources.h b/noncore/settings/networksettings2/networksettings2/resources.h index 4df3ce3..3048fb3 100644 --- a/noncore/settings/networksettings2/networksettings2/resources.h +++ b/noncore/settings/networksettings2/networksettings2/resources.h @@ -1,110 +1,128 @@ #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; typedef void (*GetNetNodeListFt_t)(QList<ANetNode>& PNN ); typedef struct NetNode_S { ANetNode * NetNode; QLibrary * TheLibrary; long NodeCountInLib; } NetNode_t; +class CurrentQPEUser { + +public : + CurrentQPEUser() : UserName(), HomeDir(), EnvList() {} + + QString UserName; + QString HomeDir; + int Uid; + int Gid; + QArray<char *> EnvList; +}; + typedef QDict<NetNode_t> Name2NetNode_t; typedef QDict<ANetNodeInstance > Name2Instance_t; typedef QDict<NodeCollection> Name2Connection_t; typedef QDict<SystemFile> Name2SystemFile_t; class TheNSResources { public : TheNSResources( void ); ~TheNSResources( ); System & system() { return *TheSystem; } QPixmap getPixmap( const QString & Name ); Name2NetNode_t & netNodes( void ) { return AllNodeTypes; } bool netNodeExists( const QString & X ) { return AllNodeTypes.find(X)!=0; } Name2SystemFile_t & systemFiles( void ) { return SystemFiles; } void addSystemFile( SystemFile * SF ) { SystemFiles.insert( SF->name(), SF ); } ANetNodeInstance * createNodeInstance( const QString & S ) { ANetNodeInstance * NNI = 0; NetNode_t * NNT = AllNodeTypes[S]; ANetNode * NN; if( ! NNT ) { NN = FakeNode = ( FakeNode ) ? FakeNode : new FakeNetNode(); } else { NN = NNT->NetNode; } NNI = NN->createInstance(); NNI->initialize(); return NNI; } Name2Instance_t & netNodeInstances( void ) { return AllNodes; } void addNodeInstance( ANetNodeInstance * I ) { AllNodes.insert( I->nodeName(), I ); } void removeNodeInstance( const QString & N ) { AllNodes.remove( N );} ANetNodeInstance * findNodeInstance( const QString & S ) { return (AllNodes.find(S)!=0) ? AllNodes[S] : 0; } const QString & netNode2Name( const char * Type ); const QString & netNode2Description( const char * Type ); void renumberConnections( void ); void addConnection( NodeCollection * NC ); void removeConnection( const QString & N ); NodeCollection * findConnection( const QString & N ); Name2Connection_t & connections( void ) { return ConnectionsMap; } + CurrentQPEUser & currentUser( void ) + { return CurrentUser; } + private : + void detectCurrentUser( void ); QString tr( const char * path ); void findAvailableNetNodes( const QString &path ); bool loadNetNode( const QString &pluginFileName, const QString &resolveString = "create_plugin"); QMap< QString, QString> NodeTypeNameMap; QMap< QString, QString> NodeTypeDescriptionMap; Name2Connection_t ConnectionsMap; System * TheSystem; Name2SystemFile_t SystemFiles; // all node type classes Name2NetNode_t AllNodeTypes; // all nodes Name2Instance_t AllNodes; + + CurrentQPEUser CurrentUser; }; extern TheNSResources * _NSResources; #define NSResources _NSResources #endif diff --git a/noncore/settings/networksettings2/networksettings2/system.cpp b/noncore/settings/networksettings2/networksettings2/system.cpp index a68f3c0..2133d34 100644 --- a/noncore/settings/networksettings2/networksettings2/system.cpp +++ b/noncore/settings/networksettings2/networksettings2/system.cpp @@ -1,87 +1,95 @@ -#include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> -#include <qfile.h> -#include <qtextstream.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 <fcntl.h> +#include <errno.h> +#include <unistd.h> + +#include <qdir.h> +#include <qregexp.h> +#include <qstringlist.h> +#include <qfile.h> +#include <qtextstream.h> #include "resources.h" #include "system.h" #define PROCNETDEV "/proc/net/dev" 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 ) : ProbedInterfaces() { probeInterfaces(); } System::~System( void ) { if( ProcDevNet ) delete ProcDevNet; } -int System::execute( const QString & S ) { +int System::runAsRoot( const QString & S ) { QString MyS = S; char * usr = getenv("USER"); int rv; if( S.isEmpty() ) { // loophole to start shell return 8888; } if( usr == 0 || strcmp( usr, "root" ) ) { // unknown or non-root user -> use SUDO MyS.prepend( "sudo " ); } fprintf( stderr, "Executing %s\n", MyS.latin1() ); rv = system( MyS.latin1() ) ; switch( rv ) { case -1 : // cannot fork return 1; case 127 : // cannot start shell return 2; default : if( WEXITSTATUS(rv) != 0 ) { // error in command return 3; } } // all is fine return 0; } 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(); @@ -273,48 +281,75 @@ void System::probeInterfaces( void ) { 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 fprintf( stderr, "OLDNIC %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 = ""; } fprintf( stderr, "NIC %s UP %d\n", NicName.latin1(), IFI->IsUp ); } } + +void System::execAsUser( QString & Cmd, char * argv[] ) { + CurrentQPEUser CU = NSResources->currentUser(); + + if( CU.UserName.isEmpty() ) { + // if we come here, the exec was not successfull + fprintf( stderr, "User not known \n" ); + return; + } + + // now we are ready to exec the requested command + setuid( CU.Uid ); + setgid( CU.Gid ); + + char ** envp = (char **)alloca( sizeof( char *) * + (CU.EnvList.count()+1) ); + + for( unsigned int i = 0 ; i < CU.EnvList.count() ; i ++ ) { + *(envp+i) = CU.EnvList[i]; + } + envp[CU.EnvList.count()]=NULL; + + execve( Cmd.latin1(), argv, envp ); + + // if we come here, the exec was not successfull + fprintf( stderr, "Could not exec : %d\n", errno ); +} diff --git a/noncore/settings/networksettings2/networksettings2/system.h b/noncore/settings/networksettings2/networksettings2/system.h index f89fe5d..96ee9bd 100644 --- a/noncore/settings/networksettings2/networksettings2/system.h +++ b/noncore/settings/networksettings2/networksettings2/system.h @@ -14,63 +14,68 @@ public : InterfaceInfo() : Name(), MACAddress(), BCastAddress(), Netmask(), DstAddress() { } ANetNodeInstance * assignedNode() { return NetNode; } void assignNode( ANetNodeInstance * NNI ) { NetNode = NNI; } ANetNodeInstance * NetNode; // netnode 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 : System( void ); ~System( void ); QDict<InterfaceInfo> & interfaces( void ) { return ProbedInterfaces; } InterfaceInfo * interface( const QString& N ) { return ProbedInterfaces[N]; } - int execute( const QString & S ); + // exec command as root + int runAsRoot( const QString & S ); + + // exec command as user + void execAsUser( QString & Cmd, char * argv[] ); + // refresh stats for this interface void refreshStatistics( InterfaceInfo & ); // reloads interfaces void probeInterfaces( void ); private : QDict<InterfaceInfo> ProbedInterfaces; QFile * ProcDevNet; }; #endif diff --git a/noncore/settings/networksettings2/nsdata.cpp b/noncore/settings/networksettings2/nsdata.cpp index eb63e02..b4d9aaa 100644 --- a/noncore/settings/networksettings2/nsdata.cpp +++ b/noncore/settings/networksettings2/nsdata.cpp @@ -1,66 +1,68 @@ #include <stdlib.h> #include <qpe/qpeapplication.h> #include <qtextstream.h> #include <qdir.h> #include <qfile.h> #include <qfileinfo.h> #include "nsdata.h" #include <asdevice.h> #include <resources.h> static QString CfgFile; NetworkSettingsData::NetworkSettingsData( void ) { // init global resources structure new TheNSResources(); - CfgFile.sprintf( "%s/NETCONFIG", getenv("HOME") ); + CfgFile.sprintf( "%s/NETCONFIG", + NSResources->currentUser().HomeDir.latin1() ); + fprintf( stderr, "Cfg from %s\n", CfgFile.latin1() ); // load settings Force = 0; IsModified = 0; loadSettings(); } // saving is done by caller NetworkSettingsData::~NetworkSettingsData( void ) { delete NSResources; } void NetworkSettingsData::loadSettings( void ) { QString S; ANetNodeInstance* NNI; QString Attr, Value; long idx; QFile F( CfgFile ); QTextStream TS( &F ); do { if( ! F.open(IO_ReadOnly) ) break; /* load the file -> FORMAT : [NETNODETYPE] Entries ... <EMPTYLINE> [connection] Name=Name Node=Name <EMPTYLINE> */ while( ! TS.atEnd() ) { S = TS.readLine(); if ( S.isEmpty() || S[0] != '[' ) continue; S = S.mid( 1, S.length()-2 ); if( ! NSResources ) { continue; @@ -308,159 +310,161 @@ QString NetworkSettingsData::generateSettings( bool ForceReq ) { } if( ! NNI ) // no instances -> next netnode type continue; // has this node data for this system file ? if( (CurDev = NNI->runtime()->asDevice() ) ) { // generate start for this nodetype for all possible devices of this type for( int i = 0; i < CurDevNN->instanceCount(); i ++ ) { S = generateSystemFileNode( *SF, CurDev, NNI, i ); if( ! S.isEmpty() ) return S; } } else { S = generateSystemFileNode( *SF, 0, NNI, -1 ); if( ! S.isEmpty() ) return S; } } if( SF->postSection() ) { S = qApp->translate( "NetworkSettings", "<p>Error in postSection for file \"%1\"</p>" ). arg( SF->name() ); return S; } } while( 0 ); SF->close(); } } Force = 0; return S; } QList<NodeCollection> NetworkSettingsData::collectPossible( const char * 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 + fprintf( stderr, "check %s\n", NC->name().latin1() ); if( NC->handlesInterface( Interface ) && // if different Intf. NC->state() != Disabled && // if not enabled NC->state() != IsUp // if already used ) { + fprintf( stderr, "Append %s\n", NC->name().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 */ -void NetworkSettingsData::canStart( const char * Interface ) { +bool NetworkSettingsData::canStart( const char * Interface ) { // load situation NodeCollection * NC = 0; QList<NodeCollection> PossibleConnections; PossibleConnections = collectPossible( Interface ); + fprintf( stderr, "Possiblilies %d\n", + PossibleConnections.count() ); switch( PossibleConnections.count() ) { case 0 : // no connections break; case 1 : // one connection NC = PossibleConnections.first(); break; default : // need to ask user ? - // are we connected to a server - // system( "su %d networksettings2 --prompt %s\n", - // "", Interface ); - break; + 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 if( ! NC->setState( Activate ) ) { // cannot bring device Online -> try other alters break; } // FT case Available : case IsUp : // also called for 'ifdown' // device is ready -> done printf( "%s-c%d-allowed\n", Interface, NC->number() ); - return; + return 0; } - } else { - // if we come here no alternatives are possible - printf( "%s-cnn-disallowed\n", Interface ); - } + } + + // if we come here no alternatives are possible + printf( "%s-cnn-disallowed\n", Interface ); + return 0; } /* Called by the system to regenerate config files */ bool NetworkSettingsData::regenerate( void ) { QString S; // load situation S = generateSettings( TRUE ); if( ! S.isEmpty() ) { fprintf( stdout, "%s\n", S.latin1() ); return 1; } return 0; } QString NetworkSettingsData::generateSystemFileNode( SystemFile &SF, AsDevice * CurDev, ANetNodeInstance * DevNNI, long DevInstNr ) { QString S=""; ANetNode * CurDevNN = DevNNI->nodeClass(); Name2Connection_t & M = NSResources->connections(); if( SF.preDeviceSection( CurDevNN ) ) { S = qApp->translate( "NetworkSettings", "<p>Error in preDeviceSection for file \"%1\" and nodetype \"%2\"</p>" ). arg( SF.name() ). arg( CurDevNN->nodeName() ); return S; } if( CurDevNN->hasDataFor( SF.name() ) ) { if( CurDevNN->generateDeviceDataForCommonFile( SF, DevInstNr ) ) { S = qApp->translate( "NetworkSettings", "<p>Error in node Device part for file \"%1\" and node \"%2\"</p>" ). arg( SF.name() ). arg( CurDevNN->nodeName() ); return S; } } if( CurDev ) fprintf( stderr, "Cur %s\n", CurDevNN->nodeName().latin1() ); else diff --git a/noncore/settings/networksettings2/nsdata.h b/noncore/settings/networksettings2/nsdata.h index b54df24..eb96930 100644 --- a/noncore/settings/networksettings2/nsdata.h +++ b/noncore/settings/networksettings2/nsdata.h @@ -1,42 +1,43 @@ #ifndef __NSDATA_H #define __NSDATA_H #include "netnode.h" class NetworkSettingsData { public : NetworkSettingsData( void ); ~NetworkSettingsData( void ); void loadSettings( void ); QString saveSettings( void ); QString generateSettings( bool Force = FALSE ); bool isModified( void ) { return IsModified; } void setModified( bool m ) { IsModified = m; } QList<NodeCollection> collectPossible( const char * Interface ); - void canStart( const char * Interface ); + // return TRUE if we need gui to decide + bool canStart( const char * Interface ); bool regenerate( void ); void forceGeneration( bool m ) { Force = m; } private : QString NetworkSettingsData::generateSystemFileNode( SystemFile & SF, AsDevice * CurDev, ANetNodeInstance * DevNNI, long DevInstNr ); bool IsModified; bool Force; }; #endif |