2012-04-06 Keith Marshall <keithmarshall@users.sourceforge.net>
+ Add scripting hooks to support creation of MS-Windows shortcuts.
+
+ * src/clistub.c (progname): New static variable with file scope; it
+ replaces former automatic variable, of same name, in main() function.
+ (set_script_hook): New static function; implement it, and call it...
+ (main) [--desktop, --start-menu]: ...from here, to interpret these new
+ command line options; they are propagated to scripts via...
+ (MINGW_GET_DESKTOP_HOOK, MINGW_GET_START_MENU_HOOK): ...these new
+ internally assigned environment variables.
+ (help_text): Document --desktop and --start-menu.
+
+ * scripts/libexec/setup.lua scripts/libexec/wsh.lua: New lua module
+ files; they implement a lua scripting API; they delegate requests to
+ the Windows Scripting Host, via either of this pair of...
+ * scripts/libexec/shlink.js: ...new script to create shortcuts, or...
+ * scripts/libexec/unlink.js: ...its complement, to remove them.
+ * Makefile.in (SRCDIST_SUBDIRS): Integrate them; enumerate them in...
+ (scripts_srcdir, LIBEXEC_SCRIPTS): ...these new macros; use to...
+ (install): ...install them.
+
+2012-04-06 Keith Marshall <keithmarshall@users.sourceforge.net>
+
Initialise $LUA_PATH to locate mingw-get specific scripts.
* src/pkgexec.cpp (lua_path_init): New static inline function.
tinyxml.$(OBJEXT) tinyxmlparser.$(OBJEXT) \
tinystr.$(OBJEXT) tinyxmlerror.$(OBJEXT)
+script_srcdir = ${srcdir}/scripts/libexec
+
BIN_PROGRAMS = pkginfo$(EXEEXT) mingw-get$(EXEEXT)
LIBEXEC_PROGRAMS = gui$(EXEEXT) lastrites$(EXEEXT)
+LIBEXEC_SCRIPTS = ${script_srcdir}/setup.lua ${script_srcdir}/wsh.lua \
+ ${script_srcdir}/shlink.js ${script_srcdir}/unlink.js
LIBEXEC_DATA = mingw-get-0.dll
all: $(BIN_PROGRAMS) $(LIBEXEC_PROGRAMS) $(LIBEXEC_DATA)
for image in $(LIBEXEC_PROGRAMS); do \
$(INSTALL_PROGRAM) $$image ${libexecdir}/${PACKAGE_TARNAME}; \
done
- for image in $(LIBEXEC_DATA); do \
+ for image in $(LIBEXEC_DATA) $(LIBEXEC_SCRIPTS); do \
$(INSTALL_DATA) $$image ${libexecdir}/${PACKAGE_TARNAME}; \
done
SRCDIST_FILES = $(LICENCE_FILES) ChangeLog NEWS INSTALL \
aclocal.m4 configure.ac configure Makefile.in version.c.in
-SRCDIST_SUBDIRS = build-aux m4 src src/pkginfo srcdist-doc tinyxml xml
+SRCDIST_SUBDIRS = build-aux m4 src src/pkginfo srcdist-doc \
+ scripts/libexec tinyxml xml
# The names of distributed pacakge archive files incorporate version
# information, derived from PACKAGE_VERSION; this is decomposed, so that
--- /dev/null
+--
+-- setup.lua
+--
+-- $Id$
+--
+-- Lua 5.2 module providing common setup hooks for mingw-get.
+--
+--
+-- This file is a component of mingw-get.
+--
+-- Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+-- Copyright (C) 2012, MinGW Project
+--
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included
+-- in all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+-- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+ local M = {}
+ local wsh = require "wsh"
+--
+ function M.libexec_path( script, subsystem )
+ if not subsystem
+ then
+ subsystem = "mingw-get"
+ end
+ return wsh.libexec_path( script, subsystem )
+ end
+--
+ function M.shlink( args, ... )
+ if args
+ then
+ wsh.execute( M.libexec_path( "shlink.js" ), args, ... )
+ end
+ end
+--
+ function M.unlink( args, ... )
+ if args
+ then
+ wsh.execute( M.libexec_path( "unlink.js" ), args, ... )
+ end
+ end
+--
+ function M.create_shortcuts( ... )
+ M.shlink( os.getenv( "MINGW_GET_DESKTOP_HOOK" ), ... )
+ M.shlink( os.getenv( "MINGW_GET_START_MENU_HOOK" ), ... )
+ end
+--
+ function M.delete_shortcuts( ... )
+ M.unlink( "--desktop", ... )
+ M.unlink( "--all-users --desktop", ... )
+ M.unlink( "--all-users --start-menu", ... )
+ M.unlink( "--start-menu", ... )
+ end
+--
+ return M
+--
+-- $RCSfile$: end of file */
--- /dev/null
+/*
+ * shlink.js
+ *
+ * $Id$
+ *
+ * Invoke the Windows Scripting Host to create or modify a windows shortcut,
+ * with specified parameters.
+ *
+ * Usage:
+ * cscript -nologo shlink.js [--option[=value] ...] target name
+ *
+ * Options:
+ * --verbose report shortcut parameter assignments on stdout
+ *
+ * --all-users
+ * create the shortcut in the start menu, or on the
+ * desktop available to all users; (has no effect,
+ * unless --start-menu or --desktop is specified)
+ *
+ * --desktop create the shortcut on the desktop of the current
+ * user, (or for all users, with --all-users)
+ *
+ * --start-menu
+ * create the shortcut in the user's start menu, (or
+ * all users' start menu, with --all-users)
+ *
+ * --arguments="argument list ..."
+ * specify arguments to be passed to the command
+ * invoked by the shortcut
+ *
+ * --description="text ..."
+ * specify the "tool tip" for the shortcut
+ *
+ * --hotkey="[SHIFT+][CTRL+][ALT+]key"
+ * specify a hot-key combination which may be used
+ * to invoke the shortcut command
+ *
+ * --icon="d:\path\to\icon\file[,index]"
+ * specify an icon to associate with the shortcut;
+ * if unspecified, the first icon in the target file,
+ * or failing that, a system default is used
+ *
+ * --show=normal|maximised|minimised
+ * specify the style of window in which the program
+ * invoked by the shortcut will start running
+ *
+ * --workingdir="d:\path\to\working\directory"
+ * specify the absolute path name for the directory
+ * which will become the current working directory when
+ * the program invoked by the shortcut is started
+ *
+ * Parameters:
+ * target the path name to the program to invoke, or the file
+ * to be opened, when the shortcut is activated.
+ *
+ * name the path name for the shortcut file itself; if this
+ * does not end with either a ".lnk" or ".url" extension,
+ * then ".lnk" will be appended, so creating a regular
+ * file system link type shortcut.
+ *
+ *
+ * This file is a component of mingw-get.
+ *
+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 2012, MinGW Project
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+var cmdName = WScript.ScriptName;
+var WinShell = WScript.CreateObject("WScript.Shell");
+
+/* Properties for the shortcut may be specified as arguments
+ * to command line options, each of which is represented in the
+ * GNU long option form, by keywords with property associations
+ * as specified by:
+ */
+var options = Array(
+ "name", /* File name/path of .lnk file */
+ "all-users",
+ "start-menu",
+ "desktop",
+ "verbose",
+ /*
+ * Option Property
+ * ------------- -------------------------
+ */
+ "arguments", /* Shortcut.Arguments */
+ "description", /* Shortcut.Description */
+ "hotkey", /* Shortcut.HotKey */
+ "icon", /* Shortcut.IconLocation */
+ "show", /* Shortcut.WindowStyle */
+ "target", /* Shortcut.TargetPath */
+ "workingdir" /* Shortcut.WorkingDirectory */
+ );
+
+/* The "complain" function provides a mechanism for writing
+ * diagnostic messages to stderr, and optionally aborting the
+ * calling script.
+ */
+function complain( condition, message )
+{
+ WScript.StdErr.WriteLine( cmdName + ": " + message );
+ if( condition < 0 )
+ WScript.Quit( -condition );
+ return condition;
+}
+
+/* Strip ".js" suffix from command name.
+ */
+var i = cmdName.lastIndexOf( ".js" );
+if( (i > 0) && (cmdName.substr( i ) == ".js") )
+ cmdName = cmdName.substr( 0, i );
+
+/* Initialise all options to "unassigned" state.
+ */
+var target = -1;
+var lnkname = -1;
+var desktop = -1;
+var allusers = -1;
+var startmenu = -1;
+var verbosity = -1;
+var unassigned = "+++unassigned+++";
+var assigned = Array( options.length );
+for( var k = 0; k < assigned.length; k++ )
+{
+ switch( options[k] )
+ {
+ case "name":
+ lnkname = k;
+ break;
+
+ case "desktop":
+ desktop = k;
+ break;
+
+ case "start-menu":
+ startmenu = k;
+ break;
+
+ case "all-users":
+ allusers = k;
+ break;
+
+ case "target":
+ target = k;
+ break;
+
+ case "verbose":
+ verbosity = k;
+ }
+ assigned[k] = unassigned;
+}
+
+/* Define the prefix, which will qualify the location
+ * of the shortcut; initialise it to nothing, so that by
+ * default shortcuts will be located by absolute path name,
+ * as specified, or relative to current working directory.
+ */
+var prefix = "";
+
+var j;
+function assign_option( name, value )
+{
+ switch( name )
+ {
+ case "desktop":
+ case "start-menu":
+ case "all-users":
+ case "verbose":
+ j = i;
+ return "set";
+ }
+ return value;
+}
+
+/* Parse the command line.
+ */
+var argv = WScript.Arguments;
+for( i = 0; i < argv.length; i++ )
+{
+ if( argv( i ).indexOf( "--" ) == 0 )
+ {
+ /* Handle arguments specifying options...
+ */
+ if( (optind = argv( j = i ).indexOf( "=" ) + 1) > 3 )
+ {
+ optnam = argv( j ).substr( 2, optind - 3 );
+ optarg = argv( j ).substr( optind );
+ }
+ else
+ {
+ optnam = argv( j ).substr( 2 );
+ if( ++j < argv.length )
+ optarg = argv( j );
+ else
+ optarg = unassigned;
+ }
+
+ var matched = 0;
+ for( var k = 0; k < options.length; k++ )
+ {
+ if( optnam == options[k] )
+ {
+ matched = 1;
+ assigned[k] = assign_option( options[k], optarg );
+ k = options.length;
+ }
+ else if( options[k].indexOf(optnam) == 0 )
+ {
+ if( ++matched > 1 )
+ complain( -2, cmdName + "option '" + argv( i ) + "' is ambiguous" );
+ assigned[k] = assign_option( options[k], optarg );
+ }
+ }
+ if( matched == 1 )
+ {
+ i = j;
+ }
+ else
+ complain( -2, "option '" + argv( i ) + "' is not supported" );
+ }
+
+ /* Handle non-option arguments...
+ */
+ else if( (target >= 0) && (assigned[target] == unassigned) )
+ /*
+ * ...the first of which is the target to which the
+ * (shortcut) link is to refer...
+ */
+ assigned[target] = argv( i );
+
+ else if( (lnkname >= 0) && (assigned[lnkname] == unassigned) )
+ /*
+ * ...the second is the file system path name at which
+ * the link file itself is to be saved...
+ */
+ assigned[lnkname] = argv( i );
+
+ else
+ /* ...and any more than two is an error.
+ */
+ complain( -2, "too many arguments" );
+}
+
+/* Verify that mandatory arguments have been specified...
+ */
+if( assigned[target] == unassigned )
+ /*
+ * First of these, the TargetPath specification, is required;
+ * diagnose and abort, if missing.
+ */
+ complain( -2, "missing argument: no target path specified" );
+
+if( assigned[lnkname] == unassigned )
+ /*
+ * Second, the path name for the link file itself is essential;
+ * again, diagnose and abort if missing.
+ */
+ complain( -2, "missing argument: no shortcut name specified" );
+
+/* We have both the mandatory arguments; check that the link name
+ * is properly terminated by a ".lnk" or ".url" suffix...
+ */
+var suffix = "";
+if( (i = assigned[lnkname].length - 4) > 0 )
+ suffix = assigned[lnkname].substr( i );
+
+/* ...and append ".lnk" as default, if not already present.
+ */
+if( (suffix != ".lnk") && (suffix != ".url") )
+ assigned[lnkname] += ".lnk";
+
+/* Add the appropriate prefix for '--desktop' or '--start-menu' shortcuts.
+ */
+if( assigned[desktop] != unassigned )
+{
+ if( assigned[startmenu] != unassigned )
+ complain( -2, "options '--desktop' and '--start-menu' are incompatible" );
+ else prefix = WinShell.SpecialFolders( (assigned[allusers] == unassigned)
+ ? "Desktop" : "AllUsersDesktop" ) + "\\";
+}
+else if( assigned[startmenu] != unassigned )
+ prefix = WinShell.SpecialFolders( (assigned[allusers] == unassigned)
+ ? "StartMenu" : "AllUsersStartMenu" ) + "\\";
+
+else if( assigned[allusers] != unassigned )
+ complain( -2,
+ "option '--all-users' also requires '--desktop' or '--start-menu'"
+ );
+
+/* Handle verbosity...
+ */
+function verbose_assignment( property, value )
+{
+ if( assigned[verbosity] == "set" )
+ WScript.Echo( cmdName + ": set " + property + " = " + value );
+}
+
+/* Initialise the shortcut entity reference.
+ */
+if( assigned[verbosity] == "set" )
+ WScript.Echo( cmdName + ": create shortcut: " + prefix + assigned[lnkname] );
+
+var Shortcut = WinShell.CreateShortcut( prefix + assigned[lnkname] );
+
+for( var k = 0; k < options.length; k++ )
+{
+ if( assigned[k] != unassigned )
+ switch( options[k] )
+ {
+ case "arguments":
+ verbose_assignment( "Shortcut.Arguments", assigned[k] );
+ Shortcut.Arguments = assigned[k];
+ break;
+
+ case "description":
+ verbose_assignment( "Shortcut.Description", assigned[k] );
+ Shortcut.Description = assigned[k];
+ break;
+
+ case "hotkey":
+ verbose_assignment( "Shortcut.HotKey", assigned[k] );
+ Shortcut.HotKey = assigned[k];
+ break;
+
+ case "icon":
+ verbose_assignment( "Shortcut.IconLocation", assigned[k] );
+ Shortcut.IconLocation = assigned[k];
+ break;
+
+ case "show":
+ verbose_assignment( "Shortcut.WindowStyle", assigned[k] );
+ var style = Array(
+ "normal", 1,
+ "maximised", 3,
+ "maximized", 3,
+ "minimised", 7,
+ "minimized", 7
+ );
+ for( j = 0; j < style.length; j++ )
+ if( style[j++].indexOf( assigned[k] ) == 0 )
+ {
+ Shortcut.WindowStyle = style[j];
+ j = 100;
+ }
+ if( j < 100 )
+ complain( 1, "unrecognised mode '--show=" + assigned[k] + "' ignored" );
+ break;
+
+ case "target":
+ verbose_assignment( "Shortcut.TargetPath", assigned[k] );
+ Shortcut.TargetPath = assigned[k];
+ break;
+
+ case "workingdir":
+ verbose_assignment( "Shortcut.WorkingDirectory", assigned[k] );
+ Shortcut.WorkingDirectory = assigned[k];
+ }
+ else if( assigned[verbosity] == "set" )
+ WScript.Echo( cmdName + ": option '--" + options[k] + "' is unassigned" );
+}
+
+/* Commit the shortcut entity to disk.
+ */
+Shortcut.Save();
+
+/* $RCSfile$: end of file */
--- /dev/null
+/*
+ * unlink.js
+ *
+ * $Id$
+ *
+ * Invoke the Windows Scripting Host to remove specified files, typically
+ * from the user's or all users' start menu or desktop directories.
+ *
+ * Usage:
+ * cscript -nologo unlink.js [--option ...] file ...
+ *
+ * Options:
+ * --all-users
+ * references to desktop or start menu files apply
+ * to the directories serving all users
+ *
+ * --desktop remove files from the user's desktop directory, (or
+ * from all users' desktop directory, with --all-users)
+ *
+ * --start-menu
+ * remove files from the user's start menu directory, (or
+ * from all users' start menu directory, with --all-users)
+ *
+ * --if-linked=target_path
+ * do not remove any matched file which is not a shortcut
+ * (.lnk or .url) referring to the specified target path;
+ * when this option is specified, any specified file name
+ * which does not already have a .lnk or .url extension
+ * will have .lnk appended, before seeking any match
+ *
+ * --force override read-only attributes when removing files.
+ *
+ * Parameters:
+ * file the path name for a file to be removed; if --desktop
+ * or --start-menu is specified, it should be a relative
+ * path name, which will then be resolved relative to the
+ * appropriate system directory path.
+ *
+ *
+ * This file is a component of mingw-get.
+ *
+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 2012, MinGW Project
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+var cmdName = WScript.ScriptName;
+var FileSystem = WScript.CreateObject("Scripting.FileSystemObject");
+var WinShell = WScript.CreateObject("WScript.Shell");
+
+/* Strip ".js" suffix from command name.
+ */
+var i = cmdName.lastIndexOf( ".js" );
+if( (i > 0) && (cmdName.substr( i ) == ".js") )
+ cmdName = cmdName.substr( 0, i );
+
+/* Specify the keywords which identify command line options.
+ */
+var options = Array(
+ /*
+ * Option Effect
+ * ------------- -------------------------
+ */
+ "all-users", /* Resolve file path names in all-users domain... */
+ "start-menu", /* ...relative to user's or all-users' start menu... */
+ "desktop", /* ...or desktop directories. */
+ "if-linked", /* Only delete shortcuts with specified target path */
+ "force" /* Forcibly override read-only attribute */
+ );
+
+/* Initialise all options as "unassigned".
+ */
+var unassigned = "+++unassigned+++";
+var assigned = Array( options.length );
+for( i = 0; i < assigned.length; i++ )
+ assigned[i] = unassigned;
+
+/* The "complain" function provides a mechanism for writing
+ * diagnostic messages to stderr, and optionally aborting the
+ * calling script.
+ */
+function complain( condition, message )
+{
+ WScript.StdErr.WriteLine( cmdName + ": " + message );
+ if( condition < 0 )
+ WScript.Quit( -condition );
+ return condition;
+}
+
+/* Parse the command line, to identify any specified options.
+ */
+var chklink = "";
+var argv = WScript.Arguments;
+for( i = 0; i < argv.length; i++ )
+{
+ if( argv( i ).indexOf( "--" ) == 0 )
+ {
+ /* Handle arguments specifying options...
+ */
+ var optind;
+ var matched = 0;
+ var optname = argv( i ).substr( 2 );
+ var optarg = "";
+ for( var k = 0; k < options.length; k++ )
+ {
+ /* Try to match each defined option in turn...
+ */
+ var argind = optname.indexOf( "=" );
+ if( argind > 0 )
+ {
+ optarg = optname.substr( argind + 1 );
+ optname = optname.substr( 0, argind );
+ }
+
+ if( optname == options[k] )
+ {
+ /* A exact (complete) match trumps any possible abbreviation...
+ */
+ matched = 1;
+ assigned[optind = k] = optname;
+ k = options.length;
+ }
+
+ else if( options[k].indexOf( optname ) == 0 )
+ {
+ /* Otherwise abbreviations are allowed, but must uniquely
+ * identify only one defined option name...
+ */
+ if( matched++ > 0 )
+ complain( -2, "option '" + argv( i ) + "' is ambiguous" );
+ assigned[optind = k] = options[k];
+ }
+ }
+ if( matched == 0 )
+ /*
+ * Bail out, if no match identified.
+ */
+ complain( -2, "option '" + argv( i ) + "' is undefined" );
+
+ if( assigned[optind] == "if-linked" )
+ chklink = optarg;
+ }
+}
+
+/* Establish prefix for resolving paths relative to desktop
+ * or start menu directories, and handle the --force option.
+ */
+var prefix = "";
+var allusers = false;
+var force = false;
+for( i = 0; i < options.length; i++ )
+{
+ switch( assigned[i] )
+ {
+ case "force":
+ force = true;
+ break;
+
+ case "all-users":
+ allusers = true;
+ break;
+
+ case "start-menu":
+ prefix = WinShell.SpecialFolders( allusers ? "AllUsersStartMenu"
+ : "StartMenu"
+ ) + "\\";
+ break;
+
+ case "desktop":
+ if( prefix != "" )
+ complain( -2, "options '--start-menu' and '--desktop' are incompatible" );
+ prefix = WinShell.SpecialFolders( allusers ? "AllUsersDesktop"
+ : "Desktop"
+ ) + "\\";
+ }
+}
+
+/* Parse the command line again, to process path name arguments,
+ * and delete the specified files.
+ */
+for( i = 0; i < argv.length; i++ )
+{
+ if( argv( i ).indexOf( "--" ) != 0 )
+ {
+ /* Not an option argument, so assume it's a path name.
+ */
+ var filename = prefix + argv( i );
+ if( chklink != "" )
+ {
+ /* The "--if-linked" option is in effect, and a viable
+ * target path has been defined. The file to be deleted
+ * MUST be a shortcut file, (i.e. it MUST bear a ".lnk" or
+ * ".url" extension); supply ".lnk" as default, if this is
+ * not so.
+ */
+ var l = filename.length - 4;
+ var suffix = (l > 0) ? filename.substr( l ) : 0;
+ if( (suffix != ".lnk") && (suffix != ".url") )
+ filename += ".lnk";
+ }
+ if( FileSystem.FileExists( filename ) )
+ {
+ /* The requisite file DOES exist...
+ */
+ if( chklink != "" )
+ {
+ /* ...but when "--if-linked is in effect, we must verify
+ * that the link target is matched, before...
+ */
+ var ref = WinShell.CreateShortcut( filename );
+ if( ref.TargetPath == chklink )
+ /*
+ * ...we may proceed with deletion.
+ */
+ FileSystem.DeleteFile( filename, force );
+ }
+ else
+ /* When "--if-linked" is NOT in effect, we may simply
+ * proceed with deletion, without further ado.
+ */
+ FileSystem.DeleteFile( filename, force );
+ }
+ }
+}
+
+/* $RCSfile$: end of file */
--- /dev/null
+--
+-- wsh.lua
+--
+-- $Id$
+--
+-- Lua 5.2 module providing a simple API for invoking system services
+-- via the Microsoft Windows Scripting Host.
+--
+--
+-- This file is a component of mingw-get.
+--
+-- Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+-- Copyright (C) 2012, MinGW Project
+--
+--
+-- Permission is hereby granted, free of charge, to any person obtaining a
+-- copy of this software and associated documentation files (the "Software"),
+-- to deal in the Software without restriction, including without limitation
+-- the rights to use, copy, modify, merge, publish, distribute, sublicense,
+-- and/or sell copies of the Software, and to permit persons to whom the
+-- Software is furnished to do so, subject to the following conditions:
+--
+-- The above copyright notice and this permission notice shall be included
+-- in all copies or substantial portions of the Software.
+--
+-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+-- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+-- DEALINGS IN THE SOFTWARE.
+--
+ local M = {}
+ local cscript = "cscript -nologo"
+--
+ function M.execute( ... )
+ local function wsh_prepare( interpreter, ... )
+ for argind, argval in ipairs {...}
+ do
+ interpreter = interpreter .. " " .. argval
+ end
+ return interpreter
+ end
+ os.execute( wsh_prepare( cscript, ... ) )
+ end
+--
+ function M.libexec_path( script, subsystem )
+ local script_path = os.getenv( "APPROOT" )
+ if script_path
+ then
+ script_path = script_path .. "libexec\\"
+ else
+ script_path = ".\\libexec\\"
+ end
+ if subsystem
+ then
+ script_path = script_path .. subsystem .. "\\"
+ end
+ return script_path .. script
+ end
+--
+ return M
+--
+-- $RCSfile$: end of file */
#define EXIT_FATAL EXIT_FAILURE + 1
+static const char *progname;
+
wchar_t *AppPathNameW( const wchar_t *relpath )
{
/* UTF-16LE implementation; NOT thread safe...
" runtime prerequisites of, and in addition to,\n"
" the nominated package\n"
"\n"
+" --desktop[=all-users]\n"
+" Enable the creation of desktop shortcuts, for\n"
+" packages which provide the capability via pre-\n"
+" or post-install scripts; the optional 'all-users'\n"
+" qualifier requests that all such shortcuts are\n"
+" to be made available to all users; without it\n"
+" shortcuts will be created for current user only\n"
+"\n"
+" Note that specification of this option does not\n"
+" guarantee that shortcuts will be created; the\n"
+" onus lies with individual package maintainers\n"
+" to provide scripting to support this capability\n"
+"\n"
+" --start-menu[=all-users]\n"
+" Enable the creation of start menu shortcuts, for\n"
+" packages which provide the capability via pre-\n"
+" or post-install scripts; the optional 'all-users'\n"
+" qualifier requests that all such shortcuts are\n"
+" to be made available to all users; without it\n"
+" shortcuts will be created for current user only\n"
+"\n"
+" Note that specification of this option does not\n"
+" guarantee that shortcuts will be created; the\n"
+" onus lies with individual package maintainers\n"
+" to provide scripting to support this capability\n"
+"\n"
"Actions:\n"
" update Update local copy of repository catalogues\n"
" list, show List and show details of available packages\n"
return result;
}
+static void set_script_hook( const char *hook, const char *optarg )
+{
+ /* Helper function to initialise the environment variables which
+ * are associated with Lua scripting hooks, when the user specifies
+ * the appropriate activation options on the command line.
+ */
+ if( optarg != NULL )
+ {
+ /* An optional argument was assigned for the hook...
+ */
+ int arglen = strlen( optarg );
+ const char *all_users = "all-users";
+ const char *value_none = "none";
+ if( strncmp( optarg, all_users, arglen ) == 0 )
+ {
+ /* When this is the "all-users" qualifier, we append it to
+ * the value to be assigned to the environment variable.
+ */
+ const char *fmt = "%s --%s";
+ char tmp[1 + snprintf( NULL, 0, fmt, hook, all_users )];
+ snprintf( tmp, sizeof( tmp ), fmt, hook, all_users );
+ putenv( tmp );
+ }
+ else if( strncmp( optarg, value_none, arglen ) == 0 )
+ {
+ /* When it is the "none" qualifier, we remove any prior
+ * assignment to the respective environment variable.
+ *
+ * FIXME: to support assignment from within profile.xml,
+ * we will eventually need additional coding here, to
+ * override any profile.xml assignment.
+ */
+ char tmp[strlen( hook )];
+ char *p = tmp;
+ do { *p++ = *hook;
+ } while( *hook++ != '=' );
+ *p = '\0';
+ putenv( tmp );
+ }
+ else
+ { /* No other qualifier is supported; diagnose and ignore.
+ */
+ while( *hook++ != '=' ) /* advance pointer; no other action */;
+ fprintf( stderr,
+ "%s: *** WARNING *** invalid argument '%s' to option %s ignored\n",
+ progname, optarg, hook
+ );
+ }
+ }
+ else
+ /* No qualifying option argument specified; simply assign the
+ * hook variable value, as passed from the getopts() handler.
+ */
+ putenv( hook );
+}
+
#define atmost( lim, val ) ((lim) < (val)) ? (lim) : (val)
int main( int argc, char **argv )
{
- /* Make a note of...
- */
- const char *progname = basename( *argv ); /* ...this program's name */
- wchar_t *approot; /* and where it is installed */
-
/* Provide storage for interpretation of any parsed command line options.
* Note that we could also initialise them here, but then we would need to
* give attention to the number of initialisers required; to save us that
*/
struct pkgopts parsed_options;
+ /* Make a note of this program's name, and where it's installed.
+ */
+ wchar_t *approot;
+ progname = basename( *argv );
+
if( argc > 1 )
{
/* The user specified arguments on the command line...
{ "all-related", no_argument, &optref, OPTION_ALL_RELATED },
+ { "desktop", optional_argument, NULL, 'D' },
+ { "start-menu", optional_argument, NULL, 'M' },
+
# if DEBUG_ENABLED( DEBUG_TRACE_DYNAMIC )
/* The "--trace" option is supported only when dynamic tracing
* debugging support has been compiled in.
++parsed_options.flags[OPTION_FLAGS].numeric;
break;
+ case 'D':
+ /* This is a request to enable, or disable, the Lua scripting
+ * hook for installation of desktop shortcuts.
+ */
+ set_script_hook( "MINGW_GET_DESKTOP_HOOK=--desktop", optarg );
+ break;
+
+ case 'M':
+ /* This is a request to enable, or disable, the Lua scripting
+ * hook for installation of start menu shortcuts.
+ */
+ set_script_hook( "MINGW_GET_START_MENU_HOOK=--start-menu", optarg );
+ break;
+
case OPTION_GENERIC:
switch( optref & OPTION_STORAGE_CLASS )
{