+2012-08-03 Keith Marshall <keithmarshall@users.sourceforge.net>
+
+ More code refactoring, to facilitate GUI implementation.
+
+ * src/clistub.c (AppPathNameW): Factor out; relocate to...
+ * src/approot.c: ...this new file; it reproduces the original
+ implementation, modified to also consider any "libexec" directory in
+ the executable path as the first child of the APPROOT prefix. Note
+ also, that no longer terminates APPROOT with a trailing backslash.
+
+ * src/approot.h: New file; it trivially declares the prototype for...
+ (AppPathNameW): ...this relocated extern "C" function.
+
+ * src/clistub.c (main): Adapt usage of AppPathNameW(), to reinstate
+ trailing backslash on assignment to APPROOT environment variable.
+
+ * Makefile.in (CLI_EXE_OBJECTS): New macro; define it as the original
+ set of prerequisites, with the addition of approot.OBJEXT, for...
+ (mingw-get.EXEEXT): ...this; use it.
+
+ * src/rites.c: Add comment regarding APPROOT usage.
+
2012-08-02 Earnie Boyd <earnie@users.sourceforge.net>
Find missing.m4 in build-aux/m4 directory.
tinyxml.$(OBJEXT) tinystr.$(OBJEXT) tinyxmlparser.$(OBJEXT) \
mkpath.$(OBJEXT) tinyxmlerror.$(OBJEXT)
+CLI_EXE_OBJECTS = \
+ clistub.$(OBJEXT) version.$(OBJEXT) approot.$(OBJEXT) getopt.$(OBJEXT)
+
script_srcdir = ${srcdir}/scripts/libexec
BIN_PROGRAMS = pkginfo$(EXEEXT) mingw-get$(EXEEXT)
pkginfo$(EXEEXT): driver.$(OBJEXT) pkginfo.$(OBJEXT)
$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $+
-mingw-get$(EXEEXT): clistub.$(OBJEXT) version.$(OBJEXT) getopt.$(OBJEXT)
+mingw-get$(EXEEXT): $(CLI_EXE_OBJECTS)
$(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) $+
GUI_LDFLAGS = -mwindows $(LDFLAGS)
--- /dev/null
+/*
+ * approot.c
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 2009, 2012, MinGW Project
+ *
+ *
+ * Implementation of helper function to identify the root directory
+ * of the mingw-get installation tree, and to map sub-directory path
+ * names relative to this tree.
+ *
+ *
+ * This is free software. Permission is granted to copy, modify and
+ * redistribute this software, under the provisions of the GNU General
+ * Public License, Version 3, (or, at your option, any later version),
+ * as published by the Free Software Foundation; see the file COPYING
+ * for licensing details.
+ *
+ * Note, in particular, that this software is provided "as is", in the
+ * hope that it may prove useful, but WITHOUT WARRANTY OF ANY KIND; not
+ * even an implied WARRANTY OF MERCHANTABILITY, nor of FITNESS FOR ANY
+ * PARTICULAR PURPOSE. Under no circumstances will the author, or the
+ * MinGW Project, accept liability for any damages, however caused,
+ * arising from the use of this software.
+ *
+ */
+#define WIN32_LEAN_AND_MEAN
+
+#include <stdio.h>
+#include <string.h>
+#include <windows.h>
+#include <limits.h>
+#include <ctype.h>
+
+#define wcscasecmp _wcsicmp
+
+wchar_t *AppPathNameW( const wchar_t *relpath )
+{
+ /* UTF-16LE implementation; NOT thread safe...
+ *
+ * Map "relpath" into the file system hierarchy with logical root
+ * at the prefix where the application suite is installed, such that
+ * it becomes "d:\prefix\relpath".
+ *
+ * If the application's executables are installed in a directory called
+ * "bin" or "sbin", then this final directory is excluded from the mapped
+ * prefix, (i.e. a program installed as "d:\prefix\bin\prog.exe" returns
+ * the mapped path as "d:\prefix\relpath", rather than as the inclusive
+ * path "d:\prefix\bin\relpath"). Additionally, if the absolute path to
+ * the program executable includes a directory called "libexec", at any
+ * level within the path, then the absolute path to the parent of this is
+ * taken as the effective prefix. In any other case, the prefix is taken
+ * as the path to the directory in which the program file is installed,
+ * (i.e. a program installed as "d:\prefix\foo\prog.exe" returns the
+ * mapped path as "d:\prefix\foo\relpath".
+ *
+ * Note that, in all cases, the returned path name is normalised, such
+ * that only "\" is used as the directory name separator; this ensures
+ * that it may be safely passed to functions such as LoadLibrary(),
+ * which are known to reject "/" as the separator.
+ *
+ *
+ * Mapped path is returned in this static buffer...
+ */
+ static wchar_t retpath[PATH_MAX], *tail = NULL;
+
+ if( tail == NULL )
+ {
+ /* First time initialisation...
+ *
+ * Fill in the static local buffer, with the appropriate "prefix"
+ * string, marking the point at which "relpath" is to be appended.
+ *
+ * On subsequent calls, we reuse this static buffer, leaving the
+ * "prefix" element unchanged, but simply overwriting the "relpath"
+ * element from any prior call; this is NOT thread safe!
+ */
+ wchar_t bindir[] = L"bin", *bindir_p = bindir;
+ wchar_t *mark, *scan = mark = tail = retpath;
+
+ /* Ascertain the installation path of the calling executable.
+ */
+ int chk = GetModuleFileNameW( NULL, retpath, PATH_MAX );
+
+ /* Validate it; reject any result which doesn't fit in "retpath".
+ */
+ if( (chk == 0) || ((chk == PATH_MAX) && (retpath[--chk] != L'\0')) )
+ return tail = NULL;
+
+ /* Parse it, to locate the end of the effective "prefix" string...
+ */
+ do { if( (*scan == L'/') || (*scan == L'\\') )
+ {
+ /* We found the start of a new path name component directory,
+ * (or maybe the file name, at the end); mark it as a possible
+ * final element of the path name, leaving "tail" pointing to
+ * the previously marked element.
+ */
+ tail = mark;
+ mark = scan;
+ if( scan > tail )
+ {
+ /* The final name element is not empty; temporarily mark
+ * it as "end-of-string", the check if it represents the
+ * "libexec" directory name...
+ */
+ *scan = L'\0';
+ if( wcscasecmp( tail, L"\\libexec" ) == 0 )
+ {
+ /* ...and when it does, we back up to mark its parent
+ * directory as the last in the "prefix" path name...
+ */
+ scan = tail;
+ *scan-- = L'\0';
+ }
+ else
+ /* ...otherwise we append a directory separator, before
+ * cycling around to append the next entity name from the
+ * module path name string.
+ */
+ *scan = L'\\';
+ }
+ }
+ } while( (*++scan) != L'\0' );
+
+ if( *(scan = tail) == L'\\' )
+ {
+ /* When we get to here, "mark" should point to the last directory
+ * separator, immediately preceeding the executable file name, while
+ * "tail" should point to the directory separator preceeding the last
+ * sub-directory name in the path; we now check, without regard to
+ * case, if this final sub-directory name is "bin" or "sbin"...
+ */
+ *mark = L'\0';
+ if( towlower( *++scan ) == L's' )
+ /*
+ * Might be "sbin"; skip the initial "s", and check for "bin"...
+ */
+ ++scan;
+
+ if( wcscasecmp( scan, L"bin" ) == 0 )
+ /*
+ * The final sub-directory is either "bin" or "sbin"; prune it...
+ */
+ *tail = L'\0';
+ /*
+ * ...but when it doesn't match either of these, just adjust the
+ * "tail" pointer, so we leave the final sub-directory name as
+ * part of the "prefix".
+ */
+ tail = mark;
+ }
+ }
+
+ if( relpath == NULL )
+ /*
+ * No "relpath" argument given; simply truncate, to return only
+ * the effective "prefix" string...
+ */
+ *tail = L'\0';
+
+ else
+ { /* We have a "relpath" argument to append; first ensure that the
+ * prefix ends with a directory name separator...
+ */
+ wchar_t *append = tail;
+ if( (*relpath != L'/') && (*relpath != L'\\') )
+ *append++ = L'\\';
+
+ do { /* ...then append the specified path to the application's root,
+ * again, taking care to use "\" as the separator character...
+ */
+ *append++ = (*relpath == L'/') ? L'\\' : *relpath;
+ } while( *relpath++ && ((append - retpath) < PATH_MAX) );
+
+ if( *--append != L'\0' )
+ /*
+ * Abort, if we didn't properly terminate the return string.
+ */
+ return NULL;
+ }
+ return retpath;
+}
+
+/* $RCSfile$: end of file */
--- /dev/null
+#ifndef APPROOT_H
+/*
+ * approot.h
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <keithmarshall@users.sourceforge.net>
+ * Copyright (C) 2012, MinGW Project
+ *
+ *
+ * Declaration of the AppPathNameW() function.
+ *
+ *
+ * This is free software. Permission is granted to copy, modify and
+ * redistribute this software, under the provisions of the GNU General
+ * Public License, Version 3, (or, at your option, any later version),
+ * as published by the Free Software Foundation; see the file COPYING
+ * for licensing details.
+ *
+ * Note, in particular, that this software is provided "as is", in the
+ * hope that it may prove useful, but WITHOUT WARRANTY OF ANY KIND; not
+ * even an implied WARRANTY OF MERCHANTABILITY, nor of FITNESS FOR ANY
+ * PARTICULAR PURPOSE. Under no circumstances will the author, or the
+ * MinGW Project, accept liability for any damages, however caused,
+ * arising from the use of this software.
+ *
+ */
+#define APPROOT_H 1
+
+#ifndef EXTERN_C
+# ifdef __cplusplus
+# define EXTERN_C extern "C"
+# else
+# define EXTERN_C extern
+# endif
+#endif
+
+EXTERN_C wchar_t *AppPathNameW( const wchar_t * );
+
+#endif /* APPROOT_H: $RCSfile$: end of file */
#define WIN32_LEAN_AND_MEAN
#include "debug.h"
+#include "approot.h"
#include <windows.h>
#include <stdio.h>
#define EXIT_FATAL EXIT_FAILURE + 1
static const char *progname;
-
-wchar_t *AppPathNameW( const wchar_t *relpath )
-{
- /* UTF-16LE implementation; NOT thread safe...
- *
- * Map "relpath" into the file system hierarchy with logical root
- * at the prefix where the application suite is installed, such that
- * it becomes "d:\prefix\relpath".
- *
- * If the application's executables are installed in a directory called
- * "bin" or "sbin", then this final directory is excluded from the mapped
- * prefix, (i.e. a program installed as "d:\prefix\bin\prog.exe" returns
- * the mapped path as "d:\prefix\relpath", rather than as the inclusive
- * path "d:\prefix\bin\relpath"); in any other case, the prefix is taken
- * as the path to the directory in which the program file is installed,
- * (i.e. a program installed as "d:\prefix\foo\prog.exe" returns the
- * mapped path as "d:\prefix\foo\relpath".
- *
- * Mapped path is returned in this static buffer...
- */
- static wchar_t retpath[MAX_PATH], *tail = NULL;
-
- if( tail == NULL )
- {
- /* First time initialisation...
- *
- * Fill in the static local buffer, with the appropriate "prefix"
- * string, marking the point at which "relpath" is to be appended.
- *
- * On subsequent calls, we reuse this static buffer, leaving the
- * "prefix" element unchanged, but simply overwriting the "relpath"
- * element from any prior call; this is NOT thread safe!
- */
- wchar_t prev = L'\\';
- wchar_t bindir[] = L"bin", *bindir_p = bindir;
- wchar_t *mark, *scan = mark = tail = retpath;
-
- /* Ascertain the installation path of the calling executable.
- */
- int chk = GetModuleFileNameW( NULL, retpath, MAX_PATH );
-
- /* Validate it; reject any result which doesn't fit in "retpath".
- */
- if( (chk == 0) || ((chk == MAX_PATH) && (retpath[--chk] != L'\0')) )
- return tail = NULL;
-
- /* Parse it, to locate the end of the effective "prefix" string...
- */
- do { if( *scan == L'/' )
- /*
- * This is a sanity check; it should not be necessary, but...
- *
- * Enforce use of "\" rather than "/" as path component separator;
- * ( "LoadLibrary" may be broken, since it seems to care! )
- */
- *scan = L'\\';
-
- if( *scan && (prev == L'\\') )
- {
- /* We found the start a new path name component directory,
- * (or maybe the file name, at the end); mark it as a possible
- * final element of the path name, leaving "tail" pointing to
- * the previously marked element.
- */
- tail = mark;
- mark = scan;
- }
- } while( (prev = *scan++) != L'\0' );
-
- /* When we get to here, "mark" should point to the executable file name,
- * at the end of the path name string, while "tail" should point to the
- * last directory in the installation path; we now check, without regard
- * to case, if this final directory name is "bin" or "sbin"...
- */
- if( (*(scan = tail) == L's') || (*scan == L'S') )
- /*
- * Might be "sbin"; skip the initial "s", and check for "bin"...
- */
- ++scan;
-
- while( *bindir_p && ((*scan++ | L'\x20') == *bindir_p++) )
- /*
- * ...could still match "bin"...
- */ ;
- if( *bindir_p || (*scan != L'\\') )
- /*
- * No, it didn't match; adjust "tail", so we leave the final
- * directory name as part of "prefix".
- */
- tail = mark;
- }
-
- if( relpath == NULL )
- /*
- * No "relpath" argument given; simply truncate, to return only
- * the effective "prefix" string...
- */
- *tail = L'\0';
-
- else
- { wchar_t *append = tail;
- do { /*
- * Append the specified path to the application's root,
- * again, taking care to use "\" as the separator character...
- */
- *append++ = (*relpath == L'/') ? L'\\' : *relpath;
- } while( *relpath++ && ((append - retpath) < MAX_PATH) );
-
- if( *--append != L'\0' )
- /*
- * Abort, if we didn't properly terminate the return string.
- */
- return NULL;
- }
- return retpath;
-}
-
extern const char *version_identification;
static const char *help_text =
if( (approot = AppPathNameW( NULL )) != NULL )
{
/* ...and set up the APPROOT environment variable to refer to
- * the associated installation prefix...
+ * the associated installation prefix, (ensuring that it ends
+ * with a directory name separator)...
*/
- char approot_setup[1 + snprintf( NULL, 0, "APPROOT=%S", approot )];
- snprintf( approot_setup, sizeof( approot_setup ), "APPROOT=%S", approot );
+ const char *approot_fmt = "APPROOT=%S\\";
+ char approot_setup[1 + snprintf( NULL, 0, approot_fmt, approot )];
+ snprintf( approot_setup, sizeof( approot_setup ), approot_fmt, approot );
putenv( approot_setup );
}
#include <stdlib.h>
#include <errno.h>
+/* Path names for supplementary files. Note that these are relative
+ * to the root of the mingw-get directory tree, as identified by the
+ * $APPROOT environment variable.
+ */
#define MINGW_GET_EXE L"bin/mingw-get.exe"
#define MINGW_GET_LCK L"var/lib/mingw-get/lock"
#define MINGW_GET_DLL L"libexec/mingw-get/mingw-get-0.dll"