summaryrefslogtreecommitdiff
path: root/scripts/context/stubs/source/mtxrun_dll.c
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/context/stubs/source/mtxrun_dll.c')
-rw-r--r--scripts/context/stubs/source/mtxrun_dll.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/scripts/context/stubs/source/mtxrun_dll.c b/scripts/context/stubs/source/mtxrun_dll.c
new file mode 100644
index 000000000..6cac18c9b
--- /dev/null
+++ b/scripts/context/stubs/source/mtxrun_dll.c
@@ -0,0 +1,214 @@
+/*
+
+Copyright:
+
+The originally 'runscript' program was written by in 2009 by
+T.M.Trzeciak and is public domain. This derived mtxrun program
+is an adapted version by Hans Hagen.
+
+Comment:
+
+In ConTeXt MkIV we have two core scripts: luatools.lua and
+mtxrun.lua where the second one is used to launch other scripts.
+Normally a user will use a call like:
+
+mtxrun --script font --reload
+
+Here mtxrun is a lua script. In order to avoid the usage of a cmd
+file on windows this runner will start texlua directly. In TeXlive
+a runner is added for each cmd file but we don't want that overhead
+(and extra files). By using an exe we can call these scripts in
+batch files without the need for using call.
+
+We also don't want to use other runners, like those that use kpse
+to locate the script as this is exactly what mtxrun itself is doing
+already. Therefore the runscript program is adapted to a more direct
+approach suitable for mtxrun.
+
+Compilation:
+
+with gcc (size optimized):
+
+gcc -Os -s -shared -o mtxrun.dll mtxrun_dll.c
+gcc -Os -s -o mtxrun.exe mtxrun_exe.c -L./ -lmtxrun
+
+with tcc (ver. 0.9.24), extra small size
+
+tcc -shared -o runscript.dll runscript_dll.c
+tcc -o runscript.exe runscript_exe.c runscript.def
+
+*/
+
+#include <windows.h>
+#include <stdio.h>
+
+#define IS_WHITESPACE(c) ((c == ' ') || (c == '\t'))
+#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];
+
+__declspec(dllexport) int dllrunscript( 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, "mtxrun: unable to determine a valid own name\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, "mtxrun: the runner has no directory part in its 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)+100 >= MAX_PATH) ) {
+ fprintf(stderr, "mtxrun: the runners path is too long: %s\n", path);
+ return -1;
+ }
+
+ // check .lua
+
+ strcpy(path, dirname);
+ strcat(path, "mtxrun.lua");
+
+ if ( GetFileAttributesA(path) != INVALID_FILE_ATTRIBUTES ) {
+ goto PROGRAM_FOUND;
+ } else {
+ fprintf(stderr, "mtxrun: the mtxrun.lua file is not in the same path\n");
+ return -1;
+ }
+
+PROGRAM_FOUND:
+
+ strcpy(cmdline,"texlua.exe ");
+
+ if ( ( strcmp(progname,"mtxrun") == 0 ) || ( strcmp(progname,"luatools") == 0 ) ) {
+ strcat(cmdline, dirname);
+ strcat(cmdline,progname);
+ strcat(cmdline, ".lua");
+ } else if ( ( strcmp(progname,"texmfstart") == 0 ) ) {
+ strcat(cmdline, dirname);
+ strcat(cmdline,"mtxrun.lua");
+ } else {
+ strcat(cmdline, dirname);
+ strcat(cmdline, "mtxrun.lua --script ");
+ strcat(cmdline,progname);
+ }
+
+ // get the command line for this process
+
+ char *argstr;
+ argstr = GetCommandLineA();
+ if ( argstr == NULL ) {
+ fprintf(stderr, "mtxrun: fetching the command line string fails\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, "mtxrun: the command line string is 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("arguments : %s\n", &argstr[-i]);
+ for (i = 0; i < argc; i++) {
+ printf("argv[%d] : %s\n", i, argv[i]);
+ }
+ printf("commandline : %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 attributes
+ NULL, // thread security attributes
+ 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, "mtxrun: unable to create a process for: %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, "mtxrun: unable to fetch the exit code for process: %s\n", cmdline);
+ return -1;
+ }
+ } else {
+ fprintf(stderr, "mtxrun: the script has been terminated unexpectedly: %s\n", cmdline);
+ return -1;
+ }
+ CloseHandle( pi.hProcess );
+
+ return ret;
+
+}