diff options
Diffstat (limited to 'Master/bin/win32/runscript.tlu')
-rwxr-xr-x | Master/bin/win32/runscript.tlu | 947 |
1 files changed, 0 insertions, 947 deletions
diff --git a/Master/bin/win32/runscript.tlu b/Master/bin/win32/runscript.tlu deleted file mode 100755 index 5140e9af1af..00000000000 --- a/Master/bin/win32/runscript.tlu +++ /dev/null @@ -1,947 +0,0 @@ - - -local svnrevision = string.match("$Revision$", "%d+") or "0" -local svndate = string.match("$Date$", "[-%d]+") or "2009-12-04" -local bannerstr = "runscript wrapper utility (rev. " .. - svnrevision .. ", " .. svndate .. ")\n" .. - "usage: runscript script-name [arguments]\n" .. - "try -help [-v] for more information" - -local helpstr = [[ - - Script wrappers in TeX Live on Windows - - Rationale - - Wrappers enable use of scripts on Windows as regular programs. - They are also required for some binary programs to set up the - right environment for them. - - Batch scripts can be used for wrapping but they are not as universal - as binaries (there are some odd cases where they don't work) and - it is hard to make them robust and secure. Compiled binary wrappers - don't suffer from these problems but they are harder to write, debug - and maintain in comparison to scripts. For these reasons a hybrid - approach is taken that combines a binary stub with a launcher script. - - Adding wrappers for user scripts - - The script wrapping machinery is not limited to scripts shipped with - TeX Live. You can also use it for script programs from manually - installed packages. This should minimize problems when using them - with TeX Live. - - First, make sure that there is an interpreter program available - on your system for the script you want to use. Interpreters for - Perl, Lua and Tcl/Tk (GUI scripts only) are bundled with TeX - Live, all others have to be installed independently. Lua - scripts are the most efficient to run, so if you consider - writing a new script, that would be the recommended choice. - - The following script types and their file extensions are currently - supported and searched in that order: - - Lua (.tlu;.texlua;.lua) -- included - Perl (.pl) -- included - Ruby (.rb) -- requires installation - Python (.py) -- requires installation - Tcl (.tcl) -- included (GUI scripts only) - Java (.jar) -- requires installation - VBScript (.vbs) -- part of Windows - JScript (.js) -- part of Windows - Batch (.bat;.cmd) -- part of Windows - - Finally, Unix-style extensionless scripts are searched as last and - the interpreter program is established based on the she-bang (#!) - specification on the very first line of the script. This can be - an arbitrary program but it must be present on the search path. - - Next, the script program needs to be installed somewhere below the - 'scripts' directory under one of the TEXMF trees (consult the - documentation or texmf/web2c/texmf.cnf file for a list). You may - need to update the file search database afterwards with: - - mktexlsr [TEXMFDIR] - - It is also possible to use scripts that are outside of TEXMF hierarchy - by adjusting TEXMFSCRIPTS environment or kpathsea variable, see - kpathsea documentation for more information on setting its variables. - - Test if the script can be located with: - - kpsewhich --format=texmfscripts <script-name>.<ext> - - This should output the full path to the script if everything is - properly installed and configured. If this test is successful, - the script can be run immediately with: - - runscript <script-name> [script arguments] - - If you prefer to call the script program simply by its name, copy - and rename bin/win32/runscript.exe (or bin/win64/runscript.exe for - 64-bit Windows) to <script-name>.exe and put it somewhere on the - search path.]] - -local docstr = [[ - - Wrapper structure - - Wrappers consist of small binary stubs and a common texlua script. - The binary stubs are all the same, just different names (but CLI - and GUI stubs differ, see below, and GUI stubs are actually all - different due to different embedded icons). - - The job of the binary stub is twofold: (a) call the texlua launcher - script 'runscript.tlu' from the same directory (or more precisely - from the directory containing 'runscript.dll') and (b) pass to it - argv[0] and the unparsed argument string as the last two arguments - (after adding a sentinel argument, which ends with a new line - character). Arbitrary C strings can be passed, because the script - is executed by linking with luatex.dll and calling the lua - interpreter internally rather than by spawning a new process. - - There are two flavours of the binary stub: one for CLI programs - and another one for GUI programs. The GUI variant does not open - a console window nor does it block the command prompt if started - from there. It also uses a dialog box to display an error message - in addition to outputting to stderr. - - The stubs are further split into a common DLL and EXE proxies - to it. This is for maintenance reasons - updates can be done by - replacement of a single DLL rather than all binary stubs. - - The launcher script knows, which variant has been used to invoke it - based on the sentinel argument. The lack of this argument means - that it was invoked in a standard way, i.e., through texlua.exe. - - All the hard work of locating a script/program to execute happens - in the launcher script. The located script/program is always - executed directly by spawning its interpreter (or binary) in a new - process. The system shell (cmd.exe) is never called (except for - batch scripts, of course). If the located script happens to be - a (tex)lua script, it is loaded and called internally from within - this script, i.e. no new process is spawned. Execution is done - using a protected call, so any compile or runtime errors are caught. - - Source files - - runscript.tlu launcher script for locating and dispatching - target scripts/programs - runscript_dll.c common DLL part of the binary stubs; locates and - calls the launcher script - runscript_exe.c EXE proxy to the common DLL for CLI mode stubs - wrunscript_exe.c EXE proxy to the common DLL for GUI mode stubs - - Compilation of binaries (requires luatex.dll in the same directory) - - with gcc (size optimized): - - gcc -Os -s -shared -o runscript.dll runscript_dll.c -L./ -lluatex - gcc -Os -s -o runscript.exe runscript_exe.c -L./ -lrunscript - gcc -mwindows -Os -s -o wrunscript.exe wrunscript_exe.c -L./ -lrunscript - - with tcc (extra small size): - - tiny_impdef luatex.dll - tcc -shared -o runscript.dll runscript_dll.c luatex.def - tcc -o runscript.exe runscript_exe.c runscript.def - tcc -o wrunscript.exe wrunscript_exe.c runscript.def - - License - - Originally written in 2009 by Tomasz M. Trzeciak, Public Domain. - - Prior work: - 'tl-w32-wrapper.texlua' by Reinhard Kotucha and Norbert Preining. - 'tl-w32-wrapper.cmd' by Tomasz M. Trzeciak. - - Changelog - - 2009/12/04 - - initial version - 2009/12/15 - - minor fixes for path & extension list parsing - 2010/01/09 - - added support for GUI mode stubs - 2010/02/28 - - enable GUI mode stubs for dviout, psv and texworks; - - added generic handling of sys programs - - added restricted repstopdf to alias_table - 2010/03/13 - - added 'readme.txt' and changelog - - added support and docs for calling user added scripts; - (use path of 'runscript.dll' instead of .exe stub to - locate 'runscript.tlu' script) - - limit search for shell_escape_commands to system trees - - added function for creating directory hierarchy - - fixed directory creation for dviout & texworks aliases - - fixed arg[0] of repstopdf & rpdfcrop - 2010/03/28 - - restructured docs, added --help and --version options - (available only when invoked under 'runscript' name) - - use TEXMF_RESTRICTED_SCRIPTS kpse var for searching - shell_escape_commands - - changed command validation to handle a list of commands - - prepend GUI mode command(s) to the command list - - added support for .tcl scripts - 2010/03/31 - - fixed fatal bug in extention_map definition for GUI mode - 2010/04/15 - - encapsulated main chunk in a function to execute with - pcall for more robustness and better error catching - - added texdoctk to scripts4tlperl table - - added tlgs and tlperl to alias_table; callable as e.g.: - runscript tlperl ... - - doc tweaks - 2010/04/22 - - ensure only backslash is used in USERPROFILE variable - (Adobe Reader crash case) - - fixed argument processing for direct execution under texlua - - more doc tweaks - 2010/05/30 - - Windows XP or newer required to run TeXworks - 2010/06/04 - - added support for Perl scripts starting with eval-exec-perl - construct in place of she-bang (#!) - 2010/06/25 - - run internal tlperl only with our Perl - - added fontinst to alias_table - - added support for all tex4ht commands from mk4ht.pl - - removed some unsued aliases - - some code refactoring and cleanup - 2010/12/28 - - use of external Perl now requires kpathsea variable - TEXLIVE_WINDOWS_TRY_EXTERNAL_PERL to be explicitly set to 1 - - alias_table replaced with if-elseif-end tests to streamline - special cases and to avoid hardcoding of texmf* file paths - - added a2ping to special cases (requires -x switch to Perl) - - set ASYMPTOTE_GS (for asy) to full path to tlgs - 2011/01/09 - - removed tex4ht commands starting with ht from mk4ht aliases; - they have their own scripts and mk4ht calls them internally, - so aliasing results in an infinite recursion - - removed alias for fontinst (no fontinst.exe any more) - - fixed GUI-mode interpreter for Ruby - 2011/09/10 - - added -dDisableFAPI=true to psview argument list. Needed by - gs-9.xx - 2012/03/12 - - added '-i', '.' to psview argument list (author's request) - - added environment clean up from Perl specific variables - (when not using external Perl) - 2012/08/05 - - added alias for fmtutil - 2013/05/09 - - added alias mkluatexfontdb -> luaotfload-tool - 2013/07/03 - - fix for psview and UNC paths in unix-style - - remove not needed is_abs_path function - 2013/08/07 - - handle updmap-sys via updmap --sys - 2013/08/08 - - allow overriding gs/gs_dll/gs_lib with kpse variables - TEXLIVE_WINDOWS_EXTERNAL_GS, ..._GS_LIB, ..._GS_DLL - 2013/08/30 - - do not pass -NULL to dviout, to allow users changing and - saving settings. Patch by Yusuke KUROKI - 2013/09/22 - - add TEXMFDIST/fonts to the GS_LIB path. Patch by Yusuke KUROKI - 2014/04/30 - - fix for argument duplication in fmtutil - 2015/04/12 - - handle fmtutil-sys via fmtutil --sys - 2015/09/10 - - more slash flipping for the sake of vbscript and unc paths - 2015/12/11 - - fix spurious arguments for updmap and fmtutil - 2016/04/22 - - Warning if external perl is requested but missing - 2017/04/22 (exactly one year later ;-) - - Cater for fmtutil-user and updmap-user => -user arg - 2017/04/24 - - GS_LIB setting for tlgs. - 2017/05/06 - - introduce sys_user_progs, make checks for updmap/fmtutil - use sys_user_progs instead, add kanji-config-updmap - 2018/03/12 - - introduce a new function gettexmfdist() for security. - 2018/04/06 - - introduce a new function is_64bit_windows_os() to - check Windows OS. - 2018/06/20 - - support also scripts in trees other than TEXMFDIST: - https://tug.org/pipermail/tex-live/2018-June/041922.html - 2018/10/10 - - support cluttex scripts - 2018/11/08 - - use included tcltk interpreter - -]] - --- HELPER SUBROUTINES -- - -local TEXDIR -local guimode - -local function show_error(msg) - if guimode then - local err_cmd - os.setenv('RUNSCRIPT_ERROR_MESSAGE', msg) - local errmess_path = TEXDIR .. '/texmf-dist/scripts/texlive/tl-errmess.vbs' - local err_cmd = {"wscript", errmess_path:gsub('/','\\')} - if lfs.isfile(errmess_path) then - os.spawn(err_cmd) - elseif lfs.isfile(TEXDIR..'/tlpkg/tltcl/tclkit.exe') and - lfs.isfile(TEXDIR..'/tlpkg/tltcl/gui_err.tcl') then - os.spawn{TEXDIR..'/tlpkg/tltcl/tclkit.exe', - TEXDIR..'/tlpkg/tltcl/gui_err.tcl'} - end - else - io.stderr:write(msg, '\n') - end -end - --- quotes string with spaces -local function _q(str) - str = string.gsub(str, '"', '') -- disallow embedded double quotes - return string.find(str, "%s") and '"'..str..'"' or str -end - --- prepends directories to path if they are not already there -local function prepend_path(path, ...) - local pathcmp = string.lower(string.gsub(path, '/', '\\'))..';' - for k = 1, select('#', ...) do - local dir = string.lower(string.gsub(select(k, ...), '/', '\\'))..';' - if not string.find(pathcmp, dir, 1, true) then path = dir..path end - end - return path -end - --- searches the PATH for a file -local function search_path(fname, PATH, PATHEXT) - if string.find(fname, '[/\\]') then - return nil, "directory part not allowed for PATH search: "..fname - end - PATH = PATH or os.getenv('PATH') - PATHEXT = PATHEXT or '\0' -- '\0' for no extension - for dir in string.gmatch(PATH, '[^;]+') do - local dirsep = (string.find(dir, '\\') and '\\' or '/') - for ext in string.gmatch(PATHEXT, '[^;]+') do - local f = dir..dirsep..fname..ext - if lfs.isfile(f) then return f, ext end - end - end - return nil, "file or program not on PATH: "..fname -end - --- tests for tex4ht command (as given in mk4ht.pl) --- except for commands starting with 'ht' (they have their own scripts) -local function is_tex4ht_command(progname) - local prefixes = 'xh uxh xhm mz oo es js jm tei teim db dbm w jh jh1' - local formats = 'context latex tex texi xelatex xetex' - for p in string.gmatch(prefixes, '%S+') do - for q in string.gmatch(formats, '%S+') do - if (progname == p..q) then - -- we have a hit, but not all combinations are valid - return (p ~= 'teim' and p ~= 'dbm') or (q ~= 'xelatex' and q~= 'xetex') - end - end - end - return false -end - --- checks whether an item is in an array -local function contains (tab, val) - for index, value in ipairs(tab) do - if value == val then - return true - end - end - return false -end - --- locates texmfscript to execute -local function find_texmfscript(progname, ext_list) - ext_list = ext_list or '\0' - for ext in string.gmatch(ext_list, '[^;]+') do - local progfullname = kpse.find_file(progname..ext, 'texmfscripts') - if progfullname then return progfullname, ext end - end - return nil, "no appropriate script or program found: "..progname -end - --- converts the #! line to arg table --- used for scripts w/o extension --- only the two most common cases are considered: --- #! /path/to/command [options] --- #! /usr/bin/env command [options] --- ([options] after the command are retained as well) -local function shebang_to_argv(progfullname) - local fid, errmsg = io.open(progfullname, 'r') - if not fid then return nil, errmsg end - local fstln = fid:read('*line') - fid:close() - if string.find(fstln, "eval.*exit.*exec.*perl") then - -- special case of Perl's time-honoured "totally devious construct": - -- eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' && eval 'exec perl -S $0 $argv:q' - return {"perl"} - elseif (string.sub(fstln, 1, 2) ~= '#!') then - return nil, "don't know how to execute script: "..progfullname - end - local argv = string.explode( string.sub(fstln, 3) ) -- split on spaces - argv[1] = string.match(argv[1], '[^/]+$') - if (argv[1] == 'env') then table.remove(argv, 1) end - return argv -end - --- checks if command exists on the path and returns its full path -local function check_command(cmdlist, PATH) - for cmd in string.gmatch(cmdlist, '%S+') do - local cmdext = cmd..(string.find(cmd, '%.[^\\/.]*$') and '' or '.exe') - local fullcmd = search_path(cmdext, PATH) - if fullcmd then - return fullcmd, cmd - end - end - return nil, 'program not found (not part of TeX Live): '..cmdlist -end - --- creates directory or directory hierarchy -local function mkdir_plus(dir) - if lfs.mkdir(chgstrcp.syscptoutf8(dir)) then - return true - end - -- try with system's mkdir in case we need to create intermediate dirs too - local ret = os.spawn({[0]=search_path("cmd.exe"), - string.format('cmd.exe /x /c mkdir "%s"', dir)}) - if ret == 0 then - return true - else - return nil, string.format("cannot create directory (error code %d): %s", ret, dir) - end -end - --- --- return the TEXMFDIST directory in TeX Live --- -local function gettexmfdist() - local ffi = require("ffi") - ffi.cdef[[ - typedef void* HANDLE; - typedef char* LPCSTR; - int GetModuleFileNameA(HANDLE h, LPCSTR l, int i); - HANDLE GetModuleHandleA(const char *a); - ]] - local buffer = ffi.new("char[?]", 512) - local runscripthandle = ffi.C.GetModuleHandleA("runscript.dll") - if runscripthandle == nil then - return nil - end - local err = ffi.C.GetModuleFileNameA(runscripthandle, buffer, 256) - if err == 0 then - return nil - end - local str = ffi.string(buffer) - str = string.gsub(str, "\\","/") - str = string.reverse(str) - local a, b --- remove '/runscript.dll' - a, b = string.find(str, '/', 1, true) - str = string.sub(str,a+1) --- remove '/win32' - a, b = string.find(str, '/', 1, true) - str = string.sub(str,a+1) --- remove '/bin' - a, b = string.find(str, '/', 1, true) - str = string.sub(str,a+1) - str = string.reverse(str) - str = str .. '/texmf-dist' - return str -end - --- --- Is the Windows OS 64bit? --- -local function is_64bit_windows_os() - local return_val = false - -- 32 bit binaries always work, thus the default is false - local architecture = os.getenv('PROCESSOR_ARCHITECTURE') - if architecture ~= nil then - if architecture == 'x86' then - local is_wow64 = os.getenv('PROCESSOR_ARCHITEW6432') - if is_wow64 == nil then - return_val = false - else - return_val = true - end - else - return_val = true - end - end - return return_val -end - --- MAIN_CHUNK -- encapsulated in a function for more robust execution with pcall - -local function MAIN_CHUNK() - ---[[ - -OVERVIEW OF MAIN_CHUNK - -We start out with a lot of housekeeping, especially with respect to -perl and ghostscript: if we are going to use the built-in versions, -then the search path and other environment variables must be set or -unset to make these findable and working right. - -Next we compose an ARGV table for os.spawn, unless the script turns -out to be a [tex]lua script; see further down this comment block. - -The parameter table ARGV can have the following elements (see the -luatex manual on os.exec and os.spawn): - -- ARGV[0]: the full path to the interpreter -- ARGV[1]: the filename part of the interpreter. The interpreter choice - depends on the detected script extension and also on gui mode. -- ARGV[2]: progfulname, the full path to the script -- ARGV[3]: argline, i.e. the unparsed arguments for the script. - This is normally the last argument passed to runscript.tlu. - See the actual code for when this is not the case. - -ARGV[0] gets priority over ARGV[1] if it is present. - -After everything has been set up, a call os.spawn(ARGV) runs the -right program with the right arguments. - -But in case the script to be run is a texlua script, we run the script -in the current texlua process using the dofile function. The original arg -argument table may have been modified before then. - -Some variables: - -- ARGV, see above -- arg, the texlua argument table of runscript.tlu -- progname, the name under which [w]runscript.exe was called -- progfullname, the full path of the script to be run. This variable - is introduced only after some special cases have been dealt with. -- argline, unparsed arguments to the script; may get modified - ---]] - --- set the system-default value for LC_CTYPE --- http://tug.org/pipermail/tex-live/2018-May/041628.html -os.setlocale("", "ctype") - --- preprocess arguments: arg[-1] => texlua.exe, arg[0] => scriptname - --- guimode already declared local -guimode = false -local argline = '' --- check for the sentinel argment coming from the .exe stub -if arg[#arg-2] and ( string.sub(arg[#arg-2], -1) == '\n' ) then - -- argv[0] and unparsed argument line are passed - -- from the .exe stub as the two last arguments - -- pop them up from the arg table - argline = table.remove(arg) -- pop unparsed arguments - arg[0] = table.remove(arg) -- pop C stub's argv[0] - guimode = (table.remove(arg) == 'GUI_MODE\n') -- pop sentinel argument -else - -- we must be called as: texlua runscript.tlu progname ... - -- this is treated the same as: runscript[.exe] progname ... - -- we don't have the unparsed arument line in this case, so construct one - for k = #arg, 1, -1 do argline = _q(arg[k]) .. ' ' .. argline end -end - --- program name - --- lower arg[0] : get file name part : remove extension -local progname, substcount = string.lower(arg[0]):gsub('^.*[\\/]', ''):gsub('%.[^.]*$', '') --- special behaviour when called under 'runscript' name -if (progname == 'runscript') then - -- we are called as: runscript progname ... - -- or as: runscript --help|-h|--version ... - -- handle options first (only --help and --version) - local opt, param = {}, nil - while true do - -- remove the first argument from the arg table and from the argline string - -- (this argument should have no embedded spaces!) - param = table.remove(arg, 1) - if not param then break end - argline = string.gsub(argline, '^%S+%s*', '') - local optname = string.lower(param):match('^%-%-?(.*)$') - if not optname then - break - elseif (optname == 'h') or (optname == 'help') then - opt.help = true - elseif (optname == 'v') then - opt.v = true - elseif (optname == 'version') then - opt.version = true - else - error("unknown option: "..param.."\n"..bannerstr) - end - end - if opt.help then - print(helpstr) - if opt.v then print(docstr) end - os.exit(0) - elseif opt.version or opt.v then - print(bannerstr) - os.exit(0) - end - -- make sure progname is valid - arg[0] = assert(param, "not enough arguments!\n"..bannerstr) - progname = string.lower(arg[0]):gsub('^.*[\\/]', ''):gsub('%.[^.]*$', '') - assert(progname == string.lower(arg[0]), "bad command name: " .. arg[0]) -end --- special case of sys programs -progname, substcount = string.gsub(progname, '%-sys$', '') -local sysprog = (substcount > 0) -- true if there was a -sys suffix removed --- special case of user programs --- we do not guard against programs foobar-user-sys ... we don't ship them -progname, substcount = string.gsub(progname, '%-user$', '') -local userprog = (substcount > 0) -- true if there was a -user suffix removed --- prevent recursive calls to this script -assert(progname ~= 'runscript', "oops! wrapping the wrapper?") - - --- kpse and environment set-up - --- init kpathsea -local k = -1 -while arg[k-1] do k = k - 1 end -- in case of a call: luatex --luaonly ... -local lua_binary = arg[k] -kpse.set_program_name(lua_binary, progname) - --- various dir-vars --- TEXDIR already declared local -TEXDIR = kpse.var_value('SELFAUTOPARENT') --- local TEXMFDIST = kpse.var_value('TEXMFDIST') --- use a new function to obtain TEXMFDIST -local TEXMFDIST = gettexmfdist() -if TEXMFDIST == nil then - TEXMFDIST = kpse.var_value('TEXMFDIST') -end -local BINDIR = kpse.var_value('SELFAUTOLOC') -local PATH = os.getenv('PATH') or '' - --- list of programs that have -sys and -user variants -local sys_user_progs = { 'updmap', 'fmtutil', 'kanji-config-updmap' } - --- restricted programs -local shell_escape_commands = string.lower(kpse.var_value('shell_escape_commands') or '') -local is_restricted_progname = string.find( ','..shell_escape_commands..',', - ','..progname..',', 1, true) -if is_restricted_progname then - -- limit search path to the restricted (system) trees - -- (not really necessary for entries in the alias_table, - -- because they are not searched for with kpathsea) - os.setenv('TEXMFSCRIPTS', kpse.var_value('TEXMF_RESTRICTED_SCRIPTS')) -end --- perl stuff -local scripts4tlperl = { - tlperl = true, - updmap = true, - fmtutil = true, - ['updmap-sys'] = true, - ['fmtutil-sys'] = true, -} -local try_extern_perl = (kpse.var_value('TEXLIVE_WINDOWS_TRY_EXTERNAL_PERL') == '1') and - not (is_restricted_progname or scripts4tlperl[progname]) -local PERLEXE = try_extern_perl and search_path('perl.exe', PATH) -local extperl_warn -if not PERLEXE then - if try_extern_perl then extperl_warn = [[ -External Perl missing or outdated. Please install a recent Perl, or configure -TeX Live to always use the builtin Perl: - tlmgr conf texmf TEXLIVE_WINDOWS_TRY_EXTERNAL_PERL 0 -Meanwhile, continuing with built-in Perl... -]] - end -- if try_extern_perl - PERLEXE = TEXDIR..'/tlpkg/tlperl/bin/perl.exe' - os.setenv('PERL5LIB', TEXDIR..'/tlpkg/tlperl/lib') - PATH = prepend_path(PATH, TEXDIR..'/tlpkg/tlperl/bin') - local PERLENV = 'PERL5OPT;PERLIO;PERLIO_DEBUG;PERLLIB;PERL5DB;PERL5DB_THREADED;' .. - 'PERL5SHELL;PERL_ALLOW_NON_IFS_LSP;PERL_DEBUG_MSTATS;' .. - 'PERL_DESTRUCT_LEVEL;PERL_DL_NONLAZY;PERL_ENCODING;PERL_HASH_SEED;' .. - 'PERL_HASH_SEED_DEBUG;PERL_ROOT;PERL_SIGNALS;PERL_UNICODE' - for var in string.gmatch(PERLENV, '[^;]+') do os.setenv(var, nil) end -end --- gs stuff -local override_gs -if not is_restricted_progname then - override_gs = kpse.var_value('TEXLIVE_WINDOWS_EXTERNAL_GS') -end --- the full path to the executable -local GSEXE --- the directory where the gs executable resides -local GSDIR --- the name of the gs executable -local GSNAME -if override_gs then - -- first check whether we got an absolute path or only executable name - if string.find(override_gs, '[/\\]') then - GSEXE = override_gs - else - -- search in the path - GSEXE = search_path(override_gs, PATH) - end -end -if GSEXE then - -- split the dir and progname part so that we can set the path - -- work on a string with all forward slashes - local foo = string.lower(string.gsub(GSEXE, '\\', '/')) - GSNAME = string.gsub(foo, '^.*[\\/]', '') - GSDIR = string.gsub(foo, '^(.*)[\\/].*$', '%1') - -- search also for a GS_DLL setting - -- we do not need to check for is_restricted_progname, since - -- GSEXE is only defined when it is not set - local GSDLL = kpse.var_value('TEXLIVE_WINDOWS_EXTERNAL_GS_DLL') - if GSDLL then - os.setenv('GS_DLL', GSDLL) - end - local GSLIB = kpse.var_value('TEXLIVE_WINDOWS_EXTERNAL_GS_LIB') - if GSLIB then - os.setenv('GS_LIB', GSLIB) - end -else - -- use built in gs - os.setenv('GS_LIB', TEXDIR..'/tlpkg/tlgs/lib;' - ..TEXDIR..'/tlpkg/tlgs/fonts;' - ..TEXDIR..'/tlpkg/tlgs/Resource/Init;' - ..TEXDIR..'/tlpkg/tlgs/Resource;' - ..TEXDIR..'/tlpkg/tlgs/kanji;' - ..os.getenv('WINDIR')..'/Fonts;'..TEXMFDIST..'/fonts') - if is_64bit_windows_os() then - os.setenv('GS_DLL', TEXDIR..'/tlpkg/tlgs/bin/gsdll64.dll') - GSEXE = TEXDIR..'/tlpkg/tlgs/bin/gswin64c.exe' - GSNAME = 'gswin64c.exe' - else - os.setenv('GS_DLL', TEXDIR..'/tlpkg/tlgs/bin/gsdll32.dll') - GSEXE = TEXDIR..'/tlpkg/tlgs/bin/gswin32c.exe' - GSNAME = 'gswin32c.exe' - end -end --- now setup the path so that the gs program will be found -GSDIR = TEXDIR..'/tlpkg/tlgs/bin' -PATH = prepend_path(PATH, GSDIR, BINDIR) -os.setenv('PATH', PATH); - --- sys stuff -if (sysprog and not contains(sys_user_progs, progname)) then - os.setenv('TEXMFVAR', kpse.var_value('TEXMFSYSVAR')) - os.setenv('TEXMFCONFIG', kpse.var_value('TEXMFSYSCONFIG')) -end --- Adobe Reader crash case: make sure USERPROFILE is not "slashed" -os.setenv("USERPROFILE", os.getenv("USERPROFILE"):gsub('/', '\\')) - --- extension to interpreter mapping - --- the extension is mapped to an argument table. --- the command to execute is given as the first element of the table, --- which can be a whitespace separated list of names to try. -local extension_map = { - ['.bat'] = {'cmd', '/c', 'call'}, - ['.jar'] = {'java.exe', '-jar'}, - ['.pl' ] = {'perl.exe'}, - ['.py' ] = {'python.exe'}, - ['.rb' ] = {'ruby.exe'}, - ['.tcl'] = {'tclsh.exe tclsh86.exe tclsh85.exe tclkitsh.exe'}, - ['.vbs'] = {'cscript.exe', '-nologo'}, -} -if guimode then - -- for GUI mode wrappers we try GUI mode interpeters where possible - extension_map['.jar'][1] = 'javaw.exe ' .. extension_map['.jar'][1] - extension_map['.pl' ][1] = 'wperl.exe ' .. extension_map['.pl' ][1] - extension_map['.py' ][1] = 'pythonw.exe ' .. extension_map['.py' ][1] - extension_map['.rb' ][1] = 'rubyw.exe ' .. extension_map['.rb' ][1] - -- gui tcl shares no interpreters with non-gui tcl - extension_map['.tcl'] = {'wish.exe wish86.exe wish85.exe tclkit.exe'} - extension_map['.vbs'][1] = 'wscript.exe ' .. extension_map['.vbs'][1] -end -extension_map['.cmd'] = extension_map['.bat'] -extension_map['.js'] = extension_map['.vbs'] - --- set up ARGV table - -local ARGV = nil - --- special cases (aliases) - -if is_tex4ht_command(progname) then - argline = progname .. ' ' .. argline - progname = 'mk4ht' -elseif progname == 'a2ping' then - table.insert(extension_map['.pl'], '-x') -elseif contains(sys_user_progs, progname) then - if sysprog then - argline = ' --sys ' .. argline - elseif userprog then - argline = ' --user ' .. argline - end - -- do not guess input encoding in format creation for ptex - -- and friends since guessing is not complete - os.setenv('GUESS_INPUT_KANJI_ENCODING', '0') -elseif progname == 'asy' then - os.setenv('ASYMPTOTE_GS', GSEXE) - os.setenv('CYGWIN', 'nodosfilewarning') - if is_64bit_windows_os() then - ARGV = {[0]=TEXDIR..'/tlpkg/asymptote64/asy.exe', 'asy'} - else - ARGV = {[0]=TEXDIR..'/tlpkg/asymptote/asy.exe', 'asy'} - end -elseif progname == 'dviout' then - local fontsdir = kpse.var_value('TEXMFVAR') .. '/fonts' - if (lfs.attributes(chgstrcp.syscptoutf8(fontsdir), 'mode') ~= 'directory') then - assert(mkdir_plus(fontsdir)) - end - local tfmpath = kpse.show_path('tfm') - tfmpath = string.gsub(tfmpath, '!!', '') - tfmpath = string.gsub(tfmpath, '/', '\\') - local texrt = {} - for d in string.gmatch(tfmpath, '([^;]+\\fonts)\\tfm[^;]*') do - if (lfs.attributes(chgstrcp.syscptoutf8(d), 'mode') == 'directory') then - table.insert(texrt, d) - end - end - local par = [["-gen=']] .. string.gsub(TEXDIR, '/', '\\') .. - [[\tlpkg\dviout\gen_pk'" "-TEXROOT=']] .. - table.concat(texrt, ';') .. [['" "-gsx=']] .. GSEXE .. [['"]]; - ARGV = {[0]=TEXDIR..'/tlpkg/dviout/dviout.exe', 'dviout', par} -elseif progname == 'mkluatexfontdb' then - progname = 'luaotfload-tool' - table.insert(arg, '--alias=mkluatexfontdb') -elseif progname == 'psv' then - argline = '-sINPUT='..argline - ARGV = {[0]=TEXDIR..'/tlpkg/tlpsv/gswxlua.exe', 'gswxlua', - '-dDisableFAPI=true', - '-l', (_q(TEXDIR..'/tlpkg/tlpsv/psv.wx.lua'):gsub('/','\\')), - '-p', (_q(TEXDIR..'/tlpkg/tlpsv/psv_view.ps'):gsub('/','\\')), - '-i', '.'} -elseif progname == 'repstopdf' or progname == 'rpdfcrop' then - argline = '--restricted ' .. argline - progname = string.sub(progname, 2, -1) -elseif progname == 'texworks' then - local winver = tonumber(string.match(os.uname().version, '%D*(%d+%.?%d*)')) - assert(winver >= 5.01, "Windows XP or newer required to run TeXworks") - local TW_LIBPATH = kpse.var_value('TW_LIBPATH') or - kpse.var_value('TEXMFCONFIG')..'/texworks' - local TW_INIPATH = kpse.var_value('TW_INIPATH') or TW_LIBPATH - os.setenv('TW_LIBPATH', TW_LIBPATH) - os.setenv('TW_INIPATH', TW_INIPATH) - if (TW_INIPATH and lfs.attributes(chgstrcp.syscptoutf8(TW_INIPATH), 'mode') ~= 'directory') then - -- TeXworks needs directory holding its configuration to exist - assert(mkdir_plus(TW_INIPATH)) - end - ARGV = {[0]=TEXDIR..'/tlpkg/texworks/texworks.exe', 'texworks'} -elseif progname == 'tlgs' then - ARGV = {[0]=GSEXE, GSNAME} -elseif progname == 'tlperl' then - ARGV = {[0]=PERLEXE, 'perl'} -elseif progname == 'latexdef' then - progname = 'texdef' - argline = ' --tex latex ' .. argline -elseif progname == 'cllualatex' then - progname = 'cluttex' - argline = ' --engine=lualatex ' .. argline -elseif progname == 'clxelatex' then - progname = 'cluttex' - argline = ' --engine=xelatex ' .. argline -end - --- general case - -if not ARGV then - os.setenv('TEXMF', TEXMFDIST) - local extlist = '.lua;.tlu;.pl;.rb;.py;.tcl;.jar;.vbs;.js;.bat;.cmd;.texlua;\0' - local progfullname = search_path(progname, BINDIR, '.lua;.tlu;.bat;.cmd') or - find_texmfscript(progname, extlist) - os.setenv('TEXMF', nil) - if progfullname == nil then - -- scripts in $TEXMFLOCAL etc. can't be found without the following - -- line !! - kpse.set_program_name('runscript') - progfullname = assert(find_texmfscript(progname, extlist)) - end - local ext = string.match(string.lower(progfullname), '%.[^\\/.]*$') or '' - if (ext == '.lua') or (ext == '.tlu') or (ext == '.texlua') then -- lua script - arg[0] = progfullname - elseif (ext == '.tcl' and guimode) then -- tcl script; use built-in tcl/tk? - local try_extern_tcl = - (kpse.var_value('TEXLIVE_WINDOWS_TRY_EXTERNAL_TCL') == '1') and - not is_restricted_progname - local TCLEXENAME, TCLEXE - if try_extern_tcl then - TCLEXE, TCLEXENAME = check_command(extension_map['.tcl'][1], PATH) - end - if try_extern_tcl and not TCLEXE then - local exttcl_warn = [[ -External Tcl missing or outdated. Please install a recent Tcl, or configure -TeX Live to always use the builtin Tcl for gui scripts: - tlmgr conf texmf TEXLIVE_WINDOWS_TRY_EXTERNAL_TCL 0 -Meanwhile, continuing with built-in Tcl... -]] - show_error(exttcl_warn) - else -- did find something - ARGV = {[0]=TCLEXE, TCLEXENAME} - end - if not TCLEXE then - -- kit: tlpkg/tltcl/tclkit.exe - -- regular wish: tlpkg/tltcl/bin/wish.exe - -- we ignore the fact that a non-kit tcl/tk provides wish AND tclsh - if lfs.isfile(TEXDIR..'/tlpkg/tltcl/tclkit.exe') then - ARGV = {[0]=TEXDIR..'/tlpkg/tltcl/tclkit.exe', 'tclkit.exe'} - PATH = prepend_path(PATH, TEXDIR:gsub('/','\\')..'\\tlpkg\\tltcl') - elseif lfs.isfile(TEXDIR..'/tlpkg/tltcl/bin/wish.exe') then - ARGV = {[0]=TEXDIR..'/tlpkg/tltcl/bin/wish.exe', 'wish.exe'} - PATH = prepend_path(PATH, TEXDIR:gsub('/','\\')..'\\tlpkg\\tltcl\\bin') - end - end - table.insert(ARGV, _q(progfullname:gsub('/','\\'))) - if (argline and argline ~= '') then argline = '-- '..argline end - else -- not gui tcl or not tcl at all - ARGV = extension_map[ext] or assert(shebang_to_argv(progfullname)) - -- [w|c]script, for one, mistakes a forward-slashed UNC script path - -- for an option even when quoted - table.insert(ARGV, _q(progfullname:gsub('/','\\'))) - if not ARGV[0] then - ARGV[0], ARGV[1] = assert(check_command(ARGV[1], PATH)) - end - end -end - --- run the program/script - -if ARGV then - table.insert(ARGV, argline) -- pass through original arguments - if string.find (table.concat(ARGV, ' '), 'perl.exe') and extperl_warn then - - show_error(extperl_warn) - end - local ret = assert(os.spawn(ARGV)) - if ret ~= 0 then - local dbginfo = debug.getinfo(1) - local errormsg = string.format("%s:%d: command failed with exit code %d:\n%s", - dbginfo.short_src, dbginfo.currentline - 2, - ret, table.concat(ARGV, ' ') ) - show_error(errormsg) - end - os.exit(ret) -else -- must be a lua script - dofile(arg[0]) -end - -end -- MAIN_CHUNK - --- execute MAIN_CHUNK with pcall to catch any runtime errors - -local success, errormsg = pcall(MAIN_CHUNK) -if not success then - os.setenv('RUNSCRIPT_ERROR_MESSAGE', errormsg) - error(errormsg) -end - --- about RUNSCRIPT_ERROR_MESSAGE environment variable: --- it stores an error message that is caught and displayed --- in a message box on the C side at process exit --- (currently used only by gui mode stubs) |