deep-c-rsc/JCGO/native/jcgoexec.c

1042 lines
27 KiB
C

/*
* @(#) $(JCGO)/native/jcgoexec.c --
* a part of the JCGO native layer library (process exec impl).
**
* Project: JCGO (http://www.ivmaisoft.com/jcgo/)
* Copyright (C) 2001-2013 Ivan Maidanski <ivmai@mail.ru>
* All rights reserved.
*/
/*
* Used control macros: JCGO_EXEC, JCGO_NOCWDIR, JCGO_NOFILES, JCGO_SYSDUALW,
* JCGO_SYSWCHAR, JCGO_UNIFSYS, JCGO_UNIPROC, JCGO_UNIX, JCGO_WINFILE.
* Macros for tuning: STATIC.
*/
/*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
**
* This software is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License (GPL) for more details.
**
* Linking this library statically or dynamically with other modules is
* making a combined work based on this library. Thus, the terms and
* conditions of the GNU General Public License cover the whole
* combination.
**
* As a special exception, the copyright holders of this library give you
* permission to link this library with independent modules to produce an
* executable, regardless of the license terms of these independent
* modules, and to copy and distribute the resulting executable under
* terms of your choice, provided that you also meet, for each linked
* independent module, the terms and conditions of the license of that
* module. An independent module is a module which is not derived from
* or based on this library. If you modify this library, you may extend
* this exception to your version of the library, but you are not
* obligated to do so. If you do not wish to do so, delete this
* exception statement from your version.
*/
#ifndef JCGO_BUILDING_JNU
#include "jcgojnu.h"
#endif
#ifdef JCGO_VER
#ifndef JCGO_EXCLUDE_VMPROCESS
#ifdef JCGO_EXEC
#include "jcgoexec.h"
#ifndef STATIC
#define STATIC static
#endif
#ifdef JCGO_WINFILE
#ifndef JCGO_CREATEPROCESS_FLAGS
#define JCGO_CREATEPROCESS_FLAGS 0
#endif
int jcgo_winFileErrnoGet(void);
STATIC HANDLE jcgo_tspawnWinExec( JCGO_JNUTCHAR_T *tprogpath,
JCGO_JNUTCHAR_T *tcmdline, JCGO_JNUTCHAR_T *tenvz, JCGO_JNUTCHAR_T *tcurdir,
HANDLE *pinHandle, HANDLE *poutHandle, HANDLE *perrHandle, int *perrcode,
int redirect )
{
PROCESS_INFORMATION pi;
#ifdef _WINBASE_NO_CREATEPIPE
#ifdef _WIN32_WCE
void *psi = NULL;
#else
#ifdef JCGO_SYSWCHAR
STARTUPINFOW si = { 0 };
#else
STARTUPINFOA si = { 0 };
#endif
void *psi = &si;
si.cb = sizeof(si);
#endif
if (!JCGO_JNUTCHAR_E(CreateProcessA(*JCGO_JNUTCHAR_C(tprogpath) ?
JCGO_JNUTCHAR_C(tprogpath) : NULL, *JCGO_JNUTCHAR_C(tcmdline) ?
JCGO_JNUTCHAR_C(tcmdline) : NULL, NULL, NULL, FALSE,
JCGO_CREATEPROCESS_FLAGS, tenvz, *JCGO_JNUTCHAR_C(tcurdir) != '.' ||
*(JCGO_JNUTCHAR_C(tcurdir) + 1) ? JCGO_JNUTCHAR_C(tcurdir) : NULL,
psi, &pi), CreateProcessW(*tprogpath ? tprogpath : NULL,
*tcmdline ? tcmdline : NULL, NULL, NULL, FALSE, tenvz != NULL ?
JCGO_CREATEPROCESS_FLAGS | CREATE_UNICODE_ENVIRONMENT :
JCGO_CREATEPROCESS_FLAGS, tenvz, *tcurdir != (wchar_t)0x2e ||
*(tcurdir + 1) ? tcurdir : NULL, psi, &pi)))
{
*perrcode = jcgo_winFileErrnoGet();
return INVALID_HANDLE_VALUE;
}
(void)CloseHandle(pi.hThread);
*pinHandle = INVALID_HANDLE_VALUE;
*poutHandle = INVALID_HANDLE_VALUE;
*perrHandle = INVALID_HANDLE_VALUE;
#else
HANDLE hInReadPipe = INVALID_HANDLE_VALUE;
HANDLE hOutWritePipe = INVALID_HANDLE_VALUE;
HANDLE hErrWritePipe = INVALID_HANDLE_VALUE;
SECURITY_ATTRIBUTES sa;
#ifdef JCGO_SYSWCHAR
STARTUPINFOW si = { 0 };
#else
STARTUPINFOA si = { 0 };
#endif
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
*pinHandle = INVALID_HANDLE_VALUE;
*poutHandle = INVALID_HANDLE_VALUE;
if (!CreatePipe(&hInReadPipe, pinHandle, &sa, JCGO_SPAWN_PIPEBUFSIZE) ||
!CreatePipe(poutHandle, &hOutWritePipe, &sa, JCGO_SPAWN_PIPEBUFSIZE) ||
(!redirect && !CreatePipe(perrHandle, &hErrWritePipe, &sa,
JCGO_SPAWN_PIPEBUFSIZE)))
{
*perrcode = jcgo_winFileErrnoGet();
(void)CloseHandle(hInReadPipe);
(void)CloseHandle(*pinHandle);
if (!redirect)
{
(void)CloseHandle(*poutHandle);
(void)CloseHandle(hOutWritePipe);
}
return INVALID_HANDLE_VALUE;
}
#ifndef _WINBASE_NO_SETHANDLEINFORMATION
(void)SetHandleInformation(*pinHandle, HANDLE_FLAG_INHERIT, FALSE);
(void)SetHandleInformation(*poutHandle, HANDLE_FLAG_INHERIT, FALSE);
if (!redirect)
(void)SetHandleInformation(*perrHandle, HANDLE_FLAG_INHERIT, FALSE);
#endif
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = hInReadPipe;
si.hStdOutput = hOutWritePipe;
si.hStdError = redirect ? hOutWritePipe : hErrWritePipe;
if (JCGO_JNUTCHAR_E(CreateProcessA(*JCGO_JNUTCHAR_C(tprogpath) ?
JCGO_JNUTCHAR_C(tprogpath) : NULL, *JCGO_JNUTCHAR_C(tcmdline) ?
JCGO_JNUTCHAR_C(tcmdline) : NULL, NULL, NULL, TRUE,
JCGO_CREATEPROCESS_FLAGS, tenvz, *JCGO_JNUTCHAR_C(tcurdir) != '.' ||
*(JCGO_JNUTCHAR_C(tcurdir) + 1) ? JCGO_JNUTCHAR_C(tcurdir) : NULL,
JCGO_JNUTCHAR_R(STARTUPINFOA, &si), &pi), CreateProcessW(*tprogpath ?
tprogpath : NULL, *tcmdline ? tcmdline : NULL, NULL, NULL, TRUE,
tenvz != NULL ? JCGO_CREATEPROCESS_FLAGS | CREATE_UNICODE_ENVIRONMENT :
JCGO_CREATEPROCESS_FLAGS, tenvz, *tcurdir != (wchar_t)0x2e ||
*(tcurdir + 1) ? tcurdir : NULL, &si, &pi)))
(void)CloseHandle(pi.hThread);
else
{
*perrcode = jcgo_winFileErrnoGet();
pi.hProcess = INVALID_HANDLE_VALUE;
(void)CloseHandle(*pinHandle);
(void)CloseHandle(*poutHandle);
if (!redirect)
(void)CloseHandle(*perrHandle);
}
(void)CloseHandle(hInReadPipe);
(void)CloseHandle(hOutWritePipe);
if (!redirect)
(void)CloseHandle(hErrWritePipe);
#endif
return pi.hProcess;
}
#else /* JCGO_WINFILE */
#ifdef JCGO_SYSWCHAR
#ifndef JCGO_SYSDUALW
#define JCGO_SPAWN_WCHARONLY
#endif
#endif
#ifndef JCGO_SPAWN_WCHARONLY
STATIC char **jcgo_spawnConvZBlock( JNIEnv *pJniEnv, jstring strZBlock,
void *buffer, jint *pofs, jint bufLen, int allowEmptyStr )
{
int i = 0;
unsigned pos = 0;
jint ofs1 = *pofs;
jint ofs2;
char **carr = NULL;
char *cstr = (char *)buffer + ofs1;
if (ofs1 < bufLen && jcgo_JnuStringToPlatformChars(pJniEnv, strZBlock, cstr,
(unsigned)bufLen - (unsigned)ofs1) >= 0)
{
if (*cstr)
{
do
{
pos++;
} while (*(cstr + pos) || *(cstr + pos + 1));
pos++;
}
ofs2 = (jint)(pos + sizeof(void *) - ((unsigned)(cstr - (char *)NULL) +
pos) % sizeof(void *)) + ofs1;
carr = (char **)((volatile char *)buffer + ofs2);
if (*cstr)
{
pos = 0;
do
{
if (*(cstr + pos) == ' ' && allowEmptyStr)
pos++;
*(carr + i) = cstr + pos;
while (*(cstr + pos))
pos++;
i++;
} while (*(cstr + (++pos)));
}
*pofs = (jint)((unsigned)(i + 1) * sizeof(void *)) + ofs2;
}
return carr;
}
#endif /* ! JCGO_SPAWN_WCHARONLY */
#ifdef JCGO_SYSWCHAR
STATIC wchar_t **jcgo_wspawnConvZBlock( JNIEnv *pJniEnv, jstring strZBlock,
void *buffer, jint *pofs, jint bufLen, int allowEmptyStr )
{
int i = 0;
unsigned pos = 0;
jint ofs1 = *pofs;
jint ofs2;
wchar_t **warr = NULL;
wchar_t *wstr = (wchar_t *)((volatile char *)buffer + ofs1);
if (ofs1 < bufLen && jcgo_JnuStringToWideChars(pJniEnv, strZBlock, wstr,
(unsigned)bufLen - (unsigned)ofs1) >= 0)
{
if (*wstr)
{
do
{
pos++;
} while (*(wstr + pos) || *(wstr + pos + 1));
pos++;
}
ofs2 = (jint)(pos * sizeof(wchar_t) + (sizeof(wchar_t) +
sizeof(void *) - 1) - ((unsigned)((volatile char *)wstr -
(volatile char *)NULL) + pos * sizeof(wchar_t)) % sizeof(void *)) +
ofs1;
warr = (wchar_t **)((volatile char *)buffer + ofs2);
if (*wstr)
{
pos = 0;
do
{
if (*(wstr + pos) == (wchar_t)0x20 && allowEmptyStr)
pos++;
*(warr + i) = wstr + pos;
while (*(wstr + pos))
pos++;
i++;
} while (*(wstr + (++pos)));
}
*pofs = (jint)((unsigned)(i + 1) * sizeof(void *)) + ofs2;
}
return warr;
}
#endif /* JCGO_SYSWCHAR */
#ifdef JCGO_UNIPROC
STATIC void jcgo_restoreVMSignals( void )
{
#ifdef SIGTERM
signal(SIGTERM, SIG_DFL);
#endif
#ifdef SIGINT
signal(SIGINT, SIG_DFL);
#endif
#ifdef SIGHUP
signal(SIGHUP, SIG_DFL);
#endif
#ifdef SIGSEGV
signal(SIGSEGV, SIG_DFL);
#endif
#ifdef SIGBUS
signal(SIGBUS, SIG_DFL);
#endif
}
STATIC void jcgo_closeInheritedFDs( void )
{
int fd;
int errcode;
for (fd = 0; fd < JCGO_SPAWN_OPENMAX; fd++)
if (fd != JCGO_FD_INFD && fd != JCGO_FD_OUTFD && fd != JCGO_FD_ERRFD)
(void)JCGO_FD_CLOSE(fd, &errcode);
}
#else /* JCGO_UNIPROC */
#ifndef JCGO_NOCWDIR
#ifndef JCGO_UNIX
#ifndef JCGO_NOFILES
#ifndef JCGO_UNIFSYS
#ifndef JCGO_SPAWN_WCHARONLY
STATIC int jcgo_driveIndexOf( char *path )
{
int drive;
char *letters = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
char ch = *path;
for (drive = 0; *(letters + drive) != ch; drive++)
if (!(*(letters + drive)))
return 0;
return (drive >> 1) + 1;
}
#endif /* ! JCGO_SPAWN_WCHARONLY */
#ifdef JCGO_SYSWCHAR
STATIC int jcgo_wdriveIndexOf( wchar_t *wpath )
{
wchar_t wch = *wpath;
return wch > (wchar_t)0x40 && wch <= (wchar_t)0x5a ? /*'Z'*/
(int)wch - 0x40 : /*('A'-1)*/
wch > (wchar_t)0x60 && wch <= (wchar_t)0x7a ? /*'z'*/
(int)wch - 0x60 : 0; /*('a'-1)*/
}
#endif /* JCGO_SYSWCHAR */
#endif /* ! JCGO_UNIFSYS */
#endif /* ! JCGO_NOFILES */
#endif /* ! JCGO_UNIX */
#endif /* ! JCGO_NOCWDIR */
STATIC jlong jcgo_tspawnvpeDir( int mode, JCGO_JNUTCHAR_T **targv,
JCGO_JNUTCHAR_T **tenvp, JCGO_JNUTCHAR_T *tcurdir, int *perrcode )
{
jlong pid = 0;
#ifndef JCGO_NOFILES
#ifndef JCGO_NOCWDIR
#ifndef JCGO_UNIFSYS
#ifndef JCGO_UNIX
int drive = 0;
#endif
#endif
JCGO_JNUTCHAR_T tbuf[JCGO_PATH_MAXSIZE];
#endif
#endif
#ifdef JCGO_NOFILES
if (tcurdir != NULL)
{
*perrcode = ENOTDIR;
pid = (jlong)-1L;
}
#else
#ifdef JCGO_NOCWDIR
JCGO_UNUSED_VAR(tcurdir);
JCGO_UNUSED_VAR(perrcode);
#else
if (tcurdir != NULL)
{
tbuf[0] = (JCGO_JNUTCHAR_T)0;
if (JCGO_PATH_TGETCWD(tbuf,
sizeof(tbuf) / sizeof(JCGO_JNUTCHAR_T)) == NULL || !tbuf[0])
{
*perrcode = ENOTDIR;
return (jlong)-1L;
}
#ifndef JCGO_UNIFSYS
#ifndef JCGO_UNIX
if (JCGO_JNUTCHAR_E(*JCGO_JNUTCHAR_C(tcurdir) &&
*(JCGO_JNUTCHAR_C(tcurdir) + 1) == ':' && *JCGO_JNUTCHAR_C(tcurdir) !=
*JCGO_JNUTCHAR_C(tbuf) && *(JCGO_JNUTCHAR_C(tbuf) + 1) == ':' &&
(drive = jcgo_driveIndexOf(JCGO_JNUTCHAR_C(tcurdir))) != 0,
*tcurdir && *(tcurdir + 1) == (wchar_t)0x3a && *tcurdir != tbuf[0] &&
tbuf[1] == (wchar_t)0x3a && (drive = jcgo_wdriveIndexOf(tcurdir)) != 0))
drive = JCGO_PATH_SETDRIVE(&drive) ? 0 :
JCGO_JNUTCHAR_E(jcgo_driveIndexOf(JCGO_JNUTCHAR_C(tbuf)),
jcgo_wdriveIndexOf(tbuf));
#endif
#endif
if (JCGO_PATH_TCHDIR(tcurdir))
{
*perrcode = ENOTDIR;
pid = (jlong)-1L;
#ifdef JCGO_UNIFSYS
tcurdir = NULL;
#endif
}
}
#endif
#endif
if (!pid)
pid = tenvp != NULL ? JCGO_JNUTCHAR_E(spawnvpe(mode,
JCGO_JNUTCHAR_C(targv[0]), (void *)targv, (void *)tenvp),
_wspawnvpe(mode, targv[0], (void *)targv, (void *)tenvp)) :
JCGO_JNUTCHAR_E(spawnvp(mode, JCGO_JNUTCHAR_C(targv[0]),
(void *)targv), _wspawnvp(mode, targv[0], (void *)targv));
#ifndef JCGO_NOFILES
#ifndef JCGO_NOCWDIR
if (tcurdir != NULL)
{
#ifndef JCGO_UNIFSYS
#ifndef JCGO_UNIX
if (drive)
(void)JCGO_PATH_SETDRIVE(&drive);
#endif
#endif
(void)JCGO_PATH_TCHDIR(tbuf);
}
#endif
#endif
return pid;
}
#endif /* ! JCGO_UNIPROC */
STATIC jlong jcgo_tspawnExec( JCGO_JNUTCHAR_T **targv,
JCGO_JNUTCHAR_T **tenvp, JCGO_JNUTCHAR_T *tcurdir, int *pinfd, int *poutfd,
int *perrfd, int *perrcode, int redirect )
{
int inpipe[2];
int outpipe[2];
int errpipe[2];
jlong pid;
int errcode2 = -1;
#ifdef JCGO_UNIPROC
JCGO_JNUTCHAR_T *targv0 = targv[0];
inpipe[0] = -1;
inpipe[1] = -1;
outpipe[0] = -1;
outpipe[1] = -1;
errpipe[0] = -1;
errpipe[1] = -1;
pid = (jlong)errcode2;
if (!JCGO_SPAWN_PIPE(inpipe, perrcode) &&
!JCGO_SPAWN_PIPE(outpipe, perrcode) &&
(redirect || !JCGO_SPAWN_PIPE(errpipe, perrcode)) &&
(pid = fork()) == (jlong)-1L)
*perrcode = errno;
if (pid)
{
if (inpipe[0] != -1)
(void)JCGO_FD_CLOSE(inpipe[0], &errcode2);
if (outpipe[1] != -1)
(void)JCGO_FD_CLOSE(outpipe[1], &errcode2);
if (errpipe[1] != -1)
(void)JCGO_FD_CLOSE(errpipe[1], &errcode2);
if (pid != (jlong)-1L)
{
*pinfd = inpipe[1];
*poutfd = outpipe[0];
*perrfd = errpipe[0];
return pid;
}
}
else jcgo_restoreVMSignals();
if (inpipe[1] != -1)
(void)JCGO_FD_CLOSE(inpipe[1], &errcode2);
if (outpipe[0] != -1)
(void)JCGO_FD_CLOSE(outpipe[0], &errcode2);
if (errpipe[0] != -1)
(void)JCGO_FD_CLOSE(errpipe[0], &errcode2);
if (!pid)
{
if (inpipe[0] != JCGO_FD_INFD)
{
dup2(inpipe[0], JCGO_FD_INFD);
(void)JCGO_FD_CLOSE(inpipe[0], &errcode2);
}
if (outpipe[1] != JCGO_FD_OUTFD)
{
dup2(outpipe[1], JCGO_FD_OUTFD);
(void)JCGO_FD_CLOSE(outpipe[1], &errcode2);
}
if (redirect)
dup2(JCGO_FD_OUTFD, JCGO_FD_ERRFD);
else
{
if (errpipe[1] != JCGO_FD_ERRFD)
{
dup2(errpipe[1], JCGO_FD_ERRFD);
(void)JCGO_FD_CLOSE(errpipe[1], &errcode2);
}
}
jcgo_closeInheritedFDs();
if (JCGO_JNUTCHAR_E(*JCGO_JNUTCHAR_C(tcurdir) == '.' &&
!(*(JCGO_JNUTCHAR_C(tcurdir) + 1)),
*tcurdir == (wchar_t)0x2e && !(*(tcurdir + 1)))
#ifndef JCGO_NOFILES
#ifndef JCGO_NOCWDIR
|| !JCGO_PATH_TCHDIR(tcurdir)
#endif
#endif
)
{
if (tenvp != NULL)
(void)JCGO_JNUTCHAR_E(execve(JCGO_JNUTCHAR_C(targv0), (void *)targv,
(void *)tenvp), _wexecve(targv0, (void *)targv, (void *)tenvp));
else (void)JCGO_JNUTCHAR_E(execvp(JCGO_JNUTCHAR_C(targv0), (void *)targv),
_wexecvp(targv0, (void *)targv));
}
JCGO_JNUTCHAR_E(perror(JCGO_JNUTCHAR_C(targv0)), _wperror(targv0));
exit(-1);
}
#else
int curin;
int curout;
int curerr;
if (!JCGO_SPAWN_PIPE(inpipe, perrcode))
{
if (!JCGO_SPAWN_PIPE(outpipe, perrcode))
{
errpipe[0] = -1;
errpipe[1] = -1;
if (redirect || !JCGO_SPAWN_PIPE(errpipe, perrcode))
{
curout = -1;
curerr = errcode2;
if ((curin = dup(JCGO_FD_INFD)) != -1 &&
(curout = dup(JCGO_FD_OUTFD)) != -1 &&
(curerr = dup(JCGO_FD_ERRFD)) != -1)
{
dup2(inpipe[0], JCGO_FD_INFD);
dup2(outpipe[1], JCGO_FD_OUTFD);
dup2(redirect ? JCGO_FD_OUTFD : errpipe[1], JCGO_FD_ERRFD);
}
else *perrcode = errno;
(void)JCGO_FD_CLOSE(inpipe[0], &errcode2);
(void)JCGO_FD_CLOSE(outpipe[1], &errcode2);
if (!redirect)
(void)JCGO_FD_CLOSE(errpipe[1], &errcode2);
if (curin != -1)
{
pid = (jlong)-1L;
if (curout != -1)
{
if (curerr != -1)
{
pid = jcgo_tspawnvpeDir(P_NOWAIT, targv, tenvp,
JCGO_JNUTCHAR_E(*JCGO_JNUTCHAR_C(tcurdir) != '.' ||
*(JCGO_JNUTCHAR_C(tcurdir) + 1), *tcurdir != (wchar_t)0x2e ||
*(tcurdir + 1)) ? tcurdir : NULL, perrcode);
dup2(curin, JCGO_FD_INFD);
dup2(curout, JCGO_FD_OUTFD);
dup2(curerr, JCGO_FD_ERRFD);
(void)JCGO_FD_CLOSE(curerr, &errcode2);
}
(void)JCGO_FD_CLOSE(curout, &errcode2);
}
(void)JCGO_FD_CLOSE(curin, &errcode2);
if (pid != (jlong)-1L && pid)
{
*pinfd = inpipe[1];
*poutfd = outpipe[0];
*perrfd = errpipe[0];
return pid;
}
}
if (!redirect)
(void)JCGO_FD_CLOSE(errpipe[0], &errcode2);
}
else (void)JCGO_FD_CLOSE(outpipe[1], &errcode2);
(void)JCGO_FD_CLOSE(outpipe[0], &errcode2);
}
else (void)JCGO_FD_CLOSE(inpipe[0], &errcode2);
(void)JCGO_FD_CLOSE(inpipe[1], &errcode2);
}
#endif
return (jlong)-1L;
}
#endif /* ! JCGO_WINFILE */
#else /* JCGO_EXEC */
#ifndef JCGO_WINFILE
#ifndef _ERRNO_H
#include <errno.h>
#endif
#endif
#ifndef EACCES
#define EACCES 12345
#endif
#endif /* ! JCGO_EXEC */
#ifndef NOJAVA_java_lang_VMProcess_getValidProgExtsList0
JCGO_JNI_EXPF(jstring,
Java_java_lang_VMProcess_getValidProgExtsList0)( JNIEnv *pJniEnv,
jclass This )
{
JCGO_UNUSED_VAR(This);
#ifdef JCGO_EXEC
return jcgo_JnuNewStringPlatform(pJniEnv, JCGO_SPAWN_PROGEXTS);
#else
return jcgo_JnuNewStringPlatform(pJniEnv, "");
#endif
}
#endif
#ifndef NOJAVA_java_lang_VMProcess_isProgSearchNeeded0
JCGO_JNI_EXPF(jint,
Java_java_lang_VMProcess_isProgSearchNeeded0)( JNIEnv *pJniEnv, jclass This )
{
JCGO_UNUSED_VAR(pJniEnv);
JCGO_UNUSED_VAR(This);
#ifdef JCGO_EXEC
return JCGO_SPAWN_ISPROGSEARCHNEEDED;
#else
return 0;
#endif
}
#endif
#ifndef NOJAVA_java_lang_VMProcess_isCmdSpaceDelimited0
JCGO_JNI_EXPF(jint,
Java_java_lang_VMProcess_isCmdSpaceDelimited0)( JNIEnv *pJniEnv, jclass This )
{
JCGO_UNUSED_VAR(pJniEnv);
JCGO_UNUSED_VAR(This);
#ifdef JCGO_EXEC
#ifdef JCGO_WINFILE
#ifdef _WIN32_WCE
return -1;
#else
return 1;
#endif
#else
return 0;
#endif
#else
return 0;
#endif
}
#endif
#ifndef NOJAVA_java_lang_VMProcess_checkPermissions0
JCGO_JNI_EXPF(jint,
Java_java_lang_VMProcess_checkPermissions0)( JNIEnv *pJniEnv, jclass This,
jstring path, jint isDirCheck )
{
#ifdef JCGO_EXEC
#ifdef JCGO_NOFILES
JCGO_UNUSED_VAR(pJniEnv);
JCGO_UNUSED_VAR(This);
JCGO_UNUSED_VAR(path);
return (jint)((int)isDirCheck ? -EACCES : 0);
#else
int res = -EACCES;
#ifdef JCGO_WINFILE
DWORD attrs;
#else
struct stat st;
#endif
JCGO_JNUTCHAR_T tbuf[JCGO_PATH_MAXSIZE];
JCGO_UNUSED_VAR(This);
if (JCGO_JNU_TSTRINGTOCHARS(pJniEnv, path, tbuf) > 0)
{
JCGO_SPAWNCALL_BEGIN(pJniEnv)
#ifdef JCGO_WINFILE
if ((attrs = JCGO_JNUTCHAR_E(GetFileAttributesA(JCGO_JNUTCHAR_C(tbuf)),
GetFileAttributesW(tbuf))) == INVALID_FILE_ATTRIBUTES)
{
res = -jcgo_winFileErrnoGet();
if ((int)isDirCheck && res == -ENOENT)
res = -ENOTDIR;
}
else
{
if ((int)isDirCheck)
{
res = 0;
if ((attrs & FILE_ATTRIBUTE_DIRECTORY) == 0)
res = -ENOTDIR;
}
else if ((attrs & FILE_ATTRIBUTE_DIRECTORY) == 0)
res = 0;
}
#else
res = JCGO_JNUTCHAR_E(stat(JCGO_JNUTCHAR_C(tbuf), &st),
_wstat(tbuf, (void *)&st));
if (res < 0)
{
if ((res = -errno) >= 0)
res = -EACCES;
else if ((int)isDirCheck && res == -ENOENT)
res = -ENOTDIR;
}
else
{
if ((int)isDirCheck)
{
if ((st.st_mode & S_IFMT) != S_IFDIR)
res = -ENOTDIR;
#ifdef JCGO_UNIPROC
#ifdef JCGO_UNIX
else if ((st.st_mode & ((st.st_uid + 1) == 0 || geteuid() == st.st_uid ?
S_IXUSR : getegid() == st.st_gid ? S_IXGRP : S_IXOTH)) == 0)
res = -EACCES;
#endif
#endif
}
else
{
#ifdef JCGO_UNIPROC
if ((st.st_mode & S_IFMT) != S_IFREG || (st.st_mode & (
#ifdef JCGO_UNIX
(st.st_uid + 1) != 0 ? (geteuid() == st.st_uid ? S_IXUSR :
getegid() == st.st_gid ? S_IXGRP : S_IXOTH) :
#endif
S_IXUSR | S_IXGRP | S_IXOTH)) == 0)
res = -EACCES;
#else
if ((st.st_mode & S_IFMT) != S_IFREG)
res = -EACCES;
#endif
}
}
#endif
JCGO_SPAWNCALL_END(pJniEnv)
}
return (jint)res;
#endif
#else
JCGO_UNUSED_VAR(pJniEnv);
JCGO_UNUSED_VAR(This);
JCGO_UNUSED_VAR(path);
return (jint)((int)isDirCheck ? 0 : -EACCES);
#endif
}
#endif
#ifndef NOJAVA_java_lang_VMProcess_getSpawnWorkBufSize0
JCGO_JNI_EXPF(jint,
Java_java_lang_VMProcess_getSpawnWorkBufSize0)( JNIEnv *pJniEnv, jclass This,
jstring cmdZBlock, jstring envZBlock, jint cmdArrLen, jint envArrLen )
{
jint size;
JCGO_UNUSED_VAR(This);
#ifdef JCGO_WINFILE
JCGO_UNUSED_VAR(cmdArrLen);
JCGO_UNUSED_VAR(envArrLen);
size = (jint)JCGO_JNUTCHAR_E(jcgo_JnuStringSizeOfPlatform(pJniEnv,
cmdZBlock), jcgo_JnuStringSizeOfWide(pJniEnv, cmdZBlock));
return (size += (jint)JCGO_JNUTCHAR_E(jcgo_JnuStringSizeOfPlatform(pJniEnv,
envZBlock), jcgo_JnuStringSizeOfWide(pJniEnv, envZBlock))) <
(jint)(((unsigned)-1) >> 1) ? size : -1;
#else
return (cmdArrLen | envArrLen) < (jint)((((unsigned)-1) >> 1) /
sizeof(void *) - 2) && (size = (cmdArrLen + envArrLen) *
(jint)sizeof(void *) + (jint)(4 * sizeof(void *) - 2)) >= 0 &&
(size += (jint)JCGO_JNUTCHAR_E(jcgo_JnuStringSizeOfPlatform(pJniEnv,
cmdZBlock), jcgo_JnuStringSizeOfWide(pJniEnv, cmdZBlock))) >= 0 &&
(size += (jint)JCGO_JNUTCHAR_E(jcgo_JnuStringSizeOfPlatform(pJniEnv,
envZBlock), jcgo_JnuStringSizeOfWide(pJniEnv, envZBlock))) <
(jint)(((unsigned)-1) >> 1) ? size : -1;
#endif
}
#endif
#ifndef NOJAVA_java_lang_VMProcess_nativeSpawn0
JCGO_JNI_EXPF(jint,
Java_java_lang_VMProcess_nativeSpawn0)( JNIEnv *pJniEnv, jclass This,
jstring progName, jstring cmdZBlock, jstring envZBlock, jstring dirpath,
jintArray fdsArr, jlongArray pidArr, jbyteArray workBuf, jint bufLen,
jint redirect )
{
int errcode = EACCES;
#ifdef JCGO_EXEC
jint ofs;
void *buffer;
#ifdef JCGO_WINFILE
HANDLE inHandle = 0;
HANDLE outHandle = 0;
HANDLE errHandle = 0;
HANDLE handle;
#ifdef JCGO_NOFILES
JCGO_JNUTCHAR_T tnamebuf[512];
#else
JCGO_JNUTCHAR_T tnamebuf[JCGO_PATH_MAXSIZE];
#endif
#else
int infd = 0;
int outfd = 0;
int errfd = 0;
jlong pid;
JCGO_JNUTCHAR_T **targv;
JCGO_JNUTCHAR_T **tenvp;
#endif
#ifdef JCGO_NOFILES
JCGO_JNUTCHAR_T tbuf[16];
#else
JCGO_JNUTCHAR_T tbuf[JCGO_PATH_MAXSIZE];
#endif
JCGO_UNUSED_VAR(This);
#ifdef JCGO_WINFILE
if (JCGO_JNU_TSTRINGTOCHARS(pJniEnv, progName, tnamebuf) <= 0)
return -EACCES;
#else
JCGO_UNUSED_VAR(progName);
#endif
if (JCGO_JNU_TSTRINGTOCHARS(pJniEnv, dirpath, tbuf) <= 0)
return -ENOTDIR;
if ((buffer = jcgo_JnuGetByteArrayElemsRegion(pJniEnv, workBuf, 0,
bufLen)) != NULL)
{
#ifdef JCGO_WINFILE
ofs = (jint)JCGO_JNUTCHAR_E(jcgo_JnuStringSizeOfPlatform(pJniEnv,
cmdZBlock), jcgo_JnuStringSizeOfWide(pJniEnv, cmdZBlock));
handle = INVALID_HANDLE_VALUE;
if (JCGO_JNUTCHAR_E(jcgo_JnuStringToPlatformChars(pJniEnv, cmdZBlock,
buffer, (unsigned)bufLen), jcgo_JnuStringToWideChars(pJniEnv, cmdZBlock,
buffer, (unsigned)bufLen)) >= 0 &&
JCGO_JNUTCHAR_E(jcgo_JnuStringToPlatformChars(pJniEnv, envZBlock,
(void *)((volatile char *)buffer + ofs), (unsigned)(bufLen - ofs)),
jcgo_JnuStringToWideChars(pJniEnv, envZBlock,
(JCGO_JNUTCHAR_T *)((volatile char *)buffer + ofs),
(unsigned)(bufLen - ofs))) >= 0)
{
JCGO_SPAWNCALL_BEGIN(pJniEnv)
handle = jcgo_tspawnWinExec(tnamebuf, buffer,
JCGO_JNUTCHAR_E((JCGO_JNUTCHAR_T)(*((char *)buffer + ofs)),
*(JCGO_JNUTCHAR_T *)((volatile char *)buffer + ofs)) ?
(JCGO_JNUTCHAR_T *)((volatile char *)buffer + ofs) : NULL, tbuf,
&inHandle, &outHandle, &errHandle, &errcode, (int)redirect);
JCGO_SPAWNCALL_END(pJniEnv)
}
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, workBuf, buffer, 0);
if (handle != INVALID_HANDLE_VALUE)
{
jcgo_JnuSetIntArrayElement(pJniEnv, fdsArr, 0,
(jint)JCGO_WINF_HANDLETONUM(inHandle));
jcgo_JnuSetIntArrayElement(pJniEnv, fdsArr, 1,
(jint)JCGO_WINF_HANDLETONUM(outHandle));
jcgo_JnuSetIntArrayElement(pJniEnv, fdsArr, 2,
(jint)JCGO_WINF_HANDLETONUM(errHandle));
jcgo_JnuSetLongArrayElement(pJniEnv, pidArr, 0,
(jlong)JCGO_WINF_HANDLETONUM(handle));
return 0;
}
#else
ofs = 0;
pid = (jlong)-1L;
if ((targv = JCGO_JNUTCHAR_E(JCGO_JNUTCHAR_R(JCGO_JNUTCHAR_T *,
jcgo_spawnConvZBlock(pJniEnv, cmdZBlock, buffer, &ofs, bufLen, 1)),
jcgo_wspawnConvZBlock(pJniEnv, cmdZBlock, buffer, &ofs,
bufLen, 1))) != NULL && targv[0] != NULL &&
(tenvp = JCGO_JNUTCHAR_E(JCGO_JNUTCHAR_R(JCGO_JNUTCHAR_T *,
jcgo_spawnConvZBlock(pJniEnv, envZBlock, buffer, &ofs, bufLen, 0)),
jcgo_wspawnConvZBlock(pJniEnv, envZBlock, buffer, &ofs,
bufLen, 0))) != NULL)
{
JCGO_SPAWNCALL_BEGIN(pJniEnv)
pid = jcgo_tspawnExec(targv, *tenvp != NULL ? tenvp : NULL, tbuf, &infd,
&outfd, &errfd, &errcode, (int)redirect);
JCGO_SPAWNCALL_END(pJniEnv)
}
jcgo_JnuReleaseByteArrayElemsRegion(pJniEnv, workBuf, buffer, 0);
if (pid != (jlong)-1L)
{
jcgo_JnuSetIntArrayElement(pJniEnv, fdsArr, 0, (jint)infd);
jcgo_JnuSetIntArrayElement(pJniEnv, fdsArr, 1, (jint)outfd);
jcgo_JnuSetIntArrayElement(pJniEnv, fdsArr, 2, (jint)errfd);
jcgo_JnuSetLongArrayElement(pJniEnv, pidArr, 0, pid);
return 0;
}
#endif
}
#else
JCGO_UNUSED_VAR(pJniEnv);
JCGO_UNUSED_VAR(This);
JCGO_UNUSED_VAR(progName);
JCGO_UNUSED_VAR(cmdZBlock);
JCGO_UNUSED_VAR(envZBlock);
JCGO_UNUSED_VAR(dirpath);
JCGO_UNUSED_VAR(fdsArr);
JCGO_UNUSED_VAR(pidArr);
JCGO_UNUSED_VAR(workBuf);
JCGO_UNUSED_VAR(bufLen);
JCGO_UNUSED_VAR(redirect);
#endif
return -errcode;
}
#endif
#ifndef NOJAVA_java_lang_VMProcess_nativeWaitFor0
JCGO_JNI_EXPF(jint,
Java_java_lang_VMProcess_nativeWaitFor0)( JNIEnv *pJniEnv, jclass This,
jlong pid, jint nohang )
{
#ifdef JCGO_EXEC
#ifdef JCGO_WINFILE
HANDLE handle = JCGO_WINF_NUMTOHANDLE(pid);
DWORD exitcode;
int status;
JCGO_UNUSED_VAR(pJniEnv);
JCGO_UNUSED_VAR(This);
JCGO_SPAWNCALL_BEGIN(pJniEnv)
if (!(int)nohang)
(void)WaitForSingleObject(handle, INFINITE);
if (GetExitCodeProcess(handle, &exitcode))
{
if (exitcode != STILL_ACTIVE)
(void)CloseHandle(handle);
}
else exitcode = 0;
JCGO_SPAWNCALL_END(pJniEnv)
if (exitcode == STILL_ACTIVE)
return -1;
status = (int)exitcode;
#else
int res;
int errcode;
int status = 0;
JCGO_UNUSED_VAR(pJniEnv);
JCGO_UNUSED_VAR(This);
JCGO_SPAWNCALL_BEGIN(pJniEnv)
res = JCGO_SPAWN_WAITPID(pid, &status, (int)nohang, &errcode);
JCGO_SPAWNCALL_END(pJniEnv)
if (!res)
return -1;
if (res == -1)
return (jint)(errcode == EINTR ? -1 : 0);
status = JCGO_SPAWN_EXITCODE(status);
#endif
if (status < 0)
status = -status;
return (jint)status;
#else
JCGO_UNUSED_VAR(pJniEnv);
JCGO_UNUSED_VAR(This);
JCGO_UNUSED_VAR(pid);
JCGO_UNUSED_VAR(nohang);
return 0;
#endif
}
#endif
#ifndef NOJAVA_java_lang_VMProcess_nativeKill
JCGO_JNI_EXPF(jint,
Java_java_lang_VMProcess_nativeKill)( JNIEnv *pJniEnv, jclass This,
jlong pid )
{
#ifdef JCGO_EXEC
int res;
JCGO_UNUSED_VAR(pJniEnv);
JCGO_UNUSED_VAR(This);
JCGO_SPAWNCALL_BEGIN(pJniEnv)
res = JCGO_SPAWN_KILL(pid);
JCGO_SPAWNCALL_END(pJniEnv)
return (jint)res;
#else
JCGO_UNUSED_VAR(pJniEnv);
JCGO_UNUSED_VAR(This);
JCGO_UNUSED_VAR(pid);
return 0;
#endif
}
#endif
#ifndef NOJAVA_java_lang_VMProcess_pipe0
JCGO_JNI_EXPF(jint,
Java_java_lang_VMProcess_pipe0)( JNIEnv *pJniEnv, jclass This,
jintArray fdsArr )
{
#ifdef JCGO_EXEC
int res;
#ifdef JCGO_WINFILE
#ifdef _WINBASE_NO_CREATEPIPE
JCGO_UNUSED_VAR(fdsArr);
res = -EACCES;
#else
HANDLE hReadPipe;
HANDLE hWritePipe;
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = FALSE;
res = 0;
hReadPipe = INVALID_HANDLE_VALUE;
hWritePipe = INVALID_HANDLE_VALUE;
JCGO_SPAWNCALL_BEGIN(pJniEnv)
if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, JCGO_SPAWN_PIPEBUFSIZE))
res = -jcgo_winFileErrnoGet();
JCGO_SPAWNCALL_END(pJniEnv)
if (res >= 0)
{
jcgo_JnuSetIntArrayElement(pJniEnv, fdsArr, 0,
(jint)JCGO_WINF_HANDLETONUM(hReadPipe));
jcgo_JnuSetIntArrayElement(pJniEnv, fdsArr, 1,
(jint)JCGO_WINF_HANDLETONUM(hWritePipe));
}
#endif
#else
int errcode = 0;
int fds[2];
fds[0] = -1;
fds[1] = -1;
JCGO_SPAWNCALL_BEGIN(pJniEnv)
res = JCGO_SPAWN_PIPE(fds, &errcode);
(void)JCGO_FD_SETCLOEXEC(fds[0]);
(void)JCGO_FD_SETCLOEXEC(fds[1]);
JCGO_SPAWNCALL_END(pJniEnv)
if (res >= 0)
{
jcgo_JnuSetIntArrayElement(pJniEnv, fdsArr, 0, (jint)fds[0]);
jcgo_JnuSetIntArrayElement(pJniEnv, fdsArr, 1, (jint)fds[1]);
}
else res = -errcode;
#endif
JCGO_UNUSED_VAR(This);
return (jint)res;
#else
JCGO_UNUSED_VAR(pJniEnv);
JCGO_UNUSED_VAR(This);
JCGO_UNUSED_VAR(fdsArr);
return -EACCES;
#endif
}
#endif
#endif /* ! JCGO_EXCLUDE_VMPROCESS */
#endif