From a117dd391ce40a6f9bce4e14ea97b79bb7ed6d37 Mon Sep 17 00:00:00 2001 From: Piotr Strzelczyk Date: Fri, 14 Aug 2009 08:03:03 +0000 Subject: exe stubs consistency check, redundant copies of universal wrapper removed git-svn-id: svn://tug.org/texlive/trunk@14660 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/texk/texlive/runscript.c | 176 ++++++++++++++++++++++++++++++++ Build/source/texk/texlive/runscript.exe | Bin 0 -> 4096 bytes 2 files changed, 176 insertions(+) create mode 100644 Build/source/texk/texlive/runscript.c create mode 100755 Build/source/texk/texlive/runscript.exe (limited to 'Build') diff --git a/Build/source/texk/texlive/runscript.c b/Build/source/texk/texlive/runscript.c new file mode 100644 index 00000000000..bb06bc2d5d5 --- /dev/null +++ b/Build/source/texk/texlive/runscript.c @@ -0,0 +1,176 @@ +/* + +runscript.c + +Public Domain +Originally written 2009 by T.M.Trzeciak + +Batch script launcher: + +Runs a batch file of the same name in the same location or sets +TL_PROGNAME environment variable to its own name and calls +the default batch script. + +Rationale: + +Batch scripts are not as universal as binary executables, there +are some odd cases where they are not interchangeable with them. + +Usage: + +simply copy and rename the compiled binary + +Compilation: + +with gcc (size optimized): +gcc -Os -s -o runscript.exe runscript.c + +with tcc (ver. 0.9.24), extra small size +tcc -o runscript.exe runscript.c + +*/ + +#include +#include +#define IS_WHITESPACE(c) ((c == ' ') || (c == '\t')) +#define DEFAULT_SCRIPT "tl-w32-wrapper.cmd" +#define MAX_CMD 32768 +//#define DRYRUN + +static char dirname[MAX_PATH]; +static char basename[MAX_PATH]; +static char progname[MAX_PATH]; +static char cmdline[MAX_CMD]; + +int main( int argc, char *argv[] ) { + int i; + static char path[MAX_PATH]; + + // get file name of this executable and split it into parts + DWORD nchars = GetModuleFileNameA(NULL, path, MAX_PATH); + if ( !nchars || (nchars == MAX_PATH) ) { + fprintf(stderr, "runscript: cannot get own name or path too long\n"); + return -1; + } + // file extension part + i = strlen(path); + while ( i && (path[i] != '.') && (path[i] != '\\') ) i--; + strcpy(basename, path); + if ( basename[i] == '.' ) basename[i] = '\0'; //remove file extension + // file name part + while ( i && (path[i] != '\\') ) i--; + if ( path[i] != '\\' ) { + fprintf(stderr, "runcmd: no directory part in own name: %s\n", path); + return -1; + } + strcpy(dirname, path); + dirname[i+1] = '\0'; //remove file name, leave trailing backslash + strcpy(progname, &basename[i+1]); + + // find program to execute + if ( (strlen(basename)+4 >= MAX_PATH) || (strlen(dirname)+strlen(DEFAULT_SCRIPT) >= MAX_PATH) ) { + fprintf(stderr, "runscript: path too long: %s\n", path); + return -1; + } + // try .bat first + strcpy(path, basename); + strcat(path, ".bat"); + if ( GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES ) goto PROGRAM_FOUND; + // try .cmd next + strcpy(path, basename); + strcat(path, ".cmd"); + if ( GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES ) goto PROGRAM_FOUND; + // pass the program name through environment (generic launcher case) + if ( !SetEnvironmentVariableA("TL_PROGNAME", progname) ) { + fprintf(stderr, "runscript: cannot set evironment variable\n", path); + return -1; + } + // check environment for default command + /*if ( GetEnvironmentVariableA("TL_W32_WRAPPER", cmd, MAX_CMD) ) goto PROGRAM_FOUND;*/ + // use default script + strcpy(path, dirname); + strcat(path, DEFAULT_SCRIPT); + if ( GetFileAttributesA(path) == INVALID_FILE_ATTRIBUTES ) { + fprintf(stderr, "runscript: missing default script: %s\n", path); + return -1; + } + +PROGRAM_FOUND: + + if ( !cmdline[0] ) { + strcpy(cmdline, "\""); + strcat(cmdline, path); + strcat(cmdline, "\""); + } + + // get the command line for this process + char *argstr; + argstr = GetCommandLineA(); + if ( argstr == NULL ) { + fprintf(stderr, "runscript: cannot get command line string\n"); + return -1; + } + // skip over argv[0] (it can contain embedded double quotes if launched from cmd.exe!) + int argstrlen = strlen(argstr); + int quoted = 0; + for ( i = 0; ( i < argstrlen) && ( !IS_WHITESPACE(argstr[i]) || quoted ); i++ ) + if (argstr[i] == '"') quoted = !quoted; + // while ( IS_WHITESPACE(argstr[i]) ) i++; // arguments leading whitespace + argstr = &argstr[i]; + if ( strlen(cmdline) + strlen(argstr) >= MAX_CMD ) { + fprintf(stderr, "runscript: command line string too long:\n%s%s\n", cmdline, argstr); + return -1; + } + // pass through all the arguments + strcat(cmdline, argstr); + +#ifdef DRYRUN + printf("progname: %s\n", progname); + printf("dirname: %s\n", dirname); + printf("args: %s\n", &argstr[-i]); + for (i = 0; i < argc; i++) printf("argv[%d]: %s\n", i, argv[i]); + printf("cmdl: %s\n", cmdline); + return; +#endif + + // create child process + STARTUPINFOA si; // ANSI variant + PROCESS_INFORMATION pi; + ZeroMemory( &si, sizeof(si) ); + si.cb = sizeof(si); + si.dwFlags = STARTF_USESTDHANDLES;// | STARTF_USESHOWWINDOW; + //si.dwFlags = STARTF_USESHOWWINDOW; + //si.wShowWindow = SW_HIDE ; // can be used to hide console window (requires STARTF_USESHOWWINDOW flag) + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + ZeroMemory( &pi, sizeof(pi) ); + if( !CreateProcessA( + NULL, // module name (uses command line if NULL) + cmdline, // command line + NULL, // process security atrributes + NULL, // thread security atrributes + TRUE, // handle inheritance + 0, // creation flags, e.g. CREATE_NEW_CONSOLE, CREATE_NO_WINDOW, DETACHED_PROCESS + NULL, // pointer to environment block (uses parent if NULL) + NULL, // starting directory (uses parent if NULL) + &si, // STARTUPINFO structure + &pi ) // PROCESS_INFORMATION structure + ) { + fprintf(stderr, "runscript: cannot create process: %s\n", cmdline); + return -1; + } + CloseHandle( pi.hThread ); // thread handle is not needed + DWORD ret = 0; + if ( WaitForSingleObject( pi.hProcess, INFINITE ) == WAIT_OBJECT_0 ) { + if ( !GetExitCodeProcess( pi.hProcess, &ret) ) { + fprintf(stderr, "runscript: cannot get process exit code: %s\n", cmdline); + return -1; + } + } else { + fprintf(stderr, "runscript: failed to wait for process termination: %s\n", cmdline); + return -1; + } + CloseHandle( pi.hProcess ); + return ret; +} diff --git a/Build/source/texk/texlive/runscript.exe b/Build/source/texk/texlive/runscript.exe new file mode 100755 index 00000000000..a93ef24732b Binary files /dev/null and b/Build/source/texk/texlive/runscript.exe differ -- cgit v1.2.3