00001 #include <sys/types.h>
00002 #include <sys/wait.h>
00003
00004 #include <net/if.h>
00005 #include <net/if_arp.h>
00006 #include <netinet/in.h>
00007 #include <arpa/inet.h>
00008 #include <sys/ioctl.h>
00009 #include <sys/socket.h>
00010 #include <stdlib.h>
00011 #include <stdio.h>
00012 #include <fcntl.h>
00013 #include <errno.h>
00014 #include <unistd.h>
00015
00016 #include <opie2/oprocess.h>
00017
00018 #include <qdir.h>
00019 #include <qregexp.h>
00020 #include <qstringlist.h>
00021 #include <qfile.h>
00022 #include <qtextstream.h>
00023 #include <qapplication.h>
00024
00025 #include "resources.h"
00026 #include "system.h"
00027
00028 #define PROCNETDEV "/proc/net/dev"
00029
00030 #ifndef ARPHRD_IEEE80211
00031 #define ARPHRD_IEEE80211 801
00032 #endif
00033
00034 static char Dig2Hex[] = {
00035 '0', '1', '2', '3',
00036 '4', '5', '6', '7',
00037 '8', '9', 'A', 'B',
00038 'C', 'D', 'E', 'F'
00039 };
00040
00041
00042 #define HN(x) Dig2Hex[(((x)&0xf0)>>4)]
00043
00044 #define LN(x) Dig2Hex[((x)&0x0f)]
00045
00046 System::System( void ) : QObject(), ProbedInterfaces() {
00047 ProcDevNet = 0;
00048 }
00049
00050 System::~System( void ) {
00051 if( ProcDevNet )
00052 delete ProcDevNet;
00053 }
00054
00055 QDict<InterfaceInfo> & System::interfaces( void ) {
00056 if( ProbedInterfaces.count() == 0 ) {
00057 probeInterfaces();
00058 }
00059 return ProbedInterfaces;
00060 }
00061
00062 int System::runAsRoot( QStringList & S, MyProcess * Prc ) {
00063 char * usr = getenv("USER");
00064
00065 if( S.count() == 0 ) {
00066
00067 return 8888;
00068 }
00069 if( usr == 0 || strcmp( usr, "root" ) ) {
00070
00071 S.prepend( "sudo" );
00072 }
00073
00074 if( getenv( "NS2TESTMODE" ) ) {
00075 odebug << "TESTMODE !!! execute "
00076 << S.join( " ")
00077 << oendl;
00078 } else {
00079 MyProcess * P;
00080
00081 if( Prc ) {
00082 P = Prc;
00083 } else {
00084 P = new MyProcess();
00085 emit processEvent( tr("Command : ") + S.join( " " ) );
00086
00087 connect( P,
00088 SIGNAL( stdoutLine( const QString & ) ),
00089 this,
00090 SIGNAL( stdoutLine( const QString & ) ) );
00091
00092 connect( P,
00093 SIGNAL( stderrLine( const QString & ) ),
00094 this,
00095 SIGNAL( stderrLine( const QString & ) ) );
00096
00097 connect( P,
00098 SIGNAL(processExited(MyProcess*) ),
00099 this, SLOT
00100 (SLOT_ProcessExited(MyProcess*) ) );
00101 }
00102
00103 P->process() << S;
00104
00105 Log(("Executing %s\n", S.join( " " ).latin1() ));
00106
00107 if( ! P->process().start( OProcess::DontCare,
00108 OProcess::AllOutput ) ) {
00109 odebug << "Error starting " << S << oendl;
00110 if( ! Prc )
00111 delete P;
00112
00113 return 0;
00114 }
00115 odebug << "Started " << S << oendl;
00116 }
00117
00118
00119 return 1;
00120 }
00121
00122 int System::execAsUser( QStringList & SL, bool Synchronous ) {
00123 MyProcess * P = new MyProcess();
00124 CurrentQPEUser CU = NSResources->currentUser();
00125 char * usr = getenv("USER");
00126
00127 if( usr == 0 ||
00128 strcmp( usr, "root" ) == 0 ) {
00129
00130 if( CU.UserName.isEmpty() ) {
00131
00132 Log(("User not known \n" ));
00133 return 0;
00134 }
00135 }
00136
00137
00138 setuid( CU.Uid );
00139 setgid( CU.Gid );
00140
00141 for( unsigned int i = 0 ; i < CU.EnvList.count() ; i ++ ) {
00142 QString X;
00143 QStringList SL;
00144 X = CU.EnvList[i];
00145 SL = QStringList::split( "=", X );
00146 P->process().setEnvironment( SL[0], SL[1] );
00147 }
00148
00149 P->process() << SL;
00150
00151 emit processEvent( tr("Command : ") + SL.join( " " ) );
00152
00153 Log(("Executing as user %s : %s\n",
00154 CU.UserName.latin1(),
00155 SL.join( " " ).latin1() ));
00156
00157 P->setEchoMode( Synchronous );
00158
00159 bool rv = P->process().start(
00160 (Synchronous) ? OProcess::Block :
00161 OProcess::DontCare,
00162 (Synchronous) ? OProcess::AllOutput :
00163 OProcess::NoCommunication );
00164 delete P;
00165
00166 if( ! rv ) {
00167
00168 Log(("Could not exec : %d\n", errno ));
00169 }
00170
00171 return rv;
00172 }
00173
00174 void System::SLOT_ProcessExited( MyProcess * P ) {
00175 QString R;
00176
00177 for( QValueListConstIterator<QCString> it = P->process().args().begin();
00178 it != P->process().args().end();
00179 ++it ) {
00180 R += (*it);
00181 R += " ";
00182 }
00183
00184 R += "Returned with " + QString().setNum( P->process().exitStatus() );
00185 emit processEvent( R );
00186 delete P;
00187 }
00188
00189 void System::refreshStatistics( InterfaceInfo & I ) {
00190 if( ! ProcDevNet ) {
00191 return;
00192 }
00193
00194 ProcDevNet->close();
00195 ProcDevNet->open( IO_ReadOnly );
00196
00197 QString line;
00198 QTextStream procTs(ProcDevNet);
00199 QStringList SL;
00200 int loc = -1;
00201 int version;
00202
00203 procTs.readLine();
00204 line = procTs.readLine();
00205
00206 if( line.find("compressed") )
00207 version = 3;
00208 else if( line.find( "bytes" ) )
00209 version = 2;
00210 else
00211 version = 1;
00212 while((line = procTs.readLine().simplifyWhiteSpace()) != QString::null) {
00213 if( (loc = line.find(":") ) == -1) {
00214 continue;
00215 }
00216
00217 if( I.Name != line.left(loc) )
00218 continue;
00219
00220
00221 SL = QStringList::split( ' ', line.mid(loc+1), FALSE );
00222
00223
00224 switch( version ) {
00225 case 1 :
00226 I.RcvBytes = "";
00227 I.RcvPackets = SL[0];
00228 I.RcvErrors = SL[1];
00229 I.RcvDropped = SL[2];
00230
00231 I.SndBytes = "";
00232 I.SndPackets = SL[5];
00233 I.SndErrors = SL[6];
00234 I.SndDropped = SL[7];
00235
00236 I.Collisions = SL[9];
00237 break;
00238 case 2 :
00239 I.RcvBytes = SL[0];
00240 I.RcvPackets = SL[1];
00241 I.RcvErrors = SL[2];
00242 I.RcvDropped = SL[3];
00243
00244 I.SndBytes = SL[6];
00245 I.SndPackets = SL[7];
00246 I.SndErrors = SL[8];
00247 I.SndDropped = SL[9];
00248
00249 I.Collisions = SL[11];
00250 break;
00251 case 3 :
00252 I.RcvBytes = SL[0];
00253 I.RcvPackets = SL[1];
00254 I.RcvErrors = SL[2];
00255 I.RcvDropped = SL[3];
00256
00257 I.SndBytes = SL[8];
00258 I.SndPackets = SL[9];
00259 I.SndErrors = SL[10];
00260 I.SndDropped = SL[11];
00261
00262 I.Collisions = SL[13];
00263 break;
00264 }
00265 break;
00266 }
00267 }
00268
00269
00270
00271
00272
00273
00274 void System::probeInterfaces( void ) {
00275
00276
00277 int sockfd;
00278
00279 struct ifreq ifrs;
00280 InterfaceInfo * IFI;
00281
00282
00283 for( QDictIterator<InterfaceInfo> it( ProbedInterfaces );
00284 it.current();
00285 ++it ) {
00286 it.current()->IsUp = 0;
00287 }
00288
00289 sockfd = socket(PF_INET, SOCK_DGRAM, 0);
00290 if(sockfd == -1) {
00291 odebug << "Cannot open INET socket "
00292 << errno
00293 << " "
00294 << strerror( errno )
00295 << oendl;
00296 return;
00297 }
00298
00299
00300
00301 ProcDevNet = new QFile(PROCNETDEV);
00302 if( ! ProcDevNet->open(IO_ReadOnly) ) {
00303 odebug << "Cannot open "
00304 << PROCNETDEV
00305 << " "
00306 << errno
00307 << " "
00308 << strerror( errno )
00309 << oendl;
00310 delete ProcDevNet;
00311 ProcDevNet =0;
00312 ::close( sockfd );
00313 return;
00314 }
00315
00316 QString line;
00317 QString NicName;
00318 QTextStream procTs(ProcDevNet);
00319 int loc = -1;
00320
00321 procTs.readLine();
00322 procTs.readLine();
00323 while((line = procTs.readLine().simplifyWhiteSpace()) != QString::null) {
00324 if((loc = line.find(":")) == -1) {
00325 continue;
00326 }
00327
00328 NicName = line.left(loc);
00329
00330
00331 strcpy( ifrs.ifr_name, NicName.latin1() );
00332
00333 if ( ! ( IFI = ProbedInterfaces.find( NicName ) ) ) {
00334
00335 Log(("New NIC found : %s\n", NicName.latin1()));
00336 IFI = new InterfaceInfo;
00337 IFI->Name = line.left(loc);
00338 IFI->Collection = 0;
00339 ProbedInterfaces.insert( IFI->Name, IFI );
00340
00341
00342 if( ioctl(sockfd, SIOCGIFFLAGS, &ifrs) >= 0 ) {
00343 IFI->IsPointToPoint = ((ifrs.ifr_flags & IFF_POINTOPOINT) == IFF_POINTOPOINT);
00344 } else {
00345 IFI->IsPointToPoint = 0;
00346 }
00347
00348
00349 IFI->DstAddress = "";
00350
00351 if( IFI->IsPointToPoint ) {
00352 if( ioctl(sockfd, SIOCGIFDSTADDR, &ifrs) >= 0 ) {
00353 IFI->DstAddress =
00354 inet_ntoa(((struct sockaddr_in*)&ifrs.ifr_dstaddr)->sin_addr);
00355 }
00356 }
00357
00358 IFI->CardType = 999999;
00359 IFI->MACAddress = "";
00360
00361 if( ioctl(sockfd, SIOCGIFHWADDR, &ifrs) >= 0 ) {
00362 Log(("Family for NIC %s : %d\n", IFI->Name.latin1(),
00363 ifrs.ifr_hwaddr.sa_family ));
00364
00365 IFI->CardType = ifrs.ifr_hwaddr.sa_family;
00366 switch( ifrs.ifr_hwaddr.sa_family ) {
00367 case ARPHRD_ETHER :
00368
00369
00370 IFI->MACAddress.sprintf(
00371 "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c",
00372 HN( ifrs.ifr_hwaddr.sa_data[0] ),
00373 LN( ifrs.ifr_hwaddr.sa_data[0] ),
00374 HN( ifrs.ifr_hwaddr.sa_data[1] ),
00375 LN( ifrs.ifr_hwaddr.sa_data[1] ),
00376 HN( ifrs.ifr_hwaddr.sa_data[2] ),
00377 LN( ifrs.ifr_hwaddr.sa_data[2] ),
00378 HN( ifrs.ifr_hwaddr.sa_data[3] ),
00379 LN( ifrs.ifr_hwaddr.sa_data[3] ),
00380 HN( ifrs.ifr_hwaddr.sa_data[4] ),
00381 LN( ifrs.ifr_hwaddr.sa_data[4] ),
00382 HN( ifrs.ifr_hwaddr.sa_data[5] ),
00383 LN( ifrs.ifr_hwaddr.sa_data[5] )
00384 );
00385 break;
00386 #ifdef ARPHRD_IEEE1394
00387 case ARPHRD_IEEE1394 :
00388 IFI->MACAddress.sprintf(
00389 "%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",
00390 HN( ifrs.ifr_hwaddr.sa_data[0] ),
00391 LN( ifrs.ifr_hwaddr.sa_data[0] ),
00392 HN( ifrs.ifr_hwaddr.sa_data[1] ),
00393 LN( ifrs.ifr_hwaddr.sa_data[1] ),
00394 HN( ifrs.ifr_hwaddr.sa_data[2] ),
00395 LN( ifrs.ifr_hwaddr.sa_data[2] ),
00396 HN( ifrs.ifr_hwaddr.sa_data[3] ),
00397 LN( ifrs.ifr_hwaddr.sa_data[3] ),
00398 HN( ifrs.ifr_hwaddr.sa_data[4] ),
00399 LN( ifrs.ifr_hwaddr.sa_data[4] ),
00400 HN( ifrs.ifr_hwaddr.sa_data[5] ),
00401 LN( ifrs.ifr_hwaddr.sa_data[5] ),
00402 HN( ifrs.ifr_hwaddr.sa_data[6] ),
00403 LN( ifrs.ifr_hwaddr.sa_data[6] ),
00404 HN( ifrs.ifr_hwaddr.sa_data[7] ),
00405 LN( ifrs.ifr_hwaddr.sa_data[7] ),
00406 HN( ifrs.ifr_hwaddr.sa_data[8] ),
00407 LN( ifrs.ifr_hwaddr.sa_data[8] ),
00408 HN( ifrs.ifr_hwaddr.sa_data[9] ),
00409 LN( ifrs.ifr_hwaddr.sa_data[9] ),
00410 HN( ifrs.ifr_hwaddr.sa_data[10] ),
00411 LN( ifrs.ifr_hwaddr.sa_data[10] ),
00412 HN( ifrs.ifr_hwaddr.sa_data[11] ),
00413 LN( ifrs.ifr_hwaddr.sa_data[11] ),
00414 HN( ifrs.ifr_hwaddr.sa_data[12] ),
00415 LN( ifrs.ifr_hwaddr.sa_data[12] ),
00416 HN( ifrs.ifr_hwaddr.sa_data[13] ),
00417 LN( ifrs.ifr_hwaddr.sa_data[13] )
00418 );
00419 break;
00420 #endif
00421 case ARPHRD_PPP :
00422 break;
00423 case ARPHRD_IEEE80211 :
00424 break;
00425 case ARPHRD_IRDA :
00426 break;
00427 }
00428 }
00429 } else
00430 Log(("Redetected NIC %s\n", NicName.latin1()));
00431
00432
00433 if( ioctl(sockfd, SIOCGIFFLAGS, &ifrs) >= 0 ) {
00434 IFI->IsUp = ((ifrs.ifr_flags & IFF_UP) == IFF_UP);
00435 IFI->HasMulticast = ((ifrs.ifr_flags & IFF_MULTICAST) == IFF_MULTICAST);
00436 } else {
00437 IFI->IsUp = 0;
00438 IFI->HasMulticast = 0;
00439 }
00440
00441 if( ioctl(sockfd, SIOCGIFADDR, &ifrs) >= 0 ) {
00442 IFI->Address =
00443 inet_ntoa(((struct sockaddr_in*)&ifrs.ifr_addr)->sin_addr);
00444 } else {
00445 IFI->Address = "";
00446 IFI->IsUp = 0;
00447 }
00448 if( ioctl(sockfd, SIOCGIFBRDADDR, &ifrs) >= 0 ) {
00449 IFI->BCastAddress =
00450 inet_ntoa(((struct sockaddr_in*)&ifrs.ifr_broadaddr)->sin_addr);
00451 } else {
00452 IFI->BCastAddress = "";
00453 }
00454 if( ioctl(sockfd, SIOCGIFNETMASK, &ifrs) >= 0 ) {
00455 IFI->Netmask =
00456 inet_ntoa(((struct sockaddr_in*)&ifrs.ifr_netmask)->sin_addr);
00457 } else {
00458 IFI->Netmask = "";
00459 }
00460 Log(("NIC %s UP ? %d\n", NicName.latin1(), IFI->IsUp ));
00461 }
00462
00463 ::close( sockfd );
00464 }
00465
00466 InterfaceInfo * System::findInterface( const QString & N ) {
00467 InterfaceInfo * Run;
00468
00469 for( QDictIterator<InterfaceInfo> It(ProbedInterfaces);
00470 It.current();
00471 ++It ) {
00472 Run = It.current();
00473 if( N == Run->Name ) {
00474
00475 return Run;
00476 }
00477 }
00478 return 0;
00479 }
00480
00481 #include <stdarg.h>
00482 static FILE * logf = 0;
00483
00484 void VLog( char * Format, ... ) {
00485 va_list l;
00486
00487 va_start(l, Format );
00488
00489 if( logf == (FILE *)0 ) {
00490 QString S = getenv("NS2LOG");
00491 if( S == "stderr" ) {
00492 logf = stderr;
00493 } else if( S.isEmpty() ) {
00494 logf = fopen( "/tmp/ns2log", "a" );
00495 } else {
00496 logf = fopen( S, "a" );
00497 }
00498
00499 if( ! logf ) {
00500 fprintf( stderr, "Cannot open logfile %s : %d\n",
00501 S.latin1(), errno );
00502 logf = (FILE *)1;
00503 } else {
00504 fprintf( logf, "____ OPEN LOGFILE ____\n");
00505 }
00506 }
00507
00508 if( (unsigned long)logf > 1 ) {
00509 vfprintf( logf, Format, l );
00510 }
00511 va_end( l );
00512 fflush( logf );
00513
00514 }
00515
00516 void LogClose( void ) {
00517 if( (long)logf > 1 ) {
00518 fprintf( logf, "____ CLOSE LOGFILE ____\n");
00519 if( logf != stderr ) {
00520 fclose( logf );
00521 }
00522 logf = 0;
00523 }
00524 }
00525
00526 QString removeSpaces( const QString & X ) {
00527 QString Y;
00528 Y = X.simplifyWhiteSpace();
00529 Y.replace( QRegExp(" "), "_" );
00530 odebug << X << " **" << Y << "**" << oendl;
00531 return Y;
00532 }
00533
00534
00535
00536
00537
00538
00539
00540 MyProcess::MyProcess() : QObject(), StdoutBuffer(), StderrBuffer() {
00541 P = new OProcess();
00542 connect( P,
00543 SIGNAL( receivedStdout(Opie::Core::OProcess*, char*, int ) ),
00544 this,
00545 SLOT( SLOT_Stdout(Opie::Core::OProcess*,char*,int) ) );
00546
00547 connect( P,
00548 SIGNAL( receivedStderr(Opie::Core::OProcess*, char*, int ) ),
00549 this,
00550 SLOT( SLOT_Stderr(Opie::Core::OProcess*,char*,int) ) );
00551 connect( P,
00552 SIGNAL( processExited(Opie::Core::OProcess*) ),
00553 this,
00554 SLOT( SLOT_ProcessExited(Opie::Core::OProcess*) ) );
00555 }
00556
00557 MyProcess::~MyProcess() {
00558 delete P;
00559 }
00560
00561 void MyProcess::SLOT_Stdout( Opie::Core::OProcess * , char * Buf, int len ) {
00562 if( EchoMode ) {
00563 write( 1, Buf, len );
00564 return;
00565 }
00566
00567 char * LB = (char *)alloca( len + 1 );
00568 memcpy( LB, Buf, len );
00569 LB[len] = '\0';
00570
00571
00572 StdoutBuffer += LB;
00573
00574 odebug << "Received " << len << " bytes on stdout" << oendl;
00575
00576 QStringList SL = QStringList::split( "\n", StdoutBuffer, TRUE );
00577
00578 for( unsigned int i = 0; i < SL.count()-1; i ++ ) {
00579 Log(( "Stdout : \"%s\"\n", SL[i].latin1() ) );
00580 emit stdoutLine( SL[i] );
00581 }
00582
00583
00584 StdoutBuffer = SL[ SL.count()-1 ];
00585 }
00586
00587 void MyProcess::SLOT_Stderr( Opie::Core::OProcess * , char * Buf, int len ) {
00588 if( EchoMode ) {
00589 write( 2, Buf, len );
00590 return;
00591 }
00592
00593 char * LB = (char *)alloca( len + 1 );
00594 memcpy( LB, Buf, len );
00595 LB[len] = '\0';
00596
00597
00598 StderrBuffer += LB;
00599
00600 odebug << "Received " << len << " bytes on stderr" << oendl;
00601
00602 QStringList SL = QStringList::split( "\n", StderrBuffer, TRUE );
00603
00604 for( unsigned int i = 0; i < SL.count()-1; i ++ ) {
00605 Log(( "Stderr : \"%s\"\n", SL[i].latin1() ) );
00606 emit stderrLine( SL[i] );
00607 }
00608
00609
00610 StderrBuffer = SL[ SL.count()-1 ];
00611 }
00612
00613 void MyProcess::SLOT_ProcessExited( Opie::Core::OProcess * ) {
00614 emit processExited( this );
00615 }