r16276 - gnucash/trunk/packaging/win32 - Add win32/redirect.c, a tool spawning itself in a parent bin\ directory.

Andreas Köhler andi5 at cvs.gnucash.org
Sun Jul 8 09:08:51 EDT 2007


Author: andi5
Date: 2007-07-08 09:08:49 -0400 (Sun, 08 Jul 2007)
New Revision: 16276
Trac: http://svn.gnucash.org/trac/changeset/16276

Added:
   gnucash/trunk/packaging/win32/redirect.c
Modified:
   gnucash/trunk/packaging/win32/Makefile.am
Log:
Add win32/redirect.c, a tool spawning itself in a parent bin\ directory.

This program, called as "prog.exe (arg)*", will search for
.\bin\prog.exe, ..\bin\prog.exe and so on.  The first hit will be
spawned with the same parameters and its exit status will be the exit
status of this program.


Modified: gnucash/trunk/packaging/win32/Makefile.am
===================================================================
--- gnucash/trunk/packaging/win32/Makefile.am	2007-07-08 13:07:17 UTC (rev 16275)
+++ gnucash/trunk/packaging/win32/Makefile.am	2007-07-08 13:08:49 UTC (rev 16276)
@@ -11,3 +11,12 @@
   opensp-1.5.2-patch.diff \
   pi.sh \
   reset.sh
+
+if OS_WIN32
+  bin_PROGRAMS = redirect
+  redirect_SOURCES = redirect.c
+  redirect_LDADD = $(GLIB_LIBS)
+  AM_CFLAGS = $(GLIB_CFLAGS)
+else
+  EXTRA_DIST += redirect.c
+endif

Added: gnucash/trunk/packaging/win32/redirect.c
===================================================================
--- gnucash/trunk/packaging/win32/redirect.c	2007-07-08 13:07:17 UTC (rev 16275)
+++ gnucash/trunk/packaging/win32/redirect.c	2007-07-08 13:08:49 UTC (rev 16276)
@@ -0,0 +1,166 @@
+/*
+ * redirect.c --
+ * Copyright (C) 2007 Andreas Koehler <andi5.py at gmx.net>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation           Voice:  +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
+ * Boston, MA  02110-1301,  USA       gnu at gnu.org
+ */
+
+#include "config.h"
+#include <glib.h>
+#include <windows.h>
+
+/* This program will search for an existing file in
+ * .\bin\$i
+ * ..\bin\$i
+ * ..\..\bin\$i
+ * and so on, where $i is the base name of argv[0].  Once found, that
+ * program is spawned synchronously with the same parameters and its
+ * exit status will be the one of this program as well.
+ * To avoid recursion, do not use it in a directory ending on "bin".
+ */
+
+/* __wgetmainargs() is an undocumented function to get the program's
+ * argv in wide char format.
+ */
+typedef struct {
+    int newmode;
+} _startupinfo;
+
+extern void __wgetmainargs(int *argc,
+                           wchar_t ***wargv,
+                           wchar_t ***wenviron,
+                           int expand_wildcards,
+                           _startupinfo *startupinfo);
+
+static gboolean
+wcharv_to_utf8_charv(wchar_t **wcharv,
+                     gchar ***utf8_charv,
+                     gint *error_index)
+{
+    gchar **retval = NULL;
+
+  *utf8_charv = NULL;
+  if (wcharv != NULL) {
+      int n = 0, i;
+
+      while (wcharv[n])
+          n++;
+      retval = g_new(gchar *, n + 1);
+
+      for (i = 0; i < n; i++) {
+          retval[i] = g_utf16_to_utf8 (wcharv[i], -1, NULL, NULL, NULL);
+          if (retval[i] == NULL) {
+              if (error_index)
+                  *error_index = i;
+              while (i)
+                  g_free(retval[--i]);
+              g_free (retval);
+              return FALSE;
+          }
+      }
+
+      retval[n] = NULL;
+  }
+  *utf8_charv = retval;
+  return TRUE;
+}
+
+static gboolean
+redirect_program(gchar **argv)
+{
+    gchar *orig_path, *orig_base, *dir, *path;
+    gchar *index;
+    gboolean retval = FALSE;
+
+    g_return_val_if_fail(*argv, FALSE);
+    if (g_path_is_absolute(*argv)) {
+        orig_path = g_strdup(*argv);
+    } else {
+        gchar *cd = g_get_current_dir();
+        orig_path = g_build_filename(cd, *argv, (gchar*) NULL);
+        g_free(cd);
+    }
+
+    orig_base = g_path_get_basename(orig_path);
+    dir = g_strdup(orig_path);
+    while (((index = strrchr(dir, '\\')) != NULL)
+           || ((index = strrchr(dir, '/')) != NULL)) {
+        *index = '\0';
+        path = g_build_filename(dir, "bin", orig_base, (gchar*) NULL);
+        g_debug("Testing %s", path);
+        if (g_file_test(path, G_FILE_TEST_EXISTS)) {
+            g_free(orig_path);
+            *argv = path;
+            retval = TRUE;
+            break;
+        }
+        g_free(path);
+    }
+
+    g_free(dir);
+    g_free(orig_base);
+    g_free(orig_path);
+
+    return retval;
+}
+
+#ifdef __GNUC__
+#    ifndef _stdcall
+#        define _stdcall  __attribute__((stdcall))
+#    endif
+#endif
+
+int _stdcall
+WinMain(struct HINSTANCE__ *hInstance,
+        struct HINSTANCE__ *hPrevInstance,
+        char *lpszCmdLine,
+        int nCmdShow)
+{
+    int argc;
+    wchar_t **wargv, **wenvp;
+    _startupinfo si = { 0 };
+    gint index, status;
+    gchar **utf8_argv;
+    GError *error = NULL;
+
+    __wgetmainargs(&argc, &wargv, &wenvp, 0, &si);
+    g_assert(argc == __argc);
+
+    if (!wcharv_to_utf8_charv(wargv, &utf8_argv, &index)) {
+        g_warning("Invalid argument at position %d", index);
+        return -1;
+    }
+
+    if (!redirect_program(utf8_argv)) {
+        g_warning("Could not find destination for %s", *utf8_argv);
+        g_strfreev(utf8_argv);
+        return -1;
+    }
+
+    if (!g_spawn_sync(NULL, utf8_argv, NULL,
+                      G_SPAWN_LEAVE_DESCRIPTORS_OPEN
+                      | G_SPAWN_CHILD_INHERITS_STDIN,
+                      NULL, NULL, NULL, NULL, &status, &error)) {
+        g_warning("Could not spawn program: %s", error->message);
+        g_error_free(error);
+        g_strfreev(utf8_argv);
+        return -1;
+    }
+
+    return status;
+}



More information about the gnucash-changes mailing list