< prev index next >
src/jdk.jpackage/linux/native/libapplauncher/LinuxPlatform.cpp
Print this page
@@ -23,50 +23,68 @@
* questions.
*/
#include "Platform.h"
-#ifdef LINUX
-
#include "JavaVirtualMachine.h"
#include "LinuxPlatform.h"
#include "PlatformString.h"
#include "IniFile.h"
#include "Helpers.h"
+#include "FilePath.h"
#include <stdlib.h>
#include <pwd.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <limits.h>
+#include <signal.h>
#define LINUX_JPACKAGE_TMP_DIR "/.java/jpackage/tmp"
-
TString GetEnv(const TString &name) {
TString result;
- char *value = ::getenv((TCHAR*)name.c_str());
+ char *value = ::getenv((TCHAR*) name.c_str());
if (value != NULL) {
result = value;
}
return result;
}
LinuxPlatform::LinuxPlatform(void) : Platform(),
- GenericPlatform(), PosixPlatform() {
+PosixPlatform() {
FMainThread = pthread_self();
}
LinuxPlatform::~LinuxPlatform(void) {
}
+TString LinuxPlatform::GetPackageAppDirectory() {
+ return FilePath::IncludeTrailingSeparator(
+ GetPackageRootDirectory()) + _T("app");
+}
+
+TString LinuxPlatform::GetAppName() {
+ TString result = GetModuleFileName();
+ result = FilePath::ExtractFileName(result);
+ return result;
+}
+
+TString LinuxPlatform::GetPackageLauncherDirectory() {
+ return GetPackageRootDirectory();
+}
+
+TString LinuxPlatform::GetPackageRuntimeBinDirectory() {
+ return FilePath::IncludeTrailingSeparator(GetPackageRootDirectory()) + _T("runtime/bin");
+}
+
void LinuxPlatform::ShowMessage(TString title, TString description) {
printf("%s %s\n", PlatformString(title).toPlatformString(),
PlatformString(description).toPlatformString());
fflush(stdout);
}
@@ -172,30 +190,94 @@
TPlatformNumber result = pages * page_size;
result = result / 1048576; // Convert from bytes to megabytes.
return result;
}
-#ifdef DEBUG
-bool LinuxPlatform::IsNativeDebuggerPresent() {
- // gdb opens file descriptors stdin=3, stdout=4, stderr=5 whereas
- // a typical prog uses only stdin=0, stdout=1, stderr=2.
+void PosixProcess::Cleanup() {
+ if (FOutputHandle != 0) {
+ close(FOutputHandle);
+ FOutputHandle = 0;
+ }
+
+ if (FInputHandle != 0) {
+ close(FInputHandle);
+ FInputHandle = 0;
+ }
+}
+
+#define PIPE_READ 0
+#define PIPE_WRITE 1
+
+bool PosixProcess::Execute(const TString Application,
+ const std::vector<TString> Arguments, bool AWait) {
bool result = false;
- FILE *fd = fopen("/tmp", "r");
- if (fileno(fd) > 5) {
+ if (FRunning == false) {
+ FRunning = true;
+
+ int handles[2];
+
+ if (pipe(handles) == -1) {
+ return false;
+ }
+
+ struct sigaction sa;
+ sa.sa_handler = SIG_IGN;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ FChildPID = fork();
+
+ // PID returned by vfork is 0 for the child process and the
+ // PID of the child process for the parent.
+ if (FChildPID == -1) {
+ // Error
+ TString message = PlatformString::Format(
+ _T("Error: Unable to create process %s"),
+ Application.data());
+ throw Exception(message);
+ } else if (FChildPID == 0) {
+ Cleanup();
+ TString command = Application;
+
+ for (std::vector<TString>::const_iterator iterator =
+ Arguments.begin(); iterator != Arguments.end();
+ iterator++) {
+ command += TString(_T(" ")) + *iterator;
+ }
+#ifdef DEBUG
+ printf("%s\n", command.data());
+#endif // DEBUG
+
+ dup2(handles[PIPE_READ], STDIN_FILENO);
+ dup2(handles[PIPE_WRITE], STDOUT_FILENO);
+
+ close(handles[PIPE_READ]);
+ close(handles[PIPE_WRITE]);
+
+ execl("/bin/sh", "sh", "-c", command.data(), (char *) 0);
+
+ _exit(127);
+ } else {
+ FOutputHandle = handles[PIPE_READ];
+ FInputHandle = handles[PIPE_WRITE];
+
+ if (AWait == true) {
+ ReadOutput();
+ Wait();
+ Cleanup();
+ FRunning = false;
result = true;
+ } else {
+ result = true;
+ }
+ }
}
- fclose(fd);
return result;
}
-int LinuxPlatform::GetProcessID() {
- int pid = getpid();
- return pid;
-}
-#endif //DEBUG
//----------------------------------------------------------------------------
#ifndef __UNIX_JPACKAGE_PLATFORM__
#define __UNIX_JPACKAGE_PLATFORM__
@@ -227,10 +309,11 @@
#define JPACKAGE_STRDUP(strSource) \
strdup((strSource))
//return "error code" (like on Windows)
+
static int JPACKAGE_STRNCPY(char *strDest, size_t numberOfElements,
const char *strSource, size_t count) {
char *s = strncpy(strDest, strSource, count);
// Duplicate behavior of the Windows' _tcsncpy_s() by adding a NULL
// terminator at the end of the string.
@@ -336,28 +419,26 @@
XMLAttribute* _next; // Next attribute for this tag
};
// Public interface
static void RemoveNonAsciiUTF8FromBuffer(char *buf);
-XMLNode* ParseXMLDocument (TCHAR* buf);
-void FreeXMLDocument (XMLNode* root);
+XMLNode* ParseXMLDocument(TCHAR* buf);
+void FreeXMLDocument(XMLNode* root);
// Utility methods for parsing document
-XMLNode* FindXMLChild (XMLNode* root, const TCHAR* name);
-TCHAR* FindXMLAttribute (XMLAttribute* attr, const TCHAR* name);
+XMLNode* FindXMLChild(XMLNode* root, const TCHAR* name);
+TCHAR* FindXMLAttribute(XMLAttribute* attr, const TCHAR* name);
// Debugging
void PrintXMLDocument(XMLNode* node, int indt);
-
#include <sys/types.h>
#include <sys/stat.h>
#include <setjmp.h>
#include <stdlib.h>
#include <wctype.h>
-
#define JWS_assert(s, msg) \
if (!(s)) { Abort(msg); }
// Internal declarations
@@ -455,51 +536,51 @@
char* q;
char c;
p = q = buf;
// We are not using NEXT_CHAR() to check if *q is NULL, as q is output
// location and offset for q is smaller than for p.
- while(*p != '\0') {
+ while (*p != '\0') {
c = *p;
- if ( (c & 0x80) == 0) {
+ if ((c & 0x80) == 0) {
/* Range A */
*q++ = *p;
NEXT_CHAR(p);
- } else if ((c & 0xE0) == 0xC0){
+ } else if ((c & 0xE0) == 0xC0) {
/* Range B */
- *q++ = (char)0xFF;
+ *q++ = (char) 0xFF;
NEXT_CHAR(p);
NEXT_CHAR_OR_BREAK(p);
} else {
/* Range C */
- *q++ = (char)0xFF;
+ *q++ = (char) 0xFF;
NEXT_CHAR(p);
SKIP_CHARS_OR_BREAK(p, 2);
}
}
/* Null terminate string */
*q = '\0';
}
static TCHAR* SkipWhiteSpace(TCHAR *p) {
if (p != NULL) {
- while(iswspace(*p))
+ while (iswspace(*p))
NEXT_CHAR_OR_BREAK(p);
}
return p;
}
static TCHAR* SkipXMLName(TCHAR *p) {
TCHAR c = *p;
/* Check if start of token */
- if ( ('a' <= c && c <= 'z') ||
+ if (('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z') ||
c == '_' || c == ':') {
- while( ('a' <= c && c <= 'z') ||
+ while (('a' <= c && c <= 'z') ||
('A' <= c && c <= 'Z') ||
('0' <= c && c <= '9') ||
- c == '_' || c == ':' || c == '.' || c == '-' ) {
+ c == '_' || c == ':' || c == '.' || c == '-') {
NEXT_CHAR(p);
c = *p;
if (c == '\0') break;
}
}
@@ -514,11 +595,11 @@
if (JPACKAGE_STRNCMP(p, _T("-->"), 3) == 0) {
SKIP_CHARS(p, 3);
return p;
}
NEXT_CHAR(p);
- } while(*p != '\0');
+ } while (*p != '\0');
}
}
return p;
}
@@ -546,11 +627,11 @@
if (JPACKAGE_STRNCMP(p, _T("?>"), 2) == 0) {
SKIP_CHARS(p, 2);
return p;
}
NEXT_CHAR(p);
- } while(*p != '\0');
+ } while (*p != '\0');
}
}
return p;
}
@@ -561,16 +642,16 @@
static void ConvertBuiltInEntities(TCHAR* p) {
TCHAR* q;
q = p;
// We are not using NEXT_CHAR() to check if *q is NULL,
// as q is output location and offset for q is smaller than for p.
- while(*p) {
+ while (*p) {
if (IsPCData(p)) {
/* dont convert &xxx values within PData */
TCHAR *end;
end = SkipPCData(p);
- while(p < end) {
+ while (p < end) {
*q++ = *p;
NEXT_CHAR(p);
}
} else {
if (JPACKAGE_STRNCMP(p, _T("&"), 5) == 0) {
@@ -617,12 +698,12 @@
/* Copy token from buffer to Token variable */
static void SetToken(int type, TCHAR* start, TCHAR* end) {
int len = end - start;
if (len > MaxTokenSize) {
if (CurTokenName != NULL) free(CurTokenName);
- CurTokenName = (TCHAR *)malloc((len + 1) * sizeof(TCHAR));
- if (CurTokenName == NULL ) {
+ CurTokenName = (TCHAR *) malloc((len + 1) * sizeof (TCHAR));
+ if (CurTokenName == NULL) {
return;
}
MaxTokenSize = len;
}
@@ -640,19 +721,19 @@
q = CurPos;
CurPos = SkipWhiteSpace(CurPos);
CurPos = SkipXMLComment(CurPos); /* Must be called befor DocTypes */
CurPos = SkipXMLDocType(CurPos); /* <! ... > directives */
CurPos = SkipXMLProlog(CurPos); /* <? ... ?> directives */
- } while(CurPos != q);
+ } while (CurPos != q);
return CurPos;
}
/* Parses next token and initializes the global token variables above
The tokennizer automatically skips comments (<!-- comment -->) and
<! ... > directives.
-*/
+ */
static void GetNextToken(void) {
TCHAR *p, *q;
/* Skip white space and comment sections */
p = SkipFilling();
@@ -677,11 +758,11 @@
CurTokenType = TOKEN_EMPTY_CLOSE_BRACKET;
SKIP_CHARS(p, 2);
} else {
/* Search for end of data */
q = p + 1;
- while(*q && *q != '<') {
+ while (*q && *q != '<') {
if (IsPCData(q)) {
q = SkipPCData(q);
} else {
NEXT_CHAR(q);
}
@@ -695,11 +776,11 @@
CurPos = p;
}
static XMLNode* CreateXMLNode(int type, TCHAR* name) {
XMLNode* node;
- node = (XMLNode*)malloc(sizeof(XMLNode));
+ node = (XMLNode*) malloc(sizeof (XMLNode));
if (node == NULL) {
return NULL;
}
node->_type = type;
node->_name = name;
@@ -709,11 +790,11 @@
return node;
}
static XMLAttribute* CreateXMLAttribute(TCHAR *name, TCHAR* value) {
XMLAttribute* attr;
- attr = (XMLAttribute*)malloc(sizeof(XMLAttribute));
+ attr = (XMLAttribute*) malloc(sizeof (XMLAttribute));
if (attr == NULL) {
return NULL;
}
attr->_name = name;
attr->_value = value;
@@ -722,12 +803,11 @@
}
XMLNode* ParseXMLDocument(TCHAR* buf) {
XMLNode* root;
int err_code = setjmp(jmpbuf);
- switch (err_code)
- {
+ switch (err_code) {
case JMP_NO_ERROR:
#ifndef _UNICODE
/* Remove UTF-8 encoding from buffer */
RemoveNonAsciiUTF8FromBuffer(buf);
#endif
@@ -744,11 +824,11 @@
if (root_node != NULL) {
FreeXMLDocument(root_node);
root_node = NULL;
}
if (CurTokenName != NULL) free(CurTokenName);
- fprintf(stderr,"Error during parsing jnlp file...\n");
+ fprintf(stderr, "Error during parsing jnlp file...\n");
exit(-1);
break;
default:
root = NULL;
break;
@@ -767,17 +847,17 @@
/* Create node for new element tag */
node = CreateXMLNode(xmlTagType, JPACKAGE_STRDUP(CurTokenName));
/* We need to save root node pointer to be able to cleanup
if an error happens during parsing */
- if(!root_node) {
+ if (!root_node) {
root_node = node;
}
/* Parse attributes. This section eats a all input until
EOF, a > or a /> */
attr = ParseXMLAttribute();
- while(attr != NULL) {
+ while (attr != NULL) {
attr->_next = node->_attributes;
node->_attributes = attr;
attr = ParseXMLAttribute();
}
@@ -785,16 +865,16 @@
* TOKEN_EMPTY_CLOSE_BRACKET */
GetNextToken();
/* Skip until '>', '/>' or EOF. This should really be an error, */
/* but we are loose */
-// if(CurTokenType == TOKEN_EMPTY_CLOSE_BRACKET ||
-// CurTokenType == TOKEN_CLOSE_BRACKET ||
-// CurTokenType == TOKEN_EOF) {
-// println("XML Parsing error: wrong kind of token found");
-// return NULL;
-// }
+ // if(CurTokenType == TOKEN_EMPTY_CLOSE_BRACKET ||
+ // CurTokenType == TOKEN_CLOSE_BRACKET ||
+ // CurTokenType == TOKEN_EOF) {
+ // println("XML Parsing error: wrong kind of token found");
+ // return NULL;
+ // }
if (CurTokenType == TOKEN_EMPTY_CLOSE_BRACKET) {
GetNextToken();
/* We are done with the sublevel - fall through to continue */
/* parsing tags at the same level */
@@ -806,11 +886,11 @@
if (CurTokenType == TOKEN_END_TAG) {
/* Find closing bracket '>' for end tag */
do {
GetNextToken();
- } while(CurTokenType != TOKEN_EOF &&
+ } while (CurTokenType != TOKEN_EOF &&
CurTokenType != TOKEN_CLOSE_BRACKET);
GetNextToken();
}
}
@@ -824,11 +904,11 @@
} else if (CurTokenType == TOKEN_PCDATA) {
/* Create node for pcdata */
node = CreateXMLNode(xmlPCDataType, JPACKAGE_STRDUP(CurTokenName));
/* We need to save root node pointer to be able to cleanup
if an error happens during parsing */
- if(!root_node) {
+ if (!root_node) {
root_node = node;
}
GetNextToken();
return node;
}
@@ -841,12 +921,11 @@
static XMLAttribute* ParseXMLAttribute(void) {
TCHAR* q = NULL;
TCHAR* name = NULL;
TCHAR* PrevPos = NULL;
- do
- {
+ do {
/* We need to check this condition to avoid endless loop
in case if an error happend during parsing. */
if (PrevPos == CurPos) {
if (name != NULL) {
free(name);
@@ -874,11 +953,11 @@
return NULL;
}
/* Find end of name */
q = CurPos;
- while(*q && !iswspace(*q) && *q !='=') NEXT_CHAR(q);
+ while (*q && !iswspace(*q) && *q != '=') NEXT_CHAR(q);
SetToken(TOKEN_UNKNOWN, CurPos, q);
if (name) {
free(name);
name = NULL;
@@ -892,24 +971,24 @@
/* Next TCHARacter must be '=' for a valid attribute.
If it is not, this is really an error.
We ignore this, and just try to parse an attribute
out of the rest of the string.
*/
- } while(*CurPos != '=');
+ } while (*CurPos != '=');
NEXT_CHAR(CurPos);
CurPos = SkipWhiteSpace(CurPos);
/* Parse CDATA part of attribute */
if ((*CurPos == '\"') || (*CurPos == '\'')) {
TCHAR quoteChar = *CurPos;
q = ++CurPos;
- while(*q != '\0' && *q != quoteChar) NEXT_CHAR(q);
+ while (*q != '\0' && *q != quoteChar) NEXT_CHAR(q);
SetToken(TOKEN_CDATA, CurPos, q);
CurPos = q + 1;
} else {
q = CurPos;
- while(*q != '\0' && !iswspace(*q)) NEXT_CHAR(q);
+ while (*q != '\0' && !iswspace(*q)) NEXT_CHAR(q);
SetToken(TOKEN_CDATA, CurPos, q);
CurPos = q;
}
//Note: no need to free name and CurTokenName duplicate; they're assigned
@@ -953,11 +1032,10 @@
if (attr == NULL) return NULL;
if (JPACKAGE_STRCMP(attr->_name, name) == 0) return attr->_value;
return FindXMLAttribute(attr->_next, name);
}
-
void PrintXMLDocument(XMLNode* node, int indt) {
if (node == NULL) return;
if (node->_type == xmlTagType) {
JPACKAGE_PRINTF(_T("\n"));
@@ -985,197 +1063,25 @@
PrintXMLAttributes(attr->_next);
}
static void indent(int indt) {
int i;
- for(i = 0; i < indt; i++) {
+ for (i = 0; i < indt; i++) {
JPACKAGE_PRINTF(_T(" "));
}
}
const TCHAR *CDStart = _T("<![CDATA[");
const TCHAR *CDEnd = _T("]]>");
-
static TCHAR* SkipPCData(TCHAR *p) {
TCHAR *end = JPACKAGE_STRSTR(p, CDEnd);
if (end != NULL) {
- return end+sizeof(CDEnd);
+ return end + sizeof (CDEnd);
}
return (++p);
}
static int IsPCData(TCHAR *p) {
- const int size = sizeof(CDStart);
+ const int size = sizeof (CDStart);
return (JPACKAGE_STRNCMP(CDStart, p, size) == 0);
}
-
-namespace {
- template<class funcType>
- class DllFunction {
- const Library& lib;
- funcType funcPtr;
- std::string theName;
-
- public:
- DllFunction(const Library& library,
- const std::string &funcName): lib(library) {
- funcPtr = reinterpret_cast<funcType>(lib.GetProcAddress(funcName));
- if (!funcPtr) {
- throw std::runtime_error("Failed to load function \""
- + funcName + "\" from \""
- + library.GetName() + "\" library");
- }
- }
-
- operator funcType() const {
- return funcPtr;
- }
- };
-} // namespace
-
-extern "C" {
-typedef Status (*XInitThreadsFuncPtr)();
-typedef Display* (*XOpenDisplayFuncPtr)(char *display_name);
-
-typedef Atom (*XInternAtomFuncPtr)(
- Display *display, char *atom_name, Bool only_if_exists);
-
-typedef Window (*XDefaultRootWindowFuncPtr)(Display *display);
-
-typedef int (*XCloseDisplayFuncPtr)(Display *display);
-}
-
-ProcessReactivator::ProcessReactivator(pid_t pid): _pid(pid) {
- const std::string libname = "libX11.so";
- if(!libX11.Load(libname)) {
- throw std::runtime_error("Failed to load \"" + libname + "\" library");
- }
-
- DllFunction<XInitThreadsFuncPtr> XInitThreadsFunc(libX11, "XInitThreads");
-
- XInitThreadsFunc();
-
- DllFunction<XOpenDisplayFuncPtr> XOpenDisplayFunc(libX11, "XOpenDisplay");
-
- _display = XOpenDisplayFunc(NULL);
-
- DllFunction<XInternAtomFuncPtr> XInternAtomFunc(libX11, "XInternAtom");
-
- _atomPid = XInternAtomFunc(_display, (char*)"_NET_WM_PID", True);
-
- if (_atomPid == None) {
- return;
- }
-
- DllFunction<XDefaultRootWindowFuncPtr> XDefaultRootWindowFunc(libX11,
- "XDefaultRootWindow");
-
- searchWindowHelper(XDefaultRootWindowFunc(_display));
-
- reactivateProcess();
-
- DllFunction<XCloseDisplayFuncPtr> XCloseDisplayFunc(libX11,
- "XCloseDisplay");
-
- XCloseDisplayFunc(_display);
-}
-
-extern "C" {
-typedef int (*XGetWindowPropertyFuncPtr)(
- Display *display, Window w, Atom property, long long_offset,
- long long_length, Bool d, Atom req_type, Atom *actual_type_return,
- int *actual_format_return, unsigned long *nitems_return,
- unsigned long *bytes_after_return, unsigned char **prop_return);
-
-typedef Status (*XQueryTreeFuncPtr)(
- Display *display, Window w, Window *root_return, Window *parent_return,
- Window **children_return, unsigned int *nchildren_return);
-
-typedef int (*XFreeFuncPtr)(void *data);
-}
-
-void ProcessReactivator::searchWindowHelper(Window w) {
-
- DllFunction<XGetWindowPropertyFuncPtr> XGetWindowPropertyFunc(libX11,
- "XGetWindowProperty");
-
- DllFunction<XFreeFuncPtr> XFreeFunc(libX11, "XFree");
-
- Atom type;
- int format;
- unsigned long num, bytesAfter;
- unsigned char* propPid = 0;
- if (Success == XGetWindowPropertyFunc(_display, w, _atomPid, 0, 1,
- False, XA_CARDINAL, &type, &format, &num, &bytesAfter, &propPid)) {
- if (propPid != 0) {
- if (_pid == *((pid_t *)propPid)) {
- _result.push_back(w);
- }
- XFreeFunc(propPid);
- }
- }
-
- DllFunction<XQueryTreeFuncPtr> XQueryTreeFunc(libX11, "XQueryTree");
-
- Window root, parent;
- Window* child;
- unsigned int numChildren;
- if (0 != XQueryTreeFunc(_display, w, &root,
- &parent, &child, &numChildren)) {
- for (unsigned int i = 0; i < numChildren; i++) {
- searchWindowHelper(child[i]);
- }
- }
-}
-
-
-extern "C" {
-typedef Status (*XGetWindowAttributesFuncPtr)(Display *display, Window w,
- XWindowAttributes *window_attributes_return);
-
-typedef Status (*XSendEventFuncPtr)(Display *display, Window w, Bool propagate,
- long event_mask, XEvent *event_send);
-
-typedef int (*XRaiseWindowFuncPtr)(Display *display, Window w);
-}
-
-void ProcessReactivator::reactivateProcess() {
-
- DllFunction<XGetWindowAttributesFuncPtr> XGetWindowAttributesFunc(libX11,
- "XGetWindowAttributes");
-
- DllFunction<XSendEventFuncPtr> XSendEventFunc(libX11, "XSendEvent");
-
- DllFunction<XRaiseWindowFuncPtr> XRaiseWindowFunc(libX11, "XRaiseWindow");
-
- DllFunction<XInternAtomFuncPtr> XInternAtomFunc(libX11, "XInternAtom");
-
- for (std::list<Window>::const_iterator it = _result.begin();
- it != _result.end(); it++) {
- // try sending an event to activate window,
- // after that we can try to raise it.
- XEvent xev;
- Atom atom = XInternAtomFunc (
- _display, (char*)"_NET_ACTIVE_WINDOW", False);
- xev.xclient.type = ClientMessage;
- xev.xclient.serial = 0;
- xev.xclient.send_event = True;
- xev.xclient.display = _display;
- xev.xclient.window = *it;
- xev.xclient.message_type = atom;
- xev.xclient.format = 32;
- xev.xclient.data.l[0] = 2;
- xev.xclient.data.l[1] = 0;
- xev.xclient.data.l[2] = 0;
- xev.xclient.data.l[3] = 0;
- xev.xclient.data.l[4] = 0;
- XWindowAttributes attr;
- XGetWindowAttributesFunc(_display, *it, &attr);
- XSendEventFunc(_display, attr.root, False,
- SubstructureRedirectMask | SubstructureNotifyMask, &xev);
- XRaiseWindowFunc(_display, *it);
- }
-}
-
-
-#endif // LINUX
< prev index next >