common.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright, 2001 Nevrax Ltd.
00006  *
00007  * This file is part of NEVRAX NEL.
00008  * NEVRAX NEL is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2, or (at your option)
00011  * any later version.
00012 
00013  * NEVRAX NEL is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00016  * General Public License for more details.
00017 
00018  * You should have received a copy of the GNU General Public License
00019  * along with NEVRAX NEL; see the file COPYING. If not, write to the
00020  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00021  * MA 02111-1307, USA.
00022  */
00023 
00024 #include "stdmisc.h"
00025 
00026 #ifdef NL_OS_WINDOWS
00027 #   define NOMINMAX
00028 #   include <windows.h>
00029 #   include <io.h>
00030 #   include <tchar.h>
00031 #elif defined NL_OS_UNIX
00032 #   include <unistd.h>
00033 #   include <cstring>
00034 #   include <cerrno>
00035 #   include <csignal>
00036 #   include <pthread.h>
00037 #   include <sched.h>
00038 #endif
00039 
00040 #include "nel/misc/command.h"
00041 #include "nel/misc/path.h"
00042 
00043 using namespace std;
00044 
00045 #ifdef NL_OS_WINDOWS
00046 #   pragma message( " " )
00047 
00048 #   if FINAL_VERSION
00049 #       pragma message( "************************" )
00050 #       pragma message( "**** FINAL_VERSION *****" )
00051 #       pragma message( "************************" )
00052 #   else
00053 #       pragma message( "Not using FINAL_VERSION")
00054 #   endif // FINAL_VERSION
00055 
00056 #   ifdef ASSERT_THROW_EXCEPTION
00057 #       pragma message( "nlassert throws exceptions" )
00058 #   else
00059 #       pragma message( "nlassert does not throw exceptions" )
00060 #   endif // ASSERT_THROW_EXCEPTION
00061 
00062 #   ifdef _STLPORT_VERSION
00063 #       pragma message( "Using STLport" )
00064 #   else
00065 #       pragma message( "Using standard STL" )
00066 #   endif // _STLPORT_VERSION
00067 
00068 #   pragma message( " " )
00069 
00070 #   if (_MSC_VER >= 1200) && (_MSC_VER < 1400) && (WINVER < 0x0500)
00071 //Using VC7 and later lib, need this to compile on VC6
00072 extern "C" long _ftol2( double dblSource ) { return _ftol( dblSource ); }
00073 #   endif
00074 
00075 
00076 #endif // NL_OS_WINDOWS
00077 
00078 
00079 
00080 namespace   NLMISC
00081 {
00082 
00083 /*
00084  * Portable Sleep() function that suspends the execution of the calling thread for a number of milliseconds.
00085  * Note: the resolution of the timer is system-dependant and may be more than 1 millisecond.
00086  */
00087 void nlSleep( uint32 ms )
00088 {
00089 #ifdef NL_OS_WINDOWS
00090 
00091 #ifdef NL_DEBUG
00092     // a Sleep(0) "block" the other thread in DEBUG/_CONSOLE, so we clamp
00093     ms = max(ms, (uint32)1);
00094 #endif
00095 
00096     Sleep( ms );
00097 
00098 #elif defined NL_OS_UNIX
00099     //usleep( ms*1000 ); // resolution: 20 ms!
00100 
00101     timespec ts;
00102     ts.tv_sec = ms/1000;
00103     ts.tv_nsec = (ms%1000)*1000000;
00104     int res;
00105     do
00106     {
00107         res = nanosleep( &ts, &ts ); // resolution: 10 ms (with common scheduling policy)
00108     }
00109     while ( (res != 0) && (errno==EINTR) );
00110 #endif
00111 }
00112 
00113 
00114 /*
00115  * Returns Thread Id (note: on Linux, Process Id is the same as the Thread Id)
00116  */
00117 uint getThreadId()
00118 {
00119 #ifdef NL_OS_WINDOWS
00120     return GetCurrentThreadId();
00121 #elif defined NL_OS_UNIX
00122     return uint(pthread_self());
00123     // doesnt work on linux kernel 2.6  return getpid();
00124 #endif
00125 
00126 }
00127 
00128 
00129 /*
00130  * Returns a readable string from a vector of bytes. '\0' are replaced by ' '
00131  */
00132 string stringFromVector( const vector<uint8>& v, bool limited )
00133 {
00134     string s;
00135 
00136     if (!v.empty())
00137     {
00138         int size = v.size ();
00139         if (limited && size > 1000)
00140         {
00141             string middle = "...<buf too big,skip middle part>...";
00142             s.resize (1000 + middle.size());
00143             memcpy (&*s.begin(), &*v.begin(), 500);
00144             memcpy (&*s.begin()+500, &*middle.begin(), middle.size());
00145             memcpy (&*s.begin()+500+middle.size(), &*v.begin()+size-500, 500);
00146         }
00147         else
00148         {
00149             s.resize (size);
00150             memcpy( &*s.begin(), &*v.begin(), v.size() );
00151         }
00152 
00153         // Replace '\0' characters
00154         string::iterator is;
00155         for ( is=s.begin(); is!=s.end(); ++is )
00156         {
00157             // remplace non printable char and % with '?' chat
00158             if ( ! isprint((uint8)(*is)) || (*is) == '%')
00159             {
00160                 (*is) = '?';
00161             }
00162         }
00163     }
00164 /*
00165     if ( ! v.empty() )
00166     {
00167         // Copy contents
00168         s.resize( v.size() );
00169         memcpy( &*s.begin(), &*v.begin(), v.size() );
00170 
00171         // Replace '\0' characters
00172         string::iterator is;
00173         for ( is=s.begin(); is!=s.end(); ++is )
00174         {
00175             // remplace non printable char and % with '?' chat
00176             if ( ! isprint((*is)) || (*is) == '%')
00177             {
00178                 (*is) = '?';
00179             }
00180         }
00181     }
00182 */  return s;
00183 }
00184 
00185 
00186 sint smprintf( char *buffer, size_t count, const char *format, ... )
00187 {
00188     sint ret;
00189 
00190     va_list args;
00191     va_start( args, format );
00192     ret = vsnprintf( buffer, count, format, args );
00193     if ( ret == -1 )
00194     {
00195         buffer[count-1] = '\0';
00196     }
00197     va_end( args );
00198 
00199     return( ret );
00200 }
00201 
00202 
00203 sint64 atoiInt64 (const char *ident, sint64 base)
00204 {
00205     sint64 number = 0;
00206     bool neg = false;
00207 
00208     // NULL string
00209     nlassert (ident != NULL);
00210 
00211     // empty string
00212     if (*ident == '\0') goto end;
00213 
00214     // + sign
00215     if (*ident == '+') ident++;
00216 
00217     // - sign
00218     if (*ident == '-') { neg = true; ident++; }
00219 
00220     while (*ident != '\0')
00221     {
00222         if (isdigit((unsigned char)*ident))
00223         {
00224             number *= base;
00225             number += (*ident)-'0';
00226         }
00227         else if (base > 10 && islower((unsigned char)*ident))
00228         {
00229             number *= base;
00230             number += (*ident)-'a'+10;
00231         }
00232         else if (base > 10 && isupper((unsigned char)*ident))
00233         {
00234             number *= base;
00235             number += (*ident)-'A'+10;
00236         }
00237         else
00238         {
00239             goto end;
00240         }
00241         ident++;
00242     }
00243 end:
00244     if (neg) number = -number;
00245     return number;
00246 }
00247 
00248 void itoaInt64 (sint64 number, char *str, sint64 base)
00249 {
00250     str[0] = '\0';
00251     char b[256];
00252     if(!number)
00253     {
00254         str[0] = '0';
00255         str[1] = '\0';
00256         return;
00257     }
00258     memset(b,'\0',255);
00259     memset(b,'0',64);
00260     sint n;
00261     sint64 x = number;
00262     if (x < 0) x = -x;
00263     char baseTable[] = "0123456789abcdefghijklmnopqrstuvwyz";
00264     for(n = 0; n < 64; n ++)
00265     {
00266         sint num = (sint)(x % base);
00267         b[64 - n] = baseTable[num];
00268         if(!x)
00269         {
00270             int k;
00271             int j = 0;
00272 
00273             if (number < 0)
00274             {
00275                 str[j++] = '-';
00276             }
00277 
00278             for(k = 64 - n + 1; k <= 64; k++)
00279             {
00280                 str[j ++] = b[k];
00281             }
00282             str[j] = '\0';
00283             break;
00284         }
00285         x /= base;
00286     }
00287 }
00288 
00289 uint raiseToNextPowerOf2(uint v)
00290 {
00291     uint    res=1;
00292     while(res<v)
00293         res<<=1;
00294 
00295     return res;
00296 }
00297 
00298 uint    getPowerOf2(uint v)
00299 {
00300     uint    res=1;
00301     uint    ret=0;
00302     while(res<v)
00303     {
00304         ret++;
00305         res<<=1;
00306     }
00307 
00308     return ret;
00309 }
00310 
00311 bool isPowerOf2(sint32 v)
00312 {
00313     while(v)
00314     {
00315         if(v&1)
00316         {
00317             v>>=1;
00318             if(v)
00319                 return false;
00320         }
00321         else
00322             v>>=1;
00323     }
00324 
00325     return true;
00326 }
00327 
00328 string bytesToHumanReadable (const std::string &bytes)
00329 {
00330     return bytesToHumanReadable (atoiInt64(bytes.c_str()));
00331 }
00332 
00333 string bytesToHumanReadable (uint64 bytes)
00334 {
00335     static const char *divTable[]= { "B", "KB", "MB", "GB", "TB" };
00336     uint div = 0;
00337     uint64 res = bytes;
00338     uint64 newres = res;
00339     for(;;)
00340     {
00341         newres /= 1024;
00342         if(newres < 8 || div > 3)
00343             break;
00344         div++;
00345         res = newres;
00346     }
00347     return toString ("%"NL_I64"u%s", res, divTable[div]);
00348 }
00349 
00350 uint32 humanReadableToBytes (const string &str)
00351 {
00352     uint32 res;
00353 
00354     if(str.empty())
00355         return 0;
00356 
00357     // not a number
00358     if(str[0]<'0' || str[0]>'9')
00359         return 0;
00360 
00361     res = atoi (str.c_str());
00362 
00363     if(str[str.size()-1] == 'B')
00364     {
00365         if (str.size()<3)
00366             return res;
00367 
00368         // there s no break and it's **normal**
00369         switch (str[str.size()-2])
00370         {
00371         case 'G': res *= 1024;
00372         case 'M': res *= 1024;
00373         case 'K': res *= 1024;
00374         default: ;
00375         }
00376     }
00377 
00378     return res;
00379 }
00380 
00381 
00382 NLMISC_CATEGORISED_COMMAND(nel,btohr, "Convert a bytes number into an human readable number", "<int>")
00383 {
00384     if (args.size() != 1)
00385         return false;
00386 
00387     log.displayNL("%s -> %s", args[0].c_str(), bytesToHumanReadable(args[0]).c_str());
00388 
00389     return true;
00390 }
00391 
00392 
00393 NLMISC_CATEGORISED_COMMAND(nel,hrtob, "Convert a human readable number into a bytes number", "<hr>")
00394 {
00395     if (args.size() != 1)
00396         return false;
00397 
00398     log.displayNL("%s -> %u", args[0].c_str(), humanReadableToBytes(args[0]));
00399 
00400     return true;
00401 }
00402 
00403 
00404 string secondsToHumanReadable (uint32 time)
00405 {
00406     static const char *divTable[] = { "s", "mn", "h", "d" };
00407     static uint  divCoef[]  = { 60, 60, 24 };
00408     uint div = 0;
00409     uint32 res = time;
00410     uint32 newres = res;
00411     for(;;)
00412     {
00413         if(div > 2)
00414             break;
00415 
00416         newres /= divCoef[div];
00417 
00418         if(newres < 3)
00419             break;
00420 
00421         div++;
00422         res = newres;
00423     }
00424     return toString ("%u%s", res, divTable[div]);
00425 }
00426 
00427 uint32 fromHumanReadable (const std::string &str)
00428 {
00429     if (str.size() == 0)
00430         return 0;
00431 
00432     uint32 val;
00433     fromString(str, val);
00434 
00435     switch (str[str.size()-1])
00436     {
00437     case 's': return val;           // second
00438     case 'n': return val*60;        // minutes (mn)
00439     case 'h': return val*60*60;     // hour
00440     case 'd': return val*60*60*24;  // day
00441     case 'b':   // bytes
00442         switch (str[str.size()-2])
00443         {
00444         case 'k': return val*1024;
00445         case 'm': return val*1024*1024;
00446         case 'g': return val*1024*1024*1024;
00447         default : return val;
00448         }
00449     default: return val;
00450     }
00451     return 0;
00452 }
00453 
00454 
00455 NLMISC_CATEGORISED_COMMAND(nel,stohr, "Convert a second number into an human readable time", "<int>")
00456 {
00457     if (args.size() != 1)
00458         return false;
00459 
00460     uint32 seconds;
00461     fromString(args[0], seconds);
00462     log.displayNL("%s -> %s", args[0].c_str(), secondsToHumanReadable(seconds).c_str());
00463 
00464     return true;
00465 }
00466 
00467 
00468 std::string toLower(const std::string &str)
00469 {
00470     string res;
00471     res.reserve(str.size());
00472     for(uint i = 0; i < str.size(); i++)
00473     {
00474         if( (str[i] >= 'A') && (str[i] <= 'Z') )
00475             res += str[i] - 'A' + 'a';
00476         else
00477             res += str[i];
00478     }
00479     return res;
00480 }
00481 
00482 char toLower(const char ch)
00483 {
00484     if( (ch >= 'A') && (ch <= 'Z') )
00485     {
00486         return ch - 'A' + 'a';
00487     }
00488     else
00489     {
00490         return ch;
00491     }
00492 }
00493 
00494 void toLower(char *str)
00495 {
00496     if (str == 0)
00497         return;
00498 
00499     while(*str != '\0')
00500     {
00501         if( (*str >= 'A') && (*str <= 'Z') )
00502         {
00503             *str = *str - 'A' + 'a';
00504         }
00505         str++;
00506     }
00507 }
00508 
00509 std::string toUpper(const std::string &str)
00510 {
00511     string res;
00512     res.reserve(str.size());
00513     for(uint i = 0; i < str.size(); i++)
00514     {
00515         if( (str[i] >= 'a') && (str[i] <= 'z') )
00516             res += str[i] - 'a' + 'A';
00517         else
00518             res += str[i];
00519     }
00520     return res;
00521 }
00522 
00523 void        toUpper(char *str)
00524 {
00525     if (str == 0)
00526         return;
00527 
00528     while(*str != '\0')
00529     {
00530         if( (*str >= 'a') && (*str <= 'z') )
00531         {
00532             *str = *str - 'a' + 'A';
00533         }
00534         str++;
00535     }
00536 }
00537 
00538 
00539 //
00540 // Exceptions
00541 //
00542 
00543 Exception::Exception() : _Reason("Unknown Exception")
00544 {
00545 //  nlinfo("Exception will be launched: %s", _Reason.c_str());
00546 }
00547 
00548 Exception::Exception(const std::string &reason) : _Reason(reason)
00549 {
00550     nlinfo("Exception will be launched: %s", _Reason.c_str());
00551 }
00552 
00553 Exception::Exception(const char *format, ...)
00554 {
00555     NLMISC_CONVERT_VARGS (_Reason, format, NLMISC::MaxCStringSize);
00556     nlinfo("Exception will be launched: %s", _Reason.c_str());
00557 }
00558 
00559 const char  *Exception::what() const throw()
00560 {
00561     return _Reason.c_str();
00562 }
00563 
00564 bool killProgram(uint32 pid)
00565 {
00566 #ifdef NL_OS_UNIX
00567     int res = kill(pid, SIGKILL);
00568     if(res == -1)
00569     {
00570         char *err = strerror (errno);
00571         nlwarning("Failed to kill '%d' err %d: '%s'", pid, errno, err);
00572     }
00573     return res == 0;
00574 /*#elif defined(NL_OS_WINDOWS)
00575     // it doesn't work because pid != handle and i don't know how to kill a pid or know the real handle of another service (not -1)
00576     int res = TerminateProcess((HANDLE)pid, 888);
00577     LPVOID lpMsgBuf;
00578     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);
00579     nlwarning("Failed to kill '%d' err %d: '%s'", pid, GetLastError (), lpMsgBuf);
00580     LocalFree(lpMsgBuf);
00581     return res != 0;
00582 */
00583 #else
00584     nlwarning("kill not implemented on this OS");
00585     return false;
00586 #endif
00587 }
00588 
00589 bool abortProgram(uint32 pid)
00590 {
00591 #ifdef NL_OS_UNIX
00592     int res = kill(pid, SIGABRT);
00593     if(res == -1)
00594     {
00595         char *err = strerror (errno);
00596         nlwarning("Failed to abort '%d' err %d: '%s'", pid, errno, err);
00597     }
00598     return res == 0;
00599 #else
00600     nlwarning("abort not implemented on this OS");
00601     return false;
00602 #endif
00603 }
00604 
00605 bool launchProgram (const std::string &programName, const std::string &arguments)
00606 {
00607 
00608 #ifdef NL_OS_WINDOWS
00609     STARTUPINFOA         si;
00610     PROCESS_INFORMATION pi;
00611 
00612     memset(&si, 0, sizeof(si));
00613     memset(&pi, 0, sizeof(pi));
00614 
00615     si.cb = sizeof(si);
00616 
00617 /*  SECURITY_ATTRIBUTES sa;
00618     sa.nLength = sizeof (sa);
00619     sa.lpSecurityDescriptor = NULL;
00620     sa.bInheritHandle = FALSE;
00621 
00622     STARTUPINFO si;
00623     si.cb = sizeof (si);
00624     si.lpReserved = NULL;
00625     si.lpDesktop = NULL;
00626     si.lpTitle = NULL;
00627     si.dwFlags = STARTF_USESHOWWINDOW;
00628     si.cbReserved2 = 0;
00629     si.wShowWindow = SW_MINIMIZE;
00630     si.lpReserved2 = NULL;
00631 
00632     PROCESS_INFORMATION pi;
00633 */
00634 
00635     // Enable nlassert/nlstop to display the error reason & callstack
00636     const TCHAR *SE_TRANSLATOR_IN_MAIN_MODULE = _T("NEL_SE_TRANS");
00637     TCHAR envBuf [2];
00638     if ( GetEnvironmentVariable( SE_TRANSLATOR_IN_MAIN_MODULE, envBuf, 2 ) != 0)
00639     {
00640         SetEnvironmentVariable( SE_TRANSLATOR_IN_MAIN_MODULE, NULL );
00641     }
00642 
00643     string arg = " " + arguments;
00644     BOOL res = CreateProcessA(programName.c_str(), (char*)arg.c_str(), 0, 0, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW, 0, 0, &si, &pi);
00645 
00646     if (res)
00647     {
00648         //nldebug("LAUNCH: Successful launch '%s' with arg '%s'", programName.c_str(), arguments.c_str());
00649         CloseHandle( pi.hProcess );
00650         CloseHandle( pi.hThread );
00651         return true;
00652     }
00653     else
00654     {
00655         LPVOID lpMsgBuf;
00656         FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);
00657         nlwarning("LAUNCH: Failed launched '%s' with arg '%s' err %d: '%s'", programName.c_str(), arguments.c_str(), GetLastError (), lpMsgBuf);
00658         LocalFree(lpMsgBuf);
00659         CloseHandle( pi.hProcess );
00660         CloseHandle( pi.hThread );
00661     }
00662 
00663 #elif defined(NL_OS_UNIX)
00664 
00665     static bool firstLaunchProgram = true;
00666     if (firstLaunchProgram)
00667     {
00668         // The aim of this is to avoid defunct process.
00669         //
00670         // From "man signal":
00671         //------
00672         // According to POSIX (3.3.1.3) it is unspecified what happens when SIGCHLD is set to SIG_IGN.   Here
00673         // the  BSD  and  SYSV  behaviours  differ,  causing BSD software that sets the action for SIGCHLD to
00674         // SIG_IGN to fail on Linux.
00675         //------
00676         //
00677         // But it works fine on my GNU/Linux so I do this because it's easier :) and I don't know exactly
00678         // what to do to be portable.
00679         signal(SIGCHLD,SIG_IGN);
00680 
00681         firstLaunchProgram = false;
00682     }
00683 
00684     // convert one arg into several args
00685     vector<string> args;
00686     string::size_type pos1 = 0, pos2 = 0;
00687     do
00688     {
00689         pos1 = arguments.find_first_not_of (" ", pos2);
00690         if (pos1 == string::npos) break;
00691         pos2 = arguments.find_first_of (" ", pos1);
00692         args.push_back (arguments.substr (pos1, pos2-pos1));
00693     }
00694     while (pos2 != string::npos);
00695 
00696     // Store the size of each arg
00697     vector<char *> argv(args.size()+2);
00698     uint i = 0;
00699     argv[i] = (char *)programName.c_str();
00700     for (; i < args.size(); i++)
00701     {
00702         argv[i+1] = (char *) args[i].c_str();
00703     }
00704     argv[i+1] = NULL;
00705 
00706     int status = vfork ();
00711     if (status == -1)
00712     {
00713         char *err = strerror (errno);
00714         nlwarning("LAUNCH: Failed launched '%s' with arg '%s' err %d: '%s'", programName.c_str(), arguments.c_str(), errno, err);
00715     }
00716     else if (status == 0)
00717     {
00718 
00719         // Exec (the only allowed instruction after vfork)
00720         status = execvp(programName.c_str(), &argv.front());
00721 
00722         if (status == -1)
00723         {
00724             perror("Failed launched");
00725             _exit(EXIT_FAILURE);
00726         }
00727     }
00728     else
00729     {
00730         //nldebug("LAUNCH: Successful launch '%s' with arg '%s'", programName.c_str(), arguments.c_str());
00731         return true;
00732     }
00733 #else
00734     nlwarning ("LAUNCH: launchProgram() not implemented");
00735 #endif
00736 
00737     return false;
00738 
00739 }
00740 
00741 /*
00742  * Display the bits (with 0 and 1) composing a byte (from right to left)
00743  */
00744 void displayByteBits( uint8 b, uint nbits, sint beginpos, bool displayBegin, NLMISC::CLog *log )
00745 {
00746     string s1, s2;
00747     sint i;
00748     for ( i=nbits-1; i!=-1; --i )
00749     {
00750         s1 += ( (b >> i) & 1 ) ? '1' : '0';
00751     }
00752     log->displayRawNL( "%s", s1.c_str() );
00753     if ( displayBegin )
00754     {
00755         for ( i=nbits; i>beginpos+1; --i )
00756         {
00757             s2 += " ";
00758         }
00759         s2 += "^";
00760         log->displayRawNL( "%s beginpos=%u", s2.c_str(), beginpos );
00761     }
00762 }
00763 
00764 
00765 //#define displayDwordBits(a,b,c)
00766 
00767 /*
00768  * Display the bits (with 0 and 1) composing a number (uint32) (from right to left)
00769  */
00770 void displayDwordBits( uint32 b, uint nbits, sint beginpos, bool displayBegin, NLMISC::CLog *log )
00771 {
00772     string s1, s2;
00773     sint i;
00774     for ( i=nbits-1; i!=-1; --i )
00775     {
00776         s1 += ( (b >> i) & 1 ) ? '1' : '0';
00777     }
00778     log->displayRawNL( "%s", s1.c_str() );
00779     if ( displayBegin )
00780     {
00781         for ( i=nbits; i>beginpos+1; --i )
00782         {
00783             s2 += " ";
00784         }
00785         s2 += "^";
00786         log->displayRawNL( "%s beginpos=%u", s2.c_str(), beginpos );
00787     }
00788 }
00789 
00790 
00791 int nlfseek64( FILE *stream, sint64 offset, int origin )
00792 {
00793 #ifdef NL_OS_WINDOWS
00794 
00795     //
00796     fpos_t pos64 = 0;
00797     switch (origin)
00798     {
00799     case SEEK_CUR:
00800         if (fgetpos(stream, &pos64) != 0)
00801             return -1;
00802     case SEEK_END:
00803         pos64 = _filelengthi64(_fileno(stream));
00804         if (pos64 == -1L)
00805             return -1;
00806     };
00807 
00808     // Seek
00809     pos64 += offset;
00810 
00811     // Set the final position
00812     return fsetpos (stream, &pos64);
00813 
00814 #else // NL_OS_WINDOWS
00815 
00816     // This code doesn't work under windows : fseek() implementation uses a signed 32 bits offset. What ever we do, it can't seek more than 2 Go.
00817     // For the moment, i don't know if it works under linux for seek of more than 2 Go.
00818 
00819     nlassert ((offset < SINT64_CONSTANT(2147483647)) && (offset > SINT64_CONSTANT(-2147483648)));
00820 
00821     bool first = true;
00822     do
00823     {
00824         // Get the size of the next fseek
00825         sint nextSeek;
00826         if (offset > 0)
00827             nextSeek = (sint)std::min ((sint64)SINT64_CONSTANT(2147483647), offset);
00828         else
00829             nextSeek = (sint)std::max ((sint64)-SINT64_CONSTANT(2147483648), offset);
00830 
00831         // Make a seek
00832         int result = fseek ( stream, nextSeek, first?origin:SEEK_CUR );
00833         if (result != 0)
00834             return result;
00835 
00836         // Remaining
00837         offset -= nextSeek;
00838         first = false;
00839     }
00840     while (offset);
00841 
00842     return 0;
00843 
00844 #endif // NL_OS_WINDOWS
00845 }
00846 
00847 sint64 nlftell64(FILE *stream)
00848 {
00849 #ifdef NL_OS_WINDOWS
00850     fpos_t pos64 = 0;
00851     if (fgetpos(stream, &pos64) == 0)
00852     {
00853         return (sint64) pos64;
00854     }
00855     else return -1;
00856 #else
00857     nlerror("Not implemented");
00858     return -1;
00859 #endif
00860 }
00861 
00862 
00868 
00869 NLMISC_CATEGORISED_COMMAND(nel, sleep, "Freeze the service for N seconds (for debug purpose)", "<N>")
00870 {
00871     if(args.size() != 1) return false;
00872 
00873     sint32 n = atoi (args[0].c_str());
00874 
00875     log.displayNL ("Sleeping during %d seconds", n);
00876 
00877     nlSleep(n * 1000);
00878     return true;
00879 }
00880 
00881 NLMISC_CATEGORISED_COMMAND(nel, system, "Execute the command line using system() function call (wait until the end of the command)", "<commandline>")
00882 {
00883     if(args.size() != 1) return false;
00884 
00885     string cmd = args[0];
00886     log.displayNL ("Executing '%s'", cmd.c_str());
00887     system(cmd.c_str());
00888     log.displayNL ("End of Execution of '%s'", cmd.c_str());
00889     return true;
00890 }
00891 
00892 NLMISC_CATEGORISED_COMMAND(nel, launchProgram, "Execute the command line using launcProgram() function call (launch in background task without waiting the end of the execution)", "<programName> <arguments>")
00893 {
00894     if(args.size() != 2) return false;
00895 
00896     string cmd = args[0];
00897     string arg = args[1];
00898     log.displayNL ("Executing '%s' with argument '%s'", cmd.c_str(), arg.c_str());
00899     launchProgram(cmd, arg);
00900     log.displayNL ("End of Execution of '%s' with argument '%s'", cmd.c_str(), arg.c_str());
00901     return true;
00902 }
00903 
00904 NLMISC_CATEGORISED_COMMAND(nel, killProgram, "kill a program given the pid", "<pid>")
00905 {
00906     if(args.size() != 1) return false;
00907     uint32 pid;
00908     fromString(args[0], pid);
00909     killProgram(pid);
00910     return true;
00911 }
00912 
00913 #ifdef NL_OS_WINDOWS
00914 LONG GetRegKey(HKEY key, LPCSTR subkey, LPSTR retdata)
00915 {
00916     HKEY hkey;
00917     LONG retval = RegOpenKeyExA(key, subkey, 0, KEY_QUERY_VALUE, &hkey);
00918 
00919     if (retval == ERROR_SUCCESS)
00920     {
00921         long datasize = MAX_PATH;
00922         char data[MAX_PATH];
00923         RegQueryValueA(hkey, NULL, data, &datasize);
00924         lstrcpyA(retdata,data);
00925         RegCloseKey(hkey);
00926     }
00927 
00928     return retval;
00929 }
00930 #endif // NL_OS_WINDOWS
00931 
00932 bool openURL (const char *url)
00933 {
00934 #ifdef NL_OS_WINDOWS
00935     char key[1024];
00936     if (GetRegKey(HKEY_CLASSES_ROOT, ".html", key) == ERROR_SUCCESS)
00937     {
00938         lstrcatA(key, "\\shell\\open\\command");
00939 
00940         if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS)
00941         {
00942             char *pos;
00943             pos = strstr(key, "\"%1\"");
00944             if (pos == NULL) {                     // No quotes found
00945                 pos = strstr(key, "%1");       // Check for %1, without quotes
00946                 if (pos == NULL)                   // No parameter at all...
00947                     pos = key+lstrlenA(key)-1;
00948                 else
00949                     *pos = '\0';                   // Remove the parameter
00950             }
00951             else
00952                 *pos = '\0';                       // Remove the parameter
00953 
00954             lstrcatA(pos, " ");
00955             lstrcatA(pos, url);
00956             int res = WinExec(key,SW_SHOWDEFAULT);
00957             return (res>31);
00958         }
00959     }
00960 #elif defined(NL_OS_MAC)
00961     return launchProgram("open", url);
00962 #elif defined(NL_OS_UNIX)
00963     return launchProgram("/etc/alternatives/x-www-browser", url);
00964 #else
00965     nlwarning("openURL() is not implemented for this OS");
00966 #endif // NL_OS_WINDOWS
00967     return false;
00968 }
00969 
00970 bool openDoc (const char *document)
00971 {
00972 #ifdef NL_OS_WINDOWS
00973     string ext = CFile::getExtension (document);
00974     char key[MAX_PATH + MAX_PATH];
00975 
00976     // First try ShellExecute()
00977     HINSTANCE result = ShellExecuteA(NULL, "open", document, NULL,NULL, SW_SHOWDEFAULT);
00978 
00979     // If it failed, get the .htm regkey and lookup the program
00980     if ((UINT)result <= HINSTANCE_ERROR)
00981     {
00982         if (GetRegKey(HKEY_CLASSES_ROOT, ext.c_str(), key) == ERROR_SUCCESS)
00983         {
00984             lstrcatA(key, "\\shell\\open\\command");
00985 
00986             if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS)
00987             {
00988                 char *pos;
00989                 pos = strstr(key, "\"%1\"");
00990                 if (pos == NULL) {                     // No quotes found
00991                     pos = strstr(key, "%1");       // Check for %1, without quotes
00992                     if (pos == NULL)                   // No parameter at all...
00993                         pos = key+lstrlenA(key)-1;
00994                     else
00995                         *pos = '\0';                   // Remove the parameter
00996                 }
00997                 else
00998                     *pos = '\0';                       // Remove the parameter
00999 
01000                 lstrcatA(pos, " ");
01001                 lstrcatA(pos, document);
01002                 int res = WinExec(key,SW_SHOWDEFAULT);
01003                 return (res>31);
01004             }
01005         }
01006     }
01007     else
01008         return true;
01009 #endif // NL_OS_WINDOWS
01010     return false;
01011 }
01012 
01013 } // NLMISC

Generated on Thu Jan 7 08:26:33 2010 for NeL by  doxygen 1.6.1