src/jdk.jpackager/share/native/library/common/LinuxPlatform.cpp
branchJDK-8200758-branch
changeset 57017 1b08af362a30
parent 56995 3d5b13207b70
equal deleted inserted replaced
57016:f63f13da91c0 57017:1b08af362a30
       
     1 /*
       
     2  * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 #include "Platform.h"
       
    27 
       
    28 #ifdef LINUX
       
    29 
       
    30 #include "JavaVirtualMachine.h"
       
    31 #include "LinuxPlatform.h"
       
    32 #include "PlatformString.h"
       
    33 #include "IniFile.h"
       
    34 #include "Helpers.h"
       
    35 
       
    36 #include <stdlib.h>
       
    37 #include <pwd.h>
       
    38 #include <sys/file.h>
       
    39 #include <sys/stat.h>
       
    40 #include <errno.h>
       
    41 #include <unistd.h>
       
    42 #include <sys/types.h>
       
    43 #include <limits.h>
       
    44 
       
    45 #define LINUX_JPACKAGER_TMP_DIR "/.java/jpackager/tmp"
       
    46 
       
    47 
       
    48 TString GetEnv(const TString &name) {
       
    49     TString result;
       
    50 
       
    51     char *value = ::getenv((TCHAR*)name.c_str());
       
    52 
       
    53     if (value != NULL) {
       
    54        result = value;
       
    55     }
       
    56 
       
    57     return result;
       
    58 }
       
    59 
       
    60 LinuxPlatform::LinuxPlatform(void) : Platform(),
       
    61         GenericPlatform(), PosixPlatform() {
       
    62     FMainThread = pthread_self();
       
    63 }
       
    64 
       
    65 LinuxPlatform::~LinuxPlatform(void) {
       
    66 }
       
    67 
       
    68 void LinuxPlatform::ShowMessage(TString title, TString description) {
       
    69     printf("%s %s\n", PlatformString(title).toPlatformString(),
       
    70             PlatformString(description).toPlatformString());
       
    71     fflush(stdout);
       
    72 }
       
    73 
       
    74 void LinuxPlatform::ShowMessage(TString description) {
       
    75     TString appname = GetModuleFileName();
       
    76     appname = FilePath::ExtractFileName(appname);
       
    77     ShowMessage(PlatformString(appname).toPlatformString(),
       
    78             PlatformString(description).toPlatformString());
       
    79 }
       
    80 
       
    81 TCHAR* LinuxPlatform::ConvertStringToFileSystemString(TCHAR* Source,
       
    82          bool &release) {
       
    83     // Not Implemented.
       
    84     return NULL;
       
    85 }
       
    86 
       
    87 TCHAR* LinuxPlatform::ConvertFileSystemStringToString(TCHAR* Source,
       
    88          bool &release) {
       
    89     // Not Implemented.
       
    90     return NULL;
       
    91 }
       
    92 
       
    93 TString LinuxPlatform::GetModuleFileName() {
       
    94     ssize_t len = 0;
       
    95     TString result;
       
    96     DynamicBuffer<TCHAR> buffer(MAX_PATH);
       
    97     if (buffer.GetData() == NULL) {
       
    98         return result;
       
    99     }
       
   100 
       
   101     if ((len = readlink("/proc/self/exe", buffer.GetData(),
       
   102             MAX_PATH - 1)) != -1) {
       
   103         buffer[len] = '\0';
       
   104         result = buffer.GetData();
       
   105     }
       
   106 
       
   107     return result;
       
   108 }
       
   109 
       
   110 void LinuxPlatform::SetCurrentDirectory(TString Value) {
       
   111     chdir(PlatformString(Value).toPlatformString());
       
   112 }
       
   113 
       
   114 TString LinuxPlatform::GetPackageRootDirectory() {
       
   115     TString filename = GetModuleFileName();
       
   116     return FilePath::ExtractFilePath(filename);
       
   117 }
       
   118 
       
   119 TString LinuxPlatform::GetAppDataDirectory() {
       
   120     TString result;
       
   121     TString home = GetEnv(_T("HOME"));
       
   122 
       
   123     if (home.empty() == false) {
       
   124         result += FilePath::IncludeTrailingSeparator(home) + _T(".local");
       
   125     }
       
   126 
       
   127     return result;
       
   128 }
       
   129 
       
   130 ISectionalPropertyContainer* LinuxPlatform::GetConfigFile(TString FileName) {
       
   131     IniFile *result = new IniFile();
       
   132     if (result == NULL) {
       
   133         return NULL;
       
   134     }
       
   135 
       
   136     if (result->LoadFromFile(FileName) == false) {
       
   137         // New property file format was not found,
       
   138         // attempt to load old property file format.
       
   139         Helpers::LoadOldConfigFile(FileName, result);
       
   140     }
       
   141 
       
   142     return result;
       
   143 }
       
   144 
       
   145 TString LinuxPlatform::GetBundledJVMLibraryFileName(TString RuntimePath) {
       
   146     TString result = FilePath::IncludeTrailingSeparator(RuntimePath) +
       
   147         "lib/libjli.so";
       
   148 
       
   149     if (FilePath::FileExists(result) == false) {
       
   150         result = FilePath::IncludeTrailingSeparator(RuntimePath) +
       
   151             "lib/jli/libjli.so";
       
   152         if (FilePath::FileExists(result) == false) {
       
   153             printf("Cannot find libjli.so!");
       
   154         }
       
   155     }
       
   156 
       
   157     return result;
       
   158 }
       
   159 
       
   160 bool LinuxPlatform::IsMainThread() {
       
   161     bool result = (FMainThread == pthread_self());
       
   162     return result;
       
   163 }
       
   164 
       
   165 TString LinuxPlatform::getTmpDirString() {
       
   166     return TString(LINUX_JPACKAGER_TMP_DIR);
       
   167 }
       
   168 
       
   169 void LinuxPlatform::reactivateAnotherInstance() {
       
   170     if (singleInstanceProcessId == 0) {
       
   171         printf("Unable to reactivate another instance, PID is undefined");
       
   172         return;
       
   173     }
       
   174 
       
   175     const ProcessReactivator reactivator(singleInstanceProcessId);
       
   176 }
       
   177 
       
   178 TPlatformNumber LinuxPlatform::GetMemorySize() {
       
   179     long pages = sysconf(_SC_PHYS_PAGES);
       
   180     long page_size = sysconf(_SC_PAGE_SIZE);
       
   181     TPlatformNumber result = pages * page_size;
       
   182     result = result / 1048576; // Convert from bytes to megabytes.
       
   183     return result;
       
   184 }
       
   185 
       
   186 #ifdef DEBUG
       
   187 bool LinuxPlatform::IsNativeDebuggerPresent() {
       
   188     // gdb opens file descriptors stdin=3, stdout=4, stderr=5 whereas
       
   189     // a typical prog uses only stdin=0, stdout=1, stderr=2.
       
   190     bool result = false;
       
   191     FILE *fd = fopen("/tmp", "r");
       
   192 
       
   193     if (fileno(fd) > 5) {
       
   194         result = true;
       
   195     }
       
   196 
       
   197     fclose(fd);
       
   198     return result;
       
   199 }
       
   200 
       
   201 int LinuxPlatform::GetProcessID() {
       
   202     int pid = getpid();
       
   203     return pid;
       
   204 }
       
   205 #endif //DEBUG
       
   206 
       
   207 //----------------------------------------------------------------------------
       
   208 
       
   209 #ifndef __UNIX_JPACKAGER_PLATFORM__
       
   210 #define __UNIX_JPACKAGER_PLATFORM__
       
   211 
       
   212 /** Provide an abstraction for difference in the platform APIs,
       
   213      e.g. string manipulation functions, etc. */
       
   214 #include <stdio.h>
       
   215 #include <string.h>
       
   216 #include <strings.h>
       
   217 #include <sys/stat.h>
       
   218 
       
   219 #define TCHAR char
       
   220 
       
   221 #define _T(x) x
       
   222 
       
   223 #define JPACKAGER_MULTIBYTE_SNPRINTF snprintf
       
   224 
       
   225 #define JPACKAGER_SNPRINTF(buffer, sizeOfBuffer, count, format, ...) \
       
   226     snprintf((buffer), (count), (format), __VA_ARGS__)
       
   227 
       
   228 #define JPACKAGER_PRINTF(format, ...) \
       
   229     printf((format), ##__VA_ARGS__)
       
   230 
       
   231 #define JPACKAGER_FPRINTF(dest, format, ...) \
       
   232     fprintf((dest), (format), __VA_ARGS__)
       
   233 
       
   234 #define JPACKAGER_SSCANF(buf, format, ...) \
       
   235     sscanf((buf), (format), __VA_ARGS__)
       
   236 
       
   237 #define JPACKAGER_STRDUP(strSource) \
       
   238     strdup((strSource))
       
   239 
       
   240 //return "error code" (like on Windows)
       
   241 static int JPACKAGER_STRNCPY(char *strDest, size_t numberOfElements,
       
   242         const char *strSource, size_t count) {
       
   243     char *s = strncpy(strDest, strSource, count);
       
   244     // Duplicate behavior of the Windows' _tcsncpy_s() by adding a NULL
       
   245     // terminator at the end of the string.
       
   246     if (count < numberOfElements) {
       
   247         s[count] = '\0';
       
   248     } else {
       
   249         s[numberOfElements - 1] = '\0';
       
   250     }
       
   251     return (s == strDest) ? 0 : 1;
       
   252 }
       
   253 
       
   254 #define JPACKAGER_STRICMP(x, y) \
       
   255     strcasecmp((x), (y))
       
   256 
       
   257 #define JPACKAGER_STRNICMP(x, y, cnt) \
       
   258     strncasecmp((x), (y), (cnt))
       
   259 
       
   260 #define JPACKAGER_STRNCMP(x, y, cnt) \
       
   261     strncmp((x), (y), (cnt))
       
   262 
       
   263 #define JPACKAGER_STRLEN(x) \
       
   264     strlen((x))
       
   265 
       
   266 #define JPACKAGER_STRSTR(x, y) \
       
   267     strstr((x), (y))
       
   268 
       
   269 #define JPACKAGER_STRCHR(x, y) \
       
   270     strchr((x), (y))
       
   271 
       
   272 #define JPACKAGER_STRRCHR(x, y) \
       
   273     strrchr((x), (y))
       
   274 
       
   275 #define JPACKAGER_STRPBRK(x, y) \
       
   276     strpbrk((x), (y))
       
   277 
       
   278 #define JPACKAGER_GETENV(x) \
       
   279     getenv((x))
       
   280 
       
   281 #define JPACKAGER_PUTENV(x) \
       
   282     putenv((x))
       
   283 
       
   284 #define JPACKAGER_STRCMP(x, y) \
       
   285     strcmp((x), (y))
       
   286 
       
   287 #define JPACKAGER_STRCPY(x, y) \
       
   288     strcpy((x), (y))
       
   289 
       
   290 #define JPACKAGER_STRCAT(x, y) \
       
   291     strcat((x), (y))
       
   292 
       
   293 #define JPACKAGER_ATOI(x) \
       
   294     atoi((x))
       
   295 
       
   296 #define JPACKAGER_FOPEN(x, y) \
       
   297     fopen((x), (y))
       
   298 
       
   299 #define JPACKAGER_FGETS(x, y, z) \
       
   300     fgets((x), (y), (z))
       
   301 
       
   302 #define JPACKAGER_REMOVE(x) \
       
   303     remove((x))
       
   304 
       
   305 #define JPACKAGER_SPAWNV(mode, cmd, args) \
       
   306     spawnv((mode), (cmd), (args))
       
   307 
       
   308 #define JPACKAGER_ISDIGIT(ch) isdigit(ch)
       
   309 
       
   310 // for non-unicode, just return the input string for
       
   311 // the following 2 conversions
       
   312 #define JPACKAGER_NEW_MULTIBYTE(message) message
       
   313 
       
   314 #define JPACKAGER_NEW_FROM_MULTIBYTE(message) message
       
   315 
       
   316 // for non-unicode, no-op for the relase operation
       
   317 // since there is no memory allocated for the
       
   318 // string conversions
       
   319 #define JPACKAGER_RELEASE_MULTIBYTE(tmpMBCS)
       
   320 
       
   321 #define JPACKAGER_RELEASE_FROM_MULTIBYTE(tmpMBCS)
       
   322 
       
   323 // The size will be used for converting from 1 byte to 1 byte encoding.
       
   324 // Ensure have space for zero-terminator.
       
   325 #define JPACKAGER_GET_SIZE_FOR_ENCODING(message, theLength) (theLength + 1)
       
   326 
       
   327 #endif
       
   328 #define xmlTagType    0
       
   329 #define xmlPCDataType 1
       
   330 
       
   331 typedef struct _xmlNode XMLNode;
       
   332 typedef struct _xmlAttribute XMLAttribute;
       
   333 
       
   334 struct _xmlNode {
       
   335     int           _type;        // Type of node: tag, pcdata, cdate
       
   336     TCHAR*         _name;       // Contents of node
       
   337     XMLNode*      _next;        // Next node at same level
       
   338     XMLNode*      _sub;         // First sub-node
       
   339     XMLAttribute* _attributes;  // List of attributes
       
   340 };
       
   341 
       
   342 struct _xmlAttribute {
       
   343     TCHAR* _name;               // Name of attribute
       
   344     TCHAR* _value;              // Value of attribute
       
   345     XMLAttribute* _next;        // Next attribute for this tag
       
   346 };
       
   347 
       
   348 // Public interface
       
   349 static void     RemoveNonAsciiUTF8FromBuffer(char *buf);
       
   350 XMLNode* ParseXMLDocument    (TCHAR* buf);
       
   351 void     FreeXMLDocument     (XMLNode* root);
       
   352 
       
   353 // Utility methods for parsing document
       
   354 XMLNode* FindXMLChild        (XMLNode* root,      const TCHAR* name);
       
   355 TCHAR*    FindXMLAttribute    (XMLAttribute* attr, const TCHAR* name);
       
   356 
       
   357 // Debugging
       
   358 void PrintXMLDocument(XMLNode* node, int indt);
       
   359 
       
   360 
       
   361 #include <sys/types.h>
       
   362 #include <sys/stat.h>
       
   363 #include <setjmp.h>
       
   364 #include <stdlib.h>
       
   365 #include <wctype.h>
       
   366 
       
   367 
       
   368 #define JWS_assert(s, msg)      \
       
   369     if (!(s)) { Abort(msg); }
       
   370 
       
   371 
       
   372 // Internal declarations
       
   373 static XMLNode*      ParseXMLElement(void);
       
   374 static XMLAttribute* ParseXMLAttribute(void);
       
   375 static TCHAR*         SkipWhiteSpace(TCHAR *p);
       
   376 static TCHAR*         SkipXMLName(TCHAR *p);
       
   377 static TCHAR*         SkipXMLComment(TCHAR *p);
       
   378 static TCHAR*         SkipXMLDocType(TCHAR *p);
       
   379 static TCHAR*         SkipXMLProlog(TCHAR *p);
       
   380 static TCHAR*         SkipPCData(TCHAR *p);
       
   381 static int           IsPCData(TCHAR *p);
       
   382 static void          ConvertBuiltInEntities(TCHAR* p);
       
   383 static void          SetToken(int type, TCHAR* start, TCHAR* end);
       
   384 static void          GetNextToken(void);
       
   385 static XMLNode*      CreateXMLNode(int type, TCHAR* name);
       
   386 static XMLAttribute* CreateXMLAttribute(TCHAR *name, TCHAR* value);
       
   387 static XMLNode*      ParseXMLElement(void);
       
   388 static XMLAttribute* ParseXMLAttribute(void);
       
   389 static void          FreeXMLAttribute(XMLAttribute* attr);
       
   390 static void          PrintXMLAttributes(XMLAttribute* attr);
       
   391 static void          indent(int indt);
       
   392 
       
   393 static jmp_buf       jmpbuf;
       
   394 static XMLNode*      root_node = NULL;
       
   395 
       
   396 /** definition of error codes for setjmp/longjmp,
       
   397  *  that can be handled in ParseXMLDocument()
       
   398  */
       
   399 #define JMP_NO_ERROR     0
       
   400 #define JMP_OUT_OF_RANGE 1
       
   401 
       
   402 #define NEXT_CHAR(p) { \
       
   403     if (*p != 0) { \
       
   404         p++; \
       
   405     } else { \
       
   406         longjmp(jmpbuf, JMP_OUT_OF_RANGE); \
       
   407     } \
       
   408 }
       
   409 #define NEXT_CHAR_OR_BREAK(p) { \
       
   410     if (*p != 0) { \
       
   411         p++; \
       
   412     } else { \
       
   413         break; \
       
   414     } \
       
   415 }
       
   416 #define NEXT_CHAR_OR_RETURN(p) { \
       
   417     if (*p != 0) { \
       
   418         p++; \
       
   419     } else { \
       
   420         return; \
       
   421     } \
       
   422 }
       
   423 #define SKIP_CHARS(p,n) { \
       
   424     int i; \
       
   425     for (i = 0; i < (n); i++) { \
       
   426         if (*p != 0) { \
       
   427             p++; \
       
   428         } else { \
       
   429            longjmp(jmpbuf, JMP_OUT_OF_RANGE); \
       
   430         } \
       
   431     } \
       
   432 }
       
   433 #define SKIP_CHARS_OR_BREAK(p,n) { \
       
   434     int i; \
       
   435     for (i = 0; i < (n); i++) { \
       
   436         if (*p != 0) { \
       
   437             p++; \
       
   438         } else { \
       
   439             break; \
       
   440         } \
       
   441     } \
       
   442     if (i < (n)) { \
       
   443         break; \
       
   444     } \
       
   445 }
       
   446 
       
   447 /** Iterates through the null-terminated buffer (i.e., C string) and
       
   448  *  replaces all UTF-8 encoded character >255 with 255
       
   449  *
       
   450  *  UTF-8 encoding:
       
   451  *
       
   452  *   Range A:  0x0000 - 0x007F
       
   453  *                               0 | bits 0 - 7
       
   454  *   Range B : 0x0080 - 0x07FF  :
       
   455  *                               110 | bits 6 - 10
       
   456  *                               10  | bits 0 - 5
       
   457  *   Range C : 0x0800 - 0xFFFF  :
       
   458  *                               1110 | bits 12-15
       
   459  *                               10   | bits  6-11
       
   460  *                               10   | bits  0-5
       
   461  */
       
   462 static void RemoveNonAsciiUTF8FromBuffer(char *buf) {
       
   463     char* p;
       
   464     char* q;
       
   465     char c;
       
   466     p = q = buf;
       
   467     // We are not using NEXT_CHAR() to check if *q is NULL, as q is output
       
   468     // location and offset for q is smaller than for p.
       
   469     while(*p != '\0') {
       
   470         c = *p;
       
   471         if ( (c & 0x80) == 0) {
       
   472             /* Range A */
       
   473             *q++ = *p;
       
   474             NEXT_CHAR(p);
       
   475         } else if ((c & 0xE0) == 0xC0){
       
   476             /* Range B */
       
   477             *q++ = (char)0xFF;
       
   478             NEXT_CHAR(p);
       
   479             NEXT_CHAR_OR_BREAK(p);
       
   480         } else {
       
   481             /* Range C */
       
   482             *q++ = (char)0xFF;
       
   483             NEXT_CHAR(p);
       
   484             SKIP_CHARS_OR_BREAK(p, 2);
       
   485         }
       
   486     }
       
   487     /* Null terminate string */
       
   488     *q = '\0';
       
   489 }
       
   490 
       
   491 static TCHAR* SkipWhiteSpace(TCHAR *p) {
       
   492     if (p != NULL) {
       
   493         while(iswspace(*p))
       
   494             NEXT_CHAR_OR_BREAK(p);
       
   495     }
       
   496     return p;
       
   497 }
       
   498 
       
   499 static TCHAR* SkipXMLName(TCHAR *p) {
       
   500     TCHAR c = *p;
       
   501     /* Check if start of token */
       
   502     if ( ('a' <= c && c <= 'z') ||
       
   503          ('A' <= c && c <= 'Z') ||
       
   504          c == '_' || c == ':') {
       
   505 
       
   506         while( ('a' <= c && c <= 'z') ||
       
   507                ('A' <= c && c <= 'Z') ||
       
   508                ('0' <= c && c <= '9') ||
       
   509                c == '_' || c == ':' || c == '.' || c == '-' ) {
       
   510             NEXT_CHAR(p);
       
   511             c = *p;
       
   512             if (c == '\0') break;
       
   513         }
       
   514     }
       
   515     return p;
       
   516 }
       
   517 
       
   518 static TCHAR* SkipXMLComment(TCHAR *p) {
       
   519     if (p != NULL) {
       
   520         if (JPACKAGER_STRNCMP(p, _T("<!--"), 4) == 0) {
       
   521             SKIP_CHARS(p, 4);
       
   522             do {
       
   523                 if (JPACKAGER_STRNCMP(p, _T("-->"), 3) == 0) {
       
   524                     SKIP_CHARS(p, 3);
       
   525                     return p;
       
   526                 }
       
   527                 NEXT_CHAR(p);
       
   528             } while(*p != '\0');
       
   529         }
       
   530     }
       
   531     return p;
       
   532 }
       
   533 
       
   534 static TCHAR* SkipXMLDocType(TCHAR *p) {
       
   535     if (p != NULL) {
       
   536         if (JPACKAGER_STRNCMP(p, _T("<!"), 2) == 0) {
       
   537             SKIP_CHARS(p, 2);
       
   538             while (*p != '\0') {
       
   539                 if (*p == '>') {
       
   540                     NEXT_CHAR(p);
       
   541                     return p;
       
   542                 }
       
   543                 NEXT_CHAR(p);
       
   544             }
       
   545         }
       
   546     }
       
   547     return p;
       
   548 }
       
   549 
       
   550 static TCHAR* SkipXMLProlog(TCHAR *p) {
       
   551     if (p != NULL) {
       
   552         if (JPACKAGER_STRNCMP(p, _T("<?"), 2) == 0) {
       
   553             SKIP_CHARS(p, 2);
       
   554             do {
       
   555                 if (JPACKAGER_STRNCMP(p, _T("?>"), 2) == 0) {
       
   556                     SKIP_CHARS(p, 2);
       
   557                     return p;
       
   558                 }
       
   559                 NEXT_CHAR(p);
       
   560             } while(*p != '\0');
       
   561         }
       
   562     }
       
   563     return p;
       
   564 }
       
   565 
       
   566 /* Search for the built-in XML entities:
       
   567  * &amp; (&), &lt; (<), &gt; (>), &apos; ('), and &quote(")
       
   568  * and convert them to a real TCHARacter
       
   569  */
       
   570 static void ConvertBuiltInEntities(TCHAR* p) {
       
   571     TCHAR* q;
       
   572     q = p;
       
   573     // We are not using NEXT_CHAR() to check if *q is NULL,
       
   574     // as q is output location and offset for q is smaller than for p.
       
   575     while(*p) {
       
   576         if (IsPCData(p)) {
       
   577             /* dont convert &xxx values within PData */
       
   578             TCHAR *end;
       
   579             end = SkipPCData(p);
       
   580             while(p < end) {
       
   581                 *q++ = *p;
       
   582                 NEXT_CHAR(p);
       
   583             }
       
   584         } else {
       
   585             if (JPACKAGER_STRNCMP(p, _T("&amp;"), 5) == 0) {
       
   586                 *q++ = '&';
       
   587                 SKIP_CHARS(p, 5);
       
   588             } else if (JPACKAGER_STRNCMP(p, _T("&lt;"), 4)  == 0) {
       
   589                 *q = '<';
       
   590                 SKIP_CHARS(p, 4);
       
   591             } else if (JPACKAGER_STRNCMP(p, _T("&gt;"), 4)  == 0) {
       
   592                 *q = '>';
       
   593                 SKIP_CHARS(p, 4);
       
   594             } else if (JPACKAGER_STRNCMP(p, _T("&apos;"), 6)  == 0) {
       
   595                 *q = '\'';
       
   596                 SKIP_CHARS(p, 6);
       
   597             } else if (JPACKAGER_STRNCMP(p, _T("&quote;"), 7)  == 0) {
       
   598                 *q = '\"';
       
   599               SKIP_CHARS(p, 7);
       
   600             } else {
       
   601               *q++ = *p;
       
   602               NEXT_CHAR(p);
       
   603             }
       
   604         }
       
   605     }
       
   606     *q = '\0';
       
   607 }
       
   608 
       
   609 /* ------------------------------------------------------------- */
       
   610 /* XML tokenizer */
       
   611 
       
   612 #define TOKEN_UNKNOWN             0
       
   613 #define TOKEN_BEGIN_TAG           1  /* <tag */
       
   614 #define TOKEN_END_TAG             2  /* </tag */
       
   615 #define TOKEN_CLOSE_BRACKET       3  /* >  */
       
   616 #define TOKEN_EMPTY_CLOSE_BRACKET 4  /* /> */
       
   617 #define TOKEN_PCDATA              5  /* pcdata */
       
   618 #define TOKEN_CDATA               6  /* cdata */
       
   619 #define TOKEN_EOF                 7
       
   620 
       
   621 static TCHAR* CurPos       = NULL;
       
   622 static TCHAR* CurTokenName        = NULL;
       
   623 static int   CurTokenType;
       
   624 static int   MaxTokenSize = -1;
       
   625 
       
   626 /* Copy token from buffer to Token variable */
       
   627 static void SetToken(int type, TCHAR* start, TCHAR* end) {
       
   628     int len = end - start;
       
   629     if (len > MaxTokenSize) {
       
   630         if (CurTokenName != NULL) free(CurTokenName);
       
   631         CurTokenName = (TCHAR *)malloc((len + 1) * sizeof(TCHAR));
       
   632         if (CurTokenName == NULL ) {
       
   633             return;
       
   634         }
       
   635         MaxTokenSize = len;
       
   636     }
       
   637 
       
   638     CurTokenType = type;
       
   639     JPACKAGER_STRNCPY(CurTokenName, len + 1, start, len);
       
   640     CurTokenName[len] = '\0';
       
   641 }
       
   642 
       
   643 /* Skip XML comments, doctypes, and prolog tags */
       
   644 static TCHAR* SkipFilling(void) {
       
   645     TCHAR *q = CurPos;
       
   646 
       
   647     /* Skip white space and comment sections */
       
   648     do {
       
   649         q = CurPos;
       
   650         CurPos = SkipWhiteSpace(CurPos);
       
   651         CurPos = SkipXMLComment(CurPos); /* Must be called befor DocTypes */
       
   652         CurPos = SkipXMLDocType(CurPos); /* <! ... > directives */
       
   653         CurPos = SkipXMLProlog(CurPos);   /* <? ... ?> directives */
       
   654     } while(CurPos != q);
       
   655 
       
   656     return CurPos;
       
   657 }
       
   658 
       
   659 /* Parses next token and initializes the global token variables above
       
   660    The tokennizer automatically skips comments (<!-- comment -->) and
       
   661    <! ... > directives.
       
   662 */
       
   663 static void GetNextToken(void) {
       
   664     TCHAR *p, *q;
       
   665 
       
   666     /* Skip white space and comment sections */
       
   667     p = SkipFilling();
       
   668 
       
   669     if (p == NULL || *p == '\0') {
       
   670         CurTokenType = TOKEN_EOF;
       
   671         return;
       
   672     } else if (p[0] == '<' && p[1] == '/') {
       
   673         /* TOKEN_END_TAG */
       
   674         q = SkipXMLName(p + 2);
       
   675         SetToken(TOKEN_END_TAG, p + 2, q);
       
   676         p = q;
       
   677     } else  if (*p == '<') {
       
   678         /* TOKEN_BEGIN_TAG */
       
   679         q = SkipXMLName(p + 1);
       
   680         SetToken(TOKEN_BEGIN_TAG, p + 1, q);
       
   681         p = q;
       
   682     } else if (p[0] == '>') {
       
   683         CurTokenType = TOKEN_CLOSE_BRACKET;
       
   684         NEXT_CHAR(p);
       
   685     } else if (p[0] == '/' && p[1] == '>') {
       
   686         CurTokenType = TOKEN_EMPTY_CLOSE_BRACKET;
       
   687         SKIP_CHARS(p, 2);
       
   688     } else {
       
   689         /* Search for end of data */
       
   690         q = p + 1;
       
   691         while(*q && *q != '<') {
       
   692             if (IsPCData(q)) {
       
   693                 q = SkipPCData(q);
       
   694             } else {
       
   695                 NEXT_CHAR(q);
       
   696             }
       
   697         }
       
   698         SetToken(TOKEN_PCDATA, p, q);
       
   699         /* Convert all entities inside token */
       
   700         ConvertBuiltInEntities(CurTokenName);
       
   701         p = q;
       
   702     }
       
   703     /* Advance pointer to beginning of next token */
       
   704     CurPos = p;
       
   705 }
       
   706 
       
   707 static XMLNode* CreateXMLNode(int type, TCHAR* name) {
       
   708     XMLNode* node;
       
   709     node  = (XMLNode*)malloc(sizeof(XMLNode));
       
   710     if (node == NULL) {
       
   711         return NULL;
       
   712     }
       
   713     node->_type = type;
       
   714     node->_name = name;
       
   715     node->_next = NULL;
       
   716     node->_sub  = NULL;
       
   717     node->_attributes = NULL;
       
   718     return node;
       
   719 }
       
   720 
       
   721 static XMLAttribute* CreateXMLAttribute(TCHAR *name, TCHAR* value) {
       
   722     XMLAttribute* attr;
       
   723     attr = (XMLAttribute*)malloc(sizeof(XMLAttribute));
       
   724     if (attr == NULL) {
       
   725         return NULL;
       
   726     }
       
   727     attr->_name = name;
       
   728     attr->_value = value;
       
   729     attr->_next =  NULL;
       
   730     return attr;
       
   731 }
       
   732 
       
   733 XMLNode* ParseXMLDocument(TCHAR* buf) {
       
   734     XMLNode* root;
       
   735     int err_code = setjmp(jmpbuf);
       
   736     switch (err_code)
       
   737     {
       
   738     case JMP_NO_ERROR:
       
   739 #ifndef _UNICODE
       
   740         /* Remove UTF-8 encoding from buffer */
       
   741         RemoveNonAsciiUTF8FromBuffer(buf);
       
   742 #endif
       
   743 
       
   744         /* Get first Token */
       
   745         CurPos = buf;
       
   746         GetNextToken();
       
   747 
       
   748         /* Parse document*/
       
   749         root =  ParseXMLElement();
       
   750     break;
       
   751     case JMP_OUT_OF_RANGE:
       
   752         /* cleanup: */
       
   753         if (root_node != NULL) {
       
   754             FreeXMLDocument(root_node);
       
   755             root_node = NULL;
       
   756         }
       
   757         if (CurTokenName != NULL) free(CurTokenName);
       
   758         fprintf(stderr,"Error during parsing jnlp file...\n");
       
   759         exit(-1);
       
   760     break;
       
   761     default:
       
   762         root = NULL;
       
   763     break;
       
   764     }
       
   765 
       
   766     return root;
       
   767 }
       
   768 
       
   769 static XMLNode* ParseXMLElement(void) {
       
   770     XMLNode*  node     = NULL;
       
   771     XMLNode*  subnode  = NULL;
       
   772     XMLNode*  nextnode = NULL;
       
   773     XMLAttribute* attr = NULL;
       
   774 
       
   775     if (CurTokenType == TOKEN_BEGIN_TAG) {
       
   776 
       
   777         /* Create node for new element tag */
       
   778         node = CreateXMLNode(xmlTagType, JPACKAGER_STRDUP(CurTokenName));
       
   779         /* We need to save root node pointer to be able to cleanup
       
   780            if an error happens during parsing */
       
   781         if(!root_node) {
       
   782             root_node = node;
       
   783         }
       
   784         /* Parse attributes. This section eats a all input until
       
   785            EOF, a > or a /> */
       
   786         attr = ParseXMLAttribute();
       
   787         while(attr != NULL) {
       
   788           attr->_next = node->_attributes;
       
   789           node->_attributes = attr;
       
   790           attr = ParseXMLAttribute();
       
   791         }
       
   792 
       
   793         /* This will eihter be a TOKEN_EOF, TOKEN_CLOSE_BRACKET, or a
       
   794          * TOKEN_EMPTY_CLOSE_BRACKET */
       
   795         GetNextToken();
       
   796 
       
   797         /* Skip until '>', '/>' or EOF. This should really be an error, */
       
   798         /* but we are loose */
       
   799 //        if(CurTokenType == TOKEN_EMPTY_CLOSE_BRACKET ||
       
   800 //               CurTokenType == TOKEN_CLOSE_BRACKET ||
       
   801 //               CurTokenType  == TOKEN_EOF) {
       
   802 //            println("XML Parsing error: wrong kind of token found");
       
   803 //            return NULL;
       
   804 //        }
       
   805 
       
   806         if (CurTokenType == TOKEN_EMPTY_CLOSE_BRACKET) {
       
   807             GetNextToken();
       
   808             /* We are done with the sublevel - fall through to continue */
       
   809             /* parsing tags at the same level */
       
   810         } else if (CurTokenType == TOKEN_CLOSE_BRACKET) {
       
   811             GetNextToken();
       
   812 
       
   813             /* Parse until end tag if found */
       
   814             node->_sub  = ParseXMLElement();
       
   815 
       
   816             if (CurTokenType == TOKEN_END_TAG) {
       
   817                 /* Find closing bracket '>' for end tag */
       
   818                 do {
       
   819                    GetNextToken();
       
   820                 } while(CurTokenType != TOKEN_EOF &&
       
   821                         CurTokenType != TOKEN_CLOSE_BRACKET);
       
   822                 GetNextToken();
       
   823             }
       
   824         }
       
   825 
       
   826         /* Continue parsing rest on same level */
       
   827         if (CurTokenType != TOKEN_EOF) {
       
   828             /* Parse rest of stream at same level */
       
   829             node->_next = ParseXMLElement();
       
   830         }
       
   831         return node;
       
   832 
       
   833     } else if (CurTokenType == TOKEN_PCDATA) {
       
   834         /* Create node for pcdata */
       
   835         node = CreateXMLNode(xmlPCDataType, JPACKAGER_STRDUP(CurTokenName));
       
   836         /* We need to save root node pointer to be able to cleanup
       
   837            if an error happens during parsing */
       
   838         if(!root_node) {
       
   839             root_node = node;
       
   840         }
       
   841         GetNextToken();
       
   842         return node;
       
   843     }
       
   844 
       
   845     /* Something went wrong. */
       
   846     return NULL;
       
   847 }
       
   848 
       
   849 /* Parses an XML attribute. */
       
   850 static XMLAttribute* ParseXMLAttribute(void) {
       
   851     TCHAR* q = NULL;
       
   852     TCHAR* name = NULL;
       
   853     TCHAR* PrevPos = NULL;
       
   854 
       
   855     do
       
   856     {
       
   857         /* We need to check this condition to avoid endless loop
       
   858            in case if an error happend during parsing. */
       
   859         if (PrevPos == CurPos) {
       
   860             if (name != NULL) {
       
   861                 free(name);
       
   862                 name = NULL;
       
   863             }
       
   864 
       
   865             return NULL;
       
   866         }
       
   867 
       
   868         PrevPos = CurPos;
       
   869 
       
   870         /* Skip whitespace etc. */
       
   871         SkipFilling();
       
   872 
       
   873         /* Check if we are done witht this attribute section */
       
   874         if (CurPos[0] == '\0' ||
       
   875             CurPos[0] == '>' ||
       
   876             (CurPos[0] == '/' && CurPos[1] == '>')) {
       
   877 
       
   878             if (name != NULL) {
       
   879                 free(name);
       
   880                 name = NULL;
       
   881             }
       
   882 
       
   883             return NULL;
       
   884         }
       
   885 
       
   886         /* Find end of name */
       
   887         q = CurPos;
       
   888         while(*q && !iswspace(*q) && *q !='=') NEXT_CHAR(q);
       
   889 
       
   890         SetToken(TOKEN_UNKNOWN, CurPos, q);
       
   891         if (name) {
       
   892             free(name);
       
   893             name = NULL;
       
   894         }
       
   895         name = JPACKAGER_STRDUP(CurTokenName);
       
   896 
       
   897         /* Skip any whitespace */
       
   898         CurPos = q;
       
   899         CurPos = SkipFilling();
       
   900 
       
   901         /* Next TCHARacter must be '=' for a valid attribute.
       
   902            If it is not, this is really an error.
       
   903            We ignore this, and just try to parse an attribute
       
   904            out of the rest of the string.
       
   905         */
       
   906     } while(*CurPos != '=');
       
   907 
       
   908     NEXT_CHAR(CurPos);
       
   909     CurPos = SkipWhiteSpace(CurPos);
       
   910     /* Parse CDATA part of attribute */
       
   911     if ((*CurPos == '\"') || (*CurPos == '\'')) {
       
   912         TCHAR quoteChar = *CurPos;
       
   913         q = ++CurPos;
       
   914         while(*q != '\0' && *q != quoteChar) NEXT_CHAR(q);
       
   915         SetToken(TOKEN_CDATA, CurPos, q);
       
   916         CurPos = q + 1;
       
   917     } else {
       
   918         q = CurPos;
       
   919         while(*q != '\0' && !iswspace(*q)) NEXT_CHAR(q);
       
   920         SetToken(TOKEN_CDATA, CurPos, q);
       
   921         CurPos = q;
       
   922     }
       
   923 
       
   924     //Note: no need to free name and CurTokenName duplicate; they're assigned
       
   925     // to an XMLAttribute structure in CreateXMLAttribute
       
   926 
       
   927     return CreateXMLAttribute(name, JPACKAGER_STRDUP(CurTokenName));
       
   928 }
       
   929 
       
   930 void FreeXMLDocument(XMLNode* root) {
       
   931     if (root == NULL) return;
       
   932     FreeXMLDocument(root->_sub);
       
   933     FreeXMLDocument(root->_next);
       
   934     FreeXMLAttribute(root->_attributes);
       
   935     free(root->_name);
       
   936     free(root);
       
   937 }
       
   938 
       
   939 static void FreeXMLAttribute(XMLAttribute* attr) {
       
   940     if (attr == NULL) return;
       
   941     free(attr->_name);
       
   942     free(attr->_value);
       
   943     FreeXMLAttribute(attr->_next);
       
   944     free(attr);
       
   945 }
       
   946 
       
   947 /* Find element at current level with a given name */
       
   948 XMLNode* FindXMLChild(XMLNode* root, const TCHAR* name) {
       
   949     if (root == NULL) return NULL;
       
   950 
       
   951     if (root->_type == xmlTagType && JPACKAGER_STRCMP(root->_name, name) == 0) {
       
   952         return root;
       
   953     }
       
   954 
       
   955     return FindXMLChild(root->_next, name);
       
   956 }
       
   957 
       
   958 /* Search for an attribute with the given name and returns the contents. Returns NULL if
       
   959  * attribute is not found
       
   960  */
       
   961 TCHAR* FindXMLAttribute(XMLAttribute* attr, const TCHAR* name) {
       
   962     if (attr == NULL) return NULL;
       
   963     if (JPACKAGER_STRCMP(attr->_name, name) == 0) return attr->_value;
       
   964     return FindXMLAttribute(attr->_next, name);
       
   965 }
       
   966 
       
   967 
       
   968 void PrintXMLDocument(XMLNode* node, int indt) {
       
   969     if (node == NULL) return;
       
   970 
       
   971     if (node->_type == xmlTagType) {
       
   972         JPACKAGER_PRINTF(_T("\n"));
       
   973         indent(indt);
       
   974         JPACKAGER_PRINTF(_T("<%s"), node->_name);
       
   975         PrintXMLAttributes(node->_attributes);
       
   976         if (node->_sub == NULL) {
       
   977             JPACKAGER_PRINTF(_T("/>\n"));
       
   978         } else {
       
   979             JPACKAGER_PRINTF(_T(">"));
       
   980             PrintXMLDocument(node->_sub, indt + 1);
       
   981             indent(indt);
       
   982             JPACKAGER_PRINTF(_T("</%s>"), node->_name);
       
   983         }
       
   984     } else {
       
   985         JPACKAGER_PRINTF(_T("%s"), node->_name);
       
   986     }
       
   987     PrintXMLDocument(node->_next, indt);
       
   988 }
       
   989 
       
   990 static void PrintXMLAttributes(XMLAttribute* attr) {
       
   991     if (attr == NULL) return;
       
   992 
       
   993     JPACKAGER_PRINTF(_T(" %s=\"%s\""), attr->_name, attr->_value);
       
   994     PrintXMLAttributes(attr->_next);
       
   995 }
       
   996 
       
   997 static void indent(int indt) {
       
   998     int i;
       
   999     for(i = 0; i < indt; i++) {
       
  1000         JPACKAGER_PRINTF(_T("  "));
       
  1001     }
       
  1002 }
       
  1003 
       
  1004 const TCHAR *CDStart = _T("<![CDATA[");
       
  1005 const TCHAR *CDEnd = _T("]]>");
       
  1006 
       
  1007 
       
  1008 static TCHAR* SkipPCData(TCHAR *p) {
       
  1009     TCHAR *end = JPACKAGER_STRSTR(p, CDEnd);
       
  1010     if (end != NULL) {
       
  1011         return end+sizeof(CDEnd);
       
  1012     }
       
  1013     return (++p);
       
  1014 }
       
  1015 
       
  1016 static int IsPCData(TCHAR *p) {
       
  1017     const int size = sizeof(CDStart);
       
  1018     return (JPACKAGER_STRNCMP(CDStart, p, size) == 0);
       
  1019 }
       
  1020 
       
  1021 namespace {
       
  1022     template<class funcType>
       
  1023     class DllFunction {
       
  1024         const Library& lib;
       
  1025         funcType funcPtr;
       
  1026         std::string theName;
       
  1027 
       
  1028     public:
       
  1029         DllFunction(const Library& library,
       
  1030                 const std::string &funcName): lib(library) {
       
  1031             funcPtr = reinterpret_cast<funcType>(lib.GetProcAddress(funcName));
       
  1032             if (!funcPtr) {
       
  1033                 throw std::runtime_error("Failed to load function \""
       
  1034                         + funcName + "\" from \""
       
  1035                         + library.GetName() + "\" library");
       
  1036             }
       
  1037         }
       
  1038 
       
  1039         operator funcType() const {
       
  1040             return funcPtr;
       
  1041         }
       
  1042     };
       
  1043 } // namespace
       
  1044 
       
  1045 extern "C" {
       
  1046 typedef Status (*XInitThreadsFuncPtr)();
       
  1047 typedef Display* (*XOpenDisplayFuncPtr)(char *display_name);
       
  1048 
       
  1049 typedef Atom (*XInternAtomFuncPtr)(
       
  1050         Display *display, char *atom_name, Bool only_if_exists);
       
  1051 
       
  1052 typedef Window (*XDefaultRootWindowFuncPtr)(Display *display);
       
  1053 
       
  1054 typedef int (*XCloseDisplayFuncPtr)(Display *display);
       
  1055 }
       
  1056 
       
  1057 ProcessReactivator::ProcessReactivator(pid_t pid): _pid(pid) {
       
  1058     const std::string libname = "libX11.so";
       
  1059     if(!libX11.Load(libname)) {
       
  1060         throw std::runtime_error("Failed to load \"" + libname + "\" library");
       
  1061     }
       
  1062 
       
  1063     DllFunction<XInitThreadsFuncPtr> XInitThreadsFunc(libX11, "XInitThreads");
       
  1064 
       
  1065     XInitThreadsFunc();
       
  1066 
       
  1067     DllFunction<XOpenDisplayFuncPtr> XOpenDisplayFunc(libX11, "XOpenDisplay");
       
  1068 
       
  1069     _display = XOpenDisplayFunc(NULL);
       
  1070 
       
  1071     DllFunction<XInternAtomFuncPtr> XInternAtomFunc(libX11, "XInternAtom");
       
  1072 
       
  1073     _atomPid = XInternAtomFunc(_display, (char*)"_NET_WM_PID", True);
       
  1074 
       
  1075     if (_atomPid == None) {
       
  1076         return;
       
  1077     }
       
  1078 
       
  1079     DllFunction<XDefaultRootWindowFuncPtr> XDefaultRootWindowFunc(libX11,
       
  1080             "XDefaultRootWindow");
       
  1081 
       
  1082     searchWindowHelper(XDefaultRootWindowFunc(_display));
       
  1083 
       
  1084     reactivateProcess();
       
  1085 
       
  1086     DllFunction<XCloseDisplayFuncPtr> XCloseDisplayFunc(libX11,
       
  1087             "XCloseDisplay");
       
  1088 
       
  1089     XCloseDisplayFunc(_display);
       
  1090 }
       
  1091 
       
  1092 extern "C" {
       
  1093 typedef int (*XGetWindowPropertyFuncPtr)(
       
  1094         Display *display, Window w, Atom property, long long_offset,
       
  1095         long long_length, Bool d, Atom req_type, Atom *actual_type_return,
       
  1096         int *actual_format_return, unsigned long *nitems_return,
       
  1097         unsigned long *bytes_after_return, unsigned char **prop_return);
       
  1098 
       
  1099 typedef Status (*XQueryTreeFuncPtr)(
       
  1100         Display *display, Window w, Window *root_return, Window *parent_return,
       
  1101          Window **children_return, unsigned int *nchildren_return);
       
  1102 
       
  1103 typedef int (*XFreeFuncPtr)(void *data);
       
  1104 }
       
  1105 
       
  1106 void ProcessReactivator::searchWindowHelper(Window w) {
       
  1107 
       
  1108     DllFunction<XGetWindowPropertyFuncPtr> XGetWindowPropertyFunc(libX11,
       
  1109             "XGetWindowProperty");
       
  1110 
       
  1111     DllFunction<XFreeFuncPtr> XFreeFunc(libX11, "XFree");
       
  1112 
       
  1113     Atom type;
       
  1114     int format;
       
  1115     unsigned long  num, bytesAfter;
       
  1116     unsigned char* propPid = 0;
       
  1117     if (Success == XGetWindowPropertyFunc(_display, w, _atomPid, 0, 1,
       
  1118             False, XA_CARDINAL, &type, &format, &num, &bytesAfter, &propPid)) {
       
  1119         if (propPid != 0) {
       
  1120             if (_pid == *((pid_t *)propPid)) {
       
  1121                 _result.push_back(w);
       
  1122             }
       
  1123             XFreeFunc(propPid);
       
  1124         }
       
  1125     }
       
  1126 
       
  1127     DllFunction<XQueryTreeFuncPtr> XQueryTreeFunc(libX11, "XQueryTree");
       
  1128 
       
  1129     Window root, parent;
       
  1130     Window* child;
       
  1131     unsigned int numChildren;
       
  1132     if (0 != XQueryTreeFunc(_display, w, &root,
       
  1133             &parent, &child, &numChildren)) {
       
  1134         for (unsigned int i = 0; i < numChildren; i++) {
       
  1135             searchWindowHelper(child[i]);
       
  1136         }
       
  1137     }
       
  1138 }
       
  1139 
       
  1140 
       
  1141 extern "C" {
       
  1142 typedef Status (*XGetWindowAttributesFuncPtr)(Display *display, Window w,
       
  1143         XWindowAttributes *window_attributes_return);
       
  1144 
       
  1145 typedef Status (*XSendEventFuncPtr)(Display *display, Window w, Bool propagate,
       
  1146         long event_mask, XEvent *event_send);
       
  1147 
       
  1148 typedef int (*XRaiseWindowFuncPtr)(Display *display, Window w);
       
  1149 }
       
  1150 
       
  1151 void ProcessReactivator::reactivateProcess() {
       
  1152 
       
  1153     DllFunction<XGetWindowAttributesFuncPtr> XGetWindowAttributesFunc(libX11,
       
  1154             "XGetWindowAttributes");
       
  1155 
       
  1156     DllFunction<XSendEventFuncPtr> XSendEventFunc(libX11, "XSendEvent");
       
  1157 
       
  1158     DllFunction<XRaiseWindowFuncPtr> XRaiseWindowFunc(libX11, "XRaiseWindow");
       
  1159 
       
  1160     DllFunction<XInternAtomFuncPtr> XInternAtomFunc(libX11, "XInternAtom");
       
  1161 
       
  1162     for (std::list<Window>::const_iterator it = _result.begin();
       
  1163             it != _result.end(); it++) {
       
  1164         // try sending an event to activate window,
       
  1165         // after that we can try to raise it.
       
  1166         XEvent xev;
       
  1167         Atom atom = XInternAtomFunc (
       
  1168                 _display, (char*)"_NET_ACTIVE_WINDOW", False);
       
  1169         xev.xclient.type = ClientMessage;
       
  1170         xev.xclient.serial = 0;
       
  1171         xev.xclient.send_event = True;
       
  1172         xev.xclient.display = _display;
       
  1173         xev.xclient.window = *it;
       
  1174         xev.xclient.message_type = atom;
       
  1175         xev.xclient.format = 32;
       
  1176         xev.xclient.data.l[0] = 2;
       
  1177         xev.xclient.data.l[1] = 0;
       
  1178         xev.xclient.data.l[2] = 0;
       
  1179         xev.xclient.data.l[3] = 0;
       
  1180         xev.xclient.data.l[4] = 0;
       
  1181         XWindowAttributes attr;
       
  1182         XGetWindowAttributesFunc(_display, *it, &attr);
       
  1183         XSendEventFunc(_display, attr.root, False,
       
  1184             SubstructureRedirectMask | SubstructureNotifyMask, &xev);
       
  1185         XRaiseWindowFunc(_display, *it);
       
  1186     }
       
  1187 }
       
  1188 
       
  1189 
       
  1190 #endif // LINUX