CASA/CASA-auth-token/server-java/package/windows/CommandLauncher/CommandLauncher.cpp

500 lines
12 KiB
C++

// CommandLauncher.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "CommandLauncher.h"
#include "string.h"
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <process.h>
#include <errno.h>
WCHAR ** G_rgArgs; // Command line arguments
int G_cArg; // Count of command line arguments
FILE * G_pf;
// Forward declarations of functions included in this code module:
int processArguments(LPTSTR lpCmdLine);
void freeArgs();
int countArgs(LPTSTR lpCmdLine);
int addArg(int iArg, LPTSTR lpString, int cChar);
void log(LPTSTR szMessage);
_TCHAR * errorMessage(int err);
int executeCommand( int cArg, _TCHAR* rgArg[]);
#define ERROR_NO_ERROR 0
#define ERROR_MEMORY_ALLOCATION_FAILED -1
#define ERROR_INVALID_NUMBER_OF_PARAMETERS -2
#define ERROR_EXEC_E2BIG -3
#define ERROR_EXEC_EACCES -4
#define ERROR_EXEC_EINVAL -5
#define ERROR_EXEC_EMFILE -6
#define ERROR_EXEC_ENOENT -7
#define ERROR_EXEC_ENOEXEC -8
#define ERROR_EXEC_ENOMEM -9
#define ERROR_EXEC_UNKNOWN -10
#define ERROR_STRCPY_FAILED -11
#define ERROR_JAVA_EXE_ARG_MISSING -12
#define ERROR_JAVA_CLASSPATH_OPTION_ARG_MISSING -13
#define ERROR_JAVA_CLASSPATH_ARG_MISSING -14
#define ERROR_BAD_COMMAND_LINE -15
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hInstance);
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(nCmdShow);
int rc;
_wfopen_s(&G_pf, L"C:\\CommandLauncher.log", L"a+");
// Process the command line
if (ERROR_NO_ERROR != (rc = processArguments(lpCmdLine)))
{
return rc;
}
rc = executeCommand(G_cArg, G_rgArgs);
log(errorMessage(rc));
fwprintf(G_pf, L"CommandLauncher: return = %d\n", rc);
fclose(G_pf);
return rc;
}
// <java exe path> -cp <classpath> class k1=v1 k2=k2
int processArguments(LPTSTR lpCmdLine)
{
int iArg;
int iChar;
int iAssignment;
int iClassStart;
int iClassEnd;
int iClassPathStart;
int iClassPathEnd;
int rc;
bool fClasspathOptionFound = false;
int iKeyStart;
int iValueEnd;
fwprintf( G_pf, L"current command line = %s\n", lpCmdLine);
// Validate the command line
if (NULL == lpCmdLine || (WCHAR)0 == *lpCmdLine)
{
return ERROR_BAD_COMMAND_LINE;
}
// Count the arguments on the command line. TThe name of this executable
// is not included in the count.
G_cArg = countArgs(lpCmdLine);
// Make sure we got enough to exec something. There must be at least the
// path to jave.exe, the classpath option, the classpath and a class.
if (G_cArg < 4)
{
return ERROR_INVALID_NUMBER_OF_PARAMETERS;
}
// Allocate an array of wide string for the arguments, add 1 for a NULL at
// the end of the array
G_rgArgs = (WCHAR**)malloc((G_cArg + 1) * sizeof(WCHAR *));
if (NULL == G_rgArgs)
{
return ERROR_MEMORY_ALLOCATION_FAILED;
}
// Null out the array
memset(G_rgArgs, 0, (G_cArg + 1) * sizeof(WCHAR *));
// Find the java.exe argument
iChar = 0;
for (iChar = 0; 0 != lpCmdLine[iChar + 4]; iChar++)
{
if (0 == _wcsnicmp(lpCmdLine + iChar, L".exe", 4))
{
break;
}
}
if (0 == lpCmdLine[iChar + 4])
{
rc = ERROR_JAVA_EXE_ARG_MISSING;
goto ErrorOut;
}
// Add the java.exe argument
if (ERROR_NO_ERROR != (rc = addArg(0, lpCmdLine, iChar + 4)))
{
goto ErrorOut;
}
// Move past the java.exe argument
iChar += 4;
// Move past any spaces
for (;L' ' == lpCmdLine[iChar]; iChar++)
{
// Intentionally left blank
}
// Find the classpath argument
for (; 0 != lpCmdLine[iChar + 3]; iChar++)
{
if (0 == _wcsnicmp(lpCmdLine + iChar, L"-cp", 3))
{
fClasspathOptionFound = true;
break;
}
}
if (!fClasspathOptionFound)
{
rc = ERROR_JAVA_CLASSPATH_OPTION_ARG_MISSING;
goto ErrorOut;
}
if (0 == lpCmdLine[iChar + 3])
{
rc = ERROR_JAVA_CLASSPATH_ARG_MISSING;
goto ErrorOut;
}
// Add the classpath option argument
if (ERROR_NO_ERROR != (rc = addArg(1, L"-cp", iChar + 3)))
{
goto ErrorOut;
}
// Move past the classpath option argument
iChar += 3;
// Move past any spaces
for (;L' ' == lpCmdLine[iChar]; iChar++)
{
// Intentionally left blank
}
// The classpath is next. It can have spaces in it so we need to work
// backards from the first key/value pair, or the end of the line if
// there are no key/value pairs.
iClassPathStart = iChar;
// Find the location of the next '='
for (; 0 != lpCmdLine[iChar] && L'=' != lpCmdLine[iChar]; iChar++)
{
// Intentially left blank
}
// If there was a key/value pair - move to the start of the key
if (L'=' == lpCmdLine[iChar])
{
iAssignment = iChar;
// Move back to the previous space. This should put us at the
// beginning of the first key/value pair. Assume that all args
// are property key/value pairs and property keys have no spaces.
for (; L' ' != lpCmdLine[iChar] && iChar >= 0; iChar--)
{
// Intentially left blank
}
}
else
{
iAssignment = 0;
iChar--;
}
// Move past any spaces (moving toward the start of the line)
for (;L' ' == lpCmdLine[iChar]; iChar--)
{
// Intentionally left blank
}
// This should put us at the end of the class to be executed
iClassEnd = iChar;
// Move to the previous space (moving toward the start of the line)
for (;L' ' != lpCmdLine[iChar]; iChar--)
{
// Intentionally left blank
}
iClassStart = iChar + 1;
// Add the class argument
if (ERROR_NO_ERROR != (rc = addArg(3, lpCmdLine + iClassStart, iClassEnd - iClassStart + 1)))
{
goto ErrorOut;
}
// Move past any spaces (moving toward the start of the line)
for (;L' ' == lpCmdLine[iChar]; iChar--)
{
// Intentionally left blank
}
// This should put us at the end of the classpath
iClassPathEnd = iChar;
// Add the class path argument
if (ERROR_NO_ERROR != (rc = addArg(2, lpCmdLine + iClassPathStart, iClassPathEnd - iClassPathStart + 1)))
{
goto ErrorOut;
}
// Are the any key/value pairs?
if (0 != iAssignment)
{
iArg = 4;
while (0 != lpCmdLine[iAssignment])
{
iKeyStart = iAssignment;
// Move back to the previous space. This should put us at the
// beginning of the current next key/value pair. Assume that all args
// are property key/value pairs and property keys have no spaces.
for (; L' ' != lpCmdLine[iKeyStart] && iKeyStart > 0; iKeyStart--)
{
// Intentially left blank
}
if (L' ' == lpCmdLine[iKeyStart])
{
iKeyStart++;
}
// Find the location of the next '='
iValueEnd = iAssignment + 1;
for (; 0 != lpCmdLine[iValueEnd] && L'=' != lpCmdLine[iValueEnd]; iValueEnd++)
{
// Intentially left blank
}
// If there was a property...
if (L'=' == lpCmdLine[iValueEnd])
{
iAssignment = iValueEnd;
// Move back to the previous space. This should put us at the
// beginning of the next key/value pair. Assume that all args
// are property key/value pairs and property keys have no spaces.
for (; L' ' != lpCmdLine[iValueEnd] && iValueEnd >= 0; iValueEnd--)
{
// Intentially left blank
}
}
else
{
// We have reached the end of the command line - back off from the
// null terminator.
iAssignment = iValueEnd;
iValueEnd--;
}
// Move thorugh any spaces
for (; L' ' == lpCmdLine[iValueEnd] && iValueEnd >= 0; iValueEnd--)
{
// Intentially left blank
}
// Add the key/value pair
if (ERROR_NO_ERROR != (rc = addArg(iArg, lpCmdLine + iKeyStart, iValueEnd - iKeyStart + 1)))
{
goto ErrorOut;
}
// Go on to the next arg
iArg++;
}
}
return ERROR_NO_ERROR;
ErrorOut:
freeArgs();
log(errorMessage(rc));
return rc;
}
void freeArgs()
{
int iArg;
if (NULL != G_rgArgs)
{
for (iArg = 0; iArg < G_cArg; iArg++)
{
if (NULL != G_rgArgs[iArg])
{
free(G_rgArgs[iArg]);
G_rgArgs[iArg] = NULL;
}
}
free(G_rgArgs);
G_rgArgs = NULL;
}
}
int countArgs(LPTSTR lpCmdLine)
{
int cArgument;
// Check if the exe to execute is the only argument. Assume that all additional
// arguments have an '=' in them.
for (cArgument = 4; *lpCmdLine != (WCHAR)0; lpCmdLine++)
{
if (*lpCmdLine == L'=')
{
cArgument++;
}
}
return cArgument;
}
int addArg(int iArg, LPTSTR lpString, int cChar)
{
int cb = (cChar + 3) * sizeof(WCHAR); // count of bytes
// Allocate space for the new arg
G_rgArgs[iArg] = (WCHAR *)malloc(cb);
if (NULL == G_rgArgs[iArg])
{
return ERROR_MEMORY_ALLOCATION_FAILED;
}
// Null out the argument
memset(G_rgArgs[iArg], 0, cb);
// Add a starting quote
// G_rgArgs[iArg][0] = L'\"';
// Copy the arg
if (0 != wcsncpy_s(G_rgArgs[iArg], cChar + 1, lpString, cChar))
{
return ERROR_STRCPY_FAILED;
}
// Add a terminating quote
// G_rgArgs[iArg][cb-1] = L'\"';
return ERROR_NO_ERROR;
}
void log(LPTSTR szMessage)
{
LPTSTR szT = L"";
if (NULL == szMessage)
szMessage = szT;
fwprintf(G_pf, L"JavaLauncher: %s\n", szMessage);
}
_TCHAR * errorMessage(int err)
{
switch (err)
{
case ERROR_NO_ERROR:
return L"No error\n";
case ERROR_MEMORY_ALLOCATION_FAILED:
return L"Memory allocation failed\n";
case ERROR_INVALID_NUMBER_OF_PARAMETERS:
return L"Invalid number of parameters\n";
case ERROR_EXEC_E2BIG:
return L"_exec: The space required for the arguments and environment settings exceeds 32 KB.\n";
case ERROR_EXEC_EACCES:
return L"_exec: The specified file has a locking or sharing violation.\n";
case ERROR_EXEC_EINVAL:
return L"_exec: Invalid parameter.\n";
case ERROR_EXEC_EMFILE:
return L"_exec: Too many files open (the specified file must be opened to determine whether it is executable).\n";
case ERROR_EXEC_ENOENT:
return L"_exec: The file or path not found.\n";
case ERROR_EXEC_ENOEXEC:
return L"_exec: The specified file is not executable or has an invalid executable-file format.\n";
case ERROR_EXEC_ENOMEM:
return L"_exec: Not enough memory is available to execute the new process; the available memory has been corrupted; or an invalid block exists, indicating that the calling process was not allocated properly.\n";
case ERROR_EXEC_UNKNOWN:
return L"Unknown _exec error.\n";
case ERROR_STRCPY_FAILED:
return L"String copy failed.\n";
case ERROR_JAVA_CLASSPATH_OPTION_ARG_MISSING:
return L"Classpath option \"-cp\" missing\n";
case ERROR_JAVA_CLASSPATH_ARG_MISSING:
return L"Classpath argument missing\n";
case ERROR_BAD_COMMAND_LINE:
return L"Bad command line\n";
default:
return L"Unknown error.\n";
}
}
int executeCommand( int cArg, _TCHAR* rgArg[] )
{
int i; // Looping variable
int rc = ERROR_NO_ERROR; // Return code
fwprintf( G_pf, L"Arg count = %d\n", cArg);
for (i = 0; i < cArg; i++)
{
fwprintf(G_pf, L"rgArg[%d] (%s)\n", i, rgArg[i]);
}
// exec the command
// if (-1 == _wexecv( rgArg[0], rgArg))
if (-1 == _wspawnv(_P_WAIT, rgArg[0], rgArg))
{
switch (errno)
{
case E2BIG: // The space required for the arguments and environment settings exceeds 32 KB.
rc = ERROR_EXEC_E2BIG;
break;
case EACCES: // The specified file has a locking or sharing violation.
rc = ERROR_EXEC_EACCES;
break;
case EINVAL: // Invalid parameter.
rc = ERROR_EXEC_EINVAL;
break;
case EMFILE: // Too many files open (the specified file must be opened to determine whether it is executable).
rc = ERROR_EXEC_EMFILE;
break;
case ENOENT: // The file or path not found.
rc = ERROR_EXEC_ENOENT;
break;
case ENOEXEC: // The specified file is not executable or has an invalid executable-file format.
rc = ERROR_EXEC_ENOEXEC;
break;
case ENOMEM: // Not enough memory is available to execute the new process; the available memory has been
// corrupted; or an invalid block exists, indicating that the calling process was not allocated
// properly.
rc = ERROR_EXEC_ENOMEM;
break;
default:
rc = ERROR_EXEC_UNKNOWN;
break;
}
}
fwprintf(G_pf, L"ExecuteCommand returning %d\n", rc);
return rc;
}